1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import { HttpStatusCode, VideoEditorTask } from '@shared/models'
9 setAccessTokensToServers,
12 } from '@shared/server-commands'
14 describe('Test video editor API validator', function () {
15 let server: PeerTubeServer
16 let command: VideoEditorCommand
17 let userAccessToken: string
20 // ---------------------------------------------------------------
22 before(async function () {
25 server = await createSingleServer(1)
27 await setAccessTokensToServers([ server ])
28 userAccessToken = await server.users.generateUserAndToken('user1')
30 await server.config.enableMinimumTranscoding()
32 const { uuid } = await server.videos.quickUpload({ name: 'video' })
35 command = server.videoEditor
37 await waitJobs([ server ])
40 describe('Task creation', function () {
42 describe('Config settings', function () {
44 it('Should fail if editor is disabled', async function () {
45 await server.config.updateExistingSubConfig({
53 await command.createEditionTasks({
55 tasks: VideoEditorCommand.getComplexTask(),
56 expectedStatus: HttpStatusCode.BAD_REQUEST_400
60 it('Should fail to enable editor if transcoding is disabled', async function () {
61 await server.config.updateExistingSubConfig({
70 expectedStatus: HttpStatusCode.BAD_REQUEST_400
74 it('Should succeed to enable video editor', async function () {
75 await server.config.updateExistingSubConfig({
88 describe('Common tasks', function () {
90 it('Should fail without token', async function () {
91 await command.createEditionTasks({
94 tasks: VideoEditorCommand.getComplexTask(),
95 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
99 it('Should fail with another user token', async function () {
100 await command.createEditionTasks({
101 token: userAccessToken,
103 tasks: VideoEditorCommand.getComplexTask(),
104 expectedStatus: HttpStatusCode.FORBIDDEN_403
108 it('Should fail with an invalid video', async function () {
109 await command.createEditionTasks({
111 tasks: VideoEditorCommand.getComplexTask(),
112 expectedStatus: HttpStatusCode.BAD_REQUEST_400
116 it('Should fail with an unknown video', async function () {
117 await command.createEditionTasks({
119 tasks: VideoEditorCommand.getComplexTask(),
120 expectedStatus: HttpStatusCode.NOT_FOUND_404
124 it('Should fail with an already in transcoding state video', async function () {
125 const { uuid } = await server.videos.quickUpload({ name: 'transcoded video' })
127 await server.jobs.pauseJobQueue()
128 await server.videos.runTranscoding({ videoId: uuid, transcodingType: 'hls' })
130 await command.createEditionTasks({
132 tasks: VideoEditorCommand.getComplexTask(),
133 expectedStatus: HttpStatusCode.CONFLICT_409
136 await server.jobs.resumeJobQueue()
139 it('Should fail with a bad complex task', async function () {
140 await command.createEditionTasks({
158 expectedStatus: HttpStatusCode.BAD_REQUEST_400
162 it('Should fail without task', async function () {
163 await command.createEditionTasks({
166 expectedStatus: HttpStatusCode.BAD_REQUEST_400
170 it('Should fail with too many tasks', async function () {
171 const tasks: VideoEditorTask[] = []
173 for (let i = 0; i < 110; i++) {
182 await command.createEditionTasks({
185 expectedStatus: HttpStatusCode.BAD_REQUEST_400
189 it('Should succeed with correct parameters', async function () {
190 await server.jobs.pauseJobQueue()
192 await command.createEditionTasks({
194 tasks: VideoEditorCommand.getComplexTask(),
195 expectedStatus: HttpStatusCode.NO_CONTENT_204
199 it('Should fail with a video that is already waiting for edition', async function () {
202 await command.createEditionTasks({
204 tasks: VideoEditorCommand.getComplexTask(),
205 expectedStatus: HttpStatusCode.CONFLICT_409
208 await server.jobs.resumeJobQueue()
210 await waitJobs([ server ])
214 describe('Cut task', function () {
216 async function cut (start: number, end: number, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
217 await command.createEditionTasks({
232 it('Should fail with bad start/end', async function () {
239 for (const value of invalid) {
240 await cut(value as any, undefined)
241 await cut(undefined, value as any)
245 it('Should fail with the same start/end', async function () {
249 it('Should fail with inconsistents start/end', async function () {
253 it('Should fail without start and end', async function () {
254 await cut(undefined, undefined)
257 it('Should succeed with the correct params', async function () {
260 await cut(0, 2, HttpStatusCode.NO_CONTENT_204)
262 await waitJobs([ server ])
266 describe('Watermark task', function () {
268 async function addWatermark (file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
269 await command.createEditionTasks({
273 name: 'add-watermark',
283 it('Should fail without waterkmark', async function () {
284 await addWatermark(undefined)
287 it('Should fail with an invalid watermark', async function () {
288 await addWatermark('video_short.mp4')
291 it('Should succeed with the correct params', async function () {
294 await addWatermark('thumbnail.jpg', HttpStatusCode.NO_CONTENT_204)
296 await waitJobs([ server ])
300 describe('Intro/Outro task', function () {
302 async function addIntroOutro (type: 'add-intro' | 'add-outro', file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
303 await command.createEditionTasks({
317 it('Should fail without file', async function () {
318 await addIntroOutro('add-intro', undefined)
319 await addIntroOutro('add-outro', undefined)
322 it('Should fail with an invalid file', async function () {
323 await addIntroOutro('add-intro', 'thumbnail.jpg')
324 await addIntroOutro('add-outro', 'thumbnail.jpg')
327 it('Should fail with a file that does not contain video stream', async function () {
328 await addIntroOutro('add-intro', 'sample.ogg')
329 await addIntroOutro('add-outro', 'sample.ogg')
333 it('Should succeed with the correct params', async function () {
336 await addIntroOutro('add-intro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
337 await waitJobs([ server ])
339 await addIntroOutro('add-outro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
340 await waitJobs([ server ])
343 it('Should check total quota when creating the task', async function () {
346 const user = await server.users.create({ username: 'user_quota_1' })
347 const token = await server.login.getAccessToken('user_quota_1')
348 const { uuid } = await server.videos.quickUpload({ token, name: 'video_quota_1', fixture: 'video_short.mp4' })
350 const addIntroOutroByUser = (type: 'add-intro' | 'add-outro', expectedStatus: HttpStatusCode) => {
351 return command.createEditionTasks({
358 file: 'video_short.mp4'
366 await waitJobs([ server ])
368 const { videoQuotaUsed } = await server.users.getMyQuotaUsed({ token })
369 await server.users.update({ userId: user.id, videoQuota: Math.round(videoQuotaUsed * 2.5) })
372 await addIntroOutroByUser('add-intro', HttpStatusCode.NO_CONTENT_204)
374 await waitJobs([ server ])
377 await addIntroOutroByUser('add-intro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
378 await addIntroOutroByUser('add-outro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
383 after(async function () {
384 await cleanupTests([ server ])