Add videos playlist exist tests
[oweals/peertube.git] / server / tests / api / videos / video-playlists.ts
1 /* tslint:disable:no-unused-expression */
2
3 import * as chai from 'chai'
4 import 'mocha'
5 import {
6   addVideoChannel,
7   addVideoInPlaylist,
8   checkPlaylistFilesWereRemoved,
9   createUser,
10   createVideoPlaylist,
11   deleteVideoChannel,
12   deleteVideoPlaylist,
13   doubleFollow, doVideosExistInMyPlaylist,
14   flushAndRunMultipleServers,
15   flushTests,
16   getAccountPlaylistsList,
17   getAccountPlaylistsListWithToken,
18   getPlaylistVideos,
19   getVideoChannelPlaylistsList,
20   getVideoPlaylist,
21   getVideoPlaylistPrivacies,
22   getVideoPlaylistsList,
23   getVideoPlaylistWithToken,
24   killallServers,
25   removeUser,
26   removeVideoFromPlaylist,
27   reorderVideosPlaylist,
28   ServerInfo,
29   setAccessTokensToServers,
30   setDefaultVideoChannel,
31   testImage,
32   unfollow,
33   updateVideoPlaylist,
34   updateVideoPlaylistElement,
35   uploadVideo,
36   uploadVideoAndGetId,
37   userLogin,
38   waitJobs
39 } from '../../../../shared/utils'
40 import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
41 import { VideoPlaylist } from '../../../../shared/models/videos/playlist/video-playlist.model'
42 import { Video } from '../../../../shared/models/videos'
43 import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model'
44 import { VideoExistInPlaylist } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
45
46 const expect = chai.expect
47
48 describe('Test video playlists', function () {
49   let servers: ServerInfo[] = []
50
51   let playlistServer2Id1: number
52   let playlistServer2Id2: number
53   let playlistServer2UUID2: number
54
55   let playlistServer1Id: number
56   let playlistServer1UUID: string
57
58   let nsfwVideoServer1: number
59
60   before(async function () {
61     this.timeout(120000)
62
63     servers = await flushAndRunMultipleServers(3, { transcoding: { enabled: false } })
64
65     // Get the access tokens
66     await setAccessTokensToServers(servers)
67     await setDefaultVideoChannel(servers)
68
69     // Server 1 and server 2 follow each other
70     await doubleFollow(servers[0], servers[1])
71     // Server 1 and server 3 follow each other
72     await doubleFollow(servers[0], servers[2])
73
74     {
75       const serverPromises: Promise<any>[][] = []
76
77       for (const server of servers) {
78         const videoPromises: Promise<any>[] = []
79
80         for (let i = 0; i < 7; i++) {
81           videoPromises.push(
82             uploadVideo(server.url, server.accessToken, { name: `video ${i} server ${server.serverNumber}`, nsfw: false })
83               .then(res => res.body.video)
84           )
85         }
86
87         serverPromises.push(videoPromises)
88       }
89
90       servers[0].videos = await Promise.all(serverPromises[0])
91       servers[1].videos = await Promise.all(serverPromises[1])
92       servers[2].videos = await Promise.all(serverPromises[2])
93     }
94
95     nsfwVideoServer1 = (await uploadVideoAndGetId({ server: servers[ 0 ], videoName: 'NSFW video', nsfw: true })).id
96
97     await waitJobs(servers)
98   })
99
100   it('Should list video playlist privacies', async function () {
101     const res = await getVideoPlaylistPrivacies(servers[0].url)
102
103     const privacies = res.body
104     expect(Object.keys(privacies)).to.have.length.at.least(3)
105
106     expect(privacies[3]).to.equal('Private')
107   })
108
109   it('Should list watch later playlist', async function () {
110     const url = servers[ 0 ].url
111     const accessToken = servers[ 0 ].accessToken
112
113     {
114       const res = await getAccountPlaylistsListWithToken(url, accessToken, 'root', 0, 5, VideoPlaylistType.WATCH_LATER)
115
116       expect(res.body.total).to.equal(1)
117       expect(res.body.data).to.have.lengthOf(1)
118
119       const playlist: VideoPlaylist = res.body.data[ 0 ]
120       expect(playlist.displayName).to.equal('Watch later')
121       expect(playlist.type.id).to.equal(VideoPlaylistType.WATCH_LATER)
122       expect(playlist.type.label).to.equal('Watch later')
123     }
124
125     {
126       const res = await getAccountPlaylistsListWithToken(url, accessToken, 'root', 0, 5, VideoPlaylistType.REGULAR)
127
128       expect(res.body.total).to.equal(0)
129       expect(res.body.data).to.have.lengthOf(0)
130     }
131
132     {
133       const res = await getAccountPlaylistsList(url, 'root', 0, 5)
134       expect(res.body.total).to.equal(0)
135       expect(res.body.data).to.have.lengthOf(0)
136     }
137   })
138
139   it('Should create a playlist on server 1 and have the playlist on server 2 and 3', async function () {
140     this.timeout(30000)
141
142     await createVideoPlaylist({
143       url: servers[0].url,
144       token: servers[0].accessToken,
145       playlistAttrs: {
146         displayName: 'my super playlist',
147         privacy: VideoPlaylistPrivacy.PUBLIC,
148         description: 'my super description',
149         thumbnailfile: 'thumbnail.jpg',
150         videoChannelId: servers[0].videoChannel.id
151       }
152     })
153
154     await waitJobs(servers)
155
156     for (const server of servers) {
157       const res = await getVideoPlaylistsList(server.url, 0, 5)
158       expect(res.body.total).to.equal(1)
159       expect(res.body.data).to.have.lengthOf(1)
160
161       const playlistFromList = res.body.data[0] as VideoPlaylist
162
163       const res2 = await getVideoPlaylist(server.url, playlistFromList.uuid)
164       const playlistFromGet = res2.body
165
166       for (const playlist of [ playlistFromGet, playlistFromList ]) {
167         expect(playlist.id).to.be.a('number')
168         expect(playlist.uuid).to.be.a('string')
169
170         expect(playlist.isLocal).to.equal(server.serverNumber === 1)
171
172         expect(playlist.displayName).to.equal('my super playlist')
173         expect(playlist.description).to.equal('my super description')
174         expect(playlist.privacy.id).to.equal(VideoPlaylistPrivacy.PUBLIC)
175         expect(playlist.privacy.label).to.equal('Public')
176         expect(playlist.type.id).to.equal(VideoPlaylistType.REGULAR)
177         expect(playlist.type.label).to.equal('Regular')
178
179         expect(playlist.videosLength).to.equal(0)
180
181         expect(playlist.ownerAccount.name).to.equal('root')
182         expect(playlist.ownerAccount.displayName).to.equal('root')
183         expect(playlist.videoChannel.name).to.equal('root_channel')
184         expect(playlist.videoChannel.displayName).to.equal('Main root channel')
185       }
186     }
187   })
188
189   it('Should create a playlist on server 2 and have the playlist on server 1 but not on server 3', async function () {
190     this.timeout(30000)
191
192     {
193       const res = await createVideoPlaylist({
194         url: servers[1].url,
195         token: servers[1].accessToken,
196         playlistAttrs: {
197           displayName: 'playlist 2',
198           privacy: VideoPlaylistPrivacy.PUBLIC
199         }
200       })
201       playlistServer2Id1 = res.body.videoPlaylist.id
202     }
203
204     {
205       const res = await createVideoPlaylist({
206         url: servers[ 1 ].url,
207         token: servers[ 1 ].accessToken,
208         playlistAttrs: {
209           displayName: 'playlist 3',
210           privacy: VideoPlaylistPrivacy.PUBLIC,
211           thumbnailfile: 'thumbnail.jpg'
212         }
213       })
214
215       playlistServer2Id2 = res.body.videoPlaylist.id
216       playlistServer2UUID2 = res.body.videoPlaylist.uuid
217     }
218
219     for (let id of [ playlistServer2Id1, playlistServer2Id2 ]) {
220       await addVideoInPlaylist({
221         url: servers[ 1 ].url,
222         token: servers[ 1 ].accessToken,
223         playlistId: id,
224         elementAttrs: { videoId: servers[ 1 ].videos[ 0 ].id, startTimestamp: 1, stopTimestamp: 2 }
225       })
226       await addVideoInPlaylist({
227         url: servers[ 1 ].url,
228         token: servers[ 1 ].accessToken,
229         playlistId: id,
230         elementAttrs: { videoId: servers[ 1 ].videos[ 1 ].id }
231       })
232     }
233
234     await waitJobs(servers)
235
236     for (const server of [ servers[0], servers[1] ]) {
237       const res = await getVideoPlaylistsList(server.url, 0, 5)
238
239       const playlist2 = res.body.data.find(p => p.displayName === 'playlist 2')
240       expect(playlist2).to.not.be.undefined
241       await testImage(server.url, 'thumbnail-playlist', playlist2.thumbnailPath)
242
243       const playlist3 = res.body.data.find(p => p.displayName === 'playlist 3')
244       expect(playlist3).to.not.be.undefined
245       await testImage(server.url, 'thumbnail', playlist3.thumbnailPath)
246     }
247
248     const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
249     expect(res.body.data.find(p => p.displayName === 'playlist 2')).to.be.undefined
250     expect(res.body.data.find(p => p.displayName === 'playlist 3')).to.be.undefined
251   })
252
253   it('Should have the playlist on server 3 after a new follow', async function () {
254     this.timeout(30000)
255
256     // Server 2 and server 3 follow each other
257     await doubleFollow(servers[1], servers[2])
258
259     const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
260
261     const playlist2 = res.body.data.find(p => p.displayName === 'playlist 2')
262     expect(playlist2).to.not.be.undefined
263     await testImage(servers[2].url, 'thumbnail-playlist', playlist2.thumbnailPath)
264
265     expect(res.body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined
266   })
267
268   it('Should correctly list the playlists', async function () {
269     this.timeout(30000)
270
271     {
272       const res = await getVideoPlaylistsList(servers[ 2 ].url, 1, 2, 'createdAt')
273
274       expect(res.body.total).to.equal(3)
275
276       const data: VideoPlaylist[] = res.body.data
277       expect(data).to.have.lengthOf(2)
278       expect(data[ 0 ].displayName).to.equal('playlist 2')
279       expect(data[ 1 ].displayName).to.equal('playlist 3')
280     }
281
282     {
283       const res = await getVideoPlaylistsList(servers[ 2 ].url, 1, 2, '-createdAt')
284
285       expect(res.body.total).to.equal(3)
286
287       const data: VideoPlaylist[] = res.body.data
288       expect(data).to.have.lengthOf(2)
289       expect(data[ 0 ].displayName).to.equal('playlist 2')
290       expect(data[ 1 ].displayName).to.equal('my super playlist')
291     }
292   })
293
294   it('Should list video channel playlists', async function () {
295     this.timeout(30000)
296
297     {
298       const res = await getVideoChannelPlaylistsList(servers[ 0 ].url, 'root_channel', 0, 2, '-createdAt')
299
300       expect(res.body.total).to.equal(1)
301
302       const data: VideoPlaylist[] = res.body.data
303       expect(data).to.have.lengthOf(1)
304       expect(data[ 0 ].displayName).to.equal('my super playlist')
305     }
306   })
307
308   it('Should list account playlists', async function () {
309     this.timeout(30000)
310
311     {
312       const res = await getAccountPlaylistsList(servers[ 1 ].url, 'root', 1, 2, '-createdAt')
313
314       expect(res.body.total).to.equal(2)
315
316       const data: VideoPlaylist[] = res.body.data
317       expect(data).to.have.lengthOf(1)
318       expect(data[ 0 ].displayName).to.equal('playlist 2')
319     }
320
321     {
322       const res = await getAccountPlaylistsList(servers[ 1 ].url, 'root', 1, 2, 'createdAt')
323
324       expect(res.body.total).to.equal(2)
325
326       const data: VideoPlaylist[] = res.body.data
327       expect(data).to.have.lengthOf(1)
328       expect(data[ 0 ].displayName).to.equal('playlist 3')
329     }
330   })
331
332   it('Should not list unlisted or private playlists', async function () {
333     this.timeout(30000)
334
335     await createVideoPlaylist({
336       url: servers[ 1 ].url,
337       token: servers[ 1 ].accessToken,
338       playlistAttrs: {
339         displayName: 'playlist unlisted',
340         privacy: VideoPlaylistPrivacy.UNLISTED
341       }
342     })
343
344     await createVideoPlaylist({
345       url: servers[ 1 ].url,
346       token: servers[ 1 ].accessToken,
347       playlistAttrs: {
348         displayName: 'playlist private',
349         privacy: VideoPlaylistPrivacy.PRIVATE
350       }
351     })
352
353     await waitJobs(servers)
354
355     for (const server of servers) {
356       const results = [
357         await getAccountPlaylistsList(server.url, 'root@localhost:9002', 0, 5, '-createdAt'),
358         await getVideoPlaylistsList(server.url, 0, 2, '-createdAt')
359       ]
360
361       expect(results[0].body.total).to.equal(2)
362       expect(results[1].body.total).to.equal(3)
363
364       for (const res of results) {
365         const data: VideoPlaylist[] = res.body.data
366         expect(data).to.have.lengthOf(2)
367         expect(data[ 0 ].displayName).to.equal('playlist 3')
368         expect(data[ 1 ].displayName).to.equal('playlist 2')
369       }
370     }
371   })
372
373   it('Should update a playlist', async function () {
374     this.timeout(30000)
375
376     await updateVideoPlaylist({
377       url: servers[1].url,
378       token: servers[1].accessToken,
379       playlistAttrs: {
380         displayName: 'playlist 3 updated',
381         description: 'description updated',
382         privacy: VideoPlaylistPrivacy.UNLISTED,
383         thumbnailfile: 'thumbnail.jpg',
384         videoChannelId: servers[1].videoChannel.id
385       },
386       playlistId: playlistServer2Id2
387     })
388
389     await waitJobs(servers)
390
391     for (const server of servers) {
392       const res = await getVideoPlaylist(server.url, playlistServer2UUID2)
393       const playlist: VideoPlaylist = res.body
394
395       expect(playlist.displayName).to.equal('playlist 3 updated')
396       expect(playlist.description).to.equal('description updated')
397
398       expect(playlist.privacy.id).to.equal(VideoPlaylistPrivacy.UNLISTED)
399       expect(playlist.privacy.label).to.equal('Unlisted')
400
401       expect(playlist.type.id).to.equal(VideoPlaylistType.REGULAR)
402       expect(playlist.type.label).to.equal('Regular')
403
404       expect(playlist.videosLength).to.equal(2)
405
406       expect(playlist.ownerAccount.name).to.equal('root')
407       expect(playlist.ownerAccount.displayName).to.equal('root')
408       expect(playlist.videoChannel.name).to.equal('root_channel')
409       expect(playlist.videoChannel.displayName).to.equal('Main root channel')
410     }
411   })
412
413   it('Should create a playlist containing different startTimestamp/endTimestamp videos', async function () {
414     this.timeout(30000)
415
416     const addVideo = (elementAttrs: any) => {
417       return addVideoInPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistId: playlistServer1Id, elementAttrs })
418     }
419
420     const res = await createVideoPlaylist({
421       url: servers[ 0 ].url,
422       token: servers[ 0 ].accessToken,
423       playlistAttrs: {
424         displayName: 'playlist 4',
425         privacy: VideoPlaylistPrivacy.PUBLIC
426       }
427     })
428
429     playlistServer1Id = res.body.videoPlaylist.id
430     playlistServer1UUID = res.body.videoPlaylist.uuid
431
432     await addVideo({ videoId: servers[0].videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 })
433     await addVideo({ videoId: servers[2].videos[1].uuid, startTimestamp: 35 })
434     await addVideo({ videoId: servers[2].videos[2].uuid })
435     await addVideo({ videoId: servers[0].videos[3].uuid, stopTimestamp: 35 })
436     await addVideo({ videoId: servers[0].videos[4].uuid, startTimestamp: 45, stopTimestamp: 60 })
437     await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 })
438
439     await waitJobs(servers)
440   })
441
442   it('Should correctly list playlist videos', async function () {
443     this.timeout(30000)
444
445     for (const server of servers) {
446       const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
447
448       expect(res.body.total).to.equal(6)
449
450       const videos: Video[] = res.body.data
451       expect(videos).to.have.lengthOf(6)
452
453       expect(videos[0].name).to.equal('video 0 server 1')
454       expect(videos[0].playlistElement.position).to.equal(1)
455       expect(videos[0].playlistElement.startTimestamp).to.equal(15)
456       expect(videos[0].playlistElement.stopTimestamp).to.equal(28)
457
458       expect(videos[1].name).to.equal('video 1 server 3')
459       expect(videos[1].playlistElement.position).to.equal(2)
460       expect(videos[1].playlistElement.startTimestamp).to.equal(35)
461       expect(videos[1].playlistElement.stopTimestamp).to.be.null
462
463       expect(videos[2].name).to.equal('video 2 server 3')
464       expect(videos[2].playlistElement.position).to.equal(3)
465       expect(videos[2].playlistElement.startTimestamp).to.be.null
466       expect(videos[2].playlistElement.stopTimestamp).to.be.null
467
468       expect(videos[3].name).to.equal('video 3 server 1')
469       expect(videos[3].playlistElement.position).to.equal(4)
470       expect(videos[3].playlistElement.startTimestamp).to.be.null
471       expect(videos[3].playlistElement.stopTimestamp).to.equal(35)
472
473       expect(videos[4].name).to.equal('video 4 server 1')
474       expect(videos[4].playlistElement.position).to.equal(5)
475       expect(videos[4].playlistElement.startTimestamp).to.equal(45)
476       expect(videos[4].playlistElement.stopTimestamp).to.equal(60)
477
478       expect(videos[5].name).to.equal('NSFW video')
479       expect(videos[5].playlistElement.position).to.equal(6)
480       expect(videos[5].playlistElement.startTimestamp).to.equal(5)
481       expect(videos[5].playlistElement.stopTimestamp).to.be.null
482
483       const res2 = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10, { nsfw: false })
484       expect(res2.body.total).to.equal(5)
485       expect(res2.body.data.find(v => v.name === 'NSFW video')).to.be.undefined
486
487       const res3 = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 2)
488       expect(res3.body.data).to.have.lengthOf(2)
489     }
490   })
491
492   it('Should reorder the playlist', async function () {
493     this.timeout(30000)
494
495     {
496       await reorderVideosPlaylist({
497         url: servers[ 0 ].url,
498         token: servers[ 0 ].accessToken,
499         playlistId: playlistServer1Id,
500         elementAttrs: {
501           startPosition: 2,
502           insertAfterPosition: 3
503         }
504       })
505
506       await waitJobs(servers)
507
508       for (const server of servers) {
509         const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
510         const names = res.body.data.map(v => v.name)
511
512         expect(names).to.deep.equal([
513           'video 0 server 1',
514           'video 2 server 3',
515           'video 1 server 3',
516           'video 3 server 1',
517           'video 4 server 1',
518           'NSFW video'
519         ])
520       }
521     }
522
523     {
524       await reorderVideosPlaylist({
525         url: servers[0].url,
526         token: servers[0].accessToken,
527         playlistId: playlistServer1Id,
528         elementAttrs: {
529           startPosition: 1,
530           reorderLength: 3,
531           insertAfterPosition: 4
532         }
533       })
534
535       await waitJobs(servers)
536
537       for (const server of servers) {
538         const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
539         const names = res.body.data.map(v => v.name)
540
541         expect(names).to.deep.equal([
542           'video 3 server 1',
543           'video 0 server 1',
544           'video 2 server 3',
545           'video 1 server 3',
546           'video 4 server 1',
547           'NSFW video'
548         ])
549       }
550     }
551
552     {
553       await reorderVideosPlaylist({
554         url: servers[0].url,
555         token: servers[0].accessToken,
556         playlistId: playlistServer1Id,
557         elementAttrs: {
558           startPosition: 6,
559           insertAfterPosition: 3
560         }
561       })
562
563       await waitJobs(servers)
564
565       for (const server of servers) {
566         const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
567         const videos: Video[] = res.body.data
568
569         const names = videos.map(v => v.name)
570
571         expect(names).to.deep.equal([
572           'video 3 server 1',
573           'video 0 server 1',
574           'video 2 server 3',
575           'NSFW video',
576           'video 1 server 3',
577           'video 4 server 1'
578         ])
579
580         for (let i = 1; i <= videos.length; i++) {
581           expect(videos[i - 1].playlistElement.position).to.equal(i)
582         }
583       }
584     }
585   })
586
587   it('Should update startTimestamp/endTimestamp of some elements', async function () {
588     this.timeout(30000)
589
590     await updateVideoPlaylistElement({
591       url: servers[0].url,
592       token: servers[0].accessToken,
593       playlistId: playlistServer1Id,
594       videoId: servers[0].videos[3].uuid,
595       elementAttrs: {
596         startTimestamp: 1
597       }
598     })
599
600     await updateVideoPlaylistElement({
601       url: servers[0].url,
602       token: servers[0].accessToken,
603       playlistId: playlistServer1Id,
604       videoId: servers[0].videos[4].uuid,
605       elementAttrs: {
606         stopTimestamp: null
607       }
608     })
609
610     await waitJobs(servers)
611
612     for (const server of servers) {
613       const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
614       const videos: Video[] = res.body.data
615
616       expect(videos[0].name).to.equal('video 3 server 1')
617       expect(videos[0].playlistElement.position).to.equal(1)
618       expect(videos[0].playlistElement.startTimestamp).to.equal(1)
619       expect(videos[0].playlistElement.stopTimestamp).to.equal(35)
620
621       expect(videos[5].name).to.equal('video 4 server 1')
622       expect(videos[5].playlistElement.position).to.equal(6)
623       expect(videos[5].playlistElement.startTimestamp).to.equal(45)
624       expect(videos[5].playlistElement.stopTimestamp).to.be.null
625     }
626   })
627
628   it('Should check videos existence in my playlist', async function () {
629     const videoIds = [
630       servers[0].videos[0].id,
631       42000,
632       servers[0].videos[3].id,
633       43000,
634       servers[0].videos[4].id
635     ]
636     const res = await doVideosExistInMyPlaylist(servers[ 0 ].url, servers[ 0 ].accessToken, videoIds)
637     const obj = res.body as VideoExistInPlaylist
638
639     {
640       const elem = obj[servers[0].videos[0].id]
641       expect(elem).to.have.lengthOf(1)
642       expect(elem[ 0 ].playlistId).to.equal(playlistServer1Id)
643       expect(elem[ 0 ].startTimestamp).to.equal(15)
644       expect(elem[ 0 ].stopTimestamp).to.equal(28)
645     }
646
647     {
648       const elem = obj[servers[0].videos[3].id]
649       expect(elem).to.have.lengthOf(1)
650       expect(elem[ 0 ].playlistId).to.equal(playlistServer1Id)
651       expect(elem[ 0 ].startTimestamp).to.equal(1)
652       expect(elem[ 0 ].stopTimestamp).to.equal(35)
653     }
654
655     {
656       const elem = obj[servers[0].videos[4].id]
657       expect(elem).to.have.lengthOf(1)
658       expect(elem[ 0 ].playlistId).to.equal(playlistServer1Id)
659       expect(elem[ 0 ].startTimestamp).to.equal(45)
660       expect(elem[ 0 ].stopTimestamp).to.equal(null)
661     }
662
663     expect(obj[42000]).to.have.lengthOf(0)
664     expect(obj[43000]).to.have.lengthOf(0)
665   })
666
667   it('Should delete some elements', async function () {
668     this.timeout(30000)
669
670     await removeVideoFromPlaylist({
671       url: servers[0].url,
672       token: servers[0].accessToken,
673       playlistId: playlistServer1Id,
674       videoId: servers[0].videos[3].uuid
675     })
676
677     await removeVideoFromPlaylist({
678       url: servers[0].url,
679       token: servers[0].accessToken,
680       playlistId: playlistServer1Id,
681       videoId: nsfwVideoServer1
682     })
683
684     await waitJobs(servers)
685
686     for (const server of servers) {
687       const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
688
689       expect(res.body.total).to.equal(4)
690
691       const videos: Video[] = res.body.data
692       expect(videos).to.have.lengthOf(4)
693
694       expect(videos[ 0 ].name).to.equal('video 0 server 1')
695       expect(videos[ 0 ].playlistElement.position).to.equal(1)
696
697       expect(videos[ 1 ].name).to.equal('video 2 server 3')
698       expect(videos[ 1 ].playlistElement.position).to.equal(2)
699
700       expect(videos[ 2 ].name).to.equal('video 1 server 3')
701       expect(videos[ 2 ].playlistElement.position).to.equal(3)
702
703       expect(videos[ 3 ].name).to.equal('video 4 server 1')
704       expect(videos[ 3 ].playlistElement.position).to.equal(4)
705     }
706   })
707
708   it('Should delete the playlist on server 1 and delete on server 2 and 3', async function () {
709     this.timeout(30000)
710
711     await deleteVideoPlaylist(servers[0].url, servers[0].accessToken, playlistServer1Id)
712
713     await waitJobs(servers)
714
715     for (const server of servers) {
716       await getVideoPlaylist(server.url, playlistServer1UUID, 404)
717     }
718   })
719
720   it('Should have deleted the thumbnail on server 1, 2 and 3', async function () {
721     this.timeout(30000)
722
723     for (const server of servers) {
724       await checkPlaylistFilesWereRemoved(playlistServer1UUID, server.serverNumber)
725     }
726   })
727
728   it('Should unfollow servers 1 and 2 and hide their playlists', async function () {
729     this.timeout(30000)
730
731     const finder = data => data.find(p => p.displayName === 'my super playlist')
732
733     {
734       const res = await getVideoPlaylistsList(servers[ 2 ].url, 0, 5)
735       expect(res.body.total).to.equal(2)
736       expect(finder(res.body.data)).to.not.be.undefined
737     }
738
739     await unfollow(servers[2].url, servers[2].accessToken, servers[0])
740
741     {
742       const res = await getVideoPlaylistsList(servers[ 2 ].url, 0, 5)
743       expect(res.body.total).to.equal(1)
744
745       expect(finder(res.body.data)).to.be.undefined
746     }
747   })
748
749   it('Should delete a channel and put the associated playlist in private mode', async function () {
750     this.timeout(30000)
751
752     const res = await addVideoChannel(servers[0].url, servers[0].accessToken, { name: 'super_channel', displayName: 'super channel' })
753     const videoChannelId = res.body.videoChannel.id
754
755     const res2 = await createVideoPlaylist({
756       url: servers[0].url,
757       token: servers[0].accessToken,
758       playlistAttrs: {
759         displayName: 'channel playlist',
760         privacy: VideoPlaylistPrivacy.PUBLIC,
761         videoChannelId
762       }
763     })
764     const videoPlaylistUUID = res2.body.videoPlaylist.uuid
765
766     await waitJobs(servers)
767
768     await deleteVideoChannel(servers[0].url, servers[0].accessToken, 'super_channel')
769
770     await waitJobs(servers)
771
772     const res3 = await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistUUID)
773     expect(res3.body.displayName).to.equal('channel playlist')
774     expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
775
776     await getVideoPlaylist(servers[1].url, videoPlaylistUUID, 404)
777   })
778
779   it('Should delete an account and delete its playlists', async function () {
780     this.timeout(30000)
781
782     const user = { username: 'user_1', password: 'password' }
783     const res = await createUser(servers[0].url, servers[0].accessToken, user.username, user.password)
784
785     const userId = res.body.user.id
786     const userAccessToken = await userLogin(servers[0], user)
787
788     await createVideoPlaylist({
789       url: servers[0].url,
790       token: userAccessToken,
791       playlistAttrs: {
792         displayName: 'playlist to be deleted',
793         privacy: VideoPlaylistPrivacy.PUBLIC
794       }
795     })
796
797     await waitJobs(servers)
798
799     const finder = data => data.find(p => p.displayName === 'playlist to be deleted')
800
801     {
802       for (const server of [ servers[0], servers[1] ]) {
803         const res = await getVideoPlaylistsList(server.url, 0, 15)
804         expect(finder(res.body.data)).to.not.be.undefined
805       }
806     }
807
808     await removeUser(servers[0].url, userId, servers[0].accessToken)
809     await waitJobs(servers)
810
811     {
812       for (const server of [ servers[0], servers[1] ]) {
813         const res = await getVideoPlaylistsList(server.url, 0, 15)
814         expect(finder(res.body.data)).to.be.undefined
815       }
816     }
817   })
818
819   after(async function () {
820     killallServers(servers)
821
822     // Keep the logs if the test failed
823     if (this['ok']) {
824       await flushTests()
825     }
826   })
827 })