]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/utils/videos/videos.ts
Refractor single server test
[github/Chocobozzz/PeerTube.git] / server / tests / utils / videos / videos.ts
1 /* tslint:disable:no-unused-expression */
2
3 import { expect } from 'chai'
4 import { readFile } from 'fs'
5 import * as parseTorrent from 'parse-torrent'
6 import { isAbsolute, join } from 'path'
7 import * as request from 'supertest'
8 import { getMyUserInformation, makeGetRequest, readFilePromise, ServerInfo } from '../'
9 import { VideoPrivacy } from '../../../../shared/models/videos'
10 import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../initializers'
11 import { dateIsValid, webtorrentAdd } from '../index'
12
13 type VideoAttributes = {
14 name?: string
15 category?: number
16 licence?: number
17 language?: number
18 nsfw?: boolean
19 description?: string
20 tags?: string[]
21 channelId?: number
22 privacy?: VideoPrivacy
23 fixture?: string
24 }
25
26 function getVideoCategories (url: string) {
27 const path = '/api/v1/videos/categories'
28
29 return makeGetRequest({
30 url,
31 path,
32 statusCodeExpected: 200
33 })
34 }
35
36 function getVideoLicences (url: string) {
37 const path = '/api/v1/videos/licences'
38
39 return makeGetRequest({
40 url,
41 path,
42 statusCodeExpected: 200
43 })
44 }
45
46 function getVideoLanguages (url: string) {
47 const path = '/api/v1/videos/languages'
48
49 return makeGetRequest({
50 url,
51 path,
52 statusCodeExpected: 200
53 })
54 }
55
56 function getVideoPrivacies (url: string) {
57 const path = '/api/v1/videos/privacies'
58
59 return makeGetRequest({
60 url,
61 path,
62 statusCodeExpected: 200
63 })
64 }
65
66 function getVideo (url: string, id: number | string, expectedStatus = 200) {
67 const path = '/api/v1/videos/' + id
68
69 return request(url)
70 .get(path)
71 .set('Accept', 'application/json')
72 .expect(expectedStatus)
73 }
74
75 function viewVideo (url: string, id: number | string, expectedStatus = 204) {
76 const path = '/api/v1/videos/' + id + '/views'
77
78 return request(url)
79 .post(path)
80 .set('Accept', 'application/json')
81 .expect(expectedStatus)
82 }
83
84 function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) {
85 const path = '/api/v1/videos/' + id
86
87 return request(url)
88 .get(path)
89 .set('Authorization', 'Bearer ' + token)
90 .set('Accept', 'application/json')
91 .expect(expectedStatus)
92 }
93
94 function getVideoDescription (url: string, descriptionPath: string) {
95 return request(url)
96 .get(descriptionPath)
97 .set('Accept', 'application/json')
98 .expect(200)
99 .expect('Content-Type', /json/)
100 }
101
102 function getVideosList (url: string) {
103 const path = '/api/v1/videos'
104
105 return request(url)
106 .get(path)
107 .query({ sort: 'name' })
108 .set('Accept', 'application/json')
109 .expect(200)
110 .expect('Content-Type', /json/)
111 }
112
113 function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) {
114 const path = '/api/v1/users/me/videos'
115
116 const req = request(url)
117 .get(path)
118 .query({ start: start })
119 .query({ count: count })
120
121 if (sort) req.query({ sort })
122
123 return req.set('Accept', 'application/json')
124 .set('Authorization', 'Bearer ' + accessToken)
125 .expect(200)
126 .expect('Content-Type', /json/)
127 }
128
129 function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
130 const path = '/api/v1/videos'
131
132 const req = request(url)
133 .get(path)
134 .query({ start: start })
135 .query({ count: count })
136
137 if (sort) req.query({ sort })
138
139 return req.set('Accept', 'application/json')
140 .expect(200)
141 .expect('Content-Type', /json/)
142 }
143
144 function getVideosListSort (url: string, sort: string) {
145 const path = '/api/v1/videos'
146
147 return request(url)
148 .get(path)
149 .query({ sort: sort })
150 .set('Accept', 'application/json')
151 .expect(200)
152 .expect('Content-Type', /json/)
153 }
154
155 function removeVideo (url: string, token: string, id: number | string, expectedStatus = 204) {
156 const path = '/api/v1/videos'
157
158 return request(url)
159 .delete(path + '/' + id)
160 .set('Accept', 'application/json')
161 .set('Authorization', 'Bearer ' + token)
162 .expect(expectedStatus)
163 }
164
165 function searchVideo (url: string, search: string) {
166 const path = '/api/v1/videos'
167 const req = request(url)
168 .get(path + '/search')
169 .query({ search })
170 .set('Accept', 'application/json')
171
172 return req.expect(200)
173 .expect('Content-Type', /json/)
174 }
175
176 function searchVideoWithPagination (url: string, search: string, start: number, count: number, sort?: string) {
177 const path = '/api/v1/videos'
178
179 const req = request(url)
180 .get(path + '/search')
181 .query({ start })
182 .query({ search })
183 .query({ count })
184
185 if (sort) req.query({ sort })
186
187 return req.set('Accept', 'application/json')
188 .expect(200)
189 .expect('Content-Type', /json/)
190 }
191
192 function searchVideoWithSort (url: string, search: string, sort: string) {
193 const path = '/api/v1/videos'
194
195 return request(url)
196 .get(path + '/search')
197 .query({ search })
198 .query({ sort })
199 .set('Accept', 'application/json')
200 .expect(200)
201 .expect('Content-Type', /json/)
202 }
203
204 async function testVideoImage (url: string, imageName: string, imagePath: string) {
205 // Don't test images if the node env is not set
206 // Because we need a special ffmpeg version for this test
207 if (process.env['NODE_TEST_IMAGE']) {
208 const res = await request(url)
209 .get(imagePath)
210 .expect(200)
211
212 const data = await readFilePromise(join(__dirname, '..', '..', 'api', 'fixtures', imageName + '.jpg'))
213
214 return data.equals(res.body)
215 } else {
216 console.log('Do not test images. Enable it by setting NODE_TEST_IMAGE env variable.')
217 return true
218 }
219 }
220
221 async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 200) {
222 const path = '/api/v1/videos/upload'
223 let defaultChannelId = '1'
224
225 try {
226 const res = await getMyUserInformation(url, accessToken)
227 defaultChannelId = res.body.videoChannels[0].id
228 } catch (e) { /* empty */ }
229
230 // Default attributes
231 let attributes = {
232 name: 'my super video',
233 category: 5,
234 licence: 4,
235 language: 3,
236 channelId: defaultChannelId,
237 nsfw: true,
238 description: 'my super description',
239 tags: [ 'tag' ],
240 privacy: VideoPrivacy.PUBLIC,
241 fixture: 'video_short.webm'
242 }
243 attributes = Object.assign(attributes, videoAttributesArg)
244
245 const req = request(url)
246 .post(path)
247 .set('Accept', 'application/json')
248 .set('Authorization', 'Bearer ' + accessToken)
249 .field('name', attributes.name)
250 .field('category', attributes.category.toString())
251 .field('licence', attributes.licence.toString())
252 .field('nsfw', JSON.stringify(attributes.nsfw))
253 .field('description', attributes.description)
254 .field('privacy', attributes.privacy.toString())
255 .field('channelId', attributes.channelId)
256
257 if (attributes.language !== undefined) {
258 req.field('language', attributes.language.toString())
259 }
260
261 for (let i = 0; i < attributes.tags.length; i++) {
262 req.field('tags[' + i + ']', attributes.tags[i])
263 }
264
265 let filePath = ''
266 if (isAbsolute(attributes.fixture)) {
267 filePath = attributes.fixture
268 } else {
269 filePath = join(__dirname, '..', '..', 'api', 'fixtures', attributes.fixture)
270 }
271
272 return req.attach('videofile', filePath)
273 .expect(specialStatus)
274 }
275
276 function updateVideo (url: string, accessToken: string, id: number, attributes: VideoAttributes, specialStatus = 204) {
277 const path = '/api/v1/videos/' + id
278 const body = {}
279
280 if (attributes.name) body['name'] = attributes.name
281 if (attributes.category) body['category'] = attributes.category
282 if (attributes.licence) body['licence'] = attributes.licence
283 if (attributes.language) body['language'] = attributes.language
284 if (attributes.nsfw) body['nsfw'] = attributes.nsfw
285 if (attributes.description) body['description'] = attributes.description
286 if (attributes.tags) body['tags'] = attributes.tags
287 if (attributes.privacy) body['privacy'] = attributes.privacy
288
289 return request(url)
290 .put(path)
291 .send(body)
292 .set('Accept', 'application/json')
293 .set('Authorization', 'Bearer ' + accessToken)
294 .expect(specialStatus)
295 }
296
297 function rateVideo (url: string, accessToken: string, id: number, rating: string, specialStatus = 204) {
298 const path = '/api/v1/videos/' + id + '/rate'
299
300 return request(url)
301 .put(path)
302 .set('Accept', 'application/json')
303 .set('Authorization', 'Bearer ' + accessToken)
304 .send({ rating })
305 .expect(specialStatus)
306 }
307
308 function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
309 return new Promise<any>((res, rej) => {
310 const torrentName = videoUUID + '-' + resolution + '.torrent'
311 const torrentPath = join(__dirname, '..', '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName)
312 readFile(torrentPath, (err, data) => {
313 if (err) return rej(err)
314
315 return res(parseTorrent(data))
316 })
317 })
318 }
319
320 async function completeVideoCheck (
321 url: string,
322 video: any,
323 attributes: {
324 name: string
325 category: number
326 licence: number
327 language: number
328 nsfw: boolean
329 description: string
330 host: string
331 account: string
332 isLocal: boolean,
333 tags: string[],
334 privacy: number,
335 channel: {
336 name: string,
337 isLocal: boolean
338 }
339 fixture: string,
340 files: {
341 resolution: number
342 size: number
343 }[]
344 }
345 ) {
346 expect(video.name).to.equal(attributes.name)
347 expect(video.category).to.equal(attributes.category)
348 expect(video.categoryLabel).to.equal(VIDEO_CATEGORIES[attributes.category])
349 expect(video.licence).to.equal(attributes.licence)
350 expect(video.licenceLabel).to.equal(VIDEO_LICENCES[attributes.licence])
351 expect(video.language).to.equal(attributes.language)
352 expect(video.languageLabel).to.equal(VIDEO_LANGUAGES[attributes.language])
353 expect(video.nsfw).to.equal(attributes.nsfw)
354 expect(video.description).to.equal(attributes.description)
355 expect(video.serverHost).to.equal(attributes.host)
356 expect(video.accountName).to.equal(attributes.account)
357 expect(video.isLocal).to.equal(attributes.isLocal)
358 expect(dateIsValid(video.createdAt)).to.be.true
359 expect(dateIsValid(video.updatedAt)).to.be.true
360
361 const res = await getVideo(url, video.id)
362 const videoDetails = res.body
363
364 expect(videoDetails.files).to.have.lengthOf(attributes.files.length)
365 expect(videoDetails.tags).to.deep.equal(attributes.tags)
366 expect(videoDetails.privacy).to.deep.equal(attributes.privacy)
367 expect(videoDetails.privacyLabel).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy])
368 expect(videoDetails.account.name).to.equal(attributes.account)
369
370 expect(videoDetails.channel.name).to.equal(attributes.channel.name)
371 expect(videoDetails.channel.isLocal).to.equal(attributes.channel.isLocal)
372 expect(dateIsValid(videoDetails.channel.createdAt)).to.be.true
373 expect(dateIsValid(videoDetails.channel.updatedAt)).to.be.true
374
375 for (const attributeFile of attributes.files) {
376 const file = videoDetails.files.find(f => f.resolution === attributeFile.resolution)
377 expect(file).not.to.be.undefined
378
379 const magnetUri = file.magnetUri
380 expect(file.magnetUri).to.have.lengthOf.above(2)
381 expect(file.torrentUrl).to.equal(`${url}/static/torrents/${videoDetails.uuid}-${file.resolution}.torrent`)
382 expect(file.fileUrl).to.equal(`${url}/static/webseed/${videoDetails.uuid}-${file.resolution}.webm`)
383 expect(file.resolution).to.equal(attributeFile.resolution)
384 expect(file.resolutionLabel).to.equal(attributeFile.resolution + 'p')
385 expect(file.size).to.equal(attributeFile.size)
386
387 const test = await testVideoImage(url, attributes.fixture, videoDetails.thumbnailPath)
388 expect(test).to.equal(true)
389
390 const torrent = await webtorrentAdd(magnetUri, true)
391 expect(torrent.files).to.be.an('array')
392 expect(torrent.files.length).to.equal(1)
393 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
394 }
395 }
396
397 // ---------------------------------------------------------------------------
398
399 export {
400 getVideoDescription,
401 getVideoCategories,
402 getVideoLicences,
403 getVideoPrivacies,
404 getVideoLanguages,
405 getMyVideos,
406 getVideo,
407 getVideoWithToken,
408 getVideosList,
409 getVideosListPagination,
410 getVideosListSort,
411 removeVideo,
412 searchVideo,
413 searchVideoWithPagination,
414 searchVideoWithSort,
415 testVideoImage,
416 uploadVideo,
417 updateVideo,
418 rateVideo,
419 viewVideo,
420 parseTorrentVideo,
421 completeVideoCheck
422 }