elit 3.6.4 → 3.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,6 +77,52 @@ function readFileSync(path, options) {
77
77
  }
78
78
  throw new Error("Unsupported runtime");
79
79
  }
80
+ function existsSync(path) {
81
+ try {
82
+ statSync(path);
83
+ return true;
84
+ } catch {
85
+ return false;
86
+ }
87
+ }
88
+ function statSync(path) {
89
+ if (isNode || isBun) {
90
+ return fs.statSync(path);
91
+ } else if (isDeno) {
92
+ const info = Deno.statSync(path);
93
+ return createStatsFromDenoFileInfo(info);
94
+ }
95
+ throw new Error("Unsupported runtime");
96
+ }
97
+ function createStatsFromDenoFileInfo(info) {
98
+ return {
99
+ isFile: () => info.isFile,
100
+ isDirectory: () => info.isDirectory,
101
+ isBlockDevice: () => false,
102
+ isCharacterDevice: () => false,
103
+ isSymbolicLink: () => info.isSymlink || false,
104
+ isFIFO: () => false,
105
+ isSocket: () => false,
106
+ dev: info.dev || 0,
107
+ ino: info.ino || 0,
108
+ mode: info.mode || 0,
109
+ nlink: info.nlink || 1,
110
+ uid: info.uid || 0,
111
+ gid: info.gid || 0,
112
+ rdev: 0,
113
+ size: info.size,
114
+ blksize: info.blksize || 4096,
115
+ blocks: info.blocks || Math.ceil(info.size / 512),
116
+ atimeMs: info.atime?.getTime() || Date.now(),
117
+ mtimeMs: info.mtime?.getTime() || Date.now(),
118
+ ctimeMs: info.birthtime?.getTime() || Date.now(),
119
+ birthtimeMs: info.birthtime?.getTime() || Date.now(),
120
+ atime: info.atime || /* @__PURE__ */ new Date(),
121
+ mtime: info.mtime || /* @__PURE__ */ new Date(),
122
+ ctime: info.birthtime || /* @__PURE__ */ new Date(),
123
+ birthtime: info.birthtime || /* @__PURE__ */ new Date()
124
+ };
125
+ }
80
126
 
81
127
  // src/path.ts
