feat: allow first arg in test step to be a function (#17096)

This commit is contained in:
Leo Kettmeir 2023-01-24 15:41:01 +01:00 committed by GitHub
parent fc2e00152b
commit 2027d98a8e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 12 deletions

View file

@ -1265,10 +1265,10 @@
*/
origin: desc.origin,
/**
* @param nameOrTestDefinition {string | TestStepDefinition}
* @param fn {(t: TestContext) => void | Promise<void>}
* @param nameOrFnOrOptions {string | TestStepDefinition | ((t: TestContext) => void | Promise<void>)}
* @param maybeFn {((t: TestContext) => void | Promise<void>) | undefined}
*/
async step(nameOrTestDefinition, fn) {
async step(nameOrFnOrOptions, maybeFn) {
if (MapPrototypeGet(testStates, desc.id).finalized) {
throw new Error(
"Cannot run test step after parent scope has finished execution. " +
@ -1277,16 +1277,29 @@
}
let stepDesc;
if (typeof nameOrTestDefinition === "string") {
if (!(ObjectPrototypeIsPrototypeOf(FunctionPrototype, fn))) {
if (typeof nameOrFnOrOptions === "string") {
if (!(ObjectPrototypeIsPrototypeOf(FunctionPrototype, maybeFn))) {
throw new TypeError("Expected function for second argument.");
}
stepDesc = {
name: nameOrTestDefinition,
fn,
name: nameOrFnOrOptions,
fn: maybeFn,
};
} else if (typeof nameOrTestDefinition === "object") {
stepDesc = nameOrTestDefinition;
} else if (typeof nameOrFnOrOptions === "function") {
if (!nameOrFnOrOptions.name) {
throw new TypeError("The step function must have a name.");
}
if (maybeFn != undefined) {
throw new TypeError(
"Unexpected second argument to TestContext.step()",
);
}
stepDesc = {
name: nameOrFnOrOptions.name,
fn: nameOrFnOrOptions,
};
} else if (typeof nameOrFnOrOptions === "object") {
stepDesc = nameOrFnOrOptions;
} else {
throw new TypeError(
"Expected a test definition or name and function.",

View file

@ -1,11 +1,17 @@
[WILDCARD]
running 5 tests from ./test/steps/passing_steps.ts
running 6 tests from ./test/steps/passing_steps.ts
description ...
step 1 ...
inner 1 ... ok ([WILDCARD]ms)
inner 2 ... ok ([WILDCARD]ms)
step 1 ... ok ([WILDCARD]ms)
description ... ok ([WILDCARD]ms)
description function as first arg ...
step1 ...
inner1 ... ok ([WILDCARD]ms)
inner1 ... ok ([WILDCARD]ms)
step1 ... ok ([WILDCARD]ms)
description function as first arg ... ok ([WILDCARD]ms)
parallel steps without sanitizers ...
step 1 ... ok ([WILDCARD])
step 2 ... ok ([WILDCARD])
@ -35,4 +41,4 @@ steps buffered then streaming reporting ...
step 2 ... ok ([WILDCARD])
steps buffered then streaming reporting ... ok ([WILDCARD])
ok | 5 passed (18 steps) | 0 failed [WILDCARD]
ok | 6 passed (21 steps) | 0 failed [WILDCARD]

View file

@ -9,6 +9,15 @@ Deno.test("description", async (t) => {
if (!success) throw new Error("Expected the step to return true.");
});
Deno.test("description function as first arg", async (t) => {
const success = await t.step(async function step1(t) {
await t.step(function inner1() {});
await t.step(function inner1() {});
});
if (!success) throw new Error("Expected the step to return true.");
});
Deno.test("parallel steps without sanitizers", async (t) => {
// allowed
await Promise.all([

View file

@ -114,7 +114,7 @@ Deno.test(async function invalidStepArguments(t) {
await (t as any).step(() => {});
},
TypeError,
"Expected a test definition or name and function.",
"The step function must have a name.",
);
});

View file

@ -668,6 +668,25 @@ declare namespace Deno {
name: string,
fn: (t: TestContext) => void | Promise<void>,
): Promise<boolean>;
/** Run a sub step of the parent test or step. 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`.
*
* ```ts
* Deno.test(async function aParentTest(t) {
* console.log("before the step");
* await t.step(function step1(t) {
* console.log("current step:", t.name);
* });
* console.log("after the step");
* });
* ```
*/
step(fn: (t: TestContext) => void | Promise<void>): Promise<boolean>;
}
/** @category Testing */