qunitx 1.2.4 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -3
- package/dist/.build-hash +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser/index.d.ts +99 -2
- package/dist/browser/index.js +87 -8
- package/dist/deno/index.js +64 -26
- package/dist/deno/module.d.ts +3 -0
- package/dist/deno/module.js +7 -3
- package/dist/deno/test.d.ts +2 -0
- package/dist/deno/test.js +27 -15
- package/dist/node/module.d.ts +37 -0
- package/dist/node/module.js +7 -3
- package/dist/node/test.d.ts +35 -0
- package/dist/node/test.js +27 -15
- package/dist/shared/assert.js +1 -0
- package/dist/shared/module-context.d.ts +1 -1
- package/dist/shared/test-context.d.ts +4 -1
- package/dist/shared/test-context.js +21 -0
- package/dist/types.d.ts +7 -3
- package/package.json +8 -7
- package/shims/deno/module.ts +31 -9
- package/shims/deno/test.ts +33 -19
- package/shims/shared/assert.ts +1 -0
- package/shims/shared/module-context.ts +1 -1
- package/shims/shared/test-context.ts +25 -1
- package/shims/types.ts +5 -4
package/shims/deno/module.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, beforeAll, afterAll } from "jsr:@std/testing/bdd";
|
|
2
2
|
import type Assert from '../shared/assert.ts';
|
|
3
|
-
import type { HooksObject } from '../types.ts';
|
|
3
|
+
import type { HookFn, HooksObject } from '../types.ts';
|
|
4
4
|
import ModuleContext from '../shared/module-context.ts';
|
|
5
5
|
export type { Assert };
|
|
6
6
|
export type { HookFn, HooksObject, PushResultInfo } from '../types.ts';
|
|
@@ -32,13 +32,13 @@ export type { HookFn, HooksObject, PushResultInfo } from '../types.ts';
|
|
|
32
32
|
* });
|
|
33
33
|
* ```
|
|
34
34
|
*/
|
|
35
|
-
export default function module(moduleName: string, moduleContent: (hooks: HooksObject<Assert>, meta: { moduleName: string; options: unknown }) => void): void;
|
|
35
|
+
export default function module(moduleName: string, moduleContent: (hooks: HooksObject<Assert>, meta: { moduleName: string; options: unknown; context: Record<string, unknown> }) => void): void;
|
|
36
36
|
/** Defines a test module (suite) with optional Deno BDD runtime options forwarded to `describe()`. */
|
|
37
|
-
export default function module(moduleName: string, runtimeOptions: object, moduleContent: (hooks: HooksObject<Assert>, meta: { moduleName: string; options: unknown }) => void): void;
|
|
37
|
+
export default function module(moduleName: string, runtimeOptions: object, moduleContent: (hooks: HooksObject<Assert>, meta: { moduleName: string; options: unknown; context: Record<string, unknown> }) => void): void;
|
|
38
38
|
export default function module(
|
|
39
39
|
moduleName: string,
|
|
40
40
|
runtimeOptions: object | ((hooks: HooksObject<Assert>) => void),
|
|
41
|
-
moduleContent?: (hooks: HooksObject<Assert>, meta: { moduleName: string; options: unknown }) => void,
|
|
41
|
+
moduleContent?: (hooks: HooksObject<Assert>, meta: { moduleName: string; options: unknown; context: Record<string, unknown> }) => void,
|
|
42
42
|
): void {
|
|
43
43
|
const targetRuntimeOptions = moduleContent ? runtimeOptions as object : {};
|
|
44
44
|
const { skip } = targetRuntimeOptions as { skip?: boolean | string };
|
|
@@ -57,8 +57,8 @@ export default function module(
|
|
|
57
57
|
const moduleContext = new ModuleContext(moduleName);
|
|
58
58
|
|
|
59
59
|
describe(moduleName, { ...targetRuntimeOptions }, function () {
|
|
60
|
-
const beforeHooks:
|
|
61
|
-
const afterHooks:
|
|
60
|
+
const beforeHooks: HookFn<Assert>[] = [];
|
|
61
|
+
const afterHooks: HookFn<Assert>[] = [];
|
|
62
62
|
|
|
63
63
|
beforeAll(async function () {
|
|
64
64
|
// before() assertions are attributed to the first direct test only (matching QUnit's model).
|
|
@@ -67,7 +67,7 @@ export default function module(
|
|
|
67
67
|
const beforeAssert = firstTest ? firstTest.assert! : moduleContext.assert!;
|
|
68
68
|
|
|
69
69
|
for (const hook of beforeHooks) {
|
|
70
|
-
await hook.call(moduleContext.userContext, beforeAssert);
|
|
70
|
+
await hook.call(moduleContext.userContext, beforeAssert, { context: moduleContext.userContext });
|
|
71
71
|
}
|
|
72
72
|
});
|
|
73
73
|
|
|
@@ -79,7 +79,7 @@ export default function module(
|
|
|
79
79
|
const lastTest = moduleContext.tests[moduleContext.tests.length - 1];
|
|
80
80
|
if (lastTest) {
|
|
81
81
|
for (let j = afterHooks.length - 1; j >= 0; j--) {
|
|
82
|
-
await afterHooks[j]!.call(lastTest.userContext, lastTest.assert
|
|
82
|
+
await afterHooks[j]!.call(lastTest.userContext, lastTest.assert!, { context: lastTest.userContext });
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
@@ -101,7 +101,7 @@ export default function module(
|
|
|
101
101
|
after(afterFn) {
|
|
102
102
|
afterHooks.push(afterFn);
|
|
103
103
|
}
|
|
104
|
-
}, { moduleName, options: runtimeOptions });
|
|
104
|
+
}, { moduleName, options: runtimeOptions, context: moduleContext.userContext });
|
|
105
105
|
|
|
106
106
|
ModuleContext.currentModuleChain.pop();
|
|
107
107
|
});
|
|
@@ -127,3 +127,25 @@ export default function module(
|
|
|
127
127
|
module.skip = function skipModule(moduleName: string, _moduleContent?: unknown): void {
|
|
128
128
|
describe(moduleName, { ignore: true }, function () {});
|
|
129
129
|
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Marks all tests inside a module as todo. Equivalent to `QUnit.module.todo`.
|
|
133
|
+
* The module is registered as ignored by Deno's runner; no test bodies run.
|
|
134
|
+
* Deno has no native "todo module" concept, so this maps to ignore.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} moduleName - Name of the module to mark as todo.
|
|
137
|
+
* @param {function} [_moduleContent] - Optional body (ignored — no tests run).
|
|
138
|
+
* @example
|
|
139
|
+
* ```js ignore
|
|
140
|
+
* import { module, test } from "qunitx";
|
|
141
|
+
*
|
|
142
|
+
* module.todo("Math — not yet implemented", () => {
|
|
143
|
+
* test("addition", (assert) => {
|
|
144
|
+
* assert.equal(1 + 1, 2);
|
|
145
|
+
* });
|
|
146
|
+
* });
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
module.todo = function todoModule(moduleName: string, _moduleContent?: unknown): void {
|
|
150
|
+
describe(moduleName, { ignore: true }, function () {});
|
|
151
|
+
};
|
package/shims/deno/test.ts
CHANGED
|
@@ -36,13 +36,13 @@ export type { PushResultInfo } from '../types.ts';
|
|
|
36
36
|
* });
|
|
37
37
|
* ```
|
|
38
38
|
*/
|
|
39
|
-
export default function test(testName: string, testContent: (assert: Assert, meta: { testName: string; options: unknown }) => void | Promise<void>): void;
|
|
39
|
+
export default function test(testName: string, testContent: (assert: Assert, meta: { testName: string; options: unknown; context: Record<string, unknown> }) => void | Promise<void>): void;
|
|
40
40
|
/** Defines an individual test with optional Deno BDD runtime options forwarded to `it()`. */
|
|
41
|
-
export default function test(testName: string, runtimeOptions: object, testContent: (assert: Assert, meta: { testName: string; options: unknown }) => void | Promise<void>): void;
|
|
41
|
+
export default function test(testName: string, runtimeOptions: object, testContent: (assert: Assert, meta: { testName: string; options: unknown; context: Record<string, unknown> }) => void | Promise<void>): void;
|
|
42
42
|
export default function test(
|
|
43
43
|
testName: string,
|
|
44
|
-
runtimeOptions: object | ((assert: Assert, meta: { testName: string; options: unknown }) => void | Promise<void>),
|
|
45
|
-
testContent?: (assert: Assert, meta: { testName: string; options: unknown }) => void | Promise<void>,
|
|
44
|
+
runtimeOptions: object | ((assert: Assert, meta: { testName: string; options: unknown; context: Record<string, unknown> }) => void | Promise<void>),
|
|
45
|
+
testContent?: (assert: Assert, meta: { testName: string; options: unknown; context: Record<string, unknown> }) => void | Promise<void>,
|
|
46
46
|
): void {
|
|
47
47
|
const moduleContext = ModuleContext.lastModule;
|
|
48
48
|
if (!moduleContext) {
|
|
@@ -68,25 +68,39 @@ export default function test(
|
|
|
68
68
|
const userContext = Object.create(moduleContext.userContext);
|
|
69
69
|
context.userContext = userContext;
|
|
70
70
|
|
|
71
|
-
it(testName, { ...targetRuntimeOptions },
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
await hook.call(userContext, context.assert!);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
71
|
+
it(testName, { ...targetRuntimeOptions }, function () {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
context.rejectTimeout = reject;
|
|
77
74
|
|
|
78
|
-
|
|
75
|
+
(async () => {
|
|
76
|
+
const hookMeta = { context: userContext };
|
|
79
77
|
|
|
80
|
-
|
|
78
|
+
try {
|
|
79
|
+
for (const module of context.module!.moduleChain) {
|
|
80
|
+
for (const hook of module.beforeEachHooks) {
|
|
81
|
+
await hook.call(userContext, context.assert!, hookMeta);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
const module = context.module!.moduleChain[i];
|
|
84
|
-
for (let j = module.afterEachHooks.length - 1; j >= 0; j--) {
|
|
85
|
-
await module.afterEachHooks[j]!.call(userContext, context.assert!);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
85
|
+
const result = await targetTestContent.call(userContext, context.assert!, { testName, options: runtimeOptions, context: userContext });
|
|
88
86
|
|
|
89
|
-
|
|
87
|
+
await context.assert!.waitForAsyncOps();
|
|
88
|
+
|
|
89
|
+
for (let i = context.module!.moduleChain.length - 1; i >= 0; i--) {
|
|
90
|
+
const module = context.module!.moduleChain[i];
|
|
91
|
+
for (let j = module.afterEachHooks.length - 1; j >= 0; j--) {
|
|
92
|
+
await module.afterEachHooks[j]!.call(userContext, context.assert!, hookMeta);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
resolve(result);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
reject(err);
|
|
99
|
+
} finally {
|
|
100
|
+
context.clearTimeoutHandle();
|
|
101
|
+
}
|
|
102
|
+
})();
|
|
103
|
+
});
|
|
90
104
|
});
|
|
91
105
|
}
|
|
92
106
|
|
package/shims/shared/assert.ts
CHANGED
|
@@ -44,6 +44,29 @@ export default class TestContext {
|
|
|
44
44
|
this.#timeout = value;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
rejectTimeout: ((err: Error) => void) | undefined;
|
|
48
|
+
#timeoutHandle: ReturnType<typeof setTimeout> | undefined;
|
|
49
|
+
#timedOut = false;
|
|
50
|
+
|
|
51
|
+
setTimeoutDuration(ms: number) {
|
|
52
|
+
if (this.#timeoutHandle !== undefined) {
|
|
53
|
+
clearTimeout(this.#timeoutHandle);
|
|
54
|
+
this.#timeoutHandle = undefined;
|
|
55
|
+
}
|
|
56
|
+
if (!this.rejectTimeout) return;
|
|
57
|
+
this.#timeoutHandle = setTimeout(() => {
|
|
58
|
+
this.#timedOut = true;
|
|
59
|
+
this.rejectTimeout!(new Error(`Test timed out after ${ms}ms`));
|
|
60
|
+
}, ms);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
clearTimeoutHandle() {
|
|
64
|
+
if (this.#timeoutHandle !== undefined) {
|
|
65
|
+
clearTimeout(this.#timeoutHandle);
|
|
66
|
+
this.#timeoutHandle = undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
47
70
|
#steps: string[] = [];
|
|
48
71
|
get steps() {
|
|
49
72
|
return this.#steps;
|
|
@@ -68,7 +91,7 @@ export default class TestContext {
|
|
|
68
91
|
this.#totalExecutedAssertions = value;
|
|
69
92
|
}
|
|
70
93
|
|
|
71
|
-
userContext:
|
|
94
|
+
userContext: Record<string, unknown> = {};
|
|
72
95
|
|
|
73
96
|
constructor(name?: string, moduleContext?: ModuleContext) {
|
|
74
97
|
if (moduleContext) {
|
|
@@ -80,6 +103,7 @@ export default class TestContext {
|
|
|
80
103
|
}
|
|
81
104
|
|
|
82
105
|
finish() {
|
|
106
|
+
if (this.#timedOut) return;
|
|
83
107
|
if (this.totalExecutedAssertions === 0) {
|
|
84
108
|
this.assert!.pushResult({
|
|
85
109
|
result: false,
|
package/shims/types.ts
CHANGED
|
@@ -37,8 +37,9 @@ export interface TestState {
|
|
|
37
37
|
asyncOps: Promise<void>[];
|
|
38
38
|
timeout?: number;
|
|
39
39
|
expectedAssertionCount?: number;
|
|
40
|
-
userContext?:
|
|
40
|
+
userContext?: Record<string, unknown>;
|
|
41
41
|
module?: { name: string };
|
|
42
|
+
setTimeoutDuration(ms: number): void;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
/** Minimal module shape that Assert needs to resolve a fallback test context. */
|
|
@@ -46,11 +47,11 @@ export interface ModuleState {
|
|
|
46
47
|
context: TestState;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
/** A lifecycle hook callback that receives an {@linkcode Assert} instance. */
|
|
50
|
-
export type HookFn<A = unknown> = (assert: A) => void | Promise<void>;
|
|
50
|
+
/** A lifecycle hook callback that receives an {@linkcode Assert} instance and a meta object with the shared context. */
|
|
51
|
+
export type HookFn<A = unknown> = (assert: A, meta: { context: Record<string, unknown> }) => void | Promise<void>;
|
|
51
52
|
export type TestFn<A = unknown> = (
|
|
52
53
|
assert: A,
|
|
53
|
-
meta: { testName: string; options: unknown },
|
|
54
|
+
meta: { testName: string; options: unknown; context: Record<string, unknown> },
|
|
54
55
|
) => void | Promise<unknown>;
|
|
55
56
|
|
|
56
57
|
/** Lifecycle hooks available inside a `module()` callback. */
|