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