mirror of
https://github.com/catdad-experiments/heic-convert
synced 2024-11-22 01:50:55 +00:00
abstracting tests to exist in a separate file, let them be required and run as a library
This commit is contained in:
parent
ad3f4cae6c
commit
2a3d82d7e4
@ -5,7 +5,7 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"pretest": "node scripts/images.js",
|
||||
"test": "mocha --timeout 40000 --slow 0 \"test/**/*.js\""
|
||||
"test": "mocha --timeout 40000 --slow 0 \"test/**/*.test.js\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,148 +1,9 @@
|
||||
/* eslint-env mocha */
|
||||
const { promisify } = require('util');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const runTests = require('./run-tests.js');
|
||||
|
||||
const root = require('rootrequire');
|
||||
const { fromBuffer: filetype } = require('file-type');
|
||||
const { expect } = require('chai');
|
||||
const toUint8 = require('buffer-to-uint8array');
|
||||
const pixelmatch = require('pixelmatch');
|
||||
const { PNG } = require('pngjs');
|
||||
const jpegJs = require('jpeg-js');
|
||||
|
||||
const convert = require('../');
|
||||
|
||||
const readFile = promisify(fs.readFile);
|
||||
|
||||
describe('heic-convert', () => {
|
||||
it('exports a function', () => {
|
||||
expect(convert).to.be.a('function');
|
||||
});
|
||||
|
||||
const decode = {
|
||||
'image/png': buffer => PNG.sync.read(buffer),
|
||||
'image/jpeg': buffer => jpegJs.decode(buffer)
|
||||
};
|
||||
|
||||
const readControl = async name => {
|
||||
const buffer = await readFile(path.resolve(root, `temp/${name}`));
|
||||
return decode['image/png'](buffer);
|
||||
};
|
||||
|
||||
const compare = (expected, actual, width, height, errString = 'actual image did not match control image') => {
|
||||
const result = pixelmatch(toUint8(Buffer.from(expected)), toUint8(Buffer.from(actual)), null, width, height, {
|
||||
threshold: 0.1
|
||||
});
|
||||
|
||||
// allow 5% of pixels to be different
|
||||
expect(result).to.be.below(width * height * 0.05, errString);
|
||||
};
|
||||
|
||||
const assertImage = async (buffer, mime, control) => {
|
||||
const type = await filetype(buffer);
|
||||
expect(type.mime).to.equal(mime);
|
||||
|
||||
const actual = decode[mime](buffer);
|
||||
|
||||
expect(actual.width).to.equal(control.width);
|
||||
expect(actual.height).to.equal(control.height);
|
||||
|
||||
compare(control.data, actual.data, control.width, control.height);
|
||||
};
|
||||
|
||||
it('converts known image to jpeg', async () => {
|
||||
const control = await readControl('0002-control.png');
|
||||
const buffer = await readFile(path.resolve(root, 'temp', '0002.heic'));
|
||||
|
||||
// quality of 92%
|
||||
const output92 = await convert({ buffer, format: 'JPEG' });
|
||||
await assertImage(output92, 'image/jpeg', control);
|
||||
|
||||
// quality of 100%
|
||||
const output100 = await convert({ buffer, format: 'JPEG', quality: 1 });
|
||||
await assertImage(output100, 'image/jpeg', control);
|
||||
|
||||
expect(output92).to.not.deep.equal(output100);
|
||||
expect(output92.length).to.be.below(output100.length);
|
||||
});
|
||||
|
||||
it('converts known image to png', async () => {
|
||||
const control = await readControl('0002-control.png');
|
||||
const buffer = await readFile(path.resolve(root, 'temp', '0002.heic'));
|
||||
|
||||
const output = await convert({ buffer, format: 'PNG' });
|
||||
await assertImage(output, 'image/png', control);
|
||||
});
|
||||
|
||||
it('converts multiple images inside a single file to jpeg', async () => {
|
||||
const controls = await Promise.all([
|
||||
readControl('0003-0-control.png'),
|
||||
readControl('0003-1-control.png'),
|
||||
]);
|
||||
const buffer = await readFile(path.resolve(root, 'temp', '0003.heic'));
|
||||
const images = await convert.all({ buffer, format: 'JPEG' });
|
||||
|
||||
expect(images).to.have.lengthOf(3);
|
||||
|
||||
for (let { i, control } of [
|
||||
{ i: 0, control: controls[0] },
|
||||
{ i: 1, control: controls[1] },
|
||||
{ i: 2, control: controls[1] },
|
||||
]) {
|
||||
expect(images[i]).to.have.a.property('convert').and.to.be.a('function');
|
||||
await assertImage(await images[i].convert(), 'image/jpeg', control);
|
||||
}
|
||||
});
|
||||
|
||||
it('converts multiple images inside a single file to png', async () => {
|
||||
const controls = await Promise.all([
|
||||
readControl('0003-0-control.png'),
|
||||
readControl('0003-1-control.png'),
|
||||
]);
|
||||
const buffer = await readFile(path.resolve(root, 'temp', '0003.heic'));
|
||||
const images = await convert.all({ buffer, format: 'PNG' });
|
||||
|
||||
expect(images).to.have.lengthOf(3);
|
||||
|
||||
for (let { i, control } of [
|
||||
{ i: 0, control: controls[0] },
|
||||
{ i: 1, control: controls[1] },
|
||||
{ i: 2, control: controls[1] },
|
||||
]) {
|
||||
expect(images[i]).to.have.a.property('convert').and.to.be.a('function');
|
||||
await assertImage(await images[i].convert(), 'image/png', control);
|
||||
}
|
||||
});
|
||||
|
||||
[
|
||||
{ when: 'converting only the main image', method: convert },
|
||||
{ when: 'converting all images', method: convert.all }
|
||||
].forEach(({ when, method }) => {
|
||||
it(`errors for an unknown output format when ${when}`, async () => {
|
||||
const buffer = Buffer.from(Math.random().toString() + Math.random().toString());
|
||||
|
||||
let error;
|
||||
|
||||
await method({ buffer, format: 'PINEAPPLES' }).catch(err => {
|
||||
error = err;
|
||||
});
|
||||
|
||||
expect(error).to.be.instanceof(Error)
|
||||
.and.to.have.property('message', 'output format needs to be one of [JPEG,PNG]');
|
||||
});
|
||||
|
||||
it(`errors if data other than a HEIC image is passed in when ${when}`, async () => {
|
||||
const buffer = Buffer.from(Math.random().toString() + Math.random().toString());
|
||||
|
||||
let error;
|
||||
|
||||
await method({ buffer, format: 'JPEG' }).catch(err => {
|
||||
error = err;
|
||||
});
|
||||
|
||||
expect(error).to.be.instanceof(TypeError)
|
||||
.and.to.have.property('message', 'input buffer is not a HEIC image');
|
||||
});
|
||||
});
|
||||
describe('heic-convert (default wasm)', () => {
|
||||
runTests(require('..'));
|
||||
});
|
||||
|
||||
describe('heic-convert (legacy js)', () => {
|
||||
runTests(require('../legacy'));
|
||||
});
|
||||
|
148
test/run-tests.js
Normal file
148
test/run-tests.js
Normal file
@ -0,0 +1,148 @@
|
||||
/* eslint-env mocha */
|
||||
const { promisify } = require('util');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const root = require('rootrequire');
|
||||
const { fromBuffer: filetype } = require('file-type');
|
||||
const { expect } = require('chai');
|
||||
const toUint8 = require('buffer-to-uint8array');
|
||||
const pixelmatch = require('pixelmatch');
|
||||
const { PNG } = require('pngjs');
|
||||
const jpegJs = require('jpeg-js');
|
||||
|
||||
const readFile = promisify(fs.readFile);
|
||||
|
||||
module.exports = function runTests(convert) {
|
||||
it('exports a function', () => {
|
||||
expect(convert).to.be.a('function');
|
||||
});
|
||||
|
||||
const decode = {
|
||||
'image/png': buffer => PNG.sync.read(Buffer.from(buffer)),
|
||||
'image/jpeg': buffer => jpegJs.decode(Buffer.from(buffer))
|
||||
};
|
||||
|
||||
const readControl = async name => {
|
||||
const buffer = await readFile(path.resolve(root, `temp/${name}`));
|
||||
return decode['image/png'](buffer);
|
||||
};
|
||||
|
||||
const compare = (expected, actual, width, height, errString = 'actual image did not match control image') => {
|
||||
const result = pixelmatch(toUint8(Buffer.from(expected)), toUint8(Buffer.from(actual)), null, width, height, {
|
||||
threshold: 0.1
|
||||
});
|
||||
|
||||
// allow 5% of pixels to be different
|
||||
expect(result).to.be.below(width * height * 0.05, errString);
|
||||
};
|
||||
|
||||
const assertImage = async (buffer, mime, control) => {
|
||||
expect(buffer).to.be.instanceOf(Uint8Array);
|
||||
|
||||
const type = await filetype(buffer);
|
||||
expect(type.mime).to.equal(mime);
|
||||
|
||||
const actual = decode[mime](buffer);
|
||||
|
||||
expect(actual.width).to.equal(control.width);
|
||||
expect(actual.height).to.equal(control.height);
|
||||
|
||||
compare(control.data, actual.data, control.width, control.height);
|
||||
};
|
||||
|
||||
it('converts known image to jpeg', async () => {
|
||||
const control = await readControl('0002-control.png');
|
||||
const buffer = await readFile(path.resolve(root, 'temp', '0002.heic'));
|
||||
|
||||
// quality of 92%
|
||||
const output92 = await convert({ buffer, format: 'JPEG' });
|
||||
await assertImage(output92, 'image/jpeg', control);
|
||||
|
||||
// quality of 100%
|
||||
const output100 = await convert({ buffer, format: 'JPEG', quality: 1 });
|
||||
await assertImage(output100, 'image/jpeg', control);
|
||||
|
||||
expect(output92).to.not.deep.equal(output100);
|
||||
expect(output92.length).to.be.below(output100.length);
|
||||
});
|
||||
|
||||
it('converts known image to png', async () => {
|
||||
const control = await readControl('0002-control.png');
|
||||
const buffer = await readFile(path.resolve(root, 'temp', '0002.heic'));
|
||||
|
||||
const output = await convert({ buffer, format: 'PNG' });
|
||||
await assertImage(output, 'image/png', control);
|
||||
});
|
||||
|
||||
it('converts multiple images inside a single file to jpeg', async () => {
|
||||
const controls = await Promise.all([
|
||||
readControl('0003-0-control.png'),
|
||||
readControl('0003-1-control.png'),
|
||||
]);
|
||||
const buffer = await readFile(path.resolve(root, 'temp', '0003.heic'));
|
||||
const images = await convert.all({ buffer, format: 'JPEG' });
|
||||
|
||||
expect(images).to.have.lengthOf(3);
|
||||
|
||||
for (let { i, control } of [
|
||||
{ i: 0, control: controls[0] },
|
||||
{ i: 1, control: controls[1] },
|
||||
{ i: 2, control: controls[1] },
|
||||
]) {
|
||||
expect(images[i]).to.have.a.property('convert').and.to.be.a('function');
|
||||
await assertImage(await images[i].convert(), 'image/jpeg', control);
|
||||
}
|
||||
});
|
||||
|
||||
it('converts multiple images inside a single file to png', async () => {
|
||||
const controls = await Promise.all([
|
||||
readControl('0003-0-control.png'),
|
||||
readControl('0003-1-control.png'),
|
||||
]);
|
||||
const buffer = await readFile(path.resolve(root, 'temp', '0003.heic'));
|
||||
const images = await convert.all({ buffer, format: 'PNG' });
|
||||
|
||||
expect(images).to.have.lengthOf(3);
|
||||
|
||||
for (let { i, control } of [
|
||||
{ i: 0, control: controls[0] },
|
||||
{ i: 1, control: controls[1] },
|
||||
{ i: 2, control: controls[1] },
|
||||
]) {
|
||||
expect(images[i]).to.have.a.property('convert').and.to.be.a('function');
|
||||
await assertImage(await images[i].convert(), 'image/png', control);
|
||||
}
|
||||
});
|
||||
|
||||
[
|
||||
{ when: 'converting only the main image', method: convert },
|
||||
{ when: 'converting all images', method: convert.all }
|
||||
].forEach(({ when, method }) => {
|
||||
it(`errors for an unknown output format when ${when}`, async () => {
|
||||
const buffer = Buffer.from(Math.random().toString() + Math.random().toString());
|
||||
|
||||
let error;
|
||||
|
||||
await method({ buffer, format: 'PINEAPPLES' }).catch(err => {
|
||||
error = err;
|
||||
});
|
||||
|
||||
expect(error).to.be.instanceof(Error)
|
||||
.and.to.have.property('message', 'output format needs to be one of [JPEG,PNG]');
|
||||
});
|
||||
|
||||
it(`errors if data other than a HEIC image is passed in when ${when}`, async () => {
|
||||
const buffer = Buffer.from(Math.random().toString() + Math.random().toString());
|
||||
|
||||
let error;
|
||||
|
||||
await method({ buffer, format: 'JPEG' }).catch(err => {
|
||||
error = err;
|
||||
});
|
||||
|
||||
expect(error).to.be.instanceof(TypeError)
|
||||
.and.to.have.property('message', 'input buffer is not a HEIC image');
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user