Skip to content

Commit

Permalink
Improve compatibility tests (#1253)
Browse files Browse the repository at this point in the history
* Create compatibility test suite for the testing module

* Replace main module compatibility tests with generative tests
  • Loading branch information
ericcornelissen authored Oct 23, 2023
1 parent 74f9428 commit 4818ca6
Show file tree
Hide file tree
Showing 3 changed files with 272 additions and 53 deletions.
8 changes: 8 additions & 0 deletions test/compat/_.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @overview Provides testing utilities.
* @license MIT
*/

import * as arbitrary from "../_arbitraries.js";

export { arbitrary };
191 changes: 138 additions & 53 deletions test/compat/index.test.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,146 @@
/**
* @overview Contains smoke tests for Shescape to verify compatibility with Node
* versions.
* @overview Contains smoke tests for the main shescape module to verify
* compatibility with Node.js versions.
* @license MIT
*/

import test from "ava";
import { testProp } from "@fast-check/ava";
import * as fc from "fast-check";

import * as constants from "../_constants.js";
import { arbitrary } from "./_.js";

import { Shescape } from "../../index.js";

test.before((t) => {
t.context.quoteShell = constants.isWindows
? constants.binCmd
: constants.binBash;
});

test("has a working `escape` function", (t) => {
const shescape = new Shescape({ shell: false });

t.true(typeof shescape.escape === "function");

const input = "Hello world!";
const result = shescape.escape(input);
t.is(typeof result, "string");
});

test("has a working `escapeAll` function", (t) => {
const shescape = new Shescape({ shell: false });

t.true(typeof shescape.escapeAll === "function");

const inputs = ["foo", "bar"];
const result = shescape.escapeAll(inputs);
for (const output of result) {
t.is(typeof output, "string");
}
});

test("has a working `quote` function", (t) => {
const shescape = new Shescape({ shell: t.context.quoteShell });

t.true(typeof shescape.quote === "function");

const input = "Hello world!";
const result = shescape.quote(input);
t.is(typeof result, "string");
});

test("has a working `quoteAll` function", (t) => {
const shescape = new Shescape({ shell: t.context.quoteShell });

t.true(typeof shescape.quoteAll === "function");

const inputs = ["foo", "bar"];
const result = shescape.quoteAll(inputs);
for (const output of result) {
t.is(typeof output, "string");
}
});
testProp(
"Shescape#escape",
[arbitrary.shescapeOptions(), arbitrary.shescapeArg()],
(t, options, arg) => {
let shescape;

try {
shescape = new Shescape(options);
} catch (error) {
const known = ["No executable could be found for "];

if (!known.some((knownError) => error.message.includes(knownError))) {
t.fail(`Unexpected error:\n${error}`);
}
}

try {
shescape.escape(arg);
} catch (error) {
const known = [
"Cannot read property 'escape' of undefined",
"Cannot read properties of undefined (reading 'escape')",
];

if (!known.some((knownError) => error.message.includes(knownError))) {
t.fail(`Unexpected error:\n${error}`);
}
}

t.pass();
},
);

testProp(
"Shescape#escapeAll",
[arbitrary.shescapeOptions(), fc.array(arbitrary.shescapeArg())],
(t, options, args) => {
let shescape;

try {
shescape = new Shescape(options);
} catch (error) {
const known = ["No executable could be found for "];

if (!known.some((knownError) => error.message.includes(knownError))) {
t.fail(`Unexpected error:\n${error}`);
}
}

try {
shescape.escapeAll(args);
} catch (error) {
const known = [
"Cannot read property 'escapeAll' of undefined",
"Cannot read properties of undefined (reading 'escapeAll')",
];

if (!known.some((knownError) => error.message.includes(knownError))) {
t.fail(`Unexpected error:\n${error}`);
}
}

t.pass();
},
);

testProp(
"Shescape#quote",
[arbitrary.shescapeOptions(), arbitrary.shescapeArg()],
(t, options, arg) => {
let shescape;

try {
shescape = new Shescape(options);
} catch (error) {
const known = ["No executable could be found for "];

if (!known.some((knownError) => error.message.includes(knownError))) {
t.fail(`Unexpected error:\n${error}`);
}
}

try {
shescape.quote(arg);
} catch (error) {
const known = [
"Cannot read property 'quote' of undefined",
"Cannot read properties of undefined (reading 'quote')",
"Quoting is not supported when no shell is used",
];

if (!known.some((knownError) => error.message.includes(knownError))) {
t.fail(`Unexpected error:\n${error}`);
}
}

t.pass();
},
);

testProp(
"Shescape#quoteAll",
[arbitrary.shescapeOptions(), fc.array(arbitrary.shescapeArg())],
(t, options, args) => {
let shescape;

try {
shescape = new Shescape(options);
} catch (error) {
const known = ["No executable could be found for "];

if (!known.some((knownError) => error.message.includes(knownError))) {
t.fail(`Unexpected error:\n${error}`);
}
}

try {
shescape.quoteAll(args);
} catch (error) {
const known = [
"Cannot read property 'quoteAll' of undefined",
"Cannot read properties of undefined (reading 'quoteAll')",
"Quoting is not supported when no shell is used",
];

if (!known.some((knownError) => error.message.includes(knownError))) {
t.fail(`Unexpected error:\n${error}`);
}
}

t.pass();
},
);
126 changes: 126 additions & 0 deletions test/compat/testing.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* @overview Contains smoke tests for the shescape testing module to verify
* compatibility with Node.js versions.
* @license MIT
*/

import { testProp } from "@fast-check/ava";
import * as fc from "fast-check";

import { arbitrary } from "./_.js";

import { Shescape as Stubscape, Throwscape } from "../../testing.js";

testProp(
"Stubscape#escape",
[arbitrary.shescapeOptions(), arbitrary.shescapeArg()],
(t, options, arg) => {
let stubscape;

try {
stubscape = new Stubscape(options);
} catch (error) {
t.fail(`Unexpected error:\n${error}`);
}

try {
stubscape.escape(arg);
} catch (error) {
t.fail(`Unexpected error:\n${error}`);
}

t.pass();
},
);

testProp(
"Stubscape#escapeAll",
[arbitrary.shescapeOptions(), fc.array(arbitrary.shescapeArg())],
(t, options, args) => {
let stubscape;

try {
stubscape = new Stubscape(options);
} catch (error) {
t.fail(`Unexpected error:\n${error}`);
}

try {
stubscape.escapeAll(args);
} catch (error) {
t.fail(`Unexpected error:\n${error}`);
}

t.pass();
},
);

testProp(
"Stubscape#quote",
[arbitrary.shescapeOptions(), arbitrary.shescapeArg()],
(t, options, arg) => {
let stubscape;

try {
stubscape = new Stubscape(options);
} catch (error) {
t.fail(`Unexpected error:\n${error}`);
}

try {
stubscape.quote(arg);
} catch (error) {
const knownErrors = [""];

if (!knownErrors.includes(error.message)) {
t.fail(`Unexpected error:\n${error}`);
}
}

t.pass();
},
);

testProp(
"Stubscape#quoteAll",
[arbitrary.shescapeOptions(), fc.array(arbitrary.shescapeArg())],
(t, options, args) => {
let stubscape;

try {
stubscape = new Stubscape(options);
} catch (error) {
t.fail(`Unexpected error:\n${error}`);
}

try {
stubscape.quoteAll(args);
} catch (error) {
const knownErrors = [""];

if (!knownErrors.includes(error.message)) {
t.fail(`Unexpected error:\n${error}`);
}
}

t.pass();
},
);

testProp(
"Throwscape#constructor",
[arbitrary.shescapeOptions()],
(t, options) => {
try {
new Throwscape(options);
} catch (error) {
const knownErrors = ["Can't be instantiated"];

if (!knownErrors.includes(error.message)) {
t.fail(`Unexpected error:\n${error}`);
}
}

t.pass();
},
);

0 comments on commit 4818ca6

Please sign in to comment.