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