From 4818ca6da5e15b88736ec1b3197c08fcc517d504 Mon Sep 17 00:00:00 2001 From: Eric Cornelissen Date: Mon, 23 Oct 2023 22:13:37 +0200 Subject: [PATCH] Improve compatibility tests (#1253) * Create compatibility test suite for the testing module * Replace main module compatibility tests with generative tests --- test/compat/_.js | 8 ++ test/compat/index.test.js | 191 ++++++++++++++++++++++++++---------- test/compat/testing.test.js | 126 ++++++++++++++++++++++++ 3 files changed, 272 insertions(+), 53 deletions(-) create mode 100644 test/compat/_.js create mode 100644 test/compat/testing.test.js diff --git a/test/compat/_.js b/test/compat/_.js new file mode 100644 index 000000000..9c14ed685 --- /dev/null +++ b/test/compat/_.js @@ -0,0 +1,8 @@ +/** + * @overview Provides testing utilities. + * @license MIT + */ + +import * as arbitrary from "../_arbitraries.js"; + +export { arbitrary }; diff --git a/test/compat/index.test.js b/test/compat/index.test.js index 078838f34..44d7ae281 100644 --- a/test/compat/index.test.js +++ b/test/compat/index.test.js @@ -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(); + }, +); diff --git a/test/compat/testing.test.js b/test/compat/testing.test.js new file mode 100644 index 000000000..bcbc6f468 --- /dev/null +++ b/test/compat/testing.test.js @@ -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(); + }, +);