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