poku 1.9.2 → 1.9.4

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/README.md CHANGED
@@ -10,10 +10,12 @@
10
10
  [ci-image]: https://img.shields.io/github/actions/workflow/status/wellwelwel/poku/ci.yml?event=push&style=flat&label=CI&branch=main
11
11
  [ql-url]: https://github.com/wellwelwel/poku/actions/workflows/codeql.yml?query=branch%3Amain
12
12
  [ql-image]: https://img.shields.io/github/actions/workflow/status/wellwelwel/poku/ci-codeql.yml?event=push&style=flat&label=Code%20QL&branch=main
13
- [license-url]: https://github.com/wellwelwel/poku/blob/main/LICENSE
14
- [license-image]: https://img.shields.io/npm/l/poku.svg?maxAge=2592000&color=9c88ff&label=License
13
+ [coverage-image]: https://img.shields.io/codecov/c/github/wellwelwel/poku?label=Coverage
14
+ [coverage-url]: https://app.codecov.io/github/wellwelwel/poku
15
15
  [downloads-image]: https://img.shields.io/npm/dt/poku.svg?&color=FFC312&label=Downloads
16
16
  [downloads-url]: https://npmjs.org/package/poku
17
+ [license-url]: https://github.com/wellwelwel/poku/blob/main/LICENSE
18
+ [license-image]: https://img.shields.io/npm/l/poku.svg?maxAge=2592000&color=9c88ff&label=License
17
19
 
18
20
  <div align="center">
19
21
  <img width="170" height="170" alt="Logo" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/poku.svg">
@@ -28,6 +30,7 @@
28
30
  [![TypeScript Version][typescript-version-image]][typescript-url]<br />
29
31
  [![GitHub Workflow Status (with event)][ci-image]][ci-url]
30
32
  [![GitHub Workflow Status (with event)][ql-image]][ql-url]
33
+ [![Coverage][coverage-image]][coverage-url]
31
34
  [![NPM Downloads][downloads-image]][downloads-url]
32
35
  [![License][license-image]][license-url]
33
36
 
@@ -55,11 +58,11 @@ Enjoying **Poku**? Consider giving him a star ⭐️
55
58
  <img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> Less verbose<br />
56
59
  <img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> High **isolation** level per file<br />
57
60
  <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> No eval needed 🔐<br />
61
+ <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> No global state<br />
58
62
  <img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> **Parallel** and **Sequential** runs 🏃🏽🏃🏻<br />
59
63
 
