@c9up/helix 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/cli/coverage/diff/overlay.d.ts.map +1 -1
  2. package/dist/cli/coverage/diff/overlay.js +19 -6
  3. package/dist/cli/coverage/diff/overlay.js.map +1 -1
  4. package/dist/cli/pool.js +10 -0
  5. package/dist/cli/pool.js.map +1 -1
  6. package/dist/runtime/equals.d.ts.map +1 -1
  7. package/dist/runtime/equals.js +6 -2
  8. package/dist/runtime/equals.js.map +1 -1
  9. package/dist/runtime/suite.d.ts +26 -0
  10. package/dist/runtime/suite.d.ts.map +1 -1
  11. package/dist/runtime/suite.js +21 -18
  12. package/dist/runtime/suite.js.map +1 -1
  13. package/index.darwin-arm64.node +0 -0
  14. package/index.darwin-x64.node +0 -0
  15. package/index.linux-arm64-gnu.node +0 -0
  16. package/index.linux-x64-gnu.node +0 -0
  17. package/index.win32-x64-msvc.node +0 -0
  18. package/package.json +2 -2
  19. package/src/cli/coverage/aggregate.ts +0 -231
  20. package/src/cli/coverage/collect.ts +0 -63
  21. package/src/cli/coverage/diff/base.ts +0 -46
  22. package/src/cli/coverage/diff/index.ts +0 -160
  23. package/src/cli/coverage/diff/overlay.ts +0 -62
  24. package/src/cli/coverage/diff/parse.ts +0 -121
  25. package/src/cli/coverage/diff/reporters.ts +0 -82
  26. package/src/cli/coverage/diff/types.ts +0 -46
  27. package/src/cli/coverage/filter.ts +0 -71
  28. package/src/cli/coverage/glob.ts +0 -0
  29. package/src/cli/coverage/index.ts +0 -126
  30. package/src/cli/coverage/reporters/json.ts +0 -40
  31. package/src/cli/coverage/reporters/lcov.ts +0 -54
  32. package/src/cli/coverage/reporters/text.ts +0 -48
  33. package/src/cli/coverage/thresholds.ts +0 -73
  34. package/src/cli/coverage/types.ts +0 -93
  35. package/src/cli/discover.ts +0 -174
  36. package/src/cli/native.ts +0 -104
  37. package/src/cli/pool.ts +0 -486
  38. package/src/cli/reporter.ts +0 -155
  39. package/src/cli/run.ts +0 -440
  40. package/src/cli/summary.ts +0 -42
  41. package/src/cli/watch/loop.ts +0 -159
  42. package/src/cli/watch/types.ts +0 -22
  43. package/src/cli/watch/watcher.ts +0 -145
  44. package/src/container/index.ts +0 -16
  45. package/src/container/override.ts +0 -86
  46. package/src/container/spy.ts +0 -25
  47. package/src/index.ts +0 -42
  48. package/src/runtime/assertion-error.ts +0 -38
  49. package/src/runtime/cli-worker.ts +0 -140
  50. package/src/runtime/equals.ts +0 -400
  51. package/src/runtime/expect.ts +0 -173
  52. package/src/runtime/index.ts +0 -50
  53. package/src/runtime/lifecycle.ts +0 -17
  54. package/src/runtime/matchers.ts +0 -452
  55. package/src/runtime/run.ts +0 -573
  56. package/src/runtime/suite.ts +0 -310
  57. package/src/runtime/test-context.ts +0 -59
  58. package/src/runtime/vi/fake-timers.ts +0 -410
  59. package/src/runtime/vi/index.ts +0 -254
  60. package/src/runtime/vi/spy.ts +0 -224
  61. package/src/runtime/vi/spyOn.ts +0 -155
  62. package/src/runtime/vi/system-time.ts +0 -121
  63. package/src/runtime/worker.ts +0 -239
  64. package/src/time/freeze.ts +0 -229
  65. package/src/time/index.ts +0 -16
@@ -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;