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({
27 statusCodeExpected: 200
31 function getVideoLicences (url: string) {
32 const path = '/api/v1/videos/licences'
34 return makeGetRequest({
37 statusCodeExpected: 200
41 function getVideoLanguages (url: string) {
42 const path = '/api/v1/videos/languages'
44 return makeGetRequest({
47 statusCodeExpected: 200
51 function getVideoPrivacies (url: string) {
52 const path = '/api/v1/videos/privacies'
54 return makeGetRequest({
57 statusCodeExpected: 200
61 function getVideo (url: string, id: number | string, expectedStatus = 200) {
62 const path = '/api/v1/videos/' + id
66 .set('Accept', 'application/json')
67 .expect(expectedStatus)
70 function viewVideo (url: string, id: number | string, expectedStatus = 204) {
71 const path = '/api/v1/videos/' + id + '/views'
75 .set('Accept', 'application/json')
76 .expect(expectedStatus)
79 function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) {
80 const path = '/api/v1/videos/' + id
84 .set('Authorization', 'Bearer ' + token)
85 .set('Accept', 'application/json')
86 .expect(expectedStatus)
89 function getVideoDescription (url: string, descriptionPath: string) {
92 .set('Accept', 'application/json')
94 .expect('Content-Type', /json/)
97 function getVideosList (url: string) {
98 const path = '/api/v1/videos'
102 .query({ sort: 'name' })
103 .set('Accept', 'application/json')
105 .expect('Content-Type', /json/)
108 function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) {
109 const path = '/api/v1/users/me/videos'
111 const req = request(url)
113 .query({ start: start })
114 .query({ count: count })
116 if (sort) req.query({ sort })
118 return req.set('Accept', 'application/json')
119 .set('Authorization', 'Bearer ' + accessToken)
121 .expect('Content-Type', /json/)
124 function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
125 const path = '/api/v1/videos'
127 const req = request(url)
129 .query({ start: start })
130 .query({ count: count })
132 if (sort) req.query({ sort })
134 return req.set('Accept', 'application/json')
136 .expect('Content-Type', /json/)
139 function getVideosListSort (url: string, sort: string) {
140 const path = '/api/v1/videos'
144 .query({ sort: sort })
145 .set('Accept', 'application/json')
147 .expect('Content-Type', /json/)
150 function removeVideo (url: string, token: string, id: number | string, expectedStatus = 204) {
151 const path = '/api/v1/videos'
154 .delete(path + '/' + id)
155 .set('Accept', 'application/json')
156 .set('Authorization', 'Bearer ' + token)
157 .expect(expectedStatus)
160 function searchVideo (url: string, search: string) {
161 const path = '/api/v1/videos'
162 const req = request(url)
163 .get(path + '/search')
165 .set('Accept', 'application/json')
167 return req.expect(200)
168 .expect('Content-Type', /json/)
171 function searchVideoWithPagination (url: string, search: string, start: number, count: number, sort?: string) {
172 const path = '/api/v1/videos'
174 const req = request(url)
175 .get(path + '/search')
180 if (sort) req.query({ sort })
182 return req.set('Accept', 'application/json')
184 .expect('Content-Type', /json/)
187 function searchVideoWithSort (url: string, search: string, sort: string) {
188 const path = '/api/v1/videos'
191 .get(path + '/search')
194 .set('Accept', 'application/json')
196 .expect('Content-Type', /json/)
199 async function testVideoImage (url: string, imageName: string, imagePath: string) {
200 // Don't test images if the node env is not set
201 // Because we need a special ffmpeg version for this test
202 if (process.env['NODE_TEST_IMAGE']) {
203 const res = await request(url)
207 const data = await readFilePromise(join(__dirname, '..', '..', 'api', 'fixtures', imageName + '.jpg'))
209 return data.equals(res.body)
211 console.log('Do not test images. Enable it by setting NODE_TEST_IMAGE env variable.')
216 async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 200) {
217 const path = '/api/v1/videos/upload'
218 let defaultChannelId = '1'
221 const res = await getMyUserInformation(url, accessToken)
222 defaultChannelId = res.body.videoChannels[0].id
223 } catch (e) { /* empty */ }
225 // Default attributes
227 name: 'my super video',
231 channelId: defaultChannelId,
233 description: 'my super description',
235 privacy: VideoPrivacy.PUBLIC,
236 fixture: 'video_short.webm'
238 attributes = Object.assign(attributes, videoAttributesArg)
240 const req = request(url)
242 .set('Accept', 'application/json')
243 .set('Authorization', 'Bearer ' + accessToken)
244 .field('name', attributes.name)
245 .field('category', attributes.category.toString())
246 .field('licence', attributes.licence.toString())
247 .field('nsfw', JSON.stringify(attributes.nsfw))
248 .field('description', attributes.description)
249 .field('privacy', attributes.privacy.toString())
250 .field('channelId', attributes.channelId)
252 if (attributes.language !== undefined) {
253 req.field('language', attributes.language.toString())
256 for (let i = 0; i < attributes.tags.length; i++) {
257 req.field('tags[' + i + ']', attributes.tags[i])
261 if (isAbsolute(attributes.fixture)) {
262 filePath = attributes.fixture
264 filePath = join(__dirname, '..', '..', 'api', 'fixtures', attributes.fixture)
267 return req.attach('videofile', filePath)
268 .expect(specialStatus)
271 function updateVideo (url: string, accessToken: string, id: number, attributes: VideoAttributes, specialStatus = 204) {
272 const path = '/api/v1/videos/' + id
275 if (attributes.name) body['name'] = attributes.name
276 if (attributes.category) body['category'] = attributes.category
277 if (attributes.licence) body['licence'] = attributes.licence
278 if (attributes.language) body['language'] = attributes.language
279 if (attributes.nsfw) body['nsfw'] = attributes.nsfw
280 if (attributes.description) body['description'] = attributes.description
281 if (attributes.tags) body['tags'] = attributes.tags
282 if (attributes.privacy) body['privacy'] = attributes.privacy
287 .set('Accept', 'application/json')
288 .set('Authorization', 'Bearer ' + accessToken)
289 .expect(specialStatus)
292 function rateVideo (url: string, accessToken: string, id: number, rating: string, specialStatus = 204) {
293 const path = '/api/v1/videos/' + id + '/rate'
297 .set('Accept', 'application/json')
298 .set('Authorization', 'Bearer ' + accessToken)
300 .expect(specialStatus)
303 function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
304 return new Promise<any>((res, rej) => {
305 const torrentName = videoUUID + '-' + resolution + '.torrent'
306 const torrentPath = join(__dirname, '..', '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName)
307 readFile(torrentPath, (err, data) => {
308 if (err) return rej(err)
310 return res(parseTorrent(data))
315 // ---------------------------------------------------------------------------
327 getVideosListPagination,
331 searchVideoWithPagination,