aboutsummaryrefslogtreecommitdiffhomepage
path: root/packages/tests/src/api/check-params/live.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-08-17 08:59:21 +0200
committerChocobozzz <me@florianbigard.com>2023-08-17 08:59:21 +0200
commitc380e3928517eb5311b38cf257816642617d7a33 (patch)
tree2ea9b70ebca16b5d109bcce98fe7f944dad89319 /packages/tests/src/api/check-params/live.ts
parenta8ca6190fb462bf6eb5685cfc1d8ae444164a487 (diff)
parent3a4992633ee62d5edfbb484d9c6bcb3cf158489d (diff)
downloadPeerTube-c380e3928517eb5311b38cf257816642617d7a33.tar.gz
PeerTube-c380e3928517eb5311b38cf257816642617d7a33.tar.zst
PeerTube-c380e3928517eb5311b38cf257816642617d7a33.zip
Merge branch 'feature/esm-and-nx' into develop
Diffstat (limited to 'packages/tests/src/api/check-params/live.ts')
-rw-r--r--packages/tests/src/api/check-params/live.ts590
1 files changed, 590 insertions, 0 deletions
diff --git a/packages/tests/src/api/check-params/live.ts b/packages/tests/src/api/check-params/live.ts
new file mode 100644
index 000000000..5900823ea
--- /dev/null
+++ b/packages/tests/src/api/check-params/live.ts
@@ -0,0 +1,590 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { omit } from '@peertube/peertube-core-utils'
5import { HttpStatusCode, LiveVideoLatencyMode, VideoCreateResult, VideoPrivacy } from '@peertube/peertube-models'
6import { buildAbsoluteFixturePath } from '@peertube/peertube-node-utils'
7import {
8 cleanupTests,
9 createSingleServer,
10 LiveCommand,
11 makePostBodyRequest,
12 makeUploadRequest,
13 PeerTubeServer,
14 sendRTMPStream,
15 setAccessTokensToServers,
16 stopFfmpeg
17} from '@peertube/peertube-server-commands'
18
19describe('Test video lives API validator', function () {
20 const path = '/api/v1/videos/live'
21 let server: PeerTubeServer
22 let userAccessToken = ''
23 let channelId: number
24 let video: VideoCreateResult
25 let videoIdNotLive: number
26 let command: LiveCommand
27
28 // ---------------------------------------------------------------
29
30 before(async function () {
31 this.timeout(30000)
32
33 server = await createSingleServer(1)
34
35 await setAccessTokensToServers([ server ])
36
37 await server.config.updateCustomSubConfig({
38 newConfig: {
39 live: {
40 enabled: true,
41 latencySetting: {
42 enabled: false
43 },
44 maxInstanceLives: 20,
45 maxUserLives: 20,
46 allowReplay: true
47 }
48 }
49 })
50
51 const username = 'user1'
52 const password = 'my super password'
53 await server.users.create({ username, password })
54 userAccessToken = await server.login.getAccessToken({ username, password })
55
56 {
57 const { videoChannels } = await server.users.getMyInfo()
58 channelId = videoChannels[0].id
59 }
60
61 {
62 videoIdNotLive = (await server.videos.quickUpload({ name: 'not live' })).id
63 }
64
65 command = server.live
66 })
67
68 describe('When creating a live', function () {
69 let baseCorrectParams
70
71 before(function () {
72 baseCorrectParams = {
73 name: 'my super name',
74 category: 5,
75 licence: 1,
76 language: 'pt',
77 nsfw: false,
78 commentsEnabled: true,
79 downloadEnabled: true,
80 waitTranscoding: true,
81 description: 'my super description',
82 support: 'my super support text',
83 tags: [ 'tag1', 'tag2' ],
84 privacy: VideoPrivacy.PUBLIC,
85 channelId,
86 saveReplay: false,
87 replaySettings: undefined,
88 permanentLive: false,
89 latencyMode: LiveVideoLatencyMode.DEFAULT
90 }
91 })
92
93 it('Should fail with nothing', async function () {
94 const fields = {}
95 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
96 })
97
98 it('Should fail with a long name', async function () {
99 const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
100
101 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
102 })
103
104 it('Should fail with a bad category', async function () {
105 const fields = { ...baseCorrectParams, category: 125 }
106
107 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
108 })
109
110 it('Should fail with a bad licence', async function () {
111 const fields = { ...baseCorrectParams, licence: 125 }
112
113 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
114 })
115
116 it('Should fail with a bad language', async function () {
117 const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
118
119 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
120 })
121
122 it('Should fail with a long description', async function () {
123 const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
124
125 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
126 })
127
128 it('Should fail with a long support text', async function () {
129 const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
130
131 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
132 })
133
134 it('Should fail without a channel', async function () {
135 const fields = omit(baseCorrectParams, [ 'channelId' ])
136
137 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
138 })
139
140 it('Should fail with a bad channel', async function () {
141 const fields = { ...baseCorrectParams, channelId: 545454 }
142
143 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
144 })
145
146 it('Should fail with a bad privacy for replay settings', async function () {
147 const fields = { ...baseCorrectParams, saveReplay: true, replaySettings: { privacy: 999 } }
148
149 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
150 })
151
152 it('Should fail with another user channel', async function () {
153 const user = {
154 username: 'fake',
155 password: 'fake_password'
156 }
157 await server.users.create({ username: user.username, password: user.password })
158
159 const accessTokenUser = await server.login.getAccessToken(user)
160 const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
161 const customChannelId = videoChannels[0].id
162
163 const fields = { ...baseCorrectParams, channelId: customChannelId }
164
165 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
166 })
167
168 it('Should fail with too many tags', async function () {
169 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
170
171 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
172 })
173
174 it('Should fail with a tag length too low', async function () {
175 const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
176
177 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
178 })
179
180 it('Should fail with a tag length too big', async function () {
181 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
182
183 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
184 })
185
186 it('Should fail with an incorrect thumbnail file', async function () {
187 const fields = baseCorrectParams
188 const attaches = {
189 thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
190 }
191
192 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
193 })
194
195 it('Should fail with a big thumbnail file', async function () {
196 const fields = baseCorrectParams
197 const attaches = {
198 thumbnailfile: buildAbsoluteFixturePath('custom-preview-big.png')
199 }
200
201 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
202 })
203
204 it('Should fail with an incorrect preview file', async function () {
205 const fields = baseCorrectParams
206 const attaches = {
207 previewfile: buildAbsoluteFixturePath('video_short.mp4')
208 }
209
210 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
211 })
212
213 it('Should fail with a big preview file', async function () {
214 const fields = baseCorrectParams
215 const attaches = {
216 previewfile: buildAbsoluteFixturePath('custom-preview-big.png')
217 }
218
219 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
220 })
221
222 it('Should fail with bad latency setting', async function () {
223 const fields = { ...baseCorrectParams, latencyMode: 42 }
224
225 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
226 })
227
228 it('Should fail to set latency if the server does not allow it', async function () {
229 const fields = { ...baseCorrectParams, latencyMode: LiveVideoLatencyMode.HIGH_LATENCY }
230
231 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
232 })
233
234 it('Should succeed with the correct parameters', async function () {
235 this.timeout(30000)
236
237 const res = await makePostBodyRequest({
238 url: server.url,
239 path,
240 token: server.accessToken,
241 fields: baseCorrectParams,
242 expectedStatus: HttpStatusCode.OK_200
243 })
244
245 video = res.body.video
246 })
247
248 it('Should forbid if live is disabled', async function () {
249 await server.config.updateCustomSubConfig({
250 newConfig: {
251 live: {
252 enabled: false
253 }
254 }
255 })
256
257 await makePostBodyRequest({
258 url: server.url,
259 path,
260 token: server.accessToken,
261 fields: baseCorrectParams,
262 expectedStatus: HttpStatusCode.FORBIDDEN_403
263 })
264 })
265
266 it('Should forbid to save replay if not enabled by the admin', async function () {
267 const fields = { ...baseCorrectParams, saveReplay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } }
268
269 await server.config.updateCustomSubConfig({
270 newConfig: {
271 live: {
272 enabled: true,
273 allowReplay: false
274 }
275 }
276 })
277
278 await makePostBodyRequest({
279 url: server.url,
280 path,
281 token: server.accessToken,
282 fields,
283 expectedStatus: HttpStatusCode.FORBIDDEN_403
284 })
285 })
286
287 it('Should allow to save replay if enabled by the admin', async function () {
288 const fields = { ...baseCorrectParams, saveReplay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } }
289
290 await server.config.updateCustomSubConfig({
291 newConfig: {
292 live: {
293 enabled: true,
294 allowReplay: true
295 }
296 }
297 })
298
299 await makePostBodyRequest({
300 url: server.url,
301 path,
302 token: server.accessToken,
303 fields,
304 expectedStatus: HttpStatusCode.OK_200
305 })
306 })
307
308 it('Should not allow live if max instance lives is reached', async function () {
309 await server.config.updateCustomSubConfig({
310 newConfig: {
311 live: {
312 enabled: true,
313 maxInstanceLives: 1
314 }
315 }
316 })
317
318 await makePostBodyRequest({
319 url: server.url,
320 path,
321 token: server.accessToken,
322 fields: baseCorrectParams,
323 expectedStatus: HttpStatusCode.FORBIDDEN_403
324 })
325 })
326
327 it('Should not allow live if max user lives is reached', async function () {
328 await server.config.updateCustomSubConfig({
329 newConfig: {
330 live: {
331 enabled: true,
332 maxInstanceLives: 20,
333 maxUserLives: 1
334 }
335 }
336 })
337
338 await makePostBodyRequest({
339 url: server.url,
340 path,
341 token: server.accessToken,
342 fields: baseCorrectParams,
343 expectedStatus: HttpStatusCode.FORBIDDEN_403
344 })
345 })
346 })
347
348 describe('When getting live information', function () {
349
350 it('Should fail with a bad access token', async function () {
351 await command.get({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
352 })
353
354 it('Should not display private information without access token', async function () {
355 const live = await command.get({ token: '', videoId: video.id })
356
357 expect(live.rtmpUrl).to.not.exist
358 expect(live.streamKey).to.not.exist
359 expect(live.latencyMode).to.exist
360 })
361
362 it('Should not display private information with token of another user', async function () {
363 const live = await command.get({ token: userAccessToken, videoId: video.id })
364
365 expect(live.rtmpUrl).to.not.exist
366 expect(live.streamKey).to.not.exist
367 expect(live.latencyMode).to.exist
368 })
369
370 it('Should display private information with appropriate token', async function () {
371 const live = await command.get({ videoId: video.id })
372
373 expect(live.rtmpUrl).to.exist
374 expect(live.streamKey).to.exist
375 expect(live.latencyMode).to.exist
376 })
377
378 it('Should fail with a bad video id', async function () {
379 await command.get({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
380 })
381
382 it('Should fail with an unknown video id', async function () {
383 await command.get({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
384 })
385
386 it('Should fail with a non live video', async function () {
387 await command.get({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
388 })
389
390 it('Should succeed with the correct params', async function () {
391 await command.get({ videoId: video.id })
392 await command.get({ videoId: video.uuid })
393 await command.get({ videoId: video.shortUUID })
394 })
395 })
396
397 describe('When getting live sessions', function () {
398
399 it('Should fail with a bad access token', async function () {
400 await command.listSessions({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
401 })
402
403 it('Should fail without token', async function () {
404 await command.listSessions({ token: null, videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
405 })
406
407 it('Should fail with the token of another user', async function () {
408 await command.listSessions({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
409 })
410
411 it('Should fail with a bad video id', async function () {
412 await command.listSessions({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
413 })
414
415 it('Should fail with an unknown video id', async function () {
416 await command.listSessions({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
417 })
418
419 it('Should fail with a non live video', async function () {
420 await command.listSessions({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
421 })
422
423 it('Should succeed with the correct params', async function () {
424 await command.listSessions({ videoId: video.id })
425 })
426 })
427
428 describe('When getting live session of a replay', function () {
429
430 it('Should fail with a bad video id', async function () {
431 await command.getReplaySession({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
432 })
433
434 it('Should fail with an unknown video id', async function () {
435 await command.getReplaySession({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
436 })
437
438 it('Should fail with a non replay video', async function () {
439 await command.getReplaySession({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
440 })
441 })
442
443 describe('When updating live information', async function () {
444
445 it('Should fail without access token', async function () {
446 await command.update({ token: '', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
447 })
448
449 it('Should fail with a bad access token', async function () {
450 await command.update({ token: 'toto', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
451 })
452
453 it('Should fail with access token of another user', async function () {
454 await command.update({ token: userAccessToken, videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
455 })
456
457 it('Should fail with a bad video id', async function () {
458 await command.update({ videoId: 'toto', fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
459 })
460
461 it('Should fail with an unknown video id', async function () {
462 await command.update({ videoId: 454555, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
463 })
464
465 it('Should fail with a non live video', async function () {
466 await command.update({ videoId: videoIdNotLive, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
467 })
468
469 it('Should fail with bad latency setting', async function () {
470 const fields = { latencyMode: 42 as any }
471
472 await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
473 })
474
475 it('Should fail with a bad privacy for replay settings', async function () {
476 const fields = { saveReplay: true, replaySettings: { privacy: 999 as any } }
477
478 await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
479 })
480
481 it('Should fail with save replay enabled but without replay settings', async function () {
482 await server.config.updateCustomSubConfig({
483 newConfig: {
484 live: {
485 enabled: true,
486 allowReplay: true
487 }
488 }
489 })
490
491 const fields = { saveReplay: true }
492
493 await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
494 })
495
496 it('Should fail with save replay disabled and replay settings', async function () {
497 const fields = { saveReplay: false, replaySettings: { privacy: VideoPrivacy.INTERNAL } }
498
499 await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
500 })
501
502 it('Should fail with only replay settings when save replay is disabled', async function () {
503 const fields = { replaySettings: { privacy: VideoPrivacy.INTERNAL } }
504
505 await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
506 })
507
508 it('Should fail to set latency if the server does not allow it', async function () {
509 const fields = { latencyMode: LiveVideoLatencyMode.HIGH_LATENCY }
510
511 await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
512 })
513
514 it('Should succeed with the correct params', async function () {
515 await command.update({ videoId: video.id, fields: { saveReplay: false } })
516 await command.update({ videoId: video.uuid, fields: { saveReplay: false } })
517 await command.update({ videoId: video.shortUUID, fields: { saveReplay: false } })
518
519 await command.update({ videoId: video.id, fields: { saveReplay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } } })
520
521 })
522
523 it('Should fail to update replay status if replay is not allowed on the instance', async function () {
524 await server.config.updateCustomSubConfig({
525 newConfig: {
526 live: {
527 enabled: true,
528 allowReplay: false
529 }
530 }
531 })
532
533 await command.update({ videoId: video.id, fields: { saveReplay: true }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
534 })
535
536 it('Should fail to update a live if it has already started', async function () {
537 this.timeout(40000)
538
539 const live = await command.get({ videoId: video.id })
540
541 const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
542
543 await command.waitUntilPublished({ videoId: video.id })
544 await command.update({ videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
545
546 await stopFfmpeg(ffmpegCommand)
547 })
548
549 it('Should fail to change live privacy if it has already started', async function () {
550 this.timeout(40000)
551
552 const live = await command.get({ videoId: video.id })
553
554 const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
555
556 await command.waitUntilPublished({ videoId: video.id })
557
558 await server.videos.update({
559 id: video.id,
560 attributes: { privacy: VideoPrivacy.PUBLIC } // Same privacy, it's fine
561 })
562
563 await server.videos.update({
564 id: video.id,
565 attributes: { privacy: VideoPrivacy.UNLISTED },
566 expectedStatus: HttpStatusCode.BAD_REQUEST_400
567 })
568
569 await stopFfmpeg(ffmpegCommand)
570 })
571
572 it('Should fail to stream twice in the save live', async function () {
573 this.timeout(40000)
574
575 const live = await command.get({ videoId: video.id })
576
577 const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
578
579 await command.waitUntilPublished({ videoId: video.id })
580
581 await command.runAndTestStreamError({ videoId: video.id, shouldHaveError: true })
582
583 await stopFfmpeg(ffmpegCommand)
584 })
585 })
586
587 after(async function () {
588 await cleanupTests([ server ])
589 })
590})