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