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