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