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