]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame_incremental - server/tests/api/videos/multiple-servers.ts
Merge branch 'release/3.3.0' into develop
[github/Chocobozzz/PeerTube.git] / server / tests / api / videos / multiple-servers.ts
... / ...
CommitLineData
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import * as chai from 'chai'
5import * as request from 'supertest'
6import {
7 buildAbsoluteFixturePath,
8 checkTmpIsEmpty,
9 checkVideoFilesWereRemoved,
10 cleanupTests,
11 completeVideoCheck,
12 createMultipleServers,
13 dateIsValid,
14 doubleFollow,
15 PeerTubeServer,
16 setAccessTokensToServers,
17 testImage,
18 wait,
19 waitJobs,
20 webtorrentAdd
21} from '@shared/extra-utils'
22import { HttpStatusCode, VideoCommentThreadTree, VideoPrivacy } from '@shared/models'
23
24const expect = chai.expect
25
26describe('Test multiple servers', function () {
27 let servers: PeerTubeServer[] = []
28 const toRemove = []
29 let videoUUID = ''
30 let videoChannelId: number
31
32 before(async function () {
33 this.timeout(120000)
34
35 servers = await createMultipleServers(3)
36
37 // Get the access tokens
38 await setAccessTokensToServers(servers)
39
40 {
41 const videoChannel = {
42 name: 'super_channel_name',
43 displayName: 'my channel',
44 description: 'super channel'
45 }
46 await servers[0].channels.create({ attributes: videoChannel })
47 const { data } = await servers[0].channels.list({ start: 0, count: 1 })
48 videoChannelId = data[0].id
49 }
50
51 // Server 1 and server 2 follow each other
52 await doubleFollow(servers[0], servers[1])
53 // Server 1 and server 3 follow each other
54 await doubleFollow(servers[0], servers[2])
55 // Server 2 and server 3 follow each other
56 await doubleFollow(servers[1], servers[2])
57 })
58
59 it('Should not have videos for all servers', async function () {
60 for (const server of servers) {
61 const { data } = await server.videos.list()
62 expect(data).to.be.an('array')
63 expect(data.length).to.equal(0)
64 }
65 })
66
67 describe('Should upload the video and propagate on each server', function () {
68 it('Should upload the video on server 1 and propagate on each server', async function () {
69 this.timeout(25000)
70
71 const attributes = {
72 name: 'my super name for server 1',
73 category: 5,
74 licence: 4,
75 language: 'ja',
76 nsfw: true,
77 description: 'my super description for server 1',
78 support: 'my super support text for server 1',
79 originallyPublishedAt: '2019-02-10T13:38:14.449Z',
80 tags: [ 'tag1p1', 'tag2p1' ],
81 channelId: videoChannelId,
82 fixture: 'video_short1.webm'
83 }
84 await servers[0].videos.upload({ attributes })
85
86 await waitJobs(servers)
87
88 // All servers should have this video
89 let publishedAt: string = null
90 for (const server of servers) {
91 const isLocal = server.port === servers[0].port
92 const checkAttributes = {
93 name: 'my super name for server 1',
94 category: 5,
95 licence: 4,
96 language: 'ja',
97 nsfw: true,
98 description: 'my super description for server 1',
99 support: 'my super support text for server 1',
100 originallyPublishedAt: '2019-02-10T13:38:14.449Z',
101 account: {
102 name: 'root',
103 host: 'localhost:' + servers[0].port
104 },
105 isLocal,
106 publishedAt,
107 duration: 10,
108 tags: [ 'tag1p1', 'tag2p1' ],
109 privacy: VideoPrivacy.PUBLIC,
110 commentsEnabled: true,
111 downloadEnabled: true,
112 channel: {
113 displayName: 'my channel',
114 name: 'super_channel_name',
115 description: 'super channel',
116 isLocal
117 },
118 fixture: 'video_short1.webm',
119 files: [
120 {
121 resolution: 720,
122 size: 572456
123 }
124 ]
125 }
126
127 const { data } = await server.videos.list()
128 expect(data).to.be.an('array')
129 expect(data.length).to.equal(1)
130 const video = data[0]
131
132 await completeVideoCheck(server, video, checkAttributes)
133 publishedAt = video.publishedAt as string
134 }
135 })
136
137 it('Should upload the video on server 2 and propagate on each server', async function () {
138 this.timeout(100000)
139
140 const user = {
141 username: 'user1',
142 password: 'super_password'
143 }
144 await servers[1].users.create({ username: user.username, password: user.password })
145 const userAccessToken = await servers[1].login.getAccessToken(user)
146
147 const attributes = {
148 name: 'my super name for server 2',
149 category: 4,
150 licence: 3,
151 language: 'de',
152 nsfw: true,
153 description: 'my super description for server 2',
154 support: 'my super support text for server 2',
155 tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ],
156 fixture: 'video_short2.webm',
157 thumbnailfile: 'thumbnail.jpg',
158 previewfile: 'preview.jpg'
159 }
160 await servers[1].videos.upload({ token: userAccessToken, attributes, mode: 'resumable' })
161
162 // Transcoding
163 await waitJobs(servers)
164
165 // All servers should have this video
166 for (const server of servers) {
167 const isLocal = server.url === 'http://localhost:' + servers[1].port
168 const checkAttributes = {
169 name: 'my super name for server 2',
170 category: 4,
171 licence: 3,
172 language: 'de',
173 nsfw: true,
174 description: 'my super description for server 2',
175 support: 'my super support text for server 2',
176 account: {
177 name: 'user1',
178 host: 'localhost:' + servers[1].port
179 },
180 isLocal,
181 commentsEnabled: true,
182 downloadEnabled: true,
183 duration: 5,
184 tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ],
185 privacy: VideoPrivacy.PUBLIC,
186 channel: {
187 displayName: 'Main user1 channel',
188 name: 'user1_channel',
189 description: 'super channel',
190 isLocal
191 },
192 fixture: 'video_short2.webm',
193 files: [
194 {
195 resolution: 240,
196 size: 270000
197 },
198 {
199 resolution: 360,
200 size: 359000
201 },
202 {
203 resolution: 480,
204 size: 465000
205 },
206 {
207 resolution: 720,
208 size: 788000
209 }
210 ],
211 thumbnailfile: 'thumbnail',
212 previewfile: 'preview'
213 }
214
215 const { data } = await server.videos.list()
216 expect(data).to.be.an('array')
217 expect(data.length).to.equal(2)
218 const video = data[1]
219
220 await completeVideoCheck(server, video, checkAttributes)
221 }
222 })
223
224 it('Should upload two videos on server 3 and propagate on each server', async function () {
225 this.timeout(45000)
226
227 {
228 const attributes = {
229 name: 'my super name for server 3',
230 category: 6,
231 licence: 5,
232 language: 'de',
233 nsfw: true,
234 description: 'my super description for server 3',
235 support: 'my super support text for server 3',
236 tags: [ 'tag1p3' ],
237 fixture: 'video_short3.webm'
238 }
239 await servers[2].videos.upload({ attributes })
240 }
241
242 {
243 const attributes = {
244 name: 'my super name for server 3-2',
245 category: 7,
246 licence: 6,
247 language: 'ko',
248 nsfw: false,
249 description: 'my super description for server 3-2',
250 support: 'my super support text for server 3-2',
251 tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ],
252 fixture: 'video_short.webm'
253 }
254 await servers[2].videos.upload({ attributes })
255 }
256
257 await waitJobs(servers)
258
259 // All servers should have this video
260 for (const server of servers) {
261 const isLocal = server.url === 'http://localhost:' + servers[2].port
262 const { data } = await server.videos.list()
263
264 expect(data).to.be.an('array')
265 expect(data.length).to.equal(4)
266
267 // We not sure about the order of the two last uploads
268 let video1 = null
269 let video2 = null
270 if (data[2].name === 'my super name for server 3') {
271 video1 = data[2]
272 video2 = data[3]
273 } else {
274 video1 = data[3]
275 video2 = data[2]
276 }
277
278 const checkAttributesVideo1 = {
279 name: 'my super name for server 3',
280 category: 6,
281 licence: 5,
282 language: 'de',
283 nsfw: true,
284 description: 'my super description for server 3',
285 support: 'my super support text for server 3',
286 account: {
287 name: 'root',
288 host: 'localhost:' + servers[2].port
289 },
290 isLocal,
291 duration: 5,
292 commentsEnabled: true,
293 downloadEnabled: true,
294 tags: [ 'tag1p3' ],
295 privacy: VideoPrivacy.PUBLIC,
296 channel: {
297 displayName: 'Main root channel',
298 name: 'root_channel',
299 description: '',
300 isLocal
301 },
302 fixture: 'video_short3.webm',
303 files: [
304 {
305 resolution: 720,
306 size: 292677
307 }
308 ]
309 }
310 await completeVideoCheck(server, video1, checkAttributesVideo1)
311
312 const checkAttributesVideo2 = {
313 name: 'my super name for server 3-2',
314 category: 7,
315 licence: 6,
316 language: 'ko',
317 nsfw: false,
318 description: 'my super description for server 3-2',
319 support: 'my super support text for server 3-2',
320 account: {
321 name: 'root',
322 host: 'localhost:' + servers[2].port
323 },
324 commentsEnabled: true,
325 downloadEnabled: true,
326 isLocal,
327 duration: 5,
328 tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ],
329 privacy: VideoPrivacy.PUBLIC,
330 channel: {
331 displayName: 'Main root channel',
332 name: 'root_channel',
333 description: '',
334 isLocal
335 },
336 fixture: 'video_short.webm',
337 files: [
338 {
339 resolution: 720,
340 size: 218910
341 }
342 ]
343 }
344 await completeVideoCheck(server, video2, checkAttributesVideo2)
345 }
346 })
347 })
348
349 describe('It should list local videos', function () {
350 it('Should list only local videos on server 1', async function () {
351 const { data, total } = await servers[0].videos.list({ filter: 'local' })
352
353 expect(total).to.equal(1)
354 expect(data).to.be.an('array')
355 expect(data.length).to.equal(1)
356 expect(data[0].name).to.equal('my super name for server 1')
357 })
358
359 it('Should list only local videos on server 2', async function () {
360 const { data, total } = await servers[1].videos.list({ filter: 'local' })
361
362 expect(total).to.equal(1)
363 expect(data).to.be.an('array')
364 expect(data.length).to.equal(1)
365 expect(data[0].name).to.equal('my super name for server 2')
366 })
367
368 it('Should list only local videos on server 3', async function () {
369 const { data, total } = await servers[2].videos.list({ filter: 'local' })
370
371 expect(total).to.equal(2)
372 expect(data).to.be.an('array')
373 expect(data.length).to.equal(2)
374 expect(data[0].name).to.equal('my super name for server 3')
375 expect(data[1].name).to.equal('my super name for server 3-2')
376 })
377 })
378
379 describe('Should seed the uploaded video', function () {
380 it('Should add the file 1 by asking server 3', async function () {
381 this.timeout(10000)
382
383 const { data } = await servers[2].videos.list()
384
385 const video = data[0]
386 toRemove.push(data[2])
387 toRemove.push(data[3])
388
389 const videoDetails = await servers[2].videos.get({ id: video.id })
390 const torrent = await webtorrentAdd(videoDetails.files[0].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 it('Should add the file 2 by asking server 1', async function () {
397 this.timeout(10000)
398
399 const { data } = await servers[0].videos.list()
400
401 const video = data[1]
402 const videoDetails = await servers[0].videos.get({ id: video.id })
403
404 const torrent = await webtorrentAdd(videoDetails.files[0].magnetUri, true)
405 expect(torrent.files).to.be.an('array')
406 expect(torrent.files.length).to.equal(1)
407 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
408 })
409
410 it('Should add the file 3 by asking server 2', async function () {
411 this.timeout(10000)
412
413 const { data } = await servers[1].videos.list()
414
415 const video = data[2]
416 const videoDetails = await servers[1].videos.get({ id: video.id })
417
418 const torrent = await webtorrentAdd(videoDetails.files[0].magnetUri, true)
419 expect(torrent.files).to.be.an('array')
420 expect(torrent.files.length).to.equal(1)
421 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
422 })
423
424 it('Should add the file 3-2 by asking server 1', async function () {
425 this.timeout(10000)
426
427 const { data } = await servers[0].videos.list()
428
429 const video = data[3]
430 const videoDetails = await servers[0].videos.get({ id: video.id })
431
432 const torrent = await webtorrentAdd(videoDetails.files[0].magnetUri)
433 expect(torrent.files).to.be.an('array')
434 expect(torrent.files.length).to.equal(1)
435 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
436 })
437
438 it('Should add the file 2 in 360p by asking server 1', async function () {
439 this.timeout(10000)
440
441 const { data } = await servers[0].videos.list()
442
443 const video = data.find(v => v.name === 'my super name for server 2')
444 const videoDetails = await servers[0].videos.get({ id: video.id })
445
446 const file = videoDetails.files.find(f => f.resolution.id === 360)
447 expect(file).not.to.be.undefined
448
449 const torrent = await webtorrentAdd(file.magnetUri)
450 expect(torrent.files).to.be.an('array')
451 expect(torrent.files.length).to.equal(1)
452 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
453 })
454 })
455
456 describe('Should update video views, likes and dislikes', function () {
457 let localVideosServer3 = []
458 let remoteVideosServer1 = []
459 let remoteVideosServer2 = []
460 let remoteVideosServer3 = []
461
462 before(async function () {
463 {
464 const { data } = await servers[0].videos.list()
465 remoteVideosServer1 = data.filter(video => video.isLocal === false).map(video => video.uuid)
466 }
467
468 {
469 const { data } = await servers[1].videos.list()
470 remoteVideosServer2 = data.filter(video => video.isLocal === false).map(video => video.uuid)
471 }
472
473 {
474 const { data } = await servers[2].videos.list()
475 localVideosServer3 = data.filter(video => video.isLocal === true).map(video => video.uuid)
476 remoteVideosServer3 = data.filter(video => video.isLocal === false).map(video => video.uuid)
477 }
478 })
479
480 it('Should view multiple videos on owned servers', async function () {
481 this.timeout(30000)
482
483 await servers[2].videos.view({ id: localVideosServer3[0] })
484 await wait(1000)
485
486 await servers[2].videos.view({ id: localVideosServer3[0] })
487 await servers[2].videos.view({ id: localVideosServer3[1] })
488
489 await wait(1000)
490
491 await servers[2].videos.view({ id: localVideosServer3[0] })
492 await servers[2].videos.view({ id: localVideosServer3[0] })
493
494 await waitJobs(servers)
495
496 // Wait the repeatable job
497 await wait(6000)
498
499 await waitJobs(servers)
500
501 for (const server of servers) {
502 const { data } = await server.videos.list()
503
504 const video0 = data.find(v => v.uuid === localVideosServer3[0])
505 const video1 = data.find(v => v.uuid === localVideosServer3[1])
506
507 expect(video0.views).to.equal(3)
508 expect(video1.views).to.equal(1)
509 }
510 })
511
512 it('Should view multiple videos on each servers', async function () {
513 this.timeout(45000)
514
515 const tasks: Promise<any>[] = []
516 tasks.push(servers[0].videos.view({ id: remoteVideosServer1[0] }))
517 tasks.push(servers[1].videos.view({ id: remoteVideosServer2[0] }))
518 tasks.push(servers[1].videos.view({ id: remoteVideosServer2[0] }))
519 tasks.push(servers[2].videos.view({ id: remoteVideosServer3[0] }))
520 tasks.push(servers[2].videos.view({ id: remoteVideosServer3[1] }))
521 tasks.push(servers[2].videos.view({ id: remoteVideosServer3[1] }))
522 tasks.push(servers[2].videos.view({ id: remoteVideosServer3[1] }))
523 tasks.push(servers[2].videos.view({ id: localVideosServer3[1] }))
524 tasks.push(servers[2].videos.view({ id: localVideosServer3[1] }))
525 tasks.push(servers[2].videos.view({ id: localVideosServer3[1] }))
526
527 await Promise.all(tasks)
528
529 await waitJobs(servers)
530
531 // Wait the repeatable job
532 await wait(16000)
533
534 await waitJobs(servers)
535
536 let baseVideos = null
537
538 for (const server of servers) {
539 const { data } = await server.videos.list()
540
541 // Initialize base videos for future comparisons
542 if (baseVideos === null) {
543 baseVideos = data
544 continue
545 }
546
547 for (const baseVideo of baseVideos) {
548 const sameVideo = data.find(video => video.name === baseVideo.name)
549 expect(baseVideo.views).to.equal(sameVideo.views)
550 }
551 }
552 })
553
554 it('Should like and dislikes videos on different services', async function () {
555 this.timeout(50000)
556
557 await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'like' })
558 await wait(500)
559 await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'dislike' })
560 await wait(500)
561 await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'like' })
562 await servers[2].videos.rate({ id: localVideosServer3[1], rating: 'like' })
563 await wait(500)
564 await servers[2].videos.rate({ id: localVideosServer3[1], rating: 'dislike' })
565 await servers[2].videos.rate({ id: remoteVideosServer3[1], rating: 'dislike' })
566 await wait(500)
567 await servers[2].videos.rate({ id: remoteVideosServer3[0], rating: 'like' })
568
569 await waitJobs(servers)
570 await wait(5000)
571 await waitJobs(servers)
572
573 let baseVideos = null
574 for (const server of servers) {
575 const { data } = await server.videos.list()
576
577 // Initialize base videos for future comparisons
578 if (baseVideos === null) {
579 baseVideos = data
580 continue
581 }
582
583 for (const baseVideo of baseVideos) {
584 const sameVideo = data.find(video => video.name === baseVideo.name)
585 expect(baseVideo.likes).to.equal(sameVideo.likes)
586 expect(baseVideo.dislikes).to.equal(sameVideo.dislikes)
587 }
588 }
589 })
590 })
591
592 describe('Should manipulate these videos', function () {
593 it('Should update the video 3 by asking server 3', async function () {
594 this.timeout(10000)
595
596 const attributes = {
597 name: 'my super video updated',
598 category: 10,
599 licence: 7,
600 language: 'fr',
601 nsfw: true,
602 description: 'my super description updated',
603 support: 'my super support text updated',
604 tags: [ 'tag_up_1', 'tag_up_2' ],
605 thumbnailfile: 'thumbnail.jpg',
606 originallyPublishedAt: '2019-02-11T13:38:14.449Z',
607 previewfile: 'preview.jpg'
608 }
609
610 await servers[2].videos.update({ id: toRemove[0].id, attributes })
611
612 await waitJobs(servers)
613 })
614
615 it('Should have the video 3 updated on each server', async function () {
616 this.timeout(10000)
617
618 for (const server of servers) {
619 const { data } = await server.videos.list()
620
621 const videoUpdated = data.find(video => video.name === 'my super video updated')
622 expect(!!videoUpdated).to.be.true
623
624 const isLocal = server.url === 'http://localhost:' + servers[2].port
625 const checkAttributes = {
626 name: 'my super video updated',
627 category: 10,
628 licence: 7,
629 language: 'fr',
630 nsfw: true,
631 description: 'my super description updated',
632 support: 'my super support text updated',
633 originallyPublishedAt: '2019-02-11T13:38:14.449Z',
634 account: {
635 name: 'root',
636 host: 'localhost:' + servers[2].port
637 },
638 isLocal,
639 duration: 5,
640 commentsEnabled: true,
641 downloadEnabled: true,
642 tags: [ 'tag_up_1', 'tag_up_2' ],
643 privacy: VideoPrivacy.PUBLIC,
644 channel: {
645 displayName: 'Main root channel',
646 name: 'root_channel',
647 description: '',
648 isLocal
649 },
650 fixture: 'video_short3.webm',
651 files: [
652 {
653 resolution: 720,
654 size: 292677
655 }
656 ],
657 thumbnailfile: 'thumbnail',
658 previewfile: 'preview'
659 }
660 await completeVideoCheck(server, videoUpdated, checkAttributes)
661 }
662 })
663
664 it('Should remove the videos 3 and 3-2 by asking server 3', async function () {
665 this.timeout(10000)
666
667 await servers[2].videos.remove({ id: toRemove[0].id })
668 await servers[2].videos.remove({ id: toRemove[1].id })
669
670 await waitJobs(servers)
671 })
672
673 it('Should not have files of videos 3 and 3-2 on each server', async function () {
674 for (const server of servers) {
675 await checkVideoFilesWereRemoved(toRemove[0].uuid, server)
676 await checkVideoFilesWereRemoved(toRemove[1].uuid, server)
677 }
678 })
679
680 it('Should have videos 1 and 3 on each server', async function () {
681 for (const server of servers) {
682 const { data } = await server.videos.list()
683
684 expect(data).to.be.an('array')
685 expect(data.length).to.equal(2)
686 expect(data[0].name).not.to.equal(data[1].name)
687 expect(data[0].name).not.to.equal(toRemove[0].name)
688 expect(data[1].name).not.to.equal(toRemove[0].name)
689 expect(data[0].name).not.to.equal(toRemove[1].name)
690 expect(data[1].name).not.to.equal(toRemove[1].name)
691
692 videoUUID = data.find(video => video.name === 'my super name for server 1').uuid
693 }
694 })
695
696 it('Should get the same video by UUID on each server', async function () {
697 let baseVideo = null
698 for (const server of servers) {
699 const video = await server.videos.get({ id: videoUUID })
700
701 if (baseVideo === null) {
702 baseVideo = video
703 continue
704 }
705
706 expect(baseVideo.name).to.equal(video.name)
707 expect(baseVideo.uuid).to.equal(video.uuid)
708 expect(baseVideo.category.id).to.equal(video.category.id)
709 expect(baseVideo.language.id).to.equal(video.language.id)
710 expect(baseVideo.licence.id).to.equal(video.licence.id)
711 expect(baseVideo.nsfw).to.equal(video.nsfw)
712 expect(baseVideo.account.name).to.equal(video.account.name)
713 expect(baseVideo.account.displayName).to.equal(video.account.displayName)
714 expect(baseVideo.account.url).to.equal(video.account.url)
715 expect(baseVideo.account.host).to.equal(video.account.host)
716 expect(baseVideo.tags).to.deep.equal(video.tags)
717 }
718 })
719
720 it('Should get the preview from each server', async function () {
721 for (const server of servers) {
722 const video = await server.videos.get({ id: videoUUID })
723
724 await testImage(server.url, 'video_short1-preview.webm', video.previewPath)
725 }
726 })
727 })
728
729 describe('Should comment these videos', function () {
730 let childOfFirstChild: VideoCommentThreadTree
731
732 it('Should add comment (threads and replies)', async function () {
733 this.timeout(25000)
734
735 {
736 const text = 'my super first comment'
737 await servers[0].comments.createThread({ videoId: videoUUID, text })
738 }
739
740 {
741 const text = 'my super second comment'
742 await servers[2].comments.createThread({ videoId: videoUUID, text })
743 }
744
745 await waitJobs(servers)
746
747 {
748 const threadId = await servers[1].comments.findCommentId({ videoId: videoUUID, text: 'my super first comment' })
749
750 const text = 'my super answer to thread 1'
751 await servers[1].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text })
752 }
753
754 await waitJobs(servers)
755
756 {
757 const threadId = await servers[2].comments.findCommentId({ videoId: videoUUID, text: 'my super first comment' })
758
759 const body = await servers[2].comments.getThread({ videoId: videoUUID, threadId })
760 const childCommentId = body.children[0].comment.id
761
762 const text3 = 'my second answer to thread 1'
763 await servers[2].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text: text3 })
764
765 const text2 = 'my super answer to answer of thread 1'
766 await servers[2].comments.addReply({ videoId: videoUUID, toCommentId: childCommentId, text: text2 })
767 }
768
769 await waitJobs(servers)
770 })
771
772 it('Should have these threads', async function () {
773 for (const server of servers) {
774 const body = await server.comments.listThreads({ videoId: videoUUID })
775
776 expect(body.total).to.equal(2)
777 expect(body.data).to.be.an('array')
778 expect(body.data).to.have.lengthOf(2)
779
780 {
781 const comment = body.data.find(c => c.text === 'my super first comment')
782 expect(comment).to.not.be.undefined
783 expect(comment.inReplyToCommentId).to.be.null
784 expect(comment.account.name).to.equal('root')
785 expect(comment.account.host).to.equal('localhost:' + servers[0].port)
786 expect(comment.totalReplies).to.equal(3)
787 expect(dateIsValid(comment.createdAt as string)).to.be.true
788 expect(dateIsValid(comment.updatedAt as string)).to.be.true
789 }
790
791 {
792 const comment = body.data.find(c => c.text === 'my super second comment')
793 expect(comment).to.not.be.undefined
794 expect(comment.inReplyToCommentId).to.be.null
795 expect(comment.account.name).to.equal('root')
796 expect(comment.account.host).to.equal('localhost:' + servers[2].port)
797 expect(comment.totalReplies).to.equal(0)
798 expect(dateIsValid(comment.createdAt as string)).to.be.true
799 expect(dateIsValid(comment.updatedAt as string)).to.be.true
800 }
801 }
802 })
803
804 it('Should have these comments', async function () {
805 for (const server of servers) {
806 const body = await server.comments.listThreads({ videoId: videoUUID })
807 const threadId = body.data.find(c => c.text === 'my super first comment').id
808
809 const tree = await server.comments.getThread({ videoId: videoUUID, threadId })
810
811 expect(tree.comment.text).equal('my super first comment')
812 expect(tree.comment.account.name).equal('root')
813 expect(tree.comment.account.host).equal('localhost:' + servers[0].port)
814 expect(tree.children).to.have.lengthOf(2)
815
816 const firstChild = tree.children[0]
817 expect(firstChild.comment.text).to.equal('my super answer to thread 1')
818 expect(firstChild.comment.account.name).equal('root')
819 expect(firstChild.comment.account.host).equal('localhost:' + servers[1].port)
820 expect(firstChild.children).to.have.lengthOf(1)
821
822 childOfFirstChild = firstChild.children[0]
823 expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1')
824 expect(childOfFirstChild.comment.account.name).equal('root')
825 expect(childOfFirstChild.comment.account.host).equal('localhost:' + servers[2].port)
826 expect(childOfFirstChild.children).to.have.lengthOf(0)
827
828 const secondChild = tree.children[1]
829 expect(secondChild.comment.text).to.equal('my second answer to thread 1')
830 expect(secondChild.comment.account.name).equal('root')
831 expect(secondChild.comment.account.host).equal('localhost:' + servers[2].port)
832 expect(secondChild.children).to.have.lengthOf(0)
833 }
834 })
835
836 it('Should delete a reply', async function () {
837 this.timeout(10000)
838
839 await servers[2].comments.delete({ videoId: videoUUID, commentId: childOfFirstChild.comment.id })
840
841 await waitJobs(servers)
842 })
843
844 it('Should have this comment marked as deleted', async function () {
845 for (const server of servers) {
846 const { data } = await server.comments.listThreads({ videoId: videoUUID })
847 const threadId = data.find(c => c.text === 'my super first comment').id
848
849 const tree = await server.comments.getThread({ videoId: videoUUID, threadId })
850 expect(tree.comment.text).equal('my super first comment')
851
852 const firstChild = tree.children[0]
853 expect(firstChild.comment.text).to.equal('my super answer to thread 1')
854 expect(firstChild.children).to.have.lengthOf(1)
855
856 const deletedComment = firstChild.children[0].comment
857 expect(deletedComment.isDeleted).to.be.true
858 expect(deletedComment.deletedAt).to.not.be.null
859 expect(deletedComment.account).to.be.null
860 expect(deletedComment.text).to.equal('')
861
862 const secondChild = tree.children[1]
863 expect(secondChild.comment.text).to.equal('my second answer to thread 1')
864 }
865 })
866
867 it('Should delete the thread comments', async function () {
868 this.timeout(10000)
869
870 const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
871 const commentId = data.find(c => c.text === 'my super first comment').id
872 await servers[0].comments.delete({ videoId: videoUUID, commentId })
873
874 await waitJobs(servers)
875 })
876
877 it('Should have the threads marked as deleted on other servers too', async function () {
878 for (const server of servers) {
879 const body = await server.comments.listThreads({ videoId: videoUUID })
880
881 expect(body.total).to.equal(2)
882 expect(body.data).to.be.an('array')
883 expect(body.data).to.have.lengthOf(2)
884
885 {
886 const comment = body.data[0]
887 expect(comment).to.not.be.undefined
888 expect(comment.inReplyToCommentId).to.be.null
889 expect(comment.account.name).to.equal('root')
890 expect(comment.account.host).to.equal('localhost:' + servers[2].port)
891 expect(comment.totalReplies).to.equal(0)
892 expect(dateIsValid(comment.createdAt as string)).to.be.true
893 expect(dateIsValid(comment.updatedAt as string)).to.be.true
894 }
895
896 {
897 const deletedComment = body.data[1]
898 expect(deletedComment).to.not.be.undefined
899 expect(deletedComment.isDeleted).to.be.true
900 expect(deletedComment.deletedAt).to.not.be.null
901 expect(deletedComment.text).to.equal('')
902 expect(deletedComment.inReplyToCommentId).to.be.null
903 expect(deletedComment.account).to.be.null
904 expect(deletedComment.totalReplies).to.equal(2)
905 expect(dateIsValid(deletedComment.createdAt as string)).to.be.true
906 expect(dateIsValid(deletedComment.updatedAt as string)).to.be.true
907 expect(dateIsValid(deletedComment.deletedAt as string)).to.be.true
908 }
909 }
910 })
911
912 it('Should delete a remote thread by the origin server', async function () {
913 this.timeout(5000)
914
915 const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
916 const commentId = data.find(c => c.text === 'my super second comment').id
917 await servers[0].comments.delete({ videoId: videoUUID, commentId })
918
919 await waitJobs(servers)
920 })
921
922 it('Should have the threads marked as deleted on other servers too', async function () {
923 for (const server of servers) {
924 const body = await server.comments.listThreads({ videoId: videoUUID })
925
926 expect(body.total).to.equal(2)
927 expect(body.data).to.have.lengthOf(2)
928
929 {
930 const comment = body.data[0]
931 expect(comment.text).to.equal('')
932 expect(comment.isDeleted).to.be.true
933 expect(comment.createdAt).to.not.be.null
934 expect(comment.deletedAt).to.not.be.null
935 expect(comment.account).to.be.null
936 expect(comment.totalReplies).to.equal(0)
937 }
938
939 {
940 const comment = body.data[1]
941 expect(comment.text).to.equal('')
942 expect(comment.isDeleted).to.be.true
943 expect(comment.createdAt).to.not.be.null
944 expect(comment.deletedAt).to.not.be.null
945 expect(comment.account).to.be.null
946 expect(comment.totalReplies).to.equal(2)
947 }
948 }
949 })
950
951 it('Should disable comments and download', async function () {
952 this.timeout(20000)
953
954 const attributes = {
955 commentsEnabled: false,
956 downloadEnabled: false
957 }
958
959 await servers[0].videos.update({ id: videoUUID, attributes })
960
961 await waitJobs(servers)
962
963 for (const server of servers) {
964 const video = await server.videos.get({ id: videoUUID })
965 expect(video.commentsEnabled).to.be.false
966 expect(video.downloadEnabled).to.be.false
967
968 const text = 'my super forbidden comment'
969 await server.comments.createThread({ videoId: videoUUID, text, expectedStatus: HttpStatusCode.CONFLICT_409 })
970 }
971 })
972 })
973
974 describe('With minimum parameters', function () {
975 it('Should upload and propagate the video', async function () {
976 this.timeout(60000)
977
978 const path = '/api/v1/videos/upload'
979
980 const req = request(servers[1].url)
981 .post(path)
982 .set('Accept', 'application/json')
983 .set('Authorization', 'Bearer ' + servers[1].accessToken)
984 .field('name', 'minimum parameters')
985 .field('privacy', '1')
986 .field('channelId', '1')
987
988 await req.attach('videofile', buildAbsoluteFixturePath('video_short.webm'))
989 .expect(HttpStatusCode.OK_200)
990
991 await waitJobs(servers)
992
993 for (const server of servers) {
994 const { data } = await server.videos.list()
995 const video = data.find(v => v.name === 'minimum parameters')
996
997 const isLocal = server.url === 'http://localhost:' + servers[1].port
998 const checkAttributes = {
999 name: 'minimum parameters',
1000 category: null,
1001 licence: null,
1002 language: null,
1003 nsfw: false,
1004 description: null,
1005 support: null,
1006 account: {
1007 name: 'root',
1008 host: 'localhost:' + servers[1].port
1009 },
1010 isLocal,
1011 duration: 5,
1012 commentsEnabled: true,
1013 downloadEnabled: true,
1014 tags: [],
1015 privacy: VideoPrivacy.PUBLIC,
1016 channel: {
1017 displayName: 'Main root channel',
1018 name: 'root_channel',
1019 description: '',
1020 isLocal
1021 },
1022 fixture: 'video_short.webm',
1023 files: [
1024 {
1025 resolution: 720,
1026 size: 59000
1027 },
1028 {
1029 resolution: 480,
1030 size: 34000
1031 },
1032 {
1033 resolution: 360,
1034 size: 31000
1035 },
1036 {
1037 resolution: 240,
1038 size: 23000
1039 }
1040 ]
1041 }
1042 await completeVideoCheck(server, video, checkAttributes)
1043 }
1044 })
1045 })
1046
1047 describe('TMP directory', function () {
1048 it('Should have an empty tmp directory', async function () {
1049 for (const server of servers) {
1050 await checkTmpIsEmpty(server)
1051 }
1052 })
1053 })
1054
1055 after(async function () {
1056 await cleanupTests(servers)
1057 })
1058})