@epikodelabs/testify 1.0.17 → 1.0.19

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Oleksii Shepel
3
+ Copyright (c) 2026 Oleksii Shepel
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # testify
2
2
 
3
- A flexible test runner for Jasmine that supports multiple execution environments with built-in TypeScript compilation, hot module reloading, and code coverage.
3
+ A flexible test runner for the Jasmine testing framework that supports multiple execution environments with built-in TypeScript compilation, hot module reloading, and code coverage.
4
4
 
5
- > “**testify** doesnt mock the browser. It invites the browser into the courtroom and asks it to testify under oath.”
5
+ > ⚖️ “*testify doesn't mock the browser. It invites the browser into the courtroom and asks it to testify under oath.*”
6
6
 
7
7
  <p align="center">
8
8
  <a href="https://github.com/epikodelabs/testify/actions/workflows/build.yml">
@@ -36,24 +36,6 @@ If testify helps you, please give it a star: https://github.com/epikodelabs/test
36
36
  - 🎯 Interactive browser-based test reporter
37
37
  - 🔧 VS Code debug integration for single-spec debugging
38
38
 
39
- ### Why "testify"?
40
-
41
- Look, we'll be honest. Coming up with a testing library name in 2025 is like trying to find a good username on Twitter in 2010. Everything's taken. We considered:
42
-
43
- - `test-runner` - Too generic (also taken)
44
- - `jasmine-tester` - Too obvious (also taken)
45
- - `vite-jasmine-runner` - Too long (and, you guessed it, taken)
46
- - `super-mega-awesome-test-framework` - Too humble
47
-
48
- So we landed on `testify` because:
49
- 1. Your tests should be able to testify about your code in court 🧑‍⚖️
50
- 2. It sounds vaguely spiritual, which you'll need when debugging flaky tests 🙏
51
- 3. The npm package name was actually available 🎉
52
- 4. It has the word "test" in it (we're nothing if not literal)
53
-
54
- > **⚖️ The testify Promise**
55
- > *testify doesn't mock the browser. It invites the browser into the courtroom and asks it to testify under oath.*
56
-
57
39
  ---
58
40
 
59
41
  ## 📦 Installation
@@ -355,6 +337,9 @@ Or manually add this configuration:
355
337
  ],
356
338
  "program": "${workspaceFolder}/node_modules/@epikodelabs/testify/bin/jasmine",
357
339
  "args": ["--spec", "${file}"],
340
+ "env": {
341
+ "TS_NODE_PROJECT": "${workspaceFolder}/tsconfig.json"
342
+ },
358
343
  "cwd": "${workspaceFolder}",
359
344
  "console": "integratedTerminal",
360
345
  "skipFiles": ["<node_internals>/**"]
@@ -719,7 +704,7 @@ Coverage reports playing hide and seek? Make sure:
719
704
 
720
705
  ## 📜 License
721
706
 
722
- MIT © 2025
707
+ MIT © 2026
723
708
 
724
709
  ---
725
710
 
@@ -727,13 +712,11 @@ MIT © 2025
727
712
 
