qunitx 1.2.6 → 1.2.8
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 +104 -20
- package/dist/.build-hash +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser/index.d.ts +20 -20
- package/dist/browser/index.js +52 -52
- package/dist/deno/index.d.ts +20 -19
- package/dist/deno/index.js +172 -186
- package/dist/deno/module.d.ts +2 -2
- package/dist/deno/module.js +11 -12
- package/dist/deno/test.d.ts +2 -2
- package/dist/deno/test.js +24 -25
- package/dist/node/index.d.ts +3 -2
- package/dist/node/index.js +1 -1
- package/dist/node/module.js +11 -12
- package/dist/node/test.js +23 -24
- package/dist/shared/assert.d.ts +2 -2
- package/dist/shared/assert.js +89 -55
- package/dist/shared/index.d.ts +1 -13
- package/dist/shared/index.js +11 -13
- package/dist/shared/module-context.d.ts +3 -3
- package/dist/shared/module-context.js +4 -4
- package/dist/shared/test-context.d.ts +10 -18
- package/dist/shared/test-context.js +26 -74
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
- package/shims/deno/index.ts +22 -21
- package/shims/deno/module.ts +15 -15
- package/shims/deno/test.ts +30 -29
- package/shims/shared/assert.ts +92 -56
- package/shims/shared/index.ts +14 -27
- package/shims/shared/module-context.ts +5 -5
- package/shims/shared/test-context.ts +27 -84
- package/shims/types.ts +1 -1
package/dist/shared/index.js
CHANGED
|
@@ -27,11 +27,8 @@ function objectType(obj) {
|
|
|
27
27
|
return typeof obj;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
function is(type, obj) {
|
|
31
|
-
return objectType(obj) === type;
|
|
32
|
-
}
|
|
33
30
|
function objectValues(obj, allowArray = true) {
|
|
34
|
-
const vals = allowArray &&
|
|
31
|
+
const vals = allowArray && objectType(obj) === "array" ? [] : {};
|
|
35
32
|
for (const key in obj) {
|
|
36
33
|
if (hasOwn.call(obj, key)) {
|
|
37
34
|
const val = obj[key];
|
|
@@ -63,13 +60,15 @@ function validateExpectedExceptionArgs(expected, message, assertionMethod) {
|
|
|
63
60
|
expected = void 0;
|
|
64
61
|
return [expected, message];
|
|
65
62
|
} else {
|
|
66
|
-
throw new Error(
|
|
63
|
+
throw new Error(
|
|
64
|
+
`assert.${assertionMethod} does not accept a string value for the expected argument.
|
|
65
|
+
Use a non-string object value (e.g. RegExp or validator function) instead if necessary.`
|
|
66
|
+
);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
const valid = !expected ||
|
|
70
|
-
expectedType === "regexp" || expectedType === "function" || expectedType === "object";
|
|
69
|
+
const valid = !expected || expectedType === "regexp" || expectedType === "function" || expectedType === "object";
|
|
71
70
|
if (!valid) {
|
|
72
|
-
throw new Error(
|
|
71
|
+
throw new Error(`Invalid expected value type (${expectedType}) provided to assert.${assertionMethod}.`);
|
|
73
72
|
}
|
|
74
73
|
return [expected, message];
|
|
75
74
|
}
|
|
@@ -99,14 +98,13 @@ function validateException(actual, expected, message) {
|
|
|
99
98
|
function errorString(error) {
|
|
100
99
|
const resultErrorString = String(error);
|
|
101
100
|
if (resultErrorString.slice(0, 7) === "[object") {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return
|
|
101
|
+
const name = error.name || "Error";
|
|
102
|
+
const msg = error.message;
|
|
103
|
+
return msg ? `${name}: ${msg}` : name;
|
|
105
104
|
}
|
|
105
|
+
return resultErrorString;
|
|
106
106
|
}
|
|
107
|
-
var shared_default = { objectValues, objectValuesSubset, validateExpectedExceptionArgs, validateException };
|
|
108
107
|
export {
|
|
109
|
-
shared_default as default,
|
|
110
108
|
objectType,
|
|
111
109
|
objectValues,
|
|
112
110
|
objectValuesSubset,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type Assert from './assert.d.ts';
|
|
2
1
|
import type { HookFn } from '../types.d.ts';
|
|
2
|
+
import type Assert from './assert.d.ts';
|
|
3
3
|
import TestContext from './test-context.d.ts';
|
|
4
4
|
export default class ModuleContext {
|
|
5
5
|
static Assert: typeof Assert;
|
|
6
6
|
static currentModuleChain: ModuleContext[];
|
|
7
|
-
static get lastModule(): ModuleContext;
|
|
7
|
+
static get lastModule(): ModuleContext | undefined;
|
|
8
8
|
name: string;
|
|
9
9
|
assert: Assert;
|
|
10
10
|
userContext: Record<string, unknown>;
|
|
11
|
-
|
|
11
|
+
testContext: TestContext;
|
|
12
12
|
moduleChain: ModuleContext[];
|
|
13
13
|
beforeEachHooks: HookFn<Assert>[];
|
|
14
14
|
afterEachHooks: HookFn<Assert>[];
|
|
@@ -3,21 +3,21 @@ class ModuleContext {
|
|
|
3
3
|
static Assert;
|
|
4
4
|
static currentModuleChain = [];
|
|
5
5
|
static get lastModule() {
|
|
6
|
-
return this.currentModuleChain
|
|
6
|
+
return this.currentModuleChain.at(-1);
|
|
7
7
|
}
|
|
8
8
|
name;
|
|
9
9
|
assert;
|
|
10
10
|
userContext;
|
|
11
11
|
// Internal fallback assert for modules with no direct tests
|
|
12
|
-
|
|
12
|
+
testContext = new TestContext();
|
|
13
13
|
moduleChain = [];
|
|
14
14
|
beforeEachHooks = [];
|
|
15
15
|
afterEachHooks = [];
|
|
16
16
|
tests = [];
|
|
17
17
|
constructor(name) {
|
|
18
|
-
const parentModule = ModuleContext.currentModuleChain
|
|
18
|
+
const parentModule = ModuleContext.currentModuleChain.at(-1);
|
|
19
19
|
ModuleContext.currentModuleChain.push(this);
|
|
20
|
-
this.moduleChain = ModuleContext.currentModuleChain
|
|
20
|
+
this.moduleChain = [...ModuleContext.currentModuleChain];
|
|
21
21
|
this.name = parentModule ? `${parentModule.name} > ${name}` : name;
|
|
22
22
|
this.assert = new ModuleContext.Assert(this);
|
|
23
23
|
this.userContext = parentModule ? Object.create(parentModule.userContext) : /* @__PURE__ */ Object.create(null);
|
|
@@ -3,26 +3,18 @@ import type ModuleContext from './module-context.d.ts';
|
|
|
3
3
|
export default class TestContext {
|
|
4
4
|
#private;
|
|
5
5
|
static Assert: typeof Assert;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
set timeout(value: number | undefined);
|
|
6
|
+
name: string | undefined;
|
|
7
|
+
module: ModuleContext | undefined;
|
|
8
|
+
asyncOps: Promise<void>[];
|
|
9
|
+
assert: Assert | undefined;
|
|
10
|
+
timeout: number | undefined;
|
|
11
|
+
steps: string[];
|
|
12
|
+
expectedAssertionCount: number | undefined;
|
|
13
|
+
totalExecutedAssertions: number;
|
|
14
|
+
userContext: Record<string, unknown>;
|
|
16
15
|
rejectTimeout: ((err: Error) => void) | undefined;
|
|
16
|
+
constructor(name?: string, moduleContext?: ModuleContext);
|
|
17
17
|
setTimeoutDuration(ms: number): void;
|
|
18
18
|
clearTimeoutHandle(): void;
|
|
19
|
-
get steps(): string[];
|
|
20
|
-
set steps(value: string[]);
|
|
21
|
-
get expectedAssertionCount(): number | undefined;
|
|
22
|
-
set expectedAssertionCount(value: number | undefined);
|
|
23
|
-
get totalExecutedAssertions(): number;
|
|
24
|
-
set totalExecutedAssertions(value: number);
|
|
25
|
-
userContext: Record<string, unknown>;
|
|
26
|
-
constructor(name?: string, moduleContext?: ModuleContext);
|
|
27
19
|
finish(): void;
|
|
28
20
|
}
|
|
@@ -1,43 +1,25 @@
|
|
|
1
1
|
class TestContext {
|
|
2
2
|
static Assert;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return this.#module;
|
|
13
|
-
}
|
|
14
|
-
set module(value) {
|
|
15
|
-
this.#module = value;
|
|
16
|
-
}
|
|
17
|
-
#asyncOps = [];
|
|
18
|
-
get asyncOps() {
|
|
19
|
-
return this.#asyncOps;
|
|
20
|
-
}
|
|
21
|
-
set asyncOps(value) {
|
|
22
|
-
this.#asyncOps = value;
|
|
23
|
-
}
|
|
24
|
-
#assert;
|
|
25
|
-
get assert() {
|
|
26
|
-
return this.#assert;
|
|
27
|
-
}
|
|
28
|
-
set assert(value) {
|
|
29
|
-
this.#assert = value;
|
|
30
|
-
}
|
|
31
|
-
#timeout;
|
|
32
|
-
get timeout() {
|
|
33
|
-
return this.#timeout;
|
|
34
|
-
}
|
|
35
|
-
set timeout(value) {
|
|
36
|
-
this.#timeout = value;
|
|
37
|
-
}
|
|
3
|
+
name;
|
|
4
|
+
module;
|
|
5
|
+
asyncOps = [];
|
|
6
|
+
assert;
|
|
7
|
+
timeout;
|
|
8
|
+
steps = [];
|
|
9
|
+
expectedAssertionCount;
|
|
10
|
+
totalExecutedAssertions = 0;
|
|
11
|
+
userContext = {};
|
|
38
12
|
rejectTimeout;
|
|
39
13
|
#timeoutHandle;
|
|
40
14
|
#timedOut = false;
|
|
15
|
+
constructor(name, moduleContext) {
|
|
16
|
+
if (moduleContext) {
|
|
17
|
+
this.name = `${moduleContext.name} | ${name}`;
|
|
18
|
+
this.module = moduleContext;
|
|
19
|
+
this.module.tests.push(this);
|
|
20
|
+
this.assert = new TestContext.Assert(moduleContext, this);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
41
23
|
setTimeoutDuration(ms) {
|
|
42
24
|
if (this.#timeoutHandle !== void 0) {
|
|
43
25
|
clearTimeout(this.#timeoutHandle);
|
|
@@ -55,59 +37,29 @@ class TestContext {
|
|
|
55
37
|
this.#timeoutHandle = void 0;
|
|
56
38
|
}
|
|
57
39
|
}
|
|
58
|
-
#steps = [];
|
|
59
|
-
get steps() {
|
|
60
|
-
return this.#steps;
|
|
61
|
-
}
|
|
62
|
-
set steps(value) {
|
|
63
|
-
this.#steps = value;
|
|
64
|
-
}
|
|
65
|
-
#expectedAssertionCount;
|
|
66
|
-
get expectedAssertionCount() {
|
|
67
|
-
return this.#expectedAssertionCount;
|
|
68
|
-
}
|
|
69
|
-
set expectedAssertionCount(value) {
|
|
70
|
-
this.#expectedAssertionCount = value;
|
|
71
|
-
}
|
|
72
|
-
#totalExecutedAssertions = 0;
|
|
73
|
-
get totalExecutedAssertions() {
|
|
74
|
-
return this.#totalExecutedAssertions;
|
|
75
|
-
}
|
|
76
|
-
set totalExecutedAssertions(value) {
|
|
77
|
-
this.#totalExecutedAssertions = value;
|
|
78
|
-
}
|
|
79
|
-
userContext = {};
|
|
80
|
-
constructor(name, moduleContext) {
|
|
81
|
-
if (moduleContext) {
|
|
82
|
-
this.name = `${moduleContext.name} | ${name}`;
|
|
83
|
-
this.module = moduleContext;
|
|
84
|
-
this.module.tests.push(this);
|
|
85
|
-
this.assert = new TestContext.Assert(moduleContext, this);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
40
|
finish() {
|
|
89
41
|
if (this.#timedOut) return;
|
|
90
|
-
if (this.
|
|
91
|
-
this.assert.pushResult({
|
|
92
|
-
result: false,
|
|
93
|
-
actual: this.totalExecutedAssertions,
|
|
94
|
-
expected: "> 0",
|
|
95
|
-
message: `Expected at least one assertion to be run for test: ${this.name}`
|
|
96
|
-
});
|
|
97
|
-
} else if (this.steps.length > 0) {
|
|
42
|
+
if (this.steps.length > 0) {
|
|
98
43
|
this.assert.pushResult({
|
|
99
44
|
result: false,
|
|
100
45
|
actual: this.steps,
|
|
101
46
|
expected: [],
|
|
102
47
|
message: `Expected assert.verifySteps() to be called before end of test after using assert.step(). Unverified steps: ${this.steps.join(", ")}`
|
|
103
48
|
});
|
|
104
|
-
} else if (this.expectedAssertionCount && this.expectedAssertionCount !== this.totalExecutedAssertions) {
|
|
49
|
+
} else if (this.expectedAssertionCount !== void 0 && this.expectedAssertionCount !== this.totalExecutedAssertions) {
|
|
105
50
|
this.assert.pushResult({
|
|
106
51
|
result: false,
|
|
107
52
|
actual: this.totalExecutedAssertions,
|
|
108
53
|
expected: this.expectedAssertionCount,
|
|
109
54
|
message: `Expected ${this.expectedAssertionCount} assertions, but ${this.totalExecutedAssertions} were run for test: ${this.name}`
|
|
110
55
|
});
|
|
56
|
+
} else if (this.expectedAssertionCount === void 0 && this.totalExecutedAssertions === 0) {
|
|
57
|
+
this.assert.pushResult({
|
|
58
|
+
result: false,
|
|
59
|
+
actual: this.totalExecutedAssertions,
|
|
60
|
+
expected: "> 0",
|
|
61
|
+
message: `Expected at least one assertion to be run for test: ${this.name}`
|
|
62
|
+
});
|
|
111
63
|
}
|
|
112
64
|
}
|
|
113
65
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export interface TestState {
|
|
|
44
44
|
}
|
|
45
45
|
/** Minimal module shape that Assert needs to resolve a fallback test context. */
|
|
46
46
|
export interface ModuleState {
|
|
47
|
-
|
|
47
|
+
testContext: TestState;
|
|
48
48
|
}
|
|
49
49
|
/** A lifecycle hook callback that receives an {@linkcode Assert} instance and a meta object with the shared context. */
|
|
50
50
|
export type HookFn<A = unknown> = (assert: A, meta: {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qunitx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.
|
|
5
|
-
"description": "
|
|
4
|
+
"version": "1.2.8",
|
|
5
|
+
"description": "Universal test library — run the same test file in Node.js, Deno, and the browser with QUnit's battle-tested assertion API",
|
|
6
6
|
"author": "Izel Nakri",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"keywords": [
|
package/shims/deno/index.ts
CHANGED
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
*
|
|
25
25
|
* @module
|
|
26
26
|
*/
|
|
27
|
-
import { AssertionError as DenoAssertionError } from "jsr:@std/assert";
|
|
28
|
-
import type { AssertionErrorOptions } from "../types.ts";
|
|
29
27
|
import '../../vendor/qunit.js';
|
|
28
|
+
import { AssertionError as DenoAssertionError } from 'jsr:@std/assert';
|
|
30
29
|
import Assert from '../shared/assert.ts';
|
|
31
30
|
import ModuleContext from '../shared/module-context.ts';
|
|
32
31
|
import TestContext from '../shared/test-context.ts';
|
|
32
|
+
import type { AssertionErrorOptions } from '../types.ts';
|
|
33
33
|
import Module from './module.ts';
|
|
34
34
|
import Test from './test.ts';
|
|
35
35
|
|
|
@@ -54,6 +54,7 @@ import Test from './test.ts';
|
|
|
54
54
|
export class AssertionError extends DenoAssertionError {
|
|
55
55
|
constructor(object: AssertionErrorOptions) {
|
|
56
56
|
super(object.message ?? 'Assertion failed');
|
|
57
|
+
if (object.stackStartFn) Error.captureStackTrace(this, object.stackStartFn);
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
|
|
@@ -111,6 +112,25 @@ export { Assert };
|
|
|
111
112
|
*/
|
|
112
113
|
export { default as module } from './module.ts';
|
|
113
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Registers a skipped test. Equivalent to `test.skip`. The test body is never
|
|
117
|
+
* executed and the test is reported as ignored by Deno's runner.
|
|
118
|
+
*
|
|
119
|
+
* @param {string} testName - Name of the test to skip.
|
|
120
|
+
* @param {function} [_testContent] - Optional body (ignored — the test will not run).
|
|
121
|
+
* @example
|
|
122
|
+
* ```js
|
|
123
|
+
* import { module, skip } from "qunitx";
|
|
124
|
+
*
|
|
125
|
+
* module("Math", () => {
|
|
126
|
+
* skip("addition is not yet implemented", (assert) => {
|
|
127
|
+
* assert.equal(1 + 1, 2);
|
|
128
|
+
* });
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export const skip = Test.skip;
|
|
133
|
+
|
|
114
134
|
/**
|
|
115
135
|
* Defines an individual test. Wraps Deno's `it()` and handles the full QUnit
|
|
116
136
|
* lifecycle: `beforeEach`/`afterEach` hooks, async assertion waiting, and step
|
|
@@ -142,25 +162,6 @@ export { default as module } from './module.ts';
|
|
|
142
162
|
* ```
|
|
143
163
|
*/
|
|
144
164
|
export { default as test } from './test.ts';
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Registers a skipped test. Equivalent to `test.skip`. The test body is never
|
|
148
|
-
* executed and the test is reported as ignored by Deno's runner.
|
|
149
|
-
*
|
|
150
|
-
* @param {string} testName - Name of the test to skip.
|
|
151
|
-
* @param {function} [_testContent] - Optional body (ignored — the test will not run).
|
|
152
|
-
* @example
|
|
153
|
-
* ```js
|
|
154
|
-
* import { module, skip } from "qunitx";
|
|
155
|
-
*
|
|
156
|
-
* module("Math", () => {
|
|
157
|
-
* skip("addition is not yet implemented", (assert) => {
|
|
158
|
-
* assert.equal(1 + 1, 2);
|
|
159
|
-
* });
|
|
160
|
-
* });
|
|
161
|
-
* ```
|
|
162
|
-
*/
|
|
163
|
-
export const skip = Test.skip;
|
|
164
165
|
export const todo = Test.todo;
|
|
165
166
|
|
|
166
167
|
/**
|
package/shims/deno/module.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { afterAll, beforeAll, describe } from 'jsr:@std/testing/bdd';
|
|
2
2
|
import type Assert from '../shared/assert.ts';
|
|
3
|
-
import type { HookFn, HooksObject } from '../types.ts';
|
|
4
3
|
import ModuleContext from '../shared/module-context.ts';
|
|
5
|
-
|
|
6
|
-
export type { HookFn, HooksObject, PushResultInfo } from '../types.ts';
|
|
4
|
+
import type { HookFn, HooksObject } from '../types.ts';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Defines a test module (suite) for Deno's BDD test runner.
|
|
@@ -53,14 +51,14 @@ export default function module(
|
|
|
53
51
|
return;
|
|
54
52
|
}
|
|
55
53
|
|
|
56
|
-
const targetModuleContent = (moduleContent
|
|
54
|
+
const targetModuleContent = (moduleContent ?? runtimeOptions) as (hooks: HooksObject<Assert>, meta: { moduleName: string; options: unknown }) => void;
|
|
57
55
|
const moduleContext = new ModuleContext(moduleName);
|
|
58
56
|
|
|
59
57
|
describe(moduleName, { ...targetRuntimeOptions }, function () {
|
|
60
58
|
const beforeHooks: HookFn<Assert>[] = [];
|
|
61
59
|
const afterHooks: HookFn<Assert>[] = [];
|
|
62
60
|
|
|
63
|
-
beforeAll(async
|
|
61
|
+
beforeAll(async () => {
|
|
64
62
|
// before() assertions are attributed to the first direct test only (matching QUnit's model).
|
|
65
63
|
// Tests inherit parent context via prototype chain, so no Object.assign needed.
|
|
66
64
|
const firstTest = moduleContext.tests[0];
|
|
@@ -72,19 +70,18 @@ export default function module(
|
|
|
72
70
|
});
|
|
73
71
|
|
|
74
72
|
afterAll(async () => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
73
|
+
const allAsyncOps = moduleContext.tests.flatMap((t) => t.asyncOps);
|
|
74
|
+
if (allAsyncOps.length > 0) await Promise.all(allAsyncOps);
|
|
78
75
|
|
|
79
|
-
const lastTest = moduleContext.tests
|
|
76
|
+
const lastTest = moduleContext.tests.at(-1);
|
|
80
77
|
if (lastTest) {
|
|
81
|
-
for (
|
|
82
|
-
await
|
|
78
|
+
for (const hook of afterHooks.toReversed()) {
|
|
79
|
+
await hook.call(lastTest.userContext, lastTest.assert!, { context: lastTest.userContext });
|
|
83
80
|
}
|
|
84
81
|
}
|
|
85
82
|
|
|
86
|
-
for (
|
|
87
|
-
|
|
83
|
+
for (const testCtx of moduleContext.tests) {
|
|
84
|
+
testCtx.finish();
|
|
88
85
|
}
|
|
89
86
|
});
|
|
90
87
|
|
|
@@ -101,7 +98,7 @@ export default function module(
|
|
|
101
98
|
after(afterFn) {
|
|
102
99
|
afterHooks.push(afterFn);
|
|
103
100
|
}
|
|
104
|
-
}, { moduleName, options:
|
|
101
|
+
}, { moduleName, options: targetRuntimeOptions, context: moduleContext.userContext });
|
|
105
102
|
|
|
106
103
|
ModuleContext.currentModuleChain.pop();
|
|
107
104
|
});
|
|
@@ -149,3 +146,6 @@ module.skip = function skipModule(moduleName: string, _moduleContent?: unknown):
|
|
|
149
146
|
module.todo = function todoModule(moduleName: string, _moduleContent?: unknown): void {
|
|
150
147
|
describe(moduleName, { ignore: true }, function () {});
|
|
151
148
|
};
|
|
149
|
+
|
|
150
|
+
export type { Assert };
|
|
151
|
+
export type { HookFn, HooksObject, PushResultInfo } from '../types.ts';
|
package/shims/deno/test.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { it } from
|
|
1
|
+
import { it } from 'jsr:@std/testing/bdd';
|
|
2
2
|
import type Assert from '../shared/assert.ts';
|
|
3
|
-
import TestContext from '../shared/test-context.ts';
|
|
4
3
|
import ModuleContext from '../shared/module-context.ts';
|
|
5
|
-
|
|
6
|
-
export type { PushResultInfo } from '../types.ts';
|
|
4
|
+
import TestContext from '../shared/test-context.ts';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Defines an individual test within a module for Deno's BDD test runner.
|
|
@@ -59,7 +57,7 @@ export default function test(
|
|
|
59
57
|
return;
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
const targetTestContent = (testContent
|
|
60
|
+
const targetTestContent = (testContent ?? runtimeOptions) as (assert: Assert, meta: { testName: string; options: unknown }) => void | Promise<void>;
|
|
63
61
|
const context = new TestContext(testName, moduleContext);
|
|
64
62
|
|
|
65
63
|
// Each test gets a fresh plain object inheriting from the module's user context.
|
|
@@ -69,38 +67,38 @@ export default function test(
|
|
|
69
67
|
context.userContext = userContext;
|
|
70
68
|
|
|
71
69
|
it(testName, { ...targetRuntimeOptions }, function () {
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
const { promise, resolve, reject } = Promise.withResolvers<void>();
|
|
71
|
+
context.rejectTimeout = reject;
|
|
74
72
|
|
|
75
|
-
|
|
76
|
-
const hookMeta = { context: userContext };
|
|
73
|
+
const hookMeta = { context: userContext };
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
(async () => {
|
|
76
|
+
try {
|
|
77
|
+
for (const mod of context.module!.moduleChain) {
|
|
78
|
+
for (const hook of mod.beforeEachHooks) {
|
|
79
|
+
await hook.call(userContext, context.assert!, hookMeta);
|
|
83
80
|
}
|
|
81
|
+
}
|
|
84
82
|
|
|
85
|
-
|
|
83
|
+
await targetTestContent.call(userContext, context.assert!, { testName, options: targetRuntimeOptions, context: userContext });
|
|
86
84
|
|
|
87
|
-
|
|
85
|
+
await context.assert!.waitForAsyncOps();
|
|
88
86
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
await module.afterEachHooks[j]!.call(userContext, context.assert!, hookMeta);
|
|
93
|
-
}
|
|
87
|
+
for (const mod of context.module!.moduleChain.toReversed()) {
|
|
88
|
+
for (const hook of mod.afterEachHooks.toReversed()) {
|
|
89
|
+
await hook.call(userContext, context.assert!, hookMeta);
|
|
94
90
|
}
|
|
95
|
-
|
|
96
|
-
resolve(result);
|
|
97
|
-
} catch (err) {
|
|
98
|
-
reject(err);
|
|
99
|
-
} finally {
|
|
100
|
-
context.clearTimeoutHandle();
|
|
101
91
|
}
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
|
|
93
|
+
resolve();
|
|
94
|
+
} catch (err) {
|
|
95
|
+
reject(err);
|
|
96
|
+
} finally {
|
|
97
|
+
context.clearTimeoutHandle();
|
|
98
|
+
}
|
|
99
|
+
})();
|
|
100
|
+
|
|
101
|
+
return promise;
|
|
104
102
|
});
|
|
105
103
|
}
|
|
106
104
|
|
|
@@ -146,3 +144,6 @@ test.skip = function skipTest(testName: string, _testContent?: unknown): void {
|
|
|
146
144
|
test.todo = function todoTest(testName: string, _testContent?: unknown): void {
|
|
147
145
|
it(testName, { ignore: true }, async function () {});
|
|
148
146
|
};
|
|
147
|
+
|
|
148
|
+
export type { Assert };
|
|
149
|
+
export type { PushResultInfo } from '../types.ts';
|