60
64
  <img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> **Poku** is [**100%** documented](https://poku.io/docs)<br />
61
65
  <img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> Designed to be human-friendly<br />
62
- <img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> **Poku** doesn't use a global state<br />
63
66
  <img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> Compatible with **Coverage** tools<br />
64
67
  <img width="16" height="16" alt="check" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/check.svg"> [**Node.js**][node-version-url], [**Bun**][bun-version-url] and [**Deno**][deno-version-url] compatibility 🩵<br />
65
68
 
@@ -108,8 +111,8 @@ bun add -d poku
108
111
  </td>
109
112
  <td width="400">
110
113
 
111
- ```ts
112
- import { poku } from 'npm:poku';
114
+ ```bash
115
+ deno add npm:poku
113
116
  ```
114
117
 
115
118
  </td>
@@ -121,7 +124,7 @@ import { poku } from 'npm:poku';
121
124
  <table>
122
125
  <tr>
123
126
  <td>
124
- <em><code>test/file.test.js</code></em>
127
+ <em><code>test/file.test.mjs</code></em>
125
128
  </td>
126
129
  </tr>
127
130
  <tr>
@@ -137,7 +140,8 @@ assert(true, 'Poku will describe it 🐷');
137
140
  </tr>
138
141
  </table>
139
142
 
140
- > Note that these examples use [**ESM**](https://poku.io/docs/examples/cjs-esm), but you can use [**CJS**](https://poku.io/docs/examples/cjs-esm) as well.
143
+ - Change from `.mjs` to `.js` by defining `"type": "module"` in your _package.json_.
144
+ - Note that these examples use [**ESM**](https://poku.io/docs/examples/cjs-esm), but you can use [**CJS**](https://poku.io/docs/examples/cjs-esm) as well.
141
145
 
142
146
  ### Run it 🚀
143
147
 
@@ -190,11 +194,10 @@ deno run npm:poku
190
194
 
191
195
  ### Helpers
192
196
 
193
- - `beforeEach` and `afterEach`
194
- - `test`
195
- - `describe` and `log`
196
- - `listFiles`
197
- - `exit`
197
+ - [**beforeEach**](https://poku.io/docs/category/beforeeach-and-aftereach) and [**afterEach**](https://poku.io/docs/category/beforeeach-and-aftereach)
198
+ - [**test**](https://poku.io/docs/documentation/helpers/test)
199
+ - [**describe**](https://poku.io/docs/documentation/helpers/describe)
200
+ - _and much more_ ✨
198
201
 
199
202
  [**See the complete documentation**](https://poku.io/docs).
200
203
 
package/lib/bin/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  "use strict";
3
3
  var _a, _b;
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
+ /* c8 ignore start */
5
6
  const list_files_js_1 = require("../modules/list-files.js");
6
7
  const get_arg_js_1 = require("../helpers/get-arg.js");
7
8
  const index_js_1 = require("../index.js");
@@ -26,3 +27,4 @@ if ((0, get_arg_js_1.hasArg)('log-success'))
26
27
  quiet,
27
28
  debug,
28
29
  });
30
+ /* c8 ignore stop */
@@ -15,3 +15,4 @@ exports.each = {
15
15
  test: true,
16
16
  },
17
17
  };
18
+ /* c8 ignore stop */
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findFile = void 0;
4
4
  const node_os_1 = require("os");
5
+ /* c8 ignore start */
5
6
  const findFile = (error) => {
6
7
  var _a;
7
8
  const stackLines = ((_a = error.stack) === null || _a === void 0 ? void 0 : _a.split(node_os_1.EOL)) || [];
@@ -25,3 +26,4 @@ const findFile = (error) => {
25
26
  return file;
26
27
  };
27
28
  exports.findFile = findFile;
29
+ /* c8 ignore stop */
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.forceArray = void 0;
4
+ /* c8 ignore start */
4
5
  const forceArray = (input) => {
5
6
  if (Array.isArray(input))
6
7
  return input;
7
8
  return [input];
8
9
  };
9
10
  exports.forceArray = forceArray;
11
+ /* c8 ignore stop */
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getLargestStringLength = exports.format = exports.backgroundColor = void 0;
4
+ /* c8 ignore start */
4
5
  const pad_js_1 = require("./pad.js");
5
6
  exports.backgroundColor = {
6
7
  white: 7,
@@ -39,3 +40,4 @@ exports.format = {
39
40
  };
40
41
  const getLargestStringLength = (arr) => arr.reduce((max, current) => Math.max(max, current.length), 0);
41
42
  exports.getLargestStringLength = getLargestStringLength;
43
+ /* c8 ignore stop */
@@ -2,3 +2,4 @@ import type { Configs } from '../@types/poku.js';
2
2
  export declare const supportedPlatforms: ReadonlyArray<Configs['platform']>;
3
3
  export declare const platformIsValid: (platform: unknown) => platform is "node" | "bun" | "deno" | undefined;
4
4
  export declare const getRuntime: (configs?: Configs) => (typeof supportedPlatforms)[number];
5
+ export declare const nodeVersion: number | undefined;
@@ -1,6 +1,12 @@
1
1
  "use strict";
2
+ /* c8 ignore start */
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ var _a;
2
7
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRuntime = exports.platformIsValid = exports.supportedPlatforms = void 0;
8
+ exports.nodeVersion = exports.getRuntime = exports.platformIsValid = exports.supportedPlatforms = void 0;
9
+ const node_process_1 = __importDefault(require("process"));
4
10
  exports.supportedPlatforms = [
5
11
  'node',
6
12
  'bun',
@@ -23,3 +29,7 @@ const getRuntime = (configs) => {
23
29
  return 'node';
24
30
  };
25
31
  exports.getRuntime = getRuntime;
32
+ exports.nodeVersion = (0, exports.getRuntime)() === 'node'
33
+ ? Number((_a = node_process_1.default.version.match(/v(\d+)\./)) === null || _a === void 0 ? void 0 : _a[1])
34
+ : undefined;
35
+ /* c8 ignore stop */
package/lib/helpers/hr.js CHANGED
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ /* c8 ignore start */
2
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
5
  };
@@ -11,3 +12,4 @@ const hr = () => {
11
12
  console.log(`${node_os_1.EOL}\x1b[2m\x1b[90m${line}\x1b[0m${node_os_1.EOL}`);
12
13
  };
13
14
  exports.hr = hr;
15
+ /* c8 ignore stop */
@@ -4,6 +4,7 @@
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.padStart = void 0;
7
+ /* c8 ignore start */
7
8
  const padStart = (str, targetLength, padString) => {
8
9
  padString = !padString ? ' ' : String(padString);
9
10
  if (str.length >= targetLength)
@@ -14,3 +15,4 @@ const padStart = (str, targetLength, padString) => {
14
15
  return fullPadString + str;
15
16
  };
16
17
  exports.padStart = padStart;
18
+ /* c8 ignore stop */
@@ -58,6 +58,7 @@ const parseAssertion = (cb, options) => __awaiter(void 0, void 0, void 0, functi
58
58
  message = options.message.message;
59
59
  else if (typeof options.defaultMessage === 'string')
60
60
  message = options.defaultMessage;
61
+ /* c8 ignore start */
61
62
  const finalMessage = (message === null || message === void 0 ? void 0 : message.trim().length) > 0
62
63
  ? format_js_1.format.bold(format_js_1.format.fail(`✘ ${message}`))
63
64
  : format_js_1.format.bold(format_js_1.format.fail('✘ No Message'));
@@ -86,5 +87,7 @@ const parseAssertion = (cb, options) => __awaiter(void 0, void 0, void 0, functi
86
87
  // Non-assertion errors
87
88
  throw error;
88
89
  }
90
+ /* c8 ignore stop */
91
+ /* c8 ignore next */
89
92
  });
90
93
  exports.parseAssertion = parseAssertion;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.removeConsecutiveRepeats = void 0;
4
+ /* c8 ignore start */
4
5
  const removeConsecutiveRepeats = (arr, specificItem) => {
5
6
  const result = [];
6
7
  let consecutiveCount = 0;
@@ -27,3 +28,4 @@ const removeConsecutiveRepeats = (arr, specificItem) => {
27
28
  return result;
28
29
  };
29
30
  exports.removeConsecutiveRepeats = removeConsecutiveRepeats;
31
+ /* c8 ignore stop */
@@ -1,4 +1,5 @@
1
1
  import { Configs } from '../@types/poku.js';
2
2
  import { Runner } from '../@types/runner.js';
3
+ export declare const isWindows: boolean;
3
4
  export declare const runner: (filename: string, configs?: Configs) => string[];
4
5
  export declare const scriptRunner: (runner: Runner) => string[];
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
+ /* c8 ignore start */
2
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
5
  };
5
6
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.scriptRunner = exports.runner = void 0;
7
+ exports.scriptRunner = exports.runner = exports.isWindows = void 0;
7
8
  const node_process_1 = __importDefault(require("process"));
8
9
  const node_path_1 = __importDefault(require("path"));
9
10
  const get_runtime_js_1 = require("./get-runtime.js");
10
- const isWindows = node_process_1.default.platform === 'win32';
11
+ exports.isWindows = node_process_1.default.platform === 'win32';
11
12
  const runner = (filename, configs) => {
12
13
  const runtime = (0, get_runtime_js_1.getRuntime)(configs);
13
14
  // Bun
@@ -15,17 +16,24 @@ const runner = (filename, configs) => {
15
16
  return ['bun'];
16
17
  // Deno
17
18
  if (runtime === 'deno')
18
- return ['deno', 'run', '--allow-read', '--allow-env', '--allow-run'];
19
+ return [
20
+ 'deno',
21
+ 'run',
22
+ '--allow-read', // Poku searches for all test files
23
+ '--allow-env', // Poku share the process.env with the `child_process`
24
+ '--allow-run', // Poku CLI
25
+ '--allow-net', // Create Service
26
+ ];
19
27
  // Node.js
20
28
  return node_path_1.default.extname(filename) === '.ts'
21
- ? [isWindows ? 'npx.cmd' : 'npx', 'tsx']
29
+ ? [exports.isWindows ? 'npx.cmd' : 'npx', 'tsx']
22
30
  : ['node'];
23
31
  };
24
32
  exports.runner = runner;
25
33
  const scriptRunner = (runner) => {
26
34
  // Bun
27
35
  if (runner === 'bun')
28
- return ['bun'];
36
+ return ['bun', 'run'];
29
37
  // Deno
30
38
  if (runner === 'deno')
31
39
  return ['deno', 'task'];
@@ -36,6 +44,7 @@ const scriptRunner = (runner) => {
36
44
  if (runner === 'pnpm')
37
45
  return ['pnpm', 'run'];
38
46
  // Node.js
39
- return ['npm', 'run'];
47
+ return [exports.isWindows ? 'npm.cmd' : 'npm', 'run'];
40
48
  };
41
49
  exports.scriptRunner = scriptRunner;
50
+ /* c8 ignore stop */
package/lib/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.startScript = exports.startService = exports.test = exports.listFiles = exports.afterEach = exports.beforeEach = exports.assertPromise = exports.log = exports.describe = exports.assert = exports.exit = exports.poku = void 0;
4
+ /* c8 ignore start */
4
5
  var poku_js_1 = require("./modules/poku.js");
5
6
  Object.defineProperty(exports, "poku", { enumerable: true, get: function () { return poku_js_1.poku; } });
6
7
  var exit_js_1 = require("./modules/exit.js");
@@ -22,3 +23,4 @@ Object.defineProperty(exports, "test", { enumerable: true, get: function () { re
22
23
  var create_service_js_1 = require("./modules/create-service.js");
23
24
  Object.defineProperty(exports, "startService", { enumerable: true, get: function () { return create_service_js_1.startService; } });
24
25
  Object.defineProperty(exports, "startScript", { enumerable: true, get: function () { return create_service_js_1.startScript; } });
26
+ /* c8 ignore stop */
@@ -24,7 +24,7 @@ export declare const assertPromise: ((value: unknown, message?: ParseAssertionOp
24
24
  notStrictEqual: (actual: unknown, expected: unknown, message?: ParseAssertionOptions['message']) => Promise<void>;
25
25
  notDeepStrictEqual: (actual: unknown, expected: unknown, message?: ParseAssertionOptions['message']) => Promise<void>;
26
26
  match: (value: string, regExp: RegExp, message?: ParseAssertionOptions['message']) => Promise<void>;
27
- ifError: (value: unknown) => Promise<void>;
27
+ ifError: (value: unknown, message?: ParseAssertionOptions['message']) => Promise<void>;
28
28
  fail: (message?: ParseAssertionOptions['message']) => Promise<void>;
29
29
  rejects: typeof rejects;
30
30
  };
@@ -31,20 +31,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
31
31
  step((generator = generator.apply(thisArg, _arguments || [])).next());
32
32
  });
33
33
  };
34
- var __importDefault = (this && this.__importDefault) || function (mod) {
35
- return (mod && mod.__esModule) ? mod : { "default": mod };
36
- };
37
- var _a;
38
34
  Object.defineProperty(exports, "__esModule", { value: true });
39
35
  exports.assertPromise = void 0;
40
- const node_process_1 = __importDefault(require("process"));
41
36
  const nodeAssert = __importStar(require("assert"));
42
37
  const parseAsssetion_js_1 = require("../helpers/parseAsssetion.js");
43
38
  const get_runtime_js_1 = require("../helpers/get-runtime.js");
44
- const runtime = (0, get_runtime_js_1.getRuntime)();
45
- const version = runtime === 'node'
46
- ? Number((_a = node_process_1.default.version.match(/v(\d+)\./)) === null || _a === void 0 ? void 0 : _a[1])
47
- : undefined;
48
39
  const ok = (value, message) => __awaiter(void 0, void 0, void 0, function* () {
49
40
  yield (0, parseAsssetion_js_1.parseAssertion)(() => {
50
41
  nodeAssert.ok(value);
@@ -90,10 +81,11 @@ const notDeepStrictEqual = (actual, expected, message) => __awaiter(void 0, void
90
81
  message,
91
82
  });
92
83
  });
93
- const ifError = (value) => __awaiter(void 0, void 0, void 0, function* () {
84
+ const ifError = (value, message) => __awaiter(void 0, void 0, void 0, function* () {
94
85
  yield (0, parseAsssetion_js_1.parseAssertion)(() => {
95
86
  nodeAssert.ifError(value);
96
87
  }, {
88
+ message,
97
89
  defaultMessage: 'Expected no error, but received an error',
98
90
  hideDiff: true,
99
91
  throw: true,
@@ -186,8 +178,9 @@ function doesNotReject(block, errorOrMessage, message) {
186
178
  });
187
179
  });
188
180
  }
181
+ /* c8 ignore start */
189
182
  const match = (value, regExp, message) => __awaiter(void 0, void 0, void 0, function* () {
190
- if (typeof version === 'number' && version < 12) {
183
+ if (typeof get_runtime_js_1.nodeVersion === 'number' && get_runtime_js_1.nodeVersion < 12) {
191
184
  throw new Error('match is available from Node.js 12 or higher');
192
185
  }
193
186
  yield (0, parseAsssetion_js_1.parseAssertion)(() => nodeAssert === null || nodeAssert === void 0 ? void 0 : nodeAssert.match(value, regExp), {
@@ -197,8 +190,10 @@ const match = (value, regExp, message) => __awaiter(void 0, void 0, void 0, func
197
190
  defaultMessage: 'Value should match regExp',
198
191
  });
199
192
  });
193
+ /* c8 ignore stop */
194
+ /* c8 ignore start */
200
195
  const doesNotMatch = (value, regExp, message) => __awaiter(void 0, void 0, void 0, function* () {
201
- if (typeof version === 'number' && version < 12) {
196
+ if (typeof get_runtime_js_1.nodeVersion === 'number' && get_runtime_js_1.nodeVersion < 12) {
202
197
  throw new Error('doesNotMatch is available from Node.js 12 or higher');
203
198
  }
204
199
  yield (0, parseAsssetion_js_1.parseAssertion)(() => nodeAssert.doesNotMatch(value, regExp), {
@@ -208,6 +203,7 @@ const doesNotMatch = (value, regExp, message) => __awaiter(void 0, void 0, void
208
203
  defaultMessage: 'Value should not match regExp',
209
204
  });
210
205
  });
206
+ /* c8 ignore stop */
211
207
  exports.assertPromise = Object.assign((value, message) => ok(value, message), {
212
208
  ok,
213
209
  equal,
@@ -24,7 +24,7 @@ export declare const assert: ((value: unknown, message?: ParseAssertionOptions['
24
24
  notStrictEqual: (actual: unknown, expected: unknown, message?: ParseAssertionOptions['message']) => void;
25
25
  notDeepStrictEqual: (actual: unknown, expected: unknown, message?: ParseAssertionOptions['message']) => void;
26
26
  match: (value: string, regExp: RegExp, message?: ParseAssertionOptions['message']) => void;
27
- ifError: (value: unknown) => void;
27
+ ifError: (value: unknown, message?: ParseAssertionOptions['message']) => void;
28
28
  fail: (message?: ParseAssertionOptions['message']) => void;
29
29
  rejects: typeof rejects;
30
30
  };
@@ -31,20 +31,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
31
31
  step((generator = generator.apply(thisArg, _arguments || [])).next());
32
32
  });
33
33
  };
34
- var __importDefault = (this && this.__importDefault) || function (mod) {
35
- return (mod && mod.__esModule) ? mod : { "default": mod };
36
- };
37
- var _a;
38
34
  Object.defineProperty(exports, "__esModule", { value: true });
39
35
  exports.assert = void 0;
40
- const node_process_1 = __importDefault(require("process"));
41
36
  const nodeAssert = __importStar(require("assert"));
42
37
  const parseAsssetion_js_1 = require("../helpers/parseAsssetion.js");
43
38
  const get_runtime_js_1 = require("../helpers/get-runtime.js");
44
- const runtime = (0, get_runtime_js_1.getRuntime)();
45
- const version = runtime === 'node'
46
- ? Number((_a = node_process_1.default.version.match(/v(\d+)\./)) === null || _a === void 0 ? void 0 : _a[1])
47
- : undefined;
48
39
  const ok = (value, message) => {
49
40
  (0, parseAsssetion_js_1.parseAssertion)(() => {
50
41
  nodeAssert.ok(value);
@@ -84,10 +75,11 @@ const notDeepStrictEqual = (actual, expected, message) => {
84
75
  message,
85
76
  });
86
77
  };
87
- const ifError = (value) => {
78
+ const ifError = (value, message) => {
88
79
  (0, parseAsssetion_js_1.parseAssertion)(() => {
89
80
  nodeAssert.ifError(value);
90
81
  }, {
82
+ message,
91
83
  defaultMessage: 'Expected no error, but received an error',
92
84
  hideDiff: true,
93
85
  throw: true,
@@ -176,8 +168,9 @@ function doesNotReject(block, errorOrMessage, message) {
176
168
  });
177
169
  });
178
170
  }
171
+ /* c8 ignore start */
179
172
  const match = (value, regExp, message) => {
180
- if (typeof version === 'number' && version < 12) {
173
+ if (typeof get_runtime_js_1.nodeVersion === 'number' && get_runtime_js_1.nodeVersion < 12) {
181
174
  throw new Error('match is available from Node.js 12 or higher');
182
175
  }
183
176
  (0, parseAsssetion_js_1.parseAssertion)(() => nodeAssert === null || nodeAssert === void 0 ? void 0 : nodeAssert.match(value, regExp), {
@@ -187,8 +180,10 @@ const match = (value, regExp, message) => {
187
180
  defaultMessage: 'Value should match regExp',
188
181
  });
189
182
  };
183
+ /* c8 ignore stop */
184
+ /* c8 ignore start */
190
185
  const doesNotMatch = (value, regExp, message) => {
191
- if (typeof version === 'number' && version < 12) {
186
+ if (typeof get_runtime_js_1.nodeVersion === 'number' && get_runtime_js_1.nodeVersion < 12) {
192
187
  throw new Error('doesNotMatch is available from Node.js 12 or higher');
193
188
  }
194
189
  (0, parseAsssetion_js_1.parseAssertion)(() => nodeAssert.doesNotMatch(value, regExp), {
@@ -198,6 +193,7 @@ const doesNotMatch = (value, regExp, message) => {
198
193
  defaultMessage: 'Value should not match regExp',
199
194
  });
200
195
  };
196
+ /* c8 ignore stop */
201
197
  exports.assert = Object.assign((value, message) => ok(value, message), {
202
198
  ok,
203
199
  equal,
@@ -6,7 +6,7 @@ import { StartScriptOptions, StartServiceOptions } from '../@types/background-pr
6
6
  * Useful for servers, APIs, etc.
7
7
  */
8
8
  export declare const startService: (file: string, options?: StartServiceOptions) => Promise<{
9
- end: () => boolean;
9
+ end: () => void;
10
10
  }>;
11
11
  /**
12
12
  *
@@ -15,7 +15,13 @@ export declare const startService: (file: string, options?: StartServiceOptions)
15
15
  * By default, it uses **npm**, but you can costumize it using the `runner` option.
16
16
  *
17
17
  * Useful for servers, APIs, etc.
18
+ *
19
+ * ---
20
+ *
21
+ * `startScript` currently doesn't works for **Bun** and **Deno**.
22
+ *
23
+ * - See: https://github.com/wellwelwel/poku/issues/143
18
24
  */
19
25
  export declare const startScript: (script: string, options?: StartScriptOptions) => Promise<{
20
- end: () => boolean;
26
+ end: () => void;
21
27
  }>;
@@ -18,25 +18,54 @@ const node_child_process_1 = require("child_process");
18
18
  const runner_js_1 = require("../helpers/runner.js");
19
19
  const node_path_1 = __importDefault(require("path"));
20
20
  const list_files_js_1 = require("./list-files.js");
21
+ const node_os_1 = require("os");
22
+ const format_js_1 = require("../helpers/format.js");
23
+ /* c8 ignore start */
24
+ const runningProcesses = {};
25
+ const secureEnds = () => Object.values(runningProcesses).forEach((end) => end());
26
+ const killWindowsProcess = (PID) => (0, node_child_process_1.spawn)('taskkill', ['/F', '/T', '/PID', PID.toString()]);
27
+ node_process_1.default.once('SIGINT', () => {
28
+ secureEnds();
29
+ });
30
+ /* c8 ignore stop */
21
31
  const backgroundProcess = (runtime, args, file, options) => new Promise((resolve, reject) => {
22
32
  let isResolved = false;
23
33
  const service = (0, node_child_process_1.spawn)(runtime, args, {
24
34
  stdio: ['inherit', 'pipe', 'pipe'],
25
- shell: false,
35
+ /* c8 ignore next */
36
+ shell: runner_js_1.isWindows,
26
37
  cwd: (options === null || options === void 0 ? void 0 : options.cwd) ? (0, list_files_js_1.sanitizePath)(node_path_1.default.normalize(options.cwd)) : undefined,
27
38
  env: node_process_1.default.env,
28
- detached: true,
39
+ /* c8 ignore next */
40
+ detached: !runner_js_1.isWindows,
41
+ /* c8 ignore next */
42
+ windowsHide: runner_js_1.isWindows,
43
+ timeout: options === null || options === void 0 ? void 0 : options.timeout,
29
44
  });
45
+ const PID = service.pid;
46
+ /* c8 ignore start */
30
47
  const end = () => {
31
- node_process_1.default.kill(-service.pid, 'SIGKILL');
32
- return true;
48
+ delete runningProcesses[PID];
49
+ if (runner_js_1.isWindows) {
50
+ killWindowsProcess(PID);
51
+ return;
52
+ }
53
+ if (['bun', 'deno'].includes(runtime) ||
54
+ ['bun', 'deno'].includes(String(options === null || options === void 0 ? void 0 : options.runner))) {
55
+ node_process_1.default.kill(PID);
56
+ return;
57
+ }
58
+ node_process_1.default.kill(-PID, 'SIGKILL');
59
+ return;
33
60
  };
61
+ runningProcesses[PID] = end;
62
+ /* c8 ignore stop */
34
63
  service.stdout.on('data', (data) => {
35
64
  if (!isResolved && typeof (options === null || options === void 0 ? void 0 : options.startAfter) !== 'number') {
36
- const stringData = String(data);
65
+ const stringData = JSON.stringify(String(data));
37
66
  if (typeof (options === null || options === void 0 ? void 0 : options.startAfter) === 'undefined' ||
38
67
  (typeof (options === null || options === void 0 ? void 0 : options.startAfter) === 'string' &&
39
- stringData.includes(options.startAfter))) {
68
+ stringData.includes(options === null || options === void 0 ? void 0 : options.startAfter))) {
40
69
  resolve({ end });
41
70
  clearTimeout(timeout);
42
71
  isResolved = true;
@@ -45,18 +74,29 @@ const backgroundProcess = (runtime, args, file, options) => new Promise((resolve
45
74
  (options === null || options === void 0 ? void 0 : options.verbose) && console.log(String(data));
46
75
  });
47
76
  service.stderr.on('data', (data) => {
48
- reject(new Error(`Service failed to start: ${data}`));
77
+ if (!isResolved && typeof (options === null || options === void 0 ? void 0 : options.startAfter) !== 'number') {
78
+ const stringData = JSON.stringify(String(data));
79
+ if (typeof (options === null || options === void 0 ? void 0 : options.startAfter) === 'undefined' ||
80
+ (typeof (options === null || options === void 0 ? void 0 : options.startAfter) === 'string' &&
81
+ stringData.includes(options === null || options === void 0 ? void 0 : options.startAfter))) {
82
+ resolve({ end });
83
+ clearTimeout(timeout);
84
+ isResolved = true;
85
+ }
86
+ }
87
+ (options === null || options === void 0 ? void 0 : options.verbose) && console.log(String(data));
49
88
  });
50
89
  service.on('error', (err) => {
51
- reject(new Error(`Service failed to start: ${err}`));
90
+ secureEnds();
91
+ reject(`Service failed to start: ${err}`);
52
92
  });
53
93
  service.on('close', (code) => {
54
94
  if (code !== 0)
55
- reject(new Error(`Service exited with code ${code}`));
95
+ reject(`Service exited with code ${code}`);
56
96
  });
57
97
  const timeout = setTimeout(() => {
58
98
  if (!isResolved) {
59
- service.kill();
99
+ secureEnds();
60
100
  reject(`createService: Timeout\nFile: ${file}`);
61
101
  }
62
102
  }, (options === null || options === void 0 ? void 0 : options.timeout) || 10000);
@@ -90,11 +130,22 @@ exports.startService = startService;
90
130
  * By default, it uses **npm**, but you can costumize it using the `runner` option.
91
131
  *
92
132
  * Useful for servers, APIs, etc.
133
+ *
134
+ * ---
135
+ *
136
+ * `startScript` currently doesn't works for **Bun** and **Deno**.
137
+ *
138
+ * - See: https://github.com/wellwelwel/poku/issues/143
93
139
  */
94
140
  const startScript = (script, options) => __awaiter(void 0, void 0, void 0, function* () {
95
- const runtimeOptions = (0, runner_js_1.scriptRunner)((options === null || options === void 0 ? void 0 : options.runner) || 'npm');
141
+ const runner = (options === null || options === void 0 ? void 0 : options.runner) || 'npm';
142
+ const runtimeOptions = (0, runner_js_1.scriptRunner)(runner);
96
143
  const runtime = runtimeOptions.shift();
97
144
  const runtimeArgs = [...runtimeOptions, script];
98
- return yield backgroundProcess(runtime, runtimeArgs, script, options);
145
+ /* c8 ignore start */
146
+ if (['bun', 'deno'].includes(runner))
147
+ throw new Error(`${format_js_1.format.bold('startScript')} currently doesn't works for Bun and Deno.${node_os_1.EOL}See: https://github.com/wellwelwel/poku/issues/143`);
148
+ /* c8 ignore stop */
149
+ return yield backgroundProcess(runtime, runtimeArgs, script, Object.assign(Object.assign({}, options), { isScript: true, runner }));
99
150
  });
100
151
  exports.startScript = startScript;
@@ -25,3 +25,4 @@ const describe = (title, options) => {
25
25
  console.log(`${pad ? node_os_1.EOL : ''}${format_js_1.format.bg(format_js_1.backgroundColor[typeof background === 'string' ? background : 'grey'], message)}`);
26
26
  };
27
27
  exports.describe = describe;
28
+ /* c8 ignore stop */
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ /* c8 ignore start */
2
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
5
  };
@@ -31,3 +32,4 @@ node_process_1.default.on('uncaughtException', (err) => {
31
32
  console.log('uncaughtException', err);
32
33
  node_process_1.default.exit(1);
33
34
  });
35
+ /* c8 ignore stop */
@@ -1,3 +1,6 @@
1
+ /**
2
+ * Both CLI, API, noExit, sequential and parallel runs are strictly tested, but these tests use deep child process for it
3
+ */
1
4
  import { Code } from '../@types/code.js';
2
5
  import { Configs } from '../@types/poku.js';
3
6
  export declare function poku(targetPaths: string | string[], configs: Configs & {
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ /**
3
+ * Both CLI, API, noExit, sequential and parallel runs are strictly tested, but these tests use deep child process for it
4
+ */
2
5
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
6
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
7
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -10,6 +13,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
13
  };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.poku = void 0;
16
+ /* c8 ignore start */
13
17
  const node_os_1 = require("os");
14
18
  const force_array_js_1 = require("../helpers/force-array.js");
15
19
  const run_tests_js_1 = require("../services/run-tests.js");
@@ -58,3 +62,4 @@ function poku(targetPaths, configs) {
58
62
  });
59
63
  }
