qunitx 1.2.2 → 1.2.5
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 +98 -2
- package/dist/browser/index.js +84 -2
- package/dist/deno/index.d.ts +5 -2
- package/dist/deno/index.js +23 -16
- package/dist/deno/module.d.ts +2 -0
- package/dist/deno/module.js +3 -3
- package/dist/deno/test.d.ts +7 -2
- package/dist/deno/test.js +10 -5
- package/dist/node/index.d.ts +4 -0
- package/dist/node/index.js +3 -1
- package/dist/node/module.d.ts +36 -0
- package/dist/node/module.js +3 -3
- package/dist/node/test.d.ts +39 -0
- package/dist/node/test.js +15 -5
- package/dist/shared/module-context.d.ts +1 -1
- package/dist/shared/test-context.d.ts +1 -1
- package/dist/types.d.ts +6 -3
- package/package.json +8 -7
- package/shims/deno/index.ts +5 -2
- package/shims/deno/module.ts +9 -9
- package/shims/deno/test.ts +39 -14
- package/shims/shared/module-context.ts +1 -1
- package/shims/shared/test-context.ts +1 -1
- package/shims/types.ts +4 -4
package/dist/deno/index.js
CHANGED
|
@@ -1049,13 +1049,13 @@ var require_qunit = __commonJS({
|
|
|
1049
1049
|
}, {
|
|
1050
1050
|
key: "getStatus",
|
|
1051
1051
|
value: function getStatus() {
|
|
1052
|
-
var _this$getTestCounts = this.getTestCounts(), total = _this$getTestCounts.total, failed = _this$getTestCounts.failed, skipped = _this$getTestCounts.skipped,
|
|
1052
|
+
var _this$getTestCounts = this.getTestCounts(), total = _this$getTestCounts.total, failed = _this$getTestCounts.failed, skipped = _this$getTestCounts.skipped, todo2 = _this$getTestCounts.todo;
|
|
1053
1053
|
if (failed) {
|
|
1054
1054
|
return "failed";
|
|
1055
1055
|
} else {
|
|
1056
1056
|
if (skipped === total) {
|
|
1057
1057
|
return "skipped";
|
|
1058
|
-
} else if (
|
|
1058
|
+
} else if (todo2 === total) {
|
|
1059
1059
|
return "todo";
|
|
1060
1060
|
} else {
|
|
1061
1061
|
return "passed";
|
|
@@ -1081,7 +1081,7 @@ var require_qunit = __commonJS({
|
|
|
1081
1081
|
var moduleName = parentModule !== null ? [parentModule.name, name].join(" > ") : name;
|
|
1082
1082
|
var parentSuite = parentModule ? parentModule.suiteReport : runSuite;
|
|
1083
1083
|
var skip2 = parentModule !== null && parentModule.skip || modifiers.skip;
|
|
1084
|
-
var
|
|
1084
|
+
var todo2 = parentModule !== null && parentModule.todo || modifiers.todo;
|
|
1085
1085
|
var env = {};
|
|
1086
1086
|
if (parentModule) {
|
|
1087
1087
|
extend(env, parentModule.testEnvironment);
|
|
@@ -1111,7 +1111,7 @@ var require_qunit = __commonJS({
|
|
|
1111
1111
|
// This property will be used to mark own tests and tests of child suites
|
|
1112
1112
|
// as either `skipped` or `todo`.
|
|
1113
1113
|
skip: skip2,
|
|
1114
|
-
todo: skip2 ? false :
|
|
1114
|
+
todo: skip2 ? false : todo2,
|
|
1115
1115
|
ignored: modifiers.ignored || false
|
|
1116
1116
|
};
|
|
1117
1117
|
if (parentModule) {
|
|
@@ -2373,7 +2373,7 @@ var require_qunit = __commonJS({
|
|
|
2373
2373
|
var moduleName = module3.name;
|
|
2374
2374
|
var testName = this.testName;
|
|
2375
2375
|
var skipped = !!this.skip;
|
|
2376
|
-
var
|
|
2376
|
+
var todo2 = !!this.todo;
|
|
2377
2377
|
var bad = 0;
|
|
2378
2378
|
var storage = config.storage;
|
|
2379
2379
|
this.runtime = Math.round(performance.now() - this.started);
|
|
@@ -2406,7 +2406,7 @@ var require_qunit = __commonJS({
|
|
|
2406
2406
|
name: testName,
|
|
2407
2407
|
module: moduleName,
|
|
2408
2408
|
skipped,
|
|
2409
|
-
todo,
|
|
2409
|
+
todo: todo2,
|
|
2410
2410
|
failed: bad,
|
|
2411
2411
|
passed: this.assertions.length - bad,
|
|
2412
2412
|
total: this.assertions.length,
|
|
@@ -2866,7 +2866,7 @@ var require_qunit = __commonJS({
|
|
|
2866
2866
|
}
|
|
2867
2867
|
}
|
|
2868
2868
|
extend(test3, {
|
|
2869
|
-
todo: function
|
|
2869
|
+
todo: function todo2(testName, callback) {
|
|
2870
2870
|
addTest({
|
|
2871
2871
|
testName,
|
|
2872
2872
|
callback,
|
|
@@ -7686,7 +7686,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
7686
7686
|
const firstTest = moduleContext.tests[0];
|
|
7687
7687
|
const beforeAssert = firstTest ? firstTest.assert : moduleContext.assert;
|
|
7688
7688
|
for (const hook of beforeHooks) {
|
|
7689
|
-
await hook.call(moduleContext.userContext, beforeAssert);
|
|
7689
|
+
await hook.call(moduleContext.userContext, beforeAssert, { context: moduleContext.userContext });
|
|
7690
7690
|
}
|
|
7691
7691
|
});
|
|
7692
7692
|
afterAll(async () => {
|
|
@@ -7696,7 +7696,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
7696
7696
|
const lastTest = moduleContext.tests[moduleContext.tests.length - 1];
|
|
7697
7697
|
if (lastTest) {
|
|
7698
7698
|
for (let j = afterHooks.length - 1; j >= 0; j--) {
|
|
7699
|
-
await afterHooks[j].call(lastTest.userContext, lastTest.assert);
|
|
7699
|
+
await afterHooks[j].call(lastTest.userContext, lastTest.assert, { context: lastTest.userContext });
|
|
7700
7700
|
}
|
|
7701
7701
|
}
|
|
7702
7702
|
for (let i = 0, len = moduleContext.tests.length; i < len; i++) {
|
|
@@ -7716,7 +7716,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
7716
7716
|
after(afterFn) {
|
|
7717
7717
|
afterHooks.push(afterFn);
|
|
7718
7718
|
}
|
|
7719
|
-
}, { moduleName, options: runtimeOptions });
|
|
7719
|
+
}, { moduleName, options: runtimeOptions, context: moduleContext.userContext });
|
|
7720
7720
|
ModuleContext.currentModuleChain.pop();
|
|
7721
7721
|
});
|
|
7722
7722
|
}
|
|
@@ -7732,8 +7732,8 @@ function test2(testName, runtimeOptions, testContent) {
|
|
|
7732
7732
|
throw new Error(`Test '${testName}' called outside of module context.`);
|
|
7733
7733
|
}
|
|
7734
7734
|
const targetRuntimeOptions = testContent ? runtimeOptions : {};
|
|
7735
|
-
const { skip: skip2 } = targetRuntimeOptions;
|
|
7736
|
-
if (skip2) {
|
|
7735
|
+
const { skip: skip2, todo: todo2 } = targetRuntimeOptions;
|
|
7736
|
+
if (skip2 || todo2) {
|
|
7737
7737
|
it(testName, { ignore: true }, async function() {
|
|
7738
7738
|
});
|
|
7739
7739
|
return;
|
|
@@ -7743,17 +7743,18 @@ function test2(testName, runtimeOptions, testContent) {
|
|
|
7743
7743
|
const userContext = Object.create(moduleContext.userContext);
|
|
7744
7744
|
context.userContext = userContext;
|
|
7745
7745
|
it(testName, { ...targetRuntimeOptions }, async function() {
|
|
7746
|
+
const hookMeta = { context: userContext };
|
|
7746
7747
|
for (const module2 of context.module.moduleChain) {
|
|
7747
7748
|
for (const hook of module2.beforeEachHooks) {
|
|
7748
|
-
await hook.call(userContext, context.assert);
|
|
7749
|
+
await hook.call(userContext, context.assert, hookMeta);
|
|
7749
7750
|
}
|
|
7750
7751
|
}
|
|
7751
|
-
const result = await targetTestContent.call(userContext, context.assert, { testName, options: runtimeOptions });
|
|
7752
|
+
const result = await targetTestContent.call(userContext, context.assert, { testName, options: runtimeOptions, context: userContext });
|
|
7752
7753
|
await context.assert.waitForAsyncOps();
|
|
7753
7754
|
for (let i = context.module.moduleChain.length - 1; i >= 0; i--) {
|
|
7754
7755
|
const module2 = context.module.moduleChain[i];
|
|
7755
7756
|
for (let j = module2.afterEachHooks.length - 1; j >= 0; j--) {
|
|
7756
|
-
await module2.afterEachHooks[j].call(userContext, context.assert);
|
|
7757
|
+
await module2.afterEachHooks[j].call(userContext, context.assert, hookMeta);
|
|
7757
7758
|
}
|
|
7758
7759
|
}
|
|
7759
7760
|
return result;
|
|
@@ -7763,6 +7764,10 @@ test2.skip = function skipTest(testName, _testContent) {
|
|
|
7763
7764
|
it(testName, { ignore: true }, async function() {
|
|
7764
7765
|
});
|
|
7765
7766
|
};
|
|
7767
|
+
test2.todo = function todoTest(testName, _testContent) {
|
|
7768
|
+
it(testName, { ignore: true }, async function() {
|
|
7769
|
+
});
|
|
7770
|
+
};
|
|
7766
7771
|
|
|
7767
7772
|
// shims/deno/index.ts
|
|
7768
7773
|
var AssertionError2 = class extends AssertionError {
|
|
@@ -7779,6 +7784,7 @@ Object.freeze(Assert);
|
|
|
7779
7784
|
Object.freeze(ModuleContext);
|
|
7780
7785
|
Object.freeze(TestContext);
|
|
7781
7786
|
var skip = test2.skip;
|
|
7787
|
+
var todo = test2.todo;
|
|
7782
7788
|
var index_default = { AssertionError: Assert.AssertionError, module, test: test2, config: {} };
|
|
7783
7789
|
export {
|
|
7784
7790
|
Assert,
|
|
@@ -7786,7 +7792,8 @@ export {
|
|
|
7786
7792
|
index_default as default,
|
|
7787
7793
|
module,
|
|
7788
7794
|
skip,
|
|
7789
|
-
test2 as test
|
|
7795
|
+
test2 as test,
|
|
7796
|
+
todo
|
|
7790
7797
|
};
|
|
7791
7798
|
/*!
|
|
7792
7799
|
* QUnit 2.25.0
|
package/dist/deno/module.d.ts
CHANGED
|
@@ -32,11 +32,13 @@ export type { HookFn, HooksObject, PushResultInfo } from '../types.d.ts';
|
|
|
32
32
|
export default function module(moduleName: string, moduleContent: (hooks: HooksObject<Assert>, meta: {
|
|
33
33
|
moduleName: string;
|
|
34
34
|
options: unknown;
|
|
35
|
+
context: Record<string, unknown>;
|
|
35
36
|
}) => void): void;
|
|
36
37
|
/** Defines a test module (suite) with optional Deno BDD runtime options forwarded to `describe()`. */
|
|
37
38
|
declare function module(moduleName: string, runtimeOptions: object, moduleContent: (hooks: HooksObject<Assert>, meta: {
|
|
38
39
|
moduleName: string;
|
|
39
40
|
options: unknown;
|
|
41
|
+
context: Record<string, unknown>;
|
|
40
42
|
}) => void): void;
|
|
41
43
|
declare namespace module {
|
|
42
44
|
var skip: (moduleName: string, _moduleContent?: unknown) => void;
|
package/dist/deno/module.js
CHANGED
|
@@ -17,7 +17,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
17
17
|
const firstTest = moduleContext.tests[0];
|
|
18
18
|
const beforeAssert = firstTest ? firstTest.assert : moduleContext.assert;
|
|
19
19
|
for (const hook of beforeHooks) {
|
|
20
|
-
await hook.call(moduleContext.userContext, beforeAssert);
|
|
20
|
+
await hook.call(moduleContext.userContext, beforeAssert, { context: moduleContext.userContext });
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
afterAll(async () => {
|
|
@@ -27,7 +27,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
27
27
|
const lastTest = moduleContext.tests[moduleContext.tests.length - 1];
|
|
28
28
|
if (lastTest) {
|
|
29
29
|
for (let j = afterHooks.length - 1; j >= 0; j--) {
|
|
30
|
-
await afterHooks[j].call(lastTest.userContext, lastTest.assert);
|
|
30
|
+
await afterHooks[j].call(lastTest.userContext, lastTest.assert, { context: lastTest.userContext });
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
for (let i = 0, len = moduleContext.tests.length; i < len; i++) {
|
|
@@ -47,7 +47,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
47
47
|
after(afterFn) {
|
|
48
48
|
afterHooks.push(afterFn);
|
|
49
49
|
}
|
|
50
|
-
}, { moduleName, options: runtimeOptions });
|
|
50
|
+
}, { moduleName, options: runtimeOptions, context: moduleContext.userContext });
|
|
51
51
|
ModuleContext.currentModuleChain.pop();
|
|
52
52
|
});
|
|
53
53
|
}
|
package/dist/deno/test.d.ts
CHANGED
|
@@ -10,8 +10,10 @@ export type { PushResultInfo } from '../types.d.ts';
|
|
|
10
10
|
* Must be called inside a `module()` callback.
|
|
11
11
|
*
|
|
12
12
|
* @param {string} testName - Name of the test
|
|
13
|
-
* @param {object} [runtimeOptions] - Optional
|
|
14
|
-
*
|
|
13
|
+
* @param {object} [runtimeOptions] - Optional options forwarded to `it()`.
|
|
14
|
+
* Use `{ skip: true | string }` to skip the test, `{ todo: true | string }` to mark it as todo
|
|
15
|
+
* (both map to Deno's `{ ignore: true }`). Other Deno BDD options like
|
|
16
|
+
* `{ concurrency: false }` or `{ sanitizeExit: false }` are forwarded as-is.
|
|
15
17
|
* @param {function} testContent - Test callback receiving `(assert, { testName, options })`
|
|
16
18
|
* @returns {void}
|
|
17
19
|
* @example
|
|
@@ -33,13 +35,16 @@ export type { PushResultInfo } from '../types.d.ts';
|
|
|
33
35
|
export default function test(testName: string, testContent: (assert: Assert, meta: {
|
|
34
36
|
testName: string;
|
|
35
37
|
options: unknown;
|
|
38
|
+
context: Record<string, unknown>;
|
|
36
39
|
}) => void | Promise<void>): void;
|
|
37
40
|
/** Defines an individual test with optional Deno BDD runtime options forwarded to `it()`. */
|
|
38
41
|
declare function test(testName: string, runtimeOptions: object, testContent: (assert: Assert, meta: {
|
|
39
42
|
testName: string;
|
|
40
43
|
options: unknown;
|
|
44
|
+
context: Record<string, unknown>;
|
|
41
45
|
}) => void | Promise<void>): void;
|
|
42
46
|
declare namespace test {
|
|
43
47
|
var skip: (testName: string, _testContent?: unknown) => void;
|
|
48
|
+
var todo: (testName: string, _testContent?: unknown) => void;
|
|
44
49
|
}
|
|
45
50
|
export default test;
|
package/dist/deno/test.js
CHANGED
|
@@ -7,8 +7,8 @@ function test(testName, runtimeOptions, testContent) {
|
|
|
7
7
|
throw new Error(`Test '${testName}' called outside of module context.`);
|
|
8
8
|
}
|
|
9
9
|
const targetRuntimeOptions = testContent ? runtimeOptions : {};
|
|
10
|
-
const { skip } = targetRuntimeOptions;
|
|
11
|
-
if (skip) {
|
|
10
|
+
const { skip, todo } = targetRuntimeOptions;
|
|
11
|
+
if (skip || todo) {
|
|
12
12
|
it(testName, { ignore: true }, async function() {
|
|
13
13
|
});
|
|
14
14
|
return;
|
|
@@ -18,17 +18,18 @@ function test(testName, runtimeOptions, testContent) {
|
|
|
18
18
|
const userContext = Object.create(moduleContext.userContext);
|
|
19
19
|
context.userContext = userContext;
|
|
20
20
|
it(testName, { ...targetRuntimeOptions }, async function() {
|
|
21
|
+
const hookMeta = { context: userContext };
|
|
21
22
|
for (const module of context.module.moduleChain) {
|
|
22
23
|
for (const hook of module.beforeEachHooks) {
|
|
23
|
-
await hook.call(userContext, context.assert);
|
|
24
|
+
await hook.call(userContext, context.assert, hookMeta);
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
const result = await targetTestContent.call(userContext, context.assert, { testName, options: runtimeOptions });
|
|
27
|
+
const result = await targetTestContent.call(userContext, context.assert, { testName, options: runtimeOptions, context: userContext });
|
|
27
28
|
await context.assert.waitForAsyncOps();
|
|
28
29
|
for (let i = context.module.moduleChain.length - 1; i >= 0; i--) {
|
|
29
30
|
const module = context.module.moduleChain[i];
|
|
30
31
|
for (let j = module.afterEachHooks.length - 1; j >= 0; j--) {
|
|
31
|
-
await module.afterEachHooks[j].call(userContext, context.assert);
|
|
32
|
+
await module.afterEachHooks[j].call(userContext, context.assert, hookMeta);
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
return result;
|
|
@@ -38,6 +39,10 @@ test.skip = function skipTest(testName, _testContent) {
|
|
|
38
39
|
it(testName, { ignore: true }, async function() {
|
|
39
40
|
});
|
|
40
41
|
};
|
|
42
|
+
test.todo = function todoTest(testName, _testContent) {
|
|
43
|
+
it(testName, { ignore: true }, async function() {
|
|
44
|
+
});
|
|
45
|
+
};
|
|
41
46
|
export {
|
|
42
47
|
test as default
|
|
43
48
|
};
|
package/dist/node/index.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ export { default as module } from './module.d.ts';
|
|
|
5
5
|
export { default as test } from './test.d.ts';
|
|
6
6
|
export { Assert };
|
|
7
7
|
export declare const skip: (testName: string, _testContent?: unknown) => void;
|
|
8
|
+
export declare const todo: (testName: string, testContent?: (assert: Assert, meta: {
|
|
9
|
+
testName: string;
|
|
10
|
+
options: unknown;
|
|
11
|
+
}) => void | Promise<void>) => void;
|
|
8
12
|
declare const _default: {
|
|
9
13
|
AssertionError: import("../types.d.ts").AssertionErrorConstructor;
|
|
10
14
|
module: typeof Module;
|
package/dist/node/index.js
CHANGED
|
@@ -17,11 +17,13 @@ Object.freeze(TestContext);
|
|
|
17
17
|
import { default as default2 } from "./module.js";
|
|
18
18
|
import { default as default3 } from "./test.js";
|
|
19
19
|
const skip = Test.skip;
|
|
20
|
+
const todo = Test.todo;
|
|
20
21
|
var node_default = { AssertionError: Assert.AssertionError, module: Module, test: Test, config: {} };
|
|
21
22
|
export {
|
|
22
23
|
Assert,
|
|
23
24
|
node_default as default,
|
|
24
25
|
default2 as module,
|
|
25
26
|
skip,
|
|
26
|
-
default3 as test
|
|
27
|
+
default3 as test,
|
|
28
|
+
todo
|
|
27
29
|
};
|
package/dist/node/module.d.ts
CHANGED
|
@@ -1,12 +1,48 @@
|
|
|
1
1
|
import type Assert from '../shared/assert.d.ts';
|
|
2
2
|
import type { HooksObject } from '../types.d.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Defines a test module (suite) for Node's built-in test runner.
|
|
5
|
+
*
|
|
6
|
+
* Wraps `describe()` from `node:test` and sets up the QUnit lifecycle
|
|
7
|
+
* (before/beforeEach/afterEach/after hooks, assertion counting, steps tracking).
|
|
8
|
+
*
|
|
9
|
+
* @param {string} moduleName - Name of the test suite.
|
|
10
|
+
* @param {object} [runtimeOptions] - Optional Node test runner options forwarded to `describe()`
|
|
11
|
+
* (e.g. `{ concurrency: true }`, `{ timeout: 5000 }`). Use `{ skip: true | string }` to skip
|
|
12
|
+
* the entire module.
|
|
13
|
+
* @param {function} moduleContent - Callback that defines tests and hooks via `hooks.before`,
|
|
14
|
+
* `hooks.beforeEach`, `hooks.afterEach`, `hooks.after`.
|
|
15
|
+
* Receives `(hooks, { moduleName, options, context })`.
|
|
16
|
+
* `context` is the shared module environment — the same object as `this` in
|
|
17
|
+
* regular-function callbacks, useful when using arrow functions.
|
|
18
|
+
* @returns {void}
|
|
19
|
+
* @example
|
|
20
|
+
* ```js
|
|
21
|
+
* import { module, test } from "qunitx";
|
|
22
|
+
*
|
|
23
|
+
* module("Math", (hooks, { context }) => {
|
|
24
|
+
* context.multiplier = 2;
|
|
25
|
+
*
|
|
26
|
+
* hooks.beforeEach((assert, { context }) => {
|
|
27
|
+
* context.value = 21;
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* test("multiplication", (assert, { context }) => {
|
|
31
|
+
* assert.equal(context.value * context.multiplier, 42);
|
|
32
|
+
* });
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
3
36
|
export default function module(moduleName: string, moduleContent: (hooks: HooksObject<Assert>, meta: {
|
|
4
37
|
moduleName: string;
|
|
5
38
|
options: unknown;
|
|
39
|
+
context: Record<string, unknown>;
|
|
6
40
|
}) => void): void;
|
|
41
|
+
/** Defines a test module (suite) with optional Node test runner options forwarded to `describe()`. */
|
|
7
42
|
declare function module(moduleName: string, runtimeOptions: object, moduleContent: (hooks: HooksObject<Assert>, meta: {
|
|
8
43
|
moduleName: string;
|
|
9
44
|
options: unknown;
|
|
45
|
+
context: Record<string, unknown>;
|
|
10
46
|
}) => void): void;
|
|
11
47
|
declare namespace module {
|
|
12
48
|
var skip: (moduleName: string, _moduleContent?: unknown) => void;
|
package/dist/node/module.js
CHANGED
|
@@ -17,7 +17,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
17
17
|
const firstTest = moduleContext.tests[0];
|
|
18
18
|
const beforeAssert = firstTest ? firstTest.assert : moduleContext.assert;
|
|
19
19
|
for (const hook of beforeHooks) {
|
|
20
|
-
await hook.call(moduleContext.userContext, beforeAssert);
|
|
20
|
+
await hook.call(moduleContext.userContext, beforeAssert, { context: moduleContext.userContext });
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
afterAll(async () => {
|
|
@@ -27,7 +27,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
27
27
|
const lastTest = moduleContext.tests[moduleContext.tests.length - 1];
|
|
28
28
|
if (lastTest) {
|
|
29
29
|
for (let j = afterHooks.length - 1; j >= 0; j--) {
|
|
30
|
-
await afterHooks[j].call(lastTest.userContext, lastTest.assert);
|
|
30
|
+
await afterHooks[j].call(lastTest.userContext, lastTest.assert, { context: lastTest.userContext });
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
for (let i = 0, len = moduleContext.tests.length; i < len; i++) {
|
|
@@ -47,7 +47,7 @@ function module(moduleName, runtimeOptions, moduleContent) {
|
|
|
47
47
|
after(afterFn) {
|
|
48
48
|
afterHooks.push(afterFn);
|
|
49
49
|
}
|
|
50
|
-
}, { moduleName, options: runtimeOptions });
|
|
50
|
+
}, { moduleName, options: runtimeOptions, context: moduleContext.userContext });
|
|
51
51
|
ModuleContext.currentModuleChain.pop();
|
|
52
52
|
});
|
|
53
53
|
}
|
package/dist/node/test.d.ts
CHANGED
|
@@ -1,13 +1,52 @@
|
|
|
1
1
|
import type Assert from '../shared/assert.d.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Defines an individual test within a module for Node's built-in test runner.
|
|
4
|
+
*
|
|
5
|
+
* Wraps `it()` from `node:test` and handles the full QUnit lifecycle:
|
|
6
|
+
* beforeEach/afterEach hooks, async assertion waiting, and step verification.
|
|
7
|
+
*
|
|
8
|
+
* Must be called inside a `module()` callback.
|
|
9
|
+
*
|
|
10
|
+
* @param {string} testName - Name of the test.
|
|
11
|
+
* @param {object} [runtimeOptions] - Optional Node test runner options forwarded to `it()`.
|
|
12
|
+
* Use `{ skip: true | string }` to skip the test, `{ todo: true | string }` to mark it as todo.
|
|
13
|
+
* Other Node options like `{ concurrency: true }` or `{ timeout: 5000 }` are forwarded as-is.
|
|
14
|
+
* @param {function} testContent - Test callback receiving `(assert, { testName, options, context })`.
|
|
15
|
+
* `context` is the per-test environment — inherits properties set by `before`/`beforeEach` hooks,
|
|
16
|
+
* and is the same object as `this` in regular-function callbacks. Useful when using arrow functions.
|
|
17
|
+
* @returns {void}
|
|
18
|
+
* @example
|
|
19
|
+
* ```js
|
|
20
|
+
* import { module, test } from "qunitx";
|
|
21
|
+
*
|
|
22
|
+
* module("Math", () => {
|
|
23
|
+
* test("addition", (assert) => {
|
|
24
|
+
* assert.equal(1 + 1, 2);
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* test("async resolves correctly", async (assert) => {
|
|
28
|
+
* const result = await Promise.resolve(42);
|
|
29
|
+
* assert.strictEqual(result, 42);
|
|
30
|
+
* });
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
2
34
|
export default function test(testName: string, testContent: (assert: Assert, meta: {
|
|
3
35
|
testName: string;
|
|
4
36
|
options: unknown;
|
|
37
|
+
context: Record<string, unknown>;
|
|
5
38
|
}) => void | Promise<void>): void;
|
|
39
|
+
/** Defines an individual test with optional Node test runner options forwarded to `it()`. */
|
|
6
40
|
declare function test(testName: string, runtimeOptions: object, testContent: (assert: Assert, meta: {
|
|
7
41
|
testName: string;
|
|
8
42
|
options: unknown;
|
|
43
|
+
context: Record<string, unknown>;
|
|
9
44
|
}) => void | Promise<void>): void;
|
|
10
45
|
declare namespace test {
|
|
11
46
|
var skip: (testName: string, _testContent?: unknown) => void;
|
|
47
|
+
var todo: (testName: string, testContent?: (assert: Assert, meta: {
|
|
48
|
+
testName: string;
|
|
49
|
+
options: unknown;
|
|
50
|
+
}) => void | Promise<void>) => void;
|
|
12
51
|
}
|
|
13
52
|
export default test;
|
package/dist/node/test.js
CHANGED
|
@@ -7,28 +7,30 @@ function test(testName, runtimeOptions, testContent) {
|
|
|
7
7
|
throw new Error(`Test '${testName}' called outside of module context.`);
|
|
8
8
|
}
|
|
9
9
|
const targetRuntimeOptions = testContent ? runtimeOptions : {};
|
|
10
|
-
const { skip } = targetRuntimeOptions;
|
|
10
|
+
const { skip, todo } = targetRuntimeOptions;
|
|
11
11
|
if (skip) {
|
|
12
12
|
it(testName, { skip }, async function() {
|
|
13
13
|
});
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
|
-
const targetTestContent = testContent
|
|
16
|
+
const targetTestContent = testContent ?? runtimeOptions;
|
|
17
17
|
const context = new TestContext(testName, moduleContext);
|
|
18
18
|
const userContext = Object.create(moduleContext.userContext);
|
|
19
19
|
context.userContext = userContext;
|
|
20
|
+
if (todo) moduleContext.tests.pop();
|
|
20
21
|
it(testName, { ...targetRuntimeOptions }, async function() {
|
|
22
|
+
const hookMeta = { context: userContext };
|
|
21
23
|
for (const module of context.module.moduleChain) {
|
|
22
24
|
for (const hook of module.beforeEachHooks) {
|
|
23
|
-
await hook.call(userContext, context.assert);
|
|
25
|
+
await hook.call(userContext, context.assert, hookMeta);
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
|
-
const result = await targetTestContent.call(userContext, context.assert, { testName, options: runtimeOptions });
|
|
28
|
+
const result = await targetTestContent.call(userContext, context.assert, { testName, options: runtimeOptions, context: userContext });
|
|
27
29
|
await context.assert.waitForAsyncOps();
|
|
28
30
|
for (let i = context.module.moduleChain.length - 1; i >= 0; i--) {
|
|
29
31
|
const module = context.module.moduleChain[i];
|
|
30
32
|
for (let j = module.afterEachHooks.length - 1; j >= 0; j--) {
|
|
31
|
-
await module.afterEachHooks[j].call(userContext, context.assert);
|
|
33
|
+
await module.afterEachHooks[j].call(userContext, context.assert, hookMeta);
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
return result;
|
|
@@ -38,6 +40,14 @@ test.skip = function skipTest(testName, _testContent) {
|
|
|
38
40
|
it(testName, { skip: true }, async function() {
|
|
39
41
|
});
|
|
40
42
|
};
|
|
43
|
+
test.todo = function todoTest(testName, testContent) {
|
|
44
|
+
if (!testContent) {
|
|
45
|
+
it(testName, { todo: true }, async function() {
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
test(testName, { todo: true }, testContent);
|
|
50
|
+
};
|
|
41
51
|
export {
|
|
42
52
|
test as default
|
|
43
53
|
};
|
|
@@ -7,7 +7,7 @@ export default class ModuleContext {
|
|
|
7
7
|
static get lastModule(): ModuleContext;
|
|
8
8
|
name: string;
|
|
9
9
|
assert: Assert;
|
|
10
|
-
userContext:
|
|
10
|
+
userContext: Record<string, unknown>;
|
|
11
11
|
context: TestContext;
|
|
12
12
|
moduleChain: ModuleContext[];
|
|
13
13
|
beforeEachHooks: HookFn<Assert>[];
|
|
@@ -19,7 +19,7 @@ export default class TestContext {
|
|
|
19
19
|
set expectedAssertionCount(value: number | undefined);
|
|
20
20
|
get totalExecutedAssertions(): number;
|
|
21
21
|
set totalExecutedAssertions(value: number);
|
|
22
|
-
userContext:
|
|
22
|
+
userContext: Record<string, unknown>;
|
|
23
23
|
constructor(name?: string, moduleContext?: ModuleContext);
|
|
24
24
|
finish(): void;
|
|
25
25
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export interface TestState {
|
|
|
36
36
|
asyncOps: Promise<void>[];
|
|
37
37
|
timeout?: number;
|
|
38
38
|
expectedAssertionCount?: number;
|
|
39
|
-
userContext?:
|
|
39
|
+
userContext?: Record<string, unknown>;
|
|
40
40
|
module?: {
|
|
41
41
|
name: string;
|
|
42
42
|
};
|
|
@@ -45,11 +45,14 @@ export interface TestState {
|
|
|
45
45
|
export interface ModuleState {
|
|
46
46
|
context: TestState;
|
|
47
47
|
}
|
|
48
|
-
/** A lifecycle hook callback that receives an {@linkcode Assert} instance. */
|
|
49
|
-
export type HookFn<A = unknown> = (assert: A
|
|
48
|
+
/** A lifecycle hook callback that receives an {@linkcode Assert} instance and a meta object with the shared context. */
|
|
49
|
+
export type HookFn<A = unknown> = (assert: A, meta: {
|
|
50
|
+
context: Record<string, unknown>;
|
|
51
|
+
}) => void | Promise<void>;
|
|
50
52
|
export type TestFn<A = unknown> = (assert: A, meta: {
|
|
51
53
|
testName: string;
|
|
52
54
|
options: unknown;
|
|
55
|
+
context: Record<string, unknown>;
|
|
53
56
|
}) => void | Promise<unknown>;
|
|
54
57
|
/** Lifecycle hooks available inside a `module()` callback. */
|
|
55
58
|
export interface HooksObject<A = unknown> {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qunitx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.5",
|
|
5
5
|
"description": "A universal test framework for testing any js file on node.js, browser or deno with QUnit API",
|
|
6
6
|
"author": "Izel Nakri",
|
|
7
7
|
"license": "MIT",
|
|
@@ -83,11 +83,11 @@
|
|
|
83
83
|
"format:fix": "prettier --write \"test/**/*.ts\" \"*.ts\" \"package.json\"",
|
|
84
84
|
"lint": "deno lint shims/",
|
|
85
85
|
"lint:docs": "deno doc --lint shims/deno/module.ts shims/deno/test.ts",
|
|
86
|
-
"build": "node
|
|
87
|
-
"build:cold": "rm -rf dist && node
|
|
88
|
-
"pretest": "node
|
|
86
|
+
"build": "node build.ts",
|
|
87
|
+
"build:cold": "rm -rf dist && node build.ts",
|
|
88
|
+
"pretest": "node build.ts && node --input-type=module -e \"import{symlinkSync}from'fs';try{symlinkSync('..','node_modules/qunitx','junction')}catch(_){}\"",
|
|
89
89
|
"run:all": "npm run run:node && npm run run:deno",
|
|
90
|
-
"run:node": "node --
|
|
90
|
+
"run:node": "node --test test/helpers/passing-tests.ts && node --test test/helpers/failing-tests.ts",
|
|
91
91
|
"run:deno": "deno test test/helpers/passing-tests.ts && deno test test/helpers/failing-tests.ts",
|
|
92
92
|
"changelog:unreleased": "git-cliff --unreleased --strip all",
|
|
93
93
|
"changelog:preview": "git-cliff",
|
|
@@ -99,8 +99,8 @@
|
|
|
99
99
|
"test:browser": "qunitx test/index.ts --debug",
|
|
100
100
|
"test:deno": "deno test --allow-read --allow-run test/index.ts",
|
|
101
101
|
"test:doctests": "deno test --doc --allow-read shims/deno/module.ts shims/deno/test.ts",
|
|
102
|
-
"test:node": "node --
|
|
103
|
-
"coverage": "deno test --coverage=tmp/coverage --allow-read --allow-env --allow-run test/index.ts && deno coverage --lcov --output=tmp/coverage/lcov.info --include='shims/' tmp/coverage && node
|
|
102
|
+
"test:node": "node --test test/index.ts",
|
|
103
|
+
"coverage": "deno test --coverage=tmp/coverage --allow-read --allow-env --allow-run test/index.ts && deno coverage --lcov --output=tmp/coverage/lcov.info --include='shims/' tmp/coverage && node scripts/check-coverage.ts",
|
|
104
104
|
"coverage:report": "npm run coverage && deno coverage --html --include='shims/' tmp/coverage",
|
|
105
105
|
"bench": "deno task bench",
|
|
106
106
|
"bench:check": "deno task bench:check",
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
111
|
"@types/node": "^22.0.0",
|
|
112
|
+
"playwright-core": "^1.59.1",
|
|
112
113
|
"prettier": "^3.8.1",
|
|
113
114
|
"qunit": "^2.25.0",
|
|
114
115
|
"qunitx-cli": "^0.9.10",
|
package/shims/deno/index.ts
CHANGED
|
@@ -120,8 +120,10 @@ export { default as module } from './module.ts';
|
|
|
120
120
|
* is an {@linkcode Assert} instance.
|
|
121
121
|
*
|
|
122
122
|
* @param {string} testName - Name of the test.
|
|
123
|
-
* @param {object} [runtimeOptions] - Optional
|
|
124
|
-
*
|
|
123
|
+
* @param {object} [runtimeOptions] - Optional options forwarded to `it()`.
|
|
124
|
+
* Use `{ skip: true | string }` to skip the test, `{ todo: true | string }` to mark it as todo
|
|
125
|
+
* (both map to Deno's `{ ignore: true }`). Other Deno BDD options like
|
|
126
|
+
* `{ concurrency: false }` or `{ sanitizeExit: false }` are forwarded as-is.
|
|
125
127
|
* @param {function} testContent - Test callback receiving `(assert, { testName, options })`.
|
|
126
128
|
* @example
|
|
127
129
|
* ```js
|
|
@@ -159,6 +161,7 @@ export { default as test } from './test.ts';
|
|
|
159
161
|
* ```
|
|
160
162
|
*/
|
|
161
163
|
export const skip = Test.skip;
|
|
164
|
+
export const todo = Test.todo;
|
|
162
165
|
|
|
163
166
|
/**
|
|
164
167
|
* The default export provides the full QUnitX API as a single object.
|
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
|
});
|