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