qunitx-cli 0.17.8 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +75 -45
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -488,12 +488,18 @@ function dumpValue(value, indent) {
488
488
  if (Array.isArray(value)) {
489
489
  if (value.length === 0) return "[]";
490
490
  const next2 = `${indent} `;
491
- return "\n" + value.map((item) => `${next2}- ${dumpValue(item, next2)}`).join("\n");
491
+ return "\n" + value.map((item) => {
492
+ const v = dumpValue(item, next2);
493
+ return v[0] === "\n" ? `${next2}-${v}` : `${next2}- ${v}`;
494
+ }).join("\n");
492
495
  }
493
496
  const entries = Object.entries(value);
494
497
  if (entries.length === 0) return "{}";
495
498
  const next = `${indent} `;
496
- return "\n" + entries.map(([entryKey, entryValue]) => `${next}${entryKey}: ${dumpValue(entryValue, next)}`).join("\n");
499
+ return "\n" + entries.map(([entryKey, entryValue]) => {
500
+ const v = dumpValue(entryValue, next);
501
+ return v[0] === "\n" ? `${next}${entryKey}:${v}` : `${next}${entryKey}: ${v}`;
502
+ }).join("\n");
497
503
  }
498
504
  function yamlLine(key, value) {
499
505
  const serialized = dumpValue(value, "");
@@ -510,12 +516,12 @@ function dumpYaml({
510
516
  at
511
517
  }) {
512
518
  return `name: ${dumpString(name, "")}
513
- ` + yamlLine("actual", actual) + yamlLine("expected", expected) + yamlLine("message", message) + yamlLine("stack", stack) + yamlLine("at", at);
519
+ ` + yamlLine("actual", actual) + yamlLine("expected", expected) + (message !== null ? yamlLine("message", message) : "") + (stack !== null ? yamlLine("stack", stack) : "") + (at !== null ? yamlLine("at", at) : "");
514
520
  }
515
521
  var NEEDS_QUOTING;
516
522
  var init_dump_yaml = __esm({
517
523
  "lib/tap/dump-yaml.ts"() {
518
- NEEDS_QUOTING = /^$|^(null|true|false|~|yes|no|on|off|y|n)$|^[{[!|>'"#%@`]|^[-?:](\s|$)|^---|^[-+]?(\d|\.\d)|^\d{4}-\d{2}-\d{2}|: |#/i;
524
+ NEEDS_QUOTING = /^$|^\s|^(null|true|false|~|yes|no|on|off|y|n)$|^[{[!|>'"#%@`]|^[-?:](\s|$)|^---|^[-+]?(\d|\.\d)|^\d{4}-\d{2}-\d{2}|: |#/i;
519
525
  }
520
526
  });
521
527
 
@@ -538,46 +544,55 @@ function TAPDisplayTestResult(COUNTER, details) {
538
544
  COUNTER.testCount++;
539
545
  if (details.status === "skipped") {
540
546
  COUNTER.skipCount++;
541
- console.log(`ok ${COUNTER.testCount}`, details.fullName.join(" | "), "# skip");
547
+ process.stdout.write(`ok ${COUNTER.testCount} ${details.fullName.join(" | ")} # skip
548
+ `);
542
549
  } else if (details.status === "todo") {
543
- console.log(`not ok ${COUNTER.testCount}`, details.fullName.join(" | "), "# skip");
550
+ process.stdout.write(`not ok ${COUNTER.testCount} ${details.fullName.join(" | ")} # skip
551
+ `);
544
552
  } else if (details.status === "failed") {
545
553
  COUNTER.failCount++;
546
- console.log(
547
- `not ok ${COUNTER.testCount}`,
548
- details.fullName.join(" | "),
549
- `# (${details.runtime.toFixed(0)} ms)`
554
+ process.stdout.write(
555
+ `not ok ${COUNTER.testCount} ${details.fullName.join(" | ")} # (${details.runtime.toFixed(0)} ms)
556
+ `
550
557
  );
551
558
  details.assertions.forEach((assertion, index) => {
552
559
  if (!assertion.passed && assertion.todo === false) {
553
560
  COUNTER.errorCount = (COUNTER.errorCount ?? 0) + 1;
554
- const stack = assertion.stack?.match(/\(.+\)/g);
555
- console.log(" ---");
556
- console.log(
561
+ process.stdout.write(" ---\n");
562
+ process.stdout.write(
557
563
  indentString(
558
564
  dumpYaml({
559
565
  name: `Assertion #${index + 1}`,
560
- actual: assertion.actual ? JSON.parse(JSON.stringify(assertion.actual, getCircularReplacer())) : assertion.actual,
561
- expected: assertion.expected ? JSON.parse(JSON.stringify(assertion.expected, getCircularReplacer())) : assertion.expected,
566
+ actual: assertion.actual !== null && typeof assertion.actual === "object" ? JSON.parse(JSON.stringify(assertion.actual, getCircularReplacer())) : assertion.actual,
567
+ expected: assertion.expected !== null && typeof assertion.expected === "object" ? JSON.parse(JSON.stringify(assertion.expected, getCircularReplacer())) : assertion.expected,
562
568
  message: assertion.message || null,
563
- stack: assertion.stack || null,
564
- at: stack ? stack[0].replace("(file://", "").replace(")", "") : null
569
+ // Trim leading/trailing whitespace: Chrome stacks start with " at ..."
570
+ // (4 spaces per frame) which would otherwise render as "stack: at ..." in YAML.
571
+ stack: assertion.stack?.trim() || null,
572
+ at: extractStackAt(assertion.stack)
565
573
  }),
566
574
  4
567
575
  )
568
576
  );
569
- console.log(" ...");
577
+ process.stdout.write(" ...\n");
570
578
  }
571
579
  });
572
580
  } else if (details.status === "passed") {
573
581
  COUNTER.passCount++;
574
- console.log(
575
- `ok ${COUNTER.testCount}`,
576
- details.fullName.join(" | "),
577
- `# (${details.runtime.toFixed(0)} ms)`
582
+ process.stdout.write(
583
+ `ok ${COUNTER.testCount} ${details.fullName.join(" | ")} # (${details.runtime.toFixed(0)} ms)
584
+ `
578
585
  );
579
586
  }
580
587
  }
588
+ function extractStackAt(stack) {
589
+ if (!stack) return null;
590
+ const chromeMatch = stack.match(/\(([^)\n]+:[0-9]+:[0-9]+)\)/);
591
+ if (chromeMatch) return chromeMatch[1].replace("file://", "");
592
+ const geckoMatch = stack.match(/@([^\s\n@]+:[0-9]+:[0-9]+)/);
593
+ if (geckoMatch) return geckoMatch[1];
594
+ return null;
595
+ }
581
596
  function getCircularReplacer() {
582
597
  const ancestors = [];
583
598
  return function(_key, value) {
@@ -898,7 +913,7 @@ function setupWebServer(config, cachedContent) {
898
913
  config._onWsOpen?.();
899
914
  } else if (event === "connection") {
900
915
  config._phase = "running";
901
- if (!config._groupMode) console.log("TAP version 13");
916
+ if (!config._groupMode) process.stdout.write("TAP version 13\n");
902
917
  if (config.debug && config._groupMode) {
903
918
  const allFiles = Object.keys(config.fsTree);
904
919
  const relFiles = allFiles.map(
@@ -907,7 +922,8 @@ function setupWebServer(config, cachedContent) {
907
922
  const shown = relFiles.slice(0, 2);
908
923
  const rest = relFiles.length - shown.length;
909
924
  const fileList = rest > 0 ? `${shown.join(" ")} +${rest} more` : shown.join(" ");
910
- console.log("#", blue(`\u2500\u2500 ${fileList} \u2500\u2500`));
925
+ process.stdout.write(`# ${blue(`\u2500\u2500 ${fileList} \u2500\u2500`)}
926
+ `);
911
927
  }
912
928
  config._resetTestTimeout?.();
913
929
  } else if (event === "testEnd" && !abort) {
@@ -915,8 +931,9 @@ function setupWebServer(config, cachedContent) {
915
931
  config.lastFailedTestFiles = config.lastRanTestFiles;
916
932
  }
917
933
  if (config.debug && details.runtime > config.timeout * 0.8) {
918
- console.log(
919
- `# SLOW (${details.runtime.toFixed(0)}ms / ${config.timeout}ms timeout): ${details.fullName.join(" | ")}`
934
+ process.stdout.write(
935
+ `# SLOW (${details.runtime.toFixed(0)}ms / ${config.timeout}ms timeout): ${details.fullName.join(" | ")}
936
+ `
920
937
  );
921
938
  }
922
939
  config._resetTestTimeout?.();
@@ -924,8 +941,9 @@ function setupWebServer(config, cachedContent) {
924
941
  } else if (event === "done") {
925
942
  config._phase = "done";
926
943
  if (config.debug && config._groupMode) {
927
- console.log(
928
- `# group done: ${details.passed} passed, ${details.failed} failed (${details.runtime}ms)`
944
+ process.stdout.write(
945
+ `# group done: ${details.passed} passed, ${details.failed} failed (${details.runtime}ms)
946
+ `
929
947
  );
930
948
  }
931
949
  if (typeof config._testRunDone === "function") {
@@ -937,8 +955,9 @@ function setupWebServer(config, cachedContent) {
937
955
  });
938
956
  server.get("/tests.js", (_req, res) => {
939
957
  const bytes = cachedContent.allTestCode?.length ?? null;
940
- console.log(
941
- `# [HTTPServer] GET /tests.js \u2192 ${bytes !== null ? `${bytes} bytes` : "NOT READY (allTestCode is null)"}`
958
+ process.stdout.write(
959
+ `# [HTTPServer] GET /tests.js \u2192 ${bytes !== null ? `${bytes} bytes` : "NOT READY (allTestCode is null)"}
960
+ `
942
961
  );
943
962
  if (bytes === null) {
944
963
  res.writeHead(503, { "Content-Type": "application/javascript", "Cache-Control": "no-store" });
@@ -953,8 +972,9 @@ function setupWebServer(config, cachedContent) {
953
972
  });
954
973
  server.get("/filtered-tests.js", (_req, res) => {
955
974
  const bytes = cachedContent.filteredTestCode?.length ?? null;
956
- console.log(
957
- `# [HTTPServer] GET /filtered-tests.js \u2192 ${bytes !== null ? `${bytes} bytes` : "NOT READY (filteredTestCode is null)"}`
975
+ process.stdout.write(
976
+ `# [HTTPServer] GET /filtered-tests.js \u2192 ${bytes !== null ? `${bytes} bytes` : "NOT READY (filteredTestCode is null)"}
977
+ `
958
978
  );
959
979
  if (bytes === null) {
960
980
  res.writeHead(503, { "Content-Type": "application/javascript", "Cache-Control": "no-store" });
@@ -1026,7 +1046,10 @@ function setupWebServer(config, cachedContent) {
1026
1046
  } else {
1027
1047
  fs8.createReadStream(filePath).pipe(res);
1028
1048
  }
1029
- console.log(`# [HTTPServer] GET ${url} ${statusCode} - ${/* @__PURE__ */ new Date() - requestStartedAt}ms`);
1049
+ process.stdout.write(
1050
+ `# [HTTPServer] GET ${url} ${statusCode} - ${/* @__PURE__ */ new Date() - requestStartedAt}ms
1051
+ `
1052
+ );
1030
1053
  });
1031
1054
  return server;
1032
1055
  }
@@ -1366,14 +1389,20 @@ var init_run_user_module = __esm({
1366
1389
 
1367
1390
  // lib/tap/display-final-result.ts
1368
1391
  function TAPDisplayFinalResult({ testCount, passCount, skipCount, failCount }, timeTaken) {
1369
- console.log("");
1370
- console.log(`1..${testCount}`);
1371
- console.log(`# tests ${testCount}`);
1372
- console.log(`# pass ${passCount}`);
1373
- console.log(`# skip ${skipCount}`);
1374
- console.log(`# fail ${failCount}`);
1375
- console.log(`# duration ${timeTaken}`);
1376
- console.log("");
1392
+ process.stdout.write("\n");
1393
+ process.stdout.write(`1..${testCount}
1394
+ `);
1395
+ process.stdout.write(`# tests ${testCount}
1396
+ `);
1397
+ process.stdout.write(`# pass ${passCount}
1398
+ `);
1399
+ process.stdout.write(`# skip ${skipCount}
1400
+ `);
1401
+ process.stdout.write(`# fail ${failCount}
1402
+ `);
1403
+ process.stdout.write(`# duration ${timeTaken}
1404
+ `);
1405
+ process.stdout.write("\n");
1377
1406
  }
1378
1407
  var init_display_final_result = __esm({
1379
1408
  "lib/tap/display-final-result.ts"() {
@@ -2026,9 +2055,10 @@ async function run(config) {
2026
2055
  _phase: "bundling"
2027
2056
  }));
2028
2057
  const groupCachedContents = groups.map(() => ({ ...cachedContent }));
2029
- console.log("TAP version 13");
2030
- console.log(
2031
- `# Running ${allFiles.length} test file${allFiles.length === 1 ? "" : "s"} across ${groupCount} group${groupCount === 1 ? "" : "s"}`
2058
+ process.stdout.write("TAP version 13\n");
2059
+ process.stdout.write(
2060
+ `# Running ${allFiles.length} test file${allFiles.length === 1 ? "" : "s"} across ${groupCount} group${groupCount === 1 ? "" : "s"}
2061
+ `
2032
2062
  );
2033
2063
  const [browser] = await Promise.all([
2034
2064
  launchBrowser(config),
@@ -2226,7 +2256,7 @@ init_color();
2226
2256
  var package_default = {
2227
2257
  name: "qunitx-cli",
2228
2258
  type: "module",
2229
- version: "0.17.8",
2259
+ version: "0.18.0",
2230
2260
  description: "Browser runner for QUnitx: run your qunitx tests in google-chrome",
2231
2261
  author: "Izel Nakri",
2232
2262
  license: "MIT",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "qunitx-cli",
3
3
  "type": "module",
4
- "version": "0.17.8",
4
+ "version": "0.18.0",
5
5
  "description": "Browser runner for QUnitx: run your qunitx tests in google-chrome",
6
6
  "author": "Izel Nakri",
7
7
  "license": "MIT",