123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
- import { HttpStatusCode, HttpStatusCodeType, VideoStudioTask } from '@peertube/peertube-models'
- import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- VideoStudioCommand,
- waitJobs
- } from '@peertube/peertube-server-commands'
- describe('Test video studio API validator', function () {
- let server: PeerTubeServer
- let command: VideoStudioCommand
- let userAccessToken: string
- let videoUUID: string
- // ---------------------------------------------------------------
- before(async function () {
- this.timeout(120_000)
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- userAccessToken = await server.users.generateUserAndToken('user1')
- await server.config.enableMinimumTranscoding()
- const { uuid } = await server.videos.quickUpload({ name: 'video' })
- videoUUID = uuid
- command = server.videoStudio
- await waitJobs([ server ])
- })
- describe('Task creation', function () {
- describe('Config settings', function () {
- it('Should fail if studio is disabled', async function () {
- await server.config.updateExistingConfig({
- newConfig: {
- videoStudio: {
- enabled: false
- }
- }
- })
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- it('Should fail to enable studio if transcoding is disabled', async function () {
- await server.config.updateExistingConfig({
- newConfig: {
- videoStudio: {
- enabled: true
- },
- transcoding: {
- enabled: false
- }
- },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- it('Should succeed to enable video studio', async function () {
- await server.config.updateExistingConfig({
- newConfig: {
- videoStudio: {
- enabled: true
- },
- transcoding: {
- enabled: true
- }
- }
- })
- })
- })
- describe('Common tasks', function () {
- it('Should fail without token', async function () {
- await command.createEditionTasks({
- token: null,
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
- it('Should fail with another user token', async function () {
- await command.createEditionTasks({
- token: userAccessToken,
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- it('Should fail with an invalid video', async function () {
- await command.createEditionTasks({
- videoId: 'tintin',
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- it('Should fail with an unknown video', async function () {
- await command.createEditionTasks({
- videoId: 42,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
- it('Should fail with an already in transcoding state video', async function () {
- this.timeout(60000)
- const { uuid } = await server.videos.quickUpload({ name: 'transcoded video' })
- await waitJobs([ server ])
- await server.jobs.pauseJobQueue()
- await server.videos.runTranscoding({ videoId: uuid, transcodingType: 'hls' })
- await command.createEditionTasks({
- videoId: uuid,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- await server.jobs.resumeJobQueue()
- })
- it('Should fail with a bad complex task', async function () {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: 'cut',
- options: {
- start: 1,
- end: 2
- }
- },
- {
- name: 'hadock',
- options: {
- start: 1,
- end: 2
- }
- }
- ] as any,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- it('Should fail without task', async function () {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [],
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- it('Should fail with too many tasks', async function () {
- const tasks: VideoStudioTask[] = []
- for (let i = 0; i < 110; i++) {
- tasks.push({
- name: 'cut',
- options: {
- start: 1
- }
- })
- }
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- it('Should succeed with correct parameters', async function () {
- await server.jobs.pauseJobQueue()
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- it('Should fail with a video that is already waiting for edition', async function () {
- this.timeout(360000)
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- await server.jobs.resumeJobQueue()
- await waitJobs([ server ])
- })
- })
- describe('Cut task', function () {
- async function cut (start: number, end: number, expectedStatus: HttpStatusCodeType = HttpStatusCode.BAD_REQUEST_400) {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: 'cut',
- options: {
- start,
- end
- }
- }
- ],
- expectedStatus
- })
- }
- it('Should fail with bad start/end', async function () {
- const invalid = [
- 'tintin',
- -1,
- undefined
- ]
- for (const value of invalid) {
- await cut(value as any, undefined)
- await cut(undefined, value as any)
- }
- })
- it('Should fail with the same start/end', async function () {
- await cut(2, 2)
- })
- it('Should fail with inconsistents start/end', async function () {
- await cut(2, 1)
- })
- it('Should fail without start and end', async function () {
- await cut(undefined, undefined)
- })
- it('Should succeed with the correct params', async function () {
- this.timeout(360000)
- await cut(0, 2, HttpStatusCode.NO_CONTENT_204)
- await waitJobs([ server ])
- })
- })
- describe('Watermark task', function () {
- async function addWatermark (file: string, expectedStatus: HttpStatusCodeType = HttpStatusCode.BAD_REQUEST_400) {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: 'add-watermark',
- options: {
- file
- }
- }
- ],
- expectedStatus
- })
- }
- it('Should fail without waterkmark', async function () {
- await addWatermark(undefined)
- })
- it('Should fail with an invalid watermark', async function () {
- await addWatermark('video_short.mp4')
- })
- it('Should succeed with the correct params', async function () {
- this.timeout(360000)
- await addWatermark('custom-thumbnail.jpg', HttpStatusCode.NO_CONTENT_204)
- await waitJobs([ server ])
- })
- })
- describe('Intro/Outro task', function () {
- async function addIntroOutro (
- type: 'add-intro' | 'add-outro',
- file: string,
- expectedStatus: HttpStatusCodeType = HttpStatusCode.BAD_REQUEST_400
- ) {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: type,
- options: {
- file
- }
- }
- ],
- expectedStatus
- })
- }
- it('Should fail without file', async function () {
- await addIntroOutro('add-intro', undefined)
- await addIntroOutro('add-outro', undefined)
- })
- it('Should fail with an invalid file', async function () {
- await addIntroOutro('add-intro', 'custom-thumbnail.jpg')
- await addIntroOutro('add-outro', 'custom-thumbnail.jpg')
- })
- it('Should fail with a file that does not contain video stream', async function () {
- await addIntroOutro('add-intro', 'sample.ogg')
- await addIntroOutro('add-outro', 'sample.ogg')
- })
- it('Should succeed with the correct params', async function () {
- this.timeout(360000)
- await addIntroOutro('add-intro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
- await waitJobs([ server ])
- await addIntroOutro('add-outro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
- await waitJobs([ server ])
- })
- it('Should check total quota when creating the task', async function () {
- this.timeout(360000)
- const user = await server.users.create({ username: 'user_quota_1' })
- const token = await server.login.getAccessToken('user_quota_1')
- const { uuid } = await server.videos.quickUpload({ token, name: 'video_quota_1', fixture: 'video_short.mp4' })
- const addIntroOutroByUser = (type: 'add-intro' | 'add-outro', expectedStatus: HttpStatusCodeType) => {
- return command.createEditionTasks({
- token,
- videoId: uuid,
- tasks: [
- {
- name: type,
- options: {
- file: 'video_short.mp4'
- }
- }
- ],
- expectedStatus
- })
- }
- await waitJobs([ server ])
- const { videoQuotaUsed } = await server.users.getMyQuotaUsed({ token })
- await server.users.update({ userId: user.id, videoQuota: Math.round(videoQuotaUsed * 2.5) })
- // Still valid
- await addIntroOutroByUser('add-intro', HttpStatusCode.NO_CONTENT_204)
- await waitJobs([ server ])
- // Too much quota
- await addIntroOutroByUser('add-intro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
- await addIntroOutroByUser('add-outro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
- })
- })
- })
- after(async function () {
- await cleanupTests([ server ])
- })
- })
|