From 31cec543f7442d5f13c2a0481919ad88b1d707c5 Mon Sep 17 00:00:00 2001 From: Eric Cornelissen Date: Sun, 22 Oct 2023 12:58:01 +0200 Subject: [PATCH 1/5] Create compatibility test suite for the testing module --- test/compat/_.js | 8 +++ test/compat/testing.test.js | 126 ++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) 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/testing.test.js b/test/compat/testing.test.js new file mode 100644 index 000000000..55be66664 --- /dev/null +++ b/test/compat/testing.test.js @@ -0,0 +1,126 @@ +/** + * @overview Contains smoke tests for 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 = ["Can't quote when shell is false"]; + + 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 = ["Can't quote when shell is false"]; + + 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(); + }, +); From a185cce2387ade87be83353642f3052f981563e0 Mon Sep 17 00:00:00 2001 From: Eric Cornelissen Date: Sun, 22 Oct 2023 13:11:43 +0200 Subject: [PATCH 2/5] Commit missing correction to the testing module --- testing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing.js b/testing.js index d0e8ea424..59b6c6526 100644 --- a/testing.js +++ b/testing.js @@ -51,7 +51,7 @@ export class Shescape { quote(arg) { if (this.shell === false) { - throw new Error(); + throw new Error("Can't quote when shell is false"); } return this.escape(arg); From c936f4e2c3e650e62245da515ea01a504bb22619 Mon Sep 17 00:00:00 2001 From: Eric Cornelissen Date: Sun, 22 Oct 2023 13:14:53 +0200 Subject: [PATCH 3/5] Extend main module compatibility tests with property tests --- test/compat/_.js | 3 +- test/compat/index.test.js | 142 +++++++++++++++++++++++++++++++++++- test/compat/testing.test.js | 2 +- 3 files changed, 142 insertions(+), 5 deletions(-) diff --git a/test/compat/_.js b/test/compat/_.js index 9c14ed685..cb9f5bd6a 100644 --- a/test/compat/_.js +++ b/test/compat/_.js @@ -4,5 +4,6 @@ */ import * as arbitrary from "../_arbitraries.js"; +import * as constants from "../_constants.js"; -export { arbitrary }; +export { arbitrary, constants }; diff --git a/test/compat/index.test.js b/test/compat/index.test.js index 078838f34..95dd2cbce 100644 --- a/test/compat/index.test.js +++ b/test/compat/index.test.js @@ -1,12 +1,14 @@ /** - * @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 { testProp } from "@fast-check/ava"; +import * as fc from "fast-check"; import test from "ava"; -import * as constants from "../_constants.js"; +import { arbitrary, constants } from "./_.js"; import { Shescape } from "../../index.js"; @@ -59,3 +61,137 @@ test("has a working `quoteAll` function", (t) => { 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 index 55be66664..7b2e94b6c 100644 --- a/test/compat/testing.test.js +++ b/test/compat/testing.test.js @@ -1,5 +1,5 @@ /** - * @overview Contains smoke tests for shescape testing module to verify + * @overview Contains smoke tests for the shescape testing module to verify * compatibility with Node.js versions. * @license MIT */ From 3471de0b34128e7c3809ba129b8d55097a19d90f Mon Sep 17 00:00:00 2001 From: Eric Cornelissen Date: Mon, 23 Oct 2023 21:51:16 +0200 Subject: [PATCH 4/5] Remove redundant compatibility test cases --- test/compat/_.js | 3 +-- test/compat/index.test.js | 53 +-------------------------------------- 2 files changed, 2 insertions(+), 54 deletions(-) diff --git a/test/compat/_.js b/test/compat/_.js index cb9f5bd6a..9c14ed685 100644 --- a/test/compat/_.js +++ b/test/compat/_.js @@ -4,6 +4,5 @@ */ import * as arbitrary from "../_arbitraries.js"; -import * as constants from "../_constants.js"; -export { arbitrary, constants }; +export { arbitrary }; diff --git a/test/compat/index.test.js b/test/compat/index.test.js index 95dd2cbce..44d7ae281 100644 --- a/test/compat/index.test.js +++ b/test/compat/index.test.js @@ -6,62 +6,11 @@ import { testProp } from "@fast-check/ava"; import * as fc from "fast-check"; -import test from "ava"; -import { arbitrary, constants } from "./_.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()], From 8fc90494ef062593e0109717ea5e3075186aef61 Mon Sep 17 00:00:00 2001 From: Eric Cornelissen Date: Mon, 23 Oct 2023 22:04:06 +0200 Subject: [PATCH 5/5] Revert quote error changes for Stubscape --- test/compat/testing.test.js | 4 ++-- testing.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/compat/testing.test.js b/test/compat/testing.test.js index 7b2e94b6c..bcbc6f468 100644 --- a/test/compat/testing.test.js +++ b/test/compat/testing.test.js @@ -70,7 +70,7 @@ testProp( try { stubscape.quote(arg); } catch (error) { - const knownErrors = ["Can't quote when shell is false"]; + const knownErrors = [""]; if (!knownErrors.includes(error.message)) { t.fail(`Unexpected error:\n${error}`); @@ -96,7 +96,7 @@ testProp( try { stubscape.quoteAll(args); } catch (error) { - const knownErrors = ["Can't quote when shell is false"]; + const knownErrors = [""]; if (!knownErrors.includes(error.message)) { t.fail(`Unexpected error:\n${error}`); diff --git a/testing.js b/testing.js index 59b6c6526..d0e8ea424 100644 --- a/testing.js +++ b/testing.js @@ -51,7 +51,7 @@ export class Shescape { quote(arg) { if (this.shell === false) { - throw new Error("Can't quote when shell is false"); + throw new Error(); } return this.escape(arg);