1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import { omit } from 'lodash'
5 import { HttpStatusCode } from '@shared/models'
7 buildAbsoluteFixturePath,
15 setAccessTokensToServers,
17 } from '@shared/extra-utils'
18 import { VideoCreateResult, VideoPrivacy } from '@shared/models'
20 describe('Test video lives API validator', function () {
21 const path = '/api/v1/videos/live'
22 let server: PeerTubeServer
23 let userAccessToken = ''
25 let video: VideoCreateResult
26 let videoIdNotLive: number
27 let command: LiveCommand
29 // ---------------------------------------------------------------
31 before(async function () {
34 server = await createSingleServer(1)
36 await setAccessTokensToServers([ server ])
38 await server.config.updateCustomSubConfig({
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 })
55 const { videoChannels } = await server.users.getMyInfo()
56 channelId = videoChannels[0].id
60 videoIdNotLive = (await server.videos.quickUpload({ name: 'not live' })).id
66 describe('When creating a live', function () {
71 name: 'my super name',
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,
89 it('Should fail with nothing', async function () {
91 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
94 it('Should fail with a long name', async function () {
95 const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
97 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
100 it('Should fail with a bad category', async function () {
101 const fields = { ...baseCorrectParams, category: 125 }
103 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
106 it('Should fail with a bad licence', async function () {
107 const fields = { ...baseCorrectParams, licence: 125 }
109 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
112 it('Should fail with a bad language', async function () {
113 const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
115 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
118 it('Should fail with a long description', async function () {
119 const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
121 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
124 it('Should fail with a long support text', async function () {
125 const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
127 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
130 it('Should fail without a channel', async function () {
131 const fields = omit(baseCorrectParams, 'channelId')
133 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
136 it('Should fail with a bad channel', async function () {
137 const fields = { ...baseCorrectParams, channelId: 545454 }
139 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
142 it('Should fail with another user channel', async function () {
145 password: 'fake_password'
147 await server.users.create({ username: user.username, password: user.password })
149 const accessTokenUser = await server.login.getAccessToken(user)
150 const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
151 const customChannelId = videoChannels[0].id
153 const fields = { ...baseCorrectParams, channelId: customChannelId }
155 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
158 it('Should fail with too many tags', async function () {
159 const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
161 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
164 it('Should fail with a tag length too low', async function () {
165 const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
167 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
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' ] }
173 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
176 it('Should fail with an incorrect thumbnail file', async function () {
177 const fields = baseCorrectParams
179 thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
182 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
185 it('Should fail with a big thumbnail file', async function () {
186 const fields = baseCorrectParams
188 thumbnailfile: buildAbsoluteFixturePath('preview-big.png')
191 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
194 it('Should fail with an incorrect preview file', async function () {
195 const fields = baseCorrectParams
197 previewfile: buildAbsoluteFixturePath('video_short.mp4')
200 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
203 it('Should fail with a big preview file', async function () {
204 const fields = baseCorrectParams
206 previewfile: buildAbsoluteFixturePath('preview-big.png')
209 await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
212 it('Should fail with save replay and permanent live set to true', async function () {
213 const fields = { ...baseCorrectParams, saveReplay: true, permanentLive: true }
215 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
218 it('Should succeed with the correct parameters', async function () {
221 const res = await makePostBodyRequest({
224 token: server.accessToken,
225 fields: baseCorrectParams,
226 expectedStatus: HttpStatusCode.OK_200
229 video = res.body.video
232 it('Should forbid if live is disabled', async function () {
233 await server.config.updateCustomSubConfig({
241 await makePostBodyRequest({
244 token: server.accessToken,
245 fields: baseCorrectParams,
246 expectedStatus: HttpStatusCode.FORBIDDEN_403
250 it('Should forbid to save replay if not enabled by the admin', async function () {
251 const fields = { ...baseCorrectParams, saveReplay: true }
253 await server.config.updateCustomSubConfig({
262 await makePostBodyRequest({
265 token: server.accessToken,
267 expectedStatus: HttpStatusCode.FORBIDDEN_403
271 it('Should allow to save replay if enabled by the admin', async function () {
272 const fields = { ...baseCorrectParams, saveReplay: true }
274 await server.config.updateCustomSubConfig({
283 await makePostBodyRequest({
286 token: server.accessToken,
288 expectedStatus: HttpStatusCode.OK_200
292 it('Should not allow live if max instance lives is reached', async function () {
293 await server.config.updateCustomSubConfig({
302 await makePostBodyRequest({
305 token: server.accessToken,
306 fields: baseCorrectParams,
307 expectedStatus: HttpStatusCode.FORBIDDEN_403
311 it('Should not allow live if max user lives is reached', async function () {
312 await server.config.updateCustomSubConfig({
316 maxInstanceLives: 20,
322 await makePostBodyRequest({
325 token: server.accessToken,
326 fields: baseCorrectParams,
327 expectedStatus: HttpStatusCode.FORBIDDEN_403
332 describe('When getting live information', function () {
334 it('Should fail without access token', async function () {
335 await command.get({ token: '', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
338 it('Should fail with a bad access token', async function () {
339 await command.get({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
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 })
346 it('Should fail with a bad video id', async function () {
347 await command.get({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
350 it('Should fail with an unknown video id', async function () {
351 await command.get({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
354 it('Should fail with a non live video', async function () {
355 await command.get({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
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 })
365 describe('When updating live information', async function () {
367 it('Should fail without access token', async function () {
368 await command.update({ token: '', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
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 })
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 })
379 it('Should fail with a bad video id', async function () {
380 await command.update({ videoId: 'toto', fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
383 it('Should fail with an unknown video id', async function () {
384 await command.update({ videoId: 454555, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
387 it('Should fail with a non live video', async function () {
388 await command.update({ videoId: videoIdNotLive, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
391 it('Should fail with save replay and permanent live set to true', async function () {
392 const fields = { saveReplay: true, permanentLive: true }
394 await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
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 } })
403 it('Should fail to update replay status if replay is not allowed on the instance', async function () {
404 await server.config.updateCustomSubConfig({
413 await command.update({ videoId: video.id, fields: { saveReplay: true }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
416 it('Should fail to update a live if it has already started', async function () {
419 const live = await command.get({ videoId: video.id })
421 const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
423 await command.waitUntilPublished({ videoId: video.id })
424 await command.update({ videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
426 await stopFfmpeg(ffmpegCommand)
429 it('Should fail to stream twice in the save live', async function () {
432 const live = await command.get({ videoId: video.id })
434 const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
436 await command.waitUntilPublished({ videoId: video.id })
438 await command.runAndTestStreamError({ videoId: video.id, shouldHaveError: true })
440 await stopFfmpeg(ffmpegCommand)
444 after(async function () {
445 await cleanupTests([ server ])