728
713
  - **Issues:** [GitHub Issues](https://github.com/epikodelabs/testify/issues)
729
714
  - **Documentation:** [GitHub Wiki](https://github.com/epikodelabs/testify/wiki)
730
- - **Changelog:** [CHANGELOG.md](./CHANGELOG.md)
731
715
 
732
716
  ---
733
717
 
734
718
  <p align="center">
735
719
  <strong>Get started</strong><br>
736
720
  <a href="https://www.npmjs.com/package/@epikodelabs/testify">Install from NPM</a> •
737
- <a href="https://github.com/epikodelabs/testify">View on GitHub</a>
738
- <a href="https://forms.gle/YOUR_FEEDBACK_FORM_ID">Give Feedback</a>
721
+ <a href="https://github.com/epikodelabs/testify">View on GitHub</a>
739
722
  </p>
package/bin/jasmine CHANGED
@@ -68,12 +68,12 @@ const __vitePreload = function preload(baseModule, deps, importerUrl) {
68
68
  const MAX_WIDTH = 63;
69
69
  const ANSI_FULL_REGEX = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\))/g;
70
70
  function wrapLine(text, width, indentation = 0, mode = "char") {
71
- text = text.replace(/\r?\n/g, " ").replace(/[\uFEFF\xA0\t]/g, " ").replace(/\s{2,}/g, " ").trim();
71
+ const normalized = text.replace(/\r?\n/g, "").replace(/[\uFEFF\xA0\t]/g, " ").replace(/\s{2,}/g, " ").trim();
72
72
  const indent = " ".repeat(indentation);
73
73
  const indentWidth = indent.length;
74
74
  if (width <= indentWidth) width = indentWidth + 1;
75
75
  const availableWidth = width - indentWidth;
76
- return mode === "char" ? wrapByChar(text, availableWidth, indent) : wrapByWord(text, availableWidth, indent);
76
+ return mode === "char" ? wrapByChar(normalized, availableWidth, indent) : wrapByWord(normalized, availableWidth, indent);
77
77
  }
78
78
  function wrapByChar(text, available, indent) {
79
79
  const lines = [];
@@ -186,8 +186,8 @@ class Logger {
186
186
  // ─── REFORMAT (RESTORED) ─────────────────────────────────
187
187
  reformat(text, opts) {
188
188
  const { width, align = "left", padChar = " " } = opts;
189
- const normalized = text.replace(/\r?\n/g, " ").replace(/[\uFEFF\xA0\t]/g, " ").replace(/\s{2,}/g, " ").trim();
190
- const lines = [];
189
+ const normalized = text.replace(/\r?\n/g, "").replace(/[\uFEFF\xA0\t]/g, " ").replace(/\s{2,}/g, " ").trim();
190
+ let result = [];
191
191
  let buf = "";
192
192
  let vis = 0;
193
193
  const tokens = normalized.split(
@@ -200,7 +200,7 @@ class Logger {
200
200
  }
201
201
  for (const ch of [...token]) {
202
202
  if (vis >= width) {
203
- lines.push(this.applyPadding(buf, vis, width, align, padChar));
203
+ result.push(this.applyPadding(buf, vis, width, align, padChar));
204
204
  buf = "";
205
205
  vis = 0;
206
206
  }
@@ -209,9 +209,9 @@ class Logger {
209
209
  }
210
210
  }
211
211
  if (buf) {
212
- lines.push(this.applyPadding(buf, vis, width, align, padChar));
212
+ result.push(this.applyPadding(buf, vis, width, align, padChar));
213
213
  }
214
- return lines;
214
+ return result;
215
215
  }
216
216
  applyPadding(text, visible, width, align, padChar) {
217
217
  const pad = Math.max(0, width - visible);
package/bin/testify CHANGED
@@ -1143,12 +1143,12 @@ class ConsoleReporter {
1143
1143
  }
1144
1144
  const ANSI_FULL_REGEX = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\))/g;
1145
1145
  function wrapLine(text, width, indentation = 0, mode = "char") {
1146
- text = text.replace(/\r?\n/g, " ").replace(/[\uFEFF\xA0\t]/g, " ").replace(/\s{2,}/g, " ").trim();
1146
+ const normalized = text.replace(/\r?\n/g, "").replace(/[\uFEFF\xA0\t]/g, " ").replace(/\s{2,}/g, " ").trim();
1147
1147
  const indent = " ".repeat(indentation);
1148
1148
  const indentWidth = indent.length;
1149
1149
  if (width <= indentWidth) width = indentWidth + 1;
1150
1150
  const availableWidth = width - indentWidth;
1151
- return mode === "char" ? wrapByChar(text, availableWidth, indent) : wrapByWord(text, availableWidth, indent);
1151
+ return mode === "char" ? wrapByChar(normalized, availableWidth, indent) : wrapByWord(normalized, availableWidth, indent);
1152
1152
  }
1153
1153
  function wrapByChar(text, available, indent) {
1154
1154
  const lines = [];
@@ -1261,8 +1261,8 @@ class Logger {
1261
1261
  // ─── REFORMAT (RESTORED) ─────────────────────────────────
1262
1262
  reformat(text, opts) {
1263
1263
  const { width, align = "left", padChar = " " } = opts;
1264
- const normalized = text.replace(/\r?\n/g, " ").replace(/[\uFEFF\xA0\t]/g, " ").replace(/\s{2,}/g, " ").trim();
1265
- const lines = [];
1264
+ const normalized = text.replace(/\r?\n/g, "").replace(/[\uFEFF\xA0\t]/g, " ").replace(/\s{2,}/g, " ").trim();
1265
+ let result = [];
1266
1266
  let buf = "";
1267
1267
  let vis = 0;
1268
1268
  const tokens = normalized.split(
@@ -1275,7 +1275,7 @@ class Logger {
1275
1275
  }
1276
1276
  for (const ch of [...token]) {
1277
1277
  if (vis >= width) {
1278
- lines.push(this.applyPadding(buf, vis, width, align, padChar));
1278
+ result.push(this.applyPadding(buf, vis, width, align, padChar));
1279
1279
  buf = "";
1280
1280
  vis = 0;
1281
1281
  }
@@ -1284,9 +1284,9 @@ class Logger {
1284
1284
  }
1285
1285
  }
1286
1286
  if (buf) {
1287
- lines.push(this.applyPadding(buf, vis, width, align, padChar));
1287
+ result.push(this.applyPadding(buf, vis, width, align, padChar));
1288
1288
  }
1289
- return lines;
1289
+ return result;
1290
1290
  }
1291
1291
  applyPadding(text, visible, width, align, padChar) {
1292
1292
  const pad = Math.max(0, width - visible);
@@ -2947,6 +2947,17 @@ export async function runTests(reporter) {
2947
2947
  process.exit(1);
2948
2948
  });
2949
2949
 
2950
+ // Only attach SIGINT/SIGTERM handlers if running as CLI entry
2951
+ if (import.meta.url === pathToFileURL(process.argv[1]).href) {
2952
+ function onExit(signal) {
2953
+ console.log(\`
2954
+ ⚙️ Caught \${signal}. Cleaning up...\`);
2955
+ process.exit(0);
2956
+ }
2957
+ process.on('SIGINT', onExit);
2958
+ process.on('SIGTERM', onExit);
2959
+ }
2960
+
2950
2961
  (async function () {
2951
2962
  try {
2952
2963
  // Load jasmine-core from testify's own node_modules
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epikodelabs/testify",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "Serve and run your Jasmine specs in a browser",
5
5
  "type": "module",
6
6
  "bin": {