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