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 await server.jobs.pauseJobQueue()
127 const { uuid } = await server.videos.quickUpload({ name: 'transcoded video' })
129 await command.createEditionTasks({
131 tasks: VideoEditorCommand.getComplexTask(),
132 expectedStatus: HttpStatusCode.CONFLICT_409
135 await server.jobs.resumeJobQueue()
138 it('Should fail with a bad complex task', async function () {
139 await command.createEditionTasks({
157 expectedStatus: HttpStatusCode.BAD_REQUEST_400
161 it('Should fail without task', async function () {
162 await command.createEditionTasks({
165 expectedStatus: HttpStatusCode.BAD_REQUEST_400
169 it('Should fail with too many tasks', async function () {
170 const tasks: VideoEditorTask[] = []
172 for (let i = 0; i < 110; i++) {
181 await command.createEditionTasks({
184 expectedStatus: HttpStatusCode.BAD_REQUEST_400
188 it('Should succeed with correct parameters', async function () {
189 await server.jobs.pauseJobQueue()
191 await command.createEditionTasks({
193 tasks: VideoEditorCommand.getComplexTask(),
194 expectedStatus: HttpStatusCode.NO_CONTENT_204
198 it('Should fail with a video that is already waiting for edition', async function () {
201 await command.createEditionTasks({
203 tasks: VideoEditorCommand.getComplexTask(),
204 expectedStatus: HttpStatusCode.CONFLICT_409
207 await server.jobs.resumeJobQueue()
209 await waitJobs([ server ])
213 describe('Cut task', function () {
215 async function cut (start: number, end: number, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
216 await command.createEditionTasks({
231 it('Should fail with bad start/end', async function () {
238 for (const value of invalid) {
239 await cut(value as any, undefined)
240 await cut(undefined, value as any)
244 it('Should fail with the same start/end', async function () {
248 it('Should fail with inconsistents start/end', async function () {
252 it('Should fail without start and end', async function () {
253 await cut(undefined, undefined)
256 it('Should succeed with the correct params', async function () {
259 await cut(0, 2, HttpStatusCode.NO_CONTENT_204)
261 await waitJobs([ server ])
265 describe('Watermark task', function () {
267 async function addWatermark (file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
268 await command.createEditionTasks({
272 name: 'add-watermark',
282 it('Should fail without waterkmark', async function () {
283 await addWatermark(undefined)
286 it('Should fail with an invalid watermark', async function () {
287 await addWatermark('video_short.mp4')
290 it('Should succeed with the correct params', async function () {
293 await addWatermark('thumbnail.jpg', HttpStatusCode.NO_CONTENT_204)
295 await waitJobs([ server ])
299 describe('Intro/Outro task', function () {
301 async function addIntroOutro (type: 'add-intro' | 'add-outro', file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
302 await command.createEditionTasks({
316 it('Should fail without file', async function () {
317 await addIntroOutro('add-intro', undefined)
318 await addIntroOutro('add-outro', undefined)
321 it('Should fail with an invalid file', async function () {
322 await addIntroOutro('add-intro', 'thumbnail.jpg')
323 await addIntroOutro('add-outro', 'thumbnail.jpg')
326 it('Should fail with a file that does not contain video stream', async function () {
327 await addIntroOutro('add-intro', 'sample.ogg')
328 await addIntroOutro('add-outro', 'sample.ogg')
332 it('Should succeed with the correct params', async function () {
335 await addIntroOutro('add-intro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
336 await waitJobs([ server ])
338 await addIntroOutro('add-outro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
339 await waitJobs([ server ])
342 it('Should check total quota when creating the task', async function () {
345 const user = await server.users.create({ username: 'user_quota_1' })
346 const token = await server.login.getAccessToken('user_quota_1')
347 const { uuid } = await server.videos.quickUpload({ token, name: 'video_quota_1', fixture: 'video_short.mp4' })
349 const addIntroOutroByUser = (type: 'add-intro' | 'add-outro', expectedStatus: HttpStatusCode) => {
350 return command.createEditionTasks({
357 file: 'video_short.mp4'
365 await waitJobs([ server ])
367 const { videoQuotaUsed } = await server.users.getMyQuotaUsed({ token })
368 await server.users.update({ userId: user.id, videoQuota: Math.round(videoQuotaUsed * 2.5) })
371 await addIntroOutroByUser('add-intro', HttpStatusCode.NO_CONTENT_204)
373 await waitJobs([ server ])
376 await addIntroOutroByUser('add-intro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
377 await addIntroOutroByUser('add-outro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
382 after(async function () {
383 await cleanupTests([ server ])