Skip to content

Commit

Permalink
abstracting tests to exist in a separate file, let them be required a…
Browse files Browse the repository at this point in the history
…nd run as a library
  • Loading branch information
catdad committed Nov 28, 2023
1 parent ad3f4ca commit 2a3d82d
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 146 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
151 changes: 6 additions & 145 deletions test/index.test.js
Original file line number Diff line number Diff line change
@@ -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;
});
describe('heic-convert (default wasm)', () => {
runTests(require('..'));
});

expect(error).to.be.instanceof(TypeError)
.and.to.have.property('message', 'input buffer is not a HEIC image');
});
});
describe('heic-convert (legacy js)', () => {
runTests(require('../legacy'));
});
148 changes: 148 additions & 0 deletions test/run-tests.js
Original file line number Diff line number Diff line change
@@ -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');
});
});
}

0 comments on commit 2a3d82d

Please sign in to comment.