@unrift/core 0.0.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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/bin/unrift.mjs +5 -0
  3. package/dist/cjs/index.cjs +31 -0
  4. package/dist/esm/cli.d.ts +3 -0
  5. package/dist/esm/cli.d.ts.map +1 -0
  6. package/dist/esm/cli.js +87 -0
  7. package/dist/esm/context.d.ts +15 -0
  8. package/dist/esm/context.d.ts.map +1 -0
  9. package/dist/esm/context.js +16 -0
  10. package/dist/esm/expect.d.ts +27 -0
  11. package/dist/esm/expect.d.ts.map +1 -0
  12. package/dist/esm/expect.js +43 -0
  13. package/dist/esm/hooks.d.ts +8 -0
  14. package/dist/esm/hooks.d.ts.map +1 -0
  15. package/dist/esm/hooks.js +18 -0
  16. package/dist/esm/index.d.ts +7 -0
  17. package/dist/esm/index.d.ts.map +1 -0
  18. package/dist/esm/index.js +4 -0
  19. package/dist/esm/injected/globals.d.ts +4 -0
  20. package/dist/esm/injected/globals.d.ts.map +1 -0
  21. package/dist/esm/injected/globals.js +6 -0
  22. package/dist/esm/interface.d.ts +18 -0
  23. package/dist/esm/interface.d.ts.map +1 -0
  24. package/dist/esm/interface.js +29 -0
  25. package/dist/esm/matchers.d.ts +2 -0
  26. package/dist/esm/matchers.d.ts.map +1 -0
  27. package/dist/esm/matchers.js +81 -0
  28. package/dist/esm/run.d.ts +21 -0
  29. package/dist/esm/run.d.ts.map +1 -0
  30. package/dist/esm/run.js +57 -0
  31. package/dist/esm/runner.d.ts +14 -0
  32. package/dist/esm/runner.d.ts.map +1 -0
  33. package/dist/esm/runner.js +207 -0
  34. package/dist/esm/suite.d.ts +58 -0
  35. package/dist/esm/suite.d.ts.map +1 -0
  36. package/dist/esm/suite.js +281 -0
  37. package/dist/esm/test.d.ts +18 -0
  38. package/dist/esm/test.d.ts.map +1 -0
  39. package/dist/esm/test.js +52 -0
  40. package/dist/esm/types.d.ts +24 -0
  41. package/dist/esm/types.d.ts.map +1 -0
  42. package/dist/esm/types.js +16 -0
  43. package/dist/esm/utils/colors.d.ts +7 -0
  44. package/dist/esm/utils/colors.d.ts.map +1 -0
  45. package/dist/esm/utils/colors.js +12 -0
  46. package/dist/esm/utils/deepEqual.d.ts +9 -0
  47. package/dist/esm/utils/deepEqual.d.ts.map +1 -0
  48. package/dist/esm/utils/deepEqual.js +201 -0
  49. package/dist/esm/utils/defineConfig.d.ts +12 -0
  50. package/dist/esm/utils/defineConfig.d.ts.map +1 -0
  51. package/dist/esm/utils/defineConfig.js +3 -0
  52. package/dist/esm/utils/discoverTestFiles.d.ts +3 -0
  53. package/dist/esm/utils/discoverTestFiles.d.ts.map +1 -0
  54. package/dist/esm/utils/discoverTestFiles.js +22 -0
  55. package/dist/esm/utils/helpers.d.ts +13 -0
  56. package/dist/esm/utils/helpers.d.ts.map +1 -0
  57. package/dist/esm/utils/helpers.js +29 -0
  58. package/dist/esm/utils/loadConfig.d.ts +9 -0
  59. package/dist/esm/utils/loadConfig.d.ts.map +1 -0
  60. package/dist/esm/utils/loadConfig.js +89 -0
  61. package/dist/esm/utils/looseEqual.d.ts +2 -0
  62. package/dist/esm/utils/looseEqual.d.ts.map +1 -0
  63. package/dist/esm/utils/looseEqual.js +205 -0
  64. package/dist/esm/utils/toThrow.d.ts +11 -0
  65. package/dist/esm/utils/toThrow.d.ts.map +1 -0
  66. package/dist/esm/utils/toThrow.js +93 -0
  67. package/dist/esm/utils/transform.d.ts +10 -0
  68. package/dist/esm/utils/transform.d.ts.map +1 -0
  69. package/dist/esm/utils/transform.js +213 -0
  70. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Elijah Kotyluk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/bin/unrift.mjs ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // Run the real CLI
