1 import { readFile } from 'fs'
2 import * as parseTorrent from 'parse-torrent'
3 import { isAbsolute, join } from 'path'
4 import * as request from 'supertest'
5 import { getMyUserInformation, makeGetRequest, readFilePromise, ServerInfo } from '../'
6 import { VideoPrivacy } from '../../../../shared/models/videos'
8 type VideoAttributes = {
17 privacy?: VideoPrivacy
21 function getVideoCategories (url: string) {
22 const path = '/api/v1/videos/categories'
24 return makeGetRequest({
30 function getVideoLicences (url: string) {
31 const path = '/api/v1/videos/licences'
33 return makeGetRequest({
39 function getVideoLanguages (url: string) {
40 const path = '/api/v1/videos/languages'
42 return makeGetRequest({
48 function getVideoPrivacies (url: string) {
49 const path = '/api/v1/videos/privacies'
51 return makeGetRequest({
57 function getVideo (url: string, id: number | string, expectedStatus = 200) {
58 const path = '/api/v1/videos/' + id
62 .set('Accept', 'application/json')
63 .expect(expectedStatus)
66 function viewVideo (url: string, id: number | string, expectedStatus = 204) {
67 const path = '/api/v1/videos/' + id + '/views'
71 .set('Accept', 'application/json')
72 .expect(expectedStatus)
75 function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) {
76 const path = '/api/v1/videos/' + id
80 .set('Authorization', 'Bearer ' + token)
81 .set('Accept', 'application/json')
82 .expect(expectedStatus)
85 function getVideoDescription (url: string, descriptionPath: string) {
88 .set('Accept', 'application/json')
90 .expect('Content-Type', /json/)
93 function getVideosList (url: string) {
94 const path = '/api/v1/videos'
98 .query({ sort: 'name' })
99 .set('Accept', 'application/json')
101 .expect('Content-Type', /json/)
104 function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) {
105 const path = '/api/v1/users/me/videos'
107 const req = request(url)
109 .query({ start: start })
110 .query({ count: count })
112 if (sort) req.query({ sort })
114 return req.set('Accept', 'application/json')
115 .set('Authorization', 'Bearer ' + accessToken)
117 .expect('Content-Type', /json/)
120 function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
121 const path = '/api/v1/videos'
123 const req = request(url)
125 .query({ start: start })
126 .query({ count: count })
128 if (sort) req.query({ sort })
130 return req.set('Accept', 'application/json')
132 .expect('Content-Type', /json/)
135 function getVideosListSort (url: string, sort: string) {
136 const path = '/api/v1/videos'
140 .query({ sort: sort })
141 .set('Accept', 'application/json')
143 .expect('Content-Type', /json/)
146 function removeVideo (url: string, token: string, id: number | string, expectedStatus = 204) {
147 const path = '/api/v1/videos'
150 .delete(path + '/' + id)
151 .set('Accept', 'application/json')
152 .set('Authorization', 'Bearer ' + token)
153 .expect(expectedStatus)
156 function searchVideo (url: string, search: string) {
157 const path = '/api/v1/videos'
158 const req = request(url)
159 .get(path + '/search')
161 .set('Accept', 'application/json')
163 return req.expect(200)
164 .expect('Content-Type', /json/)
167 function searchVideoWithPagination (url: string, search: string, start: number, count: number, sort?: string) {
168 const path = '/api/v1/videos'
170 const req = request(url)
171 .get(path + '/search')
176 if (sort) req.query({ sort })
178 return req.set('Accept', 'application/json')
180 .expect('Content-Type', /json/)
183 function searchVideoWithSort (url: string, search: string, sort: string) {
184 const path = '/api/v1/videos'
187 .get(path + '/search')
190 .set('Accept', 'application/json')
192 .expect('Content-Type', /json/)
195 async function testVideoImage (url: string, imageName: string, imagePath: string) {
196 // Don't test images if the node env is not set
197 // Because we need a special ffmpeg version for this test
198 if (process.env['NODE_TEST_IMAGE']) {
199 const res = await request(url)
203 const data = await readFilePromise(join(__dirname, '..', '..', 'api', 'fixtures', imageName + '.jpg'))
205 return data.equals(res.body)
207 console.log('Do not test images. Enable it by setting NODE_TEST_IMAGE env variable.')
212 async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 200) {
213 const path = '/api/v1/videos/upload'
214 let defaultChannelId = '1'
217 const res = await getMyUserInformation(url, accessToken)
218 defaultChannelId = res.body.videoChannels[0].id
219 } catch (e) { /* empty */ }
221 // Default attributes
223 name: 'my super video',
227 channelId: defaultChannelId,
229 description: 'my super description',
231 privacy: VideoPrivacy.PUBLIC,
232 fixture: 'video_short.webm'
234 attributes = Object.assign(attributes, videoAttributesArg)
236 const req = request(url)
238 .set('Accept', 'application/json')
239 .set('Authorization', 'Bearer ' + accessToken)
240 .field('name', attributes.name)
241 .field('category', attributes.category.toString())
242 .field('licence', attributes.licence.toString())
243 .field('nsfw', JSON.stringify(attributes.nsfw))
244 .field('description', attributes.description)
245 .field('privacy', attributes.privacy.toString())
246 .field('channelId', attributes.channelId)
248 if (attributes.language !== undefined) {
249 req.field('language', attributes.language.toString())
252 for (let i = 0; i < attributes.tags.length; i++) {
253 req.field('tags[' + i + ']', attributes.tags[i])
257 if (isAbsolute(attributes.fixture)) {
258 filePath = attributes.fixture
260 filePath = join(__dirname, '..', '..', 'api', 'fixtures', attributes.fixture)
263 return req.attach('videofile', filePath)
264 .expect(specialStatus)
267 function updateVideo (url: string, accessToken: string, id: number, attributes: VideoAttributes, specialStatus = 204) {
268 const path = '/api/v1/videos/' + id
271 if (attributes.name) body['name'] = attributes.name
272 if (attributes.category) body['category'] = attributes.category
273 if (attributes.licence) body['licence'] = attributes.licence
274 if (attributes.language) body['language'] = attributes.language
275 if (attributes.nsfw) body['nsfw'] = attributes.nsfw
276 if (attributes.description) body['description'] = attributes.description
277 if (attributes.tags) body['tags'] = attributes.tags
278 if (attributes.privacy) body['privacy'] = attributes.privacy
283 .set('Accept', 'application/json')
284 .set('Authorization', 'Bearer ' + accessToken)
285 .expect(specialStatus)
288 function rateVideo (url: string, accessToken: string, id: number, rating: string, specialStatus = 204) {
289 const path = '/api/v1/videos/' + id + '/rate'
293 .set('Accept', 'application/json')
294 .set('Authorization', 'Bearer ' + accessToken)
296 .expect(specialStatus)
299 function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
300 return new Promise<any>((res, rej) => {
301 const torrentName = videoUUID + '-' + resolution + '.torrent'
302 const torrentPath = join(__dirname, '..', '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName)
303 readFile(torrentPath, (err, data) => {
304 if (err) return rej(err)
306 return res(parseTorrent(data))
311 // ---------------------------------------------------------------------------
323 getVideosListPagination,
327 searchVideoWithPagination,