Skip to content

Commit 12374ad

Browse files
committed
Add expect.assertions() support for Node.js tests
- Add afterEachTest hook to BDD for assertion state cleanup - Implement assertion state checking in mod.node.ts - Add @std/expect and @std/internal via JSR registry (.npmrc) - Add test scripts to context-api, fx, signals, timebox packages - All 43 tests now pass on Node.js with expect.assertions() support
1 parent f62e69f commit 12374ad

File tree

10 files changed

+108
-5
lines changed

10 files changed

+108
-5
lines changed

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@jsr:registry=https://npm.jsr.io

bdd/bdd.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export interface TestPrimitives {
1717
only: (name: string, fn: () => void | Promise<void>) => void;
1818
};
1919
afterAll: (fn: () => void | Promise<void>) => void;
20+
/** Optional hook called after each test for assertion state cleanup */
21+
afterEachTest?: () => void;
2022
}
2123

2224
/**
@@ -42,7 +44,8 @@ export interface BDD {
4244
* This allows the BDD module to work with different test runners.
4345
*/
4446
export function createBDD(primitives: TestPrimitives): BDD {
45-
const { describe: $describe, it: $it, afterAll: $afterAll } = primitives;
47+
const { describe: $describe, it: $it, afterAll: $afterAll, afterEachTest } =
48+
primitives;
4649

4750
let current: TestAdapter | undefined;
4851

@@ -91,6 +94,7 @@ export function createBDD(primitives: TestPrimitives): BDD {
9194
}
9295
$it(desc, async () => {
9396
const result = await adapter.runTest(body);
97+
afterEachTest?.();
9498
if (!result.ok) {
9599
throw result.error;
96100
}
@@ -106,6 +110,7 @@ export function createBDD(primitives: TestPrimitives): BDD {
106110
const adapter = current!;
107111
$it.only(desc, async () => {
108112
const result = await adapter.runTest(body);
113+
afterEachTest?.();
109114
if (!result.ok) {
110115
throw result.error;
111116
}

bdd/mod.node.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,41 @@
11
import { after, describe as $describe, it as $it } from "node:test";
2+
import { getAssertionState } from "@std/internal/assertion-state";
23
import { createBDD } from "./bdd.ts";
34

5+
/**
6+
* Checks and resets the assertion state after each test.
7+
* This ensures expect.assertions() works correctly with Node's test runner.
8+
*/
9+
function checkAndResetAssertions(): void {
10+
const state = getAssertionState();
11+
12+
// Check if expect.hasAssertions() was used but no assertion was triggered
13+
if (state.checkAssertionErrorState()) {
14+
state.resetAssertionState();
15+
throw new Error(
16+
"Expected at least one assertion to be called but received none",
17+
);
18+
}
19+
20+
// Check if expect.assertions(n) count was not satisfied
21+
if (state.checkAssertionCountSatisfied()) {
22+
const expected = state.assertionCount;
23+
const actual = state.assertionTriggeredCount;
24+
state.resetAssertionState();
25+
throw new Error(
26+
`Expected ${expected} assertions to be called but received ${actual}`,
27+
);
28+
}
29+
30+
// Reset for next test
31+
state.resetAssertionState();
32+
}
33+
434
const bdd = createBDD({
535
describe: $describe,
636
it: $it,
737
afterAll: after,
38+
afterEachTest: checkAndResetAssertions,
839
});
940

1041
export const { describe, it, beforeAll, beforeEach } = bdd;

context-api/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
"type": "module",
55
"license": "MIT",
66
"exports": "./mod.ts",
7+
"scripts": {
8+
"test": "node --experimental-strip-types --test *.test.ts"
9+
},
710
"dependencies": {
8-
"effection": "^3"
11+
"effection": "^3",
12+
"@effectionx/bdd": "workspace:*"
913
}
1014
}

deno.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"nodeModulesDir": "none",
33
"imports": {
44
"effection": "npm:effection@^3",
5+
"@std/expect": "jsr:@std/expect@^1",
56
"@deno/dnt": "jsr:@deno/dnt@0.42.3",
67
"@std/path": "jsr:@std/path@^1",
78
"zod": "npm:zod@3.23.8",

fx/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
"type": "module",
55
"license": "MIT",
66
"exports": "./mod.ts",
7+
"scripts": {
8+
"test": "node --experimental-strip-types --test *.test.ts"
9+
},
710
"dependencies": {
8-
"effection": "^3"
11+
"effection": "^3",
12+
"@effectionx/bdd": "workspace:*"
913
}
1014
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"test": "pnpm -r --if-present test"
88
},
99
"dependencies": {
10+
"@std/expect": "npm:@jsr/std__expect@^1",
11+
"@std/internal": "npm:@jsr/std__internal@^1",
1012
"effection": "^3"
1113
},
1214
"volta": {

pnpm-lock.yaml

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

signals/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
"type": "module",
55
"license": "MIT",
66
"exports": "./mod.ts",
7+
"scripts": {
8+
"test": "node --experimental-strip-types --test *.test.ts"
9+
},
710
"dependencies": {
811
"effection": "^3",
9-
"immutable": "^5"
12+
"immutable": "^5",
13+
"@effectionx/bdd": "workspace:*"
1014
}
1115
}

timebox/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
"type": "module",
55
"license": "MIT",
66
"exports": "./mod.ts",
7+
"scripts": {
8+
"test": "node --experimental-strip-types --test *.test.ts"
9+
},
710
"dependencies": {
8-
"effection": "^3"
11+
"effection": "^3",
12+
"@effectionx/bdd": "workspace:*"
913
}
1014
}

0 commit comments

Comments
 (0)