From 2329144c906f07b9d2551fce2148988327050dc3 Mon Sep 17 00:00:00 2001 From: Mark van Seventer Date: Sun, 16 Aug 2026 21:26:23 -0700 Subject: [PATCH 1/6] Bump version. --- package-lock.json | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 53c6e97..704c9a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "glob": "13.0.x", "sharp": "0.35.3", - "yargs": "^17.6.2" + "yargs": "17.7.x" }, "bin": { "sharp": "bin/cli.js" @@ -25,7 +25,7 @@ "mocha": "11.8.x", "must": "0.13.x", "nyc": "18.0.x", - "prettier": "3.9.6", + "prettier": "3.9.x", "sinon": "22.1.x", "tempy": "3.2.x" }, diff --git a/package.json b/package.json index 9087930..86982fe 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "dependencies": { "glob": "13.0.x", "sharp": "0.35.3", - "yargs": "^17.6.2" + "yargs": "17.7.x" }, "devDependencies": { "@eslint/js": "9.39.x", @@ -42,7 +42,7 @@ "mocha": "11.8.x", "must": "0.13.x", "nyc": "18.0.x", - "prettier": "3.9.6", + "prettier": "3.9.x", "sinon": "22.1.x", "tempy": "3.2.x" }, From d03ca5f673e98986c3de77762727bc76a6884b77 Mon Sep 17 00:00:00 2001 From: Mark van Seventer Date: Sun, 16 Aug 2026 21:42:59 -0700 Subject: [PATCH 2/6] Refactor to use internal queue, and allow metadata access. --- cmd/channel-manipulation/bandbool.js | 6 +- cmd/channel-manipulation/ensure-alpha.js | 8 +- cmd/channel-manipulation/extract-channel.js | 3 +- cmd/channel-manipulation/join-channel.js | 8 +- cmd/channel-manipulation/remove-alpha.js | 7 +- cmd/colour-manipulation/greyscale.js | 6 +- .../pipeline-colourspace.js | 3 +- cmd/colour-manipulation/tint.js | 6 +- cmd/colour-manipulation/tocolourspace.js | 3 +- cmd/compositing/composite.js | 3 +- cmd/operations/affine.js | 3 +- cmd/operations/blur.js | 5 +- cmd/operations/boolean.js | 3 +- cmd/operations/clahe.js | 5 +- cmd/operations/convolve.js | 3 +- cmd/operations/dilate.js | 5 +- cmd/operations/erode.js | 5 +- cmd/operations/flatten.js | 5 +- cmd/operations/flip.js | 6 +- cmd/operations/flop.js | 6 +- cmd/operations/gamma.js | 5 +- cmd/operations/linear.js | 5 +- cmd/operations/median.js | 5 +- cmd/operations/modulate.js | 6 +- cmd/operations/negate.js | 5 +- cmd/operations/normalise.js | 3 +- cmd/operations/recomb.js | 5 +- cmd/operations/rotate.js | 5 +- cmd/operations/sharpen.js | 3 +- cmd/operations/threshold.js | 5 +- cmd/operations/unflatten.js | 6 +- cmd/output.js | 3 +- cmd/resizing/extend.js | 3 +- cmd/resizing/extract.js | 3 +- cmd/resizing/resize.js | 3 +- cmd/resizing/trim.js | 5 +- lib/cli.js | 561 +++++++++--------- lib/constants.js | 2 +- lib/convert.js | 94 +-- lib/index.js | 14 +- lib/utils.js | 8 +- test/cmd/channel-manipulation/bandbool.js | 15 +- test/cmd/channel-manipulation/ensure-alpha.js | 24 +- .../channel-manipulation/extract-channel.js | 15 +- test/cmd/channel-manipulation/join-channel.js | 15 +- test/cmd/channel-manipulation/remove-alpha.js | 15 +- test/cmd/colour-manipulation/greyscale.js | 15 +- .../pipeline-colourspace.js | 15 +- test/cmd/colour-manipulation/tint.js | 15 +- test/cmd/colour-manipulation/tocolourspace.js | 15 +- test/cmd/compositing/composite.js | 122 ++-- test/cmd/operations/affine.js | 48 +- test/cmd/operations/blur.js | 46 +- test/cmd/operations/boolean.js | 15 +- test/cmd/operations/clahe.js | 26 +- test/cmd/operations/convolve.js | 51 +- test/cmd/operations/dilate.js | 24 +- test/cmd/operations/erode.js | 24 +- test/cmd/operations/flatten.js | 24 +- test/cmd/operations/flip.js | 15 +- test/cmd/operations/flop.js | 15 +- test/cmd/operations/gamma.js | 33 +- test/cmd/operations/linear.js | 33 +- test/cmd/operations/median.js | 24 +- test/cmd/operations/modulate.js | 24 +- test/cmd/operations/negate.js | 24 +- test/cmd/operations/normalise.js | 33 +- test/cmd/operations/recomb.js | 15 +- test/cmd/operations/rotate.js | 33 +- test/cmd/operations/sharpen.js | 51 +- test/cmd/operations/threshold.js | 33 +- test/cmd/operations/unflatten.js | 15 +- test/cmd/output.js | 114 ++-- test/cmd/resizing/extend.js | 45 +- test/cmd/resizing/extract.js | 15 +- test/cmd/resizing/resize.js | 110 ++-- test/cmd/resizing/trim.js | 42 +- lib/queue.js => test/test-utils.js | 34 +- 78 files changed, 1041 insertions(+), 1039 deletions(-) rename lib/queue.js => test/test-utils.js (71%) diff --git a/cmd/channel-manipulation/bandbool.js b/cmd/channel-manipulation/bandbool.js index b1b6fae..6072ad5 100644 --- a/cmd/channel-manipulation/bandbool.js +++ b/cmd/channel-manipulation/bandbool.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; // Configure. const positionals = { @@ -51,7 +50,10 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push(["bandbool", (sharp) => sharp.bandbool(args.operator)]); + return args["#queue"].push([ + "bandbool", + (sharp) => sharp.bandbool(args.operator), + ]); }; // Exports. diff --git a/cmd/channel-manipulation/ensure-alpha.js b/cmd/channel-manipulation/ensure-alpha.js index 6cd482e..83395c8 100644 --- a/cmd/channel-manipulation/ensure-alpha.js +++ b/cmd/channel-manipulation/ensure-alpha.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-channel#ensurealpha -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { alpha: { @@ -55,7 +52,10 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push(["ensureAlpha", (sharp) => sharp.ensureAlpha(args.alpha)]); + return args["#queue"].push([ + "ensureAlpha", + (sharp) => sharp.ensureAlpha(args.alpha), + ]); }; // Exports. diff --git a/cmd/channel-manipulation/extract-channel.js b/cmd/channel-manipulation/extract-channel.js index 3b8eb99..f24344d 100644 --- a/cmd/channel-manipulation/extract-channel.js +++ b/cmd/channel-manipulation/extract-channel.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; // Configure. const positionals = { @@ -51,7 +50,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "extractChannel", (sharp) => sharp.extractChannel(args.channel), ]); diff --git a/cmd/channel-manipulation/join-channel.js b/cmd/channel-manipulation/join-channel.js index bf00d87..6440e06 100644 --- a/cmd/channel-manipulation/join-channel.js +++ b/cmd/channel-manipulation/join-channel.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-channel#joinchannel -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { images: { @@ -47,7 +44,10 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push(["joinChannel", (sharp) => sharp.joinChannel(args.images)]); + return args["#queue"].push([ + "joinChannel", + (sharp) => sharp.joinChannel(args.images), + ]); }; // Exports. diff --git a/cmd/channel-manipulation/remove-alpha.js b/cmd/channel-manipulation/remove-alpha.js index c54f4f2..7718837 100644 --- a/cmd/channel-manipulation/remove-alpha.js +++ b/cmd/channel-manipulation/remove-alpha.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-channel#removealpha -// Local modules. -import queue from "../../lib/queue.js"; - // Command builder. const builder = (yargs) => { return yargs @@ -37,8 +34,8 @@ const builder = (yargs) => { }; // Command handler. -const handler = () => - queue.push(["removeAlpha", (sharp) => sharp.removeAlpha()]); +const handler = (args) => + args["#queue"].push(["removeAlpha", (sharp) => sharp.removeAlpha()]); // Exports. export default { diff --git a/cmd/colour-manipulation/greyscale.js b/cmd/colour-manipulation/greyscale.js index c04ab9a..71d3343 100644 --- a/cmd/colour-manipulation/greyscale.js +++ b/cmd/colour-manipulation/greyscale.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-colour#greyscale -// Local modules. -import queue from "../../lib/queue.js"; - // Command builder. const builder = (yargs) => { return yargs @@ -40,7 +37,8 @@ const builder = (yargs) => { }; // Command handler. -const handler = () => queue.push(["greyscale", (sharp) => sharp.greyscale()]); +const handler = (args) => + args["#queue"].push(["greyscale", (sharp) => sharp.greyscale()]); // Exports. export default { diff --git a/cmd/colour-manipulation/pipeline-colourspace.js b/cmd/colour-manipulation/pipeline-colourspace.js index 540dd25..cb0f460 100644 --- a/cmd/colour-manipulation/pipeline-colourspace.js +++ b/cmd/colour-manipulation/pipeline-colourspace.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; // Configure. const positionals = { @@ -52,7 +51,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "pipelineColourspace", (sharp) => sharp.pipelineColourspace(args.colourspace), ]); diff --git a/cmd/colour-manipulation/tint.js b/cmd/colour-manipulation/tint.js index 1d61fe7..f017870 100644 --- a/cmd/colour-manipulation/tint.js +++ b/cmd/colour-manipulation/tint.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-colour#tint -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { rgb: { @@ -46,7 +43,8 @@ const builder = (yargs) => { }; // Command handler. -const handler = (args) => queue.push(["tint", (sharp) => sharp.tint(args.rgb)]); +const handler = (args) => + args["#queue"].push(["tint", (sharp) => sharp.tint(args.rgb)]); // Exports. export default { diff --git a/cmd/colour-manipulation/tocolourspace.js b/cmd/colour-manipulation/tocolourspace.js index 769a412..fefc399 100644 --- a/cmd/colour-manipulation/tocolourspace.js +++ b/cmd/colour-manipulation/tocolourspace.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; // Configure. const positionals = { @@ -49,7 +48,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "toColourspace", (sharp) => sharp.toColourspace(args.colourspace), ]); diff --git a/cmd/compositing/composite.js b/cmd/compositing/composite.js index 739ac95..78a85da 100644 --- a/cmd/compositing/composite.js +++ b/cmd/compositing/composite.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; // Helpers. function getValueAt(arrayLike, index) { @@ -177,7 +176,7 @@ const handler = (args) => { if (args.images) inputs.push(...args.images); // @see http://sharp.pixelplumbing.com/api-composite#composite - return queue.push([ + return args["#queue"].push([ "composite", (sharp) => { return sharp.composite( diff --git a/cmd/operations/affine.js b/cmd/operations/affine.js index df4e27a..2e3aa6b 100644 --- a/cmd/operations/affine.js +++ b/cmd/operations/affine.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; import { pick } from "../../lib/utils.js"; // Configure. @@ -92,7 +91,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "affine", (sharp) => { const { matrix } = args; diff --git a/cmd/operations/blur.js b/cmd/operations/blur.js index c37aaa5..83031d7 100644 --- a/cmd/operations/blur.js +++ b/cmd/operations/blur.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#blur -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { sigma: { @@ -68,7 +65,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "blur", (sharp) => { if (args.minAmplitude || args.precision) { diff --git a/cmd/operations/boolean.js b/cmd/operations/boolean.js index 8d5c864..dbfcca5 100644 --- a/cmd/operations/boolean.js +++ b/cmd/operations/boolean.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; // Configure. const positionals = { @@ -53,7 +52,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "boolean", (sharp) => sharp.boolean(args.operand, args.operator), ]); diff --git a/cmd/operations/clahe.js b/cmd/operations/clahe.js index a260fe9..117ef30 100644 --- a/cmd/operations/clahe.js +++ b/cmd/operations/clahe.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#clahe -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { height: { @@ -63,7 +60,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "clahe", (sharp) => { return sharp.clahe({ diff --git a/cmd/operations/convolve.js b/cmd/operations/convolve.js index 698174a..47b583f 100644 --- a/cmd/operations/convolve.js +++ b/cmd/operations/convolve.js @@ -24,7 +24,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#convolve // Local modules. -import queue from "../../lib/queue.js"; import { pick } from "../../lib/utils.js"; // Configure. @@ -86,7 +85,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "convolve", (sharp) => { return sharp.convolve({ diff --git a/cmd/operations/dilate.js b/cmd/operations/dilate.js index 39277c9..471b170 100644 --- a/cmd/operations/dilate.js +++ b/cmd/operations/dilate.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#dilate -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { width: { @@ -49,7 +46,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push(["dilate", (sharp) => sharp.dilate(args.width)]); + return args["#queue"].push(["dilate", (sharp) => sharp.dilate(args.width)]); }; // Exports. diff --git a/cmd/operations/erode.js b/cmd/operations/erode.js index b1a2dbb..94503d8 100644 --- a/cmd/operations/erode.js +++ b/cmd/operations/erode.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#erode -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { width: { @@ -49,7 +46,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push(["erode", (sharp) => sharp.erode(args.width)]); + return args["#queue"].push(["erode", (sharp) => sharp.erode(args.width)]); }; // Exports. diff --git a/cmd/operations/flatten.js b/cmd/operations/flatten.js index 8d2a87f..33e4833 100644 --- a/cmd/operations/flatten.js +++ b/cmd/operations/flatten.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#flatten -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { background: { @@ -48,7 +45,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "flatten", (sharp) => { return sharp.flatten({ background: args.background }); diff --git a/cmd/operations/flip.js b/cmd/operations/flip.js index 179f5ad..387b0cd 100644 --- a/cmd/operations/flip.js +++ b/cmd/operations/flip.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#flip -// Local modules. -import queue from "../../lib/queue.js"; - // Command builder. const builder = (yargs) => { return yargs @@ -37,7 +34,8 @@ const builder = (yargs) => { }; // Command handler. -const handler = () => queue.push(["flip", (sharp) => sharp.flip()]); +const handler = (args) => + args["#queue"].push(["flip", (sharp) => sharp.flip()]); // Exports. export default { diff --git a/cmd/operations/flop.js b/cmd/operations/flop.js index 0902683..06e8027 100644 --- a/cmd/operations/flop.js +++ b/cmd/operations/flop.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#flop -// Local modules. -import queue from "../../lib/queue.js"; - // Command builder. const builder = (yargs) => { return yargs @@ -37,7 +34,8 @@ const builder = (yargs) => { }; // Command handler. -const handler = () => queue.push(["flop", (sharp) => sharp.flop()]); +const handler = (args) => + args["#queue"].push(["flop", (sharp) => sharp.flop()]); // Exports. export default { diff --git a/cmd/operations/gamma.js b/cmd/operations/gamma.js index b65dd0b..6a086ab 100644 --- a/cmd/operations/gamma.js +++ b/cmd/operations/gamma.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#gamma -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { gamma: { @@ -53,7 +50,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => - queue.push([ + args["#queue"].push([ "gamma", (sharp) => { return sharp.gamma(args.gamma, args.gammaOut); diff --git a/cmd/operations/linear.js b/cmd/operations/linear.js index 955169d..b8e77ae 100644 --- a/cmd/operations/linear.js +++ b/cmd/operations/linear.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#linear -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { multiplier: { @@ -61,7 +58,7 @@ const builder = (yargs) => { const handler = (args) => { const multiplier = args.multiplier.length === 1 ? args.multiplier[0] : args.multiplier; - return queue.push([ + return args["#queue"].push([ "linear", (sharp) => sharp.linear(multiplier, args.offset), ]); diff --git a/cmd/operations/median.js b/cmd/operations/median.js index 0650b5f..15497d6 100644 --- a/cmd/operations/median.js +++ b/cmd/operations/median.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#median -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { size: { @@ -49,7 +46,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push(["median", (sharp) => sharp.median(args.size)]); + return args["#queue"].push(["median", (sharp) => sharp.median(args.size)]); }; // Exports. diff --git a/cmd/operations/modulate.js b/cmd/operations/modulate.js index 8e06e31..3aa53e6 100644 --- a/cmd/operations/modulate.js +++ b/cmd/operations/modulate.js @@ -24,7 +24,6 @@ // @see http://sharp.pixelplumbing.com/api-operation#modulate // Local modules. -import queue from "../../lib/queue.js"; import { pick } from "../../lib/utils.js"; // Configure. @@ -71,7 +70,10 @@ const builder = (yargs) => { // Command handler. const handler = (args) => - queue.push(["modulate", (sharp) => sharp.modulate(pick(args, optionNames))]); + args["#queue"].push([ + "modulate", + (sharp) => sharp.modulate(pick(args, optionNames)), + ]); // Exports. export default { diff --git a/cmd/operations/negate.js b/cmd/operations/negate.js index 7a26328..23afa93 100644 --- a/cmd/operations/negate.js +++ b/cmd/operations/negate.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#negate -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const options = { alpha: { @@ -49,7 +46,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => - queue.push(["negate", (sharp) => sharp.negate(args.alpha)]); + args["#queue"].push(["negate", (sharp) => sharp.negate(args.alpha)]); // Exports. export default { diff --git a/cmd/operations/normalise.js b/cmd/operations/normalise.js index 0523ed9..eff86c2 100644 --- a/cmd/operations/normalise.js +++ b/cmd/operations/normalise.js @@ -24,7 +24,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#normalise // Local modules. -import queue from "../../lib/queue.js"; import { pick } from "../../lib/utils.js"; const options = { @@ -55,7 +54,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => - queue.push([ + args["#queue"].push([ "normalise", (sharp) => sharp.normalise(pick(args, optionNames)), ]); diff --git a/cmd/operations/recomb.js b/cmd/operations/recomb.js index 6657a5a..50dd6e0 100644 --- a/cmd/operations/recomb.js +++ b/cmd/operations/recomb.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#recomb -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const placeholders = { matrix: { @@ -58,7 +55,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { const { matrix } = args; - return queue.push([ + return args["#queue"].push([ "recomb", (sharp) => { return sharp.recomb([ diff --git a/cmd/operations/rotate.js b/cmd/operations/rotate.js index dcd2055..dbb3b9b 100644 --- a/cmd/operations/rotate.js +++ b/cmd/operations/rotate.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#rotate -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { angle: { @@ -62,7 +59,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "rotate", (sharp) => sharp.rotate(args.angle, { background: args.background }), ]); diff --git a/cmd/operations/sharpen.js b/cmd/operations/sharpen.js index 92ce3ab..ccec3d6 100644 --- a/cmd/operations/sharpen.js +++ b/cmd/operations/sharpen.js @@ -24,7 +24,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#sharpen // Local modules. -import queue from "../../lib/queue.js"; import { pick } from "../../lib/utils.js"; // Configure. @@ -89,7 +88,7 @@ const handler = (args) => { ...pick(args, optionNames), }; - return queue.push([ + return args["#queue"].push([ "sharpen", (sharp) => { if (Object.keys(options).length === 0) { diff --git a/cmd/operations/threshold.js b/cmd/operations/threshold.js index f9510ba..35c2a97 100644 --- a/cmd/operations/threshold.js +++ b/cmd/operations/threshold.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#threshold -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { value: { @@ -58,7 +55,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "threshold", (sharp) => { return sharp.threshold(args.value, { greyscale: args.greyscale }); diff --git a/cmd/operations/unflatten.js b/cmd/operations/unflatten.js index 1b63bba..7412397 100644 --- a/cmd/operations/unflatten.js +++ b/cmd/operations/unflatten.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-operation#unflatten -// Local modules. -import queue from "../../lib/queue.js"; - // Command builder. const builder = (yargs) => { return yargs @@ -37,7 +34,8 @@ const builder = (yargs) => { }; // Command handler. -const handler = () => queue.push(["unflatten", (sharp) => sharp.unflatten()]); +const handler = (args) => + args["#queue"].push(["unflatten", (sharp) => sharp.unflatten()]); // Exports. export default { diff --git a/cmd/output.js b/cmd/output.js index 041598c..d100191 100644 --- a/cmd/output.js +++ b/cmd/output.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../lib/constants.js"; -import queue from "../lib/queue.js"; import { pick } from "../lib/utils.js"; // Configure. @@ -108,7 +107,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "tile", (sharp) => { return sharp.tile({ diff --git a/cmd/resizing/extend.js b/cmd/resizing/extend.js index 71c5025..9e77996 100644 --- a/cmd/resizing/extend.js +++ b/cmd/resizing/extend.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; import { pick } from "../../lib/utils.js"; // Configure. @@ -87,7 +86,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "extend", (sharp) => { return sharp.extend({ diff --git a/cmd/resizing/extract.js b/cmd/resizing/extract.js index a61378b..ed1479f 100644 --- a/cmd/resizing/extract.js +++ b/cmd/resizing/extract.js @@ -24,7 +24,6 @@ // @see https://sharp.pixelplumbing.com/api-resize#extract // Local modules. -import queue from "../../lib/queue.js"; import { pick } from "../../lib/utils.js"; // Configure. @@ -62,7 +61,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "extract", (sharp) => { return sharp.extract(pick(args, Object.keys(positionals))); diff --git a/cmd/resizing/resize.js b/cmd/resizing/resize.js index fcaf239..d9520dc 100644 --- a/cmd/resizing/resize.js +++ b/cmd/resizing/resize.js @@ -25,7 +25,6 @@ // Local modules. import constants from "../../lib/constants.js"; -import queue from "../../lib/queue.js"; import { pick } from "../../lib/utils.js"; // Configure. @@ -131,7 +130,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { // @see https://sharp.pixelplumbing.com/api-resize#resize - return queue.push([ + return args["#queue"].push([ "resize", (sharp) => { return sharp.resize(args.width, args.height, pick(args, optionNames)); diff --git a/cmd/resizing/trim.js b/cmd/resizing/trim.js index 628df41..ca59249 100644 --- a/cmd/resizing/trim.js +++ b/cmd/resizing/trim.js @@ -23,9 +23,6 @@ // @see https://sharp.pixelplumbing.com/api-resize#trim -// Local modules. -import queue from "../../lib/queue.js"; - // Configure. const positionals = { threshold: { @@ -76,7 +73,7 @@ const builder = (yargs) => { // Command handler. const handler = (args) => { - return queue.push([ + return args["#queue"].push([ "trim", (sharp) => { return sharp.trim({ diff --git a/lib/cli.js b/lib/cli.js index b092fe9..c755848 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -23,7 +23,7 @@ // Package modules. import sharp from "sharp"; -import yargsFactory from "yargs"; +import yargs from "yargs"; // Local modules. import affine from "../cmd/operations/affine.js"; @@ -63,14 +63,11 @@ import toColourspace from "../cmd/colour-manipulation/tocolourspace.js"; import trim from "../cmd/resizing/trim.js"; import unflatten from "../cmd/operations/unflatten.js"; import constants from "./constants.js"; -import queue from "./queue.js"; import { pick } from "./utils.js"; // Assets. import pkg from "../package.json" with { type: "json" }; -const yargs = yargsFactory(); - // Configure. const IS_TEXT_TERMINAL = process.stdin.isTTY; @@ -89,6 +86,7 @@ const globalOptions = { desc: "Path to (an) image file(s)", group: global, implies: "output", + requiresArg: true, type: "array", }, @@ -99,6 +97,7 @@ const globalOptions = { demand: IS_TEXT_TERMINAL, desc: "Directory or URI template to write the image files to", group: global, + nargs: 1, type: "string", }, @@ -106,12 +105,13 @@ const globalOptions = { timeout: { desc: "Number of seconds after which processing will be stopped", group: global, + nargs: 1, type: "number", }, }; // @see https://sharp.pixelplumbing.com/api-constructor -const inputOptions = { +export const inputOptions = { animated: { desc: "Read all frames/pages of an animated image", group: input, @@ -588,8 +588,13 @@ const options = { ...optimizationOptions, }; +// Helpers. +function createContext() { + return { "#queue": [] }; +} + // Configure. -const cli = yargs +const cli = yargs() .parserConfiguration({ "populate--": true }) .strict() .usage("$0 [command..]") @@ -628,7 +633,6 @@ const cli = yargs .group(["help", "version"], "Misc. Options") // Commands. - // Avoid `yargs.commandDir()` as it uses insertion order, not alphabetical. .command(affine) .command(bandbool) .command(blur) @@ -666,286 +670,275 @@ const cli = yargs .command(trim) .command(unflatten); -// Helpers. -const originalParse = cli.parse.bind(cli); -const promisifiedParse = (...args) => { - return new Promise((resolve, reject) => { - originalParse(...args, (err, argv, output) => { - if (err) { - reject(err); - } - if (argv.v || argv.help) { - reject(output); - } +// Intercept parsing as to orchestrate commands. +cli.parseAsync = async function (args, context = createContext()) { + // Capture parsing result as a promise. + const argv = await new Promise((resolve, reject) => { + return cli.parse(args, context, (err, argv, output) => { + if (err) reject(err); + if (argv.help || argv.v) reject(output); resolve(argv); }); }); + + // Invoke with remaining arguments (if any). Carry over global options. + const remainingArgv = argv["--"] ?? []; + if (remainingArgv.length > 0) { + const globalArgv = pick(argv, Object.keys(options)); + return cli.default(globalArgv).parseAsync(remainingArgv, context); + } + + // Apply global options (once). + const queue = context["#queue"]; + + // @see https://sharp.pixelplumbing.com/api-output#timeout + if (argv.timeout) { + queue.unshift([ + "timeout", + (sharp) => sharp.timeout({ seconds: argv.timeout }), + ]); + } + + // Output options. + + // @see https://sharp.pixelplumbing.com/api-output#toformat + if (argv.format) { + queue.unshift([ + "format", + (sharp) => + sharp.toFormat(argv.format, { compression: argv.hcompression }), + ]); + } + + // @see https://sharp.pixelplumbing.com/api-output#withmetadata + if (argv.metadata) { + queue.unshift([ + "withMetadata", + (sharp) => sharp.withMetadata(argv.metadata), + ]); + } + + // @see https://sharp.pixelplumbing.com/api-output#heif + const { heif } = sharp.format; + if ( + argv.hcompression !== optimizationOptions.hcompression.default || // HEIF-specific. + // Ensure libheif is installed before applying generic options. + (heif.input && + heif.input.file && + (argv.effort !== undefined || + argv.hbitdepth || + argv.lossless || + argv.quality)) + ) { + queue.unshift([ + "heif", + (sharp, { format } = {}) => { + if (format && format !== "heif") return sharp; + return sharp.heif({ + bitdepth: argv.hbitdepth, + compression: argv.hcompression, + effort: argv.effort, + force: false, + lossless: argv.lossless, + quality: argv.quality, + }); + }, + ]); + } + + // @see https://sharp.pixelplumbing.com/api-output#avif + if ( + argv.chromaSubsampling || + argv.effort !== undefined || + argv.lossless || + argv.quality + ) { + queue.unshift([ + "avif", + (sharp, { format } = {}) => { + if (format && format !== "avif") return sharp; + return sharp.avif({ + chromaSubsampling: argv.chromaSubsampling, + effort: argv.effort, + force: false, + lossless: argv.lossless, + quality: argv.quality, + }); + }, + ]); + } + + // @see https://sharp.pixelplumbing.com/api-output#gif + if ( + argv.colors || + argv.effort !== undefined || + argv.dither !== undefined || + argv.interFrameMaxError || + argv.interPaletteMaxError || + argv.keepDuplicateFrames || + argv.loop || + argv.delay !== undefined || + argv.progressive || + argv.reuse + ) { + queue.unshift([ + "gif", + (sharp, { format } = {}) => { + if (format && format !== "gif") return sharp; + return sharp.gif({ + colors: argv.colors, + force: false, + effort: argv.effort, + dither: argv.dither, + interFrameMaxError: argv.interFrameMaxError, + interPaletteMaxError: argv.interPaletteMaxError, + keepDuplicateFrames: argv.keepDuplicateFrames, + loop: argv.loop, + delay: argv.delay, + progressive: argv.progressive, + reuse: argv.reuse, + }); + }, + ]); + } + + // @see https://sharp.pixelplumbing.com/api-output#jpeg + if ( + argv.chromaSubsampling || + argv.mozjpeg || + argv.optimise || + argv.optimiseCoding !== true || + argv.optimiseScans || + argv.overshootDeringing || + argv.progressive || + argv.quantisationTable || + argv.quality || + argv.trellisQuantisation + ) { + queue.unshift([ + "jpeg", + (sharp, { format } = {}) => { + if (format && format !== "jpeg") return sharp; + return sharp.jpeg({ + chromaSubsampling: argv.chromaSubsampling, + force: false, + mozjpeg: argv.mozjpeg, + optimiseCoding: argv.optimiseCoding, + optimiseScans: argv.optimise || argv.optimiseScans, + overshootDeringing: argv.optimise || argv.overshootDeringing, + progressive: argv.progressive, + quality: argv.quality, + quantisationTable: argv.quantisationTable, + trellisQuantisation: argv.optimise || argv.trellisQuantisation, + }); + }, + ]); + } + + // @see https://sharp.pixelplumbing.com/api-output#png + if ( + argv.adaptiveFiltering || + argv.colors || + argv.compressionLevel !== undefined || + argv.dither !== undefined || + argv.effort || + argv.palette || + argv.progressive + ) { + queue.unshift([ + "png", + (sharp, { format } = {}) => { + if (format && format !== "png") return sharp; + return sharp.png({ + adaptiveFiltering: argv.adaptiveFiltering, + colors: argv.colors, + compressionLevel: argv.compressionLevel, + dither: argv.dither, + effort: argv.effort, + force: false, + palette: argv.palette, + progressive: argv.progressive, + }); + }, + ]); + } + + // @see https://sharp.pixelplumbing.com/api-output#tiff + if ( + argv.bigtiff || + argv.bitdepth || + argv.compression !== optimizationOptions.compression.default || + argv.predictor !== optimizationOptions.predictor.default || + argv.miniswhite || + argv.pyramid || + argv.quality || + argv.resolutionUnit || + argv.tileBackground || + argv.tileHeight || + argv.tileWidth || + argv.xres || + argv.yres + ) { + queue.unshift([ + "tiff", + (sharp, { format } = {}) => { + if (format && format !== "tiff") return sharp; + return sharp.tiff({ + background: argv.tileBackground, + bigtiff: argv.bigtiff, + bitdepth: argv.bitdepth, + compression: argv.compression, + force: false, + miniswhite: argv.miniswhite, + predictor: argv.predictor, + pyramid: argv.pyramid, + quality: argv.quality, + resolutionUnit: argv.resolutionUnit, + tile: argv.tileWidth !== undefined || argv.tileHeight !== undefined, + tileHeight: argv.tileHeight || argv.tileWidth, + tileWidth: argv.tileWidth || argv.tileHeight, + xres: argv.xres, + yres: argv.yres, + }); + }, + ]); + } + + // @see https://sharp.pixelplumbing.com/api-output#webp + if ( + argv.alphaQuality || + argv.quality || + argv.lossless || + argv.minSize || + argv.mixed || + argv.nearLossless || + argv.effort !== undefined || + argv.preset !== optimizationOptions.preset.default || + argv.smartDeblock || + argv.smartSubsample + ) { + queue.unshift([ + "webp", + (sharp, { format } = {}) => { + if (format && format !== "webp") return sharp; + return sharp.webp({ + alphaQuality: argv.alphaQuality, + effort: argv.effort, + force: false, + lossless: argv.lossless, + minSize: argv.minSize, + mixed: argv.mixed, + nearLossless: argv.nearLossless, + preset: argv.preset, + quality: argv.quality, + smartDeblock: argv.smartDeblock, + smartSubsample: argv.smartSubsample, + }); + }, + ]); + } + + return argv; }; -// Exports. export default cli; -cli.inputOptions = Object.keys(inputOptions); -cli.parse = function recursiveParse(args, context = {}) { - return promisifiedParse(args, context).then((argv) => { - // Handle arguments. - // NOTE Use queue.unshift to apply global options first. - - // Global options. - - // Require at least one input file. - // NOTE: check here b/c https://github.com/yargs/yargs/issues/403 - if (argv.input && argv.input.length === 0) { - throw new Error("Not enough arguments following: i, input"); - } - - // @see https://sharp.pixelplumbing.com/api-output#timeout - if (argv.timeout) { - queue.unshift([ - "timeout", - (sharp) => sharp.timeout({ seconds: argv.timeout }), - ]); - } - - // Output options. - - // @see https://sharp.pixelplumbing.com/api-output#toformat - if (argv.format) { - queue.unshift([ - "format", - (sharp) => - sharp.toFormat(argv.format, { compression: argv.hcompression }), - ]); - } - - // @see https://sharp.pixelplumbing.com/api-output#withmetadata - if (argv.metadata) { - queue.unshift([ - "withMetadata", - (sharp) => sharp.withMetadata(argv.metadata), - ]); - } - - // @see https://sharp.pixelplumbing.com/api-output#heif - const { heif } = sharp.format; - if ( - argv.hcompression !== optimizationOptions.hcompression.default || // HEIF-specific. - // Ensure libheif is installed before applying generic options. - (heif.input && - heif.input.file && - (argv.effort !== undefined || - argv.hbitdepth || - argv.lossless || - argv.quality)) - ) { - queue.unshift([ - "heif", - (sharp) => { - return sharp.heif({ - bitdepth: argv.hbitdepth, - compression: argv.hcompression, - effort: argv.effort, - force: false, - lossless: argv.lossless, - quality: argv.quality, - }); - }, - ]); - } - - // @see https://sharp.pixelplumbing.com/api-output#avif - if ( - argv.chromaSubsampling || - argv.effort !== undefined || - argv.lossless || - argv.quality - ) { - queue.unshift([ - "avif", - (sharp) => { - return sharp.avif({ - chromaSubsampling: argv.chromaSubsampling, - effort: argv.effort, - force: false, - lossless: argv.lossless, - quality: argv.quality, - }); - }, - ]); - } - - // @see https://sharp.pixelplumbing.com/api-output#gif - if ( - argv.colors || - argv.effort !== undefined || - argv.dither !== undefined || - argv.interFrameMaxError || - argv.interPaletteMaxError || - argv.keepDuplicateFrames || - argv.loop || - argv.delay !== undefined || - argv.progressive || - argv.reuse - ) { - queue.unshift([ - "gif", - (sharp) => { - return sharp.gif({ - colors: argv.colors, - force: false, - effort: argv.effort, - dither: argv.dither, - interFrameMaxError: argv.interFrameMaxError, - interPaletteMaxError: argv.interPaletteMaxError, - keepDuplicateFrames: argv.keepDuplicateFrames, - loop: argv.loop, - delay: argv.delay, - progressive: argv.progressive, - reuse: argv.reuse, - }); - }, - ]); - } - - // @see https://sharp.pixelplumbing.com/api-output#jpeg - if ( - argv.chromaSubsampling || - argv.mozjpeg || - argv.optimise || - argv.optimiseCoding !== true || - argv.optimiseScans || - argv.overshootDeringing || - argv.progressive || - argv.quantisationTable || - argv.quality || - argv.trellisQuantisation - ) { - queue.unshift([ - "jpeg", - (sharp) => { - return sharp.jpeg({ - chromaSubsampling: argv.chromaSubsampling, - force: false, - mozjpeg: argv.mozjpeg, - optimiseCoding: argv.optimiseCoding, - optimiseScans: argv.optimise || argv.optimiseScans, - overshootDeringing: argv.optimise || argv.overshootDeringing, - progressive: argv.progressive, - quality: argv.quality, - quantisationTable: argv.quantisationTable, - trellisQuantisation: argv.optimise || argv.trellisQuantisation, - }); - }, - ]); - } - - // @see https://sharp.pixelplumbing.com/api-output#png - if ( - argv.adaptiveFiltering || - argv.colors || - argv.compressionLevel !== undefined || - argv.dither !== undefined || - argv.effort || - argv.palette || - argv.progressive - ) { - queue.unshift([ - "png", - (sharp) => { - return sharp.png({ - adaptiveFiltering: argv.adaptiveFiltering, - colors: argv.colors, - compressionLevel: argv.compressionLevel, - dither: argv.dither, - effort: argv.effort, - force: false, - palette: argv.palette, - progressive: argv.progressive, - }); - }, - ]); - } - - // @see https://sharp.pixelplumbing.com/api-output#tiff - if ( - argv.bigtiff || - argv.bitdepth || - argv.compression !== optimizationOptions.compression.default || - argv.predictor !== optimizationOptions.predictor.default || - argv.miniswhite || - argv.pyramid || - argv.quality || - argv.resolutionUnit || - argv.tileBackground || - argv.tileHeight || - argv.tileWidth || - argv.xres || - argv.yres - ) { - queue.unshift([ - "tiff", - (sharp) => { - return sharp.tiff({ - background: argv.tileBackground, - bigtiff: argv.bigtiff, - bitdepth: argv.bitdepth, - compression: argv.compression, - force: false, - miniswhite: argv.miniswhite, - predictor: argv.predictor, - pyramid: argv.pyramid, - quality: argv.quality, - resolutionUnit: argv.resolutionUnit, - tile: argv.tileWidth !== undefined || argv.tileHeight !== undefined, - tileHeight: argv.tileHeight || argv.tileWidth, - tileWidth: argv.tileWidth || argv.tileHeight, - xres: argv.xres, - yres: argv.yres, - }); - }, - ]); - } - - // @see https://sharp.pixelplumbing.com/api-output#webp - if ( - argv.alphaQuality || - argv.quality || - argv.lossless || - argv.minSize || - argv.mixed || - argv.nearLossless || - argv.effort !== undefined || - argv.preset !== optimizationOptions.preset.default || - argv.smartDeblock || - argv.smartSubsample - ) { - queue.unshift([ - "webp", - (sharp) => { - return sharp.webp({ - alphaQuality: argv.alphaQuality, - effort: argv.effort, - force: false, - lossless: argv.lossless, - minSize: argv.minSize, - mixed: argv.mixed, - nearLossless: argv.nearLossless, - preset: argv.preset, - quality: argv.quality, - smartDeblock: argv.smartDeblock, - smartSubsample: argv.smartSubsample, - }); - }, - ]); - } - - // Invoke with remaining arguments (if any). - const { "--": remainingargv = [] } = argv; - if (remainingargv.length > 0) { - return recursiveParse(remainingargv, { - ...context, - ...pick(argv, Object.keys(options)), // Retain options. - }); - } - return argv; - }); -}; diff --git a/lib/constants.js b/lib/constants.js index a498c98..4bf6fe6 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -35,7 +35,7 @@ export default { EXTEND_WITH: ["background", "copy", "repeat", "mirror"], FAIL_ON: ["none", "truncated", "error", "warning"], FIT: Object.keys(sharp.fit), - FORMAT: ["avif", "gif", "heif", "jpeg", "jpg", "png", "tiff", "webp"], + FORMAT: ["avif", "gif", "heif", "jpeg", "png", "tiff", "webp"], GRAVITY: Object.keys(sharp.gravity), HEIF_COMPRESSION: ["hevc", "av1"], INTERPOLATORS: Object.keys(sharp.interpolators), diff --git a/lib/convert.js b/lib/convert.js index 10c6ade..a0d4d91 100644 --- a/lib/convert.js +++ b/lib/convert.js @@ -22,7 +22,6 @@ */ // Standard lib. -import fs from "node:fs"; import path from "node:path"; import { pipeline } from "node:stream/promises"; @@ -31,8 +30,7 @@ import { globSync } from "glob"; import sharp from "sharp"; // Local modules. -import queue from "./queue.js"; -import { isDirectory } from "./utils.js"; +import { drain, isDirectory } from "./utils.js"; // Configure. const EXTENSIONS = { @@ -49,12 +47,9 @@ const EXTENSIONS = { // Exports. export default { // Convert a list of files. - files: (input, output, options) => { + files: async (input, output, context) => { // Resolve files. - const files = input.reduce((list, input) => { - return list.concat(globSync(input, { absolute: true })); - }, []); - + const files = input.flatMap((input) => globSync(input, { absolute: true })); if (files.length === 0) { return Promise.reject(new Error("No input files")); } @@ -62,52 +57,61 @@ export default { // Process files. const isBatch = files.length > 1; const promises = files.map((src) => { - // Create pipeline. - const transformer = queue.drain(sharp(options)); + const image = sharp(src, context.options); + return image.metadata().then((metadata) => { + const format = context.format ?? metadata.format; + const transformer = drain(context.queue, image, { + format, + metadata, + }); - // Process output as a template. - const parts = path.parse(src); - const regex = /\{(root|dir|base|ext|name)\}/g; - let dest = output; - let match; - while ((match = regex.exec(output)) !== null) { - const [search, prop] = match; - dest = dest.replace(search, parts[prop]); - } - dest = path.resolve(dest); + // Process output as a template. + const parts = path.parse(src); + const regex = /\{(root|dir|base|ext|name)\}/g; + let dest = output; + let match; + while ((match = regex.exec(output)) !== null) { + const [search, prop] = match; + dest = dest.replace(search, parts[prop]); + } + dest = path.resolve(dest); - // If output was not a template, assume dest is a directory when using - // batch processing. - const outputAssumeDir = dest === path.resolve(output) && isBatch; - if (outputAssumeDir || isDirectory(dest)) { - const defaultExt = path.extname(src); - const desiredExt = transformer.options.formatOut; - dest = path.format({ - dir: dest, - name: path.basename(src, defaultExt), - ext: desiredExt in EXTENSIONS ? EXTENSIONS[desiredExt] : defaultExt, - }); - } + // If output was not a template, assume dest is a directory when using + // batch processing. + const outputAssumeDir = dest === path.resolve(output) && isBatch; + if (outputAssumeDir || isDirectory(dest)) { + const defaultExt = path.extname(src); + dest = path.format({ + dir: dest, + name: path.basename(src, defaultExt), + ext: format in EXTENSIONS ? EXTENSIONS[format] : defaultExt, + }); + } - // Write, attach info and return. - fs.createReadStream(src).pipe(transformer); - return transformer - .toFile(dest) - .then((info) => Object.assign(info, { src, path: dest })); + return transformer + .toFile(dest) + .then((info) => Object.assign(info, { src, path: dest })); + }); }); return Promise.all(promises); }, // Convert a stream. - stream: (inStream, outStream, options) => { - // Create pipeline. - const transformer = queue.drain(sharp(options)); + stream: async (inStream, outStream, context) => { + const image = sharp(context.options); + return pipeline(inStream, image) + .then(() => image.metadata()) + .then((metadata) => { + const transformer = drain(context.queue, image, { + format: context.format ?? metadata.format, + metadata, + }); - // Gather return value. - const info = {}; - transformer.on("info", (_info) => Object.assign(info, _info)); + // Gather return value. + const info = {}; + transformer.on("info", (_info) => Object.assign(info, _info)); - // Pipe, and return as promise. - return pipeline(inStream, transformer, outStream).then(() => info); + return pipeline(transformer, outStream).then(() => info); + }); }, }; diff --git a/lib/index.js b/lib/index.js index 10ae1f6..a6c6b52 100644 --- a/lib/index.js +++ b/lib/index.js @@ -22,7 +22,7 @@ */ // Local modules. -import cli from "./cli.js"; +import cli, { inputOptions } from "./cli.js"; import convert from "./convert.js"; import { pick } from "./utils.js"; @@ -32,13 +32,17 @@ export default (args, options = {}) => { // Parse arguments and handle i/o. return cli - .parse(args) + .parseAsync(args) .then((argv) => { - const options = pick(argv, cli.inputOptions); + const context = { + format: argv.format, + options: pick(argv, Object.keys(inputOptions)), + queue: argv["#queue"], + }; if (argv.input) { - return convert.files(argv.input, argv.output, options); + return convert.files(argv.input, argv.output, context); } - return convert.stream(process.stdin, process.stdout, options); + return convert.stream(process.stdin, process.stdout, context); }) .then((output) => { const info = Array.isArray(output) ? output : [output]; diff --git a/lib/utils.js b/lib/utils.js index fc5932f..667b9d8 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -24,6 +24,12 @@ // Standard lib. import fs from "node:fs"; +const drain = (queue, transformer, context) => { + return queue.reduce((pipeline, [, handler]) => { + return handler(pipeline, context); + }, transformer); +}; + const isDirectory = (path) => { try { return fs.statSync(path).isDirectory(); @@ -41,4 +47,4 @@ const pick = (object, keys) => { }; // Exports. -export { isDirectory, pick }; +export { drain, isDirectory, pick }; diff --git a/test/cmd/channel-manipulation/bandbool.js b/test/cmd/channel-manipulation/bandbool.js index 12d9db8..edf0e42 100644 --- a/test/cmd/channel-manipulation/bandbool.js +++ b/test/cmd/channel-manipulation/bandbool.js @@ -26,35 +26,34 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import bandbool from "../../../cmd/channel-manipulation/bandbool.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("bandbool ", () => { - const cli = yargsFactory().command(bandbool); + const cli = createInstance().command(bandbool); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse(["bandbool", "and"])); + before(() => cli.parseAsync(["bandbool", "and"])); // Tests. it("must set the operator flag", () => { expect(cli.parsed.argv).to.have.property("operator", "and"); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("bandbool"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("bandbool"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.bandbool, "and"); }); }); diff --git a/test/cmd/channel-manipulation/ensure-alpha.js b/test/cmd/channel-manipulation/ensure-alpha.js index 99f8d4c..c055fae 100644 --- a/test/cmd/channel-manipulation/ensure-alpha.js +++ b/test/cmd/channel-manipulation/ensure-alpha.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import ensureAlpha from "../../../cmd/channel-manipulation/ensure-alpha.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("ensureAlpha", () => { - const cli = yargsFactory().command(ensureAlpha); + const cli = createInstance().command(ensureAlpha); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["ensureAlpha"])); + before(() => cli.parseAsync(["ensureAlpha"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("ensureAlpha"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("ensureAlpha"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.ensureAlpha); }); }); @@ -63,18 +62,19 @@ export default function register() { const alpha = 0; // Run. - beforeEach(() => cli.parse(["ensureAlpha", "--alpha", alpha])); + before(() => cli.parseAsync(["ensureAlpha", "--alpha", alpha])); // Tests. it("must set the alpha flag", () => { expect(cli.parsed.argv).to.have.property("alpha", alpha); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("ensureAlpha"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("ensureAlpha"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.ensureAlpha, alpha); }); }); diff --git a/test/cmd/channel-manipulation/extract-channel.js b/test/cmd/channel-manipulation/extract-channel.js index d79c415..56a2bdf 100644 --- a/test/cmd/channel-manipulation/extract-channel.js +++ b/test/cmd/channel-manipulation/extract-channel.js @@ -26,35 +26,34 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import extractChannel from "../../../cmd/channel-manipulation/extract-channel.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("extractChannel ", () => { - const cli = yargsFactory().command(extractChannel); + const cli = createInstance().command(extractChannel); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse(["extractChannel", "red"])); + before(() => cli.parseAsync(["extractChannel", "red"])); // Tests. it("must set the operator flag", () => { expect(cli.parsed.argv).to.have.property("channel", "red"); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("extractChannel"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("extractChannel"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.extractChannel, "red"); }); }); diff --git a/test/cmd/channel-manipulation/join-channel.js b/test/cmd/channel-manipulation/join-channel.js index b2db4b8..9f3aec7 100644 --- a/test/cmd/channel-manipulation/join-channel.js +++ b/test/cmd/channel-manipulation/join-channel.js @@ -30,17 +30,16 @@ import { fileURLToPath } from "node:url"; // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import joinChannel from "../../../cmd/channel-manipulation/join-channel.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("joinChannel ", () => { - const cli = yargsFactory().command(joinChannel); + const cli = createInstance().command(joinChannel); // Default input (avoid `path.join` to test for input normalizing). const input = fileURLToPath( @@ -48,12 +47,11 @@ export default function register() { ); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("", () => { // Run. - beforeEach(() => cli.parse(["joinChannel", input, input])); + before(() => cli.parseAsync(["joinChannel", input, input])); // Tests. it("must set the operator flag", () => { @@ -65,11 +63,12 @@ export default function register() { ]); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("joinChannel"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("joinChannel"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.joinChannel, [ path.normalize(input), path.normalize(input), diff --git a/test/cmd/channel-manipulation/remove-alpha.js b/test/cmd/channel-manipulation/remove-alpha.js index 9379ddb..71e5d35 100644 --- a/test/cmd/channel-manipulation/remove-alpha.js +++ b/test/cmd/channel-manipulation/remove-alpha.js @@ -26,32 +26,31 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import removeAlpha from "../../../cmd/channel-manipulation/remove-alpha.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("removeAlpha", () => { - const cli = yargsFactory().command(removeAlpha); + const cli = createInstance().command(removeAlpha); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse(["removeAlpha"])); + before(() => cli.parseAsync(["removeAlpha"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("removeAlpha"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("removeAlpha"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.removeAlpha); }); }); diff --git a/test/cmd/colour-manipulation/greyscale.js b/test/cmd/colour-manipulation/greyscale.js index e37b125..e251f9c 100644 --- a/test/cmd/colour-manipulation/greyscale.js +++ b/test/cmd/colour-manipulation/greyscale.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import greyscale from "../../../cmd/colour-manipulation/greyscale.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { ["grayscale", "greyscale"].forEach((alias) => { describe(alias, () => { - const cli = yargsFactory().command(greyscale); + const cli = createInstance().command(greyscale); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse([alias])); + before(() => cli.parseAsync([alias])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("greyscale"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("greyscale"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.greyscale); }); }); diff --git a/test/cmd/colour-manipulation/pipeline-colourspace.js b/test/cmd/colour-manipulation/pipeline-colourspace.js index 3931150..8543087 100644 --- a/test/cmd/colour-manipulation/pipeline-colourspace.js +++ b/test/cmd/colour-manipulation/pipeline-colourspace.js @@ -26,36 +26,35 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; import pipelineColourspace from "../../../cmd/colour-manipulation/pipeline-colourspace.js"; // Test suite. export default function register() { ["pipelineColourspace", "pipelineColorspace"].forEach((alias) => { describe(`${alias} `, () => { - const cli = yargsFactory().command(pipelineColourspace); + const cli = createInstance().command(pipelineColourspace); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse([alias, "srgb"])); + before(() => cli.parseAsync([alias, "srgb"])); // Tests. it("must set the colourspace flag", () => { expect(cli.parsed.argv).to.have.property("colourspace", "srgb"); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("pipelineColourspace"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("pipelineColourspace"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.pipelineColourspace); }); }); diff --git a/test/cmd/colour-manipulation/tint.js b/test/cmd/colour-manipulation/tint.js index c36ec5e..dc9a38e 100644 --- a/test/cmd/colour-manipulation/tint.js +++ b/test/cmd/colour-manipulation/tint.js @@ -26,38 +26,37 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; import tint from "../../../cmd/colour-manipulation/tint.js"; // Test suite. export default function register() { describe("tint ", () => { - const cli = yargsFactory().command(tint); + const cli = createInstance().command(tint); // Default rgb. const rgb = "rgba(0,0,0)"; // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse(["tint", rgb])); + before(() => cli.parseAsync(["tint", rgb])); // Tests. it("must set the colourspace flag", () => { expect(cli.parsed.argv).to.have.property("rgb", rgb); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tint"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tint"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.tint); }); }); diff --git a/test/cmd/colour-manipulation/tocolourspace.js b/test/cmd/colour-manipulation/tocolourspace.js index 0e0eafe..6e2fc0d 100644 --- a/test/cmd/colour-manipulation/tocolourspace.js +++ b/test/cmd/colour-manipulation/tocolourspace.js @@ -26,36 +26,35 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; import toColourspace from "../../../cmd/colour-manipulation/tocolourspace.js"; // Test suite. export default function register() { ["toColorspace", "toColourspace"].forEach((alias) => { describe(`${alias} `, () => { - const cli = yargsFactory().command(toColourspace); + const cli = createInstance().command(toColourspace); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse([alias, "srgb"])); + before(() => cli.parseAsync([alias, "srgb"])); // Tests. it("must set the colourspace flag", () => { expect(cli.parsed.argv).to.have.property("colourspace", "srgb"); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("toColourspace"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("toColourspace"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.toColourspace); }); }); diff --git a/test/cmd/compositing/composite.js b/test/cmd/compositing/composite.js index 0088701..a9c2b25 100644 --- a/test/cmd/compositing/composite.js +++ b/test/cmd/compositing/composite.js @@ -30,17 +30,16 @@ import { fileURLToPath } from "node:url"; // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import composite from "../../../cmd/compositing/composite.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("composite", () => { - const cli = yargsFactory().command(composite); + const cli = createInstance().command(composite); // Default input (avoid `path.join` to test for input normalizing). const input = fileURLToPath( @@ -48,12 +47,11 @@ export default function register() { ); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("[images..]", () => { // Run. - beforeEach(() => cli.parse(["composite", input])); + before(() => cli.parseAsync(["composite", input])); // Tests. it("must set the images flag", () => { @@ -61,11 +59,12 @@ export default function register() { expect(cli.parsed.argv.images[0]).to.equal(path.normalize(input)); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].input", path.normalize(input)), @@ -75,7 +74,7 @@ export default function register() { describe("[options]", () => { it("should roll over when using multiple inputs", async () => { - await cli.parse([ + await cli.parseAsync([ "composite", "--create.width", 20, @@ -95,7 +94,7 @@ export default function register() { "out", ]); - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].input.create.width", 20), @@ -158,17 +157,18 @@ export default function register() { // Default blend. const blend = "add"; - beforeEach(() => cli.parse(["composite", input, "--blend", blend])); + before(() => cli.parseAsync(["composite", input, "--blend", blend])); it("must set the blend flag", () => { expect(cli.parsed.argv).to.have.property("blend", blend); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].blend", blend), @@ -183,8 +183,8 @@ export default function register() { const channels = 3; const background = "rgba(0,0,0,0)"; - beforeEach(() => { - return cli.parse([ + before(() => { + return cli.parseAsync([ "composite", "--create.width", width, @@ -204,11 +204,12 @@ export default function register() { expect(args.create).to.have.property("width", width); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].input.create.width", width), @@ -223,11 +224,12 @@ export default function register() { expect(args.create).to.have.property("height", height); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].input.create.height", height), @@ -242,11 +244,12 @@ export default function register() { expect(args.create).to.have.property("channels", channels); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].input.create.channels", channels), @@ -261,11 +264,12 @@ export default function register() { expect(args.create).to.have.property("background", background); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].input.create.background", background), @@ -278,17 +282,20 @@ export default function register() { // Default density. const density = 72.1; - beforeEach(() => cli.parse(["composite", input, "--density", density])); + before(() => + cli.parseAsync(["composite", input, "--density", density]), + ); it("must set the density flag", () => { expect(cli.parsed.argv).to.have.property("density", density); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].density", density), @@ -297,19 +304,20 @@ export default function register() { }); describe("--gravity", () => { - beforeEach(() => - cli.parse(["composite", input, "--gravity", "centre"]), + before(() => + cli.parseAsync(["composite", input, "--gravity", "centre"]), ); it("must set the gravity flag", () => { expect(cli.parsed.argv).to.have.property("gravity", "centre"); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].gravity", "centre"), @@ -321,8 +329,8 @@ export default function register() { // Default left. const left = 20; - beforeEach(() => - cli.parse(["composite", input, "--left", left, "--top", 10]), + before(() => + cli.parseAsync(["composite", input, "--left", left, "--top", 10]), ); it("must set the left flag", () => { @@ -330,11 +338,12 @@ export default function register() { expect(args).to.have.property("left", left); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].left", left), @@ -343,17 +352,18 @@ export default function register() { }); describe("--premultiplied", () => { - beforeEach(() => cli.parse(["composite", input, "--premultiplied"])); + before(() => cli.parseAsync(["composite", input, "--premultiplied"])); it("must set the premultiplied flag", () => { expect(cli.parsed.argv).to.have.property("premultiplied", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].premultiplied", true), @@ -362,17 +372,18 @@ export default function register() { }); describe("--tile", () => { - beforeEach(() => cli.parse(["composite", input, "--tile"])); + before(() => cli.parseAsync(["composite", input, "--tile"])); it("must set the tile flag", () => { expect(cli.parsed.argv).to.have.property("tile", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].tile", true), @@ -384,8 +395,8 @@ export default function register() { // Default top. const top = 20; - beforeEach(() => - cli.parse(["composite", input, "--left", 10, "--top", top]), + before(() => + cli.parseAsync(["composite", input, "--left", 10, "--top", top]), ); it("must set the top flag", () => { @@ -393,11 +404,12 @@ export default function register() { expect(args).to.have.property("top", top); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("composite"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("composite"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].top", top), diff --git a/test/cmd/operations/affine.js b/test/cmd/operations/affine.js index 03e298a..2f7fab8 100644 --- a/test/cmd/operations/affine.js +++ b/test/cmd/operations/affine.js @@ -26,28 +26,26 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import affine from "../../../cmd/operations/affine.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("affine", () => { - const cli = yargsFactory().command(affine); + const cli = createInstance().command(affine); // Default matrix. const matrix = [1, 0.3, 0.1, 0.7]; // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("", () => { // Run. - beforeEach(() => cli.parse(["affine", ...matrix])); + before(() => cli.parseAsync(["affine", ...matrix])); // Tests. it("must set the matrix flag", () => { @@ -55,11 +53,12 @@ export default function register() { expect(cli.parsed.argv.matrix).to.eql(matrix); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("affine"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("affine"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.affine, [ matrix.slice(0, 2), matrix.slice(2, 4), @@ -73,8 +72,8 @@ export default function register() { const background = "rgba(0,0,0,.5)"; // Run. - beforeEach(() => - cli.parse(["affine", ...matrix, "--background", background]), + before(() => + cli.parseAsync(["affine", ...matrix, "--background", background]), ); // Tests. @@ -82,11 +81,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property("background", background); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("affine"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("affine"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.affine, sinon.match.any, { background, }); @@ -99,8 +99,8 @@ export default function register() { const value = 10; // Run. - beforeEach(() => - cli.parse(["affine", ...matrix, `--${alias}`, value]), + before(() => + cli.parseAsync(["affine", ...matrix, `--${alias}`, value]), ); // Tests. @@ -108,11 +108,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property(alias, value); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("affine"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("affine"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.affine, sinon.match.any, { [alias]: value, }); @@ -125,8 +126,8 @@ export default function register() { const interpolator = "nohalo"; // Run. - beforeEach(() => - cli.parse(["affine", ...matrix, "--interpolate", interpolator]), + before(() => + cli.parseAsync(["affine", ...matrix, "--interpolate", interpolator]), ); // Tests. @@ -134,11 +135,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property("interpolate", interpolator); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("affine"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("affine"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.affine, sinon.match.any, { interpolate: interpolator, }); diff --git a/test/cmd/operations/blur.js b/test/cmd/operations/blur.js index 45ed036..4409ea1 100644 --- a/test/cmd/operations/blur.js +++ b/test/cmd/operations/blur.js @@ -26,37 +26,36 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import blur from "../../../cmd/operations/blur.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("blur", () => { - const cli = yargsFactory().command(blur); + const cli = createInstance().command(blur); // Default amplitude and precision. const amplitude = 0.5; const precision = "approximate"; // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["blur"])); + before(() => cli.parseAsync(["blur"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("blur"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("blur"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.blur); }); }); @@ -66,26 +65,27 @@ export default function register() { const sigma = 1.1; // Run. - beforeEach(() => cli.parse(["blur", sigma])); + before(() => cli.parseAsync(["blur", sigma])); // Tests. it("must set the sigma flag", () => { expect(cli.parsed.argv).to.have.property("sigma", sigma); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("blur"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("blur"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.blur, sigma); }); }); describe("[minAmplitude]", () => { // Run. - beforeEach(() => - cli.parse([ + before(() => + cli.parseAsync([ "blur", 5, "--minAmplitude", @@ -100,11 +100,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property("minAmplitude"); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("blur"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("blur"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.blur, { minAmplitude: amplitude, }); @@ -113,8 +114,8 @@ export default function register() { describe("[precision]", () => { // Run. - beforeEach(() => - cli.parse([ + before(() => + cli.parseAsync([ "blur", 5, "--minAmplitude", @@ -129,11 +130,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property("precision"); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("blur"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("blur"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.blur, { precision }); }); }); diff --git a/test/cmd/operations/boolean.js b/test/cmd/operations/boolean.js index 49f97e7..39c4745 100644 --- a/test/cmd/operations/boolean.js +++ b/test/cmd/operations/boolean.js @@ -30,17 +30,16 @@ import { fileURLToPath } from "node:url"; // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import boolean from "../../../cmd/operations/boolean.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("boolean", () => { - const cli = yargsFactory().command(boolean); + const cli = createInstance().command(boolean); // Default input (avoid `path.join` to test for input normalizing). const input = fileURLToPath( @@ -48,12 +47,11 @@ export default function register() { ); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe(" ", () => { // Run. - beforeEach(() => cli.parse(["boolean", input, "and"])); + before(() => cli.parseAsync(["boolean", input, "and"])); // Tests. it("must set the operand and operator flags", () => { @@ -62,11 +60,12 @@ export default function register() { expect(args).to.have.property("operator", "and"); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("boolean"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("boolean"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.boolean, path.normalize(input), "and"); }); }); diff --git a/test/cmd/operations/clahe.js b/test/cmd/operations/clahe.js index 6eca6a6..22d0060 100644 --- a/test/cmd/operations/clahe.js +++ b/test/cmd/operations/clahe.js @@ -26,20 +26,18 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import clahe from "../../../cmd/operations/clahe.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("clahe", () => { - const cli = yargsFactory().command(clahe); + const cli = createInstance().command(clahe); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); const width = 20; @@ -47,15 +45,16 @@ export default function register() { describe("..", () => { // Run. - beforeEach(() => cli.parse(["clahe", width, height])); + before(() => cli.parseAsync(["clahe", width, height])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("clahe"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("clahe"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.clahe, { width, height }); }); }); @@ -66,8 +65,8 @@ export default function register() { const slope = 10; // Run. - beforeEach(() => - cli.parse(["clahe", width, height, "--maxSlope", slope]), + before(() => + cli.parseAsync(["clahe", width, height, "--maxSlope", slope]), ); // Tests. @@ -75,11 +74,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property("maxSlope", slope); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("clahe"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("clahe"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.clahe, { maxSlope: slope }); }); }); diff --git a/test/cmd/operations/convolve.js b/test/cmd/operations/convolve.js index c1bc399..588ecfe 100644 --- a/test/cmd/operations/convolve.js +++ b/test/cmd/operations/convolve.js @@ -26,17 +26,16 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import convolve from "../../../cmd/operations/convolve.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("convolve", () => { - const cli = yargsFactory().command(convolve); + const cli = createInstance().command(convolve); // Default width, height, and kernel. const width = 3; @@ -44,12 +43,11 @@ export default function register() { const kernel = [-1, 0, 1, -2, 0, 2, -1, 0, 1]; // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe(" ", () => { // Run. - beforeEach(() => cli.parse(["convolve", width, height, ...kernel])); + before(() => cli.parseAsync(["convolve", width, height, ...kernel])); // Tests. it("must set the width, height, and kernel flags", () => { @@ -60,11 +58,12 @@ export default function register() { expect(args.kernel).to.eql(kernel); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("convolve"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("convolve"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.convolve, { width, height, @@ -78,19 +77,27 @@ export default function register() { // Default offset. const offset = 10; - beforeEach(() => - cli.parse(["convolve", width, height, ...kernel, "--offset", offset]), + before(() => + cli.parseAsync([ + "convolve", + width, + height, + ...kernel, + "--offset", + offset, + ]), ); it("must set the offset flag", () => { expect(cli.parsed.argv).to.have.property("offset", offset); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("convolve"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("convolve"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.convolve, { offset }); }); }); @@ -98,19 +105,27 @@ export default function register() { // Default scale. const scale = 10; - beforeEach(() => - cli.parse(["convolve", width, height, ...kernel, "--scale", scale]), + before(() => + cli.parseAsync([ + "convolve", + width, + height, + ...kernel, + "--scale", + scale, + ]), ); it("must set the scale flag", () => { expect(cli.parsed.argv).to.have.property("scale", scale); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("convolve"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("convolve"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.convolve, { scale }); }); }); diff --git a/test/cmd/operations/dilate.js b/test/cmd/operations/dilate.js index 5a7c7c8..b3b4b26 100644 --- a/test/cmd/operations/dilate.js +++ b/test/cmd/operations/dilate.js @@ -26,31 +26,30 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import dilate from "../../../cmd/operations/dilate.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("dilate", () => { - const cli = yargsFactory().command(dilate); + const cli = createInstance().command(dilate); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { - beforeEach(() => cli.parse(["dilate"])); + before(() => cli.parseAsync(["dilate"])); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("dilate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("dilate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.dilate, undefined); }); }); @@ -58,17 +57,18 @@ export default function register() { describe("[width]", () => { const width = 3; - beforeEach(() => cli.parse(["dilate", width])); + before(() => cli.parseAsync(["dilate", width])); it("must set the width flag", () => { expect(cli.parsed.argv).to.have.property("width", width); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("dilate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("dilate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.dilate, width); }); }); diff --git a/test/cmd/operations/erode.js b/test/cmd/operations/erode.js index 36a2027..fdf0a41 100644 --- a/test/cmd/operations/erode.js +++ b/test/cmd/operations/erode.js @@ -26,31 +26,30 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import erode from "../../../cmd/operations/erode.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("erode", () => { - const cli = yargsFactory().command(erode); + const cli = createInstance().command(erode); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { - beforeEach(() => cli.parse(["erode"])); + before(() => cli.parseAsync(["erode"])); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("erode"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("erode"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.erode, undefined); }); }); @@ -58,17 +57,18 @@ export default function register() { describe("[width]", () => { const width = 3; - beforeEach(() => cli.parse(["erode", width])); + before(() => cli.parseAsync(["erode", width])); it("must set the width flag", () => { expect(cli.parsed.argv).to.have.property("width", width); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("erode"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("erode"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.erode, width); }); }); diff --git a/test/cmd/operations/flatten.js b/test/cmd/operations/flatten.js index 0169ad1..baec114 100644 --- a/test/cmd/operations/flatten.js +++ b/test/cmd/operations/flatten.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import flatten from "../../../cmd/operations/flatten.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("flatten", () => { - const cli = yargsFactory().command(flatten); + const cli = createInstance().command(flatten); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["flatten"])); + before(() => cli.parseAsync(["flatten"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("flatten"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("flatten"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.flatten); }); }); @@ -62,18 +61,19 @@ export default function register() { const background = "rgb(0, 0, 0)"; // Run. - beforeEach(() => cli.parse(["flatten", background])); + before(() => cli.parseAsync(["flatten", background])); // Tests. it("must set the factor flag", () => { expect(cli.parsed.argv).to.have.property("background", background); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("flatten"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("flatten"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.flatten, { background }); }); }); diff --git a/test/cmd/operations/flip.js b/test/cmd/operations/flip.js index d04b255..bd433d2 100644 --- a/test/cmd/operations/flip.js +++ b/test/cmd/operations/flip.js @@ -26,32 +26,31 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import flip from "../../../cmd/operations/flip.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("flip", () => { - const cli = yargsFactory().command(flip); + const cli = createInstance().command(flip); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse(["flip"])); + before(() => cli.parseAsync(["flip"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("flip"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("flip"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.flip); }); }); diff --git a/test/cmd/operations/flop.js b/test/cmd/operations/flop.js index 9ec66a2..e398d72 100644 --- a/test/cmd/operations/flop.js +++ b/test/cmd/operations/flop.js @@ -26,32 +26,31 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import flop from "../../../cmd/operations/flop.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("flop", () => { - const cli = yargsFactory().command(flop); + const cli = createInstance().command(flop); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse(["flop"])); + before(() => cli.parseAsync(["flop"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("flop"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("flop"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.flop); }); }); diff --git a/test/cmd/operations/gamma.js b/test/cmd/operations/gamma.js index 791a078..67a8948 100644 --- a/test/cmd/operations/gamma.js +++ b/test/cmd/operations/gamma.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import gamma from "../../../cmd/operations/gamma.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("gamma", () => { - const cli = yargsFactory().command(gamma); + const cli = createInstance().command(gamma); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["gamma"])); + before(() => cli.parseAsync(["gamma"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gamma"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gamma"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.gamma); }); }); @@ -62,18 +61,19 @@ export default function register() { const gamma = 1.1; // Run. - beforeEach(() => cli.parse(["gamma", gamma])); + before(() => cli.parseAsync(["gamma", gamma])); // Tests. it("must set the gamma flag", () => { expect(cli.parsed.argv).to.have.property("gamma", gamma); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gamma"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gamma"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.gamma, gamma); }); }); @@ -83,18 +83,19 @@ export default function register() { const gammaOut = 1.1; // Run. - beforeEach(() => cli.parse(["gamma", 2.2, gammaOut])); + before(() => cli.parseAsync(["gamma", 2.2, gammaOut])); // Tests. it("must set the gammaOut flag", () => { expect(cli.parsed.argv).to.have.property("gammaOut", gammaOut); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gamma"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gamma"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.gamma, sinon.match.any, gammaOut); }); }); diff --git a/test/cmd/operations/linear.js b/test/cmd/operations/linear.js index e27b032..f03c898 100644 --- a/test/cmd/operations/linear.js +++ b/test/cmd/operations/linear.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import linear from "../../../cmd/operations/linear.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("linear", () => { - const cli = yargsFactory().command(linear); + const cli = createInstance().command(linear); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["linear"])); + before(() => cli.parseAsync(["linear"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("linear"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("linear"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.linear); }); }); @@ -62,7 +61,7 @@ export default function register() { const multiplier = 1.5; // Run. - beforeEach(() => cli.parse(["linear", multiplier])); + before(() => cli.parseAsync(["linear", multiplier])); // Tests. it("must set the multiplier flag", () => { @@ -70,11 +69,12 @@ export default function register() { expect(cli.parsed.argv.multiplier[0]).to.equal(multiplier); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("linear"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("linear"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.linear, multiplier); }); }); @@ -84,7 +84,7 @@ export default function register() { const offset = 0.5; // Run. - beforeEach(() => cli.parse(["linear", 1.5, "--offset", offset])); + before(() => cli.parseAsync(["linear", 1.5, "--offset", offset])); // Tests. it("must set the offset flag", () => { @@ -92,11 +92,12 @@ export default function register() { expect(cli.parsed.argv.offset[0]).to.equal(offset); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("linear"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("linear"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.linear, sinon.match.any, [offset]); }); }); diff --git a/test/cmd/operations/median.js b/test/cmd/operations/median.js index 833bd6f..5694e35 100644 --- a/test/cmd/operations/median.js +++ b/test/cmd/operations/median.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import median from "../../../cmd/operations/median.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("median", () => { - const cli = yargsFactory().command(median); + const cli = createInstance().command(median); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["median"])); + before(() => cli.parseAsync(["median"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("median"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("median"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.median); }); }); @@ -62,18 +61,19 @@ export default function register() { const size = 4; // Run. - beforeEach(() => cli.parse(["median", size])); + before(() => cli.parseAsync(["median", size])); // Tests. it("must set the size flag", () => { expect(cli.parsed.argv).to.have.property("size", size); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("median"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("median"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.median, size); }); }); diff --git a/test/cmd/operations/modulate.js b/test/cmd/operations/modulate.js index d51e6a5..3d2057a 100644 --- a/test/cmd/operations/modulate.js +++ b/test/cmd/operations/modulate.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; import modulate from "../../../cmd/operations/modulate.js"; // Test suite. export default function register() { describe("modulate", () => { - const cli = yargsFactory().command(modulate); + const cli = createInstance().command(modulate); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["modulate"])); + before(() => cli.parseAsync(["modulate"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("modulate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("modulate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.modulate); }); }); @@ -63,17 +62,18 @@ export default function register() { // Default value. const value = 10; - beforeEach(() => cli.parse(["modulate", `--${option}`, value])); + before(() => cli.parseAsync(["modulate", `--${option}`, value])); it(`must set the ${option} flag`, () => { expect(cli.parsed.argv).to.have.property(option, value); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("modulate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("modulate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.modulate, { [[option]]: value }); }); }); diff --git a/test/cmd/operations/negate.js b/test/cmd/operations/negate.js index 16370bf..63b4e41 100644 --- a/test/cmd/operations/negate.js +++ b/test/cmd/operations/negate.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import negate from "../../../cmd/operations/negate.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("negate", () => { - const cli = yargsFactory().command(negate); + const cli = createInstance().command(negate); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["negate"])); + before(() => cli.parseAsync(["negate"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("negate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("negate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.negate); }); }); @@ -60,18 +59,19 @@ export default function register() { describe("[options]", () => { describe("--alpha", () => { // Run. - beforeEach(() => cli.parse(["negate", "--no-alpha"])); + before(() => cli.parseAsync(["negate", "--no-alpha"])); // Tests. it("must set the alpha flag", () => { expect(cli.parsed.argv).to.have.property("alpha", false); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("negate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("negate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.negate, false); }); }); diff --git a/test/cmd/operations/normalise.js b/test/cmd/operations/normalise.js index 2126ca3..5fce9cb 100644 --- a/test/cmd/operations/normalise.js +++ b/test/cmd/operations/normalise.js @@ -26,34 +26,33 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import normalise from "../../../cmd/operations/normalise.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { ["normalise", "normalize"].forEach((alias) => { describe(alias, () => { - const cli = yargsFactory().command(normalise); + const cli = createInstance().command(normalise); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse([alias])); + before(() => cli.parseAsync([alias])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("normalise"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("normalise"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.normalise); }); }); @@ -64,18 +63,19 @@ export default function register() { const lower = 25; // Run. - beforeEach(() => cli.parse([alias, "--lower", lower])); + before(() => cli.parseAsync([alias, "--lower", lower])); // Tests. it("must set the lower flag", () => { expect(cli.parsed.argv).to.have.property("lower", lower); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("normalise"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("normalise"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.normalise, { lower }); }); }); @@ -85,18 +85,19 @@ export default function register() { const upper = 25; // Run. - beforeEach(() => cli.parse([alias, "--upper", upper])); + before(() => cli.parseAsync([alias, "--upper", upper])); // Tests. it("must set the upper flag", () => { expect(cli.parsed.argv).to.have.property("upper", upper); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("normalise"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("normalise"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.normalise, { upper }); }); }); diff --git a/test/cmd/operations/recomb.js b/test/cmd/operations/recomb.js index 2d0b973..beb8008 100644 --- a/test/cmd/operations/recomb.js +++ b/test/cmd/operations/recomb.js @@ -26,17 +26,16 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import recomb from "../../../cmd/operations/recomb.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("recomb", () => { - const cli = yargsFactory().command(recomb); + const cli = createInstance().command(recomb); // Default matrix. const matrix = [ @@ -44,12 +43,11 @@ export default function register() { ]; // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("", () => { // Run. - beforeEach(() => cli.parse(["recomb", ...matrix])); + before(() => cli.parseAsync(["recomb", ...matrix])); // Tests. it("must set the matrix flag", () => { @@ -57,11 +55,12 @@ export default function register() { expect(cli.parsed.argv.matrix).to.eql(matrix); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("recomb"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("recomb"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.recomb, [ matrix.slice(0, 3), matrix.slice(3, 6), diff --git a/test/cmd/operations/rotate.js b/test/cmd/operations/rotate.js index 57d4955..10e20b2 100644 --- a/test/cmd/operations/rotate.js +++ b/test/cmd/operations/rotate.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import rotate from "../../../cmd/operations/rotate.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("rotate", () => { - const cli = yargsFactory().command(rotate); + const cli = createInstance().command(rotate); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["rotate"])); + before(() => cli.parseAsync(["rotate"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("rotate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("rotate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.rotate); }); }); @@ -62,18 +61,19 @@ export default function register() { const angle = 90; // Run. - beforeEach(() => cli.parse(["rotate", angle])); + before(() => cli.parseAsync(["rotate", angle])); // Tests. it("must set the factor flag", () => { expect(cli.parsed.argv).to.have.property("angle", angle); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("rotate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("rotate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.rotate, angle); }); }); @@ -84,18 +84,19 @@ export default function register() { const background = "rgba(0,0,0,.5)"; // Run. - beforeEach(() => cli.parse(["rotate", "--background", background])); + before(() => cli.parseAsync(["rotate", "--background", background])); // Tests. it("must set the background flag", () => { expect(cli.parsed.argv).to.have.property("background", background); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("rotate"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("rotate"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.rotate, undefined, { background }); }); }); diff --git a/test/cmd/operations/sharpen.js b/test/cmd/operations/sharpen.js index 6527689..1315b0e 100644 --- a/test/cmd/operations/sharpen.js +++ b/test/cmd/operations/sharpen.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; import sharpen from "../../../cmd/operations/sharpen.js"; // Test suite. export default function register() { describe("sharpen", () => { - const cli = yargsFactory().command(sharpen); + const cli = createInstance().command(sharpen); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["sharpen"])); + before(() => cli.parseAsync(["sharpen"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("sharpen"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("sharpen"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.sharpen); }); }); @@ -62,18 +61,19 @@ export default function register() { const sigma = 1.1; // Run. - beforeEach(() => cli.parse(["sharpen", sigma])); + before(() => cli.parseAsync(["sharpen", sigma])); // Tests. it("must set the sigma flag", () => { expect(cli.parsed.argv).to.have.property("sigma", sigma); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("sharpen"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("sharpen"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.sharpen, { sigma }); }); }); @@ -85,18 +85,19 @@ export default function register() { const flat = 1.1; // Run. - beforeEach(() => cli.parse(["sharpen", 2, `--${alias}`, flat])); + before(() => cli.parseAsync(["sharpen", 2, `--${alias}`, flat])); // Tests. it("must set the flat flag", () => { expect(cli.parsed.argv).to.have.property("m1", flat); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("sharpen"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("sharpen"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.sharpen, { m1: flat }); }); }); @@ -108,18 +109,19 @@ export default function register() { const jagged = 1.1; // Run. - beforeEach(() => cli.parse(["sharpen", 2, `--${alias}`, jagged])); + before(() => cli.parseAsync(["sharpen", 2, `--${alias}`, jagged])); // Tests. it("must set the jagged flag", () => { expect(cli.parsed.argv).to.have.property("jagged", jagged); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("sharpen"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("sharpen"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.sharpen, { m2: jagged }); }); }); @@ -131,18 +133,19 @@ export default function register() { const value = 1.1; // Run. - beforeEach(() => cli.parse(["sharpen", 2, `--${alias}`, value])); + before(() => cli.parseAsync(["sharpen", 2, `--${alias}`, value])); // Tests. it("must set the flat flag", () => { expect(cli.parsed.argv).to.have.property(alias, value); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("sharpen"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("sharpen"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.sharpen, { [alias]: value }); }); }); diff --git a/test/cmd/operations/threshold.js b/test/cmd/operations/threshold.js index f1afeeb..f2d577f 100644 --- a/test/cmd/operations/threshold.js +++ b/test/cmd/operations/threshold.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; import threshold from "../../../cmd/operations/threshold.js"; // Test suite. export default function register() { describe("threshold", () => { - const cli = yargsFactory().command(threshold); + const cli = createInstance().command(threshold); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["threshold"])); + before(() => cli.parseAsync(["threshold"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("threshold"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("threshold"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.threshold); }); }); @@ -62,18 +61,19 @@ export default function register() { const value = 128; // Run. - beforeEach(() => cli.parse(["threshold", value])); + before(() => cli.parseAsync(["threshold", value])); // Tests. it("must set the factor flag", () => { expect(cli.parsed.argv).to.have.property("value", value); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("threshold"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("threshold"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.threshold, value); }); }); @@ -81,17 +81,18 @@ export default function register() { describe("[options]", () => { ["grayscale", "greyscale"].forEach((alias) => { describe(`--${alias}`, () => { - beforeEach(() => cli.parse(["threshold", `--${alias}`])); + before(() => cli.parseAsync(["threshold", `--${alias}`])); it("must set the greyscale flag", () => { expect(cli.parsed.argv).to.have.property("greyscale", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("threshold"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("threshold"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.threshold, sinon.match.any, { greyscale: true, }); diff --git a/test/cmd/operations/unflatten.js b/test/cmd/operations/unflatten.js index 3f60c88..064f519 100644 --- a/test/cmd/operations/unflatten.js +++ b/test/cmd/operations/unflatten.js @@ -26,32 +26,31 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import unflatten from "../../../cmd/operations/unflatten.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("unflatten", () => { - const cli = yargsFactory().command(unflatten); + const cli = createInstance().command(unflatten); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); // Run. - beforeEach(() => cli.parse(["unflatten"])); + before(() => cli.parseAsync(["unflatten"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("unflatten"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("unflatten"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.unflatten); }); }); diff --git a/test/cmd/output.js b/test/cmd/output.js index c8a0d28..71b211a 100644 --- a/test/cmd/output.js +++ b/test/cmd/output.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../lib/queue.js"; import sharp from "../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../test-utils.js"; import tile from "../../cmd/output.js"; // Test suite. export default function register() { describe("tile", () => { - const cli = yargsFactory().command(tile); + const cli = createInstance().command(tile); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["tile"])); + before(() => cli.parseAsync(["tile"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.tile); }); }); @@ -62,18 +61,19 @@ export default function register() { const size = 512; // Run. - beforeEach(() => cli.parse(["tile", size])); + before(() => cli.parseAsync(["tile", size])); // Tests. it("must set the size flag", () => { expect(cli.parsed.argv).to.have.property("size", size); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { size }); }); }); @@ -84,18 +84,19 @@ export default function register() { const angle = 90; // Run. - beforeEach(() => cli.parse(["tile", "--angle", angle])); + before(() => cli.parseAsync(["tile", "--angle", angle])); // Tests. it("must set the angle flag", () => { expect(cli.parsed.argv).to.have.property("angle", angle); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { angle }); }); }); @@ -105,18 +106,19 @@ export default function register() { const background = "rgba(0,0,0,.5)"; // Run. - beforeEach(() => cli.parse(["tile", "--background", background])); + before(() => cli.parseAsync(["tile", "--background", background])); // Tests. it("must set the background flag", () => { expect(cli.parsed.argv).to.have.property("background", background); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { background }); }); }); @@ -126,35 +128,37 @@ export default function register() { const basename = "tiles"; // Run. - beforeEach(() => cli.parse(["tile", "--basename", basename])); + before(() => cli.parseAsync(["tile", "--basename", basename])); // Tests. it("must set the id flag", () => { expect(cli.parsed.argv).to.have.property("basename", basename); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { basename }); }); }); ["center", "centre"].forEach((alias) => { describe(`--${alias}`, () => { - beforeEach(() => cli.parse(["tile", `--${alias}`])); + before(() => cli.parseAsync(["tile", `--${alias}`])); it("must set the center flag", () => { expect(cli.parsed.argv).to.have.property("center", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { center: true }); }); }); @@ -165,18 +169,19 @@ export default function register() { const container = "fs"; // Run. - beforeEach(() => cli.parse(["tile", "--container", container])); + before(() => cli.parseAsync(["tile", "--container", container])); // Tests. it("must set the container flag", () => { expect(cli.parsed.argv).to.have.property("container", container); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { container }); }); }); @@ -186,18 +191,19 @@ export default function register() { const depth = "onepixel"; // Run. - beforeEach(() => cli.parse(["tile", "--depth", depth])); + before(() => cli.parseAsync(["tile", "--depth", depth])); // Tests. it("must set the depth flag", () => { expect(cli.parsed.argv).to.have.property("depth", depth); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { depth }); }); }); @@ -207,18 +213,19 @@ export default function register() { const id = "http://www.example.com"; // Run. - beforeEach(() => cli.parse(["tile", "--id", id])); + before(() => cli.parseAsync(["tile", "--id", id])); // Tests. it("must set the id flag", () => { expect(cli.parsed.argv).to.have.property("id", id); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { id }); }); }); @@ -228,18 +235,19 @@ export default function register() { const layout = "dz"; // Run. - beforeEach(() => cli.parse(["tile", "--layout", layout])); + before(() => cli.parseAsync(["tile", "--layout", layout])); // Tests. it("must set the layout flag", () => { expect(cli.parsed.argv).to.have.property("layout", layout); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { layout }); }); }); @@ -249,18 +257,19 @@ export default function register() { const overlap = 10; // Run. - beforeEach(() => cli.parse(["tile", "--overlap", overlap])); + before(() => cli.parseAsync(["tile", "--overlap", overlap])); // Tests. it("must set the overlap flag", () => { expect(cli.parsed.argv).to.have.property("overlap", overlap); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { overlap }); }); }); @@ -270,18 +279,19 @@ export default function register() { const skip = 10; // Run. - beforeEach(() => cli.parse(["tile", "--skipBlanks", skip])); + before(() => cli.parseAsync(["tile", "--skipBlanks", skip])); // Tests. it("must set the overlap flag", () => { expect(cli.parsed.argv).to.have.property("skipBlanks", skip); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tile"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tile"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tile, { skipBlanks: skip }); }); }); diff --git a/test/cmd/resizing/extend.js b/test/cmd/resizing/extend.js index c699918..5c26f29 100644 --- a/test/cmd/resizing/extend.js +++ b/test/cmd/resizing/extend.js @@ -26,17 +26,16 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import extend from "../../../cmd/resizing/extend.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("extend", () => { - const cli = yargsFactory().command(extend); + const cli = createInstance().command(extend); // Default offsets. const top = 10; @@ -45,12 +44,11 @@ export default function register() { const right = 10; // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe(" ", () => { // Run. - beforeEach(() => cli.parse(["extend", top, bottom, left, right])); + before(() => cli.parseAsync(["extend", top, bottom, left, right])); // Tests. it("must set the top, bottom, left, and right flags", () => { @@ -61,11 +59,12 @@ export default function register() { expect(args).to.have.property("right", args.right); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("extend"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("extend"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.extend, { top, bottom, @@ -81,8 +80,8 @@ export default function register() { const background = "rgba(0,0,0,.5)"; // Run. - beforeEach(() => - cli.parse([ + before(() => + cli.parseAsync([ "extend", top, bottom, @@ -98,11 +97,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property("background", background); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("extend"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("extend"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.extend, { background }); }); }); @@ -112,8 +112,16 @@ export default function register() { const mode = "copy"; // Run. - beforeEach(() => - cli.parse(["extend", top, bottom, left, right, "--extendWith", mode]), + before(() => + cli.parseAsync([ + "extend", + top, + bottom, + left, + right, + "--extendWith", + mode, + ]), ); // Tests. @@ -121,11 +129,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property("extendWith", mode); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("extend"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("extend"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.extend, { extendWith: mode }); }); }); diff --git a/test/cmd/resizing/extract.js b/test/cmd/resizing/extract.js index bbdf3c2..4dd089e 100644 --- a/test/cmd/resizing/extract.js +++ b/test/cmd/resizing/extract.js @@ -26,20 +26,18 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import extract from "../../../cmd/resizing/extract.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("extract", () => { - const cli = yargsFactory().command(extract); + const cli = createInstance().command(extract); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe(" ", () => { @@ -50,7 +48,7 @@ export default function register() { const height = 40; // Run. - beforeEach(() => cli.parse(["extract", top, left, width, height])); + before(() => cli.parseAsync(["extract", top, left, width, height])); // Tests. it("must set the top, left, width, and height flags", () => { @@ -61,11 +59,12 @@ export default function register() { expect(args).to.have.property("height", height); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("extract"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("extract"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.extract, { top, left, width, height }); }); }); diff --git a/test/cmd/resizing/resize.js b/test/cmd/resizing/resize.js index 096543b..9b8e388 100644 --- a/test/cmd/resizing/resize.js +++ b/test/cmd/resizing/resize.js @@ -26,30 +26,28 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. import resize from "../../../cmd/resizing/resize.js"; -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; // Test suite. export default function register() { describe("resize", () => { - const cli = yargsFactory().command(resize); + const cli = createInstance().command(resize); // Default width × height. const width = 100; const height = 200; // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { it("must prompt an error", async () => { const error = await new Promise((resolve) => - cli.parse(["resize"], (err) => resolve(err)), + cli.parseAsync(["resize"], (err) => resolve(err)), ); expect(error).to.exist(); expect(error).to.have.property("message"); @@ -58,42 +56,44 @@ export default function register() { }); describe("[width]", () => { - beforeEach(() => cli.parse(["resize", width])); + before(() => cli.parseAsync(["resize", width])); it("must set the width flag", () => { const args = cli.parsed.argv; expect(args).to.have.property("width", width); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.resize, width, null); }); }); describe("[height]", () => { - beforeEach(() => cli.parse(["resize", "--height", height])); + before(() => cli.parseAsync(["resize", "--height", height])); it("must set the height flag", () => { const args = cli.parsed.argv; expect(args).to.have.property("height", height); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.resize, null, height); }); }); describe("[width] [height]", () => { // Run. - beforeEach(() => cli.parse(["resize", width, height])); + before(() => cli.parseAsync(["resize", width, height])); // Tests. it("must set the width and height flags", () => { @@ -102,11 +102,12 @@ export default function register() { expect(args).to.have.property("height", height); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.resize, width, height); }); }); @@ -118,8 +119,8 @@ export default function register() { const background = "rgba(0,0,0,.5)"; // Run. - beforeEach(() => - cli.parse(["resize", width, height, "--background", background]), + before(() => + cli.parseAsync(["resize", width, height, "--background", background]), ); // Tests. @@ -127,11 +128,12 @@ export default function register() { expect(cli.parsed.argv).to.have.property("background", background); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.resize, sinon.match.any, @@ -143,19 +145,20 @@ export default function register() { // @see https://sharp.pixelplumbing.com/api-resize#resize describe("--fastShrinkOnLoad", () => { - beforeEach(() => - cli.parse(["resize", width, height, "--no-fastShrinkOnLoad"]), + before(() => + cli.parseAsync(["resize", width, height, "--no-fastShrinkOnLoad"]), ); it("must set the fastShrinkOnLoad flag", () => { expect(cli.parsed.argv).to.have.property("fastShrinkOnLoad", false); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.resize, sinon.match.any, @@ -170,17 +173,18 @@ export default function register() { // Default fit. const fit = "fill"; - beforeEach(() => cli.parse(["resize", width, height, "--fit", fit])); + before(() => cli.parseAsync(["resize", width, height, "--fit", fit])); it("must set the fit flag", () => { expect(cli.parsed.argv).to.have.property("fit", fit); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.resize, sinon.match.any, @@ -195,19 +199,20 @@ export default function register() { // Default kernel. const kernel = "lanczos3"; - beforeEach(() => - cli.parse(["resize", width, height, "--kernel", kernel]), + before(() => + cli.parseAsync(["resize", width, height, "--kernel", kernel]), ); it("must set the kernel flag", () => { expect(cli.parsed.argv).to.have.property("kernel", kernel); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.resize, sinon.match.any, @@ -222,19 +227,20 @@ export default function register() { // Default position. const position = "centre"; - beforeEach(() => - cli.parse(["resize", width, height, "--position", position]), + before(() => + cli.parseAsync(["resize", width, height, "--position", position]), ); it("must set the position flag", () => { expect(cli.parsed.argv).to.have.property("position", position); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.resize, sinon.match.any, @@ -246,19 +252,20 @@ export default function register() { // @see https://sharp.pixelplumbing.com/api-resize#withoutenlargement describe("--withoutEnlargement", () => { - beforeEach(() => - cli.parse(["resize", width, height, "--withoutEnlargement"]), + before(() => + cli.parseAsync(["resize", width, height, "--withoutEnlargement"]), ); it("must set the withoutEnlargement flag", () => { expect(cli.parsed.argv).to.have.property("withoutEnlargement", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.resize, sinon.match.any, @@ -270,19 +277,20 @@ export default function register() { // @see https://sharp.pixelplumbing.com/api-resize#resize describe("--withoutReduction", () => { - beforeEach(() => - cli.parse(["resize", width, height, "--withoutReduction"]), + before(() => + cli.parseAsync(["resize", width, height, "--withoutReduction"]), ); it("must set the withoutReduction flag", () => { expect(cli.parsed.argv).to.have.property("withoutReduction", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("resize"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("resize"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.resize, sinon.match.any, diff --git a/test/cmd/resizing/trim.js b/test/cmd/resizing/trim.js index 59c3a52..ec64a17 100644 --- a/test/cmd/resizing/trim.js +++ b/test/cmd/resizing/trim.js @@ -26,33 +26,32 @@ // Package modules. import expect from "must"; import sinon from "sinon"; -import yargsFactory from "yargs"; // Local modules. -import queue from "../../../lib/queue.js"; import sharp from "../../mocks/sharp.js"; +import { createInstance, drain, getPipeline } from "../../test-utils.js"; import trim from "../../../cmd/resizing/trim.js"; // Test suite. export default function register() { describe("trim", () => { - const cli = yargsFactory().command(trim); + const cli = createInstance().command(trim); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("..", () => { // Run. - beforeEach(() => cli.parse(["trim"])); + before(() => cli.parseAsync(["trim"])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("trim"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("trim"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.trim); }); }); @@ -62,18 +61,19 @@ export default function register() { const threshold = 10; // Run. - beforeEach(() => cli.parse(["trim", threshold])); + before(() => cli.parseAsync(["trim", threshold])); // Tests. it("must set the threshold flag", () => { expect(cli.parsed.argv).to.have.property("threshold", threshold); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("trim"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("trim"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.trim, { threshold }); }); }); @@ -84,36 +84,38 @@ export default function register() { const background = "rgb(0, 0, 0)"; // Run. - beforeEach(() => cli.parse(["trim", "--background", background])); + before(() => cli.parseAsync(["trim", "--background", background])); // Tests. it("must set the factor flag", () => { expect(cli.parsed.argv).to.have.property("background", background); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("trim"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("trim"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.trim, { background }); }); }); describe("--lineArt", () => { // Run. - beforeEach(() => cli.parse(["trim", "--lineArt"])); + before(() => cli.parseAsync(["trim", "--lineArt"])); // Tests. it("must set the factor flag", () => { expect(cli.parsed.argv).to.have.property("lineArt", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("trim"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("trim"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.trim, { lineArt: true }); }); }); diff --git a/lib/queue.js b/test/test-utils.js similarity index 71% rename from lib/queue.js rename to test/test-utils.js index 5f2ccf7..b847f4f 100644 --- a/lib/queue.js +++ b/test/test-utils.js @@ -21,22 +21,24 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// Configure. -const queue = []; +// Package modules. +import yargs from "yargs"; -// Extend object. -Object.defineProperties(queue, { - // Add drain handler. - drain: { - value: (initialValue) => - queue.reduce((acc, [, cb]) => cb(acc), initialValue), - }, +// Local modules. +import { drain as drainPrimitive } from "../lib/utils.js"; +import sharp from "./mocks/sharp.js"; - // Add pipeline getter. - pipeline: { - get: () => queue.map(([value]) => value), - }, -}); +// Helpers. +export function createInstance() { + return yargs().middleware((argv) => { + argv["#queue"] = []; + }); +} -// Exports. -export default queue; +export function drain(argv, context) { + return drainPrimitive(argv["#queue"], sharp(), context); +} + +export function getPipeline(argv) { + return argv["#queue"].map(([name]) => name); +} From fb4ebc0c1a2320da16ccd4e1b73930ca99f6acc4 Mon Sep 17 00:00:00 2001 From: Mark van Seventer Date: Sun, 16 Aug 2026 21:44:35 -0700 Subject: [PATCH 3/6] Log only for files. --- lib/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/index.js b/lib/index.js index a6c6b52..da5a61c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -40,14 +40,15 @@ export default (args, options = {}) => { queue: argv["#queue"], }; if (argv.input) { - return convert.files(argv.input, argv.output, context); + return convert + .files(argv.input, argv.output, context) + .then((output) => { + const info = Array.isArray(output) ? output : [output]; + info.forEach((file) => logger.log(file.path)); + }); } return convert.stream(process.stdin, process.stdout, context); }) - .then((output) => { - const info = Array.isArray(output) ? output : [output]; - info.forEach((file) => logger.log(file.path)); - }) .catch((err) => { if (err instanceof Error) { logger.error(err.message); From e165aba43a384d6626313a17ac9749af798428a6 Mon Sep 17 00:00:00 2001 From: Mark van Seventer Date: Sun, 16 Aug 2026 21:50:59 -0700 Subject: [PATCH 4/6] Fix test. --- test/index.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/index.js b/test/index.js index 37f3350..453b049 100644 --- a/test/index.js +++ b/test/index.js @@ -41,6 +41,9 @@ import pkg from "../package.json" with { type: "json" }; describe("CLI", () => { // Default input. const input = fileURLToPath(new URL("./fixtures/input.jpg", import.meta.url)); + const missing = fileURLToPath( + new URL("./fixtures/missing.jpg", import.meta.url), + ); // Default output. let dest; @@ -85,14 +88,9 @@ describe("CLI", () => { }); }); it("must display errors", () => { - return cli([], { logger }).then(() => { + return cli(["-i", missing, "-o", dest], { logger }).then(() => { sinon.assert.notCalled(logger.log); - if (process.stdin.isTTY) { - sinon.assert.calledWithMatch( - logger.error, - "Missing required arguments", - ); - } + sinon.assert.calledWithMatch(logger.error, "No input files"); sinon.assert.calledWithMatch( logger.error, "Specify --help for available options", From cb2c094823b2da3c336973577b90ee39a76a43fd Mon Sep 17 00:00:00 2001 From: Mark van Seventer Date: Mon, 17 Aug 2026 23:46:46 -0700 Subject: [PATCH 5/6] Final optimizations. --- CHANGELOG.md | 7 +- README.md | 2 +- lib/convert.js | 82 ++++--- test/cli.js | 573 ++++++++++++++++++++++++++---------------------- test/convert.js | 65 ++++-- 5 files changed, 419 insertions(+), 310 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9bf2f7..d1ee265 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ # Changelog -## 6.0.0 +## 6.0.0-dev +- Internal refactor from CommonJS to ESM. - Updated `sharp` dependency to 0.35.3. -- Updated depedencies. +- Updated dependencies. +- Requires Node.js 20.10. +- Removed `jpg` output format alias; use `jpeg` instead. ## 5.3.0 (August 13, 2026) diff --git a/README.md b/README.md index 44d09e6..1aa3cc8 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Output Options --bigtiff Use BigTIFF variant [boolean] -c, --compressionLevel zlib compression level [number] [default: 6] -f, --format Force output to a given format - [choices: "avif", "gif", "heif", "jpeg", "jpg", "png", "tiff", "webp"] [default: input] + [choices: "avif", "gif", "heif", "jpeg", "png", "tiff", "webp"] [default: input] --keepDuplicateFrames Keep duplicate frames in the output instead of combining them [boolean] -m, --metadata, --withMetadata Include all metadata (EXIF, XMP, IPTC) from the input image in the diff --git a/lib/convert.js b/lib/convert.js index a0d4d91..2c3b3cc 100644 --- a/lib/convert.js +++ b/lib/convert.js @@ -22,6 +22,7 @@ */ // Standard lib. +import { createReadStream } from "node:fs"; import path from "node:path"; import { pipeline } from "node:stream/promises"; @@ -43,6 +44,16 @@ const EXTENSIONS = { tiff: ".tiff", webp: ".webp", }; +const FORMATS = { + ".avif": "avif", + ".gif": "gif", + ".jpg": "jpeg", + ".jpeg": "jpeg", + ".png": "png", + ".tif": "tiff", + ".tiff": "tiff", + ".webp": "webp", +}; // Exports. export default { @@ -51,47 +62,52 @@ export default { // Resolve files. const files = input.flatMap((input) => globSync(input, { absolute: true })); if (files.length === 0) { - return Promise.reject(new Error("No input files")); + throw new Error("No input files"); } // Process files. const isBatch = files.length > 1; const promises = files.map((src) => { - const image = sharp(src, context.options); - return image.metadata().then((metadata) => { - const format = context.format ?? metadata.format; - const transformer = drain(context.queue, image, { - format, - metadata, - }); + const image = sharp(context.options); + return pipeline(createReadStream(src), image) + .then(() => image.metadata()) + .then((metadata) => { + // Process output as a template. + const parts = path.parse(src); + const regex = /\{(root|dir|base|ext|name)\}/g; + let dest = output; + let match; + while ((match = regex.exec(output)) !== null) { + const [search, prop] = match; + dest = dest.replace(search, parts[prop]); + } + dest = path.resolve(dest); - // Process output as a template. - const parts = path.parse(src); - const regex = /\{(root|dir|base|ext|name)\}/g; - let dest = output; - let match; - while ((match = regex.exec(output)) !== null) { - const [search, prop] = match; - dest = dest.replace(search, parts[prop]); - } - dest = path.resolve(dest); + // If output was not a template, assume dest is a directory when using + // batch processing. + const outputAssumeDir = dest === path.resolve(output) && isBatch; + const outputIsDir = outputAssumeDir || isDirectory(dest); + const format = + context.format ?? + (outputIsDir ? null : FORMATS[path.extname(dest).toLowerCase()]) ?? + metadata.format; + if (outputIsDir) { + const defaultExt = path.extname(src); + dest = path.format({ + dir: dest, + name: path.basename(src, defaultExt), + ext: format in EXTENSIONS ? EXTENSIONS[format] : defaultExt, + }); + } - // If output was not a template, assume dest is a directory when using - // batch processing. - const outputAssumeDir = dest === path.resolve(output) && isBatch; - if (outputAssumeDir || isDirectory(dest)) { - const defaultExt = path.extname(src); - dest = path.format({ - dir: dest, - name: path.basename(src, defaultExt), - ext: format in EXTENSIONS ? EXTENSIONS[format] : defaultExt, + const transformer = drain(context.queue, image, { + format, + metadata, }); - } - - return transformer - .toFile(dest) - .then((info) => Object.assign(info, { src, path: dest })); - }); + return transformer + .toFile(dest) + .then((info) => Object.assign(info, { src, path: dest })); + }); }); return Promise.all(promises); }, diff --git a/test/cli.js b/test/cli.js index 702d3ce..eef9cf9 100644 --- a/test/cli.js +++ b/test/cli.js @@ -30,8 +30,8 @@ import sinon from "sinon"; // Local modules. import cli from "../lib/cli.js"; -import queue from "../lib/queue.js"; import sharp from "./mocks/sharp.js"; +import { drain, getPipeline } from "./test-utils.js"; // Assets. import pkg from "../package.json" with { type: "json" }; @@ -42,32 +42,26 @@ describe(`${pkg.name} [command..]`, () => { const input = fileURLToPath(new URL("./fixtures/input.jpg", import.meta.url)); const output = fileURLToPath(new URL("./", import.meta.url)); const ioFlags = ["-i", input, "-o", output]; - const parse = (args) => - new Promise((resolve) => - cli.parse(args, (error, argv, output) => - resolve({ error, argv, output }), - ), - ); // Reset. - afterEach("queue", () => queue.splice(0)); afterEach("sharp", sharp.prototype.reset); describe("", () => { describe("--adaptiveFiltering", () => { // Run. - beforeEach(() => cli.parse(["--adaptiveFiltering", ...ioFlags])); + before(() => cli.parseAsync(["--adaptiveFiltering", ...ioFlags])); // Tests. it("must set the adaptiveFiltering flag", () => { expect(cli.parsed.argv).to.have.property("adaptiveFiltering", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("png"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("png"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.png, { adaptiveFiltering: true }); }); }); @@ -77,25 +71,27 @@ describe(`${pkg.name} [command..]`, () => { const alphaQuality = 80; // Run. - beforeEach(() => cli.parse(["--alphaQuality", alphaQuality, ...ioFlags])); + before(() => + cli.parseAsync(["--alphaQuality", alphaQuality, ...ioFlags]), + ); // Tests. it("must set the alphaQuality flag", () => { expect(cli.parsed.argv).to.have.property("alphaQuality", alphaQuality); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.webp, { alphaQuality }); }); }); describe("--animated", () => { - beforeEach(() => - cli.parse(["--animated", "composite", input, ...ioFlags]), + before(() => + cli.parseAsync(["--animated", "composite", input, ...ioFlags]), ); it("must set the animated flag", () => { @@ -103,7 +99,7 @@ describe(`${pkg.name} [command..]`, () => { expect(args).to.have.property("animated", true); }); it("must set the animated flag when using composite", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].animated", true), @@ -112,8 +108,8 @@ describe(`${pkg.name} [command..]`, () => { }); describe("--autoOrient", () => { - beforeEach(() => - cli.parse(["--autoOrient", "composite", input, ...ioFlags]), + before(() => + cli.parseAsync(["--autoOrient", "composite", input, ...ioFlags]), ); it("must set the autoOrient flag", () => { @@ -121,7 +117,7 @@ describe(`${pkg.name} [command..]`, () => { expect(args).to.have.property("autoOrient", true); }); it("must set the autoOrient flag when using composite", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].autoOrient", true), @@ -131,18 +127,18 @@ describe(`${pkg.name} [command..]`, () => { describe("--bigtiff", () => { // Run. - beforeEach(() => cli.parse(["--bigtiff", ...ioFlags])); + before(() => cli.parseAsync(["--bigtiff", ...ioFlags])); // Tests. it("must set the bigtiff flag", () => { expect(cli.parsed.argv).to.have.property("bigtiff", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { bigtiff: true }); }); }); @@ -152,18 +148,18 @@ describe(`${pkg.name} [command..]`, () => { const bitdepth = 4; // Run. - beforeEach(() => cli.parse(["--bitdepth", bitdepth, ...ioFlags])); + before(() => cli.parseAsync(["--bitdepth", bitdepth, ...ioFlags])); // Tests. it("must set the bitdepth flag", () => { expect(cli.parsed.argv).to.have.property("bitdepth", bitdepth); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { bitdepth }); }); }); @@ -173,8 +169,8 @@ describe(`${pkg.name} [command..]`, () => { const chromaSubsampling = "4:4:4"; // Run. - beforeEach(() => - cli.parse(["--chromaSubsampling", chromaSubsampling, ...ioFlags]), + before(() => + cli.parseAsync(["--chromaSubsampling", chromaSubsampling, ...ioFlags]), ); // Tests. @@ -185,12 +181,12 @@ describe(`${pkg.name} [command..]`, () => { ); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(2); - expect(queue.pipeline).to.include("avif"); - expect(queue.pipeline).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.have.length(2); + expect(getPipeline(cli.parsed.argv)).to.include("avif"); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.jpeg, { chromaSubsampling }); }); }); @@ -201,19 +197,19 @@ describe(`${pkg.name} [command..]`, () => { const colors = 128; // Run. - beforeEach(() => cli.parse([`--${alias}`, colors, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, colors, ...ioFlags])); // Tests. it("must set the colors flag", () => { expect(cli.parsed.argv).to.have.property("colors", colors); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(2); - expect(queue.pipeline).to.include("gif"); - expect(queue.pipeline).to.include("png"); + expect(getPipeline(cli.parsed.argv)).to.have.length(2); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.include("png"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.png, { colors }); }); }); @@ -224,18 +220,18 @@ describe(`${pkg.name} [command..]`, () => { const compression = "deflate"; // Run. - beforeEach(() => cli.parse(["--compression", compression, ...ioFlags])); + before(() => cli.parseAsync(["--compression", compression, ...ioFlags])); // Tests. it("must set the compression flag", () => { expect(cli.parsed.argv).to.have.property("compression", compression); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { compression }); }); }); @@ -246,18 +242,18 @@ describe(`${pkg.name} [command..]`, () => { const level = 6; // Run. - beforeEach(() => cli.parse([`--${alias}`, level, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, level, ...ioFlags])); // Tests. it("must set the compressionLevel flag", () => { expect(cli.parsed.argv).to.have.property("compressionLevel", level); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("png"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("png"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.png, { compressionLevel: level, }); @@ -270,18 +266,18 @@ describe(`${pkg.name} [command..]`, () => { const delay = 1; // Run. - beforeEach(() => cli.parse(["--delay", delay, ...ioFlags])); + before(() => cli.parseAsync(["--delay", delay, ...ioFlags])); // Tests. it("must set the delay flag", () => { expect(cli.parsed.argv).to.have.property("delay", delay); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.gif, { delay }); }); }); @@ -291,7 +287,7 @@ describe(`${pkg.name} [command..]`, () => { const density = 300; // Run. - beforeEach(() => cli.parse(["--density", density, ...ioFlags])); + before(() => cli.parseAsync(["--density", density, ...ioFlags])); // Tests. it("must set the density flag", () => { @@ -304,19 +300,19 @@ describe(`${pkg.name} [command..]`, () => { const dither = 0.5; // Run. - beforeEach(() => cli.parse(["--dither", dither, ...ioFlags])); + before(() => cli.parseAsync(["--dither", dither, ...ioFlags])); // Tests. it("must set the dither flag", () => { expect(cli.parsed.argv).to.have.property("dither", dither); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(2); - expect(queue.pipeline).to.include("gif"); - expect(queue.pipeline).to.include("png"); + expect(getPipeline(cli.parsed.argv)).to.have.length(2); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.include("png"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.gif, { dither, force: false }); sinon.assert.calledWithMatch(pipeline.png, { dither, force: false }); }); @@ -327,22 +323,22 @@ describe(`${pkg.name} [command..]`, () => { const effort = 1; // Run. - beforeEach(() => cli.parse(["--effort", effort, ...ioFlags])); + before(() => cli.parseAsync(["--effort", effort, ...ioFlags])); // Tests. it("must set the effort flag", () => { expect(cli.parsed.argv).to.have.property("effort", effort); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(5); - expect(queue.pipeline).to.include("avif"); - expect(queue.pipeline).to.include("gif"); - expect(queue.pipeline).to.include("heif"); - expect(queue.pipeline).to.include("png"); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(5); + expect(getPipeline(cli.parsed.argv)).to.include("avif"); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.include("heif"); + expect(getPipeline(cli.parsed.argv)).to.include("png"); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.avif, { effort }); }); }); @@ -351,8 +347,8 @@ describe(`${pkg.name} [command..]`, () => { // Default failOn. const failOn = "error"; - beforeEach(() => - cli.parse(["--failOn", failOn, "composite", input, ...ioFlags]), + before(() => + cli.parseAsync(["--failOn", failOn, "composite", input, ...ioFlags]), ); it("must set the failOn flag", () => { @@ -360,7 +356,7 @@ describe(`${pkg.name} [command..]`, () => { expect(args).to.have.property("failOn", failOn); }); it("must set the failOn flag when using composite", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].failOn", failOn), @@ -374,27 +370,29 @@ describe(`${pkg.name} [command..]`, () => { const format = "jpeg"; // Run. - beforeEach(() => cli.parse([`--${alias}`, format, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, format, ...ioFlags])); // Tests. it("must set the format flag", () => { expect(cli.parsed.argv).to.have.property("format", format); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("format"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("format"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWith(pipeline.toFormat, format); }); }); }); ["h", "help"].forEach((alias) => { describe(`--${alias}`, () => { - it("must display help", () => { - const promise = cli.parse([`--${alias}`]); - return expect(promise).to.reject.to.contain("Commands"); + it("must display help", async () => { + const output = await cli + .parseAsync([`--${alias}`]) + .catch((output) => output); + expect(output).to.contain("Commands"); }); }); }); @@ -404,18 +402,18 @@ describe(`${pkg.name} [command..]`, () => { const bitdepth = 8; // Run. - beforeEach(() => cli.parse(["--hbitdepth", bitdepth, ...ioFlags])); + before(() => cli.parseAsync(["--hbitdepth", bitdepth, ...ioFlags])); // Tests. it("must set the hbitdepth flag", () => { expect(cli.parsed.argv).to.have.property("hbitdepth", bitdepth); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("heif"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("heif"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.heif, { bitdepth }); }); }); @@ -425,25 +423,27 @@ describe(`${pkg.name} [command..]`, () => { const compression = "hevc"; // Run. - beforeEach(() => cli.parse(["--hcompression", compression, ...ioFlags])); + before(() => cli.parseAsync(["--hcompression", compression, ...ioFlags])); // Tests. it("must set the compression flag", () => { expect(cli.parsed.argv).to.have.property("hcompression", compression); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("heif"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("heif"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.heif, { compression }); }); }); ["i", "input"].forEach((alias) => { describe(`--${alias}`, () => { // Run. - beforeEach(() => cli.parse([`--${alias}`, input, input, "-o", output])); + before(() => + cli.parseAsync([`--${alias}`, input, input, "-o", output]), + ); // Tests. it("must set the input flag", () => { @@ -452,16 +452,21 @@ describe(`${pkg.name} [command..]`, () => { expect(args.input).to.eql([input, input]); }); - it("must fail when no input is given", () => { - const promise = cli.parse([`--${alias}`, "-o", output]); - return expect(promise).to.reject.to.match("Not enough arguments"); + it("must fail when no input is given", async () => { + const error = await cli + .parseAsync([`--${alias}`, "-o", output]) + .then(() => { + throw new Error("STOP"); + }) + .catch((error) => error); + expect(error.message).to.contain("Not enough arguments"); }); }); }); describe("--ignoreIcc", () => { - beforeEach(() => - cli.parse(["--ignoreIcc", "composite", input, ...ioFlags]), + before(() => + cli.parseAsync(["--ignoreIcc", "composite", input, ...ioFlags]), ); // Tests. @@ -469,7 +474,7 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("ignoreIcc", true); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].ignoreIcc", true), @@ -482,18 +487,18 @@ describe(`${pkg.name} [command..]`, () => { const max = 16; // Run. - beforeEach(() => cli.parse(["--interFrameMaxError", max, ...ioFlags])); + before(() => cli.parseAsync(["--interFrameMaxError", max, ...ioFlags])); // Tests. it("must set the interFrameMaxError flag", () => { expect(cli.parsed.argv).to.have.property("interFrameMaxError", max); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.gif, { interFrameMaxError: max }); }); }); @@ -503,18 +508,18 @@ describe(`${pkg.name} [command..]`, () => { const max = 16; // Run. - beforeEach(() => cli.parse(["--interPaletteMaxError", max, ...ioFlags])); + before(() => cli.parseAsync(["--interPaletteMaxError", max, ...ioFlags])); // Tests. it("must set the interPaletteMaxError flag", () => { expect(cli.parsed.argv).to.have.property("interPaletteMaxError", max); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.gif, { interPaletteMaxError: max, }); @@ -523,18 +528,18 @@ describe(`${pkg.name} [command..]`, () => { describe("--keepDuplicateFrames", () => { // Run. - beforeEach(() => cli.parse(["--keepDuplicateFrames", ...ioFlags])); + before(() => cli.parseAsync(["--keepDuplicateFrames", ...ioFlags])); // Tests. it("must set the keepDuplicateFrames flag", () => { expect(cli.parsed.argv).to.have.property("keepDuplicateFrames", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.gif, { keepDuplicateFrames: true, }); @@ -546,7 +551,7 @@ describe(`${pkg.name} [command..]`, () => { const level = 2; // Run. - beforeEach(() => cli.parse(["--level", level, ...ioFlags])); + before(() => cli.parseAsync(["--level", level, ...ioFlags])); // Tests. it("must set the level flag", () => { @@ -558,8 +563,8 @@ describe(`${pkg.name} [command..]`, () => { // Default value. const value = 10; - beforeEach(() => - cli.parse([ + before(() => + cli.parseAsync([ "--limitInputPixels", value, "composite", @@ -573,7 +578,7 @@ describe(`${pkg.name} [command..]`, () => { expect(args).to.have.property("limitInputPixels", value); }); it("must set the limitInputPixels flag when using composite", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].limitInputPixels", value), @@ -586,38 +591,38 @@ describe(`${pkg.name} [command..]`, () => { const loop = 2; // Run. - beforeEach(() => cli.parse(["--loop", loop, ...ioFlags])); + before(() => cli.parseAsync(["--loop", loop, ...ioFlags])); // Tests. it("must set the loop flag", () => { expect(cli.parsed.argv).to.have.property("loop", loop); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.gif, { loop }); }); }); describe("--lossless", () => { // Run. - beforeEach(() => cli.parse(["--lossless", ...ioFlags])); + before(() => cli.parseAsync(["--lossless", ...ioFlags])); // Tests. it("must set the lossless flag", () => { expect(cli.parsed.argv).to.have.property("lossless", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(3); - expect(queue.pipeline).to.include("avif"); - expect(queue.pipeline).to.include("heif"); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(3); + expect(getPipeline(cli.parsed.argv)).to.include("avif"); + expect(getPipeline(cli.parsed.argv)).to.include("heif"); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.heif, { lossless: true }); sinon.assert.calledWithMatch(pipeline.webp, { lossless: true }); }); @@ -625,108 +630,108 @@ describe(`${pkg.name} [command..]`, () => { describe("--miniswhite", () => { // Run. - beforeEach(() => cli.parse(["--miniswhite", ...ioFlags])); + before(() => cli.parseAsync(["--miniswhite", ...ioFlags])); // Tests. it("must set the miniswhite flag", () => { expect(cli.parsed.argv).to.have.property("miniswhite", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { miniswhite: true }); }); }); describe("--minSize", () => { // Run. - beforeEach(() => cli.parse(["--minSize", ...ioFlags])); + before(() => cli.parseAsync(["--minSize", ...ioFlags])); // Tests. it("must set the minSize flag", () => { expect(cli.parsed.argv).to.have.property("minSize", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.webp, { minSize: true }); }); }); describe("--mixed", () => { // Run. - beforeEach(() => cli.parse(["--mixed", ...ioFlags])); + before(() => cli.parseAsync(["--mixed", ...ioFlags])); // Tests. it("must set the lossless flag", () => { expect(cli.parsed.argv).to.have.property("mixed", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.webp, { mixed: true }); }); }); describe("--mozjpeg", () => { // Run. - beforeEach(() => cli.parse(["--mozjpeg", ...ioFlags])); + before(() => cli.parseAsync(["--mozjpeg", ...ioFlags])); // Tests. it("must set the mozjpeg flag", () => { expect(cli.parsed.argv).to.have.property("mozjpeg", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.jpeg, { mozjpeg: true }); }); }); describe("--nearLossless", () => { // Run. - beforeEach(() => cli.parse(["--nearLossless", ...ioFlags])); + before(() => cli.parseAsync(["--nearLossless", ...ioFlags])); // Tests. it("must set the nearLossless flag", () => { expect(cli.parsed.argv).to.have.property("nearLossless", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.webp, { nearLossless: true }); }); }); ["optimise", "optimize"].forEach((alias) => { describe(`--${alias}`, () => { // Run. - beforeEach(() => cli.parse([`--${alias}`, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, ...ioFlags])); // Tests. it("must set the optimise flag", () => { expect(cli.parsed.argv).to.have.property("optimise", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.jpeg, { optimiseScans: true, overshootDeringing: true, @@ -738,18 +743,18 @@ describe(`${pkg.name} [command..]`, () => { ["optimiseCoding", "optimizeCoding"].forEach((alias) => { describe(`--${alias}`, () => { // Run. - beforeEach(() => cli.parse([`--no-${alias}`, ...ioFlags])); + before(() => cli.parseAsync([`--no-${alias}`, ...ioFlags])); // Tests. it("must set the optimiseScans flag", () => { expect(cli.parsed.argv).to.have.property("optimiseCoding", false); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.jpeg, { optimiseCoding: false, }); @@ -759,20 +764,20 @@ describe(`${pkg.name} [command..]`, () => { ["optimiseScans", "optimizeScans"].forEach((alias) => { describe(`--${alias}`, () => { // Run (implies --progressive). - beforeEach(() => cli.parse([`--${alias}`, "-p", ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, "-p", ...ioFlags])); // Tests. it("must set the optimiseScans flag", () => { expect(cli.parsed.argv).to.have.property("optimiseScans", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(3); - expect(queue.pipeline).to.include("jpeg"); - expect(queue.pipeline).to.include("gif"); // Because: -p. - expect(queue.pipeline).to.include("png"); // Because: -p. + expect(getPipeline(cli.parsed.argv)).to.have.length(3); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); // Because: -p. + expect(getPipeline(cli.parsed.argv)).to.include("png"); // Because: -p. }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.jpeg, { optimiseScans: true }); }); }); @@ -780,7 +785,7 @@ describe(`${pkg.name} [command..]`, () => { ["o", "output"].forEach((alias) => { describe(`--${alias}`, () => { // Run. - beforeEach(() => cli.parse([`--${alias}`, output, "-i", input])); + before(() => cli.parseAsync([`--${alias}`, output, "-i", input])); // Tests. it("must set the output flag", () => { @@ -791,18 +796,18 @@ describe(`${pkg.name} [command..]`, () => { describe("--overshootDeringing", () => { // Run. - beforeEach(() => cli.parse(["--overshootDeringing", ...ioFlags])); + before(() => cli.parseAsync(["--overshootDeringing", ...ioFlags])); // Tests. it("must set the overshootDeringing flag", () => { expect(cli.parsed.argv).to.have.property("overshootDeringing", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.jpeg, { overshootDeringing: true, }); @@ -814,7 +819,7 @@ describe(`${pkg.name} [command..]`, () => { const page = 2; // Run. - beforeEach(() => cli.parse(["--page", page, ...ioFlags])); + before(() => cli.parseAsync(["--page", page, ...ioFlags])); // Tests. it("must set the page flag", () => { @@ -827,7 +832,7 @@ describe(`${pkg.name} [command..]`, () => { const pages = 2; // Run. - beforeEach(() => cli.parse(["--pages", pages, ...ioFlags])); + before(() => cli.parseAsync(["--pages", pages, ...ioFlags])); // Tests. it("must set the pages flag", () => { @@ -837,18 +842,18 @@ describe(`${pkg.name} [command..]`, () => { describe("--palette", () => { // Run. - beforeEach(() => cli.parse(["--palette", ...ioFlags])); + before(() => cli.parseAsync(["--palette", ...ioFlags])); // Tests. it("must set the palette flag", () => { expect(cli.parsed.argv).to.have.property("palette", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("png"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("png"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.png, { palette: true }); }); }); @@ -857,8 +862,14 @@ describe(`${pkg.name} [command..]`, () => { // Default value. const value = "rgb(255, 255, 255)"; - beforeEach(() => - cli.parse(["--pdfBackground", value, "composite", input, ...ioFlags]), + before(() => + cli.parseAsync([ + "--pdfBackground", + value, + "composite", + input, + ...ioFlags, + ]), ); it("must set the pdfBackground flag", () => { @@ -866,7 +877,7 @@ describe(`${pkg.name} [command..]`, () => { expect(args).to.have.property("pdfBackground", value); }); it("must set the pdfBackground flag when using composite", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch( pipeline.composite, sinon.match.hasNested("[0].pdfBackground", value), @@ -879,18 +890,18 @@ describe(`${pkg.name} [command..]`, () => { const predictor = "float"; // Run. - beforeEach(() => cli.parse(["--predictor", predictor, ...ioFlags])); + before(() => cli.parseAsync(["--predictor", predictor, ...ioFlags])); // Tests. it("must set the predictor flag", () => { expect(cli.parsed.argv).to.have.property("predictor", predictor); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { predictor }); }); }); @@ -900,36 +911,36 @@ describe(`${pkg.name} [command..]`, () => { const preset = "text"; // Run. - beforeEach(() => cli.parse(["--preset", preset, ...ioFlags])); + before(() => cli.parseAsync(["--preset", preset, ...ioFlags])); // Tests. it("must set the preset flag", () => { expect(cli.parsed.argv).to.have.property("preset", preset); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.webp, { preset }); }); }); describe("--pyramid", () => { // Run. - beforeEach(() => cli.parse(["--pyramid", ...ioFlags])); + before(() => cli.parseAsync(["--pyramid", ...ioFlags])); // Tests. it("must set the pyramid flag", () => { expect(cli.parsed.argv).to.have.property("pyramid", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { pyramid: true }); }); }); @@ -937,20 +948,20 @@ describe(`${pkg.name} [command..]`, () => { // Run. describe(`--${alias}`, () => { // Run. - beforeEach(() => cli.parse([`--${alias}`, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, ...ioFlags])); // Tests. it("must set the format flag", () => { expect(cli.parsed.argv).to.have.property("progressive", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(3); - expect(queue.pipeline).to.include("gif"); - expect(queue.pipeline).to.include("jpeg"); - expect(queue.pipeline).to.include("png"); + expect(getPipeline(cli.parsed.argv)).to.have.length(3); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.include("png"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.gif, { progressive: true }); sinon.assert.calledWithMatch(pipeline.jpeg, { progressive: true }); sinon.assert.calledWithMatch(pipeline.png, { progressive: true }); @@ -964,22 +975,22 @@ describe(`${pkg.name} [command..]`, () => { const quality = 80; // Run. - beforeEach(() => cli.parse([`--${alias}`, quality, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, quality, ...ioFlags])); // Tests. it("must set the format flag", () => { expect(cli.parsed.argv).to.have.property("quality", quality); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(5); - expect(queue.pipeline).to.include("avif"); - expect(queue.pipeline).to.include("heif"); - expect(queue.pipeline).to.include("jpeg"); - expect(queue.pipeline).to.include("tiff"); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(5); + expect(getPipeline(cli.parsed.argv)).to.include("avif"); + expect(getPipeline(cli.parsed.argv)).to.include("heif"); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.avif, { force: false, quality, @@ -1010,18 +1021,18 @@ describe(`${pkg.name} [command..]`, () => { describe(`--${alias}`, () => { // Run. - beforeEach(() => cli.parse([`--${alias}`, table, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, table, ...ioFlags])); // Tests. it("must set the quantisationTable flag", () => { expect(cli.parsed.argv).to.have.property("quantisationTable", table); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.jpeg, { quantisationTable: table, }); @@ -1031,18 +1042,18 @@ describe(`${pkg.name} [command..]`, () => { ["reuse", "reoptimise", "reoptimize"].forEach((alias) => { describe(`--${alias}`, () => { // Run. - beforeEach(() => cli.parse([`--${alias}`, `--${alias}`, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, `--${alias}`, ...ioFlags])); // Tests. it("must set the reoptimise flag", () => { expect(cli.parsed.argv).to.have.property("reuse", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("gif"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("gif"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.gif, { reuse: true }); }); }); @@ -1053,54 +1064,54 @@ describe(`${pkg.name} [command..]`, () => { const unit = "cm"; // Run. - beforeEach(() => cli.parse(["--resolutionUnit", unit, ...ioFlags])); + before(() => cli.parseAsync(["--resolutionUnit", unit, ...ioFlags])); // Tests. it("must set the resolutionUnit flag", () => { expect(cli.parsed.argv).to.have.property("resolutionUnit", unit); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { resolutionUnit: unit }); }); }); describe("--smartDeblock", () => { // Run. - beforeEach(() => cli.parse(["--smartDeblock", ...ioFlags])); + before(() => cli.parseAsync(["--smartDeblock", ...ioFlags])); // Tests. it("must set the smartDeblock flag", () => { expect(cli.parsed.argv).to.have.property("smartDeblock", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.webp, { smartDeblock: true }); }); }); describe("--smartSubsample", () => { // Run. - beforeEach(() => cli.parse(["--smartSubsample", ...ioFlags])); + before(() => cli.parseAsync(["--smartSubsample", ...ioFlags])); // Tests. it("must set the smartSubsample flag", () => { expect(cli.parsed.argv).to.have.property("smartSubsample", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("webp"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("webp"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.webp, { smartSubsample: true }); }); }); @@ -1110,7 +1121,7 @@ describe(`${pkg.name} [command..]`, () => { const subifd = 1; // Run. - beforeEach(() => cli.parse(["--subifd", subifd, ...ioFlags])); + before(() => cli.parseAsync(["--subifd", subifd, ...ioFlags])); // Tests. it("must set the subifd flag", () => { @@ -1123,8 +1134,8 @@ describe(`${pkg.name} [command..]`, () => { const tileBackground = "rgb(0, 0, 0)"; // Run. - beforeEach(() => - cli.parse(["--tileBackground", tileBackground, ...ioFlags]), + before(() => + cli.parseAsync(["--tileBackground", tileBackground, ...ioFlags]), ); // Tests. @@ -1135,11 +1146,11 @@ describe(`${pkg.name} [command..]`, () => { ); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { background: tileBackground, }); @@ -1151,18 +1162,18 @@ describe(`${pkg.name} [command..]`, () => { const tileHeight = 100; // Run. - beforeEach(() => cli.parse(["--tileHeight", tileHeight, ...ioFlags])); + before(() => cli.parseAsync(["--tileHeight", tileHeight, ...ioFlags])); // Tests. it("must set the tileHeight flag", () => { expect(cli.parsed.argv).to.have.property("tileHeight", tileHeight); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { tile: true, tileHeight, @@ -1177,8 +1188,8 @@ describe(`${pkg.name} [command..]`, () => { const tileWidth = 50; // Run. - beforeEach(() => - cli.parse([ + before(() => + cli.parseAsync([ "--tileHeight", tileHeight, "--tileWidth", @@ -1192,11 +1203,11 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("tileWidth", tileWidth); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { tile: true, tileHeight, @@ -1207,18 +1218,18 @@ describe(`${pkg.name} [command..]`, () => { describe("--trellisQuantisation", () => { // Run. - beforeEach(() => cli.parse(["--trellisQuantisation", ...ioFlags])); + before(() => cli.parseAsync(["--trellisQuantisation", ...ioFlags])); // Tests. it("must set the trellisQuantisation flag", () => { expect(cli.parsed.argv).to.have.property("trellisQuantisation", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("jpeg"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.jpeg, { trellisQuantisation: true, }); @@ -1226,12 +1237,10 @@ describe(`${pkg.name} [command..]`, () => { }); ["v", "version"].forEach((alias) => { describe(`--${alias}`, () => { - it("must set the version flag", async () => { - const { argv } = await parse([`--${alias}`]); - expect(argv).to.have.property("version", true); - }); it("must display the version number", async () => { - const { output } = await parse([`--${alias}`]); + const output = await cli + .parseAsync([`--${alias}`]) + .catch((output) => output); expect(output).to.equal(pkg.version); }); }); @@ -1242,25 +1251,25 @@ describe(`${pkg.name} [command..]`, () => { const timeout = 2; // Run. - beforeEach(() => cli.parse(["--timeout", timeout, ...ioFlags])); + before(() => cli.parseAsync(["--timeout", timeout, ...ioFlags])); // Tests. it("must set the timeout flag", () => { expect(cli.parsed.argv).to.have.property("timeout", timeout); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("timeout"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("timeout"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.timeout, { seconds: timeout }); }); }); describe("--unlimited", () => { // Run. - beforeEach(() => cli.parse(["--unlimited", ...ioFlags])); + before(() => cli.parseAsync(["--unlimited", ...ioFlags])); // Tests. it("must set the unlimited flag", () => { @@ -1270,18 +1279,18 @@ describe(`${pkg.name} [command..]`, () => { ["m", "metadata", "withMetadata"].forEach((alias) => { describe(`--${alias}`, () => { // Run. - beforeEach(() => cli.parse([`--${alias}`, ...ioFlags])); + before(() => cli.parseAsync([`--${alias}`, ...ioFlags])); // Tests. it("must set the withMetadata flag", () => { expect(cli.parsed.argv).to.have.property("withMetadata", true); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("withMetadata"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("withMetadata"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.withMetadata); }); }); @@ -1292,18 +1301,18 @@ describe(`${pkg.name} [command..]`, () => { const xRes = 1.5; // Run. - beforeEach(() => cli.parse(["--xres", xRes, ...ioFlags])); + before(() => cli.parseAsync(["--xres", xRes, ...ioFlags])); // Tests. it("must set the xres flag", () => { expect(cli.parsed.argv).to.have.property("xres", xRes); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { xres: xRes }); }); }); @@ -1313,18 +1322,18 @@ describe(`${pkg.name} [command..]`, () => { const yRes = 1.5; // Run. - beforeEach(() => cli.parse(["--yres", yRes, ...ioFlags])); + before(() => cli.parseAsync(["--yres", yRes, ...ioFlags])); // Tests. it("must set the yres flag", () => { expect(cli.parsed.argv).to.have.property("yres", yRes); }); it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("tiff"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("tiff"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.calledWithMatch(pipeline.tiff, { yres: yRes }); }); }); @@ -1332,16 +1341,66 @@ describe(`${pkg.name} [command..]`, () => { describe("[command]", () => { // Run. - beforeEach(() => cli.parse(["flip", ...ioFlags])); + before(() => cli.parseAsync(["flip", ...ioFlags])); // Tests. it("must update the pipeline", () => { - expect(queue.pipeline).to.have.length(1); - expect(queue.pipeline).to.include("flip"); + expect(getPipeline(cli.parsed.argv)).to.have.length(1); + expect(getPipeline(cli.parsed.argv)).to.include("flip"); }); it("must execute the pipeline", () => { - const pipeline = queue.drain(sharp()); + const pipeline = drain(cli.parsed.argv); sinon.assert.called(pipeline.flip); }); + + it("must prepend global options once", async () => { + await cli.parseAsync([ + ...ioFlags, + "rotate", + "90", + "--", + "resize", + "100", + "--format", + "jpeg", + ]); + expect(getPipeline(cli.parsed.argv)).to.eql([ + "format", + "rotate", + "resize", + ]); + }); + + it("must use the last repeated global option", async () => { + const argv = await cli.parseAsync([ + ...ioFlags, + "--format", + "jpeg", + "rotate", + "90", + "--", + "resize", + "100", + "--format", + "webp", + ]); + expect(argv.format).to.equal("webp"); + expect(getPipeline(argv)).to.eql(["format", "rotate", "resize"]); + }); + + it("must apply format-specific options only to the selected format", async () => { + const argv = await cli.parseAsync(["--quality", 90, ...ioFlags]); + const pipeline = drain(argv, { + format: "jpeg", + metadata: { format: "jpeg" }, + }); + sinon.assert.called(pipeline.jpeg); + sinon.assert.notCalled(pipeline.avif); + sinon.assert.notCalled(pipeline.gif); + sinon.assert.notCalled(pipeline.heif); + sinon.assert.notCalled(pipeline.png); + sinon.assert.notCalled(pipeline.tiff); + sinon.assert.notCalled(pipeline.webp); + }); }); }); diff --git a/test/convert.js b/test/convert.js index bea99f3..adad603 100644 --- a/test/convert.js +++ b/test/convert.js @@ -23,7 +23,7 @@ // Standard lib. import path from "node:path"; -import { Readable } from "node:stream"; +import { Readable, Writable } from "node:stream"; import { fileURLToPath } from "node:url"; // Package modules. @@ -33,12 +33,12 @@ import { temporaryDirectory, temporaryFile } from "tempy"; // Local modules. import convert from "../lib/convert.js"; -import queue from "../lib/queue.js"; import tile from "../cmd/output.js"; // Test suite. describe("convert", () => { const options = { sequentialRead: false }; + const createContext = () => ({ options, queue: [] }); // Default input. const input = fileURLToPath(new URL("./fixtures/input.jpg", import.meta.url)); @@ -50,12 +50,9 @@ describe("convert", () => { dest = temporaryDirectory(); }); beforeEach(() => { - copy = temporaryFile(); + copy = temporaryFile({ extension: "jpg" }); }); beforeEach(async () => fs.copy(input, copy)); - afterEach(() => { - queue.length = 0; // Empty queue. - }); afterEach(() => fs.remove(copy)); afterEach(() => fs.emptyDir(dest)); after(() => fs.remove(dest)); @@ -63,23 +60,37 @@ describe("convert", () => { // Tests. it("must convert a file", () => { return convert - .files([input], dest, options) + .files([input], dest, createContext()) .then(([info]) => expect(fs.existsSync(info.path)).to.be.true); }); it("must convert a file formatted based on extension", () => { return convert - .files([input], path.join(dest, "{name}.avif"), options) + .files([input], path.join(dest, "{name}.avif"), createContext()) .then(([info]) => { expect(info).to.have.property("format", "heif"); expect(info).to.have.property("path"); expect(info.path).to.contain(".avif"); }); }); + it("must pass the output extension format to queued handlers", () => { + const context = createContext(); + let format; + context.queue.push([ + "format", + (sharp, context) => { + format = context.format; + return sharp; + }, + ]); + return convert + .files([input], path.join(dest, "{name}.avif"), context) + .then(() => expect(format).to.equal("avif")); + }); it("must convert a file and output to an existing directory", () => { // Negative test for directory that does not exist. const rand = "" + Math.random(); return convert - .files([input, input], rand, options) + .files([input, input], rand, createContext()) .then(() => { throw new Error("STOP"); }) @@ -92,21 +103,22 @@ describe("convert", () => { }); it("must convert multiple files", () => { return convert - .files([input, input], dest, options) + .files([input, input], dest, createContext()) .then((info) => expect(info).to.have.length(2)); }); it("must support output templates", () => { const rand = Math.random(); return convert - .files([input], path.join(dest, `{name}-${rand}{ext}`), options) + .files([input], path.join(dest, `{name}-${rand}{ext}`), createContext()) .then(([info]) => expect(info.path).to.contain(`input-${rand}.jpg`)); }); it("must allow the same file as input and output", () => { - return convert.files([copy], path.dirname(copy), options); + return convert.files([copy], path.dirname(copy), createContext()); }); it("must support tiled output", () => { - tile.handler({ container: "zip" }); - return convert.files([input], dest, options); + const context = createContext(); + tile.handler({ "#queue": context.queue, container: "zip" }); + return convert.files([input], dest, context); }); it("must warn if there is no files", () => { return convert @@ -125,14 +137,18 @@ describe("convert", () => { // Default output. let dest; beforeEach(() => { - dest = temporaryFile(); + dest = temporaryFile({ extension: "jpg" }); }); afterEach(() => fs.remove(dest)); // Tests. it("must convert a file", () => { return convert - .stream(fs.createReadStream(input), fs.createWriteStream(dest), options) + .stream( + fs.createReadStream(input), + fs.createWriteStream(dest), + createContext(), + ) .then((info) => { expect(info.format).to.exist(); expect(info.path).not.to.exist(); @@ -144,7 +160,7 @@ describe("convert", () => { .stream( Readable.from(["not an image"]), fs.createWriteStream(dest), - options, + createContext(), ) .then(() => { throw new Error("STOP"); @@ -154,5 +170,20 @@ describe("convert", () => { expect(err.message).to.contain("unsupported image format"); }); }); + + it("must reject output stream errors", () => { + const error = new Error("output failed"); + const failingOutput = new Writable({ + write(_chunk, _encoding, callback) { + callback(error); + }, + }); + return convert + .stream(fs.createReadStream(input), failingOutput, createContext()) + .then(() => { + throw new Error("STOP"); + }) + .catch((err) => expect(err).to.equal(error)); + }); }); }); From 96adcec348152be79705da7be808090759b8deca Mon Sep 17 00:00:00 2001 From: Mark van Seventer Date: Tue, 18 Aug 2026 00:07:13 -0700 Subject: [PATCH 6/6] Be consistent. --- test/cli.js | 269 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 158 insertions(+), 111 deletions(-) diff --git a/test/cli.js b/test/cli.js index eef9cf9..d519024 100644 --- a/test/cli.js +++ b/test/cli.js @@ -80,8 +80,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("alphaQuality", alphaQuality); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -134,8 +135,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("bigtiff", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -155,8 +157,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("bitdepth", bitdepth); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -181,9 +184,10 @@ describe(`${pkg.name} [command..]`, () => { ); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(2); - expect(getPipeline(cli.parsed.argv)).to.include("avif"); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(2); + expect(pipeline).to.include("avif"); + expect(pipeline).to.include("jpeg"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -204,9 +208,10 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("colors", colors); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(2); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); - expect(getPipeline(cli.parsed.argv)).to.include("png"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(2); + expect(pipeline).to.include("gif"); + expect(pipeline).to.include("png"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -227,8 +232,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("compression", compression); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -249,8 +255,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("compressionLevel", level); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("png"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("png"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -273,8 +280,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("delay", delay); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gif"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -307,9 +315,10 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("dither", dither); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(2); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); - expect(getPipeline(cli.parsed.argv)).to.include("png"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(2); + expect(pipeline).to.include("gif"); + expect(pipeline).to.include("png"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -330,12 +339,13 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("effort", effort); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(5); - expect(getPipeline(cli.parsed.argv)).to.include("avif"); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); - expect(getPipeline(cli.parsed.argv)).to.include("heif"); - expect(getPipeline(cli.parsed.argv)).to.include("png"); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(5); + expect(pipeline).to.include("avif"); + expect(pipeline).to.include("gif"); + expect(pipeline).to.include("heif"); + expect(pipeline).to.include("png"); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -377,8 +387,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("format", format); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("format"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("format"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -409,8 +420,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("hbitdepth", bitdepth); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("heif"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("heif"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -430,8 +442,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("hcompression", compression); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("heif"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("heif"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -494,8 +507,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("interFrameMaxError", max); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gif"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -515,8 +529,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("interPaletteMaxError", max); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gif"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -535,8 +550,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("keepDuplicateFrames", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gif"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -598,8 +614,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("loop", loop); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gif"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -616,10 +633,11 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("lossless", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(3); - expect(getPipeline(cli.parsed.argv)).to.include("avif"); - expect(getPipeline(cli.parsed.argv)).to.include("heif"); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(3); + expect(pipeline).to.include("avif"); + expect(pipeline).to.include("heif"); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -637,8 +655,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("miniswhite", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -655,8 +674,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("minSize", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -673,8 +693,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("mixed", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -691,8 +712,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("mozjpeg", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("jpeg"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -709,8 +731,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("nearLossless", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -727,8 +750,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("optimise", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("jpeg"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -750,8 +774,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("optimiseCoding", false); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("jpeg"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -771,10 +796,11 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("optimiseScans", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(3); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); // Because: -p. - expect(getPipeline(cli.parsed.argv)).to.include("png"); // Because: -p. + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(3); + expect(pipeline).to.include("jpeg"); + expect(pipeline).to.include("gif"); // Because: -p. + expect(pipeline).to.include("png"); // Because: -p. }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -803,8 +829,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("overshootDeringing", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("jpeg"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -849,8 +876,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("palette", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("png"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("png"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -897,8 +925,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("predictor", predictor); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -918,8 +947,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("preset", preset); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -936,8 +966,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("pyramid", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -955,10 +986,11 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("progressive", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(3); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); - expect(getPipeline(cli.parsed.argv)).to.include("png"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(3); + expect(pipeline).to.include("gif"); + expect(pipeline).to.include("jpeg"); + expect(pipeline).to.include("png"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -982,12 +1014,13 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("quality", quality); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(5); - expect(getPipeline(cli.parsed.argv)).to.include("avif"); - expect(getPipeline(cli.parsed.argv)).to.include("heif"); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(5); + expect(pipeline).to.include("avif"); + expect(pipeline).to.include("heif"); + expect(pipeline).to.include("jpeg"); + expect(pipeline).to.include("tiff"); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1028,8 +1061,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("quantisationTable", table); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("jpeg"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1049,8 +1083,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("reuse", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("gif"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("gif"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1071,8 +1106,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("resolutionUnit", unit); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1089,8 +1125,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("smartDeblock", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1107,8 +1144,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("smartSubsample", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("webp"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("webp"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1146,8 +1184,9 @@ describe(`${pkg.name} [command..]`, () => { ); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1169,8 +1208,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("tileHeight", tileHeight); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1203,8 +1243,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("tileWidth", tileWidth); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1225,8 +1266,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("trellisQuantisation", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("jpeg"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("jpeg"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1258,8 +1300,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("timeout", timeout); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("timeout"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("timeout"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1286,8 +1329,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("withMetadata", true); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("withMetadata"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("withMetadata"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1308,8 +1352,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("xres", xRes); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1329,8 +1374,9 @@ describe(`${pkg.name} [command..]`, () => { expect(cli.parsed.argv).to.have.property("yres", yRes); }); it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("tiff"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("tiff"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv); @@ -1345,8 +1391,9 @@ describe(`${pkg.name} [command..]`, () => { // Tests. it("must update the pipeline", () => { - expect(getPipeline(cli.parsed.argv)).to.have.length(1); - expect(getPipeline(cli.parsed.argv)).to.include("flip"); + const pipeline = getPipeline(cli.parsed.argv); + expect(pipeline).to.have.length(1); + expect(pipeline).to.include("flip"); }); it("must execute the pipeline", () => { const pipeline = drain(cli.parsed.argv);