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