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