]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/check-params/live.ts
Introduce live command
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / live.ts
CommitLineData
77e9f859
C
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
77e9f859 4import { omit } from 'lodash'
4f219914 5import { VideoCreateResult, VideoPrivacy } from '@shared/models'
3d470a53 6import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
77e9f859 7import {
3d470a53 8 buildAbsoluteFixturePath,
77e9f859
C
9 cleanupTests,
10 createUser,
11 flushAndRunServer,
77e9f859
C
12 getMyUserInformation,
13 immutableAssign,
4f219914 14 LiveCommand,
77e9f859
C
15 makePostBodyRequest,
16 makeUploadRequest,
17 sendRTMPStream,
18 ServerInfo,
19 setAccessTokensToServers,
20 stopFfmpeg,
77e9f859 21 uploadVideoAndGetId,
4f219914 22 userLogin
77e9f859
C
23} from '../../../../shared/extra-utils'
24
25describe('Test video lives API validator', function () {
26 const path = '/api/v1/videos/live'
27 let server: ServerInfo
28 let userAccessToken = ''
77e9f859 29 let channelId: number
d4a8e7a6 30 let video: VideoCreateResult
77e9f859 31 let videoIdNotLive: number
4f219914 32 let command: LiveCommand
77e9f859
C
33
34 // ---------------------------------------------------------------
35
36 before(async function () {
37 this.timeout(30000)
38
39 server = await flushAndRunServer(1)
40
41 await setAccessTokensToServers([ server ])
42
65e6e260
C
43 await server.configCommand.updateCustomSubConfig({
44 newConfig: {
45 live: {
46 enabled: true,
47 maxInstanceLives: 20,
48 maxUserLives: 20,
49 allowReplay: true
50 }
77e9f859
C
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 }
4f219914
C
67
68 command = server.liveCommand
77e9f859
C
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,
bb4ba6d9
C
89 saveReplay: false,
90 permanentLive: false
77e9f859
C
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 = {
3d470a53 184 thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
77e9f859
C
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 = {
3d470a53 193 thumbnailfile: buildAbsoluteFixturePath('preview-big.png')
77e9f859
C
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 = {
3d470a53 202 previewfile: buildAbsoluteFixturePath('video_short.mp4')
77e9f859
C
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 = {
3d470a53 211 previewfile: buildAbsoluteFixturePath('preview-big.png')
77e9f859
C
212 }
213
214 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
215 })
216
bb4ba6d9
C
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
77e9f859
C
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,
2d53be02 231 statusCodeExpected: HttpStatusCode.OK_200
77e9f859
C
232 })
233
d4a8e7a6 234 video = res.body.video
77e9f859
C
235 })
236
237 it('Should forbid if live is disabled', async function () {
65e6e260
C
238 await server.configCommand.updateCustomSubConfig({
239 newConfig: {
240 live: {
241 enabled: false
242 }
77e9f859
C
243 }
244 })
245
246 await makePostBodyRequest({
247 url: server.url,
248 path,
249 token: server.accessToken,
250 fields: baseCorrectParams,
2d53be02 251 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
77e9f859
C
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
65e6e260
C
258 await server.configCommand.updateCustomSubConfig({
259 newConfig: {
260 live: {
261 enabled: true,
262 allowReplay: false
263 }
77e9f859
C
264 }
265 })
266
267 await makePostBodyRequest({
268 url: server.url,
269 path,
270 token: server.accessToken,
271 fields,
2d53be02 272 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
77e9f859
C
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
65e6e260
C
279 await server.configCommand.updateCustomSubConfig({
280 newConfig: {
281 live: {
282 enabled: true,
283 allowReplay: true
284 }
77e9f859
C
285 }
286 })
287
288 await makePostBodyRequest({
289 url: server.url,
290 path,
291 token: server.accessToken,
292 fields,
2d53be02 293 statusCodeExpected: HttpStatusCode.OK_200
77e9f859
C
294 })
295 })
296
297 it('Should not allow live if max instance lives is reached', async function () {
65e6e260
C
298 await server.configCommand.updateCustomSubConfig({
299 newConfig: {
300 live: {
301 enabled: true,
302 maxInstanceLives: 1
303 }
77e9f859
C
304 }
305 })
306
307 await makePostBodyRequest({
308 url: server.url,
309 path,
310 token: server.accessToken,
311 fields: baseCorrectParams,
2d53be02 312 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
77e9f859
C
313 })
314 })
315
316 it('Should not allow live if max user lives is reached', async function () {
65e6e260
C
317 await server.configCommand.updateCustomSubConfig({
318 newConfig: {
319 live: {
320 enabled: true,
321 maxInstanceLives: 20,
322 maxUserLives: 1
323 }
77e9f859
C
324 }
325 })
326
327 await makePostBodyRequest({
328 url: server.url,
329 path,
330 token: server.accessToken,
331 fields: baseCorrectParams,
2d53be02 332 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
77e9f859
C
333 })
334 })
335 })
336
337 describe('When getting live information', function () {
338
339 it('Should fail without access token', async function () {
4f219914 340 await command.getLive({ token: '', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
77e9f859
C
341 })
342
343 it('Should fail with a bad access token', async function () {
4f219914 344 await command.getLive({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
77e9f859
C
345 })
346
347 it('Should fail with access token of another user', async function () {
4f219914 348 await command.getLive({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
77e9f859
C
349 })
350
351 it('Should fail with a bad video id', async function () {
4f219914 352 await command.getLive({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
77e9f859
C
353 })
354
355 it('Should fail with an unknown video id', async function () {
4f219914 356 await command.getLive({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
77e9f859
C
357 })
358
359 it('Should fail with a non live video', async function () {
4f219914 360 await command.getLive({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
77e9f859
C
361 })
362
363 it('Should succeed with the correct params', async function () {
4f219914
C
364 await command.getLive({ videoId: video.id })
365 await command.getLive({ videoId: video.uuid })
366 await command.getLive({ videoId: video.shortUUID })
77e9f859
C
367 })
368 })
369
370 describe('When updating live information', async function () {
371
372 it('Should fail without access token', async function () {
4f219914 373 await command.updateLive({ token: '', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
77e9f859
C
374 })
375
376 it('Should fail with a bad access token', async function () {
4f219914 377 await command.updateLive({ token: 'toto', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
77e9f859
C
378 })
379
380 it('Should fail with access token of another user', async function () {
4f219914 381 await command.updateLive({ token: userAccessToken, videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
77e9f859
C
382 })
383
384 it('Should fail with a bad video id', async function () {
4f219914 385 await command.updateLive({ videoId: 'toto', fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
77e9f859
C
386 })
387
388 it('Should fail with an unknown video id', async function () {
4f219914 389 await command.updateLive({ videoId: 454555, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
77e9f859
C
390 })
391
392 it('Should fail with a non live video', async function () {
4f219914 393 await command.updateLive({ videoId: videoIdNotLive, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
77e9f859
C
394 })
395
bb4ba6d9
C
396 it('Should fail with save replay and permanent live set to true', async function () {
397 const fields = { saveReplay: true, permanentLive: true }
398
4f219914 399 await command.updateLive({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
bb4ba6d9
C
400 })
401
77e9f859 402 it('Should succeed with the correct params', async function () {
4f219914
C
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 } })
77e9f859
C
406 })
407
408 it('Should fail to update replay status if replay is not allowed on the instance', async function () {
65e6e260
C
409 await server.configCommand.updateCustomSubConfig({
410 newConfig: {
411 live: {
412 enabled: true,
413 allowReplay: false
414 }
77e9f859
C
415 }
416 })
417
4f219914 418 await command.updateLive({ videoId: video.id, fields: { saveReplay: true }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
77e9f859
C
419 })
420
421 it('Should fail to update a live if it has already started', async function () {
59fd824c 422 this.timeout(40000)
77e9f859 423
4f219914 424 const live = await command.getLive({ videoId: video.id })
77e9f859 425
4f219914 426 const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
77e9f859 427
4f219914
C
428 await command.waitUntilLivePublished({ videoId: video.id })
429 await command.updateLive({ videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
77e9f859 430
4f219914 431 await stopFfmpeg(ffmpegCommand)
77e9f859 432 })
97969c4e
C
433
434 it('Should fail to stream twice in the save live', async function () {
59fd824c 435 this.timeout(40000)
97969c4e 436
4f219914 437 const live = await command.getLive({ videoId: video.id })
97969c4e 438
4f219914 439 const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
97969c4e 440
4f219914 441 await command.waitUntilLivePublished({ videoId: video.id })
97969c4e 442
4f219914 443 await command.runAndTestFfmpegStreamError({ videoId: video.id, shouldHaveError: true })
97969c4e 444
4f219914 445 await stopFfmpeg(ffmpegCommand)
97969c4e 446 })
77e9f859
C
447 })
448
449 after(async function () {
450 await cleanupTests([ server ])
451 })
452})