From 2291680a67332bcf2cbf6e8501556220e0ff27e2 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 30 Sep 2021 10:43:02 -0400 Subject: [PATCH] Move test steps to be unstable. --- cli/dts/lib.deno.ns.d.ts | 28 +++----------- cli/dts/lib.deno.unstable.d.ts | 37 +++++++++++++++++++ cli/tests/integration/test_tests.rs | 16 +++++--- .../testdata/test/steps/no_unstable_flag.out | 13 +++++++ .../testdata/test/steps/no_unstable_flag.ts | 4 ++ runtime/js/40_testing.js | 12 ++++++ runtime/js/99_main.js | 3 ++ 7 files changed, 85 insertions(+), 28 deletions(-) create mode 100644 cli/tests/testdata/test/steps/no_unstable_flag.out create mode 100644 cli/tests/testdata/test/steps/no_unstable_flag.ts diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index e8167a1ea21d12..afa68a328204db 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -113,29 +113,17 @@ declare namespace Deno { * See: https://no-color.org/ */ export const noColor: boolean; + /** **UNSTABLE**: New option, yet to be vetted. */ export interface Tester { - /** Run a sub step of the parent test with a given name. Returns a promise - * that resolves to a boolean signifying if the step completed successfully. - * The returned promise never rejects unless the arguments are invalid. - * If the test was ignored, the promise returns `false`. - */ - step(t: TestStepDefinition): Promise; - - /** Run a sub step of the parent test with a given name. Returns a promise - * that resolves to a boolean signifying if the step completed successfully. - * The returned promise never rejects unless the arguments are invalid. - * If the test was ignored, the promise returns `false`. - */ - step( - name: string, - fn: (t: Tester) => void | Promise, - ): Promise; } - export interface TestStepDefinition { + export interface TestDefinition { fn: (t: Tester) => void | Promise; name: string; ignore?: boolean; + /** If at least one test has `only` set to true, only run tests that have + * `only` set to true and fail the test suite. */ + only?: boolean; /** Check that the number of async completed ops after the test is the same * as number of dispatched ops. Defaults to true. */ sanitizeOps?: boolean; @@ -148,12 +136,6 @@ declare namespace Deno { sanitizeExit?: boolean; } - export interface TestDefinition extends TestStepDefinition { - /** If at least one test has `only` set to true, only run tests that have - * `only` set to true and fail the test suite. */ - only?: boolean; - } - /** Register a test which will be run when `deno test` is used on the command * line and the containing module looks like a test module. * `fn` can be async if required. diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index bfc4536f03bb93..95443752de809e 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -1007,6 +1007,43 @@ declare namespace Deno { }; } + /** **UNSTABLE**: New option, yet to be vetted. */ + export interface Tester { + /** Run a sub step of the parent test with a given name. Returns a promise + * that resolves to a boolean signifying if the step completed successfully. + * The returned promise never rejects unless the arguments are invalid. + * If the test was ignored, the promise returns `false`. + */ + step(t: TestStepDefinition): Promise; + + /** Run a sub step of the parent test with a given name. Returns a promise + * that resolves to a boolean signifying if the step completed successfully. + * The returned promise never rejects unless the arguments are invalid. + * If the test was ignored, the promise returns `false`. + */ + step( + name: string, + fn: (t: Tester) => void | Promise, + ): Promise; + } + + /** **UNSTABLE**: New option, yet to be vetted. */ + export interface TestStepDefinition { + fn: (t: Tester) => void | Promise; + name: string; + ignore?: boolean; + /** Check that the number of async completed ops after the test is the same + * as number of dispatched ops. Defaults to true. */ + sanitizeOps?: boolean; + /** Ensure the test case does not "leak" resources - ie. the resource table + * after the test has exactly the same contents as before the test. Defaults + * to true. */ + sanitizeResources?: boolean; + /** Ensure the test case does not prematurely cause the process to exit, + * for example via a call to `Deno.exit`. Defaults to true. */ + sanitizeExit?: boolean; + } + /** The type of the resource record. * Only the listed types are supported currently. */ export type RecordType = diff --git a/cli/tests/integration/test_tests.rs b/cli/tests/integration/test_tests.rs index 5b6265012a8d47..0967677c6506d5 100644 --- a/cli/tests/integration/test_tests.rs +++ b/cli/tests/integration/test_tests.rs @@ -182,31 +182,37 @@ itest!(shuffle_with_seed { }); itest!(steps_passing_steps { - args: "test test/steps/passing_steps.ts", + args: "test --unstable test/steps/passing_steps.ts", exit_code: 0, output: "test/steps/passing_steps.out", }); itest!(steps_passing_steps_concurrent { - args: "test --jobs=2 test/steps/passing_steps.ts", + args: "test --unstable --jobs=2 test/steps/passing_steps.ts", exit_code: 0, output: "test/steps/passing_steps.out", }); itest!(steps_failing_steps { - args: "test test/steps/failing_steps.ts", + args: "test --unstable test/steps/failing_steps.ts", exit_code: 1, output: "test/steps/failing_steps.out", }); itest!(steps_ignored_steps { - args: "test test/steps/ignored_steps.ts", + args: "test --unstable test/steps/ignored_steps.ts", exit_code: 0, output: "test/steps/ignored_steps.out", }); itest!(steps_invalid_usage { - args: "test test/steps/invalid_usage.ts", + args: "test --unstable test/steps/invalid_usage.ts", exit_code: 1, output: "test/steps/invalid_usage.out", }); + +itest!(steps_no_unstable_flag { + args: "test test/steps/no_unstable_flag.ts", + exit_code: 1, + output: "test/steps/no_unstable_flag.out", +}); diff --git a/cli/tests/testdata/test/steps/no_unstable_flag.out b/cli/tests/testdata/test/steps/no_unstable_flag.out new file mode 100644 index 00000000000000..8fe6ba4f7cb87e --- /dev/null +++ b/cli/tests/testdata/test/steps/no_unstable_flag.out @@ -0,0 +1,13 @@ +[WILDCARD] +running 1 test from [WILDCARD]/no_unstable_flag.ts +test description ... FAILED ([WILDCARD]) + +failures: + +description +Error: Test steps are unstable. The --unstable flag must be provided. + at [WILDCARD] + +failures: + +[WILDCARD] diff --git a/cli/tests/testdata/test/steps/no_unstable_flag.ts b/cli/tests/testdata/test/steps/no_unstable_flag.ts new file mode 100644 index 00000000000000..737efba117bd68 --- /dev/null +++ b/cli/tests/testdata/test/steps/no_unstable_flag.ts @@ -0,0 +1,4 @@ +Deno.test("description", async (t) => { + // deno-lint-ignore no-explicit-any + await (t as any).step("step", () => {}); +}); diff --git a/runtime/js/40_testing.js b/runtime/js/40_testing.js index 849b4d97c529e0..d9d9db70f5072d 100644 --- a/runtime/js/40_testing.js +++ b/runtime/js/40_testing.js @@ -26,6 +26,7 @@ RegExpPrototypeTest, SymbolToStringTag, } = window.__bootstrap.primordials; + let testStepsEnabled = false; // Wrap test function in additional assertion that makes sure // the test case does not leak async "ops" - ie. number of async @@ -594,6 +595,12 @@ finishing test case.`; * @param fn {(t: Tester) => void | Promise} */ async step(nameOrTestDefinition, fn) { + if (!testStepsEnabled) { + throw new Error( + "Test steps are unstable. The --unstable flag must be provided.", + ); + } + if (parentStep.finalized) { throw new Error( "Cannot run test step after tester's scope has finished execution. " + @@ -732,9 +739,14 @@ finishing test case.`; return value == null ? defaultValue : value; } + function enableTestSteps() { + testStepsEnabled = true; + } + window.__bootstrap.internals = { ...window.__bootstrap.internals ?? {}, runTests, + enableTestSteps, }; window.__bootstrap.testing = { diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 9bbc0697190ffe..535a253d92e25a 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -216,6 +216,9 @@ delete Object.prototype.__proto__; runtimeOptions.v8Version, runtimeOptions.tsVersion, ); + if (runtimeOptions.unstableFlag) { + internals.enableTestSteps(); + } build.setBuildInfo(runtimeOptions.target); util.setLogDebug(runtimeOptions.debugFlag, source); const prepareStackTrace = core.createPrepareStackTrace(