]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/videos/video-playlists.ts
Introduce config command
[github/Chocobozzz/PeerTube.git] / server / tests / api / videos / video-playlists.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
418d092a 2
418d092a 3import 'mocha'
59fd824c 4import * as chai from 'chai'
c3d29f69 5import { HttpStatusCode } from '@shared/core-utils'
418d092a 6import {
c3d29f69
C
7 addAccountToAccountBlocklist,
8 addAccountToServerBlocklist,
9 addServerToAccountBlocklist,
10 addServerToServerBlocklist,
418d092a 11 addVideoChannel,
df0b219d 12 addVideoInPlaylist,
bfbd9128 13 addVideoToBlacklist,
8519cc92
C
14 checkPlaylistFilesWereRemoved,
15 cleanupTests,
418d092a 16 createUser,
df0b219d
C
17 createVideoPlaylist,
18 deleteVideoChannel,
19 deleteVideoPlaylist,
8519cc92
C
20 doubleFollow,
21 doVideosExistInMyPlaylist,
418d092a 22 flushAndRunMultipleServers,
bfbd9128
C
23 generateUserAccessToken,
24 getAccessToken,
df0b219d 25 getAccountPlaylistsList,
8519cc92
C
26 getAccountPlaylistsListWithToken,
27 getMyUserInformation,
df0b219d
C
28 getPlaylistVideos,
29 getVideoChannelPlaylistsList,
30 getVideoPlaylist,
d4c9f45b 31 getVideoPlaylistPrivacies,
df0b219d
C
32 getVideoPlaylistsList,
33 getVideoPlaylistWithToken,
c3d29f69
C
34 removeAccountFromAccountBlocklist,
35 removeAccountFromServerBlocklist,
36 removeServerFromAccountBlocklist,
37 removeServerFromServerBlocklist,
df0b219d 38 removeUser,
bfbd9128 39 removeVideoFromBlacklist,
df0b219d
C
40 removeVideoFromPlaylist,
41 reorderVideosPlaylist,
418d092a
C
42 ServerInfo,
43 setAccessTokensToServers,
df0b219d 44 setDefaultVideoChannel,
418d092a 45 testImage,
bfbd9128 46 updateVideo,
df0b219d
C
47 updateVideoPlaylist,
48 updateVideoPlaylistElement,
418d092a 49 uploadVideo,
df0b219d 50 uploadVideoAndGetId,
418d092a 51 userLogin,
7f88a58e 52 wait,
bfbd9128 53 waitJobs
c3d29f69 54} from '@shared/extra-utils'
bfbd9128 55import {
c3d29f69
C
56 User,
57 VideoExistInPlaylist,
58 VideoPlaylist,
59 VideoPlaylistCreateResult,
60 VideoPlaylistElement,
61 VideoPlaylistElementType,
62 VideoPlaylistPrivacy,
63 VideoPlaylistType,
64 VideoPrivacy
65} from '@shared/models'
418d092a
C
66
67const expect = chai.expect
68
bfbd9128
C
69async function checkPlaylistElementType (
70 servers: ServerInfo[],
71 playlistId: string,
72 type: VideoPlaylistElementType,
73 position: number,
74 name: string,
75 total: number
76) {
77 for (const server of servers) {
78 const res = await getPlaylistVideos(server.url, server.accessToken, playlistId, 0, 10)
79 expect(res.body.total).to.equal(total)
80
81 const videoElement: VideoPlaylistElement = res.body.data.find((e: VideoPlaylistElement) => e.position === position)
82 expect(videoElement.type).to.equal(type, 'On server ' + server.url)
83
84 if (type === VideoPlaylistElementType.REGULAR) {
85 expect(videoElement.video).to.not.be.null
86 expect(videoElement.video.name).to.equal(name)
87 } else {
88 expect(videoElement.video).to.be.null
89 }
90 }
91}
92
418d092a
C
93describe('Test video playlists', function () {
94 let servers: ServerInfo[] = []
95
df0b219d
C
96 let playlistServer2Id1: number
97 let playlistServer2Id2: number
98 let playlistServer2UUID2: number
99
100 let playlistServer1Id: number
101 let playlistServer1UUID: string
bfbd9128
C
102 let playlistServer1UUID2: string
103
104 let playlistElementServer1Video4: number
105 let playlistElementServer1Video5: number
106 let playlistElementNSFW: number
df0b219d
C
107
108 let nsfwVideoServer1: number
109
bfbd9128
C
110 let userAccessTokenServer1: string
111
418d092a
C
112 before(async function () {
113 this.timeout(120000)
114
df0b219d 115 servers = await flushAndRunMultipleServers(3, { transcoding: { enabled: false } })
418d092a
C
116
117 // Get the access tokens
118 await setAccessTokensToServers(servers)
df0b219d 119 await setDefaultVideoChannel(servers)
418d092a
C
120
121 // Server 1 and server 2 follow each other
122 await doubleFollow(servers[0], servers[1])
123 // Server 1 and server 3 follow each other
124 await doubleFollow(servers[0], servers[2])
df0b219d
C
125
126 {
59fd824c
C
127 servers[0].videos = []
128 servers[1].videos = []
129 servers[2].videos = []
df0b219d
C
130
131 for (const server of servers) {
df0b219d 132 for (let i = 0; i < 7; i++) {
59fd824c
C
133 const name = `video ${i} server ${server.serverNumber}`
134 const resVideo = await uploadVideo(server.url, server.accessToken, { name, nsfw: false })
df0b219d 135
59fd824c
C
136 server.videos.push(resVideo.body.video)
137 }
df0b219d 138 }
df0b219d
C
139 }
140
a1587156 141 nsfwVideoServer1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'NSFW video', nsfw: true })).id
df0b219d 142
bfbd9128
C
143 {
144 await createUser({
a1587156
C
145 url: servers[0].url,
146 accessToken: servers[0].accessToken,
bfbd9128
C
147 username: 'user1',
148 password: 'password'
149 })
150 userAccessTokenServer1 = await getAccessToken(servers[0].url, 'user1', 'password')
151 }
152
df0b219d 153 await waitJobs(servers)
418d092a
C
154 })
155
bfbd9128
C
156 describe('Get default playlists', function () {
157 it('Should list video playlist privacies', async function () {
a1587156 158 const res = await getVideoPlaylistPrivacies(servers[0].url)
d4c9f45b 159
bfbd9128
C
160 const privacies = res.body
161 expect(Object.keys(privacies)).to.have.length.at.least(3)
d4c9f45b 162
a1587156 163 expect(privacies[3]).to.equal('Private')
bfbd9128 164 })
d4c9f45b 165
bfbd9128 166 it('Should list watch later playlist', async function () {
a1587156
C
167 const url = servers[0].url
168 const accessToken = servers[0].accessToken
df0b219d 169
bfbd9128
C
170 {
171 const res = await getAccountPlaylistsListWithToken(url, accessToken, 'root', 0, 5, VideoPlaylistType.WATCH_LATER)
172
173 expect(res.body.total).to.equal(1)
174 expect(res.body.data).to.have.lengthOf(1)
175
a1587156 176 const playlist: VideoPlaylist = res.body.data[0]
bfbd9128
C
177 expect(playlist.displayName).to.equal('Watch later')
178 expect(playlist.type.id).to.equal(VideoPlaylistType.WATCH_LATER)
179 expect(playlist.type.label).to.equal('Watch later')
180 }
181
182 {
183 const res = await getAccountPlaylistsListWithToken(url, accessToken, 'root', 0, 5, VideoPlaylistType.REGULAR)
184
185 expect(res.body.total).to.equal(0)
186 expect(res.body.data).to.have.lengthOf(0)
187 }
188
189 {
190 const res = await getAccountPlaylistsList(url, 'root', 0, 5)
191 expect(res.body.total).to.equal(0)
192 expect(res.body.data).to.have.lengthOf(0)
193 }
194 })
195
196 it('Should get private playlist for a classic user', async function () {
a1587156 197 const token = await generateUserAccessToken(servers[0], 'toto')
bfbd9128 198
a1587156 199 const res = await getAccountPlaylistsListWithToken(servers[0].url, token, 'toto', 0, 5)
df0b219d
C
200
201 expect(res.body.total).to.equal(1)
202 expect(res.body.data).to.have.lengthOf(1)
418d092a 203
a1587156
C
204 const playlistId = res.body.data[0].id
205 await getPlaylistVideos(servers[0].url, token, playlistId, 0, 5)
bfbd9128
C
206 })
207 })
df0b219d 208
bfbd9128 209 describe('Create and federate playlists', function () {
df0b219d 210
bfbd9128
C
211 it('Should create a playlist on server 1 and have the playlist on server 2 and 3', async function () {
212 this.timeout(30000)
df0b219d 213
bfbd9128 214 await createVideoPlaylist({
a1587156
C
215 url: servers[0].url,
216 token: servers[0].accessToken,
bfbd9128
C
217 playlistAttrs: {
218 displayName: 'my super playlist',
219 privacy: VideoPlaylistPrivacy.PUBLIC,
220 description: 'my super description',
221 thumbnailfile: 'thumbnail.jpg',
a1587156 222 videoChannelId: servers[0].videoChannel.id
bfbd9128
C
223 }
224 })
225
226 await waitJobs(servers)
7f88a58e
C
227 // Processing a playlist by the receiver could be long
228 await wait(3000)
bfbd9128
C
229
230 for (const server of servers) {
231 const res = await getVideoPlaylistsList(server.url, 0, 5)
232 expect(res.body.total).to.equal(1)
233 expect(res.body.data).to.have.lengthOf(1)
234
a1587156 235 const playlistFromList = res.body.data[0] as VideoPlaylist
bfbd9128
C
236
237 const res2 = await getVideoPlaylist(server.url, playlistFromList.uuid)
951b582f 238 const playlistFromGet = res2.body as VideoPlaylist
bfbd9128
C
239
240 for (const playlist of [ playlistFromGet, playlistFromList ]) {
241 expect(playlist.id).to.be.a('number')
242 expect(playlist.uuid).to.be.a('string')
243
244 expect(playlist.isLocal).to.equal(server.serverNumber === 1)
245
246 expect(playlist.displayName).to.equal('my super playlist')
247 expect(playlist.description).to.equal('my super description')
248 expect(playlist.privacy.id).to.equal(VideoPlaylistPrivacy.PUBLIC)
249 expect(playlist.privacy.label).to.equal('Public')
250 expect(playlist.type.id).to.equal(VideoPlaylistType.REGULAR)
251 expect(playlist.type.label).to.equal('Regular')
951b582f 252 expect(playlist.embedPath).to.equal('/video-playlists/embed/' + playlist.uuid)
bfbd9128
C
253
254 expect(playlist.videosLength).to.equal(0)
df0b219d 255
bfbd9128
C
256 expect(playlist.ownerAccount.name).to.equal('root')
257 expect(playlist.ownerAccount.displayName).to.equal('root')
258 expect(playlist.videoChannel.name).to.equal('root_channel')
259 expect(playlist.videoChannel.displayName).to.equal('Main root channel')
260 }
261 }
262 })
4d09cfba 263
bfbd9128
C
264 it('Should create a playlist on server 2 and have the playlist on server 1 but not on server 3', async function () {
265 this.timeout(30000)
266
267 {
268 const res = await createVideoPlaylist({
a1587156
C
269 url: servers[1].url,
270 token: servers[1].accessToken,
bfbd9128
C
271 playlistAttrs: {
272 displayName: 'playlist 2',
273 privacy: VideoPlaylistPrivacy.PUBLIC,
a1587156 274 videoChannelId: servers[1].videoChannel.id
bfbd9128
C
275 }
276 })
277 playlistServer2Id1 = res.body.videoPlaylist.id
278 }
4d09cfba 279
bfbd9128
C
280 {
281 const res = await createVideoPlaylist({
a1587156
C
282 url: servers[1].url,
283 token: servers[1].accessToken,
bfbd9128
C
284 playlistAttrs: {
285 displayName: 'playlist 3',
286 privacy: VideoPlaylistPrivacy.PUBLIC,
287 thumbnailfile: 'thumbnail.jpg',
a1587156 288 videoChannelId: servers[1].videoChannel.id
bfbd9128
C
289 }
290 })
291
292 playlistServer2Id2 = res.body.videoPlaylist.id
293 playlistServer2UUID2 = res.body.videoPlaylist.uuid
294 }
295
a1587156 296 for (const id of [ playlistServer2Id1, playlistServer2Id2 ]) {
bfbd9128 297 await addVideoInPlaylist({
a1587156
C
298 url: servers[1].url,
299 token: servers[1].accessToken,
bfbd9128 300 playlistId: id,
a1587156 301 elementAttrs: { videoId: servers[1].videos[0].id, startTimestamp: 1, stopTimestamp: 2 }
bfbd9128
C
302 })
303 await addVideoInPlaylist({
a1587156
C
304 url: servers[1].url,
305 token: servers[1].accessToken,
bfbd9128 306 playlistId: id,
a1587156 307 elementAttrs: { videoId: servers[1].videos[1].id }
bfbd9128
C
308 })
309 }
310
311 await waitJobs(servers)
7f88a58e 312 await wait(3000)
bfbd9128 313
a1587156 314 for (const server of [ servers[0], servers[1] ]) {
bfbd9128
C
315 const res = await getVideoPlaylistsList(server.url, 0, 5)
316
317 const playlist2 = res.body.data.find(p => p.displayName === 'playlist 2')
318 expect(playlist2).to.not.be.undefined
319 await testImage(server.url, 'thumbnail-playlist', playlist2.thumbnailPath)
320
321 const playlist3 = res.body.data.find(p => p.displayName === 'playlist 3')
322 expect(playlist3).to.not.be.undefined
323 await testImage(server.url, 'thumbnail', playlist3.thumbnailPath)
324 }
4d09cfba 325
a1587156 326 const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
bfbd9128
C
327 expect(res.body.data.find(p => p.displayName === 'playlist 2')).to.be.undefined
328 expect(res.body.data.find(p => p.displayName === 'playlist 3')).to.be.undefined
329 })
330
331 it('Should have the playlist on server 3 after a new follow', async function () {
332 this.timeout(30000)
333
334 // Server 2 and server 3 follow each other
a1587156 335 await doubleFollow(servers[1], servers[2])
bfbd9128 336
a1587156 337 const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
bfbd9128
C
338
339 const playlist2 = res.body.data.find(p => p.displayName === 'playlist 2')
340 expect(playlist2).to.not.be.undefined
a1587156 341 await testImage(servers[2].url, 'thumbnail-playlist', playlist2.thumbnailPath)
bfbd9128
C
342
343 expect(res.body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined
344 })
4d09cfba
C
345 })
346
bfbd9128 347 describe('List playlists', function () {
65af03a2 348
bfbd9128
C
349 it('Should correctly list the playlists', async function () {
350 this.timeout(30000)
351
352 {
a1587156 353 const res = await getVideoPlaylistsList(servers[2].url, 1, 2, 'createdAt')
df0b219d 354
bfbd9128
C
355 expect(res.body.total).to.equal(3)
356
357 const data: VideoPlaylist[] = res.body.data
358 expect(data).to.have.lengthOf(2)
a1587156
C
359 expect(data[0].displayName).to.equal('playlist 2')
360 expect(data[1].displayName).to.equal('playlist 3')
bfbd9128
C
361 }
362
363 {
a1587156 364 const res = await getVideoPlaylistsList(servers[2].url, 1, 2, '-createdAt')
bfbd9128
C
365
366 expect(res.body.total).to.equal(3)
367
368 const data: VideoPlaylist[] = res.body.data
369 expect(data).to.have.lengthOf(2)
a1587156
C
370 expect(data[0].displayName).to.equal('playlist 2')
371 expect(data[1].displayName).to.equal('my super playlist')
df0b219d
C
372 }
373 })
374
bfbd9128
C
375 it('Should list video channel playlists', async function () {
376 this.timeout(30000)
df0b219d 377
bfbd9128 378 {
a1587156 379 const res = await getVideoChannelPlaylistsList(servers[0].url, 'root_channel', 0, 2, '-createdAt')
df0b219d 380
bfbd9128 381 expect(res.body.total).to.equal(1)
df0b219d 382
bfbd9128
C
383 const data: VideoPlaylist[] = res.body.data
384 expect(data).to.have.lengthOf(1)
a1587156 385 expect(data[0].displayName).to.equal('my super playlist')
bfbd9128
C
386 }
387 })
df0b219d 388
bfbd9128
C
389 it('Should list account playlists', async function () {
390 this.timeout(30000)
df0b219d 391
bfbd9128 392 {
a1587156 393 const res = await getAccountPlaylistsList(servers[1].url, 'root', 1, 2, '-createdAt')
df0b219d 394
bfbd9128
C
395 expect(res.body.total).to.equal(2)
396
397 const data: VideoPlaylist[] = res.body.data
398 expect(data).to.have.lengthOf(1)
a1587156 399 expect(data[0].displayName).to.equal('playlist 2')
bfbd9128 400 }
df0b219d 401
bfbd9128 402 {
a1587156 403 const res = await getAccountPlaylistsList(servers[1].url, 'root', 1, 2, 'createdAt')
df0b219d 404
bfbd9128
C
405 expect(res.body.total).to.equal(2)
406
407 const data: VideoPlaylist[] = res.body.data
408 expect(data).to.have.lengthOf(1)
a1587156 409 expect(data[0].displayName).to.equal('playlist 3')
df0b219d 410 }
822c7e61
C
411
412 {
a1587156 413 const res = await getAccountPlaylistsList(servers[1].url, 'root', 0, 10, 'createdAt', '3')
822c7e61
C
414
415 expect(res.body.total).to.equal(1)
416
417 const data: VideoPlaylist[] = res.body.data
418 expect(data).to.have.lengthOf(1)
a1587156 419 expect(data[0].displayName).to.equal('playlist 3')
822c7e61
C
420 }
421
422 {
a1587156 423 const res = await getAccountPlaylistsList(servers[1].url, 'root', 0, 10, 'createdAt', '4')
822c7e61
C
424
425 expect(res.body.total).to.equal(0)
426
427 const data: VideoPlaylist[] = res.body.data
428 expect(data).to.have.lengthOf(0)
429 }
bfbd9128 430 })
d4a8e7a6 431 })
418d092a 432
d4a8e7a6
C
433 describe('Playlist rights', function () {
434 let unlistedPlaylist: VideoPlaylistCreateResult
435 let privatePlaylist: VideoPlaylistCreateResult
436
437 before(async function () {
bfbd9128 438 this.timeout(30000)
df0b219d 439
d4a8e7a6
C
440 {
441 const res = await createVideoPlaylist({
442 url: servers[1].url,
443 token: servers[1].accessToken,
444 playlistAttrs: {
445 displayName: 'playlist unlisted',
446 privacy: VideoPlaylistPrivacy.UNLISTED,
447 videoChannelId: servers[1].videoChannel.id
448 }
449 })
450 unlistedPlaylist = res.body.videoPlaylist
451 }
df0b219d 452
d4a8e7a6
C
453 {
454 const res = await createVideoPlaylist({
455 url: servers[1].url,
456 token: servers[1].accessToken,
457 playlistAttrs: {
458 displayName: 'playlist private',
459 privacy: VideoPlaylistPrivacy.PRIVATE
460 }
461 })
462 privatePlaylist = res.body.videoPlaylist
463 }
df0b219d 464
bfbd9128 465 await waitJobs(servers)
7f88a58e 466 await wait(3000)
d4a8e7a6 467 })
df0b219d 468
d4a8e7a6 469 it('Should not list unlisted or private playlists', async function () {
bfbd9128
C
470 for (const server of servers) {
471 const results = [
a1587156 472 await getAccountPlaylistsList(server.url, 'root@localhost:' + servers[1].port, 0, 5, '-createdAt'),
bfbd9128
C
473 await getVideoPlaylistsList(server.url, 0, 2, '-createdAt')
474 ]
475
a1587156
C
476 expect(results[0].body.total).to.equal(2)
477 expect(results[1].body.total).to.equal(3)
bfbd9128
C
478
479 for (const res of results) {
480 const data: VideoPlaylist[] = res.body.data
481 expect(data).to.have.lengthOf(2)
a1587156
C
482 expect(data[0].displayName).to.equal('playlist 3')
483 expect(data[1].displayName).to.equal('playlist 2')
bfbd9128
C
484 }
485 }
486 })
d4a8e7a6
C
487
488 it('Should not get unlisted playlist using only the id', async function () {
489 await getVideoPlaylist(servers[1].url, unlistedPlaylist.id, 404)
490 })
491
492 it('Should get unlisted plyaylist using uuid or shortUUID', async function () {
493 await getVideoPlaylist(servers[1].url, unlistedPlaylist.uuid)
494 await getVideoPlaylist(servers[1].url, unlistedPlaylist.shortUUID)
495 })
496
497 it('Should not get private playlist without token', async function () {
498 for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) {
499 await getVideoPlaylist(servers[1].url, id, 401)
500 }
501 })
502
503 it('Should get private playlist with a token', async function () {
504 for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) {
505 await getVideoPlaylistWithToken(servers[1].url, servers[1].accessToken, id)
506 }
507 })
bfbd9128 508 })
df0b219d 509
bfbd9128 510 describe('Update playlists', function () {
df0b219d 511
bfbd9128
C
512 it('Should update a playlist', async function () {
513 this.timeout(30000)
df0b219d 514
bfbd9128
C
515 await updateVideoPlaylist({
516 url: servers[1].url,
517 token: servers[1].accessToken,
518 playlistAttrs: {
519 displayName: 'playlist 3 updated',
520 description: 'description updated',
521 privacy: VideoPlaylistPrivacy.UNLISTED,
522 thumbnailfile: 'thumbnail.jpg',
523 videoChannelId: servers[1].videoChannel.id
524 },
525 playlistId: playlistServer2Id2
526 })
df0b219d 527
bfbd9128 528 await waitJobs(servers)
df0b219d 529
bfbd9128
C
530 for (const server of servers) {
531 const res = await getVideoPlaylist(server.url, playlistServer2UUID2)
532 const playlist: VideoPlaylist = res.body
418d092a 533
bfbd9128
C
534 expect(playlist.displayName).to.equal('playlist 3 updated')
535 expect(playlist.description).to.equal('description updated')
df0b219d 536
bfbd9128
C
537 expect(playlist.privacy.id).to.equal(VideoPlaylistPrivacy.UNLISTED)
538 expect(playlist.privacy.label).to.equal('Unlisted')
df0b219d 539
bfbd9128
C
540 expect(playlist.type.id).to.equal(VideoPlaylistType.REGULAR)
541 expect(playlist.type.label).to.equal('Regular')
df0b219d 542
bfbd9128 543 expect(playlist.videosLength).to.equal(2)
df0b219d 544
bfbd9128
C
545 expect(playlist.ownerAccount.name).to.equal('root')
546 expect(playlist.ownerAccount.displayName).to.equal('root')
547 expect(playlist.videoChannel.name).to.equal('root_channel')
548 expect(playlist.videoChannel.displayName).to.equal('Main root channel')
549 }
550 })
418d092a
C
551 })
552
bfbd9128 553 describe('Element timestamps', function () {
df0b219d 554
bfbd9128
C
555 it('Should create a playlist containing different startTimestamp/endTimestamp videos', async function () {
556 this.timeout(30000)
df0b219d 557
bfbd9128 558 const addVideo = (elementAttrs: any) => {
a1587156 559 return addVideoInPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistId: playlistServer1Id, elementAttrs })
bfbd9128 560 }
df0b219d 561
bfbd9128 562 const res = await createVideoPlaylist({
a1587156
C
563 url: servers[0].url,
564 token: servers[0].accessToken,
bfbd9128
C
565 playlistAttrs: {
566 displayName: 'playlist 4',
567 privacy: VideoPlaylistPrivacy.PUBLIC,
a1587156 568 videoChannelId: servers[0].videoChannel.id
bfbd9128
C
569 }
570 })
df0b219d 571
bfbd9128
C
572 playlistServer1Id = res.body.videoPlaylist.id
573 playlistServer1UUID = res.body.videoPlaylist.uuid
df0b219d 574
a1587156
C
575 await addVideo({ videoId: servers[0].videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 })
576 await addVideo({ videoId: servers[2].videos[1].uuid, startTimestamp: 35 })
577 await addVideo({ videoId: servers[2].videos[2].uuid })
bfbd9128 578 {
a1587156 579 const res = await addVideo({ videoId: servers[0].videos[3].uuid, stopTimestamp: 35 })
bfbd9128
C
580 playlistElementServer1Video4 = res.body.videoPlaylistElement.id
581 }
df0b219d 582
bfbd9128 583 {
a1587156 584 const res = await addVideo({ videoId: servers[0].videos[4].uuid, startTimestamp: 45, stopTimestamp: 60 })
bfbd9128
C
585 playlistElementServer1Video5 = res.body.videoPlaylistElement.id
586 }
418d092a 587
bfbd9128
C
588 {
589 const res = await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 })
590 playlistElementNSFW = res.body.videoPlaylistElement.id
37190663
C
591
592 await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 4 })
593 await addVideo({ videoId: nsfwVideoServer1 })
bfbd9128 594 }
df0b219d 595
bfbd9128
C
596 await waitJobs(servers)
597 })
df0b219d 598
bfbd9128
C
599 it('Should correctly list playlist videos', async function () {
600 this.timeout(30000)
df0b219d 601
bfbd9128
C
602 for (const server of servers) {
603 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
418d092a 604
37190663 605 expect(res.body.total).to.equal(8)
df0b219d 606
bfbd9128 607 const videoElements: VideoPlaylistElement[] = res.body.data
37190663 608 expect(videoElements).to.have.lengthOf(8)
df0b219d 609
a1587156
C
610 expect(videoElements[0].video.name).to.equal('video 0 server 1')
611 expect(videoElements[0].position).to.equal(1)
612 expect(videoElements[0].startTimestamp).to.equal(15)
613 expect(videoElements[0].stopTimestamp).to.equal(28)
df0b219d 614
a1587156
C
615 expect(videoElements[1].video.name).to.equal('video 1 server 3')
616 expect(videoElements[1].position).to.equal(2)
617 expect(videoElements[1].startTimestamp).to.equal(35)
618 expect(videoElements[1].stopTimestamp).to.be.null
df0b219d 619
a1587156
C
620 expect(videoElements[2].video.name).to.equal('video 2 server 3')
621 expect(videoElements[2].position).to.equal(3)
622 expect(videoElements[2].startTimestamp).to.be.null
623 expect(videoElements[2].stopTimestamp).to.be.null
df0b219d 624
a1587156
C
625 expect(videoElements[3].video.name).to.equal('video 3 server 1')
626 expect(videoElements[3].position).to.equal(4)
627 expect(videoElements[3].startTimestamp).to.be.null
628 expect(videoElements[3].stopTimestamp).to.equal(35)
df0b219d 629
a1587156
C
630 expect(videoElements[4].video.name).to.equal('video 4 server 1')
631 expect(videoElements[4].position).to.equal(5)
632 expect(videoElements[4].startTimestamp).to.equal(45)
633 expect(videoElements[4].stopTimestamp).to.equal(60)
418d092a 634
a1587156
C
635 expect(videoElements[5].video.name).to.equal('NSFW video')
636 expect(videoElements[5].position).to.equal(6)
637 expect(videoElements[5].startTimestamp).to.equal(5)
638 expect(videoElements[5].stopTimestamp).to.be.null
df0b219d 639
37190663
C
640 expect(videoElements[6].video.name).to.equal('NSFW video')
641 expect(videoElements[6].position).to.equal(7)
642 expect(videoElements[6].startTimestamp).to.equal(4)
643 expect(videoElements[6].stopTimestamp).to.be.null
644
645 expect(videoElements[7].video.name).to.equal('NSFW video')
646 expect(videoElements[7].position).to.equal(8)
647 expect(videoElements[7].startTimestamp).to.be.null
648 expect(videoElements[7].stopTimestamp).to.be.null
649
bfbd9128
C
650 const res3 = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 2)
651 expect(res3.body.data).to.have.lengthOf(2)
df0b219d
C
652 }
653 })
bfbd9128 654 })
df0b219d 655
bfbd9128
C
656 describe('Element type', function () {
657 let groupUser1: ServerInfo[]
658 let groupWithoutToken1: ServerInfo[]
659 let group1: ServerInfo[]
660 let group2: ServerInfo[]
df0b219d 661
bfbd9128
C
662 let video1: string
663 let video2: string
664 let video3: string
df0b219d 665
bfbd9128 666 before(async function () {
19149d45 667 this.timeout(60000)
df0b219d 668
a1587156
C
669 groupUser1 = [ Object.assign({}, servers[0], { accessToken: userAccessTokenServer1 }) ]
670 groupWithoutToken1 = [ Object.assign({}, servers[0], { accessToken: undefined }) ]
671 group1 = [ servers[0] ]
672 group2 = [ servers[1], servers[2] ]
df0b219d 673
bfbd9128 674 const res = await createVideoPlaylist({
a1587156 675 url: servers[0].url,
bfbd9128
C
676 token: userAccessTokenServer1,
677 playlistAttrs: {
678 displayName: 'playlist 56',
679 privacy: VideoPlaylistPrivacy.PUBLIC,
a1587156 680 videoChannelId: servers[0].videoChannel.id
bfbd9128
C
681 }
682 })
418d092a 683
bfbd9128
C
684 const playlistServer1Id2 = res.body.videoPlaylist.id
685 playlistServer1UUID2 = res.body.videoPlaylist.uuid
df0b219d 686
bfbd9128 687 const addVideo = (elementAttrs: any) => {
a1587156 688 return addVideoInPlaylist({ url: servers[0].url, token: userAccessTokenServer1, playlistId: playlistServer1Id2, elementAttrs })
bfbd9128 689 }
df0b219d 690
bfbd9128
C
691 video1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 89', token: userAccessTokenServer1 })).uuid
692 video2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 90' })).uuid
693 video3 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 91', nsfw: true })).uuid
df0b219d 694
19149d45
C
695 await waitJobs(servers)
696
bfbd9128
C
697 await addVideo({ videoId: video1, startTimestamp: 15, stopTimestamp: 28 })
698 await addVideo({ videoId: video2, startTimestamp: 35 })
699 await addVideo({ videoId: video3 })
df0b219d 700
bfbd9128
C
701 await waitJobs(servers)
702 })
df0b219d 703
bfbd9128
C
704 it('Should update the element type if the video is private', async function () {
705 this.timeout(20000)
df0b219d 706
bfbd9128
C
707 const name = 'video 89'
708 const position = 1
df0b219d 709
bfbd9128 710 {
a1587156 711 await updateVideo(servers[0].url, servers[0].accessToken, video1, { privacy: VideoPrivacy.PRIVATE })
bfbd9128 712 await waitJobs(servers)
418d092a 713
bfbd9128
C
714 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
715 await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.PRIVATE, position, name, 3)
716 await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.PRIVATE, position, name, 3)
717 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
718 }
df0b219d 719
bfbd9128 720 {
a1587156 721 await updateVideo(servers[0].url, servers[0].accessToken, video1, { privacy: VideoPrivacy.PUBLIC })
bfbd9128 722 await waitJobs(servers)
418d092a 723
bfbd9128
C
724 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
725 await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
726 await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
727 // We deleted the video, so even if we recreated it, the old entry is still deleted
728 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
df0b219d
C
729 }
730 })
731
bfbd9128
C
732 it('Should update the element type if the video is blacklisted', async function () {
733 this.timeout(20000)
df0b219d 734
bfbd9128
C
735 const name = 'video 89'
736 const position = 1
df0b219d 737
bfbd9128 738 {
a1587156 739 await addVideoToBlacklist(servers[0].url, servers[0].accessToken, video1, 'reason', true)
bfbd9128 740 await waitJobs(servers)
418d092a 741
bfbd9128
C
742 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
743 await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
744 await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
745 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
746 }
df0b219d 747
bfbd9128 748 {
a1587156 749 await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, video1)
bfbd9128 750 await waitJobs(servers)
df0b219d 751
bfbd9128
C
752 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
753 await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
754 await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
755 // We deleted the video (because unfederated), so even if we recreated it, the old entry is still deleted
756 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
757 }
758 })
df0b219d 759
bfbd9128
C
760 it('Should update the element type if the account or server of the video is blocked', async function () {
761 this.timeout(90000)
df0b219d 762
bfbd9128
C
763 const name = 'video 90'
764 const position = 2
df0b219d 765
bfbd9128 766 {
a1587156 767 await addAccountToAccountBlocklist(servers[0].url, userAccessTokenServer1, 'root@localhost:' + servers[1].port)
bfbd9128 768 await waitJobs(servers)
df0b219d 769
bfbd9128
C
770 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
771 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
df0b219d 772
a1587156 773 await removeAccountFromAccountBlocklist(servers[0].url, userAccessTokenServer1, 'root@localhost:' + servers[1].port)
bfbd9128 774 await waitJobs(servers)
df0b219d 775
bfbd9128
C
776 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
777 }
df0b219d 778
bfbd9128 779 {
a1587156 780 await addServerToAccountBlocklist(servers[0].url, userAccessTokenServer1, 'localhost:' + servers[1].port)
bfbd9128 781 await waitJobs(servers)
df0b219d 782
bfbd9128
C
783 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
784 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
df0b219d 785
a1587156 786 await removeServerFromAccountBlocklist(servers[0].url, userAccessTokenServer1, 'localhost:' + servers[1].port)
bfbd9128 787 await waitJobs(servers)
418d092a 788
bfbd9128
C
789 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
790 }
df0b219d 791
bfbd9128 792 {
a1587156 793 await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, 'root@localhost:' + servers[1].port)
bfbd9128 794 await waitJobs(servers)
df0b219d 795
bfbd9128
C
796 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
797 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
df0b219d 798
a1587156 799 await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, 'root@localhost:' + servers[1].port)
bfbd9128 800 await waitJobs(servers)
df0b219d 801
bfbd9128 802 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
df0b219d 803 }
df0b219d 804
bfbd9128 805 {
a1587156 806 await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
bfbd9128 807 await waitJobs(servers)
df0b219d 808
bfbd9128
C
809 await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
810 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
df0b219d 811
a1587156 812 await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
bfbd9128 813 await waitJobs(servers)
df0b219d 814
bfbd9128 815 await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
df0b219d 816 }
bfbd9128 817 })
df0b219d 818
bfbd9128
C
819 it('Should hide the video if it is NSFW', async function () {
820 const res = await getPlaylistVideos(servers[0].url, userAccessTokenServer1, playlistServer1UUID2, 0, 10, { nsfw: false })
821 expect(res.body.total).to.equal(3)
df0b219d 822
bfbd9128
C
823 const elements: VideoPlaylistElement[] = res.body.data
824 const element = elements.find(e => e.position === 3)
df0b219d 825
bfbd9128
C
826 expect(element).to.exist
827 expect(element.video).to.be.null
828 expect(element.type).to.equal(VideoPlaylistElementType.UNAVAILABLE)
829 })
df0b219d 830
bfbd9128 831 })
df0b219d 832
bfbd9128
C
833 describe('Managing playlist elements', function () {
834
835 it('Should reorder the playlist', async function () {
836 this.timeout(30000)
837
838 {
839 await reorderVideosPlaylist({
a1587156
C
840 url: servers[0].url,
841 token: servers[0].accessToken,
bfbd9128
C
842 playlistId: playlistServer1Id,
843 elementAttrs: {
844 startPosition: 2,
845 insertAfterPosition: 3
846 }
847 })
848
849 await waitJobs(servers)
850
851 for (const server of servers) {
852 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
853 const names = (res.body.data as VideoPlaylistElement[]).map(v => v.video.name)
854
855 expect(names).to.deep.equal([
856 'video 0 server 1',
857 'video 2 server 3',
858 'video 1 server 3',
859 'video 3 server 1',
860 'video 4 server 1',
37190663
C
861 'NSFW video',
862 'NSFW video',
bfbd9128
C
863 'NSFW video'
864 ])
df0b219d
C
865 }
866 }
df0b219d 867
bfbd9128
C
868 {
869 await reorderVideosPlaylist({
a1587156
C
870 url: servers[0].url,
871 token: servers[0].accessToken,
bfbd9128
C
872 playlistId: playlistServer1Id,
873 elementAttrs: {
874 startPosition: 1,
875 reorderLength: 3,
876 insertAfterPosition: 4
877 }
878 })
879
880 await waitJobs(servers)
881
882 for (const server of servers) {
883 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
884 const names = (res.body.data as VideoPlaylistElement[]).map(v => v.video.name)
885
886 expect(names).to.deep.equal([
887 'video 3 server 1',
888 'video 0 server 1',
889 'video 2 server 3',
890 'video 1 server 3',
891 'video 4 server 1',
37190663
C
892 'NSFW video',
893 'NSFW video',
bfbd9128
C
894 'NSFW video'
895 ])
896 }
df0b219d 897 }
df0b219d 898
bfbd9128
C
899 {
900 await reorderVideosPlaylist({
a1587156
C
901 url: servers[0].url,
902 token: servers[0].accessToken,
bfbd9128
C
903 playlistId: playlistServer1Id,
904 elementAttrs: {
905 startPosition: 6,
906 insertAfterPosition: 3
907 }
908 })
909
910 await waitJobs(servers)
911
912 for (const server of servers) {
913 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
914 const elements: VideoPlaylistElement[] = res.body.data
915 const names = elements.map(v => v.video.name)
916
917 expect(names).to.deep.equal([
918 'video 3 server 1',
919 'video 0 server 1',
920 'video 2 server 3',
921 'NSFW video',
922 'video 1 server 3',
37190663
C
923 'video 4 server 1',
924 'NSFW video',
925 'NSFW video'
bfbd9128
C
926 ])
927
928 for (let i = 1; i <= elements.length; i++) {
a1587156 929 expect(elements[i - 1].position).to.equal(i)
bfbd9128
C
930 }
931 }
df0b219d
C
932 }
933 })
934
bfbd9128
C
935 it('Should update startTimestamp/endTimestamp of some elements', async function () {
936 this.timeout(30000)
937
938 await updateVideoPlaylistElement({
a1587156
C
939 url: servers[0].url,
940 token: servers[0].accessToken,
bfbd9128
C
941 playlistId: playlistServer1Id,
942 playlistElementId: playlistElementServer1Video4,
943 elementAttrs: {
944 startTimestamp: 1
945 }
946 })
df0b219d 947
bfbd9128 948 await updateVideoPlaylistElement({
a1587156
C
949 url: servers[0].url,
950 token: servers[0].accessToken,
bfbd9128
C
951 playlistId: playlistServer1Id,
952 playlistElementId: playlistElementServer1Video5,
953 elementAttrs: {
954 stopTimestamp: null
955 }
956 })
df0b219d 957
bfbd9128 958 await waitJobs(servers)
df0b219d 959
bfbd9128
C
960 for (const server of servers) {
961 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
962 const elements: VideoPlaylistElement[] = res.body.data
418d092a 963
a1587156
C
964 expect(elements[0].video.name).to.equal('video 3 server 1')
965 expect(elements[0].position).to.equal(1)
966 expect(elements[0].startTimestamp).to.equal(1)
967 expect(elements[0].stopTimestamp).to.equal(35)
0b16f5f2 968
a1587156
C
969 expect(elements[5].video.name).to.equal('video 4 server 1')
970 expect(elements[5].position).to.equal(6)
971 expect(elements[5].startTimestamp).to.equal(45)
972 expect(elements[5].stopTimestamp).to.be.null
bfbd9128
C
973 }
974 })
0b16f5f2 975
bfbd9128
C
976 it('Should check videos existence in my playlist', async function () {
977 const videoIds = [
a1587156 978 servers[0].videos[0].id,
bfbd9128 979 42000,
a1587156 980 servers[0].videos[3].id,
bfbd9128 981 43000,
a1587156 982 servers[0].videos[4].id
bfbd9128 983 ]
a1587156 984 const res = await doVideosExistInMyPlaylist(servers[0].url, servers[0].accessToken, videoIds)
bfbd9128
C
985 const obj = res.body as VideoExistInPlaylist
986
987 {
a1587156 988 const elem = obj[servers[0].videos[0].id]
bfbd9128 989 expect(elem).to.have.lengthOf(1)
a1587156
C
990 expect(elem[0].playlistElementId).to.exist
991 expect(elem[0].playlistId).to.equal(playlistServer1Id)
992 expect(elem[0].startTimestamp).to.equal(15)
993 expect(elem[0].stopTimestamp).to.equal(28)
bfbd9128 994 }
0b16f5f2 995
bfbd9128 996 {
a1587156 997 const elem = obj[servers[0].videos[3].id]
bfbd9128 998 expect(elem).to.have.lengthOf(1)
a1587156
C
999 expect(elem[0].playlistElementId).to.equal(playlistElementServer1Video4)
1000 expect(elem[0].playlistId).to.equal(playlistServer1Id)
1001 expect(elem[0].startTimestamp).to.equal(1)
1002 expect(elem[0].stopTimestamp).to.equal(35)
bfbd9128 1003 }
0b16f5f2 1004
bfbd9128 1005 {
a1587156 1006 const elem = obj[servers[0].videos[4].id]
bfbd9128 1007 expect(elem).to.have.lengthOf(1)
a1587156
C
1008 expect(elem[0].playlistId).to.equal(playlistServer1Id)
1009 expect(elem[0].startTimestamp).to.equal(45)
1010 expect(elem[0].stopTimestamp).to.equal(null)
bfbd9128 1011 }
0b16f5f2 1012
a1587156
C
1013 expect(obj[42000]).to.have.lengthOf(0)
1014 expect(obj[43000]).to.have.lengthOf(0)
bfbd9128 1015 })
2a10aab3 1016
bfbd9128 1017 it('Should automatically update updatedAt field of playlists', async function () {
a1587156
C
1018 const server = servers[1]
1019 const videoId = servers[1].videos[5].id
2a10aab3 1020
bfbd9128
C
1021 async function getPlaylistNames () {
1022 const res = await getAccountPlaylistsListWithToken(server.url, server.accessToken, 'root', 0, 5, undefined, '-updatedAt')
2a10aab3 1023
bfbd9128
C
1024 return (res.body.data as VideoPlaylist[]).map(p => p.displayName)
1025 }
2a10aab3 1026
bfbd9128
C
1027 const elementAttrs = { videoId }
1028 const res1 = await addVideoInPlaylist({ url: server.url, token: server.accessToken, playlistId: playlistServer2Id1, elementAttrs })
1029 const res2 = await addVideoInPlaylist({ url: server.url, token: server.accessToken, playlistId: playlistServer2Id2, elementAttrs })
2a10aab3 1030
bfbd9128
C
1031 const element1 = res1.body.videoPlaylistElement.id
1032 const element2 = res2.body.videoPlaylistElement.id
2a10aab3 1033
bfbd9128 1034 const names1 = await getPlaylistNames()
a1587156
C
1035 expect(names1[0]).to.equal('playlist 3 updated')
1036 expect(names1[1]).to.equal('playlist 2')
2a10aab3 1037
bfbd9128
C
1038 await removeVideoFromPlaylist({
1039 url: server.url,
1040 token: server.accessToken,
1041 playlistId: playlistServer2Id1,
1042 playlistElementId: element1
1043 })
2a10aab3 1044
bfbd9128 1045 const names2 = await getPlaylistNames()
a1587156
C
1046 expect(names2[0]).to.equal('playlist 2')
1047 expect(names2[1]).to.equal('playlist 3 updated')
2a10aab3 1048
bfbd9128
C
1049 await removeVideoFromPlaylist({
1050 url: server.url,
1051 token: server.accessToken,
1052 playlistId: playlistServer2Id2,
1053 playlistElementId: element2
1054 })
df0b219d 1055
bfbd9128 1056 const names3 = await getPlaylistNames()
a1587156
C
1057 expect(names3[0]).to.equal('playlist 3 updated')
1058 expect(names3[1]).to.equal('playlist 2')
df0b219d
C
1059 })
1060
bfbd9128
C
1061 it('Should delete some elements', async function () {
1062 this.timeout(30000)
df0b219d 1063
bfbd9128 1064 await removeVideoFromPlaylist({
a1587156
C
1065 url: servers[0].url,
1066 token: servers[0].accessToken,
bfbd9128
C
1067 playlistId: playlistServer1Id,
1068 playlistElementId: playlistElementServer1Video4
1069 })
df0b219d 1070
bfbd9128 1071 await removeVideoFromPlaylist({
a1587156
C
1072 url: servers[0].url,
1073 token: servers[0].accessToken,
bfbd9128
C
1074 playlistId: playlistServer1Id,
1075 playlistElementId: playlistElementNSFW
1076 })
df0b219d 1077
bfbd9128 1078 await waitJobs(servers)
df0b219d 1079
bfbd9128
C
1080 for (const server of servers) {
1081 const res = await getPlaylistVideos(server.url, server.accessToken, playlistServer1UUID, 0, 10)
418d092a 1082
37190663 1083 expect(res.body.total).to.equal(6)
df0b219d 1084
bfbd9128 1085 const elements: VideoPlaylistElement[] = res.body.data
37190663 1086 expect(elements).to.have.lengthOf(6)
df0b219d 1087
a1587156
C
1088 expect(elements[0].video.name).to.equal('video 0 server 1')
1089 expect(elements[0].position).to.equal(1)
df0b219d 1090
a1587156
C
1091 expect(elements[1].video.name).to.equal('video 2 server 3')
1092 expect(elements[1].position).to.equal(2)
418d092a 1093
a1587156
C
1094 expect(elements[2].video.name).to.equal('video 1 server 3')
1095 expect(elements[2].position).to.equal(3)
1b319b7a 1096
a1587156
C
1097 expect(elements[3].video.name).to.equal('video 4 server 1')
1098 expect(elements[3].position).to.equal(4)
37190663
C
1099
1100 expect(elements[4].video.name).to.equal('NSFW video')
1101 expect(elements[4].position).to.equal(5)
1102
1103 expect(elements[5].video.name).to.equal('NSFW video')
1104 expect(elements[5].position).to.equal(6)
1b319b7a
C
1105 }
1106 })
1b319b7a 1107
bfbd9128
C
1108 it('Should be able to create a public playlist, and set it to private', async function () {
1109 this.timeout(30000)
1b319b7a 1110
bfbd9128 1111 const res = await createVideoPlaylist({
a1587156
C
1112 url: servers[0].url,
1113 token: servers[0].accessToken,
bfbd9128
C
1114 playlistAttrs: {
1115 displayName: 'my super public playlist',
1116 privacy: VideoPlaylistPrivacy.PUBLIC,
a1587156 1117 videoChannelId: servers[0].videoChannel.id
bfbd9128
C
1118 }
1119 })
1120 const videoPlaylistIds = res.body.videoPlaylist
1b319b7a 1121
bfbd9128 1122 await waitJobs(servers)
1b319b7a 1123
bfbd9128 1124 for (const server of servers) {
f2eb23cd 1125 await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
bfbd9128 1126 }
1b319b7a 1127
bfbd9128 1128 const playlistAttrs = { privacy: VideoPlaylistPrivacy.PRIVATE }
a1587156 1129 await updateVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistId: videoPlaylistIds.id, playlistAttrs })
1b319b7a 1130
bfbd9128 1131 await waitJobs(servers)
1b319b7a 1132
a1587156 1133 for (const server of [ servers[1], servers[2] ]) {
f2eb23cd 1134 await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.NOT_FOUND_404)
bfbd9128 1135 }
f2eb23cd 1136 await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, HttpStatusCode.UNAUTHORIZED_401)
418d092a 1137
f2eb23cd 1138 await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
bfbd9128
C
1139 })
1140 })
df0b219d 1141
bfbd9128 1142 describe('Playlist deletion', function () {
df0b219d 1143
bfbd9128
C
1144 it('Should delete the playlist on server 1 and delete on server 2 and 3', async function () {
1145 this.timeout(30000)
418d092a 1146
a1587156 1147 await deleteVideoPlaylist(servers[0].url, servers[0].accessToken, playlistServer1Id)
418d092a 1148
bfbd9128 1149 await waitJobs(servers)
418d092a 1150
bfbd9128 1151 for (const server of servers) {
f2eb23cd 1152 await getVideoPlaylist(server.url, playlistServer1UUID, HttpStatusCode.NOT_FOUND_404)
bfbd9128
C
1153 }
1154 })
418d092a 1155
bfbd9128
C
1156 it('Should have deleted the thumbnail on server 1, 2 and 3', async function () {
1157 this.timeout(30000)
df0b219d 1158
bfbd9128
C
1159 for (const server of servers) {
1160 await checkPlaylistFilesWereRemoved(playlistServer1UUID, server.internalServerNumber)
1161 }
1162 })
df0b219d 1163
bfbd9128
C
1164 it('Should unfollow servers 1 and 2 and hide their playlists', async function () {
1165 this.timeout(30000)
df0b219d 1166
bfbd9128 1167 const finder = data => data.find(p => p.displayName === 'my super playlist')
df0b219d 1168
bfbd9128 1169 {
a1587156 1170 const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
bfbd9128
C
1171 expect(res.body.total).to.equal(3)
1172 expect(finder(res.body.data)).to.not.be.undefined
1173 }
418d092a 1174
c3d29f69 1175 await servers[2].followsCommand.unfollow({ target: servers[0] })
df0b219d 1176
bfbd9128 1177 {
a1587156 1178 const res = await getVideoPlaylistsList(servers[2].url, 0, 5)
bfbd9128 1179 expect(res.body.total).to.equal(1)
418d092a 1180
bfbd9128 1181 expect(finder(res.body.data)).to.be.undefined
df0b219d
C
1182 }
1183 })
df0b219d 1184
bfbd9128
C
1185 it('Should delete a channel and put the associated playlist in private mode', async function () {
1186 this.timeout(30000)
df0b219d 1187
a1587156 1188 const res = await addVideoChannel(servers[0].url, servers[0].accessToken, { name: 'super_channel', displayName: 'super channel' })
bfbd9128 1189 const videoChannelId = res.body.videoChannel.id
df0b219d 1190
bfbd9128 1191 const res2 = await createVideoPlaylist({
a1587156
C
1192 url: servers[0].url,
1193 token: servers[0].accessToken,
bfbd9128
C
1194 playlistAttrs: {
1195 displayName: 'channel playlist',
1196 privacy: VideoPlaylistPrivacy.PUBLIC,
1197 videoChannelId
1198 }
1199 })
1200 const videoPlaylistUUID = res2.body.videoPlaylist.uuid
1201
1202 await waitJobs(servers)
df0b219d 1203
a1587156 1204 await deleteVideoChannel(servers[0].url, servers[0].accessToken, 'super_channel')
df0b219d 1205
bfbd9128 1206 await waitJobs(servers)
418d092a 1207
a1587156 1208 const res3 = await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistUUID)
bfbd9128
C
1209 expect(res3.body.displayName).to.equal('channel playlist')
1210 expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
df0b219d 1211
f2eb23cd 1212 await getVideoPlaylist(servers[1].url, videoPlaylistUUID, HttpStatusCode.NOT_FOUND_404)
1eddc9a7 1213 })
df0b219d 1214
bfbd9128
C
1215 it('Should delete an account and delete its playlists', async function () {
1216 this.timeout(30000)
418d092a 1217
bfbd9128
C
1218 const user = { username: 'user_1', password: 'password' }
1219 const res = await createUser({
a1587156
C
1220 url: servers[0].url,
1221 accessToken: servers[0].accessToken,
bfbd9128
C
1222 username: user.username,
1223 password: user.password
1224 })
397d78fb 1225
bfbd9128 1226 const userId = res.body.user.id
a1587156 1227 const userAccessToken = await userLogin(servers[0], user)
df0b219d 1228
a1587156
C
1229 const resChannel = await getMyUserInformation(servers[0].url, userAccessToken)
1230 const userChannel = (resChannel.body as User).videoChannels[0]
df0b219d 1231
bfbd9128 1232 await createVideoPlaylist({
a1587156 1233 url: servers[0].url,
bfbd9128
C
1234 token: userAccessToken,
1235 playlistAttrs: {
1236 displayName: 'playlist to be deleted',
1237 privacy: VideoPlaylistPrivacy.PUBLIC,
1238 videoChannelId: userChannel.id
1239 }
1240 })
df0b219d 1241
bfbd9128
C
1242 await waitJobs(servers)
1243
1244 const finder = data => data.find(p => p.displayName === 'playlist to be deleted')
1245
1246 {
a1587156 1247 for (const server of [ servers[0], servers[1] ]) {
bfbd9128
C
1248 const res = await getVideoPlaylistsList(server.url, 0, 15)
1249 expect(finder(res.body.data)).to.not.be.undefined
1250 }
df0b219d 1251 }
df0b219d 1252
a1587156 1253 await removeUser(servers[0].url, userId, servers[0].accessToken)
bfbd9128 1254 await waitJobs(servers)
df0b219d 1255
bfbd9128 1256 {
a1587156 1257 for (const server of [ servers[0], servers[1] ]) {
bfbd9128
C
1258 const res = await getVideoPlaylistsList(server.url, 0, 15)
1259 expect(finder(res.body.data)).to.be.undefined
1260 }
df0b219d 1261 }
bfbd9128 1262 })
418d092a
C
1263 })
1264
7c3b7976
C
1265 after(async function () {
1266 await cleanupTests(servers)
418d092a
C
1267 })
1268})