82
128
  function getSeparator(isWin) {
@@ -324,12 +370,16 @@ var testPattern = void 0;
324
370
  var currentTestFile = void 0;
325
371
  var currentSourceMapConsumer = void 0;
326
372
  var wrapperLineOffset = 0;
327
- async function transpileFile(filePath) {
328
- const source = await readFile(filePath, "utf-8");
329
- const result = (0, import_esbuild.transformSync)(source, {
330
- loader: filePath.endsWith(".ts") || filePath.endsWith(".tsx") ? "ts" : "js",
331
- format: "esm",
332
- sourcemap: "inline",
373
+ var TEST_MODULE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".json"];
374
+ function resolveTestLoader(filePath) {
375
+ return /\.(?:ts|tsx|mts|cts)$/i.test(filePath) ? "ts" : "js";
376
+ }
377
+ function createTestTransformOptions(filePath, format, sourcemap) {
378
+ return {
379
+ loader: resolveTestLoader(filePath),
380
+ format,
381
+ sourcemap,
382
+ sourcefile: filePath,
333
383
  target: "es2020",
334
384
  tsconfigRaw: {
335
385
  compilerOptions: {
@@ -338,7 +388,106 @@ async function transpileFile(filePath) {
338
388
  jsxFragmentFactory: "Fragment"
339
389
  }
340
390
  }
341
- });
391
+ };
392
+ }
393
+ function resolveExistingTestModulePath(basePath) {
394
+ const nodePath = require("path");
395
+ if (existsSync(basePath) && statSync(basePath).isFile()) {
396
+ return basePath;
397
+ }
398
+ for (const extension of TEST_MODULE_EXTENSIONS) {
399
+ const candidatePath = `${basePath}${extension}`;
400
+ if (existsSync(candidatePath) && statSync(candidatePath).isFile()) {
401
+ return candidatePath;
402
+ }
403
+ }
404
+ if (existsSync(basePath) && statSync(basePath).isDirectory()) {
405
+ const packageJsonPath = nodePath.join(basePath, "package.json");
406
+ if (existsSync(packageJsonPath) && statSync(packageJsonPath).isFile()) {
407
+ try {
408
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
409
+ for (const candidateEntry of [packageJson.main, packageJson.module]) {
410
+ if (typeof candidateEntry !== "string" || candidateEntry.trim().length === 0) {
411
+ continue;
412
+ }
413
+ try {
414
+ return resolveExistingTestModulePath(nodePath.resolve(basePath, candidateEntry));
415
+ } catch {
416
+ continue;
417
+ }
418
+ }
419
+ } catch {
420
+ }
421
+ }
422
+ for (const extension of TEST_MODULE_EXTENSIONS) {
423
+ const candidatePath = nodePath.join(basePath, `index${extension}`);
424
+ if (existsSync(candidatePath) && statSync(candidatePath).isFile()) {
425
+ return candidatePath;
426
+ }
427
+ }
428
+ }
429
+ return basePath;
430
+ }
431
+ function resolveTestModulePath(fromFilePath, specifier) {
432
+ if (!specifier.startsWith(".") && !specifier.startsWith("/")) {
433
+ return specifier;
434
+ }
435
+ const nodePath = require("path");
436
+ const basePath = specifier.startsWith(".") ? nodePath.resolve(dirname(fromFilePath), specifier) : specifier;
437
+ return resolveExistingTestModulePath(basePath);
438
+ }
439
+ function shouldTranspileTestModule(filePath) {
440
+ return /\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs)$/i.test(filePath);
441
+ }
442
+ function createTestModuleRequire(fromFilePath, moduleCache) {
443
+ return (specifier) => {
444
+ if (specifier.startsWith("elit/") || specifier === "elit") {
445
+ return require(specifier);
446
+ }
447
+ const resolvedPath = resolveTestModulePath(fromFilePath, specifier);
448
+ if (resolvedPath === specifier) {
449
+ return require(specifier);
450
+ }
451
+ if (!existsSync(resolvedPath) || !statSync(resolvedPath).isFile()) {
452
+ return require(resolvedPath);
453
+ }
454
+ if (!shouldTranspileTestModule(resolvedPath)) {
455
+ return require(resolvedPath);
456
+ }
457
+ return loadTranspiledTestModule(resolvedPath, moduleCache);
458
+ };
459
+ }
460
+ function loadTranspiledTestModule(modulePath, moduleCache) {
461
+ const cached = moduleCache.get(modulePath);
462
+ if (cached) {
463
+ return cached.exports;
464
+ }
465
+ const source = readFileSync(modulePath, "utf-8");
466
+ let transpiled;
467
+ try {
468
+ transpiled = (0, import_esbuild.transformSync)(source, createTestTransformOptions(modulePath, "cjs", false));
469
+ } catch (error) {
470
+ throw new Error(`Failed to transpile test dependency ${modulePath}: ${error instanceof Error ? error.message : String(error)}`);
471
+ }
472
+ const moduleRecord = { exports: {} };
473
+ const moduleObj = { exports: moduleRecord.exports };
474
+ moduleCache.set(modulePath, moduleRecord);
475
+ try {
476
+ const fn = new Function("module", "exports", "require", "__filename", "__dirname", transpiled.code);
477
+ const requireFn = createTestModuleRequire(modulePath, moduleCache);
478
+ fn(moduleObj, moduleObj.exports, requireFn, modulePath, dirname(modulePath));
479
+ } catch (error) {
480
+ throw new Error(`Failed to execute test dependency ${modulePath}: ${error instanceof Error ? error.message : String(error)}`);
481
+ }
482
+ moduleRecord.exports = moduleObj.exports;
483
+ if (!modulePath.includes(".test.") && !modulePath.includes(".spec.")) {
484
+ coveredFiles.add(modulePath);
485
+ }
486
+ return moduleRecord.exports;
487
+ }
488
+ async function transpileFile(filePath) {
489
+ const source = await readFile(filePath, "utf-8");
490
+ const result = (0, import_esbuild.transformSync)(source, createTestTransformOptions(filePath, "esm", "inline"));
342
491
  let sourceMap;
343
492
  const sourceMapMatch = result.code.match(/\/\/# sourceMappingURL=data:application\/json;base64,(.+)/);
344
493
  if (sourceMapMatch) {
@@ -350,7 +499,7 @@ async function transpileFile(filePath) {
350
499
  }
351
500
  function createTestFunction(defaultTimeout = 5e3) {
352
501
  const testFn = function(name, fn, timeout) {
353
- const test2 = {
502
+ const test = {
354
503
  name,
355
504
  fn,
356
505
  skip: currentSuite.skip,
@@ -359,10 +508,10 @@ function createTestFunction(defaultTimeout = 5e3) {
359
508
  timeout: timeout ?? defaultTimeout,
360
509
  suite: currentSuite
361
510
  };
362
- currentSuite.tests.push(test2);
511
+ currentSuite.tests.push(test);
363
512
  };
364
513
  testFn.skip = (name, fn, timeout) => {
365
- const test2 = {
514
+ const test = {
366
515
  name,
367
516
  fn,
368
517
  skip: true,
@@ -371,11 +520,11 @@ function createTestFunction(defaultTimeout = 5e3) {
371
520
  timeout: timeout ?? defaultTimeout,
372
521
  suite: currentSuite
373
522
  };
374
- currentSuite.tests.push(test2);
523
+ currentSuite.tests.push(test);
375
524
  };
376
525
  testFn.only = (name, fn, timeout) => {
377
526
  hasOnly = true;
378
- const test2 = {
527
+ const test = {
379
528
  name,
380
529
  fn,
381
530
  skip: false,
@@ -384,10 +533,10 @@ function createTestFunction(defaultTimeout = 5e3) {
384
533
  timeout: timeout ?? defaultTimeout,
385
534
  suite: currentSuite
386
535
  };
387
- currentSuite.tests.push(test2);
536
+ currentSuite.tests.push(test);
388
537
  };
389
538
  testFn.todo = (name, fn, timeout) => {
390
- const test2 = {
539
+ const test = {
391
540
  name,
392
541
  fn,
393
542
  skip: false,
@@ -396,7 +545,7 @@ function createTestFunction(defaultTimeout = 5e3) {
396
545
  timeout: timeout ?? defaultTimeout,
397
546
  suite: currentSuite
398
547
  };
399
- currentSuite.tests.push(test2);
548
+ currentSuite.tests.push(test);
400
549
  };
401
550
  return testFn;
402
551
  }
@@ -962,29 +1111,7 @@ async function runTests(options) {
962
1111
  try {
963
1112
  const source = await readFile(file, "utf-8");
964
1113
  const testFileDir = dirname(file);
965
- const importRegex = /import\s+{\s*([^}]+)\s*}\s+from\s+['"]([^'"]+)['"]/g;
966
- const imports = {};
967
- let importIndex = 0;
968
- let codeWithoutImports = source.replace(importRegex, (_, named, path) => {
969
- const varName = `__import_${importIndex++}`;
970
- const trimmedNamed = named.trim();
971
- imports[varName] = { path, named: trimmedNamed };
972
- return `// ${trimmedNamed} import injected later
973
- `;
974
- });
975
- const result = (0, import_esbuild.transformSync)(codeWithoutImports, {
976
- loader: file.endsWith(".ts") || file.endsWith(".tsx") ? "ts" : "js",
977
- format: "iife",
978
- sourcemap: "inline",
979
- target: "es2020",
980
- tsconfigRaw: {
981
- compilerOptions: {
982
- jsx: "react",
983
- jsxFactory: "h",
984
- jsxFragmentFactory: "Fragment"
985
- }
986
- }
987
- });
1114
+ const result = (0, import_esbuild.transformSync)(source, createTestTransformOptions(file, "cjs", "inline"));
988
1115
  let code = result.code;
989
1116
  const sourceMapMatch = code.match(/\/\/# sourceMappingURL=data:application\/json;base64,(.+)/);
990
1117
  if (sourceMapMatch) {
@@ -995,99 +1122,15 @@ async function runTests(options) {
995
1122
  } else {
996
1123
  currentSourceMapConsumer = void 0;
997
1124
  }
998
- const importedValues = {};
999
- const importParamNames = [];
1000
- const importAssignments = [];
1001
- if (Object.keys(imports).length > 0) {
1002
- for (const [, { path, named }] of Object.entries(imports)) {
1003
- let resolvedPath = path;
1004
- if (path.startsWith(".")) {
1005
- const nodePath = require("path");
1006
- resolvedPath = nodePath.resolve(testFileDir, path);
1007
- }
1008
- if (!resolvedPath.endsWith(".ts") && !resolvedPath.endsWith(".js") && !resolvedPath.endsWith(".mjs") && !resolvedPath.endsWith(".cjs")) {
1009
- resolvedPath += ".ts";
1010
- }
1011
- if (resolvedPath.endsWith(".ts")) {
1012
- try {
1013
- const importSource = await readFile(resolvedPath, "utf-8");
1014
- const transpiled = (0, import_esbuild.transformSync)(importSource, {
1015
- loader: "ts",
1016
- format: "cjs",
1017
- target: "es2020",
1018
- tsconfigRaw: {
1019
- compilerOptions: {
1020
- jsx: "react",
1021
- jsxFactory: "h",
1022
- jsxFragmentFactory: "Fragment"
1023
- }
1024
- }
1025
- });
1026
- const moduleExports = {};
1027
- const moduleObj = { exports: moduleExports };
1028
- const fn2 = new Function("module", "exports", "require", "__filename", "__dirname", transpiled.code);
1029
- const requireFn = (id) => {
1030
- if (id.startsWith("elit/") || id === "elit") {
1031
- return require(id);
1032
- }
1033
- if (id.startsWith(".")) {
1034
- const nodePath = require("path");
1035
- const absPath = nodePath.resolve(dirname(resolvedPath), id);
1036
- return require(absPath);
1037
- }
1038
- return require(id);
1039
- };
1040
- fn2(moduleObj, moduleExports, requireFn, resolvedPath, dirname(resolvedPath));
1041
- if (!resolvedPath.includes(".test.") && !resolvedPath.includes(".spec.")) {
1042
- coveredFiles.add(resolvedPath);
1043
- }
1044
- let exportedValue = moduleObj.exports[named];
1045
- if (exportedValue === void 0 && moduleObj.exports.default) {
1046
- exportedValue = moduleObj.exports.default[named];
1047
- }
1048
- if (exportedValue === void 0 && typeof moduleObj.exports === "object") {
1049
- exportedValue = moduleObj.exports[named];
1050
- }
1051
- const paramKey = `__import_${Math.random().toString(36).substring(2, 11)}`;
1052
- importedValues[paramKey] = exportedValue;
1053
- importParamNames.push(paramKey);
1054
- importAssignments.push(`const ${named} = ${paramKey};`);
1055
- } catch (err) {
1056
- const paramKey = `__import_${Math.random().toString(36).substring(2, 11)}`;
1057
- importedValues[paramKey] = null;
1058
- importParamNames.push(paramKey);
1059
- importAssignments.push(`const ${named} = ${paramKey}; /* Error importing ${resolvedPath}: ${err} */`);
1060
- }
1061
- } else {
1062
- const requiredModule = require(resolvedPath);
1063
- const exportedValue = requiredModule[named];
1064
- const paramKey = `__import_${Math.random().toString(36).substring(2, 11)}`;
1065
- importedValues[paramKey] = exportedValue;
1066
- importParamNames.push(paramKey);
1067
- importAssignments.push(`const ${named} = ${paramKey};`);
1068
- }
1069
- }
1070
- }
1071
- let preamble = "";
1072
- if (Object.keys(imports).length > 0) {
1073
- const iifeStartMatch = code.match(/^(\s*(?:var\s+\w+\s*=\s*)?\(\(\)\s*=>\s*\{\n)/);
1074
- if (iifeStartMatch) {
1075
- const iifePrefix = iifeStartMatch[1];
1076
- const assignments = `${importAssignments.join("\n")}
1077
- `;
1078
- preamble = iifePrefix;
1079
- code = iifePrefix + assignments + code.slice(iifeStartMatch[1].length);
1080
- } else {
1081
- preamble = importAssignments.join("\n") + "\n";
1082
- code = preamble + code;
1083
- }
1084
- }
1085
- wrapperLineOffset = preamble.split("\n").length;
1125
+ wrapperLineOffset = 0;
1086
1126
  setupGlobals();
1087
- const allParams = ["describe", "it", "test", "expect", "beforeAll", "afterAll", "beforeEach", "afterEach", "vi", "require", "module", "__filename", "__dirname", ...importParamNames];
1088
- const allArgs = [describe, it, test, expect, beforeAll, afterAll, beforeEach, afterEach, vi, require, module, file, testFileDir, ...importParamNames.map((p) => importedValues[p])];
1089
- const fn = new Function(...allParams, code);
1090
- await fn(...allArgs);
1127
+ const moduleCache = /* @__PURE__ */ new Map();
1128
+ const moduleRecord = { exports: {} };
1129
+ const moduleObj = { exports: moduleRecord.exports };
1130
+ moduleCache.set(file, moduleRecord);
1131
+ const fn = new Function("module", "exports", "require", "__filename", "__dirname", code);
1132
+ const requireFn = createTestModuleRequire(file, moduleCache);
1133
+ await fn(moduleObj, moduleObj.exports, requireFn, file, testFileDir);
1091
1134
  await executeSuite(currentSuite, timeout, bail);
1092
1135
  if (currentSourceMapConsumer) {
1093
1136
  currentSourceMapConsumer.destroy();
@@ -1152,22 +1195,22 @@ async function executeSuite(suite, timeout, bail, parentMatched = false) {
1152
1195
  for (const hook of beforeAllHooks) {
1153
1196
  await hook();
1154
1197
  }
1155
- for (const test2 of suite.tests) {
1156
- if (hasOnly && !test2.only && !suite.only) {
1198
+ for (const test of suite.tests) {
1199
+ if (hasOnly && !test.only && !suite.only) {
1157
1200
  continue;
1158
1201
  }
1159
1202
  let testMatches = true;
1160
1203
  if (testPattern) {
1161
1204
  const escapedPattern = escapeRegex(testPattern);
1162
1205
  const regex = new RegExp(escapedPattern, "i");
1163
- testMatches = regex.test(test2.name);
1206
+ testMatches = regex.test(test.name);
1164
1207
  }
1165
1208
  if (!testMatches) {
1166
1209
  continue;
1167
1210
  }
1168
- if (test2.skip || suite.skip) {
1211
+ if (test.skip || suite.skip) {
1169
1212
  testResults.push({
1170
- name: test2.name,
1213
+ name: test.name,
1171
1214
  status: "skip",
1172
1215
  duration: 0,
1173
1216
  suite: suite.name,
@@ -1175,9 +1218,9 @@ async function executeSuite(suite, timeout, bail, parentMatched = false) {
1175
1218
  });
1176
1219
  continue;
1177
1220
  }
1178
- if (test2.todo) {
1221
+ if (test.todo) {
1179
1222
  testResults.push({
1180
- name: test2.name,
1223
+ name: test.name,
1181
1224
  status: "todo",
1182
1225
  duration: 0,
1183
1226
  suite: suite.name,
@@ -1191,13 +1234,13 @@ async function executeSuite(suite, timeout, bail, parentMatched = false) {
1191
1234
  const startTime = Date.now();
1192
1235
  try {
1193
1236
  await Promise.race([
1194
- test2.fn(),
1237
+ test.fn(),
1195
1238
  new Promise(
1196
- (_, reject) => setTimeout(() => reject(new Error(`Test timed out after ${test2.timeout}ms`)), test2.timeout)
1239
+ (_, reject) => setTimeout(() => reject(new Error(`Test timed out after ${test.timeout}ms`)), test.timeout)
1197
1240
  )
1198
1241
  ]);
1199
1242
  testResults.push({
1200
- name: test2.name,
1243
+ name: test.name,
1201
1244
  status: "pass",
1202
1245
  duration: Date.now() - startTime,
1203
1246
  suite: suite.name,
@@ -1211,7 +1254,7 @@ async function executeSuite(suite, timeout, bail, parentMatched = false) {
1211
1254
  codeSnippet = error.codeSnippet;
1212
1255
  }
1213
1256
  testResults.push({
1214
- name: test2.name,
1257
+ name: test.name,
1215
1258
  status: "fail",
1216
1259
  duration: Date.now() - startTime,
1217
1260
  error,