]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/check-params/video-playlists.ts
Merge branch 'release/2.1.0' into develop
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / video-playlists.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import {
5 addVideoInPlaylist,
6 cleanupTests,
7 createVideoPlaylist,
8 deleteVideoPlaylist,
9 flushAndRunServer,
10 generateUserAccessToken,
11 getAccountPlaylistsListWithToken,
12 getVideoPlaylist,
13 immutableAssign,
14 makeGetRequest,
15 removeVideoFromPlaylist,
16 reorderVideosPlaylist,
17 ServerInfo,
18 setAccessTokensToServers,
19 setDefaultVideoChannel,
20 updateVideoPlaylist,
21 updateVideoPlaylistElement,
22 uploadVideoAndGetId
23 } from '../../../../shared/extra-utils'
24 import {
25 checkBadCountPagination,
26 checkBadSortPagination,
27 checkBadStartPagination
28 } from '../../../../shared/extra-utils/requests/check-api-params'
29 import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
30 import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model'
31
32 describe('Test video playlists API validator', function () {
33 let server: ServerInfo
34 let userAccessToken: string
35 let playlistUUID: string
36 let privatePlaylistUUID: string
37 let watchLaterPlaylistId: number
38 let videoId: number
39 // eslint-disable-next-line @typescript-eslint/no-unused-vars
40 let videoId2: number
41 let playlistElementId: number
42
43 // ---------------------------------------------------------------
44
45 before(async function () {
46 this.timeout(30000)
47
48 server = await flushAndRunServer(1)
49
50 await setAccessTokensToServers([ server ])
51 await setDefaultVideoChannel([ server ])
52
53 userAccessToken = await generateUserAccessToken(server, 'user1')
54 videoId = (await uploadVideoAndGetId({ server, videoName: 'video 1' })).id
55 videoId2 = (await uploadVideoAndGetId({ server, videoName: 'video 2' })).id
56
57 {
58 const res = await getAccountPlaylistsListWithToken(server.url, server.accessToken, 'root', 0, 5, VideoPlaylistType.WATCH_LATER)
59 watchLaterPlaylistId = res.body.data[0].id
60 }
61
62 {
63 const res = await createVideoPlaylist({
64 url: server.url,
65 token: server.accessToken,
66 playlistAttrs: {
67 displayName: 'super playlist',
68 privacy: VideoPlaylistPrivacy.PUBLIC,
69 videoChannelId: server.videoChannel.id
70 }
71 })
72 playlistUUID = res.body.videoPlaylist.uuid
73 }
74
75 {
76 const res = await createVideoPlaylist({
77 url: server.url,
78 token: server.accessToken,
79 playlistAttrs: {
80 displayName: 'private',
81 privacy: VideoPlaylistPrivacy.PRIVATE
82 }
83 })
84 privatePlaylistUUID = res.body.videoPlaylist.uuid
85 }
86 })
87
88 describe('When listing playlists', function () {
89 const globalPath = '/api/v1/video-playlists'
90 const accountPath = '/api/v1/accounts/root/video-playlists'
91 const videoChannelPath = '/api/v1/video-channels/root_channel/video-playlists'
92
93 it('Should fail with a bad start pagination', async function () {
94 await checkBadStartPagination(server.url, globalPath, server.accessToken)
95 await checkBadStartPagination(server.url, accountPath, server.accessToken)
96 await checkBadStartPagination(server.url, videoChannelPath, server.accessToken)
97 })
98
99 it('Should fail with a bad count pagination', async function () {
100 await checkBadCountPagination(server.url, globalPath, server.accessToken)
101 await checkBadCountPagination(server.url, accountPath, server.accessToken)
102 await checkBadCountPagination(server.url, videoChannelPath, server.accessToken)
103 })
104
105 it('Should fail with an incorrect sort', async function () {
106 await checkBadSortPagination(server.url, globalPath, server.accessToken)
107 await checkBadSortPagination(server.url, accountPath, server.accessToken)
108 await checkBadSortPagination(server.url, videoChannelPath, server.accessToken)
109 })
110
111 it('Should fail with a bad playlist type', async function () {
112 await makeGetRequest({ url: server.url, path: globalPath, query: { playlistType: 3 } })
113 await makeGetRequest({ url: server.url, path: accountPath, query: { playlistType: 3 } })
114 await makeGetRequest({ url: server.url, path: videoChannelPath, query: { playlistType: 3 } })
115 })
116
117 it('Should fail with a bad account parameter', async function () {
118 const accountPath = '/api/v1/accounts/root2/video-playlists'
119
120 await makeGetRequest({ url: server.url, path: accountPath, statusCodeExpected: 404, token: server.accessToken })
121 })
122
123 it('Should fail with a bad video channel parameter', async function () {
124 const accountPath = '/api/v1/video-channels/bad_channel/video-playlists'
125
126 await makeGetRequest({ url: server.url, path: accountPath, statusCodeExpected: 404, token: server.accessToken })
127 })
128
129 it('Should success with the correct parameters', async function () {
130 await makeGetRequest({ url: server.url, path: globalPath, statusCodeExpected: 200, token: server.accessToken })
131 await makeGetRequest({ url: server.url, path: accountPath, statusCodeExpected: 200, token: server.accessToken })
132 await makeGetRequest({ url: server.url, path: videoChannelPath, statusCodeExpected: 200, token: server.accessToken })
133 })
134 })
135
136 describe('When listing videos of a playlist', function () {
137 const path = '/api/v1/video-playlists/'
138
139 it('Should fail with a bad start pagination', async function () {
140 await checkBadStartPagination(server.url, path + playlistUUID + '/videos', server.accessToken)
141 })
142
143 it('Should fail with a bad count pagination', async function () {
144 await checkBadCountPagination(server.url, path + playlistUUID + '/videos', server.accessToken)
145 })
146
147 it('Should success with the correct parameters', async function () {
148 await makeGetRequest({ url: server.url, path: path + playlistUUID + '/videos', statusCodeExpected: 200 })
149 })
150 })
151
152 describe('When getting a video playlist', function () {
153 it('Should fail with a bad id or uuid', async function () {
154 await getVideoPlaylist(server.url, 'toto', 400)
155 })
156
157 it('Should fail with an unknown playlist', async function () {
158 await getVideoPlaylist(server.url, 42, 404)
159 })
160
161 it('Should fail to get an unlisted playlist with the number id', async function () {
162 const res = await createVideoPlaylist({
163 url: server.url,
164 token: server.accessToken,
165 playlistAttrs: {
166 displayName: 'super playlist',
167 privacy: VideoPlaylistPrivacy.UNLISTED
168 }
169 })
170 const playlist = res.body.videoPlaylist
171
172 await getVideoPlaylist(server.url, playlist.id, 404)
173 await getVideoPlaylist(server.url, playlist.uuid, 200)
174 })
175
176 it('Should succeed with the correct params', async function () {
177 await getVideoPlaylist(server.url, playlistUUID, 200)
178 })
179 })
180
181 describe('When creating/updating a video playlist', function () {
182 const getBase = (playlistAttrs: any = {}, wrapper: any = {}) => {
183 return Object.assign({
184 expectedStatus: 400,
185 url: server.url,
186 token: server.accessToken,
187 playlistAttrs: Object.assign({
188 displayName: 'display name',
189 privacy: VideoPlaylistPrivacy.UNLISTED,
190 thumbnailfile: 'thumbnail.jpg',
191 videoChannelId: server.videoChannel.id
192 }, playlistAttrs)
193 }, wrapper)
194 }
195 const getUpdate = (params: any, playlistId: number | string) => {
196 return immutableAssign(params, { playlistId: playlistId })
197 }
198
199 it('Should fail with an unauthenticated user', async function () {
200 const params = getBase({}, { token: null, expectedStatus: 401 })
201
202 await createVideoPlaylist(params)
203 await updateVideoPlaylist(getUpdate(params, playlistUUID))
204 })
205
206 it('Should fail without displayName', async function () {
207 const params = getBase({ displayName: undefined })
208
209 await createVideoPlaylist(params)
210 })
211
212 it('Should fail with an incorrect display name', async function () {
213 const params = getBase({ displayName: 's'.repeat(300) })
214
215 await createVideoPlaylist(params)
216 await updateVideoPlaylist(getUpdate(params, playlistUUID))
217 })
218
219 it('Should fail with an incorrect description', async function () {
220 const params = getBase({ description: 't' })
221
222 await createVideoPlaylist(params)
223 await updateVideoPlaylist(getUpdate(params, playlistUUID))
224 })
225
226 it('Should fail with an incorrect privacy', async function () {
227 const params = getBase({ privacy: 45 })
228
229 await createVideoPlaylist(params)
230 await updateVideoPlaylist(getUpdate(params, playlistUUID))
231 })
232
233 it('Should fail with an unknown video channel id', async function () {
234 const params = getBase({ videoChannelId: 42 }, { expectedStatus: 404 })
235
236 await createVideoPlaylist(params)
237 await updateVideoPlaylist(getUpdate(params, playlistUUID))
238 })
239
240 it('Should fail with an incorrect thumbnail file', async function () {
241 const params = getBase({ thumbnailfile: 'avatar.png' })
242
243 await createVideoPlaylist(params)
244 await updateVideoPlaylist(getUpdate(params, playlistUUID))
245 })
246
247 it('Should fail to set "public" a playlist not assigned to a channel', async function () {
248 const params = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: undefined })
249 const params2 = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: 'null' })
250 const params3 = getBase({ privacy: undefined, videoChannelId: 'null' })
251
252 await createVideoPlaylist(params)
253 await createVideoPlaylist(params2)
254 await updateVideoPlaylist(getUpdate(params, privatePlaylistUUID))
255 await updateVideoPlaylist(getUpdate(params2, playlistUUID))
256 await updateVideoPlaylist(getUpdate(params3, playlistUUID))
257 })
258
259 it('Should fail with an unknown playlist to update', async function () {
260 await updateVideoPlaylist(getUpdate(
261 getBase({}, { expectedStatus: 404 }),
262 42
263 ))
264 })
265
266 it('Should fail to update a playlist of another user', async function () {
267 await updateVideoPlaylist(getUpdate(
268 getBase({}, { token: userAccessToken, expectedStatus: 403 }),
269 playlistUUID
270 ))
271 })
272
273 it('Should fail to update the watch later playlist', async function () {
274 await updateVideoPlaylist(getUpdate(
275 getBase({}, { expectedStatus: 400 }),
276 watchLaterPlaylistId
277 ))
278 })
279
280 it('Should succeed with the correct params', async function () {
281 {
282 const params = getBase({}, { expectedStatus: 200 })
283 await createVideoPlaylist(params)
284 }
285
286 {
287 const params = getBase({}, { expectedStatus: 204 })
288 await updateVideoPlaylist(getUpdate(params, playlistUUID))
289 }
290 })
291 })
292
293 describe('When adding an element in a playlist', function () {
294 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
295 return Object.assign({
296 expectedStatus: 400,
297 url: server.url,
298 token: server.accessToken,
299 playlistId: playlistUUID,
300 elementAttrs: Object.assign({
301 videoId,
302 startTimestamp: 2,
303 stopTimestamp: 3
304 }, elementAttrs)
305 }, wrapper)
306 }
307
308 it('Should fail with an unauthenticated user', async function () {
309 const params = getBase({}, { token: null, expectedStatus: 401 })
310 await addVideoInPlaylist(params)
311 })
312
313 it('Should fail with the playlist of another user', async function () {
314 const params = getBase({}, { token: userAccessToken, expectedStatus: 403 })
315 await addVideoInPlaylist(params)
316 })
317
318 it('Should fail with an unknown or incorrect playlist id', async function () {
319 {
320 const params = getBase({}, { playlistId: 'toto' })
321 await addVideoInPlaylist(params)
322 }
323
324 {
325 const params = getBase({}, { playlistId: 42, expectedStatus: 404 })
326 await addVideoInPlaylist(params)
327 }
328 })
329
330 it('Should fail with an unknown or incorrect video id', async function () {
331 const params = getBase({ videoId: 42 }, { expectedStatus: 404 })
332 await addVideoInPlaylist(params)
333 })
334
335 it('Should fail with a bad start/stop timestamp', async function () {
336 {
337 const params = getBase({ startTimestamp: -42 })
338 await addVideoInPlaylist(params)
339 }
340
341 {
342 const params = getBase({ stopTimestamp: 'toto' as any })
343 await addVideoInPlaylist(params)
344 }
345 })
346
347 it('Succeed with the correct params', async function () {
348 const params = getBase({}, { expectedStatus: 200 })
349 const res = await addVideoInPlaylist(params)
350 playlistElementId = res.body.videoPlaylistElement.id
351 })
352
353 it('Should fail if the video was already added in the playlist', async function () {
354 const params = getBase({}, { expectedStatus: 409 })
355 await addVideoInPlaylist(params)
356 })
357 })
358
359 describe('When updating an element in a playlist', function () {
360 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
361 return Object.assign({
362 url: server.url,
363 token: server.accessToken,
364 elementAttrs: Object.assign({
365 startTimestamp: 1,
366 stopTimestamp: 2
367 }, elementAttrs),
368 playlistElementId,
369 playlistId: playlistUUID,
370 expectedStatus: 400
371 }, wrapper)
372 }
373
374 it('Should fail with an unauthenticated user', async function () {
375 const params = getBase({}, { token: null, expectedStatus: 401 })
376 await updateVideoPlaylistElement(params)
377 })
378
379 it('Should fail with the playlist of another user', async function () {
380 const params = getBase({}, { token: userAccessToken, expectedStatus: 403 })
381 await updateVideoPlaylistElement(params)
382 })
383
384 it('Should fail with an unknown or incorrect playlist id', async function () {
385 {
386 const params = getBase({}, { playlistId: 'toto' })
387 await updateVideoPlaylistElement(params)
388 }
389
390 {
391 const params = getBase({}, { playlistId: 42, expectedStatus: 404 })
392 await updateVideoPlaylistElement(params)
393 }
394 })
395
396 it('Should fail with an unknown or incorrect playlistElement id', async function () {
397 {
398 const params = getBase({}, { playlistElementId: 'toto' })
399 await updateVideoPlaylistElement(params)
400 }
401
402 {
403 const params = getBase({}, { playlistElementId: 42, expectedStatus: 404 })
404 await updateVideoPlaylistElement(params)
405 }
406 })
407
408 it('Should fail with a bad start/stop timestamp', async function () {
409 {
410 const params = getBase({ startTimestamp: 'toto' as any })
411 await updateVideoPlaylistElement(params)
412 }
413
414 {
415 const params = getBase({ stopTimestamp: -42 })
416 await updateVideoPlaylistElement(params)
417 }
418 })
419
420 it('Should fail with an unknown element', async function () {
421 const params = getBase({}, { playlistElementId: 888, expectedStatus: 404 })
422 await updateVideoPlaylistElement(params)
423 })
424
425 it('Succeed with the correct params', async function () {
426 const params = getBase({}, { expectedStatus: 204 })
427 await updateVideoPlaylistElement(params)
428 })
429 })
430
431 describe('When reordering elements of a playlist', function () {
432 let videoId3: number
433 let videoId4: number
434
435 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
436 return Object.assign({
437 url: server.url,
438 token: server.accessToken,
439 playlistId: playlistUUID,
440 elementAttrs: Object.assign({
441 startPosition: 1,
442 insertAfterPosition: 2,
443 reorderLength: 3
444 }, elementAttrs),
445 expectedStatus: 400
446 }, wrapper)
447 }
448
449 before(async function () {
450 videoId3 = (await uploadVideoAndGetId({ server, videoName: 'video 3' })).id
451 videoId4 = (await uploadVideoAndGetId({ server, videoName: 'video 4' })).id
452
453 for (const id of [ videoId3, videoId4 ]) {
454 await addVideoInPlaylist({
455 url: server.url,
456 token: server.accessToken,
457 playlistId: playlistUUID,
458 elementAttrs: { videoId: id }
459 })
460 }
461 })
462
463 it('Should fail with an unauthenticated user', async function () {
464 const params = getBase({}, { token: null, expectedStatus: 401 })
465 await reorderVideosPlaylist(params)
466 })
467
468 it('Should fail with the playlist of another user', async function () {
469 const params = getBase({}, { token: userAccessToken, expectedStatus: 403 })
470 await reorderVideosPlaylist(params)
471 })
472
473 it('Should fail with an invalid playlist', async function () {
474 {
475 const params = getBase({}, { playlistId: 'toto' })
476 await reorderVideosPlaylist(params)
477 }
478
479 {
480 const params = getBase({}, { playlistId: 42, expectedStatus: 404 })
481 await reorderVideosPlaylist(params)
482 }
483 })
484
485 it('Should fail with an invalid start position', async function () {
486 {
487 const params = getBase({ startPosition: -1 })
488 await reorderVideosPlaylist(params)
489 }
490
491 {
492 const params = getBase({ startPosition: 'toto' as any })
493 await reorderVideosPlaylist(params)
494 }
495
496 {
497 const params = getBase({ startPosition: 42 })
498 await reorderVideosPlaylist(params)
499 }
500 })
501
502 it('Should fail with an invalid insert after position', async function () {
503 {
504 const params = getBase({ insertAfterPosition: 'toto' as any })
505 await reorderVideosPlaylist(params)
506 }
507
508 {
509 const params = getBase({ insertAfterPosition: -2 })
510 await reorderVideosPlaylist(params)
511 }
512
513 {
514 const params = getBase({ insertAfterPosition: 42 })
515 await reorderVideosPlaylist(params)
516 }
517 })
518
519 it('Should fail with an invalid reorder length', async function () {
520 {
521 const params = getBase({ reorderLength: 'toto' as any })
522 await reorderVideosPlaylist(params)
523 }
524
525 {
526 const params = getBase({ reorderLength: -2 })
527 await reorderVideosPlaylist(params)
528 }
529
530 {
531 const params = getBase({ reorderLength: 42 })
532 await reorderVideosPlaylist(params)
533 }
534 })
535
536 it('Succeed with the correct params', async function () {
537 const params = getBase({}, { expectedStatus: 204 })
538 await reorderVideosPlaylist(params)
539 })
540 })
541
542 describe('When checking exists in playlist endpoint', function () {
543 const path = '/api/v1/users/me/video-playlists/videos-exist'
544
545 it('Should fail with an unauthenticated user', async function () {
546 await makeGetRequest({
547 url: server.url,
548 path,
549 query: { videoIds: [ 1, 2 ] },
550 statusCodeExpected: 401
551 })
552 })
553
554 it('Should fail with invalid video ids', async function () {
555 await makeGetRequest({
556 url: server.url,
557 token: server.accessToken,
558 path,
559 query: { videoIds: 'toto' }
560 })
561
562 await makeGetRequest({
563 url: server.url,
564 token: server.accessToken,
565 path,
566 query: { videoIds: [ 'toto' ] }
567 })
568
569 await makeGetRequest({
570 url: server.url,
571 token: server.accessToken,
572 path,
573 query: { videoIds: [ 1, 'toto' ] }
574 })
575 })
576
577 it('Should succeed with the correct params', async function () {
578 await makeGetRequest({
579 url: server.url,
580 token: server.accessToken,
581 path,
582 query: { videoIds: [ 1, 2 ] },
583 statusCodeExpected: 200
584 })
585 })
586 })
587
588 describe('When deleting an element in a playlist', function () {
589 const getBase = (wrapper: any = {}) => {
590 return Object.assign({
591 url: server.url,
592 token: server.accessToken,
593 playlistElementId,
594 playlistId: playlistUUID,
595 expectedStatus: 400
596 }, wrapper)
597 }
598
599 it('Should fail with an unauthenticated user', async function () {
600 const params = getBase({ token: null, expectedStatus: 401 })
601 await removeVideoFromPlaylist(params)
602 })
603
604 it('Should fail with the playlist of another user', async function () {
605 const params = getBase({ token: userAccessToken, expectedStatus: 403 })
606 await removeVideoFromPlaylist(params)
607 })
608
609 it('Should fail with an unknown or incorrect playlist id', async function () {
610 {
611 const params = getBase({ playlistId: 'toto' })
612 await removeVideoFromPlaylist(params)
613 }
614
615 {
616 const params = getBase({ playlistId: 42, expectedStatus: 404 })
617 await removeVideoFromPlaylist(params)
618 }
619 })
620
621 it('Should fail with an unknown or incorrect video id', async function () {
622 {
623 const params = getBase({ playlistElementId: 'toto' })
624 await removeVideoFromPlaylist(params)
625 }
626
627 {
628 const params = getBase({ playlistElementId: 42, expectedStatus: 404 })
629 await removeVideoFromPlaylist(params)
630 }
631 })
632
633 it('Should fail with an unknown element', async function () {
634 const params = getBase({ playlistElementId: 888, expectedStatus: 404 })
635 await removeVideoFromPlaylist(params)
636 })
637
638 it('Succeed with the correct params', async function () {
639 const params = getBase({ expectedStatus: 204 })
640 await removeVideoFromPlaylist(params)
641 })
642 })
643
644 describe('When deleting a playlist', function () {
645 it('Should fail with an unknown playlist', async function () {
646 await deleteVideoPlaylist(server.url, server.accessToken, 42, 404)
647 })
648
649 it('Should fail with a playlist of another user', async function () {
650 await deleteVideoPlaylist(server.url, userAccessToken, playlistUUID, 403)
651 })
652
653 it('Should fail with the watch later playlist', async function () {
654 await deleteVideoPlaylist(server.url, server.accessToken, watchLaterPlaylistId, 400)
655 })
656
657 it('Should succeed with the correct params', async function () {
658 await deleteVideoPlaylist(server.url, server.accessToken, playlistUUID)
659 })
660 })
661
662 after(async function () {
663 await cleanupTests([ server ])
664 })
665 })