From 4534db656d81f0e33dcbfbaf75c547009c9c31b8 Mon Sep 17 00:00:00 2001 From: Sebastien Filion Date: Tue, 7 Jul 2020 09:13:38 -0400 Subject: [PATCH] feat(test): Add support for regex in filter flag (#6343) Currently, the documentation makes it sound like the test subcommand's filter flag could accept some kind of pattern matching value like a glob or a regex, although the function "createFilterFn" accepts a regex as an argument, there's no way to pass an actual regex value from the CLI. This commit makes it possible to pass a string that could be cast as regex when string matches "^/.*/$". With this change, a user can use the filter flag as follow: deno test --filter "/test-.+/" Also tested that `\` get escaped properly, on MacOS at least, and this is also a valid flag: deno test --filter "/test-\d+/" --- cli/flags.rs | 2 +- cli/js/testing.ts | 5 +++ cli/tests/unit/filter_function_test.ts | 52 ++++++++++++++++++++++++++ cli/tests/unit/unit_tests.ts | 1 + docs/testing.md | 27 ++++++++++++- 5 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 cli/tests/unit/filter_function_test.ts diff --git a/cli/flags.rs b/cli/flags.rs index b78dc646a2..4cacb01e40 100644 --- a/cli/flags.rs +++ b/cli/flags.rs @@ -1105,7 +1105,7 @@ fn test_subcommand<'a, 'b>() -> App<'a, 'b> { Arg::with_name("filter") .long("filter") .takes_value(true) - .help("Run tests with this string in the test name"), + .help("Run tests with this string or pattern in the test name"), ) .arg( Arg::with_name("files") diff --git a/cli/js/testing.ts b/cli/js/testing.ts index e8d42c2ebb..0648683a47 100644 --- a/cli/js/testing.ts +++ b/cli/js/testing.ts @@ -308,6 +308,9 @@ function createFilterFn( if (filter) { if (filter instanceof RegExp) { passes = passes && filter.test(def.name); + } else if (filter.startsWith("/") && filter.endsWith("/")) { + const filterAsRegex = new RegExp(filter.slice(1, filter.length - 1)); + passes = passes && filterAsRegex.test(def.name); } else { passes = passes && def.name.includes(filter); } @@ -325,6 +328,8 @@ function createFilterFn( }; } +exposeForTest("createFilterFn", createFilterFn); + interface RunTestsOptions { exitOnFail?: boolean; failFast?: boolean; diff --git a/cli/tests/unit/filter_function_test.ts b/cli/tests/unit/filter_function_test.ts new file mode 100644 index 0000000000..dd83c1dbcb --- /dev/null +++ b/cli/tests/unit/filter_function_test.ts @@ -0,0 +1,52 @@ +import { unitTest, assertEquals } from "./test_util.ts"; + +// @ts-expect-error TypeScript (as of 3.7) does not support indexing namespaces by symbol +const { createFilterFn } = Deno[Deno.internal]; + +unitTest(function filterAsString(): void { + const filterFn = createFilterFn("my-test"); + const tests = [ + { + fn(): void {}, + name: "my-test", + }, + { + fn(): void {}, + name: "other-test", + }, + ]; + const filteredTests = tests.filter(filterFn); + assertEquals(filteredTests.length, 1); +}); + +unitTest(function filterAsREGEX(): void { + const filterFn = createFilterFn("/.+-test/"); + const tests = [ + { + fn(): void {}, + name: "my-test", + }, + { + fn(): void {}, + name: "other-test", + }, + ]; + const filteredTests = tests.filter(filterFn); + assertEquals(filteredTests.length, 2); +}); + +unitTest(function filterAsEscapedREGEX(): void { + const filterFn = createFilterFn("/\\w+-test/"); + const tests = [ + { + fn(): void {}, + name: "my-test", + }, + { + fn(): void {}, + name: "other-test", + }, + ]; + const filteredTests = tests.filter(filterFn); + assertEquals(filteredTests.length, 2); +}); diff --git a/cli/tests/unit/unit_tests.ts b/cli/tests/unit/unit_tests.ts index 1701170d1a..ad820a55ca 100644 --- a/cli/tests/unit/unit_tests.ts +++ b/cli/tests/unit/unit_tests.ts @@ -24,6 +24,7 @@ import "./event_target_test.ts"; import "./fetch_test.ts"; import "./file_test.ts"; import "./files_test.ts"; +import "./filter_function_test.ts"; import "./form_data_test.ts"; import "./format_error_test.ts"; import "./fs_events_test.ts"; diff --git a/docs/testing.md b/docs/testing.md index f444831257..174123cce9 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -129,10 +129,33 @@ There are a number of options to filter the tests you are running. Tests can be run individually or in groups using the command line `--filter` option. -```shell -deno test --filter "hello world" tests/ +The filter flags accept a string or a pattern as value. + +Assuming the following tests: + +```ts +Deno.test({ name: "my-test", fn: myTest }); +Deno.test({ name: "test-1", fn: test1 }); +Deno.test({ name: "test2", fn: test2 }); ``` +This command will run all of these tests because they all contain the word +"test". + +```shell +deno test --filter "test" tests/ +``` + +On the flip side, the following command uses a pattern and will run the second +and third tests. + +```shell +deno test --filter "/test-*\d/" tests/ +``` + +_To let Deno know that you want to use a pattern, wrap your filter with +forward-slashes like the JavaScript syntactic sugar for a REGEX._ + This command will run any test which contains the string "hello world" in its test name for tests found within files in the `tests/` directory.