X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Ftests%2Fapi%2Fvideos%2Fvideo-imports.ts;h=192b2aeb9ae7c705090ee2ecf90d1eaeb23e8ef0;hb=HEAD;hp=b6168b54e2df34f0389085d237f452ede220c48e;hpb=1740952b8c0b84f3b1b6edc99890b757000fe3ef;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/tests/api/videos/video-imports.ts b/server/tests/api/videos/video-imports.ts index b6168b54e..192b2aeb9 100644 --- a/server/tests/api/videos/video-imports.ts +++ b/server/tests/api/videos/video-imports.ts @@ -1,32 +1,30 @@ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ -import 'mocha' import { expect } from 'chai' import { pathExists, readdir, remove } from 'fs-extra' import { join } from 'path' +import { FIXTURE_URLS, testCaptionFile, testImage } from '@server/tests/shared' +import { areHttpImportTestsDisabled } from '@shared/core-utils' +import { CustomConfig, HttpStatusCode, Video, VideoImportState, VideoPrivacy, VideoResolution, VideoState } from '@shared/models' import { - areHttpImportTestsDisabled, cleanupTests, createMultipleServers, createSingleServer, doubleFollow, - FIXTURE_URLS, + getServerImportConfig, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel, - testCaptionFile, - testImage, waitJobs -} from '@shared/extra-utils' -import { VideoPrivacy, VideoResolution } from '@shared/models' +} from '@shared/server-commands' +import { DeepPartial } from '@shared/typescript-utils' async function checkVideosServer1 (server: PeerTubeServer, idHttp: string, idMagnet: string, idTorrent: string) { const videoHttp = await server.videos.get({ id: idHttp }) expect(videoHttp.name).to.equal('small video - youtube') - // FIXME: youtube-dl seems broken - // expect(videoHttp.category.label).to.equal('News & Politics') - // expect(videoHttp.licence.label).to.equal('Attribution') + expect(videoHttp.category.label).to.equal('News & Politics') + expect(videoHttp.licence.label).to.equal('Attribution') expect(videoHttp.language.label).to.equal('Unknown') expect(videoHttp.nsfw).to.be.false expect(videoHttp.description).to.equal('this is a super description') @@ -42,7 +40,7 @@ async function checkVideosServer1 (server: PeerTubeServer, idHttp: string, idMag const videoTorrent = await server.videos.get({ id: idTorrent }) for (const video of [ videoMagnet, videoTorrent ]) { - expect(video.category.label).to.equal('Misc') + expect(video.category.label).to.equal('Unknown') expect(video.licence.label).to.equal('Unknown') expect(video.language.label).to.equal('Unknown') expect(video.nsfw).to.be.false @@ -69,6 +67,8 @@ async function checkVideoServer2 (server: PeerTubeServer, id: number | string) { expect(video.description).to.equal('my super description') expect(video.tags).to.deep.equal([ 'supertag1', 'supertag2' ]) + await testImage(server.url, 'thumbnail', video.thumbnailPath) + expect(video.files).to.have.lengthOf(1) const bodyCaptions = await server.captions.list({ videoId: id }) @@ -85,28 +85,23 @@ describe('Test video imports', function () { let servers: PeerTubeServer[] = [] before(async function () { - this.timeout(30_000) - - // Run servers - servers = await createMultipleServers(2, { - import: { - videos: { - http: { - youtube_dl_release: { - url: mode === 'youtube-dl' - ? 'https://yt-dl.org/downloads/latest/youtube-dl' - : 'https://api.github.com/repos/yt-dlp/yt-dlp/releases', - - name: mode - } - } - } - } - }) + this.timeout(60_000) + + servers = await createMultipleServers(2, getServerImportConfig(mode)) await setAccessTokensToServers(servers) await setDefaultVideoChannel(servers) + for (const server of servers) { + await server.config.updateExistingSubConfig({ + newConfig: { + transcoding: { + alwaysTranscodeOriginalResolution: false + } + } + }) + } + await doubleFollow(servers[0], servers[1]) }) @@ -145,9 +140,11 @@ describe('Test video imports', function () { expect(enCaption.language.label).to.equal('English') expect(enCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-en.vtt$`)) - const regex = `WEBVTT[ \n]+Kind: captions[ \n]+Language: en[ \n]+00:00:01.600 --> 00:00:04.200[ \n]+English \\(US\\)[ \n]+` + - `00:00:05.900 --> 00:00:07.999[ \n]+This is a subtitle in American English[ \n]+` + - `00:00:10.000 --> 00:00:14.000[ \n]+Adding subtitles is very easy to do` + const regex = `WEBVTT[ \n]+Kind: captions[ \n]+` + + `(Language: en[ \n]+)?` + + `00:00:01.600 --> 00:00:04.200( position:\\d+% line:\\d+%)?[ \n]+English \\(US\\)[ \n]+` + + `00:00:05.900 --> 00:00:07.999( position:\\d+% line:\\d+%)?[ \n]+This is a subtitle in American English[ \n]+` + + `00:00:10.000 --> 00:00:14.000( position:\\d+% line:\\d+%)?[ \n]+Adding subtitles is very easy to do` await testCaptionFile(servers[0].url, enCaption.captionPath, new RegExp(regex)) } @@ -157,9 +154,11 @@ describe('Test video imports', function () { expect(frCaption.language.label).to.equal('French') expect(frCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-fr.vtt`)) - const regex = `WEBVTT[ \n]+Kind: captions[ \n]+Language: fr[ \n]+00:00:01.600 --> 00:00:04.200[ \n]+` + - `Français \\(FR\\)[ \n]+00:00:05.900 --> 00:00:07.999[ \n]+C'est un sous-titre français[ \n]+` + - `00:00:10.000 --> 00:00:14.000[ \n]+Ajouter un sous-titre est vraiment facile` + const regex = `WEBVTT[ \n]+Kind: captions[ \n]+` + + `(Language: fr[ \n]+)?` + + `00:00:01.600 --> 00:00:04.200( position:\\d+% line:\\d+%)?[ \n]+Français \\(FR\\)[ \n]+` + + `00:00:05.900 --> 00:00:07.999( position:\\d+% line:\\d+%)?[ \n]+C'est un sous-titre français[ \n]+` + + `00:00:10.000 --> 00:00:14.000( position:\\d+% line:\\d+%)?[ \n]+Ajouter un sous-titre est vraiment facile` await testCaptionFile(servers[0].url, frCaption.captionPath, new RegExp(regex)) } @@ -221,6 +220,23 @@ describe('Test video imports', function () { expect(videoImports[0].video.name).to.equal('你好 世界 720p.mp4') }) + it('Should filter my imports on target URL', async function () { + const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ targetUrl: FIXTURE_URLS.youtube }) + expect(total).to.equal(1) + expect(videoImports).to.have.lengthOf(1) + + expect(videoImports[0].targetUrl).to.equal(FIXTURE_URLS.youtube) + }) + + it('Should search in my imports', async function () { + const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ search: 'peertube2' }) + expect(total).to.equal(1) + expect(videoImports).to.have.lengthOf(1) + + expect(videoImports[0].magnetUri).to.equal(FIXTURE_URLS.magnet) + expect(videoImports[0].video.name).to.equal('super peertube2 video') + }) + it('Should have the video listed on the two instances', async function () { this.timeout(120_000) @@ -239,18 +255,20 @@ describe('Test video imports', function () { it('Should import a video on server 2 with some fields', async function () { this.timeout(60_000) - const attributes = { - targetUrl: FIXTURE_URLS.youtube, - channelId: servers[1].store.channel.id, - privacy: VideoPrivacy.PUBLIC, - category: 10, - licence: 7, - language: 'en', - name: 'my super name', - description: 'my super description', - tags: [ 'supertag1', 'supertag2' ] - } - const { video } = await servers[1].imports.importVideo({ attributes }) + const { video } = await servers[1].imports.importVideo({ + attributes: { + targetUrl: FIXTURE_URLS.youtube, + channelId: servers[1].store.channel.id, + privacy: VideoPrivacy.PUBLIC, + category: 10, + licence: 7, + language: 'en', + name: 'my super name', + description: 'my super description', + tags: [ 'supertag1', 'supertag2' ], + thumbnailfile: 'thumbnail.jpg' + } + }) expect(video.name).to.equal('my super name') }) @@ -296,10 +314,11 @@ describe('Test video imports', function () { it('Should import no HDR version on a HDR video', async function () { this.timeout(300_000) - const config = { + const config: DeepPartial = { transcoding: { enabled: true, resolutions: { + '0p': false, '144p': true, '240p': true, '360p': false, @@ -311,19 +330,9 @@ describe('Test video imports', function () { }, webtorrent: { enabled: true }, hls: { enabled: false } - }, - import: { - videos: { - http: { - enabled: true - }, - torrent: { - enabled: true - } - } } } - await servers[0].config.updateCustomSubConfig({ newConfig: config }) + await servers[0].config.updateExistingSubConfig({ newConfig: config }) const attributes = { name: 'hdr video', @@ -343,6 +352,76 @@ describe('Test video imports', function () { expect(maxResolution, 'expected max resolution not met').to.equals(VideoResolution.H_240P) }) + it('Should not import resolution higher than enabled transcoding resolution', async function () { + this.timeout(300_000) + + const config: DeepPartial = { + transcoding: { + enabled: true, + resolutions: { + '0p': false, + '144p': true, + '240p': false, + '360p': false, + '480p': false, + '720p': false, + '1080p': false, + '1440p': false, + '2160p': false + }, + alwaysTranscodeOriginalResolution: false + } + } + await servers[0].config.updateExistingSubConfig({ newConfig: config }) + + const attributes = { + name: 'small resolution video', + targetUrl: FIXTURE_URLS.youtube, + channelId: servers[0].store.channel.id, + privacy: VideoPrivacy.PUBLIC + } + const { video: videoImported } = await servers[0].imports.importVideo({ attributes }) + const videoUUID = videoImported.uuid + + await waitJobs(servers) + + // test resolution + const video = await servers[0].videos.get({ id: videoUUID }) + expect(video.name).to.equal('small resolution video') + expect(video.files).to.have.lengthOf(1) + expect(video.files[0].resolution.id).to.equal(144) + }) + + it('Should import resolution higher than enabled transcoding resolution', async function () { + this.timeout(300_000) + + const config: DeepPartial = { + transcoding: { + alwaysTranscodeOriginalResolution: true + } + } + await servers[0].config.updateExistingSubConfig({ newConfig: config }) + + const attributes = { + name: 'bigger resolution video', + targetUrl: FIXTURE_URLS.youtube, + channelId: servers[0].store.channel.id, + privacy: VideoPrivacy.PUBLIC + } + const { video: videoImported } = await servers[0].imports.importVideo({ attributes }) + const videoUUID = videoImported.uuid + + await waitJobs(servers) + + // test resolution + const video = await servers[0].videos.get({ id: videoUUID }) + expect(video.name).to.equal('bigger resolution video') + + expect(video.files).to.have.lengthOf(2) + expect(video.files.find(f => f.resolution.id === 240)).to.exist + expect(video.files.find(f => f.resolution.id === 144)).to.exist + }) + it('Should import a peertube video', async function () { this.timeout(120_000) @@ -370,6 +449,16 @@ describe('Test video imports', function () { const video = await server.videos.get({ id: videoUUID }) expect(video.name).to.equal('E2E tests') + + const { data: captions } = await server.captions.list({ videoId: videoUUID }) + expect(captions).to.have.lengthOf(1) + expect(captions[0].language.id).to.equal('fr') + + const str = `WEBVTT FILE\r?\n\r?\n` + + `1\r?\n` + + `00:00:04.000 --> 00:00:09.000\r?\n` + + `January 1, 1994. The North American` + await testCaptionFile(server.url, captions[0].captionPath, new RegExp(str)) } } }) @@ -380,10 +469,94 @@ describe('Test video imports', function () { }) } - runSuite('youtube-dl') + // FIXME: youtube-dl seems broken + // runSuite('youtube-dl') runSuite('yt-dlp') + describe('Delete/cancel an import', function () { + let server: PeerTubeServer + + let finishedImportId: number + let finishedVideo: Video + let pendingImportId: number + + async function importVideo (name: string) { + const attributes = { name, channelId: server.store.channel.id, targetUrl: FIXTURE_URLS.goodVideo } + const res = await server.imports.importVideo({ attributes }) + + return res.id + } + + before(async function () { + this.timeout(120_000) + + server = await createSingleServer(1) + + await setAccessTokensToServers([ server ]) + await setDefaultVideoChannel([ server ]) + + finishedImportId = await importVideo('finished') + await waitJobs([ server ]) + + await server.jobs.pauseJobQueue() + pendingImportId = await importVideo('pending') + + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(2) + + finishedVideo = data.find(i => i.id === finishedImportId).video + }) + + it('Should delete a video import', async function () { + await server.imports.delete({ importId: finishedImportId }) + + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(1) + expect(data[0].id).to.equal(pendingImportId) + expect(data[0].state.id).to.equal(VideoImportState.PENDING) + }) + + it('Should not have deleted the associated video', async function () { + const video = await server.videos.get({ id: finishedVideo.id, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) + expect(video.name).to.equal('finished') + expect(video.state.id).to.equal(VideoState.PUBLISHED) + }) + + it('Should cancel a video import', async function () { + await server.imports.cancel({ importId: pendingImportId }) + + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(1) + expect(data[0].id).to.equal(pendingImportId) + expect(data[0].state.id).to.equal(VideoImportState.CANCELLED) + }) + + it('Should not have processed the cancelled video import', async function () { + this.timeout(60_000) + + await server.jobs.resumeJobQueue() + + await waitJobs([ server ]) + + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(1) + expect(data[0].id).to.equal(pendingImportId) + expect(data[0].state.id).to.equal(VideoImportState.CANCELLED) + expect(data[0].video.state.id).to.equal(VideoState.TO_IMPORT) + }) + + it('Should delete the cancelled video import', async function () { + await server.imports.delete({ importId: pendingImportId }) + const { data } = await server.imports.getMyVideoImports() + expect(data).to.have.lengthOf(0) + }) + + after(async function () { + await cleanupTests([ server ]) + }) + }) + describe('Auto update', function () { let server: PeerTubeServer