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(url, path)
27 function getVideoLicences (url: string) {
28 const path = '/api/v1/videos/licences'
30 return makeGetRequest(url, path)
33 function getVideoLanguages (url: string) {
34 const path = '/api/v1/videos/languages'
36 return makeGetRequest(url, path)
39 function getVideoPrivacies (url: string) {
40 const path = '/api/v1/videos/privacies'
42 return makeGetRequest(url, path)
45 function getVideo (url: string, id: number | string, expectedStatus = 200) {
46 const path = '/api/v1/videos/' + id
50 .set('Accept', 'application/json')
51 .expect(expectedStatus)
54 function viewVideo (url: string, id: number | string, expectedStatus = 204) {
55 const path = '/api/v1/videos/' + id + '/views'
59 .set('Accept', 'application/json')
60 .expect(expectedStatus)
63 function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) {
64 const path = '/api/v1/videos/' + id
68 .set('Authorization', 'Bearer ' + token)
69 .set('Accept', 'application/json')
70 .expect(expectedStatus)
73 function getVideoDescription (url: string, descriptionPath: string) {
76 .set('Accept', 'application/json')
78 .expect('Content-Type', /json/)
81 function getVideosList (url: string) {
82 const path = '/api/v1/videos'
86 .query({ sort: 'name' })
87 .set('Accept', 'application/json')
89 .expect('Content-Type', /json/)
92 function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) {
93 const path = '/api/v1/users/me/videos'
95 const req = request(url)
97 .query({ start: start })
98 .query({ count: count })
100 if (sort) req.query({ sort })
102 return req.set('Accept', 'application/json')
103 .set('Authorization', 'Bearer ' + accessToken)
105 .expect('Content-Type', /json/)
108 function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
109 const path = '/api/v1/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')
120 .expect('Content-Type', /json/)
123 function getVideosListSort (url: string, sort: string) {
124 const path = '/api/v1/videos'
128 .query({ sort: sort })
129 .set('Accept', 'application/json')
131 .expect('Content-Type', /json/)
134 function removeVideo (url: string, token: string, id: number, expectedStatus = 204) {
135 const path = '/api/v1/videos'
138 .delete(path + '/' + id)
139 .set('Accept', 'application/json')
140 .set('Authorization', 'Bearer ' + token)
141 .expect(expectedStatus)
144 function searchVideo (url: string, search: string) {
145 const path = '/api/v1/videos'
146 const req = request(url)
147 .get(path + '/search')
149 .set('Accept', 'application/json')
151 return req.expect(200)
152 .expect('Content-Type', /json/)
155 function searchVideoWithPagination (url: string, search: string, start: number, count: number, sort?: string) {
156 const path = '/api/v1/videos'
158 const req = request(url)
159 .get(path + '/search')
164 if (sort) req.query({ sort })
166 return req.set('Accept', 'application/json')
168 .expect('Content-Type', /json/)
171 function searchVideoWithSort (url: string, search: string, sort: string) {
172 const path = '/api/v1/videos'
175 .get(path + '/search')
178 .set('Accept', 'application/json')
180 .expect('Content-Type', /json/)
183 async function testVideoImage (url: string, imageName: string, imagePath: string) {
184 // Don't test images if the node env is not set
185 // Because we need a special ffmpeg version for this test
186 if (process.env['NODE_TEST_IMAGE']) {
187 const res = await request(url)
191 const data = await readFilePromise(join(__dirname, '..', 'api', 'fixtures', imageName + '.jpg'))
193 return data.equals(res.body)
195 console.log('Do not test images. Enable it by setting NODE_TEST_IMAGE env variable.')
200 async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 200) {
201 const path = '/api/v1/videos/upload'
202 let defaultChannelId = '1'
205 const res = await getMyUserInformation(url, accessToken)
206 defaultChannelId = res.body.videoChannels[0].id
207 } catch (e) { /* empty */ }
209 // Default attributes
211 name: 'my super video',
215 channelId: defaultChannelId,
217 description: 'my super description',
219 privacy: VideoPrivacy.PUBLIC,
220 fixture: 'video_short.webm'
222 attributes = Object.assign(attributes, videoAttributesArg)
224 const req = request(url)
226 .set('Accept', 'application/json')
227 .set('Authorization', 'Bearer ' + accessToken)
228 .field('name', attributes.name)
229 .field('category', attributes.category.toString())
230 .field('licence', attributes.licence.toString())
231 .field('nsfw', JSON.stringify(attributes.nsfw))
232 .field('description', attributes.description)
233 .field('privacy', attributes.privacy.toString())
234 .field('channelId', attributes.channelId)
236 if (attributes.language !== undefined) {
237 req.field('language', attributes.language.toString())
240 for (let i = 0; i < attributes.tags.length; i++) {
241 req.field('tags[' + i + ']', attributes.tags[i])
245 if (isAbsolute(attributes.fixture)) {
246 filePath = attributes.fixture
248 filePath = join(__dirname, '..', 'api', 'fixtures', attributes.fixture)
251 return req.attach('videofile', filePath)
252 .expect(specialStatus)
255 function updateVideo (url: string, accessToken: string, id: number, attributes: VideoAttributes, specialStatus = 204) {
256 const path = '/api/v1/videos/' + id
259 if (attributes.name) body['name'] = attributes.name
260 if (attributes.category) body['category'] = attributes.category
261 if (attributes.licence) body['licence'] = attributes.licence
262 if (attributes.language) body['language'] = attributes.language
263 if (attributes.nsfw) body['nsfw'] = attributes.nsfw
264 if (attributes.description) body['description'] = attributes.description
265 if (attributes.tags) body['tags'] = attributes.tags
266 if (attributes.privacy) body['privacy'] = attributes.privacy
271 .set('Accept', 'application/json')
272 .set('Authorization', 'Bearer ' + accessToken)
273 .expect(specialStatus)
276 function rateVideo (url: string, accessToken: string, id: number, rating: string, specialStatus = 204) {
277 const path = '/api/v1/videos/' + id + '/rate'
281 .set('Accept', 'application/json')
282 .set('Authorization', 'Bearer ' + accessToken)
284 .expect(specialStatus)
287 function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
288 return new Promise<any>((res, rej) => {
289 const torrentName = videoUUID + '-' + resolution + '.torrent'
290 const torrentPath = join(__dirname, '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName)
291 readFile(torrentPath, (err, data) => {
292 if (err) return rej(err)
294 return res(parseTorrent(data))
299 // ---------------------------------------------------------------------------
311 getVideosListPagination,
315 searchVideoWithPagination,