import nodeAssert from "node:assert/strict"; import { test, describe, beforeEach, afterEach, after, before } from "node:test"; import type { Matcher, Test, TestFn, TestRunner } from "core/test"; // Track mock function calls const mockCalls = new WeakMap(); function createMockFunction any>(fn: T): T { const mockFn = (...args: Parameters) => { const currentCalls = mockCalls.get(mockFn) || 0; mockCalls.set(mockFn, currentCalls + 1); return fn(...args); }; return mockFn as T; } const nodeTestMatcher = (actual: T, parentFailMsg?: string) => ({ toEqual: (expected: T, failMsg = parentFailMsg) => { nodeAssert.deepEqual(actual, expected, failMsg); }, toBe: (expected: T, failMsg = parentFailMsg) => { nodeAssert.strictEqual(actual, expected, failMsg); }, toBeString: (failMsg = parentFailMsg) => { nodeAssert.strictEqual(typeof actual, "string", failMsg); }, toBeUndefined: (failMsg = parentFailMsg) => { nodeAssert.strictEqual(actual, undefined, failMsg); }, toBeDefined: (failMsg = parentFailMsg) => { nodeAssert.notStrictEqual(actual, undefined, failMsg); }, toBeOneOf: (expected: T | Array | Iterable, failMsg = parentFailMsg) => { const e = Array.isArray(expected) ? expected : [expected]; nodeAssert.ok(e.includes(actual), failMsg); }, toHaveBeenCalled: (failMsg = parentFailMsg) => { const calls = mockCalls.get(actual as Function) || 0; nodeAssert.ok(calls > 0, failMsg || "Expected function to have been called at least once"); }, toHaveBeenCalledTimes: (expected: number, failMsg = parentFailMsg) => { const calls = mockCalls.get(actual as Function) || 0; nodeAssert.strictEqual( calls, expected, failMsg || `Expected function to have been called ${expected} times`, ); }, }) satisfies Matcher; const nodeTestResolverProxy = ( actual: Promise, handler: { resolve?: any; reject?: any }, ) => { return new Proxy( {}, { get: (_, prop) => { if (prop === "then") { return actual.then(handler.resolve, handler.reject); } return actual; }, }, ) as Matcher>; }; function nodeTest(label: string, fn: TestFn, options?: any) { return test(label, fn as any); } nodeTest.if = (condition: boolean): Test => { if (condition) { return nodeTest; } return (() => {}) as any; }; nodeTest.skip = (label: string, fn: TestFn) => { return test.skip(label, fn as any); }; nodeTest.skipIf = (condition: boolean): Test => { if (condition) { return (() => {}) as any; } return nodeTest; }; export const nodeTestRunner: TestRunner = { describe, test: nodeTest, mock: createMockFunction, expect: (actual?: T, failMsg?: string) => ({ ...nodeTestMatcher(actual, failMsg), resolves: nodeTestResolverProxy(actual as Promise, { resolve: (r) => nodeTestMatcher(r, failMsg), }), rejects: nodeTestResolverProxy(actual as Promise, { reject: (r) => nodeTestMatcher(r, failMsg), }), }), beforeEach: beforeEach, afterEach: afterEach, afterAll: after, beforeAll: before, };