60
64
  exports.poku = poku;
65
+ /* c8 ignore stop */
@@ -19,6 +19,7 @@ function test(cb) {
19
19
  yield beforeResult;
20
20
  }
21
21
  const resultCb = cb();
22
+ /* c8 ignore next */
22
23
  if (resultCb instanceof Promise)
23
24
  yield resultCb;
24
25
  if (typeof each_js_1.each.after.cb === 'function' && each_js_1.each.after.test) {
@@ -23,10 +23,13 @@ const format_js_1 = require("../helpers/format.js");
23
23
  const logs_js_1 = require("../helpers/logs.js");
24
24
  const remove_repeats_js_1 = require("../helpers/remove-repeats.js");
25
25
  const each_js_1 = require("./each.js");
26
+ /* c8 ignore stop */
27
+ /* c8 ignore start */
26
28
  exports.fileResults = {
27
29
  success: [],
28
30
  fail: [],
29
31
  };
32
+ /* c8 ignore stop */
30
33
  const runTestFile = (filePath, configs) => new Promise((resolve) => __awaiter(void 0, void 0, void 0, function* () {
31
34
  const runtimeOptions = (0, runner_js_1.runner)(filePath, configs);
32
35
  const runtime = runtimeOptions.shift();
@@ -75,7 +78,8 @@ const runTestFile = (filePath, configs) => new Promise((resolve) => __awaiter(vo
75
78
  // Export spawn helper is not an option
76
79
  const child = (0, node_child_process_1.spawn)(runtime, runtimeArguments, {
77
80
  stdio: ['inherit', 'pipe', 'pipe'],
78
- shell: false,
81
+ /* c8 ignore next */
82
+ shell: runner_js_1.isWindows,
79
83
  env: Object.assign(Object.assign({}, node_process_1.default.env), { FILE: (configs === null || configs === void 0 ? void 0 : configs.parallel) ? fileRelative : '' }),
80
84
  });
81
85
  child.stdout.on('data', stdOut);
package/package.json CHANGED
@@ -1,22 +1,21 @@
1
1
  {
2
2
  "name": "poku",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "description": "🐷 Poku makes testing easy for Node.js, Bun & Deno at the same time.",
5
5
  "main": "./lib/index.js",
6
6
  "scripts": {
7
- "test": "tsx ./test/run.test.ts",
8
- "pretest:c8": "npm run build",
9
- "test:c8": "c8 --reporter=text --reporter=lcov npm run test:e2e",
10
- "test:e2e": "npx poku --parallel ci/test/unit,ci/test/integration,ci/test/e2e",
7
+ "test": "tsx src/bin/index.ts --parallel --debug test/unit,test/integration,test/e2e",
8
+ "test:c8": "c8 npm run test",
11
9
  "test:ci": "tsx ./test/ci.test.ts",
12
10
  "test:node": "FILTER='node-' npm run test:ci",
13
11
  "test:deno": "FILTER='deno-' npm run test:ci",
14
12
  "test:bun": "FILTER='bun-' npm run test:ci",
15
13
  "predocker:deno": "docker compose -f ./test/docker/playground/deno/docker-compose.yml down",
16
14
  "docker:deno": "docker compose -f ./test/docker/playground/deno/docker-compose.yml up --build",
17
- "clear": "rm -rf ./lib ./ci",
15
+ "clear": "shx rm -rf ./lib ./ci ./coverage",
16
+ "prebuild": "npm run clear",
18
17
  "build": "tsc && tsc -p tsconfig.test.json",
19
- "postbuild": "tsx ./tools/compatibility/node.ts && chmod +x lib/bin/index.js",
18
+ "postbuild": "tsx ./tools/compatibility/node.ts && shx cp fixtures/server/package.json ci/fixtures/server/package.json && shx chmod +x lib/bin/index.js",
20
19
  "eslint:checker": "eslint . --ext .js,.ts",
21
20
  "eslint:fix": "eslint . --fix --config ./.eslintrc.json",
22
21
  "lint:checker": "npm run eslint:checker && npm run prettier:checker",
@@ -103,9 +102,9 @@
103
102
  ],
104
103
  "type": "commonjs",
105
104
  "devDependencies": {
106
- "@types/node": "^20.11.27",
107
- "@typescript-eslint/eslint-plugin": "^7.2.0",
108
- "@typescript-eslint/parser": "^7.2.0",
105
+ "@types/node": "^20.12.7",
106
+ "@typescript-eslint/eslint-plugin": "^7.7.1",
107
+ "@typescript-eslint/parser": "^7.7.1",
109
108
  "c8": "^9.1.0",
110
109
  "eslint": "^8.57.0",
111
110
  "eslint-config-prettier": "^9.1.0",
@@ -114,7 +113,8 @@
114
113
  "eslint-plugin-prettier": "^5.1.3",
115
114
  "packages-update": "^1.2.1",
116
115
  "prettier": "^3.2.5",
117
- "tsx": "^4.7.1",
118
- "typescript": "^5.4.2"
116
+ "shx": "^0.3.4",
117
+ "tsx": "4.2.1",
118
+ "typescript": "^5.4.5"
119
119
  }
120
120
  }