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