@unrift/core 0.3.0 → 0.4.0
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/bin/unrift.mjs +2 -1
- package/dist/esm/cli.js +5 -0
- package/dist/esm/expect.d.ts +12 -0
- package/dist/esm/expect.d.ts.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/matchers.d.ts.map +1 -1
- package/dist/esm/matchers.js +161 -1
- package/dist/esm/mock/auto.d.ts +27 -0
- package/dist/esm/mock/auto.d.ts.map +1 -0
- package/dist/esm/mock/auto.js +108 -0
- package/dist/esm/mock/fetch.d.ts +47 -0
- package/dist/esm/mock/fetch.d.ts.map +1 -0
- package/dist/esm/mock/fetch.js +149 -0
- package/dist/esm/mock/fs.d.ts +54 -0
- package/dist/esm/mock/fs.d.ts.map +1 -0
- package/dist/esm/mock/fs.js +125 -0
- package/dist/esm/mock/index.d.ts +70 -0
- package/dist/esm/mock/index.d.ts.map +1 -0
- package/dist/esm/mock/index.js +70 -0
- package/dist/esm/mock/module-loader.d.ts +66 -0
- package/dist/esm/mock/module-loader.d.ts.map +1 -0
- package/dist/esm/mock/module-loader.js +123 -0
- package/dist/esm/mock/module.d.ts +99 -0
- package/dist/esm/mock/module.d.ts.map +1 -0
- package/dist/esm/mock/module.js +198 -0
- package/dist/esm/mock/register-loader.d.ts +17 -0
- package/dist/esm/mock/register-loader.d.ts.map +1 -0
- package/dist/esm/mock/register-loader.js +45 -0
- package/dist/esm/mock/spy.d.ts +73 -0
- package/dist/esm/mock/spy.d.ts.map +1 -0
- package/dist/esm/mock/spy.js +307 -0
- package/dist/esm/mock/stub.d.ts +26 -0
- package/dist/esm/mock/stub.d.ts.map +1 -0
- package/dist/esm/mock/stub.js +82 -0
- package/dist/esm/mock/timers.d.ts +51 -0
- package/dist/esm/mock/timers.d.ts.map +1 -0
- package/dist/esm/mock/timers.js +581 -0
- package/dist/esm/runner.d.ts.map +1 -1
- package/dist/esm/runner.js +13 -8
- package/dist/esm/test.d.ts.map +1 -1
- package/dist/esm/test.js +12 -5
- package/dist/esm/utils/compareEngine.js +3 -3
- package/dist/esm/utils/discoverTestFiles.js +1 -1
- package/dist/esm/utils/helpers.d.ts +10 -0
- package/dist/esm/utils/helpers.d.ts.map +1 -1
- package/dist/esm/utils/helpers.js +13 -0
- package/dist/esm/utils/toThrow.d.ts.map +1 -1
- package/dist/esm/utils/toThrow.js +2 -1
- package/package.json +4 -3
package/dist/esm/test.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { TaskMode, TaskStatus } from "./types.js";
|
|
2
2
|
import { toError } from "./utils/toError.js";
|
|
3
|
+
/**
|
|
4
|
+
* Captured at module load so the runner's own timing measurements are
|
|
5
|
+
* immune to user mocks (e.g. mock.useFakeTimers patches performance.now).
|
|
6
|
+
*/
|
|
7
|
+
const realPerformanceNow = performance.now.bind(performance);
|
|
3
8
|
export class Test {
|
|
4
9
|
description;
|
|
5
10
|
durationMs = 0;
|
|
@@ -26,7 +31,7 @@ export class Test {
|
|
|
26
31
|
this.durationMs = 0;
|
|
27
32
|
return;
|
|
28
33
|
}
|
|
29
|
-
const start =
|
|
34
|
+
const start = realPerformanceNow();
|
|
30
35
|
this.status = TaskStatus.Running;
|
|
31
36
|
const exec = Promise.resolve().then(() => this.fn());
|
|
32
37
|
try {
|
|
@@ -37,9 +42,11 @@ export class Test {
|
|
|
37
42
|
reject(new Error(`Test "${this.description}" timed out after ${timeoutMs} ms`));
|
|
38
43
|
}, timeoutMs);
|
|
39
44
|
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
/**
|
|
46
|
+
* NOTE: Promise.race does not cancel the losing promise. A timed-out test
|
|
47
|
+
* function continues running in the background. True cancellation would
|
|
48
|
+
* require AbortController integration, which is a larger future change.
|
|
49
|
+
*/
|
|
43
50
|
try {
|
|
44
51
|
await Promise.race([exec, timeoutFn]);
|
|
45
52
|
}
|
|
@@ -58,7 +65,7 @@ export class Test {
|
|
|
58
65
|
this.status = TaskStatus.Fail;
|
|
59
66
|
}
|
|
60
67
|
finally {
|
|
61
|
-
this.durationMs =
|
|
68
|
+
this.durationMs = realPerformanceNow() - start;
|
|
62
69
|
}
|
|
63
70
|
}
|
|
64
71
|
}
|
|
@@ -142,7 +142,7 @@ export function compareInternal(left, right, options, leftToRightSeen, rightToLe
|
|
|
142
142
|
const rightSet = currentRight;
|
|
143
143
|
if (leftSet.size !== rightSet.size)
|
|
144
144
|
return false;
|
|
145
|
-
// Fast path: primitive-only sets can use has() directly
|
|
145
|
+
// Fast path: primitive-only sets can use has() directly - O(n) vs O(n²)
|
|
146
146
|
let allPrimitive = true;
|
|
147
147
|
for (const v of leftSet) {
|
|
148
148
|
if (!isPrimitive(v)) {
|
|
@@ -179,7 +179,7 @@ export function compareInternal(left, right, options, leftToRightSeen, rightToLe
|
|
|
179
179
|
const rightMap = currentRight;
|
|
180
180
|
if (leftMap.size !== rightMap.size)
|
|
181
181
|
return false;
|
|
182
|
-
// Fast path: primitive-only keys can use get() directly
|
|
182
|
+
// Fast path: primitive-only keys can use get() directly - O(n) vs O(n²)
|
|
183
183
|
let allKeysPrimitive = true;
|
|
184
184
|
for (const k of leftMap.keys()) {
|
|
185
185
|
if (!isPrimitive(k)) {
|
|
@@ -230,7 +230,7 @@ export function compareInternal(left, right, options, leftToRightSeen, rightToLe
|
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
else {
|
|
233
|
-
// Prototype-insensitive (looseEqual)
|
|
233
|
+
// Prototype-insensitive (looseEqual) - union-of-keys, missing ≈ undefined
|
|
234
234
|
const leftKeys = Object.keys(currentLeft);
|
|
235
235
|
const rightKeys = Object.keys(currentRight);
|
|
236
236
|
const allKeys = new Set([...leftKeys, ...rightKeys]);
|
|
@@ -14,6 +14,16 @@ export declare function isGlobPattern(pattern: string): boolean;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function globToRegex(glob: string): RegExp;
|
|
16
16
|
export declare function safeRegExp(source: string): RegExp;
|
|
17
|
+
/**
|
|
18
|
+
* Stateless RegExp match for user-supplied patterns.
|
|
19
|
+
*
|
|
20
|
+
* `RegExp.prototype.test` advances `lastIndex` for `/g` and `/y` regexes, so
|
|
21
|
+
* reusing the same regex object across calls (a matcher tested against several
|
|
22
|
+
* requests, or the same assertion run twice) can start mid-string and miss.
|
|
23
|
+
* Resetting `lastIndex` first makes every test independent - "does this pattern
|
|
24
|
+
* match the string" regardless of prior calls.
|
|
25
|
+
*/
|
|
26
|
+
export declare function regexTest(re: RegExp, value: string): boolean;
|
|
17
27
|
/**
|
|
18
28
|
* SameValueZero-ish semantics:
|
|
19
29
|
* - NaN equals NaN
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,KAAK,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhF,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,SAAS,GACT,WAAW,GACX,UAAU,GACV,WAAW,GACX,UAAU,GACV,YAAY,GACZ,YAAY,GACZ,aAAa,GACb,cAAc,CAAC;AAEnB,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAY9D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE5D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAyDhD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CASzD"}
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,KAAK,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhF,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,SAAS,GACT,WAAW,GACX,UAAU,GACV,WAAW,GACX,UAAU,GACV,YAAY,GACZ,YAAY,GACZ,aAAa,GACb,cAAc,CAAC;AAEnB,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAY9D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE5D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAyDhD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG5D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CASzD"}
|
|
@@ -98,6 +98,19 @@ export function safeRegExp(source) {
|
|
|
98
98
|
throw new Error(`Invalid regex "${source}": ${msg}`);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Stateless RegExp match for user-supplied patterns.
|
|
103
|
+
*
|
|
104
|
+
* `RegExp.prototype.test` advances `lastIndex` for `/g` and `/y` regexes, so
|
|
105
|
+
* reusing the same regex object across calls (a matcher tested against several
|
|
106
|
+
* requests, or the same assertion run twice) can start mid-string and miss.
|
|
107
|
+
* Resetting `lastIndex` first makes every test independent - "does this pattern
|
|
108
|
+
* match the string" regardless of prior calls.
|
|
109
|
+
*/
|
|
110
|
+
export function regexTest(re, value) {
|
|
111
|
+
re.lastIndex = 0;
|
|
112
|
+
return re.test(value);
|
|
113
|
+
}
|
|
101
114
|
/**
|
|
102
115
|
* SameValueZero-ish semantics:
|
|
103
116
|
* - NaN equals NaN
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toThrow.d.ts","sourceRoot":"","sources":["../../../src/utils/toThrow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"toThrow.d.ts","sourceRoot":"","sources":["../../../src/utils/toThrow.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,MAAM,GACN,MAAM,GACN,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,GACnC;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,UAAU,WAAW;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,MAAM,CAAC;CACvB;AAgED,wBAAgB,OAAO,CACrB,QAAQ,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,eAAe,EAC1B,KAAK,UAAQ,GACZ,WAAW,CAgEb"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { regexTest } from "./helpers.js";
|
|
1
2
|
function isErrorConstructor(err) {
|
|
2
3
|
return typeof err === "function";
|
|
3
4
|
}
|
|
@@ -24,7 +25,7 @@ function matchThrown(thrown, expected) {
|
|
|
24
25
|
}
|
|
25
26
|
// toThrow(/regex/)
|
|
26
27
|
if (expected instanceof RegExp) {
|
|
27
|
-
return expected
|
|
28
|
+
return regexTest(expected, msg);
|
|
28
29
|
}
|
|
29
30
|
// toThrow(ErrorClass)
|
|
30
31
|
if (isErrorConstructor(expected)) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unrift/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Core engine for the Unrift TypeScript test framework
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Core engine for the Unrift TypeScript test framework - runner, matchers, CLI, and programmatic API",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/cjs/index.cjs",
|
|
@@ -58,7 +58,8 @@
|
|
|
58
58
|
"access": "public"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"esbuild": "^0.27.2"
|
|
61
|
+
"esbuild": "^0.27.2",
|
|
62
|
+
"memfs": "^4.57.7"
|
|
62
63
|
},
|
|
63
64
|
"devDependencies": {
|
|
64
65
|
"ts-node": "^10.9.2",
|