@c9up/helix 0.1.3 → 0.1.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/dist/cli/coverage/aggregate.d.ts +24 -0
- package/dist/cli/coverage/aggregate.d.ts.map +1 -0
- package/dist/cli/coverage/aggregate.js +215 -0
- package/dist/cli/coverage/aggregate.js.map +1 -0
- package/dist/cli/coverage/collect.d.ts +13 -0
- package/dist/cli/coverage/collect.d.ts.map +1 -0
- package/dist/cli/coverage/collect.js +66 -0
- package/dist/cli/coverage/collect.js.map +1 -0
- package/dist/cli/coverage/diff/base.d.ts +17 -0
- package/dist/cli/coverage/diff/base.d.ts.map +1 -0
- package/dist/cli/coverage/diff/base.js +44 -0
- package/dist/cli/coverage/diff/base.js.map +1 -0
- package/dist/cli/coverage/diff/index.d.ts +25 -0
- package/dist/cli/coverage/diff/index.d.ts.map +1 -0
- package/dist/cli/coverage/diff/index.js +119 -0
- package/dist/cli/coverage/diff/index.js.map +1 -0
- package/dist/cli/coverage/diff/overlay.d.ts +19 -0
- package/dist/cli/coverage/diff/overlay.d.ts.map +1 -0
- package/dist/cli/coverage/diff/overlay.js +58 -0
- package/dist/cli/coverage/diff/overlay.js.map +1 -0
- package/dist/cli/coverage/diff/parse.d.ts +27 -0
- package/dist/cli/coverage/diff/parse.d.ts.map +1 -0
- package/dist/cli/coverage/diff/parse.js +105 -0
- package/dist/cli/coverage/diff/parse.js.map +1 -0
- package/dist/cli/coverage/diff/reporters.d.ts +12 -0
- package/dist/cli/coverage/diff/reporters.d.ts.map +1 -0
- package/dist/cli/coverage/diff/reporters.js +59 -0
- package/dist/cli/coverage/diff/reporters.js.map +1 -0
- package/dist/cli/coverage/diff/types.d.ts +46 -0
- package/dist/cli/coverage/diff/types.d.ts.map +1 -0
- package/dist/cli/coverage/diff/types.js +15 -0
- package/dist/cli/coverage/diff/types.js.map +1 -0
- package/dist/cli/coverage/filter.d.ts +13 -0
- package/dist/cli/coverage/filter.d.ts.map +1 -0
- package/dist/cli/coverage/filter.js +60 -0
- package/dist/cli/coverage/filter.js.map +1 -0
- package/dist/cli/coverage/glob.d.ts +4 -0
- package/dist/cli/coverage/glob.d.ts.map +1 -0
- package/dist/cli/coverage/glob.js +0 -0
- package/dist/cli/coverage/glob.js.map +1 -0
- package/dist/cli/coverage/index.d.ts +40 -0
- package/dist/cli/coverage/index.d.ts.map +1 -0
- package/dist/cli/coverage/index.js +85 -0
- package/dist/cli/coverage/index.js.map +1 -0
- package/dist/cli/coverage/reporters/json.d.ts +13 -0
- package/dist/cli/coverage/reporters/json.d.ts.map +1 -0
- package/dist/cli/coverage/reporters/json.js +37 -0
- package/dist/cli/coverage/reporters/json.js.map +1 -0
- package/dist/cli/coverage/reporters/lcov.d.ts +13 -0
- package/dist/cli/coverage/reporters/lcov.d.ts.map +1 -0
- package/dist/cli/coverage/reporters/lcov.js +51 -0
- package/dist/cli/coverage/reporters/lcov.js.map +1 -0
- package/dist/cli/coverage/reporters/text.d.ts +8 -0
- package/dist/cli/coverage/reporters/text.d.ts.map +1 -0
- package/dist/cli/coverage/reporters/text.js +39 -0
- package/dist/cli/coverage/reporters/text.js.map +1 -0
- package/dist/cli/coverage/thresholds.d.ts +14 -0
- package/dist/cli/coverage/thresholds.d.ts.map +1 -0
- package/dist/cli/coverage/thresholds.js +58 -0
- package/dist/cli/coverage/thresholds.js.map +1 -0
- package/dist/cli/coverage/types.d.ts +118 -0
- package/dist/cli/coverage/types.d.ts.map +1 -0
- package/dist/cli/coverage/types.js +8 -0
- package/dist/cli/coverage/types.js.map +1 -0
- package/dist/cli/discover.d.ts +27 -0
- package/dist/cli/discover.d.ts.map +1 -0
- package/dist/cli/discover.js +142 -0
- package/dist/cli/discover.js.map +1 -0
- package/dist/cli/native.d.ts +43 -0
- package/dist/cli/native.d.ts.map +1 -0
- package/dist/cli/native.js +64 -0
- package/dist/cli/native.js.map +1 -0
- package/dist/cli/pool.d.ts +55 -0
- package/dist/cli/pool.d.ts.map +1 -0
- package/dist/cli/pool.js +404 -0
- package/dist/cli/pool.js.map +1 -0
- package/dist/cli/reporter.d.ts +51 -0
- package/dist/cli/reporter.d.ts.map +1 -0
- package/dist/cli/reporter.js +124 -0
- package/dist/cli/reporter.js.map +1 -0
- package/dist/cli/run.d.ts +61 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +302 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/summary.d.ts +18 -0
- package/dist/cli/summary.d.ts.map +1 -0
- package/dist/cli/summary.js +20 -0
- package/dist/cli/summary.js.map +1 -0
- package/dist/cli/watch/loop.d.ts +26 -0
- package/dist/cli/watch/loop.d.ts.map +1 -0
- package/dist/cli/watch/loop.js +133 -0
- package/dist/cli/watch/loop.js.map +1 -0
- package/dist/cli/watch/types.d.ts +22 -0
- package/dist/cli/watch/types.d.ts.map +1 -0
- package/dist/cli/watch/types.js +6 -0
- package/dist/cli/watch/types.js.map +1 -0
- package/dist/cli/watch/watcher.d.ts +25 -0
- package/dist/cli/watch/watcher.d.ts.map +1 -0
- package/dist/cli/watch/watcher.js +122 -0
- package/dist/cli/watch/watcher.js.map +1 -0
- package/dist/container/index.d.ts +7 -0
- package/dist/container/index.d.ts.map +1 -0
- package/dist/container/index.js +6 -0
- package/dist/container/index.js.map +1 -0
- package/{src/container/override.ts → dist/container/override.d.ts} +6 -46
- package/dist/container/override.d.ts.map +1 -0
- package/dist/container/override.js +67 -0
- package/dist/container/override.js.map +1 -0
- package/{src/container/spy.ts → dist/container/spy.d.ts} +2 -6
- package/dist/container/spy.d.ts.map +1 -0
- package/dist/container/spy.js +23 -0
- package/dist/container/spy.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/{src/index.ts → dist/index.js} +2 -25
- package/dist/index.js.map +1 -0
- package/dist/runtime/assertion-error.d.ts +20 -0
- package/dist/runtime/assertion-error.d.ts.map +1 -0
- package/dist/runtime/assertion-error.js +23 -0
- package/dist/runtime/assertion-error.js.map +1 -0
- package/dist/runtime/cli-worker.d.ts +25 -0
- package/dist/runtime/cli-worker.d.ts.map +1 -0
- package/dist/runtime/cli-worker.js +128 -0
- package/dist/runtime/cli-worker.js.map +1 -0
- package/dist/runtime/equals.d.ts +25 -0
- package/dist/runtime/equals.d.ts.map +1 -0
- package/dist/runtime/equals.js +343 -0
- package/dist/runtime/equals.js.map +1 -0
- package/dist/runtime/expect.d.ts +32 -0
- package/dist/runtime/expect.d.ts.map +1 -0
- package/dist/runtime/expect.js +121 -0
- package/dist/runtime/expect.js.map +1 -0
- package/{src/runtime/index.ts → dist/runtime/index.d.ts} +5 -27
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +17 -0
- package/dist/runtime/index.js.map +1 -0
- package/{src/runtime/lifecycle.ts → dist/runtime/lifecycle.d.ts} +2 -8
- package/dist/runtime/lifecycle.d.ts.map +1 -0
- package/dist/runtime/lifecycle.js +10 -0
- package/dist/runtime/lifecycle.js.map +1 -0
- package/dist/runtime/matchers.d.ts +42 -0
- package/dist/runtime/matchers.d.ts.map +1 -0
- package/dist/runtime/matchers.js +375 -0
- package/dist/runtime/matchers.js.map +1 -0
- package/dist/runtime/run.d.ts +55 -0
- package/dist/runtime/run.d.ts.map +1 -0
- package/dist/runtime/run.js +456 -0
- package/dist/runtime/run.js.map +1 -0
- package/dist/runtime/suite.d.ts +91 -0
- package/dist/runtime/suite.d.ts.map +1 -0
- package/dist/runtime/suite.js +206 -0
- package/dist/runtime/suite.js.map +1 -0
- package/dist/runtime/test-context.d.ts +25 -0
- package/dist/runtime/test-context.d.ts.map +1 -0
- package/dist/runtime/test-context.js +52 -0
- package/dist/runtime/test-context.js.map +1 -0
- package/dist/runtime/vi/fake-timers.d.ts +48 -0
- package/dist/runtime/vi/fake-timers.d.ts.map +1 -0
- package/dist/runtime/vi/fake-timers.js +317 -0
- package/dist/runtime/vi/fake-timers.js.map +1 -0
- package/dist/runtime/vi/index.d.ts +70 -0
- package/dist/runtime/vi/index.d.ts.map +1 -0
- package/dist/runtime/vi/index.js +209 -0
- package/dist/runtime/vi/index.js.map +1 -0
- package/dist/runtime/vi/spy.d.ts +54 -0
- package/dist/runtime/vi/spy.d.ts.map +1 -0
- package/dist/runtime/vi/spy.js +159 -0
- package/dist/runtime/vi/spy.js.map +1 -0
- package/dist/runtime/vi/spyOn.d.ts +28 -0
- package/dist/runtime/vi/spyOn.d.ts.map +1 -0
- package/dist/runtime/vi/spyOn.js +121 -0
- package/dist/runtime/vi/spyOn.js.map +1 -0
- package/dist/runtime/vi/system-time.d.ts +30 -0
- package/dist/runtime/vi/system-time.d.ts.map +1 -0
- package/dist/runtime/vi/system-time.js +100 -0
- package/dist/runtime/vi/system-time.js.map +1 -0
- package/dist/runtime/worker.d.ts +26 -0
- package/dist/runtime/worker.d.ts.map +1 -0
- package/dist/runtime/worker.js +195 -0
- package/dist/runtime/worker.js.map +1 -0
- package/dist/time/freeze.d.ts +80 -0
- package/dist/time/freeze.d.ts.map +1 -0
- package/dist/time/freeze.js +184 -0
- package/dist/time/freeze.js.map +1 -0
- package/{src/time/index.ts → dist/time/index.d.ts} +1 -1
- package/dist/time/index.d.ts.map +1 -0
- package/dist/time/index.js +15 -0
- package/dist/time/index.js.map +1 -0
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +2 -2
- package/src/cli/coverage/aggregate.ts +0 -231
- package/src/cli/coverage/collect.ts +0 -63
- package/src/cli/coverage/diff/base.ts +0 -46
- package/src/cli/coverage/diff/index.ts +0 -160
- package/src/cli/coverage/diff/overlay.ts +0 -62
- package/src/cli/coverage/diff/parse.ts +0 -121
- package/src/cli/coverage/diff/reporters.ts +0 -82
- package/src/cli/coverage/diff/types.ts +0 -46
- package/src/cli/coverage/filter.ts +0 -71
- package/src/cli/coverage/glob.ts +0 -0
- package/src/cli/coverage/index.ts +0 -126
- package/src/cli/coverage/reporters/json.ts +0 -40
- package/src/cli/coverage/reporters/lcov.ts +0 -54
- package/src/cli/coverage/reporters/text.ts +0 -48
- package/src/cli/coverage/thresholds.ts +0 -73
- package/src/cli/coverage/types.ts +0 -93
- package/src/cli/discover.ts +0 -174
- package/src/cli/native.ts +0 -104
- package/src/cli/pool.ts +0 -486
- package/src/cli/reporter.ts +0 -155
- package/src/cli/run.ts +0 -440
- package/src/cli/summary.ts +0 -42
- package/src/cli/watch/loop.ts +0 -159
- package/src/cli/watch/types.ts +0 -22
- package/src/cli/watch/watcher.ts +0 -145
- package/src/container/index.ts +0 -16
- package/src/runtime/assertion-error.ts +0 -38
- package/src/runtime/cli-worker.ts +0 -140
- package/src/runtime/equals.ts +0 -400
- package/src/runtime/expect.ts +0 -173
- package/src/runtime/matchers.ts +0 -452
- package/src/runtime/run.ts +0 -573
- package/src/runtime/suite.ts +0 -310
- package/src/runtime/test-context.ts +0 -59
- package/src/runtime/vi/fake-timers.ts +0 -410
- package/src/runtime/vi/index.ts +0 -254
- package/src/runtime/vi/spy.ts +0 -224
- package/src/runtime/vi/spyOn.ts +0 -155
- package/src/runtime/vi/system-time.ts +0 -121
- package/src/runtime/worker.ts +0 -239
- package/src/time/freeze.ts +0 -229
package/src/runtime/matchers.ts
DELETED
|
@@ -1,452 +0,0 @@
|
|
|
1
|
-
import { equals, partialEquals } from "./equals.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Matcher signature. Returns `{ pass, message }`:
|
|
5
|
-
* - `pass`: whether the assertion holds.
|
|
6
|
-
* - `message`: diagnostic message for the failure path. Called lazily to
|
|
7
|
-
* avoid formatting cost when the matcher passes.
|
|
8
|
-
*/
|
|
9
|
-
export interface MatcherResult {
|
|
10
|
-
pass: boolean;
|
|
11
|
-
message(): string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type Matcher<Args extends unknown[] = unknown[]> = (
|
|
15
|
-
received: unknown,
|
|
16
|
-
...args: Args
|
|
17
|
-
) => MatcherResult;
|
|
18
|
-
|
|
19
|
-
export interface SpyLike {
|
|
20
|
-
__helixIsSpy: true;
|
|
21
|
-
calls: unknown[][];
|
|
22
|
-
callCount: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function isSpy(value: unknown): value is SpyLike {
|
|
26
|
-
// Spies are callable, so `typeof` can be "function" OR "object".
|
|
27
|
-
if (!value || (typeof value !== "object" && typeof value !== "function")) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
const v = value as Partial<SpyLike>;
|
|
31
|
-
return (
|
|
32
|
-
v.__helixIsSpy === true &&
|
|
33
|
-
Array.isArray(v.calls) &&
|
|
34
|
-
typeof v.callCount === "number"
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function repr(value: unknown, maxLen = 200): string {
|
|
39
|
-
try {
|
|
40
|
-
if (typeof value === "string") {
|
|
41
|
-
const s = JSON.stringify(value);
|
|
42
|
-
return s.length > maxLen ? `${s.slice(0, maxLen)}..."` : s;
|
|
43
|
-
}
|
|
44
|
-
if (typeof value === "function") {
|
|
45
|
-
const src = value.toString();
|
|
46
|
-
return src.length > 40 ? `${src.slice(0, 40)}...` : src;
|
|
47
|
-
}
|
|
48
|
-
if (value === undefined) return "undefined";
|
|
49
|
-
if (value === null) return "null";
|
|
50
|
-
if (typeof value === "bigint") return `${value}n`;
|
|
51
|
-
if (typeof value === "object") {
|
|
52
|
-
const json = JSON.stringify(value);
|
|
53
|
-
if (json === undefined) return String(value);
|
|
54
|
-
return json.length > maxLen ? `${json.slice(0, maxLen)}...` : json;
|
|
55
|
-
}
|
|
56
|
-
return String(value);
|
|
57
|
-
} catch {
|
|
58
|
-
return String(value);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export const matchers = {
|
|
63
|
-
toBe(received: unknown, expected: unknown): MatcherResult {
|
|
64
|
-
const pass = Object.is(received, expected);
|
|
65
|
-
return {
|
|
66
|
-
pass,
|
|
67
|
-
message: () =>
|
|
68
|
-
`expected ${repr(received)} to be ${repr(expected)} (strict equality)`,
|
|
69
|
-
};
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
toEqual(received: unknown, expected: unknown): MatcherResult {
|
|
73
|
-
const pass = equals(received, expected);
|
|
74
|
-
return {
|
|
75
|
-
pass,
|
|
76
|
-
message: () =>
|
|
77
|
-
`expected ${repr(received)} to deep-equal ${repr(expected)}`,
|
|
78
|
-
};
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
toMatchObject(received: unknown, expected: unknown): MatcherResult {
|
|
82
|
-
const pass = partialEquals(received, expected);
|
|
83
|
-
return {
|
|
84
|
-
pass,
|
|
85
|
-
message: () =>
|
|
86
|
-
`expected ${repr(received)} to match subset ${repr(expected)}`,
|
|
87
|
-
};
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
toContain(received: unknown, item: unknown): MatcherResult {
|
|
91
|
-
let pass = false;
|
|
92
|
-
if (typeof received === "string" && typeof item === "string") {
|
|
93
|
-
pass = received.includes(item);
|
|
94
|
-
} else if (Array.isArray(received)) {
|
|
95
|
-
// Deep equality so `.toContain({id:1})` works on arrays of objects.
|
|
96
|
-
pass = received.some((x) => equals(x, item));
|
|
97
|
-
} else if (received instanceof Set) {
|
|
98
|
-
// Deep equality: consistent with the Array branch.
|
|
99
|
-
for (const v of received) {
|
|
100
|
-
if (equals(v, item)) {
|
|
101
|
-
pass = true;
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// NB: `toContain` intentionally does not support `Map` — its semantics
|
|
107
|
-
// (keys? values? entries?) are ambiguous. Users should use
|
|
108
|
-
// `expect([...map.keys()]).toContain(k)` explicitly.
|
|
109
|
-
return {
|
|
110
|
-
pass,
|
|
111
|
-
message: () => `expected ${repr(received)} to contain ${repr(item)}`,
|
|
112
|
-
};
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
toMatch(received: unknown, expected: RegExp | string): MatcherResult {
|
|
116
|
-
if (typeof received !== "string") {
|
|
117
|
-
return {
|
|
118
|
-
pass: false,
|
|
119
|
-
message: () =>
|
|
120
|
-
`expected a string, got ${typeof received} (${repr(received)})`,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
const pass =
|
|
124
|
-
expected instanceof RegExp
|
|
125
|
-
? expected.test(received)
|
|
126
|
-
: received.includes(expected);
|
|
127
|
-
return {
|
|
128
|
-
pass,
|
|
129
|
-
message: () =>
|
|
130
|
-
`expected "${received}" to match ${expected instanceof RegExp ? expected : `"${expected}"`}`,
|
|
131
|
-
};
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
toHaveLength(received: unknown, length: number): MatcherResult {
|
|
135
|
-
const actual =
|
|
136
|
-
received && typeof (received as { length?: unknown }).length === "number"
|
|
137
|
-
? (received as { length: number }).length
|
|
138
|
-
: undefined;
|
|
139
|
-
return {
|
|
140
|
-
pass: actual === length,
|
|
141
|
-
message: () =>
|
|
142
|
-
`expected length ${length}, got ${actual === undefined ? "no .length" : actual} (value: ${repr(received)})`,
|
|
143
|
-
};
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
toBeDefined(received: unknown): MatcherResult {
|
|
147
|
-
return {
|
|
148
|
-
pass: received !== undefined,
|
|
149
|
-
message: () => `expected value to be defined, got undefined`,
|
|
150
|
-
};
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
toBeUndefined(received: unknown): MatcherResult {
|
|
154
|
-
return {
|
|
155
|
-
pass: received === undefined,
|
|
156
|
-
message: () => `expected value to be undefined, got ${repr(received)}`,
|
|
157
|
-
};
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
toBeNull(received: unknown): MatcherResult {
|
|
161
|
-
return {
|
|
162
|
-
pass: received === null,
|
|
163
|
-
message: () => `expected null, got ${repr(received)}`,
|
|
164
|
-
};
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
toBeInstanceOf(received: unknown, ctor: unknown): MatcherResult {
|
|
168
|
-
if (typeof ctor !== "function") {
|
|
169
|
-
return {
|
|
170
|
-
pass: false,
|
|
171
|
-
message: () => `expected a constructor, got ${typeof ctor}`,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
// Arrow functions and bound functions without `prototype` are not
|
|
175
|
-
// constructible; `x instanceof arrowFn` throws TypeError. Reject
|
|
176
|
-
// upfront with a clean AssertionError instead of leaking the raw error.
|
|
177
|
-
const ctorFn = ctor as { prototype?: unknown; name?: string };
|
|
178
|
-
if (ctorFn.prototype === undefined) {
|
|
179
|
-
return {
|
|
180
|
-
pass: false,
|
|
181
|
-
message: () =>
|
|
182
|
-
`expected a constructor (function with a prototype), got ${ctorFn.name ?? "anonymous"} (arrow / bound fn?)`,
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
let pass = false;
|
|
186
|
-
try {
|
|
187
|
-
pass = received instanceof (ctor as new (...a: unknown[]) => object);
|
|
188
|
-
} catch {
|
|
189
|
-
pass = false;
|
|
190
|
-
}
|
|
191
|
-
return {
|
|
192
|
-
pass,
|
|
193
|
-
message: () =>
|
|
194
|
-
`expected ${repr(received)} to be instance of ${ctorFn.name ?? "anonymous"}`,
|
|
195
|
-
};
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
toBeGreaterThan(received: unknown, expected: number | bigint): MatcherResult {
|
|
199
|
-
if (typeof received !== "number" && typeof received !== "bigint") {
|
|
200
|
-
return {
|
|
201
|
-
pass: false,
|
|
202
|
-
message: () => `expected a number or bigint, got ${typeof received}`,
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
return {
|
|
206
|
-
pass: compareGt(received, expected),
|
|
207
|
-
message: () => `expected ${received} to be > ${expected}`,
|
|
208
|
-
};
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
toBeGreaterThanOrEqual(
|
|
212
|
-
received: unknown,
|
|
213
|
-
expected: number | bigint,
|
|
214
|
-
): MatcherResult {
|
|
215
|
-
if (typeof received !== "number" && typeof received !== "bigint") {
|
|
216
|
-
return {
|
|
217
|
-
pass: false,
|
|
218
|
-
message: () => `expected a number or bigint, got ${typeof received}`,
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
return {
|
|
222
|
-
pass: compareGte(received, expected),
|
|
223
|
-
message: () => `expected ${received} to be >= ${expected}`,
|
|
224
|
-
};
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
toBeLessThan(received: unknown, expected: number | bigint): MatcherResult {
|
|
228
|
-
if (typeof received !== "number" && typeof received !== "bigint") {
|
|
229
|
-
return {
|
|
230
|
-
pass: false,
|
|
231
|
-
message: () => `expected a number or bigint, got ${typeof received}`,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
return {
|
|
235
|
-
pass: compareLt(received, expected),
|
|
236
|
-
message: () => `expected ${received} to be < ${expected}`,
|
|
237
|
-
};
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
toBeLessThanOrEqual(
|
|
241
|
-
received: unknown,
|
|
242
|
-
expected: number | bigint,
|
|
243
|
-
): MatcherResult {
|
|
244
|
-
if (typeof received !== "number" && typeof received !== "bigint") {
|
|
245
|
-
return {
|
|
246
|
-
pass: false,
|
|
247
|
-
message: () => `expected a number or bigint, got ${typeof received}`,
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
return {
|
|
251
|
-
pass: compareLte(received, expected),
|
|
252
|
-
message: () => `expected ${received} to be <= ${expected}`,
|
|
253
|
-
};
|
|
254
|
-
},
|
|
255
|
-
|
|
256
|
-
toBeTruthy(received: unknown): MatcherResult {
|
|
257
|
-
return {
|
|
258
|
-
pass: Boolean(received),
|
|
259
|
-
message: () => `expected ${repr(received)} to be truthy`,
|
|
260
|
-
};
|
|
261
|
-
},
|
|
262
|
-
|
|
263
|
-
toBeFalsy(received: unknown): MatcherResult {
|
|
264
|
-
return {
|
|
265
|
-
pass: !received,
|
|
266
|
-
message: () => `expected ${repr(received)} to be falsy`,
|
|
267
|
-
};
|
|
268
|
-
},
|
|
269
|
-
|
|
270
|
-
toBeNaN(received: unknown): MatcherResult {
|
|
271
|
-
return {
|
|
272
|
-
pass: typeof received === "number" && Number.isNaN(received),
|
|
273
|
-
message: () => `expected ${repr(received)} to be NaN`,
|
|
274
|
-
};
|
|
275
|
-
},
|
|
276
|
-
|
|
277
|
-
toThrow(
|
|
278
|
-
received: unknown,
|
|
279
|
-
expected?: string | RegExp | Error | (new (...args: unknown[]) => Error),
|
|
280
|
-
): MatcherResult {
|
|
281
|
-
if (typeof received !== "function") {
|
|
282
|
-
return {
|
|
283
|
-
pass: false,
|
|
284
|
-
message: () => `expected a function, got ${typeof received}`,
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
let error: unknown;
|
|
288
|
-
let returned: unknown;
|
|
289
|
-
try {
|
|
290
|
-
returned = received();
|
|
291
|
-
} catch (err) {
|
|
292
|
-
error = err;
|
|
293
|
-
}
|
|
294
|
-
if (
|
|
295
|
-
error === undefined &&
|
|
296
|
-
returned &&
|
|
297
|
-
typeof (returned as { then?: unknown }).then === "function"
|
|
298
|
-
) {
|
|
299
|
-
// Swallow the rejection so it doesn't become an unhandledRejection.
|
|
300
|
-
(returned as Promise<unknown>).catch(() => {});
|
|
301
|
-
return {
|
|
302
|
-
pass: false,
|
|
303
|
-
message: () =>
|
|
304
|
-
`expected function to throw synchronously, but it returned a Promise — use \`expect(fn()).rejects.toThrow(...)\` for async`,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
if (error === undefined) {
|
|
308
|
-
return {
|
|
309
|
-
pass: false,
|
|
310
|
-
message: () => `expected function to throw, but it returned normally`,
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
if (expected === undefined) {
|
|
314
|
-
return { pass: true, message: () => `` };
|
|
315
|
-
}
|
|
316
|
-
const pass = matchThrownError(error, expected);
|
|
317
|
-
return {
|
|
318
|
-
pass,
|
|
319
|
-
message: () =>
|
|
320
|
-
`expected function to throw matching ${reprExpected(expected)}, got ${repr(error)}`,
|
|
321
|
-
};
|
|
322
|
-
},
|
|
323
|
-
|
|
324
|
-
toHaveBeenCalled(received: unknown): MatcherResult {
|
|
325
|
-
if (!isSpy(received)) {
|
|
326
|
-
return {
|
|
327
|
-
pass: false,
|
|
328
|
-
message: () =>
|
|
329
|
-
`toHaveBeenCalled requires a spy (from vi.fn/vi.spyOn); got ${repr(received)}`,
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
return {
|
|
333
|
-
pass: received.callCount > 0,
|
|
334
|
-
message: () =>
|
|
335
|
-
`expected spy to have been called at least once, but it wasn't`,
|
|
336
|
-
};
|
|
337
|
-
},
|
|
338
|
-
|
|
339
|
-
toHaveBeenCalledTimes(received: unknown, n: number): MatcherResult {
|
|
340
|
-
if (!isSpy(received)) {
|
|
341
|
-
return {
|
|
342
|
-
pass: false,
|
|
343
|
-
message: () =>
|
|
344
|
-
`toHaveBeenCalledTimes requires a spy; got ${repr(received)}`,
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
return {
|
|
348
|
-
pass: received.callCount === n,
|
|
349
|
-
message: () =>
|
|
350
|
-
`expected spy to be called ${n} times, got ${received.callCount}`,
|
|
351
|
-
};
|
|
352
|
-
},
|
|
353
|
-
|
|
354
|
-
toHaveBeenCalledWith(
|
|
355
|
-
received: unknown,
|
|
356
|
-
...expectedArgs: unknown[]
|
|
357
|
-
): MatcherResult {
|
|
358
|
-
if (!isSpy(received)) {
|
|
359
|
-
return {
|
|
360
|
-
pass: false,
|
|
361
|
-
message: () =>
|
|
362
|
-
`toHaveBeenCalledWith requires a spy; got ${repr(received)}`,
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
const pass = received.calls.some((actualArgs) =>
|
|
366
|
-
equals(actualArgs, expectedArgs),
|
|
367
|
-
);
|
|
368
|
-
return {
|
|
369
|
-
pass,
|
|
370
|
-
message: () =>
|
|
371
|
-
`expected spy to have been called with ${repr(expectedArgs)}\nActual calls: ${repr(received.calls)}`,
|
|
372
|
-
};
|
|
373
|
-
},
|
|
374
|
-
|
|
375
|
-
toHaveBeenCalledOnce(received: unknown): MatcherResult {
|
|
376
|
-
if (!isSpy(received)) {
|
|
377
|
-
return {
|
|
378
|
-
pass: false,
|
|
379
|
-
message: () =>
|
|
380
|
-
`toHaveBeenCalledOnce requires a spy; got ${repr(received)}`,
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
return {
|
|
384
|
-
pass: received.callCount === 1,
|
|
385
|
-
message: () =>
|
|
386
|
-
`expected spy to have been called exactly once, got ${received.callCount} calls`,
|
|
387
|
-
};
|
|
388
|
-
},
|
|
389
|
-
};
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Cross-type numeric comparison: JS's `>` / `>=` operators accept mixed
|
|
393
|
-
* `number` and `bigint` operands, but TypeScript refuses the union. These
|
|
394
|
-
* helpers narrow through typeof so the comparison is fully typed.
|
|
395
|
-
*/
|
|
396
|
-
function compareGt(a: number | bigint, b: number | bigint): boolean {
|
|
397
|
-
if (typeof a === "number" && typeof b === "number") return a > b;
|
|
398
|
-
if (typeof a === "bigint" && typeof b === "bigint") return a > b;
|
|
399
|
-
// Mixed number/bigint — JS's `>` operator accepts it at runtime. Coerce
|
|
400
|
-
// both sides to a common `number` view for the comparison; BigInt values
|
|
401
|
-
// outside Number range lose precision only when larger than 2^53, which
|
|
402
|
-
// is acceptable for ordering.
|
|
403
|
-
return Number(a) > Number(b);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function compareGte(a: number | bigint, b: number | bigint): boolean {
|
|
407
|
-
if (typeof a === "number" && typeof b === "number") return a >= b;
|
|
408
|
-
if (typeof a === "bigint" && typeof b === "bigint") return a >= b;
|
|
409
|
-
return Number(a) >= Number(b);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
function compareLt(a: number | bigint, b: number | bigint): boolean {
|
|
413
|
-
if (typeof a === "number" && typeof b === "number") return a < b;
|
|
414
|
-
if (typeof a === "bigint" && typeof b === "bigint") return a < b;
|
|
415
|
-
return Number(a) < Number(b);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
function compareLte(a: number | bigint, b: number | bigint): boolean {
|
|
419
|
-
if (typeof a === "number" && typeof b === "number") return a <= b;
|
|
420
|
-
if (typeof a === "bigint" && typeof b === "bigint") return a <= b;
|
|
421
|
-
return Number(a) <= Number(b);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
function matchThrownError(
|
|
425
|
-
error: unknown,
|
|
426
|
-
expected: string | RegExp | Error | (new (...args: unknown[]) => Error),
|
|
427
|
-
): boolean {
|
|
428
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
429
|
-
if (typeof expected === "string") return msg.includes(expected);
|
|
430
|
-
if (expected instanceof RegExp) return expected.test(msg);
|
|
431
|
-
if (expected instanceof Error) {
|
|
432
|
-
return (
|
|
433
|
-
error instanceof Error &&
|
|
434
|
-
msg === expected.message &&
|
|
435
|
-
Object.getPrototypeOf(error) === Object.getPrototypeOf(expected)
|
|
436
|
-
);
|
|
437
|
-
}
|
|
438
|
-
// Ctor.
|
|
439
|
-
return error instanceof (expected as new (...args: unknown[]) => Error);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
function reprExpected(
|
|
443
|
-
expected: string | RegExp | Error | (new (...args: unknown[]) => Error),
|
|
444
|
-
): string {
|
|
445
|
-
if (typeof expected === "string") return `"${expected}"`;
|
|
446
|
-
if (expected instanceof RegExp) return String(expected);
|
|
447
|
-
if (expected instanceof Error)
|
|
448
|
-
return `${expected.constructor.name}("${expected.message}")`;
|
|
449
|
-
return (expected as { name?: string }).name ?? "anonymous";
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
export type MatcherName = keyof typeof matchers;
|