]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/check-params/video-editor.ts
Fix torrent creation
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / video-editor.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import { HttpStatusCode, VideoEditorTask } from '@shared/models'
5 import {
6 cleanupTests,
7 createSingleServer,
8 PeerTubeServer,
9 setAccessTokensToServers,
10 VideoEditorCommand,
11 waitJobs
12 } from '@shared/server-commands'
13
14 describe('Test video editor API validator', function () {
15 let server: PeerTubeServer
16 let command: VideoEditorCommand
17 let userAccessToken: string
18 let videoUUID: string
19
20 // ---------------------------------------------------------------
21
22 before(async function () {
23 this.timeout(120_000)
24
25 server = await createSingleServer(1)
26
27 await setAccessTokensToServers([ server ])
28 userAccessToken = await server.users.generateUserAndToken('user1')
29
30 await server.config.enableMinimumTranscoding()
31
32 const { uuid } = await server.videos.quickUpload({ name: 'video' })
33 videoUUID = uuid
34
35 command = server.videoEditor
36
37 await waitJobs([ server ])
38 })
39
40 describe('Task creation', function () {
41
42 describe('Config settings', function () {
43
44 it('Should fail if editor is disabled', async function () {
45 await server.config.updateExistingSubConfig({
46 newConfig: {
47 videoEditor: {
48 enabled: false
49 }
50 }
51 })
52
53 await command.createEditionTasks({
54 videoId: videoUUID,
55 tasks: VideoEditorCommand.getComplexTask(),
56 expectedStatus: HttpStatusCode.BAD_REQUEST_400
57 })
58 })
59
60 it('Should fail to enable editor if transcoding is disabled', async function () {
61 await server.config.updateExistingSubConfig({
62 newConfig: {
63 videoEditor: {
64 enabled: true
65 },
66 transcoding: {
67 enabled: false
68 }
69 },
70 expectedStatus: HttpStatusCode.BAD_REQUEST_400
71 })
72 })
73
74 it('Should succeed to enable video editor', async function () {
75 await server.config.updateExistingSubConfig({
76 newConfig: {
77 videoEditor: {
78 enabled: true
79 },
80 transcoding: {
81 enabled: true
82 }
83 }
84 })
85 })
86 })
87
88 describe('Common tasks', function () {
89
90 it('Should fail without token', async function () {
91 await command.createEditionTasks({
92 token: null,
93 videoId: videoUUID,
94 tasks: VideoEditorCommand.getComplexTask(),
95 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
96 })
97 })
98
99 it('Should fail with another user token', async function () {
100 await command.createEditionTasks({
101 token: userAccessToken,
102 videoId: videoUUID,
103 tasks: VideoEditorCommand.getComplexTask(),
104 expectedStatus: HttpStatusCode.FORBIDDEN_403
105 })
106 })
107
108 it('Should fail with an invalid video', async function () {
109 await command.createEditionTasks({
110 videoId: 'tintin',
111 tasks: VideoEditorCommand.getComplexTask(),
112 expectedStatus: HttpStatusCode.BAD_REQUEST_400
113 })
114 })
115
116 it('Should fail with an unknown video', async function () {
117 await command.createEditionTasks({
118 videoId: 42,
119 tasks: VideoEditorCommand.getComplexTask(),
120 expectedStatus: HttpStatusCode.NOT_FOUND_404
121 })
122 })
123
124 it('Should fail with an already in transcoding state video', async function () {
125 const { uuid } = await server.videos.quickUpload({ name: 'transcoded video' })
126
127 await server.jobs.pauseJobQueue()
128 await server.videos.runTranscoding({ videoId: uuid, transcodingType: 'hls' })
129
130 await command.createEditionTasks({
131 videoId: uuid,
132 tasks: VideoEditorCommand.getComplexTask(),
133 expectedStatus: HttpStatusCode.CONFLICT_409
134 })
135
136 await server.jobs.resumeJobQueue()
137 })
138
139 it('Should fail with a bad complex task', async function () {
140 await command.createEditionTasks({
141 videoId: videoUUID,
142 tasks: [
143 {
144 name: 'cut',
145 options: {
146 start: 1,
147 end: 2
148 }
149 },
150 {
151 name: 'hadock',
152 options: {
153 start: 1,
154 end: 2
155 }
156 }
157 ] as any,
158 expectedStatus: HttpStatusCode.BAD_REQUEST_400
159 })
160 })
161
162 it('Should fail without task', async function () {
163 await command.createEditionTasks({
164 videoId: videoUUID,
165 tasks: [],
166 expectedStatus: HttpStatusCode.BAD_REQUEST_400
167 })
168 })
169
170 it('Should fail with too many tasks', async function () {
171 const tasks: VideoEditorTask[] = []
172
173 for (let i = 0; i < 110; i++) {
174 tasks.push({
175 name: 'cut',
176 options: {
177 start: 1
178 }
179 })
180 }
181
182 await command.createEditionTasks({
183 videoId: videoUUID,
184 tasks,
185 expectedStatus: HttpStatusCode.BAD_REQUEST_400
186 })
187 })
188
189 it('Should succeed with correct parameters', async function () {
190 await server.jobs.pauseJobQueue()
191
192 await command.createEditionTasks({
193 videoId: videoUUID,
194 tasks: VideoEditorCommand.getComplexTask(),
195 expectedStatus: HttpStatusCode.NO_CONTENT_204
196 })
197 })
198
199 it('Should fail with a video that is already waiting for edition', async function () {
200 this.timeout(120000)
201
202 await command.createEditionTasks({
203 videoId: videoUUID,
204 tasks: VideoEditorCommand.getComplexTask(),
205 expectedStatus: HttpStatusCode.CONFLICT_409
206 })
207
208 await server.jobs.resumeJobQueue()
209
210 await waitJobs([ server ])
211 })
212 })
213
214 describe('Cut task', function () {
215
216 async function cut (start: number, end: number, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
217 await command.createEditionTasks({
218 videoId: videoUUID,
219 tasks: [
220 {
221 name: 'cut',
222 options: {
223 start,
224 end
225 }
226 }
227 ],
228 expectedStatus
229 })
230 }
231
232 it('Should fail with bad start/end', async function () {
233 const invalid = [
234 'tintin',
235 -1,
236 undefined
237 ]
238
239 for (const value of invalid) {
240 await cut(value as any, undefined)
241 await cut(undefined, value as any)
242 }
243 })
244
245 it('Should fail with the same start/end', async function () {
246 await cut(2, 2)
247 })
248
249 it('Should fail with inconsistents start/end', async function () {
250 await cut(2, 1)
251 })
252
253 it('Should fail without start and end', async function () {
254 await cut(undefined, undefined)
255 })
256
257 it('Should succeed with the correct params', async function () {
258 this.timeout(120000)
259
260 await cut(0, 2, HttpStatusCode.NO_CONTENT_204)
261
262 await waitJobs([ server ])
263 })
264 })
265
266 describe('Watermark task', function () {
267
268 async function addWatermark (file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
269 await command.createEditionTasks({
270 videoId: videoUUID,
271 tasks: [
272 {
273 name: 'add-watermark',
274 options: {
275 file
276 }
277 }
278 ],
279 expectedStatus
280 })
281 }
282
283 it('Should fail without waterkmark', async function () {
284 await addWatermark(undefined)
285 })
286
287 it('Should fail with an invalid watermark', async function () {
288 await addWatermark('video_short.mp4')
289 })
290
291 it('Should succeed with the correct params', async function () {
292 this.timeout(120000)
293
294 await addWatermark('thumbnail.jpg', HttpStatusCode.NO_CONTENT_204)
295
296 await waitJobs([ server ])
297 })
298 })
299
300 describe('Intro/Outro task', function () {
301
302 async function addIntroOutro (type: 'add-intro' | 'add-outro', file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
303 await command.createEditionTasks({
304 videoId: videoUUID,
305 tasks: [
306 {
307 name: type,
308 options: {
309 file
310 }
311 }
312 ],
313 expectedStatus
314 })
315 }
316
317 it('Should fail without file', async function () {
318 await addIntroOutro('add-intro', undefined)
319 await addIntroOutro('add-outro', undefined)
320 })
321
322 it('Should fail with an invalid file', async function () {
323 await addIntroOutro('add-intro', 'thumbnail.jpg')
324 await addIntroOutro('add-outro', 'thumbnail.jpg')
325 })
326
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')
330
331 })
332
333 it('Should succeed with the correct params', async function () {
334 this.timeout(120000)
335
336 await addIntroOutro('add-intro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
337 await waitJobs([ server ])
338
339 await addIntroOutro('add-outro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
340 await waitJobs([ server ])
341 })
342
343 it('Should check total quota when creating the task', async function () {
344 this.timeout(120000)
345
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' })
349
350 const addIntroOutroByUser = (type: 'add-intro' | 'add-outro', expectedStatus: HttpStatusCode) => {
351 return command.createEditionTasks({
352 token,
353 videoId: uuid,
354 tasks: [
355 {
356 name: type,
357 options: {
358 file: 'video_short.mp4'
359 }
360 }
361 ],
362 expectedStatus
363 })
364 }
365
366 await waitJobs([ server ])
367
368 const { videoQuotaUsed } = await server.users.getMyQuotaUsed({ token })
369 await server.users.update({ userId: user.id, videoQuota: Math.round(videoQuotaUsed * 2.5) })
370
371 // Still valid
372 await addIntroOutroByUser('add-intro', HttpStatusCode.NO_CONTENT_204)
373
374 await waitJobs([ server ])
375
376 // Too much quota
377 await addIntroOutroByUser('add-intro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
378 await addIntroOutroByUser('add-outro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
379 })
380 })
381 })
382
383 after(async function () {
384 await cleanupTests([ server ])
385 })
386 })