"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^6.0.0",
"fast-xml-parser": "^4.0.0-beta.8",
+ "jpeg-js": "^0.4.4",
"mocha": "^10.0.0",
+ "pixelmatch": "^5.3.0",
+ "pngjs": "^7.0.0",
"proxy": "^1.0.2",
"resolve-tspaths": "^0.8.8",
"socket.io-client": "^4.5.4",
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { expect } from 'chai'
-import { testImage } from '@server/tests/shared'
+import { testImageSize } from '@server/tests/shared'
import { AbuseState, HttpStatusCode, UserAdminFlag, UserRole, VideoPlaylistType } from '@shared/models'
import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
const user = await server.users.getMyInfo({ token: userToken })
for (const avatar of user.account.avatars) {
- await testImage(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, '.gif')
+ await testImageSize(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, '.gif')
}
})
const user = await server.users.getMyInfo({ token: userToken })
for (const avatar of user.account.avatars) {
- await testImage(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, extension)
+ await testImageSize(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, extension)
}
}
})
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 })
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')
})
const imageDestJPG = join(imageDestDir, 'test.jpg')
const imageDestPNG = join(imageDestDir, 'test.png')
- const thumbnailSize = { width: 223, height: 122 }
+ const thumbnailSize = { width: 280, height: 157 }
it('Should skip processing if the source image is okay', async function () {
const input = buildAbsoluteFixturePath('thumbnail.jpg')
import { expect } from 'chai'
import { pathExists, readFile } from 'fs-extra'
+import JPEG from 'jpeg-js'
import { join } from 'path'
+import pixelmatch from 'pixelmatch'
+import { PNG } from 'pngjs'
import { root } from '@shared/core-utils'
import { HttpStatusCode } from '@shared/models'
import { makeGetRequest, PeerTubeServer } from '@shared/server-commands'
expect(content.toString()).to.contain(str)
}
-async function testImage (url: string, imageName: string, imageHTTPPath: string, extension = '.jpg') {
+async function testImageSize (url: string, imageName: string, imageHTTPPath: string, extension = '.jpg') {
const res = await makeGetRequest({
url,
path: imageHTTPPath,
expect(body.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
}
+async function testImage (url: string, imageName: string, imageHTTPPath: string, extension = '.jpg') {
+ const res = await makeGetRequest({
+ url,
+ path: imageHTTPPath,
+ expectedStatus: HttpStatusCode.OK_200
+ })
+
+ const body = res.body
+ const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension))
+
+ const img1 = imageHTTPPath.endsWith('.png')
+ ? PNG.sync.read(body)
+ : JPEG.decode(body)
+
+ const img2 = extension === '.png'
+ ? PNG.sync.read(data)
+ : JPEG.decode(data)
+
+ const result = pixelmatch(img1.data, img2.data, null, img1.width, img1.height, { threshold: 0.1 })
+
+ expect(result).to.equal(0, `${imageHTTPPath} image is not the same as ${imageName}${extension}`)
+}
+
async function testFileExistsOrNot (server: PeerTubeServer, directory: string, filePath: string, exist: boolean) {
const base = server.servers.buildDirectory(directory)
export {
dateIsValid,
+ testImageSize,
testImage,
expectLogDoesNotContain,
testFileExistsOrNot,
export class ImportsCommand extends AbstractCommand {
importVideo (options: OverrideCommandOptions & {
- attributes: VideoImportCreate & { torrentfile?: string }
+ attributes: (VideoImportCreate | { torrentfile?: string, previewfile?: string, thumbnailfile?: string })
}) {
const { attributes } = options
const path = '/api/v1/videos/imports'
let attaches: any = {}
if (attributes.torrentfile) attaches = { torrentfile: attributes.torrentfile }
+ if (attributes.thumbnailfile) attaches = { thumbnailfile: attributes.thumbnailfile }
+ if (attributes.previewfile) attaches = { previewfile: attributes.previewfile }
return unwrapBody<VideoImport>(this.postUploadRequest({
...options,
dependencies:
pngjs "^3.0.0"
+pixelmatch@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-5.3.0.tgz#5e5321a7abedfb7962d60dbf345deda87cb9560a"
+ integrity sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==
+ dependencies:
+ pngjs "^6.0.0"
+
please-upgrade-node@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821"
integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==
+pngjs@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-7.0.0.tgz#a8b7446020ebbc6ac739db6c5415a65d17090e26"
+ integrity sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==
+
postcss@^8.1.10, postcss@^8.3.11:
version "8.4.21"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"