]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/videos/single-server.ts
Merge branch 'release/3.2.0' into develop
[github/Chocobozzz/PeerTube.git] / server / tests / api / videos / single-server.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import * as chai from 'chai'
5 import { keyBy } from 'lodash'
6
7 import {
8 checkVideoFilesWereRemoved,
9 cleanupTests,
10 completeVideoCheck,
11 flushAndRunServer,
12 getVideo,
13 getVideoCategories,
14 getVideoLanguages,
15 getVideoLicences,
16 getVideoPrivacies,
17 getVideosList,
18 getVideosListPagination,
19 getVideosListSort,
20 getVideosWithFilters,
21 rateVideo,
22 removeVideo,
23 ServerInfo,
24 setAccessTokensToServers,
25 testImage,
26 updateVideo,
27 uploadVideo,
28 viewVideo,
29 wait
30 } from '../../../../shared/extra-utils'
31 import { VideoPrivacy } from '../../../../shared/models/videos'
32 import { HttpStatusCode } from '@shared/core-utils'
33
34 const expect = chai.expect
35
36 describe('Test a single server', function () {
37
38 function runSuite (mode: 'legacy' | 'resumable') {
39 let server: ServerInfo = null
40 let videoId = -1
41 let videoId2 = -1
42 let videoUUID = ''
43 let videosListBase: any[] = null
44
45 const getCheckAttributes = () => ({
46 name: 'my super name',
47 category: 2,
48 licence: 6,
49 language: 'zh',
50 nsfw: true,
51 description: 'my super description',
52 support: 'my super support text',
53 account: {
54 name: 'root',
55 host: 'localhost:' + server.port
56 },
57 isLocal: true,
58 duration: 5,
59 tags: [ 'tag1', 'tag2', 'tag3' ],
60 privacy: VideoPrivacy.PUBLIC,
61 commentsEnabled: true,
62 downloadEnabled: true,
63 channel: {
64 displayName: 'Main root channel',
65 name: 'root_channel',
66 description: '',
67 isLocal: true
68 },
69 fixture: 'video_short.webm',
70 files: [
71 {
72 resolution: 720,
73 size: 218910
74 }
75 ]
76 })
77
78 const updateCheckAttributes = () => ({
79 name: 'my super video updated',
80 category: 4,
81 licence: 2,
82 language: 'ar',
83 nsfw: false,
84 description: 'my super description updated',
85 support: 'my super support text updated',
86 account: {
87 name: 'root',
88 host: 'localhost:' + server.port
89 },
90 isLocal: true,
91 tags: [ 'tagup1', 'tagup2' ],
92 privacy: VideoPrivacy.PUBLIC,
93 duration: 5,
94 commentsEnabled: false,
95 downloadEnabled: false,
96 channel: {
97 name: 'root_channel',
98 displayName: 'Main root channel',
99 description: '',
100 isLocal: true
101 },
102 fixture: 'video_short3.webm',
103 files: [
104 {
105 resolution: 720,
106 size: 292677
107 }
108 ]
109 })
110
111 before(async function () {
112 this.timeout(30000)
113
114 server = await flushAndRunServer(1)
115
116 await setAccessTokensToServers([ server ])
117 })
118
119 it('Should list video categories', async function () {
120 const res = await getVideoCategories(server.url)
121
122 const categories = res.body
123 expect(Object.keys(categories)).to.have.length.above(10)
124
125 expect(categories[11]).to.equal('News & Politics')
126 })
127
128 it('Should list video licences', async function () {
129 const res = await getVideoLicences(server.url)
130
131 const licences = res.body
132 expect(Object.keys(licences)).to.have.length.above(5)
133
134 expect(licences[3]).to.equal('Attribution - No Derivatives')
135 })
136
137 it('Should list video languages', async function () {
138 const res = await getVideoLanguages(server.url)
139
140 const languages = res.body
141 expect(Object.keys(languages)).to.have.length.above(5)
142
143 expect(languages['ru']).to.equal('Russian')
144 })
145
146 it('Should list video privacies', async function () {
147 const res = await getVideoPrivacies(server.url)
148
149 const privacies = res.body
150 expect(Object.keys(privacies)).to.have.length.at.least(3)
151
152 expect(privacies[3]).to.equal('Private')
153 })
154
155 it('Should not have videos', async function () {
156 const res = await getVideosList(server.url)
157
158 expect(res.body.total).to.equal(0)
159 expect(res.body.data).to.be.an('array')
160 expect(res.body.data.length).to.equal(0)
161 })
162
163 it('Should upload the video', async function () {
164 this.timeout(10000)
165
166 const videoAttributes = {
167 name: 'my super name',
168 category: 2,
169 nsfw: true,
170 licence: 6,
171 tags: [ 'tag1', 'tag2', 'tag3' ]
172 }
173 const res = await uploadVideo(server.url, server.accessToken, videoAttributes, HttpStatusCode.OK_200, mode)
174 expect(res.body.video).to.not.be.undefined
175 expect(res.body.video.id).to.equal(1)
176 expect(res.body.video.uuid).to.have.length.above(5)
177
178 videoId = res.body.video.id
179 videoUUID = res.body.video.uuid
180 })
181
182 it('Should get and seed the uploaded video', async function () {
183 this.timeout(5000)
184
185 const res = await getVideosList(server.url)
186
187 expect(res.body.total).to.equal(1)
188 expect(res.body.data).to.be.an('array')
189 expect(res.body.data.length).to.equal(1)
190
191 const video = res.body.data[0]
192 await completeVideoCheck(server.url, video, getCheckAttributes())
193 })
194
195 it('Should get the video by UUID', async function () {
196 this.timeout(5000)
197
198 const res = await getVideo(server.url, videoUUID)
199
200 const video = res.body
201 await completeVideoCheck(server.url, video, getCheckAttributes())
202 })
203
204 it('Should have the views updated', async function () {
205 this.timeout(20000)
206
207 await viewVideo(server.url, videoId)
208 await viewVideo(server.url, videoId)
209 await viewVideo(server.url, videoId)
210
211 await wait(1500)
212
213 await viewVideo(server.url, videoId)
214 await viewVideo(server.url, videoId)
215
216 await wait(1500)
217
218 await viewVideo(server.url, videoId)
219 await viewVideo(server.url, videoId)
220
221 // Wait the repeatable job
222 await wait(8000)
223
224 const res = await getVideo(server.url, videoId)
225
226 const video = res.body
227 expect(video.views).to.equal(3)
228 })
229
230 it('Should remove the video', async function () {
231 await removeVideo(server.url, server.accessToken, videoId)
232
233 await checkVideoFilesWereRemoved(videoUUID, 1)
234 })
235
236 it('Should not have videos', async function () {
237 const res = await getVideosList(server.url)
238
239 expect(res.body.total).to.equal(0)
240 expect(res.body.data).to.be.an('array')
241 expect(res.body.data).to.have.lengthOf(0)
242 })
243
244 it('Should upload 6 videos', async function () {
245 this.timeout(25000)
246
247 const videos = new Set([
248 'video_short.mp4', 'video_short.ogv', 'video_short.webm',
249 'video_short1.webm', 'video_short2.webm', 'video_short3.webm'
250 ])
251
252 for (const video of videos) {
253 const videoAttributes = {
254 name: video + ' name',
255 description: video + ' description',
256 category: 2,
257 licence: 1,
258 language: 'en',
259 nsfw: true,
260 tags: [ 'tag1', 'tag2', 'tag3' ],
261 fixture: video
262 }
263
264 await uploadVideo(server.url, server.accessToken, videoAttributes, HttpStatusCode.OK_200, mode)
265 }
266 })
267
268 it('Should have the correct durations', async function () {
269 const res = await getVideosList(server.url)
270
271 expect(res.body.total).to.equal(6)
272 const videos = res.body.data
273 expect(videos).to.be.an('array')
274 expect(videos).to.have.lengthOf(6)
275
276 const videosByName = keyBy<{ duration: number }>(videos, 'name')
277 expect(videosByName['video_short.mp4 name'].duration).to.equal(5)
278 expect(videosByName['video_short.ogv name'].duration).to.equal(5)
279 expect(videosByName['video_short.webm name'].duration).to.equal(5)
280 expect(videosByName['video_short1.webm name'].duration).to.equal(10)
281 expect(videosByName['video_short2.webm name'].duration).to.equal(5)
282 expect(videosByName['video_short3.webm name'].duration).to.equal(5)
283 })
284
285 it('Should have the correct thumbnails', async function () {
286 const res = await getVideosList(server.url)
287
288 const videos = res.body.data
289 // For the next test
290 videosListBase = videos
291
292 for (const video of videos) {
293 const videoName = video.name.replace(' name', '')
294 await testImage(server.url, videoName, video.thumbnailPath)
295 }
296 })
297
298 it('Should list only the two first videos', async function () {
299 const res = await getVideosListPagination(server.url, 0, 2, 'name')
300
301 const videos = res.body.data
302 expect(res.body.total).to.equal(6)
303 expect(videos.length).to.equal(2)
304 expect(videos[0].name).to.equal(videosListBase[0].name)
305 expect(videos[1].name).to.equal(videosListBase[1].name)
306 })
307
308 it('Should list only the next three videos', async function () {
309 const res = await getVideosListPagination(server.url, 2, 3, 'name')
310
311 const videos = res.body.data
312 expect(res.body.total).to.equal(6)
313 expect(videos.length).to.equal(3)
314 expect(videos[0].name).to.equal(videosListBase[2].name)
315 expect(videos[1].name).to.equal(videosListBase[3].name)
316 expect(videos[2].name).to.equal(videosListBase[4].name)
317 })
318
319 it('Should list the last video', async function () {
320 const res = await getVideosListPagination(server.url, 5, 6, 'name')
321
322 const videos = res.body.data
323 expect(res.body.total).to.equal(6)
324 expect(videos.length).to.equal(1)
325 expect(videos[0].name).to.equal(videosListBase[5].name)
326 })
327
328 it('Should not have the total field', async function () {
329 const res = await getVideosListPagination(server.url, 5, 6, 'name', true)
330
331 const videos = res.body.data
332 expect(res.body.total).to.not.exist
333 expect(videos.length).to.equal(1)
334 expect(videos[0].name).to.equal(videosListBase[5].name)
335 })
336
337 it('Should list and sort by name in descending order', async function () {
338 const res = await getVideosListSort(server.url, '-name')
339
340 const videos = res.body.data
341 expect(res.body.total).to.equal(6)
342 expect(videos.length).to.equal(6)
343 expect(videos[0].name).to.equal('video_short.webm name')
344 expect(videos[1].name).to.equal('video_short.ogv name')
345 expect(videos[2].name).to.equal('video_short.mp4 name')
346 expect(videos[3].name).to.equal('video_short3.webm name')
347 expect(videos[4].name).to.equal('video_short2.webm name')
348 expect(videos[5].name).to.equal('video_short1.webm name')
349
350 videoId = videos[3].uuid
351 videoId2 = videos[5].uuid
352 })
353
354 it('Should list and sort by trending in descending order', async function () {
355 const res = await getVideosListPagination(server.url, 0, 2, '-trending')
356
357 const videos = res.body.data
358 expect(res.body.total).to.equal(6)
359 expect(videos.length).to.equal(2)
360 })
361
362 it('Should list and sort by hotness in descending order', async function () {
363 const res = await getVideosListPagination(server.url, 0, 2, '-hot')
364
365 const videos = res.body.data
366 expect(res.body.total).to.equal(6)
367 expect(videos.length).to.equal(2)
368 })
369
370 it('Should list and sort by best in descending order', async function () {
371 const res = await getVideosListPagination(server.url, 0, 2, '-best')
372
373 const videos = res.body.data
374 expect(res.body.total).to.equal(6)
375 expect(videos.length).to.equal(2)
376 })
377
378 it('Should update a video', async function () {
379 const attributes = {
380 name: 'my super video updated',
381 category: 4,
382 licence: 2,
383 language: 'ar',
384 nsfw: false,
385 description: 'my super description updated',
386 commentsEnabled: false,
387 downloadEnabled: false,
388 tags: [ 'tagup1', 'tagup2' ]
389 }
390 await updateVideo(server.url, server.accessToken, videoId, attributes)
391 })
392
393 it('Should filter by tags and category', async function () {
394 const res1 = await getVideosWithFilters(server.url, { tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: [ 4 ] })
395 expect(res1.body.total).to.equal(1)
396 expect(res1.body.data[0].name).to.equal('my super video updated')
397
398 const res2 = await getVideosWithFilters(server.url, { tagsAllOf: [ 'tagup1', 'tagup2' ], categoryOneOf: [ 3 ] })
399 expect(res2.body.total).to.equal(0)
400 })
401
402 it('Should have the video updated', async function () {
403 this.timeout(60000)
404
405 const res = await getVideo(server.url, videoId)
406 const video = res.body
407
408 await completeVideoCheck(server.url, video, updateCheckAttributes())
409 })
410
411 it('Should update only the tags of a video', async function () {
412 const attributes = {
413 tags: [ 'supertag', 'tag1', 'tag2' ]
414 }
415 await updateVideo(server.url, server.accessToken, videoId, attributes)
416
417 const res = await getVideo(server.url, videoId)
418 const video = res.body
419
420 await completeVideoCheck(server.url, video, Object.assign(updateCheckAttributes(), attributes))
421 })
422
423 it('Should update only the description of a video', async function () {
424 const attributes = {
425 description: 'hello everybody'
426 }
427 await updateVideo(server.url, server.accessToken, videoId, attributes)
428
429 const res = await getVideo(server.url, videoId)
430 const video = res.body
431
432 const expectedAttributes = Object.assign(updateCheckAttributes(), { tags: [ 'supertag', 'tag1', 'tag2' ] }, attributes)
433 await completeVideoCheck(server.url, video, expectedAttributes)
434 })
435
436 it('Should like a video', async function () {
437 await rateVideo(server.url, server.accessToken, videoId, 'like')
438
439 const res = await getVideo(server.url, videoId)
440 const video = res.body
441
442 expect(video.likes).to.equal(1)
443 expect(video.dislikes).to.equal(0)
444 })
445
446 it('Should dislike the same video', async function () {
447 await rateVideo(server.url, server.accessToken, videoId, 'dislike')
448
449 const res = await getVideo(server.url, videoId)
450 const video = res.body
451
452 expect(video.likes).to.equal(0)
453 expect(video.dislikes).to.equal(1)
454 })
455
456 it('Should sort by originallyPublishedAt', async function () {
457 {
458 const now = new Date()
459 const attributes = { originallyPublishedAt: now.toISOString() }
460 await updateVideo(server.url, server.accessToken, videoId, attributes)
461
462 const res = await getVideosListSort(server.url, '-originallyPublishedAt')
463 const names = res.body.data.map(v => v.name)
464
465 expect(names[0]).to.equal('my super video updated')
466 expect(names[1]).to.equal('video_short2.webm name')
467 expect(names[2]).to.equal('video_short1.webm name')
468 expect(names[3]).to.equal('video_short.webm name')
469 expect(names[4]).to.equal('video_short.ogv name')
470 expect(names[5]).to.equal('video_short.mp4 name')
471 }
472
473 {
474 const now = new Date()
475 const attributes = { originallyPublishedAt: now.toISOString() }
476 await updateVideo(server.url, server.accessToken, videoId2, attributes)
477
478 const res = await getVideosListSort(server.url, '-originallyPublishedAt')
479 const names = res.body.data.map(v => v.name)
480
481 expect(names[0]).to.equal('video_short1.webm name')
482 expect(names[1]).to.equal('my super video updated')
483 expect(names[2]).to.equal('video_short2.webm name')
484 expect(names[3]).to.equal('video_short.webm name')
485 expect(names[4]).to.equal('video_short.ogv name')
486 expect(names[5]).to.equal('video_short.mp4 name')
487 }
488 })
489
490 after(async function () {
491 await cleanupTests([ server ])
492 })
493 }
494
495 describe('Legacy upload', function () {
496 runSuite('legacy')
497 })
498
499 describe('Resumable upload', function () {
500 runSuite('resumable')
501 })
502 })