1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
10 generateUserAccessToken,
11 getAccountPlaylistsListWithToken,
15 removeVideoFromPlaylist,
16 reorderVideosPlaylist,
18 setAccessTokensToServers,
19 setDefaultVideoChannel,
21 updateVideoPlaylistElement,
23 } from '../../../../shared/extra-utils'
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'
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
39 let playlistElementId: number
41 // ---------------------------------------------------------------
43 before(async function () {
46 server = await flushAndRunServer(1)
48 await setAccessTokensToServers([ server ])
49 await setDefaultVideoChannel([ server ])
51 userAccessToken = await generateUserAccessToken(server, 'user1')
52 videoId = (await uploadVideoAndGetId({ server, videoName: 'video 1' })).id
55 const res = await getAccountPlaylistsListWithToken(server.url, server.accessToken, 'root', 0, 5, VideoPlaylistType.WATCH_LATER)
56 watchLaterPlaylistId = res.body.data[0].id
60 const res = await createVideoPlaylist({
62 token: server.accessToken,
64 displayName: 'super playlist',
65 privacy: VideoPlaylistPrivacy.PUBLIC,
66 videoChannelId: server.videoChannel.id
69 playlistUUID = res.body.videoPlaylist.uuid
73 const res = await createVideoPlaylist({
75 token: server.accessToken,
77 displayName: 'private',
78 privacy: VideoPlaylistPrivacy.PRIVATE
81 privatePlaylistUUID = res.body.videoPlaylist.uuid
85 describe('When listing playlists', function () {
86 const globalPath = '/api/v1/video-playlists'
87 const accountPath = '/api/v1/accounts/root/video-playlists'
88 const videoChannelPath = '/api/v1/video-channels/root_channel/video-playlists'
90 it('Should fail with a bad start pagination', async function () {
91 await checkBadStartPagination(server.url, globalPath, server.accessToken)
92 await checkBadStartPagination(server.url, accountPath, server.accessToken)
93 await checkBadStartPagination(server.url, videoChannelPath, server.accessToken)
96 it('Should fail with a bad count pagination', async function () {
97 await checkBadCountPagination(server.url, globalPath, server.accessToken)
98 await checkBadCountPagination(server.url, accountPath, server.accessToken)
99 await checkBadCountPagination(server.url, videoChannelPath, server.accessToken)
102 it('Should fail with an incorrect sort', async function () {
103 await checkBadSortPagination(server.url, globalPath, server.accessToken)
104 await checkBadSortPagination(server.url, accountPath, server.accessToken)
105 await checkBadSortPagination(server.url, videoChannelPath, server.accessToken)
108 it('Should fail with a bad playlist type', async function () {
109 await makeGetRequest({ url: server.url, path: globalPath, query: { playlistType: 3 } })
110 await makeGetRequest({ url: server.url, path: accountPath, query: { playlistType: 3 } })
111 await makeGetRequest({ url: server.url, path: videoChannelPath, query: { playlistType: 3 } })
114 it('Should fail with a bad account parameter', async function () {
115 const accountPath = '/api/v1/accounts/root2/video-playlists'
117 await makeGetRequest({ url: server.url, path: accountPath, statusCodeExpected: 404, token: server.accessToken })
120 it('Should fail with a bad video channel parameter', async function () {
121 const accountPath = '/api/v1/video-channels/bad_channel/video-playlists'
123 await makeGetRequest({ url: server.url, path: accountPath, statusCodeExpected: 404, token: server.accessToken })
126 it('Should success with the correct parameters', async function () {
127 await makeGetRequest({ url: server.url, path: globalPath, statusCodeExpected: 200, token: server.accessToken })
128 await makeGetRequest({ url: server.url, path: accountPath, statusCodeExpected: 200, token: server.accessToken })
129 await makeGetRequest({ url: server.url, path: videoChannelPath, statusCodeExpected: 200, token: server.accessToken })
133 describe('When listing videos of a playlist', function () {
134 const path = '/api/v1/video-playlists/'
136 it('Should fail with a bad start pagination', async function () {
137 await checkBadStartPagination(server.url, path + playlistUUID + '/videos', server.accessToken)
140 it('Should fail with a bad count pagination', async function () {
141 await checkBadCountPagination(server.url, path + playlistUUID + '/videos', server.accessToken)
144 it('Should success with the correct parameters', async function () {
145 await makeGetRequest({ url: server.url, path: path + playlistUUID + '/videos', statusCodeExpected: 200 })
149 describe('When getting a video playlist', function () {
150 it('Should fail with a bad id or uuid', async function () {
151 await getVideoPlaylist(server.url, 'toto', 400)
154 it('Should fail with an unknown playlist', async function () {
155 await getVideoPlaylist(server.url, 42, 404)
158 it('Should fail to get an unlisted playlist with the number id', async function () {
159 const res = await createVideoPlaylist({
161 token: server.accessToken,
163 displayName: 'super playlist',
164 privacy: VideoPlaylistPrivacy.UNLISTED
167 const playlist = res.body.videoPlaylist
169 await getVideoPlaylist(server.url, playlist.id, 404)
170 await getVideoPlaylist(server.url, playlist.uuid, 200)
173 it('Should succeed with the correct params', async function () {
174 await getVideoPlaylist(server.url, playlistUUID, 200)
178 describe('When creating/updating a video playlist', function () {
179 const getBase = (playlistAttrs: any = {}, wrapper: any = {}) => {
180 return Object.assign({
183 token: server.accessToken,
184 playlistAttrs: Object.assign({
185 displayName: 'display name',
186 privacy: VideoPlaylistPrivacy.UNLISTED,
187 thumbnailfile: 'thumbnail.jpg',
188 videoChannelId: server.videoChannel.id
192 const getUpdate = (params: any, playlistId: number | string) => {
193 return immutableAssign(params, { playlistId: playlistId })
196 it('Should fail with an unauthenticated user', async function () {
197 const params = getBase({}, { token: null, expectedStatus: 401 })
199 await createVideoPlaylist(params)
200 await updateVideoPlaylist(getUpdate(params, playlistUUID))
203 it('Should fail without displayName', async function () {
204 const params = getBase({ displayName: undefined })
206 await createVideoPlaylist(params)
209 it('Should fail with an incorrect display name', async function () {
210 const params = getBase({ displayName: 's'.repeat(300) })
212 await createVideoPlaylist(params)
213 await updateVideoPlaylist(getUpdate(params, playlistUUID))
216 it('Should fail with an incorrect description', async function () {
217 const params = getBase({ description: 't' })
219 await createVideoPlaylist(params)
220 await updateVideoPlaylist(getUpdate(params, playlistUUID))
223 it('Should fail with an incorrect privacy', async function () {
224 const params = getBase({ privacy: 45 })
226 await createVideoPlaylist(params)
227 await updateVideoPlaylist(getUpdate(params, playlistUUID))
230 it('Should fail with an unknown video channel id', async function () {
231 const params = getBase({ videoChannelId: 42 }, { expectedStatus: 404 })
233 await createVideoPlaylist(params)
234 await updateVideoPlaylist(getUpdate(params, playlistUUID))
237 it('Should fail with an incorrect thumbnail file', async function () {
238 const params = getBase({ thumbnailfile: 'avatar.png' })
240 await createVideoPlaylist(params)
241 await updateVideoPlaylist(getUpdate(params, playlistUUID))
244 it('Should fail to set "public" a playlist not assigned to a channel', async function () {
245 const params = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: undefined })
246 const params2 = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: 'null' })
247 const params3 = getBase({ privacy: undefined, videoChannelId: 'null' })
249 await createVideoPlaylist(params)
250 await createVideoPlaylist(params2)
251 await updateVideoPlaylist(getUpdate(params, privatePlaylistUUID))
252 await updateVideoPlaylist(getUpdate(params2, playlistUUID))
253 await updateVideoPlaylist(getUpdate(params3, playlistUUID))
256 it('Should fail with an unknown playlist to update', async function () {
257 await updateVideoPlaylist(getUpdate(
258 getBase({}, { expectedStatus: 404 }),
263 it('Should fail to update a playlist of another user', async function () {
264 await updateVideoPlaylist(getUpdate(
265 getBase({}, { token: userAccessToken, expectedStatus: 403 }),
270 it('Should fail to update the watch later playlist', async function () {
271 await updateVideoPlaylist(getUpdate(
272 getBase({}, { expectedStatus: 400 }),
277 it('Should succeed with the correct params', async function () {
279 const params = getBase({}, { expectedStatus: 200 })
280 await createVideoPlaylist(params)
284 const params = getBase({}, { expectedStatus: 204 })
285 await updateVideoPlaylist(getUpdate(params, playlistUUID))
290 describe('When adding an element in a playlist', function () {
291 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
292 return Object.assign({
295 token: server.accessToken,
296 playlistId: playlistUUID,
297 elementAttrs: Object.assign({
305 it('Should fail with an unauthenticated user', async function () {
306 const params = getBase({}, { token: null, expectedStatus: 401 })
307 await addVideoInPlaylist(params)
310 it('Should fail with the playlist of another user', async function () {
311 const params = getBase({}, { token: userAccessToken, expectedStatus: 403 })
312 await addVideoInPlaylist(params)
315 it('Should fail with an unknown or incorrect playlist id', async function () {
317 const params = getBase({}, { playlistId: 'toto' })
318 await addVideoInPlaylist(params)
322 const params = getBase({}, { playlistId: 42, expectedStatus: 404 })
323 await addVideoInPlaylist(params)
327 it('Should fail with an unknown or incorrect video id', async function () {
328 const params = getBase({ videoId: 42 }, { expectedStatus: 404 })
329 await addVideoInPlaylist(params)
332 it('Should fail with a bad start/stop timestamp', async function () {
334 const params = getBase({ startTimestamp: -42 })
335 await addVideoInPlaylist(params)
339 const params = getBase({ stopTimestamp: 'toto' as any })
340 await addVideoInPlaylist(params)
344 it('Succeed with the correct params', async function () {
345 const params = getBase({}, { expectedStatus: 200 })
346 const res = await addVideoInPlaylist(params)
347 playlistElementId = res.body.videoPlaylistElement.id
351 describe('When updating an element in a playlist', function () {
352 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
353 return Object.assign({
355 token: server.accessToken,
356 elementAttrs: Object.assign({
361 playlistId: playlistUUID,
366 it('Should fail with an unauthenticated user', async function () {
367 const params = getBase({}, { token: null, expectedStatus: 401 })
368 await updateVideoPlaylistElement(params)
371 it('Should fail with the playlist of another user', async function () {
372 const params = getBase({}, { token: userAccessToken, expectedStatus: 403 })
373 await updateVideoPlaylistElement(params)
376 it('Should fail with an unknown or incorrect playlist id', async function () {
378 const params = getBase({}, { playlistId: 'toto' })
379 await updateVideoPlaylistElement(params)
383 const params = getBase({}, { playlistId: 42, expectedStatus: 404 })
384 await updateVideoPlaylistElement(params)
388 it('Should fail with an unknown or incorrect playlistElement id', async function () {
390 const params = getBase({}, { playlistElementId: 'toto' })
391 await updateVideoPlaylistElement(params)
395 const params = getBase({}, { playlistElementId: 42, expectedStatus: 404 })
396 await updateVideoPlaylistElement(params)
400 it('Should fail with a bad start/stop timestamp', async function () {
402 const params = getBase({ startTimestamp: 'toto' as any })
403 await updateVideoPlaylistElement(params)
407 const params = getBase({ stopTimestamp: -42 })
408 await updateVideoPlaylistElement(params)
412 it('Should fail with an unknown element', async function () {
413 const params = getBase({}, { playlistElementId: 888, expectedStatus: 404 })
414 await updateVideoPlaylistElement(params)
417 it('Succeed with the correct params', async function () {
418 const params = getBase({}, { expectedStatus: 204 })
419 await updateVideoPlaylistElement(params)
423 describe('When reordering elements of a playlist', function () {
427 const getBase = (elementAttrs: any = {}, wrapper: any = {}) => {
428 return Object.assign({
430 token: server.accessToken,
431 playlistId: playlistUUID,
432 elementAttrs: Object.assign({
434 insertAfterPosition: 2,
441 before(async function () {
442 videoId3 = (await uploadVideoAndGetId({ server, videoName: 'video 3' })).id
443 videoId4 = (await uploadVideoAndGetId({ server, videoName: 'video 4' })).id
445 for (const id of [ videoId3, videoId4 ]) {
446 await addVideoInPlaylist({
448 token: server.accessToken,
449 playlistId: playlistUUID,
450 elementAttrs: { videoId: id }
455 it('Should fail with an unauthenticated user', async function () {
456 const params = getBase({}, { token: null, expectedStatus: 401 })
457 await reorderVideosPlaylist(params)
460 it('Should fail with the playlist of another user', async function () {
461 const params = getBase({}, { token: userAccessToken, expectedStatus: 403 })
462 await reorderVideosPlaylist(params)
465 it('Should fail with an invalid playlist', async function () {
467 const params = getBase({}, { playlistId: 'toto' })
468 await reorderVideosPlaylist(params)
472 const params = getBase({}, { playlistId: 42, expectedStatus: 404 })
473 await reorderVideosPlaylist(params)
477 it('Should fail with an invalid start position', async function () {
479 const params = getBase({ startPosition: -1 })
480 await reorderVideosPlaylist(params)
484 const params = getBase({ startPosition: 'toto' as any })
485 await reorderVideosPlaylist(params)
489 const params = getBase({ startPosition: 42 })
490 await reorderVideosPlaylist(params)
494 it('Should fail with an invalid insert after position', async function () {
496 const params = getBase({ insertAfterPosition: 'toto' as any })
497 await reorderVideosPlaylist(params)
501 const params = getBase({ insertAfterPosition: -2 })
502 await reorderVideosPlaylist(params)
506 const params = getBase({ insertAfterPosition: 42 })
507 await reorderVideosPlaylist(params)
511 it('Should fail with an invalid reorder length', async function () {
513 const params = getBase({ reorderLength: 'toto' as any })
514 await reorderVideosPlaylist(params)
518 const params = getBase({ reorderLength: -2 })
519 await reorderVideosPlaylist(params)
523 const params = getBase({ reorderLength: 42 })
524 await reorderVideosPlaylist(params)
528 it('Succeed with the correct params', async function () {
529 const params = getBase({}, { expectedStatus: 204 })
530 await reorderVideosPlaylist(params)
534 describe('When checking exists in playlist endpoint', function () {
535 const path = '/api/v1/users/me/video-playlists/videos-exist'
537 it('Should fail with an unauthenticated user', async function () {
538 await makeGetRequest({
541 query: { videoIds: [ 1, 2 ] },
542 statusCodeExpected: 401
546 it('Should fail with invalid video ids', async function () {
547 await makeGetRequest({
549 token: server.accessToken,
551 query: { videoIds: 'toto' }
554 await makeGetRequest({
556 token: server.accessToken,
558 query: { videoIds: [ 'toto' ] }
561 await makeGetRequest({
563 token: server.accessToken,
565 query: { videoIds: [ 1, 'toto' ] }
569 it('Should succeed with the correct params', async function () {
570 await makeGetRequest({
572 token: server.accessToken,
574 query: { videoIds: [ 1, 2 ] },
575 statusCodeExpected: 200
580 describe('When deleting an element in a playlist', function () {
581 const getBase = (wrapper: any = {}) => {
582 return Object.assign({
584 token: server.accessToken,
586 playlistId: playlistUUID,
591 it('Should fail with an unauthenticated user', async function () {
592 const params = getBase({ token: null, expectedStatus: 401 })
593 await removeVideoFromPlaylist(params)
596 it('Should fail with the playlist of another user', async function () {
597 const params = getBase({ token: userAccessToken, expectedStatus: 403 })
598 await removeVideoFromPlaylist(params)
601 it('Should fail with an unknown or incorrect playlist id', async function () {
603 const params = getBase({ playlistId: 'toto' })
604 await removeVideoFromPlaylist(params)
608 const params = getBase({ playlistId: 42, expectedStatus: 404 })
609 await removeVideoFromPlaylist(params)
613 it('Should fail with an unknown or incorrect video id', async function () {
615 const params = getBase({ playlistElementId: 'toto' })
616 await removeVideoFromPlaylist(params)
620 const params = getBase({ playlistElementId: 42, expectedStatus: 404 })
621 await removeVideoFromPlaylist(params)
625 it('Should fail with an unknown element', async function () {
626 const params = getBase({ playlistElementId: 888, expectedStatus: 404 })
627 await removeVideoFromPlaylist(params)
630 it('Succeed with the correct params', async function () {
631 const params = getBase({ expectedStatus: 204 })
632 await removeVideoFromPlaylist(params)
636 describe('When deleting a playlist', function () {
637 it('Should fail with an unknown playlist', async function () {
638 await deleteVideoPlaylist(server.url, server.accessToken, 42, 404)
641 it('Should fail with a playlist of another user', async function () {
642 await deleteVideoPlaylist(server.url, userAccessToken, playlistUUID, 403)
645 it('Should fail with the watch later playlist', async function () {
646 await deleteVideoPlaylist(server.url, server.accessToken, watchLaterPlaylistId, 400)
649 it('Should succeed with the correct params', async function () {
650 await deleteVideoPlaylist(server.url, server.accessToken, playlistUUID)
654 after(async function () {
655 await cleanupTests([ server ])