5
+ await import("../dist/esm/cli.js");
@@ -0,0 +1,31 @@
1
+ 'use strict';
2
+
3
+ let esm;
4
+
5
+ function load() {
6
+ if (!esm) {
7
+ esm = require('node:module')
8
+ .createRequire(__filename)('../esm/index.js');
9
+ }
10
+ return esm;
11
+ }
12
+
13
+ module.exports = new Proxy({}, {
14
+ get(_t, p) {
15
+ return load()[p];
16
+ },
17
+ has(_t, p) {
18
+ return p in load();
19
+ },
20
+ ownKeys() {
21
+ return Reflect.ownKeys(load());
22
+ },
23
+ getOwnPropertyDescriptor(_t, p) {
24
+ return {
25
+ configurable: true,
26
+ enumerable: true,
27
+ writable: false,
28
+ value: load()[p],
29
+ };
30
+ }
31
+ });
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ import { runTestsCLI } from "./runner.js";
3
+ function safeRegExp(source) {
4
+ try {
5
+ return new RegExp(source);
6
+ }
7
+ catch (err) {
8
+ const msg = err instanceof Error ? err.message : String(err);
9
+ throw new Error(`Invalid pattern regex "${source}": ${msg}`);
10
+ }
11
+ }
12
+ function printHelp() {
13
+ console.log(`
14
+ Unrift Test Runner
15
+
16
+ Usage:
17
+ unrift [pattern] [options]
18
+
19
+ Options:
20
+ -c, --config <path> Path to config file
21
+ -d, --debug Enable debug logging
22
+ -l, --list List discovered test files
23
+ -j, --json Output test results as JSON
24
+ --cache-clean Clear transform cache
25
+ -h, --help Show help
26
+
27
+ Examples:
28
+ unrift
29
+ unrift math
30
+ unrift -c test/config.ts --debug
31
+ `);
32
+ }
33
+ function parseArgs(argv) {
34
+ let configPath;
35
+ let pattern;
36
+ let debug = false;
37
+ let help = false;
38
+ let list = false;
39
+ let json = false;
40
+ let cacheClean = false;
41
+ const rest = [];
42
+ for (let i = 0; i < argv.length; i++) {
43
+ const a = argv[i];
44
+ if (a === "--help" || a === "-h") {
45
+ help = true;
46
+ continue;
47
+ }
48
+ if (a === "--config" || a === "-c") {
49
+ const next = argv[i + 1];
50
+ if (!next)
51
+ throw new Error(`${a} requires a path`);
52
+ configPath = next;
53
+ i++;
54
+ continue;
55
+ }
56
+ if (a === "--debug" || a === "-d") {
57
+ debug = true;
58
+ continue;
59
+ }
60
+ if (a === "--list" || a === "-l") {
61
+ list = true;
62
+ continue;
63
+ }
64
+ if (a === "--json" || a === "-j") {
65
+ json = true;
66
+ continue;
67
+ }
68
+ if (a === "--cache-clean" || a === "--clear-cache") {
69
+ cacheClean = true;
70
+ continue;
71
+ }
72
+ // First non-flag arg is pattern
73
+ rest.push(a);
74
+ }
75
+ if (rest[0])
76
+ pattern = safeRegExp(rest[0]);
77
+ return { configPath, pattern, debug, list, json, cacheClean, help };
78
+ }
79
+ const { configPath, pattern, debug, list, json, cacheClean, help } = parseArgs(process.argv.slice(2));
80
+ if (help) {
81
+ printHelp();
82
+ process.exit(0);
83
+ }
84
+ runTestsCLI({ pattern, configPath, debug, list, json, cacheClean }).catch((err) => {
85
+ console.error(err);
86
+ process.exit(1);
87
+ });
@@ -0,0 +1,15 @@
1
+ import { Suite } from "./suite";
2
+ export declare enum RunState {
3
+ Register = "register",
4
+ Run = "run",
5
+ Idle = "idle"
6
+ }
7
+ type UnriftState = RunState;
8
+ interface UnriftGlobalContext {
9
+ currentSuite: Suite | null;
10
+ state: UnriftState;
11
+ }
12
+ export declare const unriftGlobalContext: UnriftGlobalContext;
13
+ export declare function assertRegisterState(apiName: string): void;
14
+ export {};
15
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,oBAAY,QAAQ;IAClB,QAAQ,aAAa;IACrB,GAAG,QAAQ;IACX,IAAI,SAAS;CACd;AAED,KAAK,WAAW,GAAG,QAAQ,CAAC;AAE5B,UAAU,mBAAmB;IAC3B,YAAY,EAAE,KAAK,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,eAAO,MAAM,mBAAmB,EAAE,mBAGjC,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,QAOlD"}
@@ -0,0 +1,16 @@
1
+ export var RunState;
2
+ (function (RunState) {
3
+ RunState["Register"] = "register";
4
+ RunState["Run"] = "run";
5
+ RunState["Idle"] = "idle";
6
+ })(RunState || (RunState = {}));
7
+ export const unriftGlobalContext = {
8
+ currentSuite: null,
9
+ state: RunState.Register,
10
+ };
11
+ export function assertRegisterState(apiName) {
12
+ if (unriftGlobalContext.state !== RunState.Register) {
13
+ throw new Error(`Unrift: ${apiName}() can only be called during test registration (module import time). ` +
14
+ `You likely called it inside a running test or hook.`);
15
+ }
16
+ }
@@ -0,0 +1,27 @@
1
+ import type { MatcherMap } from "./types";
2
+ export declare function extendMatchers(newMatchers: MatcherMap): void;
3
+ /**
4
+ * Built-in matchers
5
+ * @TODO add more matchers and extract to separate package.
6
+ */
7
+ export interface Matchers<T> {
8
+ toBe(expected: T): void | Promise<void>;
9
+ toBeDefined(): void | Promise<void>;
10
+ toBeFalsy(): void | Promise<void>;
11
+ toBeNull(): void | Promise<void>;
12
+ toBeTruthy(): void | Promise<void>;
13
+ toBeUndefined(): void | Promise<void>;
14
+ toEqual(expected: unknown): void | Promise<void>;
15
+ toMatch(expected: RegExp | string): void | Promise<void>;
16
+ toStrictEqual(expected: unknown): void | Promise<void>;
17
+ toThrow(expected?: unknown): void | Promise<void>;
18
+ readonly not: Matchers<T>;
19
+ }
20
+ export interface Matchers<T> {
21
+ }
22
+ export interface ExpectInterface {
23
+ <T>(value: T): Matchers<T>;
24
+ extend<M extends MatcherMap>(m: M): void;
25
+ }
26
+ export declare const expect: ExpectInterface;
27
+ //# sourceMappingURL=expect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../../src/expect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1D,wBAAgB,cAAc,CAAC,WAAW,EAAE,UAAU,QAErD;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,WAAW,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,SAAS,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,QAAQ,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,UAAU,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,aAAa,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC3B;AAID,MAAM,WAAW,QAAQ,CAAC,CAAC;CAAI;AAE/B,MAAM,WAAW,eAAe;IAC9B,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;CAC1C;AAED,eAAO,MAAM,MAAM,EAAE,eAyCjB,CAAC"}
@@ -0,0 +1,43 @@
1
+ const matcherRegistry = Object.create(null);
2
+ export function extendMatchers(newMatchers) {
3
+ for (const key in newMatchers)
4
+ matcherRegistry[key] = newMatchers[key];
5
+ }
6
+ export const expect = (() => {
7
+ function expectFn(received) {
8
+ function makeExpectation(isNot) {
9
+ const ctx = {
10
+ isNot,
11
+ diff(a, b) {
12
+ return ("\n Received: " +
13
+ JSON.stringify(a, null, 2) +
14
+ "\n Expected: " +
15
+ JSON.stringify(b, null, 2));
16
+ },
17
+ };
18
+ const matcherFns = {};
19
+ for (const name in matcherRegistry) {
20
+ const fn = matcherRegistry[name];
21
+ matcherFns[name] = (...args) => fn.call(ctx, received, ...args);
22
+ }
23
+ return new Proxy(matcherFns, {
24
+ get(target, prop) {
25
+ if (prop === "not")
26
+ return makeExpectation(!isNot);
27
+ if (typeof prop === "string" && !(prop in target)) {
28
+ throw new Error(`Unknown matcher: ${prop}`);
29
+ }
30
+ return target[prop];
31
+ },
32
+ });
33
+ }
34
+ return makeExpectation(false);
35
+ }
36
+ expectFn.extend = extendMatchers;
37
+ return expectFn;
38
+ })();
39
+ Object.defineProperty(expect, "matchers", {
40
+ get() {
41
+ return matcherRegistry;
42
+ },
43
+ });
@@ -0,0 +1,8 @@
1
+ import { type PromisableFn } from "./types";
2
+ type HookFn = PromisableFn<void>;
3
+ export declare function beforeAll(...hooks: HookFn[]): void;
4
+ export declare function afterAll(...hooks: HookFn[]): void;
5
+ export declare function beforeEach(...hooks: HookFn[]): void;
6
+ export declare function afterEach(...hooks: HookFn[]): void;
7
+ export {};
8
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/hooks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,KAAK,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;AAEjC,wBAAgB,SAAS,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAGlD;AAED,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAGjD;AAED,wBAAgB,UAAU,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAGnD;AAED,wBAAgB,SAAS,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAGlD"}
@@ -0,0 +1,18 @@
1
+ import { assertRegisterState } from "./context.js";
2
+ import { getCurrentSuite } from "./suite.js";
3
+ export function beforeAll(...hooks) {
4
+ assertRegisterState("beforeAll");
5
+ getCurrentSuite().beforeAllHooks.push(...hooks);
6
+ }
7
+ export function afterAll(...hooks) {
8
+ assertRegisterState("afterAll");
9
+ getCurrentSuite().afterAllHooks.push(...hooks);
10
+ }
11
+ export function beforeEach(...hooks) {
12
+ assertRegisterState("beforeEach");
13
+ getCurrentSuite().beforeEachHooks.push(...hooks);
14
+ }
15
+ export function afterEach(...hooks) {
16
+ assertRegisterState("afterEach");
17
+ getCurrentSuite().afterEachHooks.push(...hooks);
18
+ }
@@ -0,0 +1,7 @@
1
+ export { beforeEach, afterEach, beforeAll, afterAll } from "./hooks";
2
+ export { defineConfig, type UnriftConfigOptions } from "./utils/defineConfig";
3
+ export { describe, it } from "./interface";
4
+ export { expect, extendMatchers } from "./expect";
5
+ export type { Matchers, ExpectInterface } from "./expect";
6
+ export type { MatcherContext, MatcherFn, MatcherMap } from "./types";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAElD,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { beforeEach, afterEach, beforeAll, afterAll } from "./hooks.js";
2
+ export { defineConfig } from "./utils/defineConfig.js";
3
+ export { describe, it } from "./interface.js";
4
+ export { expect, extendMatchers } from "./expect.js";
@@ -0,0 +1,4 @@
1
+ export declare const injectedDirname: string;
2
+ export declare const injectedFilename: string;
3
+ export declare const injectedRequire: NodeJS.Require;
4
+ //# sourceMappingURL=globals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../../../src/injected/globals.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAiC,CAAC;AAC/D,eAAO,MAAM,eAAe,gBAAiC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import path from "node:path";
3
+ import { createRequire } from "node:module";
4
+ export const injectedDirname = path.dirname(fileURLToPath(import.meta.url));
5
+ export const injectedFilename = fileURLToPath(import.meta.url);
6
+ export const injectedRequire = createRequire(import.meta.url);
@@ -0,0 +1,18 @@
1
+ import { type PromisableFn } from "./types";
2
+ /**
3
+ * @TODO expose test and suite aliases
4
+ */
5
+ type DescribeFn = {
6
+ (description: string, fn: () => void): void;
7
+ only: (description: string, fn: () => void) => void;
8
+ skip: (description: string, fn: () => void) => void;
9
+ };
10
+ type ItFn = {
11
+ (description: string, fn: PromisableFn<void>): void;
12
+ only: (description: string, fn: PromisableFn<void>) => void;
13
+ skip: (description: string, fn: PromisableFn<void>) => void;
14
+ };
15
+ declare const describe: DescribeFn;
16
+ declare const it: ItFn;
17
+ export { describe, it };
18
+ //# sourceMappingURL=interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/interface.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAY,MAAM,SAAS,CAAC;AAEtD;;GAEG;AAEH,KAAK,UAAU,GAAG;IAChB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC5C,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACpD,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF,KAAK,IAAI,GAAG;IACV,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpD,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IAC5D,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;CAC7D,CAAC;AAmBF,QAAA,MAAM,QAAQ,EAAE,UAC8B,CAAC;AAY/C,QAAA,MAAM,EAAE,EAAE,IAAkE,CAAC;AAI7E,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { assertRegisterState, unriftGlobalContext } from "./context.js";
2
+ import { getCurrentSuite, Suite } from "./suite.js";
3
+ import { Test } from "./test.js";
4
+ import { TaskMode } from "./types.js";
5
+ function _describe(description, fn, mode) {
6
+ assertRegisterState("describe");
7
+ const parent = getCurrentSuite();
8
+ const suite = new Suite(description, parent, mode);
9
+ parent.addSuite(suite);
10
+ unriftGlobalContext.currentSuite = suite;
11
+ try {
12
+ fn();
13
+ }
14
+ finally {
15
+ unriftGlobalContext.currentSuite = parent;
16
+ }
17
+ }
18
+ const describe = (description, fn) => _describe(description, fn, TaskMode.Default);
19
+ describe.only = (description, fn) => _describe(description, fn, TaskMode.Only);
20
+ describe.skip = (description, fn) => _describe(description, fn, TaskMode.Skip);
21
+ function _it(description, fn, mode) {
22
+ assertRegisterState("it");
23
+ const test = new Test(description, fn, mode);
24
+ getCurrentSuite().addTest(test);
25
+ }
26
+ const it = (description, fn) => _it(description, fn, TaskMode.Default);
27
+ it.only = (description, fn) => _it(description, fn, TaskMode.Only);
28
+ it.skip = (description, fn) => _it(description, fn, TaskMode.Skip);
29
+ export { describe, it };
@@ -0,0 +1,2 @@
1
+ export declare function ensureInternalMatchers(): void;
2
+ //# sourceMappingURL=matchers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/matchers.ts"],"names":[],"mappings":"AAUA,wBAAgB,sBAAsB,SAMrC"}
@@ -0,0 +1,81 @@
1
+ import { expect } from "./expect.js";
2
+ import { deepEqual } from "./utils/deepEqual.js";
3
+ import { looseEqual } from "./utils/looseEqual.js";
4
+ import { toThrow } from "./utils/toThrow.js";
5
+ let matchersRegistered = false;
6
+ export function ensureInternalMatchers() {
7
+ if (matchersRegistered)
8
+ return;
9
+ registerCoreMatchers();
10
+ matchersRegistered = true;
11
+ }
12
+ function registerCoreMatchers() {
13
+ expect.extend({
14
+ toBe(received, expected) {
15
+ const pass = Object.is(received, expected);
16
+ if (this.isNot ? pass : !pass) {
17
+ throw new Error(this.diff(received, expected));
18
+ }
19
+ },
20
+ toBeDefined(received) {
21
+ const pass = received !== undefined;
22
+ if (this.isNot ? pass : !pass) {
23
+ throw new Error(this.diff(received, "defined value"));
24
+ }
25
+ },
26
+ toBeFalsy(received) {
27
+ const pass = !received;
28
+ if (this.isNot ? pass : !pass) {
29
+ throw new Error(this.diff(received, "falsy value"));
30
+ }
31
+ },
32
+ toBeTruthy(received) {
33
+ const pass = Boolean(received);
34
+ if (this.isNot ? pass : !pass) {
35
+ throw new Error(this.diff(received, "truthy value"));
36
+ }
37
+ },
38
+ toBeNull(received) {
39
+ const pass = received === null;
40
+ if (this.isNot ? pass : !pass) {
41
+ throw new Error(this.diff(received, null));
42
+ }
43
+ },
44
+ toBeUndefined(received) {
45
+ const pass = received === undefined;
46
+ if (this.isNot ? pass : !pass) {
47
+ throw new Error(this.diff(received, undefined));
48
+ }
49
+ },
50
+ toEqual(received, expected) {
51
+ const pass = looseEqual(received, expected);
52
+ if (this.isNot ? pass : !pass) {
53
+ throw new Error(this.diff(received, expected));
54
+ }
55
+ },
56
+ toMatch(received, expected) {
57
+ if (typeof received !== "string") {
58
+ throw new Error(this.diff(received, "Value must be a string to use toMatch()"));
59
+ }
60
+ if (!(typeof expected === "string" || expected instanceof RegExp)) {
61
+ throw new Error(this.diff(expected, "Expected must be a string or RegExp"));
62
+ }
63
+ const pass = typeof expected === "string"
64
+ ? received.includes(expected)
65
+ : expected.test(received);
66
+ if (this.isNot ? pass : !pass)
67
+ throw new Error(this.diff(received, expected));
68
+ },
69
+ toStrictEqual(received, expected) {
70
+ const pass = deepEqual(received, expected);
71
+ if (this.isNot ? pass : !pass) {
72
+ throw new Error(this.diff(received, expected));
73
+ }
74
+ },
75
+ toThrow(received, expected) {
76
+ const { pass, message } = toThrow(received, expected, this.isNot);
77
+ if (!pass)
78
+ throw new Error(message());
79
+ },
80
+ });
81
+ }
@@ -0,0 +1,21 @@
1
+ import { TaskStatus } from "./types";
2
+ type RunEngineOptions = {
3
+ files: string[];
4
+ timeoutMs?: number;
5
+ bail?: boolean;
6
+ matchers?: string[];
7
+ };
8
+ type RunEngineResult = {
9
+ isOnly: boolean;
10
+ timeoutMs?: number;
11
+ bail: boolean;
12
+ results: Array<{
13
+ description: string;
14
+ status: TaskStatus;
15
+ error?: Error;
16
+ durationMs: number;
17
+ }>;
18
+ };
19
+ export declare function runEngine(options: RunEngineOptions): Promise<RunEngineResult>;
20
+ export {};
21
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,UAAU,EAAE,MAAM,SAAS,CAAC;AAG/C,KAAK,gBAAgB,GAAG;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,UAAU,CAAC;QACnB,KAAK,CAAC,EAAE,KAAK,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ,CAAC;AAYF,wBAAsB,SAAS,CAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CA2D1B"}
@@ -0,0 +1,57 @@
1
+ import { clearContext, computeOnlyFlags, rootSuite, Suite } from "./suite.js";
2
+ import { ensureInternalMatchers } from "./matchers.js";
3
+ import { RunState, unriftGlobalContext } from "./context.js";
4
+ import { TaskMode } from "./types.js";
5
+ import { toImportUrl } from "./utils/transform.js";
6
+ async function loadMatcherModules(specifiers) {
7
+ for (const spec of specifiers ?? []) {
8
+ await import(spec);
9
+ }
10
+ }
11
+ function normalizePath(p) {
12
+ return p.replace(/\\/g, "/");
13
+ }
14
+ export async function runEngine(options) {
15
+ const { files } = options;
16
+ clearContext();
17
+ ensureInternalMatchers();
18
+ await loadMatcherModules(options.matchers);
19
+ const timeoutMs = options.timeoutMs;
20
+ const bail = options.bail ?? false;
21
+ unriftGlobalContext.state = RunState.Register;
22
+ try {
23
+ for (const file of files) {
24
+ const fileSuite = new Suite(normalizePath(file), rootSuite, TaskMode.Default);
25
+ rootSuite.addSuite(fileSuite);
26
+ unriftGlobalContext.currentSuite = fileSuite;
27
+ try {
28
+ await import(toImportUrl(file, "bundle-test"));
29
+ }
30
+ catch (err) {
31
+ const error = err instanceof Error ? err : new Error(String(err));
32
+ fileSuite.errors.push({
33
+ label: "import",
34
+ error,
35
+ });
36
+ fileSuite.markSubtreeSkipped();
37
+ }
38
+ finally {
39
+ unriftGlobalContext.currentSuite = rootSuite;
40
+ }
41
+ }
42
+ const isOnly = computeOnlyFlags(rootSuite);
43
+ unriftGlobalContext.state = RunState.Run;
44
+ await rootSuite.run({ timeoutMs, bail }, { bailed: false }, isOnly, false);
45
+ const results = rootSuite.getResults();
46
+ return {
47
+ isOnly,
48
+ timeoutMs,
49
+ bail,
50
+ results,
51
+ };
52
+ }
53
+ finally {
54
+ unriftGlobalContext.state = RunState.Idle;
55
+ unriftGlobalContext.currentSuite = rootSuite;
56
+ }
57
+ }
@@ -0,0 +1,14 @@
1
+ interface RunnerOptions {
2
+ configPath?: string;
3
+ testDir?: string;
4
+ pattern?: RegExp;
5
+ timeoutMs?: number;
6
+ bail?: boolean;
7
+ debug?: boolean;
8
+ list?: boolean;
9
+ json?: boolean;
10
+ cacheClean?: boolean;
11
+ }
12
+ export declare function runTestsCLI(options?: RunnerOptions): Promise<void>;
13
+ export {};
14
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner.ts"],"names":[],"mappings":"AAeA,UAAU,aAAa;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAyGD,wBAAsB,WAAW,CAAC,OAAO,GAAE,aAAkB,iBA4M5D"}