elit 3.6.5 → 3.6.7
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/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/README.md +6 -0
- package/dist/build.cjs +421 -331
- package/dist/build.d.ts +1 -16
- package/dist/build.js +420 -330
- package/dist/build.mjs +420 -330
- package/dist/chokidar.cjs +219 -182
- package/dist/chokidar.d.ts +25 -10
- package/dist/chokidar.js +217 -182
- package/dist/chokidar.mjs +218 -183
- package/dist/cli.cjs +21608 -20241
- package/dist/cli.d.ts +19 -37
- package/dist/cli.mjs +21262 -19910
- package/dist/config.cjs +357 -350
- package/dist/config.d.ts +19 -240
- package/dist/config.js +520 -515
- package/dist/config.mjs +346 -341
- package/dist/contracts-BeW9k0yZ.d.ts +54 -0
- package/dist/contracts-D7KIS-TK.d.ts +36 -0
- package/dist/coverage.cjs +448 -485
- package/dist/coverage.d.ts +13 -59
- package/dist/coverage.js +447 -484
- package/dist/coverage.mjs +447 -484
- package/dist/database.cjs +819 -828
- package/dist/database.d.ts +8 -24
- package/dist/database.js +818 -829
- package/dist/database.mjs +818 -829
- package/dist/desktop-auto-render.cjs +1700 -1522
- package/dist/desktop-auto-render.d.ts +4 -9
- package/dist/desktop-auto-render.js +1695 -1517
- package/dist/desktop-auto-render.mjs +1696 -1518
- package/dist/desktop.cjs +3 -1
- package/dist/desktop.d.ts +4 -1
- package/dist/desktop.js +1 -1
- package/dist/desktop.mjs +1 -1
- package/dist/dev-build.cjs +830 -0
- package/dist/dev-build.d.ts +53 -0
- package/dist/dev-build.js +3318 -0
- package/dist/dev-build.mjs +797 -0
- package/dist/dom.cjs +717 -590
- package/dist/dom.d.ts +2 -15
- package/dist/dom.js +714 -587
- package/dist/dom.mjs +716 -589
- package/dist/el.cjs +62 -52
- package/dist/el.d.ts +5 -10
- package/dist/el.js +60 -52
- package/dist/el.mjs +60 -52
- package/dist/fs.cjs +72 -63
- package/dist/fs.d.ts +22 -19
- package/dist/fs.js +71 -62
- package/dist/fs.mjs +71 -62
- package/dist/hmr.cjs +40 -14
- package/dist/hmr.d.ts +11 -23
- package/dist/hmr.js +38 -14
- package/dist/hmr.mjs +38 -14
- package/dist/http.cjs +251 -99
- package/dist/http.d.ts +38 -104
- package/dist/http.js +249 -99
- package/dist/http.mjs +249 -99
- package/dist/https.cjs +524 -228
- package/dist/https.d.ts +44 -36
- package/dist/https.js +520 -226
- package/dist/https.mjs +522 -228
- package/dist/index.cjs +7502 -7690
- package/dist/index.d.ts +8 -3
- package/dist/index.js +7486 -7676
- package/dist/index.mjs +7497 -7686
- package/dist/mime-types.cjs +10 -4
- package/dist/mime-types.d.ts +8 -11
- package/dist/mime-types.js +9 -3
- package/dist/mime-types.mjs +9 -3
- package/dist/native.cjs +8616 -8869
- package/dist/native.d.ts +7 -8
- package/dist/native.js +8682 -8935
- package/dist/native.mjs +8615 -8868
- package/dist/path.cjs +83 -77
- package/dist/path.d.ts +29 -29
- package/dist/path.js +82 -76
- package/dist/path.mjs +82 -76
- package/dist/pm.cjs +3300 -0
- package/dist/pm.d.ts +256 -0
- package/dist/pm.js +5638 -0
- package/dist/pm.mjs +3196 -0
- package/dist/preview-build.cjs +712 -0
- package/dist/preview-build.d.ts +59 -0
- package/dist/preview-build.js +3194 -0
- package/dist/preview-build.mjs +676 -0
- package/dist/render-context.cjs +13 -2
- package/dist/render-context.d.ts +9 -31
- package/dist/render-context.js +11 -2
- package/dist/render-context.mjs +11 -2
- package/dist/router.cjs +787 -645
- package/dist/router.d.ts +8 -12
- package/dist/router.js +786 -644
- package/dist/router.mjs +786 -644
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/server.cjs +3315 -2603
- package/dist/server.d.ts +49 -4
- package/dist/server.js +7611 -2834
- package/dist/server.mjs +3317 -2607
- package/dist/smtp-server.cjs +128 -0
- package/dist/smtp-server.d.ts +27 -0
- package/dist/smtp-server.js +4199 -0
- package/dist/smtp-server.mjs +100 -0
- package/dist/state-DvEkDehk.d.ts +195 -0
- package/dist/state.cjs +768 -658
- package/dist/state.d.ts +11 -69
- package/dist/state.js +760 -650
- package/dist/state.mjs +767 -657
- package/dist/style.cjs +1011 -968
- package/dist/style.d.ts +13 -127
- package/dist/style.js +1009 -970
- package/dist/style.mjs +1011 -971
- package/dist/test-reporter.cjs +332 -316
- package/dist/test-reporter.d.ts +28 -33
- package/dist/test-reporter.js +328 -312
- package/dist/test-reporter.mjs +328 -312
- package/dist/test-runtime.cjs +927 -968
- package/dist/test-runtime.d.ts +24 -99
- package/dist/test-runtime.js +922 -965
- package/dist/test-runtime.mjs +922 -965
- package/dist/test.cjs +4428 -4273
- package/dist/test.d.ts +2 -8
- package/dist/test.js +4307 -4154
- package/dist/test.mjs +4419 -4267
- package/dist/types-BONVzPtp.d.ts +59 -0
- package/dist/types-BR4wMiVx.d.ts +32 -0
- package/dist/types-C4gKykuG.d.ts +23 -0
- package/dist/types-CIhpN1-K.d.ts +64 -0
- package/dist/types-Ckj8md_j.d.ts +84 -0
- package/dist/types-CpjQTAkX.d.ts +24 -0
- package/dist/types-D0LjrYjS.d.ts +14 -0
- package/dist/types-DAisuVr5.d.ts +75 -0
- package/dist/types-tJn88E1N.d.ts +242 -0
- package/dist/types.d.ts +71 -226
- package/dist/universal.cjs +1 -1
- package/dist/universal.d.ts +1 -5
- package/dist/universal.js +1 -1
- package/dist/universal.mjs +1 -1
- package/dist/websocket-XfyK23zD.d.ts +119 -0
- package/dist/ws.cjs +129 -108
- package/dist/ws.d.ts +21 -131
- package/dist/ws.js +128 -109
- package/dist/ws.mjs +128 -109
- package/dist/wss.cjs +757 -479
- package/dist/wss.d.ts +31 -28
- package/dist/wss.js +755 -479
- package/dist/wss.mjs +758 -482
- package/package.json +16 -1
- package/vendor/epaint-0.31.1/src/image.rs +418 -0
- package/dist/server-CcBFc2F5.d.ts +0 -449
package/dist/test-runtime.mjs
CHANGED
|
@@ -6,10 +6,53 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
// src/test
|
|
10
|
-
|
|
9
|
+
// src/test/runtime/state.ts
|
|
10
|
+
function createRootSuite() {
|
|
11
|
+
return {
|
|
12
|
+
name: "root",
|
|
13
|
+
tests: [],
|
|
14
|
+
suites: [],
|
|
15
|
+
skip: false,
|
|
16
|
+
only: false
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
var runtimeState = {
|
|
20
|
+
currentSuite: createRootSuite(),
|
|
21
|
+
testResults: [],
|
|
22
|
+
hasOnly: false,
|
|
23
|
+
coveredFiles: /* @__PURE__ */ new Set(),
|
|
24
|
+
describePattern: void 0,
|
|
25
|
+
testPattern: void 0,
|
|
26
|
+
currentTestFile: void 0,
|
|
27
|
+
currentSourceMapConsumer: void 0,
|
|
28
|
+
wrapperLineOffset: 0,
|
|
29
|
+
beforeAllHooks: [],
|
|
30
|
+
afterAllHooks: [],
|
|
31
|
+
beforeEachHooks: [],
|
|
32
|
+
afterEachHooks: []
|
|
33
|
+
};
|
|
34
|
+
function resetSuiteState() {
|
|
35
|
+
runtimeState.currentSuite = createRootSuite();
|
|
36
|
+
runtimeState.hasOnly = false;
|
|
37
|
+
}
|
|
38
|
+
function resetHookState() {
|
|
39
|
+
runtimeState.beforeAllHooks = [];
|
|
40
|
+
runtimeState.afterAllHooks = [];
|
|
41
|
+
runtimeState.beforeEachHooks = [];
|
|
42
|
+
runtimeState.afterEachHooks = [];
|
|
43
|
+
}
|
|
44
|
+
function resetSourceMapState() {
|
|
45
|
+
runtimeState.currentSourceMapConsumer = void 0;
|
|
46
|
+
runtimeState.wrapperLineOffset = 0;
|
|
47
|
+
}
|
|
48
|
+
function getCoveredFiles() {
|
|
49
|
+
return runtimeState.coveredFiles;
|
|
50
|
+
}
|
|
51
|
+
function resetCoveredFiles() {
|
|
52
|
+
runtimeState.coveredFiles.clear();
|
|
53
|
+
}
|
|
11
54
|
|
|
12
|
-
// src/runtime.ts
|
|
55
|
+
// src/shares/runtime.ts
|
|
13
56
|
var runtime = (() => {
|
|
14
57
|
if (typeof Deno !== "undefined") return "deno";
|
|
15
58
|
if (typeof Bun !== "undefined") return "bun";
|
|
@@ -19,7 +62,15 @@ var isNode = runtime === "node";
|
|
|
19
62
|
var isBun = runtime === "bun";
|
|
20
63
|
var isDeno = runtime === "deno";
|
|
21
64
|
|
|
22
|
-
// src/fs.ts
|
|
65
|
+
// src/server/fs/node-modules.ts
|
|
66
|
+
var fs;
|
|
67
|
+
var fsPromises;
|
|
68
|
+
if (isNode || isBun) {
|
|
69
|
+
fs = __require("fs");
|
|
70
|
+
fsPromises = __require("fs/promises");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/server/fs/utils.ts
|
|
23
74
|
function parseOptions(options, defaultValue) {
|
|
24
75
|
return typeof options === "string" ? { encoding: options } : options || defaultValue;
|
|
25
76
|
}
|
|
@@ -29,12 +80,37 @@ function decodeContent(content, encoding) {
|
|
|
29
80
|
}
|
|
30
81
|
return Buffer.from(content instanceof ArrayBuffer ? new Uint8Array(content) : content);
|
|
31
82
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
83
|
+
function createStatsFromDenoFileInfo(info) {
|
|
84
|
+
return {
|
|
85
|
+
isFile: () => info.isFile,
|
|
86
|
+
isDirectory: () => info.isDirectory,
|
|
87
|
+
isBlockDevice: () => false,
|
|
88
|
+
isCharacterDevice: () => false,
|
|
89
|
+
isSymbolicLink: () => info.isSymlink || false,
|
|
90
|
+
isFIFO: () => false,
|
|
91
|
+
isSocket: () => false,
|
|
92
|
+
dev: info.dev || 0,
|
|
93
|
+
ino: info.ino || 0,
|
|
94
|
+
mode: info.mode || 0,
|
|
95
|
+
nlink: info.nlink || 1,
|
|
96
|
+
uid: info.uid || 0,
|
|
97
|
+
gid: info.gid || 0,
|
|
98
|
+
rdev: 0,
|
|
99
|
+
size: info.size,
|
|
100
|
+
blksize: info.blksize || 4096,
|
|
101
|
+
blocks: info.blocks || Math.ceil(info.size / 512),
|
|
102
|
+
atimeMs: info.atime?.getTime() || Date.now(),
|
|
103
|
+
mtimeMs: info.mtime?.getTime() || Date.now(),
|
|
104
|
+
ctimeMs: info.birthtime?.getTime() || Date.now(),
|
|
105
|
+
birthtimeMs: info.birthtime?.getTime() || Date.now(),
|
|
106
|
+
atime: info.atime || /* @__PURE__ */ new Date(),
|
|
107
|
+
mtime: info.mtime || /* @__PURE__ */ new Date(),
|
|
108
|
+
ctime: info.birthtime || /* @__PURE__ */ new Date(),
|
|
109
|
+
birthtime: info.birthtime || /* @__PURE__ */ new Date()
|
|
110
|
+
};
|
|
37
111
|
}
|
|
112
|
+
|
|
113
|
+
// src/server/fs/file-ops.ts
|
|
38
114
|
async function readFile(path, options) {
|
|
39
115
|
const opts = parseOptions(options, {});
|
|
40
116
|
if (isNode || isBun) {
|
|
@@ -72,421 +148,460 @@ function statSync(path) {
|
|
|
72
148
|
}
|
|
73
149
|
throw new Error("Unsupported runtime");
|
|
74
150
|
}
|
|
75
|
-
function createStatsFromDenoFileInfo(info) {
|
|
76
|
-
return {
|
|
77
|
-
isFile: () => info.isFile,
|
|
78
|
-
isDirectory: () => info.isDirectory,
|
|
79
|
-
isBlockDevice: () => false,
|
|
80
|
-
isCharacterDevice: () => false,
|
|
81
|
-
isSymbolicLink: () => info.isSymlink || false,
|
|
82
|
-
isFIFO: () => false,
|
|
83
|
-
isSocket: () => false,
|
|
84
|
-
dev: info.dev || 0,
|
|
85
|
-
ino: info.ino || 0,
|
|
86
|
-
mode: info.mode || 0,
|
|
87
|
-
nlink: info.nlink || 1,
|
|
88
|
-
uid: info.uid || 0,
|
|
89
|
-
gid: info.gid || 0,
|
|
90
|
-
rdev: 0,
|
|
91
|
-
size: info.size,
|
|
92
|
-
blksize: info.blksize || 4096,
|
|
93
|
-
blocks: info.blocks || Math.ceil(info.size / 512),
|
|
94
|
-
atimeMs: info.atime?.getTime() || Date.now(),
|
|
95
|
-
mtimeMs: info.mtime?.getTime() || Date.now(),
|
|
96
|
-
ctimeMs: info.birthtime?.getTime() || Date.now(),
|
|
97
|
-
birthtimeMs: info.birthtime?.getTime() || Date.now(),
|
|
98
|
-
atime: info.atime || /* @__PURE__ */ new Date(),
|
|
99
|
-
mtime: info.mtime || /* @__PURE__ */ new Date(),
|
|
100
|
-
ctime: info.birthtime || /* @__PURE__ */ new Date(),
|
|
101
|
-
birthtime: info.birthtime || /* @__PURE__ */ new Date()
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
151
|
|
|
105
|
-
// src/
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
function getCwd() {
|
|
110
|
-
if (isNode || isBun) {
|
|
111
|
-
return process.cwd();
|
|
112
|
-
} else if (isDeno) {
|
|
113
|
-
return Deno.cwd();
|
|
114
|
-
}
|
|
115
|
-
return "/";
|
|
116
|
-
}
|
|
117
|
-
function findLastSeparator(path) {
|
|
118
|
-
return Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
119
|
-
}
|
|
120
|
-
function createPathOps(isWin) {
|
|
121
|
-
return {
|
|
122
|
-
sep: getSeparator(isWin),
|
|
123
|
-
delimiter: isWin ? ";" : ":",
|
|
124
|
-
normalize: (path) => normalizePath(path, isWin),
|
|
125
|
-
join: (...paths) => joinPaths(paths, isWin),
|
|
126
|
-
resolve: (...paths) => resolvePaths(paths, isWin),
|
|
127
|
-
isAbsolute: (path) => isWin ? isAbsoluteWin(path) : isAbsolutePosix(path),
|
|
128
|
-
relative: (from, to) => relativePath(from, to, isWin),
|
|
129
|
-
dirname: (path) => getDirname(path, isWin),
|
|
130
|
-
basename: (path, ext) => getBasename(path, ext, isWin),
|
|
131
|
-
extname: (path) => getExtname(path),
|
|
132
|
-
parse: (path) => parsePath(path, isWin),
|
|
133
|
-
format: (pathObject) => formatPath(pathObject, isWin)
|
|
134
|
-
};
|
|
152
|
+
// src/test/runtime/assertion-context.ts
|
|
153
|
+
function getAssertionMethod(stack) {
|
|
154
|
+
const assertionMatch = stack.match(/at _?Expect\.(\w+)/);
|
|
155
|
+
return assertionMatch ? assertionMatch[1] : void 0;
|
|
135
156
|
}
|
|
136
|
-
function
|
|
137
|
-
|
|
157
|
+
function getTargetPattern(assertionMethod) {
|
|
158
|
+
if (assertionMethod === "toEqual") return ".toEqual(";
|
|
159
|
+
if (assertionMethod === "toStrictEqual") return ".toStrictEqual(";
|
|
160
|
+
if (assertionMethod === "toMatch") return ".toMatch(";
|
|
161
|
+
if (assertionMethod === "toContain") return ".toContain(";
|
|
162
|
+
if (assertionMethod === "toHaveLength") return ".toHaveLength(";
|
|
163
|
+
if (assertionMethod === "toBeDefined") return ".toBeDefined(";
|
|
164
|
+
if (assertionMethod === "toBeNull") return ".toBeNull(";
|
|
165
|
+
if (assertionMethod === "toBeUndefined") return ".toBeUndefined(";
|
|
166
|
+
if (assertionMethod === "toBeTruthy") return ".toBeTruthy(";
|
|
167
|
+
if (assertionMethod === "toBeFalsy") return ".toBeFalsy(";
|
|
168
|
+
if (assertionMethod === "toThrow") return ".toThrow(";
|
|
169
|
+
if (assertionMethod === "toBeGreaterThan") return ".toBeGreaterThan(";
|
|
170
|
+
if (assertionMethod === "toBeGreaterThanOrEqual") return ".toBeGreaterThanOrEqual(";
|
|
171
|
+
if (assertionMethod === "toBeLessThan") return ".toBeLessThan(";
|
|
172
|
+
if (assertionMethod === "toBeLessThanOrEqual") return ".toBeLessThanOrEqual(";
|
|
173
|
+
return ".toBe(";
|
|
138
174
|
}
|
|
139
|
-
function
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return true;
|
|
145
|
-
}
|
|
146
|
-
if (code >= 65 && code <= 90 || code >= 97 && code <= 122) {
|
|
147
|
-
if (len > 2 && path.charCodeAt(1) === 58) {
|
|
148
|
-
const code2 = path.charCodeAt(2);
|
|
149
|
-
if (code2 === 47 || code2 === 92) {
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
175
|
+
function readSourceLines(filePath) {
|
|
176
|
+
try {
|
|
177
|
+
let sourceCode = readFileSync(filePath, "utf-8");
|
|
178
|
+
if (Buffer.isBuffer(sourceCode)) {
|
|
179
|
+
sourceCode = sourceCode.toString("utf-8");
|
|
152
180
|
}
|
|
181
|
+
return sourceCode.split("\n");
|
|
182
|
+
} catch {
|
|
183
|
+
return void 0;
|
|
153
184
|
}
|
|
154
|
-
return false;
|
|
155
185
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
186
|
+
function resolveMappedLine(lineNumber, sourceLines, assertionMethod) {
|
|
187
|
+
const targetPattern = getTargetPattern(assertionMethod);
|
|
188
|
+
if (lineNumber <= 0 || lineNumber > sourceLines.length) {
|
|
189
|
+
return lineNumber;
|
|
190
|
+
}
|
|
191
|
+
if (sourceLines[lineNumber - 1].includes(targetPattern)) {
|
|
192
|
+
return lineNumber;
|
|
193
|
+
}
|
|
194
|
+
for (let index = 1; index <= 3; index++) {
|
|
195
|
+
const searchLine = lineNumber - index;
|
|
196
|
+
if (searchLine > 0 && searchLine <= sourceLines.length && sourceLines[searchLine - 1].includes(targetPattern)) {
|
|
197
|
+
return searchLine;
|
|
198
|
+
}
|
|
161
199
|
}
|
|
162
|
-
return
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
const
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (i === 0 && isAbsolute) result.push("");
|
|
178
|
-
continue;
|
|
200
|
+
return lineNumber;
|
|
201
|
+
}
|
|
202
|
+
function resolveAssertionContext(stack) {
|
|
203
|
+
if (!stack) {
|
|
204
|
+
return {};
|
|
205
|
+
}
|
|
206
|
+
const assertionMethod = getAssertionMethod(stack);
|
|
207
|
+
const stackFrames = [];
|
|
208
|
+
for (const line of stack.split("\n")) {
|
|
209
|
+
const match = line.match(/<anonymous>:([0-9]+):([0-9]+)/);
|
|
210
|
+
if (match) {
|
|
211
|
+
stackFrames.push({
|
|
212
|
+
line: parseInt(match[1], 10),
|
|
213
|
+
column: parseInt(match[2], 10)
|
|
214
|
+
});
|
|
179
215
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
216
|
+
}
|
|
217
|
+
const targetFrame = stackFrames.length > 1 ? stackFrames[1] : stackFrames[0];
|
|
218
|
+
let lineNumber;
|
|
219
|
+
if (targetFrame && runtimeState.currentSourceMapConsumer) {
|
|
220
|
+
try {
|
|
221
|
+
const transpiledLine = targetFrame.line - runtimeState.wrapperLineOffset;
|
|
222
|
+
const originalPosition = runtimeState.currentSourceMapConsumer.originalPositionFor({
|
|
223
|
+
line: transpiledLine,
|
|
224
|
+
column: targetFrame.column
|
|
225
|
+
});
|
|
226
|
+
if (originalPosition.line !== null) {
|
|
227
|
+
lineNumber = originalPosition.line;
|
|
228
|
+
} else {
|
|
229
|
+
const posWithoutColumn = runtimeState.currentSourceMapConsumer.originalPositionFor({
|
|
230
|
+
line: transpiledLine,
|
|
231
|
+
column: 0
|
|
232
|
+
});
|
|
233
|
+
if (posWithoutColumn.line !== null) {
|
|
234
|
+
lineNumber = posWithoutColumn.line;
|
|
235
|
+
} else {
|
|
236
|
+
const lineMappings = [];
|
|
237
|
+
runtimeState.currentSourceMapConsumer.eachMapping((mapping) => {
|
|
238
|
+
if (mapping.originalLine !== null) {
|
|
239
|
+
lineMappings.push({
|
|
240
|
+
line: mapping.originalLine,
|
|
241
|
+
distance: Math.abs(mapping.generatedLine - transpiledLine)
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
if (lineMappings.length > 0) {
|
|
246
|
+
lineMappings.sort((left, right) => left.distance - right.distance);
|
|
247
|
+
lineNumber = lineMappings[0].line;
|
|
248
|
+
}
|
|
184
249
|
}
|
|
185
|
-
} else if (!isAbsolute) {
|
|
186
|
-
result.push("..");
|
|
187
250
|
}
|
|
188
|
-
}
|
|
189
|
-
result.push(part);
|
|
251
|
+
} catch {
|
|
190
252
|
}
|
|
191
253
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return isAbsolute ? separator : ".";
|
|
254
|
+
if (!runtimeState.currentTestFile || !lineNumber) {
|
|
255
|
+
return { lineNumber };
|
|
195
256
|
}
|
|
196
|
-
|
|
197
|
-
|
|
257
|
+
const sourceLines = readSourceLines(runtimeState.currentTestFile);
|
|
258
|
+
if (!sourceLines) {
|
|
259
|
+
return { lineNumber };
|
|
198
260
|
}
|
|
199
|
-
|
|
261
|
+
lineNumber = resolveMappedLine(lineNumber, sourceLines, assertionMethod);
|
|
262
|
+
const codeLine = lineNumber > 0 && lineNumber <= sourceLines.length ? sourceLines[lineNumber - 1] : void 0;
|
|
263
|
+
return {
|
|
264
|
+
lineNumber,
|
|
265
|
+
codeSnippet: codeLine ? codeLine.trim() : void 0
|
|
266
|
+
};
|
|
200
267
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
joined += separator + path;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
268
|
+
|
|
269
|
+
// src/test/runtime/expect.ts
|
|
270
|
+
var AssertionError = class extends Error {
|
|
271
|
+
constructor(message, filePath, lineNumber, columnNumber, codeSnippet) {
|
|
272
|
+
super(message);
|
|
273
|
+
this.filePath = filePath;
|
|
274
|
+
this.lineNumber = lineNumber;
|
|
275
|
+
this.columnNumber = columnNumber;
|
|
276
|
+
this.codeSnippet = codeSnippet;
|
|
277
|
+
this.name = "AssertionError";
|
|
214
278
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
279
|
+
};
|
|
280
|
+
var Expect = class _Expect {
|
|
281
|
+
constructor(actual, isNot = false, isAsync = false) {
|
|
282
|
+
this.actual = actual;
|
|
283
|
+
this.isNot = isNot;
|
|
284
|
+
this.isAsync = isAsync;
|
|
285
|
+
this._not = null;
|
|
286
|
+
this._resolves = null;
|
|
287
|
+
this._rejects = null;
|
|
288
|
+
}
|
|
289
|
+
get not() {
|
|
290
|
+
if (!this._not) {
|
|
291
|
+
this._not = new _Expect(this.actual, !this.isNot, false);
|
|
227
292
|
}
|
|
293
|
+
return this._not;
|
|
228
294
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
295
|
+
get resolves() {
|
|
296
|
+
if (!this._resolves) {
|
|
297
|
+
this._resolves = new _Expect(this.actual, this.isNot, true);
|
|
298
|
+
}
|
|
299
|
+
return this._resolves;
|
|
232
300
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
from = resolvePaths([from], isWin);
|
|
237
|
-
to = resolvePaths([to], isWin);
|
|
238
|
-
if (from === to) return "";
|
|
239
|
-
const separator = getSeparator(isWin);
|
|
240
|
-
const fromParts = from.split(separator).filter((p) => p.length > 0);
|
|
241
|
-
const toParts = to.split(separator).filter((p) => p.length > 0);
|
|
242
|
-
let commonLength = 0;
|
|
243
|
-
const minLength = Math.min(fromParts.length, toParts.length);
|
|
244
|
-
for (let i = 0; i < minLength; i++) {
|
|
245
|
-
if (fromParts[i] === toParts[i]) {
|
|
246
|
-
commonLength++;
|
|
247
|
-
} else {
|
|
248
|
-
break;
|
|
301
|
+
get rejects() {
|
|
302
|
+
if (!this._rejects) {
|
|
303
|
+
this._rejects = new _Expect(this.actual, this.isNot, true);
|
|
249
304
|
}
|
|
305
|
+
return this._rejects;
|
|
250
306
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
307
|
+
assertCondition(condition, message, showExpectedReceived = true, expectedDisplay, callerStack) {
|
|
308
|
+
if (this.isNot) {
|
|
309
|
+
condition = !condition;
|
|
310
|
+
}
|
|
311
|
+
if (!condition) {
|
|
312
|
+
let errorMessage = message;
|
|
313
|
+
if (showExpectedReceived) {
|
|
314
|
+
const expectedValue = expectedDisplay ?? this.stringify(this.expected ?? "truthy");
|
|
315
|
+
errorMessage += `
|
|
316
|
+
Expected: ${expectedValue}
|
|
317
|
+
Received: ${this.stringify(this.actual)}`;
|
|
318
|
+
}
|
|
319
|
+
const stack = callerStack || new Error().stack;
|
|
320
|
+
const { lineNumber, codeSnippet } = resolveAssertionContext(stack);
|
|
321
|
+
throw new AssertionError(errorMessage, runtimeState.currentTestFile, lineNumber, void 0, codeSnippet);
|
|
322
|
+
}
|
|
255
323
|
}
|
|
256
|
-
|
|
257
|
-
|
|
324
|
+
stringify(value) {
|
|
325
|
+
if (value === void 0) return "undefined";
|
|
326
|
+
if (value === null) return "null";
|
|
327
|
+
if (typeof value === "string") return `"${value}"`;
|
|
328
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
329
|
+
if (typeof value === "function") return "Function";
|
|
330
|
+
if (Array.isArray(value)) return `[${value.map((item) => this.stringify(item)).join(", ")}]`;
|
|
331
|
+
if (typeof value === "object") {
|
|
332
|
+
const keys = Object.keys(value);
|
|
333
|
+
if (keys.length === 0) return "{}";
|
|
334
|
+
return `{ ${keys.slice(0, 3).map((key) => `${key}: ${this.stringify(value[key])}`).join(", ")}${keys.length > 3 ? "..." : ""} }`;
|
|
335
|
+
}
|
|
336
|
+
return String(value);
|
|
258
337
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const normalized = normalizePath(path, isWin);
|
|
265
|
-
const lastSepIndex = normalized.lastIndexOf(separator);
|
|
266
|
-
if (lastSepIndex === -1) return ".";
|
|
267
|
-
if (lastSepIndex === 0) return separator;
|
|
268
|
-
return normalized.slice(0, lastSepIndex);
|
|
269
|
-
}
|
|
270
|
-
function getBasename(path, ext, isWin) {
|
|
271
|
-
if (path.length === 0) return "";
|
|
272
|
-
const lastSepIndex = isWin ? findLastSeparator(path) : path.lastIndexOf("/");
|
|
273
|
-
let base = lastSepIndex === -1 ? path : path.slice(lastSepIndex + 1);
|
|
274
|
-
if (ext && base.endsWith(ext)) {
|
|
275
|
-
base = base.slice(0, base.length - ext.length);
|
|
276
|
-
}
|
|
277
|
-
return base;
|
|
278
|
-
}
|
|
279
|
-
function getExtname(path) {
|
|
280
|
-
const lastDotIndex = path.lastIndexOf(".");
|
|
281
|
-
const lastSepIndex = findLastSeparator(path);
|
|
282
|
-
if (lastDotIndex === -1 || lastDotIndex < lastSepIndex || lastDotIndex === path.length - 1) {
|
|
283
|
-
return "";
|
|
284
|
-
}
|
|
285
|
-
return path.slice(lastDotIndex);
|
|
286
|
-
}
|
|
287
|
-
function parsePath(path, isWin) {
|
|
288
|
-
let root = "";
|
|
289
|
-
if (isWin) {
|
|
290
|
-
if (path.length >= 2 && path[1] === ":") {
|
|
291
|
-
root = path.slice(0, 2);
|
|
292
|
-
if (path.length > 2 && (path[2] === "\\" || path[2] === "/")) {
|
|
293
|
-
root += "\\";
|
|
338
|
+
async handleAsyncAssertion(value, assertion) {
|
|
339
|
+
try {
|
|
340
|
+
const resolvedValue = await this.actual;
|
|
341
|
+
if (this.isNot) {
|
|
342
|
+
throw new Error("Promise resolved when it should have rejected");
|
|
294
343
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
344
|
+
assertion(resolvedValue);
|
|
345
|
+
return Promise.resolve(resolvedValue);
|
|
346
|
+
} catch (error) {
|
|
347
|
+
if (this.isNot) {
|
|
348
|
+
return Promise.resolve(void 0);
|
|
349
|
+
}
|
|
350
|
+
if (typeof value === "string") {
|
|
351
|
+
this.assertCondition(
|
|
352
|
+
error.message?.includes(value),
|
|
353
|
+
`Expected error message to include "${value}"`
|
|
354
|
+
);
|
|
355
|
+
} else if (value instanceof RegExp) {
|
|
356
|
+
this.assertCondition(
|
|
357
|
+
value.test(error.message),
|
|
358
|
+
`Expected error message to match ${value}`
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
return Promise.resolve(void 0);
|
|
301
362
|
}
|
|
302
363
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// src/test-runtime.ts
|
|
322
|
-
import { SourceMapConsumer } from "source-map";
|
|
323
|
-
function escapeRegex(str) {
|
|
324
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
325
|
-
}
|
|
326
|
-
var AssertionError = class extends Error {
|
|
327
|
-
constructor(message, filePath, lineNumber, columnNumber, codeSnippet) {
|
|
328
|
-
super(message);
|
|
329
|
-
this.filePath = filePath;
|
|
330
|
-
this.lineNumber = lineNumber;
|
|
331
|
-
this.columnNumber = columnNumber;
|
|
332
|
-
this.codeSnippet = codeSnippet;
|
|
333
|
-
this.name = "AssertionError";
|
|
364
|
+
toBe(value) {
|
|
365
|
+
const stack = new Error().stack;
|
|
366
|
+
if (this.isAsync) {
|
|
367
|
+
return this.handleAsyncAssertion(value, (actual) => {
|
|
368
|
+
this.expected = value;
|
|
369
|
+
this.assertCondition(actual === value, "Expected values to be strictly equal (using ===)", false, void 0, stack);
|
|
370
|
+
if (typeof actual !== typeof value) {
|
|
371
|
+
throw new Error(`Types don't match: expected ${typeof value} but got ${typeof actual}`);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
this.expected = value;
|
|
376
|
+
this.assertCondition(this.actual === value, "Expected values to be strictly equal (using ===)", true, void 0, stack);
|
|
377
|
+
if (typeof this.actual !== typeof value) {
|
|
378
|
+
throw new Error(`Types don't match: expected ${typeof value} but got ${typeof this.actual}`);
|
|
379
|
+
}
|
|
334
380
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
var testPattern = void 0;
|
|
348
|
-
var currentTestFile = void 0;
|
|
349
|
-
var currentSourceMapConsumer = void 0;
|
|
350
|
-
var wrapperLineOffset = 0;
|
|
351
|
-
var TEST_MODULE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".json"];
|
|
352
|
-
function resolveTestLoader(filePath) {
|
|
353
|
-
return /\.(?:ts|tsx|mts|cts)$/i.test(filePath) ? "ts" : "js";
|
|
354
|
-
}
|
|
355
|
-
function createTestTransformOptions(filePath, format, sourcemap) {
|
|
356
|
-
return {
|
|
357
|
-
loader: resolveTestLoader(filePath),
|
|
358
|
-
format,
|
|
359
|
-
sourcemap,
|
|
360
|
-
sourcefile: filePath,
|
|
361
|
-
target: "es2020",
|
|
362
|
-
tsconfigRaw: {
|
|
363
|
-
compilerOptions: {
|
|
364
|
-
jsx: "react",
|
|
365
|
-
jsxFactory: "h",
|
|
366
|
-
jsxFragmentFactory: "Fragment"
|
|
381
|
+
toEqual(value) {
|
|
382
|
+
const stack = new Error().stack;
|
|
383
|
+
this.expected = value;
|
|
384
|
+
const isEqual = (left, right) => {
|
|
385
|
+
if (left === right) return true;
|
|
386
|
+
if (left == null || right == null) return left === right;
|
|
387
|
+
if (typeof left !== typeof right) return false;
|
|
388
|
+
if (typeof left !== "object") return left === right;
|
|
389
|
+
if (Array.isArray(left) !== Array.isArray(right)) return false;
|
|
390
|
+
if (Array.isArray(left)) {
|
|
391
|
+
if (left.length !== right.length) return false;
|
|
392
|
+
return left.every((item, index) => isEqual(item, right[index]));
|
|
367
393
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return basePath;
|
|
394
|
+
const keysLeft = Object.keys(left);
|
|
395
|
+
const keysRight = Object.keys(right);
|
|
396
|
+
if (keysLeft.length !== keysRight.length) return false;
|
|
397
|
+
return keysLeft.every((key) => isEqual(left[key], right[key]));
|
|
398
|
+
};
|
|
399
|
+
this.assertCondition(isEqual(this.actual, value), "Expected values to be deeply equal", false, void 0, stack);
|
|
375
400
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
401
|
+
toBeTruthy() {
|
|
402
|
+
this.assertCondition(!!this.actual, "Expected value to be truthy", false, void 0, new Error().stack);
|
|
403
|
+
}
|
|
404
|
+
toBeFalsy() {
|
|
405
|
+
this.assertCondition(!this.actual, "Expected value to be falsy", false, void 0, new Error().stack);
|
|
406
|
+
}
|
|
407
|
+
toBeNull() {
|
|
408
|
+
this.assertCondition(this.actual === null, "Expected value to be null", false, void 0, new Error().stack);
|
|
409
|
+
}
|
|
410
|
+
toBeUndefined() {
|
|
411
|
+
this.assertCondition(this.actual === void 0, "Expected value to be undefined", false, void 0, new Error().stack);
|
|
412
|
+
}
|
|
413
|
+
toBeDefined() {
|
|
414
|
+
this.assertCondition(this.actual !== void 0, "Expected value to be defined", false, void 0, new Error().stack);
|
|
415
|
+
}
|
|
416
|
+
toBeGreaterThan(value) {
|
|
417
|
+
const stack = new Error().stack;
|
|
418
|
+
this.expected = value;
|
|
419
|
+
this.assertCondition(typeof this.actual === "number" && this.actual > value, `Expected ${this.stringify(this.actual)} to be greater than ${value}`, true, String(value), stack);
|
|
420
|
+
}
|
|
421
|
+
toBeGreaterThanOrEqual(value) {
|
|
422
|
+
const stack = new Error().stack;
|
|
423
|
+
this.expected = value;
|
|
424
|
+
this.assertCondition(typeof this.actual === "number" && this.actual >= value, `Expected ${this.stringify(this.actual)} to be greater than or equal to ${value}`, true, `${value}`, stack);
|
|
425
|
+
}
|
|
426
|
+
toBeLessThan(value) {
|
|
427
|
+
const stack = new Error().stack;
|
|
428
|
+
this.expected = value;
|
|
429
|
+
this.assertCondition(typeof this.actual === "number" && this.actual < value, `Expected ${this.stringify(this.actual)} to be less than ${value}`, true, String(value), stack);
|
|
430
|
+
}
|
|
431
|
+
toBeLessThanOrEqual(value) {
|
|
432
|
+
const stack = new Error().stack;
|
|
433
|
+
this.expected = value;
|
|
434
|
+
this.assertCondition(typeof this.actual === "number" && this.actual <= value, `Expected ${this.stringify(this.actual)} to be less than or equal to ${value}`, true, `${value}`, stack);
|
|
435
|
+
}
|
|
436
|
+
toContain(value) {
|
|
437
|
+
const stack = new Error().stack;
|
|
438
|
+
this.expected = value;
|
|
439
|
+
if (typeof this.actual === "string") {
|
|
440
|
+
this.assertCondition(this.actual.includes(value), `Expected "${this.actual}" to contain "${value}"`, false, void 0, stack);
|
|
441
|
+
} else if (Array.isArray(this.actual)) {
|
|
442
|
+
this.assertCondition(this.actual.some((item) => this.deepEqual(item, value)), `Expected array to contain ${this.stringify(value)}`, false, void 0, stack);
|
|
443
|
+
} else {
|
|
444
|
+
throw new Error(`toContain expects string or array, got ${typeof this.actual}`);
|
|
380
445
|
}
|
|
381
446
|
}
|
|
382
|
-
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
447
|
+
toHaveLength(length) {
|
|
448
|
+
const stack = new Error().stack;
|
|
449
|
+
this.expected = length;
|
|
450
|
+
const actualLength = this.actual?.length;
|
|
451
|
+
this.assertCondition(actualLength === length, `Expected length to be ${length}, but got ${actualLength}`, false, void 0, stack);
|
|
452
|
+
}
|
|
453
|
+
toThrow(error) {
|
|
454
|
+
if (this.isAsync) {
|
|
455
|
+
return this.handleAsyncAssertion(error, () => {
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
let threw = false;
|
|
459
|
+
let thrownError = null;
|
|
460
|
+
try {
|
|
461
|
+
if (typeof this.actual === "function") {
|
|
462
|
+
this.actual();
|
|
398
463
|
}
|
|
464
|
+
} catch (caughtError) {
|
|
465
|
+
threw = true;
|
|
466
|
+
thrownError = caughtError;
|
|
399
467
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (
|
|
403
|
-
|
|
468
|
+
this.assertCondition(threw, "Expected function to throw an error");
|
|
469
|
+
if (error) {
|
|
470
|
+
if (typeof error === "string") {
|
|
471
|
+
this.assertCondition(thrownError.message.includes(error), `Expected error message to include "${error}"`);
|
|
472
|
+
} else if (error instanceof RegExp) {
|
|
473
|
+
this.assertCondition(error.test(thrownError.message), `Expected error message to match ${error}`);
|
|
404
474
|
}
|
|
405
475
|
}
|
|
406
476
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const basePath = specifier.startsWith(".") ? nodePath.resolve(dirname(fromFilePath), specifier) : specifier;
|
|
415
|
-
return resolveExistingTestModulePath(basePath);
|
|
416
|
-
}
|
|
417
|
-
function shouldTranspileTestModule(filePath) {
|
|
418
|
-
return /\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs)$/i.test(filePath);
|
|
419
|
-
}
|
|
420
|
-
function createTestModuleRequire(fromFilePath, moduleCache) {
|
|
421
|
-
return (specifier) => {
|
|
422
|
-
if (specifier.startsWith("elit/") || specifier === "elit") {
|
|
423
|
-
return __require(specifier);
|
|
424
|
-
}
|
|
425
|
-
const resolvedPath = resolveTestModulePath(fromFilePath, specifier);
|
|
426
|
-
if (resolvedPath === specifier) {
|
|
427
|
-
return __require(specifier);
|
|
477
|
+
toMatch(pattern) {
|
|
478
|
+
this.expected = pattern;
|
|
479
|
+
const text = String(this.actual);
|
|
480
|
+
if (pattern instanceof RegExp) {
|
|
481
|
+
this.assertCondition(pattern.test(text), `Expected "${text}" to match ${pattern}`);
|
|
482
|
+
} else {
|
|
483
|
+
this.assertCondition(text.includes(pattern), `Expected "${text}" to contain "${pattern}"`);
|
|
428
484
|
}
|
|
429
|
-
|
|
430
|
-
|
|
485
|
+
}
|
|
486
|
+
toBeInstanceOf(classType) {
|
|
487
|
+
this.expected = classType;
|
|
488
|
+
this.assertCondition(this.actual instanceof classType, `Expected value to be instance of ${classType.name}`);
|
|
489
|
+
}
|
|
490
|
+
toHaveProperty(path, value) {
|
|
491
|
+
const keys = Array.isArray(path) ? path : path.split(".");
|
|
492
|
+
let object = this.actual;
|
|
493
|
+
for (const key of keys) {
|
|
494
|
+
if (object == null || !Object.hasOwnProperty.call(object, key)) {
|
|
495
|
+
throw new Error(`Expected object to have property "${path}"`);
|
|
496
|
+
}
|
|
497
|
+
object = object[key];
|
|
431
498
|
}
|
|
432
|
-
if (
|
|
433
|
-
|
|
499
|
+
if (value !== void 0) {
|
|
500
|
+
this.assertCondition(this.deepEqual(object, value), `Expected property "${path}" to equal ${this.stringify(value)}`);
|
|
434
501
|
}
|
|
435
|
-
return loadTranspiledTestModule(resolvedPath, moduleCache);
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
function loadTranspiledTestModule(modulePath, moduleCache) {
|
|
439
|
-
const cached = moduleCache.get(modulePath);
|
|
440
|
-
if (cached) {
|
|
441
|
-
return cached.exports;
|
|
442
502
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
try {
|
|
446
|
-
transpiled = transformSync(source, createTestTransformOptions(modulePath, "cjs", false));
|
|
447
|
-
} catch (error) {
|
|
448
|
-
throw new Error(`Failed to transpile test dependency ${modulePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
503
|
+
toBeCalled() {
|
|
504
|
+
this.assertCondition(this.actual._isMock && this.actual._calls.length > 0, "Expected mock function to have been called");
|
|
449
505
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
moduleCache.set(modulePath, moduleRecord);
|
|
453
|
-
try {
|
|
454
|
-
const fn = new Function("module", "exports", "require", "__filename", "__dirname", transpiled.code);
|
|
455
|
-
const requireFn = createTestModuleRequire(modulePath, moduleCache);
|
|
456
|
-
fn(moduleObj, moduleObj.exports, requireFn, modulePath, dirname(modulePath));
|
|
457
|
-
} catch (error) {
|
|
458
|
-
throw new Error(`Failed to execute test dependency ${modulePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
506
|
+
toBeCalledTimes(times) {
|
|
507
|
+
this.assertCondition(this.actual._isMock && this.actual._calls.length === times, `Expected mock to be called ${times} times, but was called ${this.actual._calls?.length || 0} times`);
|
|
459
508
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
coveredFiles.add(modulePath);
|
|
509
|
+
toBeCalledWith(...args) {
|
|
510
|
+
this.assertCondition(this.actual._isMock && this.actual._calls.some((call) => this.deepEqual(call, args)), `Expected mock to be called with ${this.stringify(args)}`);
|
|
463
511
|
}
|
|
464
|
-
|
|
512
|
+
lastReturnedWith(value) {
|
|
513
|
+
const lastResult = this.actual._results?.[this.actual._results.length - 1];
|
|
514
|
+
this.assertCondition(lastResult && this.deepEqual(lastResult.value, value), `Expected last call to return ${this.stringify(value)}`);
|
|
515
|
+
}
|
|
516
|
+
deepEqual(left, right) {
|
|
517
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
function expect(actual) {
|
|
521
|
+
return new Expect(actual);
|
|
465
522
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
523
|
+
|
|
524
|
+
// src/test/runtime/hooks.ts
|
|
525
|
+
var beforeAll = (fn) => runtimeState.beforeAllHooks.push(fn);
|
|
526
|
+
var afterAll = (fn) => runtimeState.afterAllHooks.push(fn);
|
|
527
|
+
var beforeEach = (fn) => runtimeState.beforeEachHooks.push(fn);
|
|
528
|
+
var afterEach = (fn) => runtimeState.afterEachHooks.push(fn);
|
|
529
|
+
|
|
530
|
+
// src/test/runtime/mocks.ts
|
|
531
|
+
function createMockFunction() {
|
|
532
|
+
const mock = function(...args) {
|
|
533
|
+
mock._calls.push(args);
|
|
534
|
+
try {
|
|
535
|
+
const result = mock._implementation ? mock._implementation(...args) : void 0;
|
|
536
|
+
mock._results.push({ type: "return", value: result });
|
|
537
|
+
return result;
|
|
538
|
+
} catch (error) {
|
|
539
|
+
mock._results.push({ type: "throw", value: error });
|
|
540
|
+
throw error;
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
mock._isMock = true;
|
|
544
|
+
mock._calls = [];
|
|
545
|
+
mock._results = [];
|
|
546
|
+
mock._implementation = null;
|
|
547
|
+
mock.mockImplementation = function(fn) {
|
|
548
|
+
mock._implementation = fn;
|
|
549
|
+
return mock;
|
|
550
|
+
};
|
|
551
|
+
mock.mockReturnValue = function(value) {
|
|
552
|
+
mock._implementation = (() => value);
|
|
553
|
+
return mock;
|
|
554
|
+
};
|
|
555
|
+
mock.mockResolvedValue = function(value) {
|
|
556
|
+
mock._implementation = (() => Promise.resolve(value));
|
|
557
|
+
return mock;
|
|
558
|
+
};
|
|
559
|
+
mock.mockRejectedValue = function(value) {
|
|
560
|
+
mock._implementation = (() => Promise.reject(value));
|
|
561
|
+
return mock;
|
|
562
|
+
};
|
|
563
|
+
mock.restore = function() {
|
|
564
|
+
mock._calls = [];
|
|
565
|
+
mock._results = [];
|
|
566
|
+
mock._implementation = null;
|
|
567
|
+
};
|
|
568
|
+
mock.clear = function() {
|
|
569
|
+
mock._calls = [];
|
|
570
|
+
mock._results = [];
|
|
571
|
+
};
|
|
572
|
+
return mock;
|
|
477
573
|
}
|
|
574
|
+
var vi = {
|
|
575
|
+
fn: () => createMockFunction(),
|
|
576
|
+
spyOn: (obj, method) => {
|
|
577
|
+
const original = obj[method];
|
|
578
|
+
const mock = createMockFunction();
|
|
579
|
+
mock.mockImplementation(original);
|
|
580
|
+
obj[method] = mock;
|
|
581
|
+
mock.restore = () => {
|
|
582
|
+
obj[method] = original;
|
|
583
|
+
};
|
|
584
|
+
return mock;
|
|
585
|
+
},
|
|
586
|
+
clearAllMocks: () => {
|
|
587
|
+
},
|
|
588
|
+
restoreAllMocks: () => {
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
// src/test/runtime/test-api.ts
|
|
478
593
|
function createTestFunction(defaultTimeout = 5e3) {
|
|
479
594
|
const testFn = function(name, fn, timeout) {
|
|
480
595
|
const test = {
|
|
481
596
|
name,
|
|
482
597
|
fn,
|
|
483
|
-
skip: currentSuite.skip,
|
|
598
|
+
skip: runtimeState.currentSuite.skip,
|
|
484
599
|
only: false,
|
|
485
600
|
todo: false,
|
|
486
601
|
timeout: timeout ?? defaultTimeout,
|
|
487
|
-
suite: currentSuite
|
|
602
|
+
suite: runtimeState.currentSuite
|
|
488
603
|
};
|
|
489
|
-
currentSuite.tests.push(test);
|
|
604
|
+
runtimeState.currentSuite.tests.push(test);
|
|
490
605
|
};
|
|
491
606
|
testFn.skip = (name, fn, timeout) => {
|
|
492
607
|
const test = {
|
|
@@ -496,12 +611,12 @@ function createTestFunction(defaultTimeout = 5e3) {
|
|
|
496
611
|
only: false,
|
|
497
612
|
todo: false,
|
|
498
613
|
timeout: timeout ?? defaultTimeout,
|
|
499
|
-
suite: currentSuite
|
|
614
|
+
suite: runtimeState.currentSuite
|
|
500
615
|
};
|
|
501
|
-
currentSuite.tests.push(test);
|
|
616
|
+
runtimeState.currentSuite.tests.push(test);
|
|
502
617
|
};
|
|
503
618
|
testFn.only = (name, fn, timeout) => {
|
|
504
|
-
hasOnly = true;
|
|
619
|
+
runtimeState.hasOnly = true;
|
|
505
620
|
const test = {
|
|
506
621
|
name,
|
|
507
622
|
fn,
|
|
@@ -509,9 +624,9 @@ function createTestFunction(defaultTimeout = 5e3) {
|
|
|
509
624
|
only: true,
|
|
510
625
|
todo: false,
|
|
511
626
|
timeout: timeout ?? defaultTimeout,
|
|
512
|
-
suite: currentSuite
|
|
627
|
+
suite: runtimeState.currentSuite
|
|
513
628
|
};
|
|
514
|
-
currentSuite.tests.push(test);
|
|
629
|
+
runtimeState.currentSuite.tests.push(test);
|
|
515
630
|
};
|
|
516
631
|
testFn.todo = (name, fn, timeout) => {
|
|
517
632
|
const test = {
|
|
@@ -521,15 +636,15 @@ function createTestFunction(defaultTimeout = 5e3) {
|
|
|
521
636
|
only: false,
|
|
522
637
|
todo: true,
|
|
523
638
|
timeout: timeout ?? defaultTimeout,
|
|
524
|
-
suite: currentSuite
|
|
639
|
+
suite: runtimeState.currentSuite
|
|
525
640
|
};
|
|
526
|
-
currentSuite.tests.push(test);
|
|
641
|
+
runtimeState.currentSuite.tests.push(test);
|
|
527
642
|
};
|
|
528
643
|
return testFn;
|
|
529
644
|
}
|
|
530
645
|
function createDescribeFunction() {
|
|
531
646
|
const describeFn = function(name, fn) {
|
|
532
|
-
const parent = currentSuite;
|
|
647
|
+
const parent = runtimeState.currentSuite;
|
|
533
648
|
const suite = {
|
|
534
649
|
name,
|
|
535
650
|
tests: [],
|
|
@@ -539,12 +654,12 @@ function createDescribeFunction() {
|
|
|
539
654
|
only: parent.only
|
|
540
655
|
};
|
|
541
656
|
parent.suites.push(suite);
|
|
542
|
-
currentSuite = suite;
|
|
657
|
+
runtimeState.currentSuite = suite;
|
|
543
658
|
fn();
|
|
544
|
-
currentSuite = parent;
|
|
659
|
+
runtimeState.currentSuite = parent;
|
|
545
660
|
};
|
|
546
661
|
describeFn.skip = (name, fn) => {
|
|
547
|
-
const parent = currentSuite;
|
|
662
|
+
const parent = runtimeState.currentSuite;
|
|
548
663
|
const suite = {
|
|
549
664
|
name,
|
|
550
665
|
tests: [],
|
|
@@ -554,13 +669,13 @@ function createDescribeFunction() {
|
|
|
554
669
|
only: false
|
|
555
670
|
};
|
|
556
671
|
parent.suites.push(suite);
|
|
557
|
-
currentSuite = suite;
|
|
672
|
+
runtimeState.currentSuite = suite;
|
|
558
673
|
fn();
|
|
559
|
-
currentSuite = parent;
|
|
674
|
+
runtimeState.currentSuite = parent;
|
|
560
675
|
};
|
|
561
676
|
describeFn.only = (name, fn) => {
|
|
562
|
-
hasOnly = true;
|
|
563
|
-
const parent = currentSuite;
|
|
677
|
+
runtimeState.hasOnly = true;
|
|
678
|
+
const parent = runtimeState.currentSuite;
|
|
564
679
|
const suite = {
|
|
565
680
|
name,
|
|
566
681
|
tests: [],
|
|
@@ -570,594 +685,476 @@ function createDescribeFunction() {
|
|
|
570
685
|
only: true
|
|
571
686
|
};
|
|
572
687
|
parent.suites.push(suite);
|
|
573
|
-
currentSuite = suite;
|
|
688
|
+
runtimeState.currentSuite = suite;
|
|
574
689
|
fn();
|
|
575
|
-
currentSuite = parent;
|
|
690
|
+
runtimeState.currentSuite = parent;
|
|
576
691
|
};
|
|
577
692
|
return describeFn;
|
|
578
693
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
694
|
+
|
|
695
|
+
// src/test/runtime/globals.ts
|
|
696
|
+
var globals = {
|
|
697
|
+
describe: createDescribeFunction(),
|
|
698
|
+
it: createTestFunction(5e3),
|
|
699
|
+
test: createTestFunction(5e3),
|
|
700
|
+
expect,
|
|
701
|
+
beforeAll,
|
|
702
|
+
afterAll,
|
|
703
|
+
beforeEach,
|
|
704
|
+
afterEach,
|
|
705
|
+
vi
|
|
706
|
+
};
|
|
707
|
+
function setupGlobals() {
|
|
708
|
+
global.describe = globals.describe;
|
|
709
|
+
global.it = globals.it;
|
|
710
|
+
global.test = globals.test;
|
|
711
|
+
global.expect = globals.expect;
|
|
712
|
+
global.beforeAll = globals.beforeAll;
|
|
713
|
+
global.afterAll = globals.afterAll;
|
|
714
|
+
global.beforeEach = globals.beforeEach;
|
|
715
|
+
global.afterEach = globals.afterEach;
|
|
716
|
+
global.vi = globals.vi;
|
|
717
|
+
}
|
|
718
|
+
function clearGlobals() {
|
|
719
|
+
delete global.describe;
|
|
720
|
+
delete global.it;
|
|
721
|
+
delete global.test;
|
|
722
|
+
delete global.expect;
|
|
723
|
+
delete global.beforeAll;
|
|
724
|
+
delete global.afterAll;
|
|
725
|
+
delete global.beforeEach;
|
|
726
|
+
delete global.afterEach;
|
|
727
|
+
delete global.vi;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// src/test/runtime/transpile.ts
|
|
731
|
+
import { transformSync } from "esbuild";
|
|
732
|
+
|
|
733
|
+
// src/server/path/platform.ts
|
|
734
|
+
function getSeparator(isWin) {
|
|
735
|
+
return isWin ? "\\" : "/";
|
|
736
|
+
}
|
|
737
|
+
function getCwd() {
|
|
738
|
+
if (isNode || isBun) {
|
|
739
|
+
return process.cwd();
|
|
587
740
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
this._not = new _Expect(this.actual, !this.isNot, false);
|
|
591
|
-
}
|
|
592
|
-
return this._not;
|
|
741
|
+
if (isDeno) {
|
|
742
|
+
return Deno.cwd();
|
|
593
743
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
return
|
|
744
|
+
return "/";
|
|
745
|
+
}
|
|
746
|
+
var isWindows = (() => {
|
|
747
|
+
if (isNode) {
|
|
748
|
+
return process.platform === "win32";
|
|
749
|
+
}
|
|
750
|
+
if (isDeno) {
|
|
751
|
+
return Deno.build.os === "windows";
|
|
752
|
+
}
|
|
753
|
+
return typeof process !== "undefined" && process.platform === "win32";
|
|
754
|
+
})();
|
|
755
|
+
|
|
756
|
+
// src/server/path/operations.ts
|
|
757
|
+
function findLastSeparator(path) {
|
|
758
|
+
return Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
759
|
+
}
|
|
760
|
+
function isAbsolutePosix(path) {
|
|
761
|
+
return path.length > 0 && path[0] === "/";
|
|
762
|
+
}
|
|
763
|
+
function isAbsoluteWin(path) {
|
|
764
|
+
const len = path.length;
|
|
765
|
+
if (len === 0) return false;
|
|
766
|
+
const code = path.charCodeAt(0);
|
|
767
|
+
if (code === 47 || code === 92) {
|
|
768
|
+
return true;
|
|
599
769
|
}
|
|
600
|
-
|
|
601
|
-
if (
|
|
602
|
-
|
|
770
|
+
if (code >= 65 && code <= 90 || code >= 97 && code <= 122) {
|
|
771
|
+
if (len > 2 && path.charCodeAt(1) === 58) {
|
|
772
|
+
const code2 = path.charCodeAt(2);
|
|
773
|
+
if (code2 === 47 || code2 === 92) {
|
|
774
|
+
return true;
|
|
775
|
+
}
|
|
603
776
|
}
|
|
604
|
-
return this._rejects;
|
|
605
777
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
function normalizePath(path, isWin) {
|
|
781
|
+
if (path.length === 0) return ".";
|
|
782
|
+
const separator = getSeparator(isWin);
|
|
783
|
+
const isAbsolute = isWin ? isAbsoluteWin(path) : isAbsolutePosix(path);
|
|
784
|
+
const trailingSeparator = path[path.length - 1] === separator || isWin && path[path.length - 1] === "/";
|
|
785
|
+
const normalized = path.replace(isWin ? /[\/\\]+/g : /\/+/g, separator);
|
|
786
|
+
const parts = normalized.split(separator);
|
|
787
|
+
const result = [];
|
|
788
|
+
for (let index = 0; index < parts.length; index++) {
|
|
789
|
+
const part = parts[index];
|
|
790
|
+
if (part === "" || part === ".") {
|
|
791
|
+
if (index === 0 && isAbsolute) result.push("");
|
|
792
|
+
continue;
|
|
609
793
|
}
|
|
610
|
-
if (
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
errorMsg += `
|
|
615
|
-
Expected: ${expectedValue}
|
|
616
|
-
Received: ${this.stringify(this.actual)}`;
|
|
617
|
-
}
|
|
618
|
-
const stack = callerStack || new Error().stack;
|
|
619
|
-
let lineNumber = void 0;
|
|
620
|
-
let codeSnippet = void 0;
|
|
621
|
-
let assertionMethod = void 0;
|
|
622
|
-
if (stack) {
|
|
623
|
-
const assertionMatch = stack.match(/at _Expect\.(\w+)/);
|
|
624
|
-
if (assertionMatch) {
|
|
625
|
-
assertionMethod = assertionMatch[1];
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
if (stack) {
|
|
629
|
-
const lines = stack.split("\n");
|
|
630
|
-
const stackFrames = [];
|
|
631
|
-
for (const line of lines) {
|
|
632
|
-
const match = line.match(/<anonymous>:([0-9]+):([0-9]+)/);
|
|
633
|
-
if (match) {
|
|
634
|
-
stackFrames.push({
|
|
635
|
-
line: parseInt(match[1], 10),
|
|
636
|
-
column: parseInt(match[2], 10)
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
const targetFrame = stackFrames.length > 1 ? stackFrames[1] : stackFrames[0];
|
|
641
|
-
if (targetFrame && currentSourceMapConsumer) {
|
|
642
|
-
try {
|
|
643
|
-
const transpiledLine = targetFrame.line - wrapperLineOffset;
|
|
644
|
-
const originalPosition = currentSourceMapConsumer.originalPositionFor({
|
|
645
|
-
line: transpiledLine,
|
|
646
|
-
column: targetFrame.column
|
|
647
|
-
});
|
|
648
|
-
if (originalPosition.line !== null) {
|
|
649
|
-
lineNumber = originalPosition.line;
|
|
650
|
-
if (currentTestFile) {
|
|
651
|
-
try {
|
|
652
|
-
let sourceCode = readFileSync(currentTestFile, "utf-8");
|
|
653
|
-
if (Buffer.isBuffer(sourceCode)) {
|
|
654
|
-
sourceCode = sourceCode.toString("utf-8");
|
|
655
|
-
}
|
|
656
|
-
const sourceLines = sourceCode.split("\n");
|
|
657
|
-
let targetPattern = ".toBe(";
|
|
658
|
-
if (assertionMethod === "toEqual") targetPattern = ".toEqual(";
|
|
659
|
-
else if (assertionMethod === "toStrictEqual") targetPattern = ".toStrictEqual(";
|
|
660
|
-
else if (assertionMethod === "toMatch") targetPattern = ".toMatch(";
|
|
661
|
-
else if (assertionMethod === "toContain") targetPattern = ".toContain(";
|
|
662
|
-
else if (assertionMethod === "toHaveLength") targetPattern = ".toHaveLength(";
|
|
663
|
-
else if (assertionMethod === "toBeDefined") targetPattern = ".toBeDefined(";
|
|
664
|
-
else if (assertionMethod === "toBeNull") targetPattern = ".toBeNull(";
|
|
665
|
-
else if (assertionMethod === "toBeUndefined") targetPattern = ".toBeUndefined(";
|
|
666
|
-
else if (assertionMethod === "toBeTruthy") targetPattern = ".toBeTruthy(";
|
|
667
|
-
else if (assertionMethod === "toBeFalsy") targetPattern = ".toBeFalsy(";
|
|
668
|
-
else if (assertionMethod === "toThrow") targetPattern = ".toThrow(";
|
|
669
|
-
else if (assertionMethod === "toBeGreaterThan") targetPattern = ".toBeGreaterThan(";
|
|
670
|
-
else if (assertionMethod === "toBeGreaterThanOrEqual") targetPattern = ".toBeGreaterThanOrEqual(";
|
|
671
|
-
else if (assertionMethod === "toBeLessThan") targetPattern = ".toBeLessThan(";
|
|
672
|
-
else if (assertionMethod === "toBeLessThanOrEqual") targetPattern = ".toBeLessThanOrEqual(";
|
|
673
|
-
if (lineNumber > 0 && lineNumber <= sourceLines.length) {
|
|
674
|
-
const mappedLine = sourceLines[lineNumber - 1];
|
|
675
|
-
const hasMatchingAssertion = mappedLine.includes(targetPattern);
|
|
676
|
-
if (!hasMatchingAssertion) {
|
|
677
|
-
for (let i = 1; i <= 3; i++) {
|
|
678
|
-
const searchLine = lineNumber - i;
|
|
679
|
-
if (searchLine > 0 && searchLine <= sourceLines.length) {
|
|
680
|
-
const testLine = sourceLines[searchLine - 1];
|
|
681
|
-
if (testLine.includes(targetPattern)) {
|
|
682
|
-
lineNumber = searchLine;
|
|
683
|
-
break;
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
} catch (e) {
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
} else {
|
|
693
|
-
const posWithoutColumn = currentSourceMapConsumer.originalPositionFor({
|
|
694
|
-
line: transpiledLine,
|
|
695
|
-
column: 0
|
|
696
|
-
});
|
|
697
|
-
if (posWithoutColumn.line !== null) {
|
|
698
|
-
lineNumber = posWithoutColumn.line;
|
|
699
|
-
} else {
|
|
700
|
-
const lineMappings = [];
|
|
701
|
-
currentSourceMapConsumer.eachMapping((mapping) => {
|
|
702
|
-
if (mapping.originalLine !== null) {
|
|
703
|
-
const distance = Math.abs(mapping.generatedLine - transpiledLine);
|
|
704
|
-
lineMappings.push({
|
|
705
|
-
line: mapping.originalLine,
|
|
706
|
-
distance
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
});
|
|
710
|
-
if (lineMappings.length > 0) {
|
|
711
|
-
lineMappings.sort((a, b) => a.distance - b.distance);
|
|
712
|
-
lineNumber = lineMappings[0].line;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
} catch (e) {
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
if (currentTestFile && lineNumber) {
|
|
720
|
-
try {
|
|
721
|
-
let sourceCode = readFileSync(currentTestFile, "utf-8");
|
|
722
|
-
if (Buffer.isBuffer(sourceCode)) {
|
|
723
|
-
sourceCode = sourceCode.toString("utf-8");
|
|
724
|
-
}
|
|
725
|
-
const sourceLines = sourceCode.split("\n");
|
|
726
|
-
if (lineNumber > 0 && lineNumber <= sourceLines.length) {
|
|
727
|
-
const codeLine = sourceLines[lineNumber - 1];
|
|
728
|
-
if (codeLine) {
|
|
729
|
-
codeSnippet = codeLine.trim();
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
} catch (e) {
|
|
733
|
-
}
|
|
794
|
+
if (part === "..") {
|
|
795
|
+
if (result.length > 0 && result[result.length - 1] !== "..") {
|
|
796
|
+
if (!(result.length === 1 && result[0] === "")) {
|
|
797
|
+
result.pop();
|
|
734
798
|
}
|
|
799
|
+
} else if (!isAbsolute) {
|
|
800
|
+
result.push("..");
|
|
735
801
|
}
|
|
736
|
-
|
|
802
|
+
} else {
|
|
803
|
+
result.push(part);
|
|
737
804
|
}
|
|
738
805
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
if (typeof value === "string") return `"${value}"`;
|
|
743
|
-
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
744
|
-
if (typeof value === "function") return "Function";
|
|
745
|
-
if (Array.isArray(value)) return `[${value.map((v) => this.stringify(v)).join(", ")}]`;
|
|
746
|
-
if (typeof value === "object") {
|
|
747
|
-
const keys = Object.keys(value);
|
|
748
|
-
if (keys.length === 0) return "{}";
|
|
749
|
-
return `{ ${keys.slice(0, 3).map((k) => `${k}: ${this.stringify(value[k])}`).join(", ")}${keys.length > 3 ? "..." : ""} }`;
|
|
750
|
-
}
|
|
751
|
-
return String(value);
|
|
806
|
+
let finalPath = result.join(separator);
|
|
807
|
+
if (finalPath.length === 0) {
|
|
808
|
+
return isAbsolute ? separator : ".";
|
|
752
809
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
if (
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
);
|
|
770
|
-
} else if (value instanceof RegExp) {
|
|
771
|
-
this.assertCondition(
|
|
772
|
-
value.test(error.message),
|
|
773
|
-
`Expected error message to match ${value}`
|
|
774
|
-
);
|
|
810
|
+
if (trailingSeparator && finalPath[finalPath.length - 1] !== separator) {
|
|
811
|
+
finalPath += separator;
|
|
812
|
+
}
|
|
813
|
+
return finalPath;
|
|
814
|
+
}
|
|
815
|
+
function joinPaths(paths, isWin) {
|
|
816
|
+
if (paths.length === 0) return ".";
|
|
817
|
+
const separator = getSeparator(isWin);
|
|
818
|
+
let joined = "";
|
|
819
|
+
for (let index = 0; index < paths.length; index++) {
|
|
820
|
+
const path = paths[index];
|
|
821
|
+
if (path && path.length > 0) {
|
|
822
|
+
if (joined.length === 0) {
|
|
823
|
+
joined = path;
|
|
824
|
+
} else {
|
|
825
|
+
joined += separator + path;
|
|
775
826
|
}
|
|
776
|
-
return Promise.resolve(void 0);
|
|
777
827
|
}
|
|
778
828
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
this.assertCondition(this.actual === value, `Expected values to be strictly equal (using ===)`, true, void 0, stack);
|
|
792
|
-
if (typeof this.actual !== typeof value) {
|
|
793
|
-
throw new Error(`Types don't match: expected ${typeof value} but got ${typeof this.actual}`);
|
|
829
|
+
if (joined.length === 0) return ".";
|
|
830
|
+
return normalizePath(joined, isWin);
|
|
831
|
+
}
|
|
832
|
+
function resolvePaths(paths, isWin) {
|
|
833
|
+
const separator = getSeparator(isWin);
|
|
834
|
+
let resolved = "";
|
|
835
|
+
let absolute = false;
|
|
836
|
+
for (let index = paths.length - 1; index >= 0 && !absolute; index--) {
|
|
837
|
+
const path = paths[index];
|
|
838
|
+
if (path && path.length > 0) {
|
|
839
|
+
resolved = path + (resolved.length > 0 ? separator + resolved : "");
|
|
840
|
+
absolute = isWin ? isAbsoluteWin(resolved) : isAbsolutePosix(resolved);
|
|
794
841
|
}
|
|
795
842
|
}
|
|
796
|
-
|
|
797
|
-
const
|
|
798
|
-
|
|
799
|
-
const isEqual = (a, b) => {
|
|
800
|
-
if (a === b) return true;
|
|
801
|
-
if (a == null || b == null) return a === b;
|
|
802
|
-
if (typeof a !== typeof b) return false;
|
|
803
|
-
if (typeof a !== "object") return a === b;
|
|
804
|
-
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
805
|
-
if (Array.isArray(a)) {
|
|
806
|
-
if (a.length !== b.length) return false;
|
|
807
|
-
return a.every((item, i) => isEqual(item, b[i]));
|
|
808
|
-
}
|
|
809
|
-
const keysA = Object.keys(a);
|
|
810
|
-
const keysB = Object.keys(b);
|
|
811
|
-
if (keysA.length !== keysB.length) return false;
|
|
812
|
-
return keysA.every((key) => isEqual(a[key], b[key]));
|
|
813
|
-
};
|
|
814
|
-
this.assertCondition(isEqual(this.actual, value), "Expected values to be deeply equal", false, void 0, stack);
|
|
815
|
-
}
|
|
816
|
-
toBeTruthy() {
|
|
817
|
-
const stack = new Error().stack;
|
|
818
|
-
this.assertCondition(!!this.actual, `Expected value to be truthy`, false, void 0, stack);
|
|
819
|
-
}
|
|
820
|
-
toBeFalsy() {
|
|
821
|
-
const stack = new Error().stack;
|
|
822
|
-
this.assertCondition(!this.actual, `Expected value to be falsy`, false, void 0, stack);
|
|
823
|
-
}
|
|
824
|
-
toBeNull() {
|
|
825
|
-
const stack = new Error().stack;
|
|
826
|
-
this.assertCondition(this.actual === null, `Expected value to be null`, false, void 0, stack);
|
|
843
|
+
if (!absolute) {
|
|
844
|
+
const cwd = getCwd();
|
|
845
|
+
resolved = cwd + (resolved.length > 0 ? separator + resolved : "");
|
|
827
846
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
847
|
+
return normalizePath(resolved, isWin);
|
|
848
|
+
}
|
|
849
|
+
function relativePath(from, to, isWin) {
|
|
850
|
+
const resolvedFrom = resolvePaths([from], isWin);
|
|
851
|
+
const resolvedTo = resolvePaths([to], isWin);
|
|
852
|
+
if (resolvedFrom === resolvedTo) return "";
|
|
853
|
+
const separator = getSeparator(isWin);
|
|
854
|
+
const fromParts = resolvedFrom.split(separator).filter((part) => part.length > 0);
|
|
855
|
+
const toParts = resolvedTo.split(separator).filter((part) => part.length > 0);
|
|
856
|
+
const minLength = Math.min(fromParts.length, toParts.length);
|
|
857
|
+
let commonLength = 0;
|
|
858
|
+
for (let index = 0; index < minLength; index++) {
|
|
859
|
+
if (fromParts[index] === toParts[index]) {
|
|
860
|
+
commonLength++;
|
|
861
|
+
} else {
|
|
862
|
+
break;
|
|
863
|
+
}
|
|
831
864
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
865
|
+
const result = [];
|
|
866
|
+
const upCount = fromParts.length - commonLength;
|
|
867
|
+
for (let index = 0; index < upCount; index++) {
|
|
868
|
+
result.push("..");
|
|
835
869
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
this.expected = value;
|
|
839
|
-
this.assertCondition(
|
|
840
|
-
typeof this.actual === "number" && this.actual > value,
|
|
841
|
-
`Expected ${this.stringify(this.actual)} to be greater than ${value}`,
|
|
842
|
-
true,
|
|
843
|
-
String(value),
|
|
844
|
-
stack
|
|
845
|
-
);
|
|
870
|
+
for (let index = commonLength; index < toParts.length; index++) {
|
|
871
|
+
result.push(toParts[index]);
|
|
846
872
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
873
|
+
return result.join(separator) || ".";
|
|
874
|
+
}
|
|
875
|
+
function getDirname(path, isWin) {
|
|
876
|
+
if (path.length === 0) return ".";
|
|
877
|
+
const separator = getSeparator(isWin);
|
|
878
|
+
const normalized = normalizePath(path, isWin);
|
|
879
|
+
const lastSeparatorIndex = normalized.lastIndexOf(separator);
|
|
880
|
+
if (lastSeparatorIndex === -1) return ".";
|
|
881
|
+
if (lastSeparatorIndex === 0) return separator;
|
|
882
|
+
return normalized.slice(0, lastSeparatorIndex);
|
|
883
|
+
}
|
|
884
|
+
function getBasename(path, ext, isWin) {
|
|
885
|
+
if (path.length === 0) return "";
|
|
886
|
+
const lastSeparatorIndex = isWin ? findLastSeparator(path) : path.lastIndexOf("/");
|
|
887
|
+
let base = lastSeparatorIndex === -1 ? path : path.slice(lastSeparatorIndex + 1);
|
|
888
|
+
if (ext && base.endsWith(ext)) {
|
|
889
|
+
base = base.slice(0, base.length - ext.length);
|
|
857
890
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
String(value),
|
|
866
|
-
stack
|
|
867
|
-
);
|
|
891
|
+
return base;
|
|
892
|
+
}
|
|
893
|
+
function getExtname(path) {
|
|
894
|
+
const lastDotIndex = path.lastIndexOf(".");
|
|
895
|
+
const lastSeparatorIndex = findLastSeparator(path);
|
|
896
|
+
if (lastDotIndex === -1 || lastDotIndex < lastSeparatorIndex || lastDotIndex === path.length - 1) {
|
|
897
|
+
return "";
|
|
868
898
|
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
899
|
+
return path.slice(lastDotIndex);
|
|
900
|
+
}
|
|
901
|
+
function parsePath(path, isWin) {
|
|
902
|
+
let root = "";
|
|
903
|
+
if (isWin) {
|
|
904
|
+
if (path.length >= 2 && path[1] === ":") {
|
|
905
|
+
root = path.slice(0, 2);
|
|
906
|
+
if (path.length > 2 && (path[2] === "\\" || path[2] === "/")) {
|
|
907
|
+
root += "\\";
|
|
908
|
+
}
|
|
909
|
+
} else if (path[0] === "\\" || path[0] === "/") {
|
|
910
|
+
root = "\\";
|
|
911
|
+
}
|
|
912
|
+
} else if (path[0] === "/") {
|
|
913
|
+
root = "/";
|
|
879
914
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
915
|
+
const dir = getDirname(path, isWin);
|
|
916
|
+
const base = getBasename(path, void 0, isWin);
|
|
917
|
+
const ext = getExtname(path);
|
|
918
|
+
const name = ext ? base.slice(0, base.length - ext.length) : base;
|
|
919
|
+
return { root, dir, base, ext, name };
|
|
920
|
+
}
|
|
921
|
+
function formatPath(pathObject, isWin) {
|
|
922
|
+
const separator = getSeparator(isWin);
|
|
923
|
+
const dir = pathObject.dir || pathObject.root || "";
|
|
924
|
+
const base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
|
|
925
|
+
if (!dir) return base;
|
|
926
|
+
if (dir === pathObject.root) return dir + base;
|
|
927
|
+
return dir + separator + base;
|
|
928
|
+
}
|
|
929
|
+
function createPathOps(isWin) {
|
|
930
|
+
return {
|
|
931
|
+
sep: getSeparator(isWin),
|
|
932
|
+
delimiter: isWin ? ";" : ":",
|
|
933
|
+
normalize: (path) => normalizePath(path, isWin),
|
|
934
|
+
join: (...paths) => joinPaths(paths, isWin),
|
|
935
|
+
resolve: (...paths) => resolvePaths(paths, isWin),
|
|
936
|
+
isAbsolute: (path) => isWin ? isAbsoluteWin(path) : isAbsolutePosix(path),
|
|
937
|
+
relative: (from, to) => relativePath(from, to, isWin),
|
|
938
|
+
dirname: (path) => getDirname(path, isWin),
|
|
939
|
+
basename: (path, ext) => getBasename(path, ext, isWin),
|
|
940
|
+
extname: (path) => getExtname(path),
|
|
941
|
+
parse: (path) => parsePath(path, isWin),
|
|
942
|
+
format: (pathObject) => formatPath(pathObject, isWin)
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// src/server/path/index.ts
|
|
947
|
+
var posix = createPathOps(false);
|
|
948
|
+
var win32 = createPathOps(true);
|
|
949
|
+
function dirname(path) {
|
|
950
|
+
return getDirname(path, isWindows);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
// src/test/runtime/transpile.ts
|
|
954
|
+
var TEST_MODULE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".json"];
|
|
955
|
+
function resolveTestLoader(filePath) {
|
|
956
|
+
return /\.(?:ts|tsx|mts|cts)$/i.test(filePath) ? "ts" : "js";
|
|
957
|
+
}
|
|
958
|
+
function createTestTransformOptions(filePath, format, sourcemap) {
|
|
959
|
+
return {
|
|
960
|
+
loader: resolveTestLoader(filePath),
|
|
961
|
+
format,
|
|
962
|
+
sourcemap,
|
|
963
|
+
sourcefile: filePath,
|
|
964
|
+
target: "es2020",
|
|
965
|
+
tsconfigRaw: {
|
|
966
|
+
compilerOptions: {
|
|
967
|
+
jsx: "react",
|
|
968
|
+
jsxFactory: "h",
|
|
969
|
+
jsxFragmentFactory: "Fragment"
|
|
970
|
+
}
|
|
901
971
|
}
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
function extractInlineSourceMap(code) {
|
|
975
|
+
const sourceMapMatch = code.match(/\/\/# sourceMappingURL=data:application\/json;base64,(.+)/);
|
|
976
|
+
if (!sourceMapMatch) {
|
|
977
|
+
return void 0;
|
|
902
978
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
false,
|
|
911
|
-
void 0,
|
|
912
|
-
stack
|
|
913
|
-
);
|
|
979
|
+
const json = Buffer.from(sourceMapMatch[1], "base64").toString("utf-8");
|
|
980
|
+
return JSON.parse(json);
|
|
981
|
+
}
|
|
982
|
+
function resolveExistingTestModulePath(basePath) {
|
|
983
|
+
const nodePath = __require("path");
|
|
984
|
+
if (existsSync(basePath) && statSync(basePath).isFile()) {
|
|
985
|
+
return basePath;
|
|
914
986
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
987
|
+
for (const extension of TEST_MODULE_EXTENSIONS) {
|
|
988
|
+
const candidatePath = `${basePath}${extension}`;
|
|
989
|
+
if (existsSync(candidatePath) && statSync(candidatePath).isFile()) {
|
|
990
|
+
return candidatePath;
|
|
919
991
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
992
|
+
}
|
|
993
|
+
if (existsSync(basePath) && statSync(basePath).isDirectory()) {
|
|
994
|
+
const packageJsonPath = nodePath.join(basePath, "package.json");
|
|
995
|
+
if (existsSync(packageJsonPath) && statSync(packageJsonPath).isFile()) {
|
|
996
|
+
try {
|
|
997
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
998
|
+
for (const candidateEntry of [packageJson.main, packageJson.module]) {
|
|
999
|
+
if (typeof candidateEntry !== "string" || candidateEntry.trim().length === 0) {
|
|
1000
|
+
continue;
|
|
1001
|
+
}
|
|
1002
|
+
try {
|
|
1003
|
+
return resolveExistingTestModulePath(nodePath.resolve(basePath, candidateEntry));
|
|
1004
|
+
} catch {
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
} catch {
|
|
925
1009
|
}
|
|
926
|
-
} catch (e) {
|
|
927
|
-
threw = true;
|
|
928
|
-
thrownError = e;
|
|
929
1010
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
if (
|
|
933
|
-
|
|
934
|
-
thrownError.message.includes(error),
|
|
935
|
-
`Expected error message to include "${error}"`
|
|
936
|
-
);
|
|
937
|
-
} else if (error instanceof RegExp) {
|
|
938
|
-
this.assertCondition(
|
|
939
|
-
error.test(thrownError.message),
|
|
940
|
-
`Expected error message to match ${error}`
|
|
941
|
-
);
|
|
1011
|
+
for (const extension of TEST_MODULE_EXTENSIONS) {
|
|
1012
|
+
const candidatePath = nodePath.join(basePath, `index${extension}`);
|
|
1013
|
+
if (existsSync(candidatePath) && statSync(candidatePath).isFile()) {
|
|
1014
|
+
return candidatePath;
|
|
942
1015
|
}
|
|
943
1016
|
}
|
|
944
1017
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
pattern.test(str),
|
|
951
|
-
`Expected "${str}" to match ${pattern}`
|
|
952
|
-
);
|
|
953
|
-
} else {
|
|
954
|
-
this.assertCondition(
|
|
955
|
-
str.includes(pattern),
|
|
956
|
-
`Expected "${str}" to contain "${pattern}"`
|
|
957
|
-
);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
toBeInstanceOf(classType) {
|
|
961
|
-
this.expected = classType;
|
|
962
|
-
this.assertCondition(
|
|
963
|
-
this.actual instanceof classType,
|
|
964
|
-
`Expected value to be instance of ${classType.name}`
|
|
965
|
-
);
|
|
1018
|
+
return basePath;
|
|
1019
|
+
}
|
|
1020
|
+
function resolveTestModulePath(fromFilePath, specifier) {
|
|
1021
|
+
if (!specifier.startsWith(".") && !specifier.startsWith("/")) {
|
|
1022
|
+
return specifier;
|
|
966
1023
|
}
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1024
|
+
const nodePath = __require("path");
|
|
1025
|
+
const basePath = specifier.startsWith(".") ? nodePath.resolve(dirname(fromFilePath), specifier) : specifier;
|
|
1026
|
+
return resolveExistingTestModulePath(basePath);
|
|
1027
|
+
}
|
|
1028
|
+
function shouldTranspileTestModule(filePath) {
|
|
1029
|
+
return /\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs)$/i.test(filePath);
|
|
1030
|
+
}
|
|
1031
|
+
function createTestModuleRequire(fromFilePath, moduleCache) {
|
|
1032
|
+
return (specifier) => {
|
|
1033
|
+
if (specifier.startsWith("elit/") || specifier === "elit") {
|
|
1034
|
+
return __require(specifier);
|
|
975
1035
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
`Expected property "${path}" to equal ${this.stringify(value)}`
|
|
980
|
-
);
|
|
1036
|
+
const resolvedPath = resolveTestModulePath(fromFilePath, specifier);
|
|
1037
|
+
if (resolvedPath === specifier) {
|
|
1038
|
+
return __require(specifier);
|
|
981
1039
|
}
|
|
1040
|
+
if (!existsSync(resolvedPath) || !statSync(resolvedPath).isFile()) {
|
|
1041
|
+
return __require(resolvedPath);
|
|
1042
|
+
}
|
|
1043
|
+
if (!shouldTranspileTestModule(resolvedPath)) {
|
|
1044
|
+
return __require(resolvedPath);
|
|
1045
|
+
}
|
|
1046
|
+
return loadTranspiledTestModule(resolvedPath, moduleCache);
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
function loadTranspiledTestModule(modulePath, moduleCache) {
|
|
1050
|
+
const cached = moduleCache.get(modulePath);
|
|
1051
|
+
if (cached) {
|
|
1052
|
+
return cached.exports;
|
|
982
1053
|
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
);
|
|
989
|
-
}
|
|
990
|
-
toBeCalledTimes(times) {
|
|
991
|
-
this.assertCondition(
|
|
992
|
-
this.actual._isMock && this.actual._calls.length === times,
|
|
993
|
-
`Expected mock to be called ${times} times, but was called ${this.actual._calls?.length || 0} times`
|
|
994
|
-
);
|
|
995
|
-
}
|
|
996
|
-
toBeCalledWith(...args) {
|
|
997
|
-
this.assertCondition(this.actual._isMock && this.actual._calls.some((call) => this.deepEqual(call, args)), `Expected mock to be called with ${this.stringify(args)}`);
|
|
1054
|
+
const source = readFileSync(modulePath, "utf-8");
|
|
1055
|
+
let transpiled;
|
|
1056
|
+
try {
|
|
1057
|
+
transpiled = transformSync(source, createTestTransformOptions(modulePath, "cjs", false));
|
|
1058
|
+
} catch (error) {
|
|
1059
|
+
throw new Error(`Failed to transpile test dependency ${modulePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
998
1060
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
);
|
|
1061
|
+
const moduleRecord = { exports: {} };
|
|
1062
|
+
const moduleObject = { exports: moduleRecord.exports };
|
|
1063
|
+
moduleCache.set(modulePath, moduleRecord);
|
|
1064
|
+
try {
|
|
1065
|
+
const fn = new Function("module", "exports", "require", "__filename", "__dirname", transpiled.code);
|
|
1066
|
+
const requireFn = createTestModuleRequire(modulePath, moduleCache);
|
|
1067
|
+
fn(moduleObject, moduleObject.exports, requireFn, modulePath, dirname(modulePath));
|
|
1068
|
+
} catch (error) {
|
|
1069
|
+
throw new Error(`Failed to execute test dependency ${modulePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1005
1070
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1071
|
+
moduleRecord.exports = moduleObject.exports;
|
|
1072
|
+
if (!modulePath.includes(".test.") && !modulePath.includes(".spec.")) {
|
|
1073
|
+
runtimeState.coveredFiles.add(modulePath);
|
|
1008
1074
|
}
|
|
1009
|
-
|
|
1010
|
-
function expect(actual) {
|
|
1011
|
-
return new Expect(actual);
|
|
1075
|
+
return moduleRecord.exports;
|
|
1012
1076
|
}
|
|
1013
|
-
function
|
|
1014
|
-
const
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
return result;
|
|
1020
|
-
} catch (error) {
|
|
1021
|
-
mock._results.push({ type: "throw", value: error });
|
|
1022
|
-
throw error;
|
|
1023
|
-
}
|
|
1024
|
-
};
|
|
1025
|
-
mock._isMock = true;
|
|
1026
|
-
mock._calls = [];
|
|
1027
|
-
mock._results = [];
|
|
1028
|
-
mock._implementation = null;
|
|
1029
|
-
mock.mockImplementation = function(fn) {
|
|
1030
|
-
mock._implementation = fn;
|
|
1031
|
-
return mock;
|
|
1032
|
-
};
|
|
1033
|
-
mock.mockReturnValue = function(value) {
|
|
1034
|
-
mock._implementation = (() => value);
|
|
1035
|
-
return mock;
|
|
1036
|
-
};
|
|
1037
|
-
mock.mockResolvedValue = function(value) {
|
|
1038
|
-
mock._implementation = (() => Promise.resolve(value));
|
|
1039
|
-
return mock;
|
|
1040
|
-
};
|
|
1041
|
-
mock.mockRejectedValue = function(value) {
|
|
1042
|
-
mock._implementation = (() => Promise.reject(value));
|
|
1043
|
-
return mock;
|
|
1044
|
-
};
|
|
1045
|
-
mock.restore = function() {
|
|
1046
|
-
mock._calls = [];
|
|
1047
|
-
mock._results = [];
|
|
1048
|
-
mock._implementation = null;
|
|
1049
|
-
};
|
|
1050
|
-
mock.clear = function() {
|
|
1051
|
-
mock._calls = [];
|
|
1052
|
-
mock._results = [];
|
|
1077
|
+
async function transpileFile(filePath) {
|
|
1078
|
+
const source = await readFile(filePath, "utf-8");
|
|
1079
|
+
const result = transformSync(source, createTestTransformOptions(filePath, "esm", "inline"));
|
|
1080
|
+
return {
|
|
1081
|
+
code: result.code,
|
|
1082
|
+
sourceMap: extractInlineSourceMap(result.code)
|
|
1053
1083
|
};
|
|
1054
|
-
return mock;
|
|
1055
1084
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
},
|
|
1068
|
-
clearAllMocks: () => {
|
|
1069
|
-
},
|
|
1070
|
-
restoreAllMocks: () => {
|
|
1085
|
+
|
|
1086
|
+
// src/test/runtime/runner.ts
|
|
1087
|
+
import { transformSync as transformSync2 } from "esbuild";
|
|
1088
|
+
import { SourceMapConsumer } from "source-map";
|
|
1089
|
+
function escapeRegex(str) {
|
|
1090
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1091
|
+
}
|
|
1092
|
+
function destroyCurrentSourceMapConsumer() {
|
|
1093
|
+
if (runtimeState.currentSourceMapConsumer) {
|
|
1094
|
+
runtimeState.currentSourceMapConsumer.destroy();
|
|
1095
|
+
runtimeState.currentSourceMapConsumer = void 0;
|
|
1071
1096
|
}
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1097
|
+
}
|
|
1098
|
+
function suiteOrDescendantMatches(suite) {
|
|
1099
|
+
if (!runtimeState.describePattern) {
|
|
1100
|
+
return true;
|
|
1101
|
+
}
|
|
1102
|
+
const regex = new RegExp(escapeRegex(runtimeState.describePattern), "i");
|
|
1103
|
+
if (regex.test(suite.name)) {
|
|
1104
|
+
return true;
|
|
1105
|
+
}
|
|
1106
|
+
for (const child of suite.suites) {
|
|
1107
|
+
if (suiteOrDescendantMatches(child)) {
|
|
1108
|
+
return true;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
return false;
|
|
1112
|
+
}
|
|
1081
1113
|
async function runTests(options) {
|
|
1082
|
-
const { files, timeout = 5e3, bail = false, describePattern
|
|
1083
|
-
describePattern =
|
|
1084
|
-
testPattern =
|
|
1085
|
-
testResults.length = 0;
|
|
1086
|
-
hasOnly = false;
|
|
1114
|
+
const { files, timeout = 5e3, bail = false, describePattern, testPattern } = options;
|
|
1115
|
+
runtimeState.describePattern = describePattern;
|
|
1116
|
+
runtimeState.testPattern = testPattern;
|
|
1117
|
+
runtimeState.testResults.length = 0;
|
|
1087
1118
|
for (const file of files) {
|
|
1088
|
-
|
|
1119
|
+
resetSuiteState();
|
|
1120
|
+
resetHookState();
|
|
1121
|
+
resetSourceMapState();
|
|
1122
|
+
runtimeState.currentTestFile = file;
|
|
1089
1123
|
try {
|
|
1090
1124
|
const source = await readFile(file, "utf-8");
|
|
1091
1125
|
const testFileDir = dirname(file);
|
|
1092
|
-
const result =
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
const base64 = sourceMapMatch[1];
|
|
1097
|
-
const json = Buffer.from(base64, "base64").toString("utf-8");
|
|
1098
|
-
const sourceMap = JSON.parse(json);
|
|
1099
|
-
currentSourceMapConsumer = await new SourceMapConsumer(sourceMap);
|
|
1100
|
-
} else {
|
|
1101
|
-
currentSourceMapConsumer = void 0;
|
|
1102
|
-
}
|
|
1103
|
-
wrapperLineOffset = 0;
|
|
1126
|
+
const result = transformSync2(source, createTestTransformOptions(file, "cjs", "inline"));
|
|
1127
|
+
const sourceMap = extractInlineSourceMap(result.code);
|
|
1128
|
+
runtimeState.currentSourceMapConsumer = sourceMap ? await new SourceMapConsumer(sourceMap) : void 0;
|
|
1129
|
+
runtimeState.wrapperLineOffset = 0;
|
|
1104
1130
|
setupGlobals();
|
|
1105
1131
|
const moduleCache = /* @__PURE__ */ new Map();
|
|
1106
1132
|
const moduleRecord = { exports: {} };
|
|
1107
|
-
const
|
|
1133
|
+
const moduleObject = { exports: moduleRecord.exports };
|
|
1108
1134
|
moduleCache.set(file, moduleRecord);
|
|
1109
|
-
const fn = new Function("module", "exports", "require", "__filename", "__dirname", code);
|
|
1135
|
+
const fn = new Function("module", "exports", "require", "__filename", "__dirname", result.code);
|
|
1110
1136
|
const requireFn = createTestModuleRequire(file, moduleCache);
|
|
1111
|
-
await fn(
|
|
1112
|
-
await executeSuite(currentSuite, timeout, bail);
|
|
1113
|
-
if (currentSourceMapConsumer) {
|
|
1114
|
-
currentSourceMapConsumer.destroy();
|
|
1115
|
-
currentSourceMapConsumer = void 0;
|
|
1116
|
-
}
|
|
1117
|
-
currentSuite = {
|
|
1118
|
-
name: "root",
|
|
1119
|
-
tests: [],
|
|
1120
|
-
suites: [],
|
|
1121
|
-
skip: false,
|
|
1122
|
-
only: false
|
|
1123
|
-
};
|
|
1124
|
-
hasOnly = false;
|
|
1125
|
-
beforeAllHooks = [];
|
|
1126
|
-
afterAllHooks = [];
|
|
1127
|
-
beforeEachHooks = [];
|
|
1128
|
-
afterEachHooks = [];
|
|
1137
|
+
await fn(moduleObject, moduleObject.exports, requireFn, file, testFileDir);
|
|
1138
|
+
await executeSuite(runtimeState.currentSuite, timeout, bail);
|
|
1129
1139
|
} catch (error) {
|
|
1130
|
-
if (currentSourceMapConsumer) {
|
|
1131
|
-
currentSourceMapConsumer.destroy();
|
|
1132
|
-
currentSourceMapConsumer = void 0;
|
|
1133
|
-
}
|
|
1134
1140
|
console.error(`Error loading test file ${file}:`, error);
|
|
1141
|
+
} finally {
|
|
1142
|
+
destroyCurrentSourceMapConsumer();
|
|
1135
1143
|
}
|
|
1136
1144
|
}
|
|
1137
|
-
const passed = testResults.filter((
|
|
1138
|
-
const failed = testResults.filter((
|
|
1139
|
-
const skipped = testResults.filter((
|
|
1140
|
-
const todo = testResults.filter((
|
|
1141
|
-
return { passed, failed, skipped, todo, results: testResults };
|
|
1145
|
+
const passed = runtimeState.testResults.filter((result) => result.status === "pass").length;
|
|
1146
|
+
const failed = runtimeState.testResults.filter((result) => result.status === "fail").length;
|
|
1147
|
+
const skipped = runtimeState.testResults.filter((result) => result.status === "skip").length;
|
|
1148
|
+
const todo = runtimeState.testResults.filter((result) => result.status === "todo").length;
|
|
1149
|
+
return { passed, failed, skipped, todo, results: runtimeState.testResults };
|
|
1142
1150
|
}
|
|
1143
1151
|
async function executeSuite(suite, timeout, bail, parentMatched = false) {
|
|
1144
1152
|
let directMatch = false;
|
|
1145
|
-
if (describePattern) {
|
|
1146
|
-
const
|
|
1147
|
-
const regex = new RegExp(escapedPattern, "i");
|
|
1153
|
+
if (runtimeState.describePattern) {
|
|
1154
|
+
const regex = new RegExp(escapeRegex(runtimeState.describePattern), "i");
|
|
1148
1155
|
directMatch = regex.test(suite.name);
|
|
1149
1156
|
}
|
|
1150
|
-
|
|
1151
|
-
if (!describePattern) return true;
|
|
1152
|
-
const escapedPattern = escapeRegex(describePattern);
|
|
1153
|
-
const regex = new RegExp(escapedPattern, "i");
|
|
1154
|
-
if (regex.test(s.name)) return true;
|
|
1155
|
-
for (const child of s.suites) {
|
|
1156
|
-
if (suiteOrDescendantMatches(child)) return true;
|
|
1157
|
-
}
|
|
1158
|
-
return false;
|
|
1159
|
-
}
|
|
1160
|
-
const shouldRunSuite = !describePattern || directMatch || parentMatched || suiteOrDescendantMatches(suite);
|
|
1157
|
+
const shouldRunSuite = !runtimeState.describePattern || directMatch || parentMatched || suiteOrDescendantMatches(suite);
|
|
1161
1158
|
if (!shouldRunSuite) {
|
|
1162
1159
|
return;
|
|
1163
1160
|
}
|
|
@@ -1166,47 +1163,46 @@ async function executeSuite(suite, timeout, bail, parentMatched = false) {
|
|
|
1166
1163
|
await executeSuite(childSuite, timeout, bail, parentMatched || directMatch);
|
|
1167
1164
|
}
|
|
1168
1165
|
}
|
|
1169
|
-
const shouldRunTests = !describePattern || directMatch || parentMatched || suite.name === "";
|
|
1166
|
+
const shouldRunTests = !runtimeState.describePattern || directMatch || parentMatched || suite.name === "";
|
|
1170
1167
|
if (!shouldRunTests) {
|
|
1171
1168
|
return;
|
|
1172
1169
|
}
|
|
1173
|
-
for (const hook of beforeAllHooks) {
|
|
1170
|
+
for (const hook of runtimeState.beforeAllHooks) {
|
|
1174
1171
|
await hook();
|
|
1175
1172
|
}
|
|
1176
1173
|
for (const test of suite.tests) {
|
|
1177
|
-
if (hasOnly && !test.only && !suite.only) {
|
|
1174
|
+
if (runtimeState.hasOnly && !test.only && !suite.only) {
|
|
1178
1175
|
continue;
|
|
1179
1176
|
}
|
|
1180
1177
|
let testMatches = true;
|
|
1181
|
-
if (testPattern) {
|
|
1182
|
-
const
|
|
1183
|
-
const regex = new RegExp(escapedPattern, "i");
|
|
1178
|
+
if (runtimeState.testPattern) {
|
|
1179
|
+
const regex = new RegExp(escapeRegex(runtimeState.testPattern), "i");
|
|
1184
1180
|
testMatches = regex.test(test.name);
|
|
1185
1181
|
}
|
|
1186
1182
|
if (!testMatches) {
|
|
1187
1183
|
continue;
|
|
1188
1184
|
}
|
|
1189
1185
|
if (test.skip || suite.skip) {
|
|
1190
|
-
testResults.push({
|
|
1186
|
+
runtimeState.testResults.push({
|
|
1191
1187
|
name: test.name,
|
|
1192
1188
|
status: "skip",
|
|
1193
1189
|
duration: 0,
|
|
1194
1190
|
suite: suite.name,
|
|
1195
|
-
file: currentTestFile
|
|
1191
|
+
file: runtimeState.currentTestFile
|
|
1196
1192
|
});
|
|
1197
1193
|
continue;
|
|
1198
1194
|
}
|
|
1199
1195
|
if (test.todo) {
|
|
1200
|
-
testResults.push({
|
|
1196
|
+
runtimeState.testResults.push({
|
|
1201
1197
|
name: test.name,
|
|
1202
1198
|
status: "todo",
|
|
1203
1199
|
duration: 0,
|
|
1204
1200
|
suite: suite.name,
|
|
1205
|
-
file: currentTestFile
|
|
1201
|
+
file: runtimeState.currentTestFile
|
|
1206
1202
|
});
|
|
1207
1203
|
continue;
|
|
1208
1204
|
}
|
|
1209
|
-
for (const hook of beforeEachHooks) {
|
|
1205
|
+
for (const hook of runtimeState.beforeEachHooks) {
|
|
1210
1206
|
await hook();
|
|
1211
1207
|
}
|
|
1212
1208
|
const startTime = Date.now();
|
|
@@ -1217,27 +1213,27 @@ async function executeSuite(suite, timeout, bail, parentMatched = false) {
|
|
|
1217
1213
|
(_, reject) => setTimeout(() => reject(new Error(`Test timed out after ${test.timeout}ms`)), test.timeout)
|
|
1218
1214
|
)
|
|
1219
1215
|
]);
|
|
1220
|
-
testResults.push({
|
|
1216
|
+
runtimeState.testResults.push({
|
|
1221
1217
|
name: test.name,
|
|
1222
1218
|
status: "pass",
|
|
1223
1219
|
duration: Date.now() - startTime,
|
|
1224
1220
|
suite: suite.name,
|
|
1225
|
-
file: currentTestFile
|
|
1221
|
+
file: runtimeState.currentTestFile
|
|
1226
1222
|
});
|
|
1227
1223
|
} catch (error) {
|
|
1228
|
-
let lineNumber
|
|
1229
|
-
let codeSnippet
|
|
1224
|
+
let lineNumber;
|
|
1225
|
+
let codeSnippet;
|
|
1230
1226
|
if (error instanceof AssertionError) {
|
|
1231
1227
|
lineNumber = error.lineNumber;
|
|
1232
1228
|
codeSnippet = error.codeSnippet;
|
|
1233
1229
|
}
|
|
1234
|
-
testResults.push({
|
|
1230
|
+
runtimeState.testResults.push({
|
|
1235
1231
|
name: test.name,
|
|
1236
1232
|
status: "fail",
|
|
1237
1233
|
duration: Date.now() - startTime,
|
|
1238
1234
|
error,
|
|
1239
1235
|
suite: suite.name,
|
|
1240
|
-
file: currentTestFile,
|
|
1236
|
+
file: runtimeState.currentTestFile,
|
|
1241
1237
|
lineNumber,
|
|
1242
1238
|
codeSnippet
|
|
1243
1239
|
});
|
|
@@ -1245,53 +1241,14 @@ async function executeSuite(suite, timeout, bail, parentMatched = false) {
|
|
|
1245
1241
|
throw error;
|
|
1246
1242
|
}
|
|
1247
1243
|
}
|
|
1248
|
-
for (const hook of afterEachHooks) {
|
|
1244
|
+
for (const hook of runtimeState.afterEachHooks) {
|
|
1249
1245
|
await hook();
|
|
1250
1246
|
}
|
|
1251
1247
|
}
|
|
1252
|
-
for (const hook of afterAllHooks) {
|
|
1248
|
+
for (const hook of runtimeState.afterAllHooks) {
|
|
1253
1249
|
await hook();
|
|
1254
1250
|
}
|
|
1255
1251
|
}
|
|
1256
|
-
var globals = {
|
|
1257
|
-
describe: createDescribeFunction(),
|
|
1258
|
-
it: createTestFunction(5e3),
|
|
1259
|
-
test: createTestFunction(5e3),
|
|
1260
|
-
expect,
|
|
1261
|
-
beforeAll,
|
|
1262
|
-
afterAll,
|
|
1263
|
-
beforeEach,
|
|
1264
|
-
afterEach,
|
|
1265
|
-
vi
|
|
1266
|
-
};
|
|
1267
|
-
function setupGlobals() {
|
|
1268
|
-
global.describe = globals.describe;
|
|
1269
|
-
global.it = globals.it;
|
|
1270
|
-
global.test = globals.test;
|
|
1271
|
-
global.expect = globals.expect;
|
|
1272
|
-
global.beforeAll = globals.beforeAll;
|
|
1273
|
-
global.afterAll = globals.afterAll;
|
|
1274
|
-
global.beforeEach = globals.beforeEach;
|
|
1275
|
-
global.afterEach = globals.afterEach;
|
|
1276
|
-
global.vi = globals.vi;
|
|
1277
|
-
}
|
|
1278
|
-
function clearGlobals() {
|
|
1279
|
-
delete global.describe;
|
|
1280
|
-
delete global.it;
|
|
1281
|
-
delete global.test;
|
|
1282
|
-
delete global.expect;
|
|
1283
|
-
delete global.beforeAll;
|
|
1284
|
-
delete global.afterAll;
|
|
1285
|
-
delete global.beforeEach;
|
|
1286
|
-
delete global.afterEach;
|
|
1287
|
-
delete global.vi;
|
|
1288
|
-
}
|
|
1289
|
-
function getCoveredFiles() {
|
|
1290
|
-
return coveredFiles;
|
|
1291
|
-
}
|
|
1292
|
-
function resetCoveredFiles() {
|
|
1293
|
-
coveredFiles.clear();
|
|
1294
|
-
}
|
|
1295
1252
|
export {
|
|
1296
1253
|
clearGlobals,
|
|
1297
1254
|
getCoveredFiles,
|