]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/check-params/live.ts
Introduce live command
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / live.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import { omit } from 'lodash'
5 import { VideoCreateResult, VideoPrivacy } from '@shared/models'
6 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
7 import {
8 buildAbsoluteFixturePath,
9 cleanupTests,
10 createUser,
11 flushAndRunServer,
12 getMyUserInformation,
13 immutableAssign,
14 LiveCommand,
15 makePostBodyRequest,
16 makeUploadRequest,
17 sendRTMPStream,
18 ServerInfo,
19 setAccessTokensToServers,
20 stopFfmpeg,
21 uploadVideoAndGetId,
22 userLogin
23 } from '../../../../shared/extra-utils'
24
25 describe('Test video lives API validator', function () {
26 const path = '/api/v1/videos/live'
27 let server: ServerInfo
28 let userAccessToken = ''
29 let channelId: number
30 let video: VideoCreateResult
31 let videoIdNotLive: number
32 let command: LiveCommand
33
34 // ---------------------------------------------------------------
35
36 before(async function () {
37 this.timeout(30000)
38
39 server = await flushAndRunServer(1)
40
41 await setAccessTokensToServers([ server ])
42
43 await server.configCommand.updateCustomSubConfig({
44 newConfig: {
45 live: {
46 enabled: true,
47 maxInstanceLives: 20,
48 maxUserLives: 20,
49 allowReplay: true
50 }
51 }
52 })
53
54 const username = 'user1'
55 const password = 'my super password'
56 await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
57 userAccessToken = await userLogin(server, { username, password })
58
59 {
60 const res = await getMyUserInformation(server.url, server.accessToken)
61 channelId = res.body.videoChannels[0].id
62 }
63
64 {
65 videoIdNotLive = (await uploadVideoAndGetId({ server, videoName: 'not live' })).id
66 }
67
68 command = server.liveCommand
69 })
70
71 describe('When creating a live', function () {
72 let baseCorrectParams
73
74 before(function () {
75 baseCorrectParams = {
76 name: 'my super name',
77 category: 5,
78 licence: 1,
79 language: 'pt',
80 nsfw: false,
81 commentsEnabled: true,
82 downloadEnabled: true,
83 waitTranscoding: true,
84 description: 'my super description',
85 support: 'my super support text',
86 tags: [ 'tag1', 'tag2' ],
87 privacy: VideoPrivacy.PUBLIC,
88 channelId,
89 saveReplay: false,
90 permanentLive: false
91 }
92 })
93
94 it('Should fail with nothing', async function () {
95 const fields = {}
96 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
97 })
98
99 it('Should fail with a long name', async function () {
100 const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(65) })
101
102 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
103 })
104
105 it('Should fail with a bad category', async function () {
106 const fields = immutableAssign(baseCorrectParams, { category: 125 })
107
108 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
109 })
110
111 it('Should fail with a bad licence', async function () {
112 const fields = immutableAssign(baseCorrectParams, { licence: 125 })
113
114 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
115 })
116
117 it('Should fail with a bad language', async function () {
118 const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) })
119
120 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
121 })
122
123 it('Should fail with a long description', async function () {
124 const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) })
125
126 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
127 })
128
129 it('Should fail with a long support text', async function () {
130 const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) })
131
132 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
133 })
134
135 it('Should fail without a channel', async function () {
136 const fields = omit(baseCorrectParams, 'channelId')
137
138 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
139 })
140
141 it('Should fail with a bad channel', async function () {
142 const fields = immutableAssign(baseCorrectParams, { channelId: 545454 })
143
144 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
145 })
146
147 it('Should fail with another user channel', async function () {
148 const user = {
149 username: 'fake',
150 password: 'fake_password'
151 }
152 await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
153
154 const accessTokenUser = await userLogin(server, user)
155 const res = await getMyUserInformation(server.url, accessTokenUser)
156 const customChannelId = res.body.videoChannels[0].id
157
158 const fields = immutableAssign(baseCorrectParams, { channelId: customChannelId })
159
160 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
161 })
162
163 it('Should fail with too many tags', async function () {
164 const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] })
165
166 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
167 })
168
169 it('Should fail with a tag length too low', async function () {
170 const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 't' ] })
171
172 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
173 })
174
175 it('Should fail with a tag length too big', async function () {
176 const fields = immutableAssign(baseCorrectParams, { tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] })
177
178 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
179 })
180
181 it('Should fail with an incorrect thumbnail file', async function () {
182 const fields = baseCorrectParams
183 const attaches = {
184 thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
185 }
186
187 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
188 })
189
190 it('Should fail with a big thumbnail file', async function () {
191 const fields = baseCorrectParams
192 const attaches = {
193 thumbnailfile: buildAbsoluteFixturePath('preview-big.png')
194 }
195
196 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
197 })
198
199 it('Should fail with an incorrect preview file', async function () {
200 const fields = baseCorrectParams
201 const attaches = {
202 previewfile: buildAbsoluteFixturePath('video_short.mp4')
203 }
204
205 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
206 })
207
208 it('Should fail with a big preview file', async function () {
209 const fields = baseCorrectParams
210 const attaches = {
211 previewfile: buildAbsoluteFixturePath('preview-big.png')
212 }
213
214 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
215 })
216
217 it('Should fail with save replay and permanent live set to true', async function () {
218 const fields = immutableAssign(baseCorrectParams, { saveReplay: true, permanentLive: true })
219
220 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
221 })
222
223 it('Should succeed with the correct parameters', async function () {
224 this.timeout(30000)
225
226 const res = await makePostBodyRequest({
227 url: server.url,
228 path,
229 token: server.accessToken,
230 fields: baseCorrectParams,
231 statusCodeExpected: HttpStatusCode.OK_200
232 })
233
234 video = res.body.video
235 })
236
237 it('Should forbid if live is disabled', async function () {
238 await server.configCommand.updateCustomSubConfig({
239 newConfig: {
240 live: {
241 enabled: false
242 }
243 }
244 })
245
246 await makePostBodyRequest({
247 url: server.url,
248 path,
249 token: server.accessToken,
250 fields: baseCorrectParams,
251 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
252 })
253 })
254
255 it('Should forbid to save replay if not enabled by the admin', async function () {
256 const fields = immutableAssign(baseCorrectParams, { saveReplay: true })
257
258 await server.configCommand.updateCustomSubConfig({
259 newConfig: {
260 live: {
261 enabled: true,
262 allowReplay: false
263 }
264 }
265 })
266
267 await makePostBodyRequest({
268 url: server.url,
269 path,
270 token: server.accessToken,
271 fields,
272 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
273 })
274 })
275
276 it('Should allow to save replay if enabled by the admin', async function () {
277 const fields = immutableAssign(baseCorrectParams, { saveReplay: true })
278
279 await server.configCommand.updateCustomSubConfig({
280 newConfig: {
281 live: {
282 enabled: true,
283 allowReplay: true
284 }
285 }
286 })
287
288 await makePostBodyRequest({
289 url: server.url,
290 path,
291 token: server.accessToken,
292 fields,
293 statusCodeExpected: HttpStatusCode.OK_200
294 })
295 })
296
297 it('Should not allow live if max instance lives is reached', async function () {
298 await server.configCommand.updateCustomSubConfig({
299 newConfig: {
300 live: {
301 enabled: true,
302 maxInstanceLives: 1
303 }
304 }
305 })
306
307 await makePostBodyRequest({
308 url: server.url,
309 path,
310 token: server.accessToken,
311 fields: baseCorrectParams,
312 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
313 })
314 })
315
316 it('Should not allow live if max user lives is reached', async function () {
317 await server.configCommand.updateCustomSubConfig({
318 newConfig: {
319 live: {
320 enabled: true,
321 maxInstanceLives: 20,
322 maxUserLives: 1
323 }
324 }
325 })
326
327 await makePostBodyRequest({
328 url: server.url,
329 path,
330 token: server.accessToken,
331 fields: baseCorrectParams,
332 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
333 })
334 })
335 })
336
337 describe('When getting live information', function () {
338
339 it('Should fail without access token', async function () {
340 await command.getLive({ token: '', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
341 })
342
343 it('Should fail with a bad access token', async function () {
344 await command.getLive({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
345 })
346
347 it('Should fail with access token of another user', async function () {
348 await command.getLive({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
349 })
350
351 it('Should fail with a bad video id', async function () {
352 await command.getLive({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
353 })
354
355 it('Should fail with an unknown video id', async function () {
356 await command.getLive({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
357 })
358
359 it('Should fail with a non live video', async function () {
360 await command.getLive({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
361 })
362
363 it('Should succeed with the correct params', async function () {
364 await command.getLive({ videoId: video.id })
365 await command.getLive({ videoId: video.uuid })
366 await command.getLive({ videoId: video.shortUUID })
367 })
368 })
369
370 describe('When updating live information', async function () {
371
372 it('Should fail without access token', async function () {
373 await command.updateLive({ token: '', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
374 })
375
376 it('Should fail with a bad access token', async function () {
377 await command.updateLive({ token: 'toto', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
378 })
379
380 it('Should fail with access token of another user', async function () {
381 await command.updateLive({ token: userAccessToken, videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
382 })
383
384 it('Should fail with a bad video id', async function () {
385 await command.updateLive({ videoId: 'toto', fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
386 })
387
388 it('Should fail with an unknown video id', async function () {
389 await command.updateLive({ videoId: 454555, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
390 })
391
392 it('Should fail with a non live video', async function () {
393 await command.updateLive({ videoId: videoIdNotLive, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
394 })
395
396 it('Should fail with save replay and permanent live set to true', async function () {
397 const fields = { saveReplay: true, permanentLive: true }
398
399 await command.updateLive({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
400 })
401
402 it('Should succeed with the correct params', async function () {
403 await command.updateLive({ videoId: video.id, fields: { saveReplay: false } })
404 await command.updateLive({ videoId: video.uuid, fields: { saveReplay: false } })
405 await command.updateLive({ videoId: video.shortUUID, fields: { saveReplay: false } })
406 })
407
408 it('Should fail to update replay status if replay is not allowed on the instance', async function () {
409 await server.configCommand.updateCustomSubConfig({
410 newConfig: {
411 live: {
412 enabled: true,
413 allowReplay: false
414 }
415 }
416 })
417
418 await command.updateLive({ videoId: video.id, fields: { saveReplay: true }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
419 })
420
421 it('Should fail to update a live if it has already started', async function () {
422 this.timeout(40000)
423
424 const live = await command.getLive({ videoId: video.id })
425
426 const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
427
428 await command.waitUntilLivePublished({ videoId: video.id })
429 await command.updateLive({ videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
430
431 await stopFfmpeg(ffmpegCommand)
432 })
433
434 it('Should fail to stream twice in the save live', async function () {
435 this.timeout(40000)
436
437 const live = await command.getLive({ videoId: video.id })
438
439 const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
440
441 await command.waitUntilLivePublished({ videoId: video.id })
442
443 await command.runAndTestFfmpegStreamError({ videoId: video.id, shouldHaveError: true })
444
445 await stopFfmpeg(ffmpegCommand)
446 })
447 })
448
449 after(async function () {
450 await cleanupTests([ server ])
451 })
452 })