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