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