poku 1.4.0 → 1.5.1
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 +69 -71
- package/lib/@types/poku.d.ts +11 -0
- package/lib/bin/index.js +5 -4
- package/lib/helpers/format.d.ts +2 -0
- package/lib/helpers/format.js +10 -3
- package/lib/helpers/hr.js +2 -3
- package/lib/helpers/logs.d.ts +1 -2
- package/lib/helpers/logs.js +3 -5
- package/lib/helpers/parseAsssetion.js +33 -17
- package/lib/helpers/remove-repeats.d.ts +1 -0
- package/lib/helpers/remove-repeats.js +29 -0
- package/lib/modules/assert.js +12 -13
- package/lib/modules/exit.js +9 -8
- package/lib/modules/list-files.d.ts +1 -0
- package/lib/modules/list-files.js +16 -5
- package/lib/modules/poku.js +24 -3
- package/lib/services/run-test-file.d.ts +6 -0
- package/lib/services/run-test-file.js +59 -20
- package/lib/services/run-tests.d.ts +4 -0
- package/lib/services/run-tests.js +18 -18
- package/package.json +12 -9
package/README.md
CHANGED
|
@@ -4,15 +4,14 @@
|
|
|
4
4
|
[bun-version-image]: https://img.shields.io/badge/Bun->=0.5.3-f471b5
|
|
5
5
|
[deno-version-url]: https://github.com/denoland/deno
|
|
6
6
|
[deno-version-image]: https://img.shields.io/badge/Deno->=1.30.0-70ffaf
|
|
7
|
-
[npm-image]: https://img.shields.io/npm/v/poku.svg?color=3dc1d3
|
|
8
|
-
[npm-url]: https://npmjs.org/package/poku
|
|
9
7
|
[typescript-url]: https://github.com/microsoft/TypeScript
|
|
8
|
+
[typescript-version-image]: https://img.shields.io/badge/TypeScript->=5.0.2-3077c6
|
|
10
9
|
[ci-url]: https://github.com/wellwelwel/poku/actions/workflows/ci.yml?query=branch%3Amain
|
|
11
10
|
[ci-image]: https://img.shields.io/github/actions/workflow/status/wellwelwel/poku/ci.yml?event=push&style=flat&label=CI&branch=main
|
|
12
11
|
[ql-url]: https://github.com/wellwelwel/poku/actions/workflows/codeql.yml?query=branch%3Amain
|
|
13
12
|
[ql-image]: https://img.shields.io/github/actions/workflow/status/wellwelwel/poku/codeql.yml?event=push&style=flat&label=Code%20QL&branch=main
|
|
14
13
|
[license-url]: https://github.com/wellwelwel/poku/blob/main/LICENSE
|
|
15
|
-
[license-image]: https://img.shields.io/npm/l/poku.svg?maxAge=2592000&color=9c88ff
|
|
14
|
+
[license-image]: https://img.shields.io/npm/l/poku.svg?maxAge=2592000&color=9c88ff&label=License
|
|
16
15
|
|
|
17
16
|
# Poku
|
|
18
17
|
|
|
@@ -20,72 +19,71 @@
|
|
|
20
19
|
|
|
21
20
|
**Poku** is your test runner pet for [**Node.js**][node-version-url], [**Bun**][bun-version-url] and [**Deno**][deno-version-url] combining **flexibility**, **parallel** and **sequential** runs, **human-friendly assertion errors** and **high isolation level**.
|
|
22
21
|
|
|
22
|
+
> By creating **Poku**, my aim is to show that testing can be simpler.
|
|
23
|
+
|
|
23
24
|
[![Node.js Version][node-version-image]][node-version-url]
|
|
24
25
|
[![Bun Version][bun-version-image]][bun-version-url]
|
|
25
26
|
[![Deno Version][deno-version-image]][deno-version-url]
|
|
26
|
-
[![
|
|
27
|
-
[![License][license-image]][license-url]
|
|
27
|
+
[![TypeScript Version][typescript-version-image]][typescript-url]
|
|
28
28
|
[![GitHub Workflow Status (with event)][ci-image]][ci-url]
|
|
29
29
|
[![GitHub Workflow Status (with event)][ql-image]][ql-url]
|
|
30
|
+
[![License][license-image]][license-url]
|
|
30
31
|
|
|
31
|
-
Enjoying Poku
|
|
32
|
+
Enjoying **Poku**? Consider giving him a star ⭐️
|
|
32
33
|
|
|
33
34
|
---
|
|
34
35
|
|
|
35
|
-
🐷 [**Documentation Website**](https://poku.dev)
|
|
36
|
+
🐷 [**Documentation Website**](https://poku.dev) • 🔬 [**Compare Poku with the Most Popular Test Runners**](https://poku.dev/docs/comparing)
|
|
36
37
|
|
|
37
38
|
---
|
|
38
39
|
|
|
39
40
|
## Why Poku?
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
Don't worry about `describe`, `it`, `beforeEach` and everything else 🚀 <br/>
|
|
43
|
+
After all, you don't need to learn what you already know ([**see why**](https://poku.dev/docs/examples/beforeEach)) ✨
|
|
42
44
|
|
|
43
45
|
- Supports **ESM** and **CJS**
|
|
44
46
|
- Designed to be highly intuitive
|
|
45
|
-
- No need to compile [**TypeScript**][typescript-url] \*
|
|
46
47
|
- Compatible with **Coverage** tools
|
|
47
|
-
- Allows both **in-code** and **CLI** usage
|
|
48
48
|
- [**Node.js**][node-version-url], [**Bun**][bun-version-url] and [**Deno**][deno-version-url] compatibility
|
|
49
49
|
- Zero configurations, except you want
|
|
50
|
-
-
|
|
50
|
+
- Allows both **API (_in-code_)** and **CLI** usage
|
|
51
|
+
- Poku adapts to your test, not the other way around
|
|
52
|
+
- You can use **Poku**'s `assert` with every test runner you want
|
|
51
53
|
- [**And much more!**](https://poku.dev)
|
|
52
54
|
|
|
53
55
|
---
|
|
54
56
|
|
|
55
|
-
-
|
|
56
|
-
- **Zero** external dependencies
|
|
57
|
+
- [](https://packagephobia.com/result?p=poku)
|
|
58
|
+
- **Zero** external dependencies 🌱
|
|
57
59
|
|
|
58
60
|
---
|
|
59
61
|
|
|
60
62
|
## Documentation
|
|
61
63
|
|
|
62
|
-
- See detailed
|
|
64
|
+
- See detailed usage in [**Documentation**](https://poku.dev/docs/category/documentation) section for **Poku**'s **CLI**, **API (_in-code_)** and **assert**, advanced concepts and much more.
|
|
63
65
|
|
|
64
66
|
---
|
|
65
67
|
|
|
66
68
|
## Overview
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
| ------------------------------------------------------------ | ---------------------------------------------------------- |
|
|
70
|
-
| `npx poku test/unit,test/integration` | `npx poku --parallel test/unit,test/integration` |
|
|
71
|
-
| <img src=".github/assets/readme/sequential.png" width="360"> | <img src=".github/assets/readme/parallel.png" width="360"> |
|
|
70
|
+
### `poku`
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
| Sequential | Concurrent |
|
|
73
|
+
| -------------------------------------------------- | ------------------------------------------------ |
|
|
74
|
+
| <img src=".github/assets/readme/sequential.png" /> | <img src=".github/assets/readme/parallel.png" /> |
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
> [**See the complete `poku` documentation**](https://poku.dev/docs/category/poku).
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
---
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
import { assert } from 'poku'; // Node and Bun
|
|
82
|
-
import { assert } from 'npm:poku'; // Deno
|
|
80
|
+
### `assert`
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
| Using `poku` | Using `node` |
|
|
83
|
+
| --------------------------------------------------- | --------------------------------------------------- |
|
|
84
|
+
| <img src=".github/assets/readme/assert-poku.png" /> | <img src=".github/assets/readme/assert-node.png" /> |
|
|
87
85
|
|
|
88
|
-
>
|
|
86
|
+
> [**See the complete assert's documentation**](https://poku.dev/docs/documentation/assert).
|
|
89
87
|
|
|
90
88
|
---
|
|
91
89
|
|
|
@@ -93,86 +91,68 @@ assert.deepStrictEqual(1, '1', 'My optional custom message');
|
|
|
93
91
|
|
|
94
92
|
### **Node.js**
|
|
95
93
|
|
|
96
|
-
> <img src=".github/assets/readme/node-js.svg" width="24" />
|
|
97
|
-
|
|
98
94
|
```bash
|
|
99
|
-
npm
|
|
95
|
+
npm i -D poku
|
|
100
96
|
```
|
|
101
97
|
|
|
102
98
|
### TypeScript (Node.js)
|
|
103
99
|
|
|
104
|
-
> <img src=".github/assets/readme/node-js.svg" width="24" />
|
|
105
|
-
> <img src=".github/assets/readme/plus.svg" width="24" />
|
|
106
|
-
> <img src=".github/assets/readme/typescript.svg" width="24" />
|
|
107
|
-
|
|
108
100
|
```bash
|
|
109
|
-
npm
|
|
101
|
+
npm i -D poku tsx
|
|
110
102
|
```
|
|
111
103
|
|
|
112
104
|
### Bun
|
|
113
105
|
|
|
114
|
-
> <img src=".github/assets/readme/bun.svg" width="24" />
|
|
115
|
-
> <img src=".github/assets/readme/plus.svg" width="24" />
|
|
116
|
-
> <img src=".github/assets/readme/typescript.svg" width="24" />
|
|
117
|
-
|
|
118
106
|
```bash
|
|
119
|
-
bun add
|
|
107
|
+
bun add -d poku
|
|
120
108
|
```
|
|
121
109
|
|
|
122
110
|
### **Deno**
|
|
123
111
|
|
|
124
|
-
> <img src=".github/assets/readme/deno.svg" width="24" />
|
|
125
|
-
> <img src=".github/assets/readme/plus.svg" width="24" />
|
|
126
|
-
> <img src=".github/assets/readme/typescript.svg" width="24" />
|
|
127
|
-
|
|
128
112
|
```ts
|
|
129
113
|
import { poku } from 'npm:poku';
|
|
130
114
|
```
|
|
131
115
|
|
|
132
|
-
- **Poku** requires these permissions by default: `--allow-read`, `--allow-env` and `--allow-run`.
|
|
133
|
-
|
|
134
116
|
---
|
|
135
117
|
|
|
136
118
|
## Quick Start
|
|
137
119
|
|
|
138
|
-
###
|
|
120
|
+
### CLI
|
|
139
121
|
|
|
140
122
|
> <img src=".github/assets/readme/node-js.svg" width="24" />
|
|
141
|
-
> <img src=".github/assets/readme/plus.svg" width="24" />
|
|
142
|
-
> <img src=".github/assets/readme/bun.svg" width="24" />
|
|
143
|
-
|
|
144
|
-
```ts
|
|
145
|
-
import { poku } from 'poku';
|
|
146
123
|
|
|
147
|
-
|
|
124
|
+
```bash
|
|
125
|
+
npx poku targetDir
|
|
148
126
|
```
|
|
149
127
|
|
|
150
|
-
> <img src=".github/assets/readme/
|
|
151
|
-
|
|
152
|
-
```ts
|
|
153
|
-
import { poku } from 'npm:poku';
|
|
128
|
+
> <img src=".github/assets/readme/bun.svg" width="24" />
|
|
154
129
|
|
|
155
|
-
|
|
130
|
+
```bash
|
|
131
|
+
bun poku targetDir
|
|
156
132
|
```
|
|
157
133
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
> <img src=".github/assets/readme/node-js.svg" width="24" />
|
|
134
|
+
> <img src=".github/assets/readme/deno.svg" width="24" />
|
|
161
135
|
|
|
162
136
|
```bash
|
|
163
|
-
|
|
137
|
+
deno run npm:poku targetDir
|
|
164
138
|
```
|
|
165
139
|
|
|
166
|
-
|
|
140
|
+
### API (_In-code_)
|
|
167
141
|
|
|
168
|
-
|
|
169
|
-
|
|
142
|
+
#### Node.js, TypeScript (Node.js) and Bun
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import { poku } from 'poku';
|
|
146
|
+
|
|
147
|
+
await poku(['targetDir']);
|
|
170
148
|
```
|
|
171
149
|
|
|
172
|
-
|
|
150
|
+
#### Deno
|
|
173
151
|
|
|
174
|
-
```
|
|
175
|
-
|
|
152
|
+
```ts
|
|
153
|
+
import { poku } from 'npm:poku';
|
|
154
|
+
|
|
155
|
+
await poku(['targetDir']);
|
|
176
156
|
```
|
|
177
157
|
|
|
178
158
|
---
|
|
@@ -189,4 +169,22 @@ I'm continuously working to improve **Poku**. If you've got something interestin
|
|
|
189
169
|
|
|
190
170
|
## Acknowledgements
|
|
191
171
|
|
|
192
|
-
- [**Contributors**](https://github.com/wellwelwel/poku/graphs/contributors)
|
|
172
|
+
- [**Contributors**](https://github.com/wellwelwel/poku/graphs/contributors).
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Contributing
|
|
177
|
+
|
|
178
|
+
Please check the [**CONTRIBUTING.md**](./CONTRIBUTING.md) for instructions 🚀
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## License
|
|
183
|
+
|
|
184
|
+
Poku is under the [**MIT** License](./LICENSE).
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Security Policy
|
|
189
|
+
|
|
190
|
+
Please check the [**SECURITY.md**](./SECURITY.md) and the section [**Is Poku Safe?**](https://poku.dev/docs/security) from Documentation.
|
package/lib/@types/poku.d.ts
CHANGED
|
@@ -9,14 +9,19 @@ export type Configs = {
|
|
|
9
9
|
*/
|
|
10
10
|
noExit?: boolean;
|
|
11
11
|
/**
|
|
12
|
+
* @deprecated
|
|
12
13
|
* Customize `stdout` options.
|
|
13
14
|
*/
|
|
14
15
|
log?: {
|
|
15
16
|
/**
|
|
17
|
+
* @deprecated
|
|
18
|
+
*
|
|
16
19
|
* @default false
|
|
17
20
|
*/
|
|
18
21
|
success?: boolean;
|
|
19
22
|
/**
|
|
23
|
+
* @deprecated
|
|
24
|
+
*
|
|
20
25
|
* @default true
|
|
21
26
|
*/
|
|
22
27
|
fail?: boolean;
|
|
@@ -26,6 +31,12 @@ export type Configs = {
|
|
|
26
31
|
*
|
|
27
32
|
* @default false
|
|
28
33
|
*/
|
|
34
|
+
debug?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* This option overwrites the `debug` settings.
|
|
37
|
+
*
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
29
40
|
quiet?: boolean;
|
|
30
41
|
/**
|
|
31
42
|
* Determines the mode of test execution.
|
package/lib/bin/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const list_files_js_1 = require("../modules/list-files.js");
|
|
|
6
6
|
const get_arg_js_1 = require("../helpers/get-arg.js");
|
|
7
7
|
const index_js_1 = require("../index.js");
|
|
8
8
|
const get_runtime_js_1 = require("../helpers/get-runtime.js");
|
|
9
|
+
const format_js_1 = require("../helpers/format.js");
|
|
9
10
|
const dirs = ((0, get_arg_js_1.hasArg)('include')
|
|
10
11
|
? (_a = (0, get_arg_js_1.getArg)('include')) === null || _a === void 0 ? void 0 : _a.split(',')
|
|
11
12
|
: (_b = (0, get_arg_js_1.getLastParam)()) === null || _b === void 0 ? void 0 : _b.split(',')) || [];
|
|
@@ -14,14 +15,14 @@ const filter = (0, get_arg_js_1.getArg)('filter');
|
|
|
14
15
|
const exclude = (0, get_arg_js_1.getArg)('exclude');
|
|
15
16
|
const parallel = (0, get_arg_js_1.hasArg)('parallel');
|
|
16
17
|
const quiet = (0, get_arg_js_1.hasArg)('quiet');
|
|
17
|
-
const
|
|
18
|
+
const debug = (0, get_arg_js_1.hasArg)('debug');
|
|
19
|
+
if ((0, get_arg_js_1.hasArg)('log-success'))
|
|
20
|
+
console.log(`The flag ${format_js_1.format.bold('--log-success')} is deprecated. Use ${format_js_1.format.bold('--debug')} instead.`);
|
|
18
21
|
(0, index_js_1.poku)(dirs, {
|
|
19
22
|
platform: (0, get_runtime_js_1.platformIsValid)(platform) ? platform : undefined,
|
|
20
23
|
filter: filter ? new RegExp((0, list_files_js_1.escapeRegExp)(filter)) : undefined,
|
|
21
24
|
exclude: exclude ? new RegExp((0, list_files_js_1.escapeRegExp)(exclude)) : undefined,
|
|
22
25
|
parallel,
|
|
23
26
|
quiet,
|
|
24
|
-
|
|
25
|
-
success: logSuccess,
|
|
26
|
-
},
|
|
27
|
+
debug,
|
|
27
28
|
});
|
package/lib/helpers/format.d.ts
CHANGED
package/lib/helpers/format.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.format = void 0;
|
|
3
|
+
exports.getLargestStringLength = exports.format = void 0;
|
|
4
4
|
const pad_js_1 = require("./pad.js");
|
|
5
5
|
exports.format = {
|
|
6
6
|
counter: (current, total, pad = '0') => {
|
|
@@ -10,7 +10,14 @@ exports.format = {
|
|
|
10
10
|
dim: (value) => `\x1b[2m${value}\x1b[0m`,
|
|
11
11
|
bold: (value) => `\x1b[1m${value}\x1b[0m`,
|
|
12
12
|
underline: (value) => `\x1b[4m${value}\x1b[0m`,
|
|
13
|
-
info: (value) => `\x1b[
|
|
13
|
+
info: (value) => `\x1b[94m${value}\x1b[0m`,
|
|
14
14
|
success: (value) => `\x1b[32m${value}\x1b[0m`,
|
|
15
|
-
fail: (value) => `\x1b[
|
|
15
|
+
fail: (value) => `\x1b[91m${value}\x1b[0m`,
|
|
16
|
+
bg: (bg, text) => {
|
|
17
|
+
const padding = ' '.repeat(1);
|
|
18
|
+
const paddedText = `${padding}${text}${padding}`;
|
|
19
|
+
return `\x1b[${bg}m\x1b[1m${paddedText}\x1b[0m`;
|
|
20
|
+
},
|
|
16
21
|
};
|
|
22
|
+
const getLargestStringLength = (arr) => arr.reduce((max, current) => Math.max(max, current.length), 0);
|
|
23
|
+
exports.getLargestStringLength = getLargestStringLength;
|
package/lib/helpers/hr.js
CHANGED
|
@@ -7,8 +7,7 @@ exports.hr = void 0;
|
|
|
7
7
|
const node_os_1 = require("os");
|
|
8
8
|
const node_process_1 = __importDefault(require("process"));
|
|
9
9
|
const hr = () => {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
console.log(`\x1b[2m${line}\x1b[0m${node_os_1.EOL}`);
|
|
10
|
+
const line = '⎯'.repeat(node_process_1.default.stdout.columns - 10);
|
|
11
|
+
console.log(`${node_os_1.EOL}\x1b[2m\x1b[90m${line}\x1b[0m${node_os_1.EOL}`);
|
|
13
12
|
};
|
|
14
13
|
exports.hr = hr;
|
package/lib/helpers/logs.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { Configs } from '../@types/poku.js';
|
|
2
2
|
export declare const isQuiet: (configs?: Configs) => boolean;
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const showFailures: (configs?: Configs) => boolean;
|
|
3
|
+
export declare const isDebug: (configs?: Configs) => boolean;
|
package/lib/helpers/logs.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.isDebug = exports.isQuiet = void 0;
|
|
4
4
|
const isQuiet = (configs) => typeof (configs === null || configs === void 0 ? void 0 : configs.quiet) === 'boolean' && Boolean(configs === null || configs === void 0 ? void 0 : configs.quiet);
|
|
5
5
|
exports.isQuiet = isQuiet;
|
|
6
|
-
const
|
|
7
|
-
exports.
|
|
8
|
-
const showFailures = (configs) => { var _a, _b; return typeof ((_a = configs === null || configs === void 0 ? void 0 : configs.log) === null || _a === void 0 ? void 0 : _a.fail) === 'undefined' || Boolean((_b = configs === null || configs === void 0 ? void 0 : configs.log) === null || _b === void 0 ? void 0 : _b.fail); };
|
|
9
|
-
exports.showFailures = showFailures;
|
|
6
|
+
const isDebug = (configs) => Boolean(configs === null || configs === void 0 ? void 0 : configs.debug);
|
|
7
|
+
exports.isDebug = isDebug;
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.parseAssertion = void 0;
|
|
7
7
|
const node_process_1 = __importDefault(require("process"));
|
|
8
|
+
const node_path_1 = __importDefault(require("path"));
|
|
8
9
|
const node_assert_1 = __importDefault(require("assert"));
|
|
9
10
|
const node_os_1 = require("os");
|
|
10
11
|
const format_js_1 = require("./format.js");
|
|
@@ -25,35 +26,50 @@ const findFile = (error) => {
|
|
|
25
26
|
}
|
|
26
27
|
return file;
|
|
27
28
|
};
|
|
29
|
+
const formatFail = (str) => format_js_1.format.bold(format_js_1.format.fail(`✘ ${str}`));
|
|
28
30
|
const parseAssertion = (cb, options) => {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
const isPoku = typeof ((_a = node_process_1.default.env) === null || _a === void 0 ? void 0 : _a.FILE) === 'string' && ((_b = node_process_1.default.env) === null || _b === void 0 ? void 0 : _b.FILE.length) > 0;
|
|
33
|
+
const FILE = node_process_1.default.env.FILE;
|
|
29
34
|
try {
|
|
30
35
|
cb();
|
|
36
|
+
if (typeof options.message === 'string') {
|
|
37
|
+
const message = isPoku
|
|
38
|
+
? `${format_js_1.format.bold(format_js_1.format.success(`✔ ${options.message}`))} ${format_js_1.format.dim(format_js_1.format.success(`› ${FILE}`))}`
|
|
39
|
+
: format_js_1.format.bold(format_js_1.format.success(`✔ ${options.message}`));
|
|
40
|
+
console.log(message);
|
|
41
|
+
}
|
|
31
42
|
}
|
|
32
43
|
catch (error) {
|
|
33
44
|
if (error instanceof node_assert_1.default.AssertionError) {
|
|
34
45
|
const { code, actual, expected, operator } = error;
|
|
35
|
-
const
|
|
36
|
-
(
|
|
46
|
+
const absoultePath = findFile(error);
|
|
47
|
+
const file = node_path_1.default.relative(node_path_1.default.resolve(node_process_1.default.cwd()), absoultePath);
|
|
48
|
+
let message = '';
|
|
37
49
|
if (typeof options.message === 'string')
|
|
38
|
-
|
|
50
|
+
message = options.message;
|
|
39
51
|
else if (options.message instanceof Error)
|
|
40
|
-
|
|
52
|
+
message = options.message.message;
|
|
41
53
|
else if (typeof options.defaultMessage === 'string')
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
message = options.defaultMessage;
|
|
55
|
+
const finalMessage = (message === null || message === void 0 ? void 0 : message.trim().length) > 0
|
|
56
|
+
? `${formatFail(message)}`
|
|
57
|
+
: `${formatFail('No Message')}`;
|
|
58
|
+
console.log(isPoku
|
|
59
|
+
? `${finalMessage} ${format_js_1.format.dim(format_js_1.format.fail(`› ${FILE}`))}`
|
|
60
|
+
: finalMessage);
|
|
61
|
+
file && console.log(`${format_js_1.format.dim(' File')} ${file}`);
|
|
62
|
+
console.log(`${format_js_1.format.dim(' Code')} ${code}`);
|
|
63
|
+
console.log(`${format_js_1.format.dim(' Operator')} ${operator}${node_os_1.EOL}`);
|
|
47
64
|
if (!(options === null || options === void 0 ? void 0 : options.hideDiff)) {
|
|
48
|
-
console.log(format_js_1.format.dim(
|
|
65
|
+
console.log(format_js_1.format.dim(` ${(options === null || options === void 0 ? void 0 : options.actual) || 'Actual'}:`));
|
|
49
66
|
console.log(format_js_1.format.bold(typeof actual === 'function' || actual instanceof RegExp
|
|
50
|
-
? String(actual)
|
|
51
|
-
: format_js_1.format.fail(JSON.stringify(actual))));
|
|
52
|
-
console.log(`${node_os_1.EOL}${format_js_1.format.dim(`${(options === null || options === void 0 ? void 0 : options.expected) || 'Expected'}:`)}`);
|
|
53
|
-
console.log(format_js_1.format.bold(typeof expected === 'function' || expected instanceof RegExp
|
|
54
|
-
? String(expected)
|
|
55
|
-
: format_js_1.format.success(JSON.stringify(expected))));
|
|
56
|
-
(0, hr_js_1.hr)();
|
|
67
|
+
? ` ${String(actual)}`
|
|
68
|
+
: ` ${format_js_1.format.fail(JSON.stringify(actual))}`));
|
|
69
|
+
console.log(`${node_os_1.EOL} ${format_js_1.format.dim(`${(options === null || options === void 0 ? void 0 : options.expected) || 'Expected'}:`)}`);
|
|
70
|
+
console.log(format_js_1.format.bold(`${typeof expected === 'function' || expected instanceof RegExp
|
|
71
|
+
? ` ${String(expected)}`
|
|
72
|
+
: ` ${format_js_1.format.success(JSON.stringify(expected))}`}`));
|
|
57
73
|
}
|
|
58
74
|
if (options.throw) {
|
|
59
75
|
console.log(error);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const removeConsecutiveRepeats: (arr: string[], specificItem: RegExp) => string[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeConsecutiveRepeats = void 0;
|
|
4
|
+
const removeConsecutiveRepeats = (arr, specificItem) => {
|
|
5
|
+
const result = [];
|
|
6
|
+
let consecutiveCount = 0;
|
|
7
|
+
for (let i = 0; i < arr.length; i++) {
|
|
8
|
+
if (specificItem.test(arr[i])) {
|
|
9
|
+
consecutiveCount++;
|
|
10
|
+
if (consecutiveCount <= 2) {
|
|
11
|
+
result.push(arr[i]);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
consecutiveCount = 0;
|
|
16
|
+
result.push(arr[i]);
|
|
17
|
+
}
|
|
18
|
+
// Check if the next item is different or we're at the end of the array
|
|
19
|
+
if (i + 1 === arr.length || !specificItem.test(arr[i + 1])) {
|
|
20
|
+
// If more than two consecutive, remove them from the result
|
|
21
|
+
if (consecutiveCount > 2) {
|
|
22
|
+
result.splice(-consecutiveCount);
|
|
23
|
+
}
|
|
24
|
+
consecutiveCount = 0; // Reset the counter for the next group
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
exports.removeConsecutiveRepeats = removeConsecutiveRepeats;
|
package/lib/modules/assert.js
CHANGED
|
@@ -35,7 +35,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
35
35
|
exports.assert = void 0;
|
|
36
36
|
const nodeAssert = __importStar(require("assert"));
|
|
37
37
|
const parseAsssetion_js_1 = require("../helpers/parseAsssetion.js");
|
|
38
|
-
const format_js_1 = require("../helpers/format.js");
|
|
39
38
|
const ok = (value, message) => (0, parseAsssetion_js_1.parseAssertion)(() => nodeAssert.ok(value), { message });
|
|
40
39
|
const equal = (actual, expected, message) => (0, parseAsssetion_js_1.parseAssertion)(() => nodeAssert.equal(actual, expected), { message });
|
|
41
40
|
const deepEqual = (actual, expected, message) => (0, parseAsssetion_js_1.parseAssertion)(() => nodeAssert.deepEqual(actual, expected), { message });
|
|
@@ -47,7 +46,7 @@ const doesNotMatch = (value, regExp, message) => (0, parseAsssetion_js_1.parseAs
|
|
|
47
46
|
message,
|
|
48
47
|
actual: 'Value',
|
|
49
48
|
expected: 'RegExp',
|
|
50
|
-
defaultMessage:
|
|
49
|
+
defaultMessage: 'Value should not match regExp',
|
|
51
50
|
});
|
|
52
51
|
function doesNotReject(block, errorOrMessage, message) {
|
|
53
52
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -62,7 +61,7 @@ function doesNotReject(block, errorOrMessage, message) {
|
|
|
62
61
|
throw error;
|
|
63
62
|
}, {
|
|
64
63
|
message,
|
|
65
|
-
defaultMessage:
|
|
64
|
+
defaultMessage: 'Got unwanted rejection',
|
|
66
65
|
hideDiff: true,
|
|
67
66
|
throw: true,
|
|
68
67
|
});
|
|
@@ -77,7 +76,7 @@ function doesNotReject(block, errorOrMessage, message) {
|
|
|
77
76
|
throw error_1;
|
|
78
77
|
}, {
|
|
79
78
|
message: typeof errorOrMessage === 'string' ? errorOrMessage : undefined,
|
|
80
|
-
defaultMessage:
|
|
79
|
+
defaultMessage: 'Got unwanted rejection',
|
|
81
80
|
hideDiff: true,
|
|
82
81
|
throw: true,
|
|
83
82
|
});
|
|
@@ -97,7 +96,7 @@ function doesNotThrow(block, errorOrMessage, message) {
|
|
|
97
96
|
throw error;
|
|
98
97
|
}, {
|
|
99
98
|
message: message,
|
|
100
|
-
defaultMessage:
|
|
99
|
+
defaultMessage: 'Expected function not to throw',
|
|
101
100
|
hideDiff: true,
|
|
102
101
|
throw: true,
|
|
103
102
|
});
|
|
@@ -113,7 +112,7 @@ function doesNotThrow(block, errorOrMessage, message) {
|
|
|
113
112
|
throw error;
|
|
114
113
|
}, {
|
|
115
114
|
message: msg,
|
|
116
|
-
defaultMessage:
|
|
115
|
+
defaultMessage: 'Expected function not to throw',
|
|
117
116
|
hideDiff: true,
|
|
118
117
|
throw: true,
|
|
119
118
|
});
|
|
@@ -132,7 +131,7 @@ function throws(block, errorOrMessage, message) {
|
|
|
132
131
|
throw error;
|
|
133
132
|
}, {
|
|
134
133
|
message: message,
|
|
135
|
-
defaultMessage:
|
|
134
|
+
defaultMessage: 'Expected function to throw',
|
|
136
135
|
hideDiff: true,
|
|
137
136
|
});
|
|
138
137
|
}
|
|
@@ -147,7 +146,7 @@ function throws(block, errorOrMessage, message) {
|
|
|
147
146
|
throw error;
|
|
148
147
|
}, {
|
|
149
148
|
message: msg,
|
|
150
|
-
defaultMessage:
|
|
149
|
+
defaultMessage: 'Expected function to throw',
|
|
151
150
|
hideDiff: true,
|
|
152
151
|
});
|
|
153
152
|
}
|
|
@@ -167,7 +166,7 @@ const match = (value, regExp, message) => (0, parseAsssetion_js_1.parseAssertion
|
|
|
167
166
|
message,
|
|
168
167
|
actual: 'Value',
|
|
169
168
|
expected: 'RegExp',
|
|
170
|
-
defaultMessage:
|
|
169
|
+
defaultMessage: 'Value should match regExp',
|
|
171
170
|
});
|
|
172
171
|
const ifError = (value) => {
|
|
173
172
|
try {
|
|
@@ -177,7 +176,7 @@ const ifError = (value) => {
|
|
|
177
176
|
(0, parseAsssetion_js_1.parseAssertion)(() => {
|
|
178
177
|
throw error;
|
|
179
178
|
}, {
|
|
180
|
-
defaultMessage:
|
|
179
|
+
defaultMessage: 'Expected no error, but received an error',
|
|
181
180
|
hideDiff: true,
|
|
182
181
|
throw: true,
|
|
183
182
|
});
|
|
@@ -192,7 +191,7 @@ const fail = (message) => {
|
|
|
192
191
|
throw error;
|
|
193
192
|
}, {
|
|
194
193
|
message,
|
|
195
|
-
defaultMessage:
|
|
194
|
+
defaultMessage: 'Test failed intentionally',
|
|
196
195
|
hideDiff: true,
|
|
197
196
|
});
|
|
198
197
|
}
|
|
@@ -210,7 +209,7 @@ function rejects(block, errorOrMessage, message) {
|
|
|
210
209
|
throw error;
|
|
211
210
|
}, {
|
|
212
211
|
message,
|
|
213
|
-
defaultMessage:
|
|
212
|
+
defaultMessage: 'Expected promise to be rejected with specified error',
|
|
214
213
|
hideDiff: true,
|
|
215
214
|
});
|
|
216
215
|
}
|
|
@@ -225,7 +224,7 @@ function rejects(block, errorOrMessage, message) {
|
|
|
225
224
|
throw error_1;
|
|
226
225
|
}, {
|
|
227
226
|
message: msg,
|
|
228
|
-
defaultMessage:
|
|
227
|
+
defaultMessage: 'Expected promise to be rejected',
|
|
229
228
|
hideDiff: true,
|
|
230
229
|
});
|
|
231
230
|
}
|
package/lib/modules/exit.js
CHANGED
|
@@ -5,23 +5,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.exit = void 0;
|
|
7
7
|
const node_process_1 = __importDefault(require("process"));
|
|
8
|
-
const node_os_1 = require("os");
|
|
9
8
|
const hr_js_1 = require("../helpers/hr.js");
|
|
9
|
+
const run_tests_js_1 = require("../services/run-tests.js");
|
|
10
|
+
const format_js_1 = require("../helpers/format.js");
|
|
10
11
|
const exit = (code, quiet) => {
|
|
12
|
+
const isPoku = run_tests_js_1.results.success > 0 || run_tests_js_1.results.fail > 0;
|
|
11
13
|
!quiet &&
|
|
12
14
|
node_process_1.default.on('exit', (code) => {
|
|
13
|
-
|
|
15
|
+
isPoku &&
|
|
16
|
+
console.log(format_js_1.format.bg(42, `PASS › ${run_tests_js_1.results.success}`), format_js_1.format.bg(run_tests_js_1.results.fail === 0 ? 100 : 41, `FAIL › ${run_tests_js_1.results.fail}`));
|
|
17
|
+
isPoku && (0, hr_js_1.hr)();
|
|
18
|
+
console.log(`${format_js_1.format.dim('Exited with code')} ${format_js_1.format.bold(format_js_1.format === null || format_js_1.format === void 0 ? void 0 : format_js_1.format[code === 0 ? 'success' : 'fail'](String(code)))}`);
|
|
14
19
|
});
|
|
15
|
-
!quiet && (0, hr_js_1.hr)();
|
|
16
|
-
if (code !== 0)
|
|
17
|
-
!quiet && console.log('Some tests failed.');
|
|
20
|
+
isPoku && !quiet && (0, hr_js_1.hr)();
|
|
21
|
+
if (code !== 0)
|
|
18
22
|
node_process_1.default.exit(1);
|
|
19
|
-
}
|
|
20
|
-
!quiet && console.log('All tests passed.');
|
|
21
23
|
node_process_1.default.exit(0);
|
|
22
24
|
};
|
|
23
25
|
exports.exit = exit;
|
|
24
|
-
node_process_1.default.stdout.on('resize', hr_js_1.hr);
|
|
25
26
|
node_process_1.default.on('unhandledRejection', (reason) => {
|
|
26
27
|
console.log('unhandledRejection', reason);
|
|
27
28
|
node_process_1.default.exit(1);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Configs } from '../@types/list-files.js';
|
|
2
|
+
export declare const sanitizePath: (input: string, ensureTarget?: boolean) => string;
|
|
2
3
|
export declare const escapeRegExp: (string: string) => string;
|
|
3
4
|
export declare const listFiles: (dirPath: string, files?: string[], configs?: Configs) => string[];
|
|
4
5
|
export declare const publicListFiles: (targetDir: string, configs?: Configs) => string[];
|
|
@@ -4,18 +4,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
var _a;
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.publicListFiles = exports.listFiles = exports.escapeRegExp = void 0;
|
|
7
|
+
exports.publicListFiles = exports.listFiles = exports.escapeRegExp = exports.sanitizePath = void 0;
|
|
8
8
|
const node_process_1 = __importDefault(require("process"));
|
|
9
9
|
const node_fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const node_path_1 = __importDefault(require("path"));
|
|
11
|
+
const sanitizePath = (input, ensureTarget) => {
|
|
12
|
+
const sanitizedPath = input
|
|
13
|
+
.replace(/[/\\]+/g, node_path_1.default.sep) // adapting slashes according to OS
|
|
14
|
+
.replace(/(\.\.(\/|\\|$))+/g, '') // ensure the current path level
|
|
15
|
+
.replace(/[<>:|^?*]+/g, ''); // removing unusual path characters
|
|
16
|
+
// Preventing absolute path access
|
|
17
|
+
return ensureTarget ? sanitizedPath.replace(/^[/\\]/, './') : sanitizedPath;
|
|
18
|
+
};
|
|
19
|
+
exports.sanitizePath = sanitizePath;
|
|
11
20
|
const escapeRegExp = (string) => string.replace(/[.*{}[\]\\]/g, '\\$&');
|
|
12
21
|
exports.escapeRegExp = escapeRegExp;
|
|
13
22
|
const envFilter = ((_a = node_process_1.default.env.FILTER) === null || _a === void 0 ? void 0 : _a.trim())
|
|
14
23
|
? new RegExp((0, exports.escapeRegExp)(node_process_1.default.env.FILTER), 'i')
|
|
15
24
|
: null;
|
|
16
25
|
const listFiles = (dirPath, files = [], configs) => {
|
|
17
|
-
const currentFiles = node_fs_1.default.readdirSync(dirPath);
|
|
18
|
-
const defaultRegExp = /\.test\./i;
|
|
26
|
+
const currentFiles = node_fs_1.default.readdirSync((0, exports.sanitizePath)(dirPath));
|
|
27
|
+
const defaultRegExp = /\.(test|spec)\./i;
|
|
19
28
|
const filter = (envFilter
|
|
20
29
|
? envFilter
|
|
21
30
|
: (configs === null || configs === void 0 ? void 0 : configs.filter) instanceof RegExp
|
|
@@ -27,7 +36,9 @@ const listFiles = (dirPath, files = [], configs) => {
|
|
|
27
36
|
: [configs.exclude]
|
|
28
37
|
: undefined;
|
|
29
38
|
for (const file of currentFiles) {
|
|
30
|
-
const fullPath = node_path_1.default.join(dirPath, file);
|
|
39
|
+
const fullPath = (0, exports.sanitizePath)(node_path_1.default.join(dirPath, file));
|
|
40
|
+
if (/node_modules/.test(fullPath))
|
|
41
|
+
continue;
|
|
31
42
|
if (exclude && exclude.some((regex) => regex.test(fullPath)))
|
|
32
43
|
continue;
|
|
33
44
|
if (node_fs_1.default.statSync(fullPath).isDirectory())
|
|
@@ -38,5 +49,5 @@ const listFiles = (dirPath, files = [], configs) => {
|
|
|
38
49
|
return files;
|
|
39
50
|
};
|
|
40
51
|
exports.listFiles = listFiles;
|
|
41
|
-
const publicListFiles = (targetDir, configs) => (0, exports.listFiles)(targetDir, [], configs);
|
|
52
|
+
const publicListFiles = (targetDir, configs) => (0, exports.listFiles)((0, exports.sanitizePath)(targetDir), [], configs);
|
|
42
53
|
exports.publicListFiles = publicListFiles;
|
package/lib/modules/poku.js
CHANGED
|
@@ -10,17 +10,38 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.poku = void 0;
|
|
13
|
+
const node_os_1 = require("os");
|
|
13
14
|
const force_array_js_1 = require("../helpers/force-array.js");
|
|
14
15
|
const run_tests_js_1 = require("../services/run-tests.js");
|
|
15
16
|
const exit_js_1 = require("./exit.js");
|
|
17
|
+
const format_js_1 = require("../helpers/format.js");
|
|
18
|
+
const logs_js_1 = require("../helpers/logs.js");
|
|
19
|
+
const hr_js_1 = require("../helpers/hr.js");
|
|
20
|
+
const run_test_file_js_1 = require("../services/run-test-file.js");
|
|
21
|
+
const indentation_js_1 = require("../helpers/indentation.js");
|
|
16
22
|
function poku(targetDirs, configs) {
|
|
17
23
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18
24
|
let code = 0;
|
|
19
|
-
const
|
|
25
|
+
const prepareDirs = (0, force_array_js_1.forceArray)(targetDirs);
|
|
26
|
+
const dirs = prepareDirs.length > 0 ? prepareDirs : ['./'];
|
|
27
|
+
const showLogs = !(0, logs_js_1.isQuiet)(configs);
|
|
20
28
|
if (configs === null || configs === void 0 ? void 0 : configs.parallel) {
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
if (showLogs) {
|
|
30
|
+
(0, hr_js_1.hr)();
|
|
31
|
+
console.log(`${format_js_1.format.bold('Running the Test Suite in Parallel')}${node_os_1.EOL}`);
|
|
32
|
+
}
|
|
33
|
+
const concurrency = yield Promise.all(dirs.map((dir) => (0, run_tests_js_1.runTestsParallel)(dir, configs)));
|
|
34
|
+
if (concurrency.some((result) => !result))
|
|
23
35
|
code = 1;
|
|
36
|
+
showLogs && (0, hr_js_1.hr)();
|
|
37
|
+
if (showLogs && run_test_file_js_1.fileResults.success.length > 0)
|
|
38
|
+
console.log(run_test_file_js_1.fileResults.success
|
|
39
|
+
.map((current) => `${indentation_js_1.indentation.test}${format_js_1.format.success('✔')} ${format_js_1.format.dim(current)}`)
|
|
40
|
+
.join(node_os_1.EOL));
|
|
41
|
+
if (showLogs && run_test_file_js_1.fileResults.fail.length > 0)
|
|
42
|
+
console.log(run_test_file_js_1.fileResults.fail
|
|
43
|
+
.map((current) => `${indentation_js_1.indentation.test}${format_js_1.format.fail('✘')} ${current}`)
|
|
44
|
+
.join(node_os_1.EOL));
|
|
24
45
|
if (configs === null || configs === void 0 ? void 0 : configs.noExit)
|
|
25
46
|
return code;
|
|
26
47
|
(0, exit_js_1.exit)(code, configs === null || configs === void 0 ? void 0 : configs.quiet);
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import { Configs } from '../@types/poku.js';
|
|
2
|
+
type FileResults = {
|
|
3
|
+
success: string[];
|
|
4
|
+
fail: string[];
|
|
5
|
+
};
|
|
6
|
+
export declare const fileResults: FileResults;
|
|
2
7
|
export declare const runTestFile: (filePath: string, configs?: Configs) => Promise<boolean>;
|
|
8
|
+
export {};
|
|
@@ -3,44 +3,83 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.runTestFile = void 0;
|
|
6
|
+
exports.runTestFile = exports.fileResults = void 0;
|
|
7
7
|
const node_process_1 = __importDefault(require("process"));
|
|
8
|
-
const
|
|
8
|
+
const node_os_1 = require("os");
|
|
9
9
|
const node_path_1 = __importDefault(require("path"));
|
|
10
|
+
const node_child_process_1 = require("child_process");
|
|
10
11
|
const runner_js_1 = require("../helpers/runner.js");
|
|
11
12
|
const indentation_js_1 = require("../helpers/indentation.js");
|
|
12
13
|
const format_js_1 = require("../helpers/format.js");
|
|
13
14
|
const logs_js_1 = require("../helpers/logs.js");
|
|
15
|
+
const remove_repeats_js_1 = require("../helpers/remove-repeats.js");
|
|
16
|
+
exports.fileResults = {
|
|
17
|
+
success: [],
|
|
18
|
+
fail: [],
|
|
19
|
+
};
|
|
14
20
|
const runTestFile = (filePath, configs) => new Promise((resolve) => {
|
|
15
|
-
let output = '';
|
|
16
|
-
const showLogs = !(0, logs_js_1.isQuiet)(configs);
|
|
17
|
-
const showSuccess = (0, logs_js_1.showSuccesses)(configs);
|
|
18
|
-
const showFailure = (0, logs_js_1.showFailures)(configs);
|
|
19
|
-
const log = () => console.log(output === null || output === void 0 ? void 0 : output.trim());
|
|
20
|
-
const fileRelative = node_path_1.default.relative(node_process_1.default.cwd(), filePath);
|
|
21
|
-
showLogs &&
|
|
22
|
-
console.log(`${indentation_js_1.indentation.test}${format_js_1.format.info('→')} ${fileRelative}`);
|
|
23
21
|
const runtimeOptions = (0, runner_js_1.runner)(filePath, configs);
|
|
24
22
|
const runtime = runtimeOptions.shift();
|
|
25
23
|
const runtimeArguments = runtimeOptions.length > 1 ? [...runtimeOptions, filePath] : [filePath];
|
|
24
|
+
const fileRelative = node_path_1.default.relative(node_process_1.default.cwd(), filePath);
|
|
25
|
+
const showLogs = !(0, logs_js_1.isQuiet)(configs);
|
|
26
|
+
const showSuccess = (0, logs_js_1.isDebug)(configs);
|
|
27
|
+
const pad = (configs === null || configs === void 0 ? void 0 : configs.parallel) ? ' ' : ' ';
|
|
28
|
+
let output = '';
|
|
29
|
+
const log = () => {
|
|
30
|
+
const outputs = (0, remove_repeats_js_1.removeConsecutiveRepeats)(showSuccess
|
|
31
|
+
? output.split(/(\r\n|\r|\n)/)
|
|
32
|
+
: output.split(/(\r\n|\r|\n)/).filter((current) => {
|
|
33
|
+
if (current.includes('Exited with code'))
|
|
34
|
+
return false;
|
|
35
|
+
return (/u001b\[0m|(\r\n|\r|\n)/i.test(JSON.stringify(current)) ||
|
|
36
|
+
current === '');
|
|
37
|
+
}), /(\r\n|\r|\n)|^$/);
|
|
38
|
+
// Remove last EOL
|
|
39
|
+
outputs.length > 1 && outputs.pop();
|
|
40
|
+
if (!showSuccess &&
|
|
41
|
+
/error:/i.test(output) &&
|
|
42
|
+
!/error:/i.test(outputs.join()))
|
|
43
|
+
Object.assign(outputs, [
|
|
44
|
+
...outputs,
|
|
45
|
+
format_js_1.format.bold(format_js_1.format.fail(`✘ External Error ${format_js_1.format.dim(`› ${fileRelative}`)}`)),
|
|
46
|
+
format_js_1.format.dim(' For detailed diagnostics:'),
|
|
47
|
+
`${format_js_1.format.dim(` CLI ›`)} rerun with the ${format_js_1.format.bold('--debug')} flag enabled.`,
|
|
48
|
+
`${format_js_1.format.dim(` API ›`)} set the config option ${format_js_1.format.bold('debug')} to true.`,
|
|
49
|
+
`${format_js_1.format.dim(' RUN ›')} ${format_js_1.format.bold(`${runtime === 'tsx' ? 'npx tsx' : runtime}${runtimeArguments.slice(0, -1).join(' ')} ${fileRelative}`)}`,
|
|
50
|
+
]);
|
|
51
|
+
const mappedOutputs = outputs.map((current) => `${pad}${current}`);
|
|
52
|
+
if (outputs.length === 1 && outputs[0] === '')
|
|
53
|
+
return;
|
|
54
|
+
console.log(showSuccess ? mappedOutputs.join('') : mappedOutputs.join(node_os_1.EOL));
|
|
55
|
+
};
|
|
56
|
+
const stdOut = (data) => {
|
|
57
|
+
output += String(data);
|
|
58
|
+
};
|
|
59
|
+
if (!(configs === null || configs === void 0 ? void 0 : configs.parallel)) {
|
|
60
|
+
showLogs &&
|
|
61
|
+
console.log(`${indentation_js_1.indentation.test}${format_js_1.format.info(format_js_1.format.dim('●'))} ${format_js_1.format.dim(fileRelative)}`);
|
|
62
|
+
}
|
|
26
63
|
const child = (0, node_child_process_1.spawn)(runtime, runtimeArguments, {
|
|
27
64
|
stdio: ['inherit', 'pipe', 'pipe'],
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
child.stdout.on('data', (data) => {
|
|
31
|
-
output += data.toString();
|
|
32
|
-
});
|
|
33
|
-
child.stderr.on('data', (data) => {
|
|
34
|
-
output += data.toString();
|
|
65
|
+
shell: false,
|
|
66
|
+
env: Object.assign(Object.assign({}, node_process_1.default.env), { FILE: (configs === null || configs === void 0 ? void 0 : configs.parallel) ? fileRelative : '' }),
|
|
35
67
|
});
|
|
68
|
+
child.stdout.on('data', stdOut);
|
|
69
|
+
child.stderr.on('data', stdOut);
|
|
36
70
|
child.on('close', (code) => {
|
|
37
|
-
if (showLogs
|
|
38
|
-
((code === 0 && showSuccess) || (code !== 0 && showFailure)))
|
|
71
|
+
if (showLogs)
|
|
39
72
|
log();
|
|
40
|
-
|
|
73
|
+
const result = code === 0;
|
|
74
|
+
if (result)
|
|
75
|
+
exports.fileResults.success.push(fileRelative);
|
|
76
|
+
else
|
|
77
|
+
exports.fileResults.fail.push(fileRelative);
|
|
78
|
+
resolve(result);
|
|
41
79
|
});
|
|
42
80
|
child.on('error', (err) => {
|
|
43
81
|
console.log(`Failed to start test: ${filePath}`, err);
|
|
82
|
+
exports.fileResults.fail.push(fileRelative);
|
|
44
83
|
resolve(false);
|
|
45
84
|
});
|
|
46
85
|
});
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { Configs } from '../@types/poku.js';
|
|
2
|
+
export declare const results: {
|
|
3
|
+
success: number;
|
|
4
|
+
fail: number;
|
|
5
|
+
};
|
|
2
6
|
export declare const runTests: (dir: string, configs?: Configs) => Promise<boolean>;
|
|
3
7
|
export declare const runTestsParallel: (dir: string, configs?: Configs) => Promise<boolean>;
|
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.runTestsParallel = exports.runTests = void 0;
|
|
15
|
+
exports.runTestsParallel = exports.runTests = exports.results = void 0;
|
|
16
16
|
const node_process_1 = __importDefault(require("process"));
|
|
17
17
|
const node_os_1 = require("os");
|
|
18
18
|
const node_path_1 = __importDefault(require("path"));
|
|
@@ -23,9 +23,13 @@ const hr_js_1 = require("../helpers/hr.js");
|
|
|
23
23
|
const format_js_1 = require("../helpers/format.js");
|
|
24
24
|
const run_test_file_js_1 = require("./run-test-file.js");
|
|
25
25
|
const logs_js_1 = require("../helpers/logs.js");
|
|
26
|
+
exports.results = {
|
|
27
|
+
success: 0,
|
|
28
|
+
fail: 0,
|
|
29
|
+
};
|
|
26
30
|
const runTests = (dir, configs) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
31
|
const cwd = node_process_1.default.cwd();
|
|
28
|
-
const testDir = node_path_1.default.join(cwd, dir);
|
|
32
|
+
const testDir = node_path_1.default.join(cwd, (0, list_files_js_1.sanitizePath)(dir));
|
|
29
33
|
const currentDir = node_path_1.default.relative(cwd, testDir);
|
|
30
34
|
const files = (0, list_files_js_1.listFiles)(testDir, undefined, configs);
|
|
31
35
|
const totalTests = files.length;
|
|
@@ -33,7 +37,7 @@ const runTests = (dir, configs) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
33
37
|
let passed = true;
|
|
34
38
|
if (showLogs) {
|
|
35
39
|
(0, hr_js_1.hr)();
|
|
36
|
-
console.log(`${format_js_1.format.bold('Directory:')} ${format_js_1.format.underline(currentDir)}${node_os_1.EOL}`);
|
|
40
|
+
console.log(`${format_js_1.format.bold('Directory:')} ${format_js_1.format.underline(`./${currentDir}`)}${node_os_1.EOL}`);
|
|
37
41
|
}
|
|
38
42
|
for (let i = 0; i < files.length; i++) {
|
|
39
43
|
const filePath = files[i];
|
|
@@ -43,13 +47,16 @@ const runTests = (dir, configs) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
43
47
|
const counter = format_js_1.format.counter(testNumber, totalTests);
|
|
44
48
|
const command = `${(0, runner_js_1.runner)(fileRelative, configs).join(' ')} ${fileRelative}`;
|
|
45
49
|
const nextLine = i + 1 !== files.length ? node_os_1.EOL : '';
|
|
46
|
-
const log = `${counter}/${totalTests} ${command}
|
|
50
|
+
const log = `${counter}/${totalTests} ${command}`;
|
|
47
51
|
if (testPassed) {
|
|
52
|
+
++exports.results.success;
|
|
48
53
|
showLogs &&
|
|
49
|
-
console.log(`${indentation_js_1.indentation.test}${format_js_1.format.success('✔')} ${log}
|
|
54
|
+
console.log(`${indentation_js_1.indentation.test}${format_js_1.format.success('✔')} ${log}`, nextLine);
|
|
50
55
|
}
|
|
51
56
|
else {
|
|
52
|
-
|
|
57
|
+
++exports.results.fail;
|
|
58
|
+
showLogs &&
|
|
59
|
+
console.log(`${indentation_js_1.indentation.test}${format_js_1.format.fail('✘')} ${log}`, nextLine);
|
|
53
60
|
passed = false;
|
|
54
61
|
}
|
|
55
62
|
}
|
|
@@ -60,23 +67,16 @@ const runTestsParallel = (dir, configs) => __awaiter(void 0, void 0, void 0, fun
|
|
|
60
67
|
const cwd = node_process_1.default.cwd();
|
|
61
68
|
const testDir = node_path_1.default.join(cwd, dir);
|
|
62
69
|
const files = (0, list_files_js_1.listFiles)(testDir, undefined, configs);
|
|
63
|
-
const showLogs = !(0, logs_js_1.isQuiet)(configs);
|
|
64
70
|
const promises = files.map((filePath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
-
const fileRelative = node_path_1.default.relative(cwd, filePath);
|
|
66
71
|
const testPassed = yield (0, run_test_file_js_1.runTestFile)(filePath, configs);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
showLogs &&
|
|
70
|
-
console.log(`${indentation_js_1.indentation.test}${format_js_1.format.success('✔')} ${command}`);
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
showLogs &&
|
|
74
|
-
console.log(`${indentation_js_1.indentation.test}${format_js_1.format.fail('✖')} ${command}`);
|
|
72
|
+
if (!testPassed) {
|
|
73
|
+
++exports.results.fail;
|
|
75
74
|
return false;
|
|
76
75
|
}
|
|
76
|
+
++exports.results.success;
|
|
77
77
|
return true;
|
|
78
78
|
}));
|
|
79
|
-
const
|
|
80
|
-
return
|
|
79
|
+
const concurrency = yield Promise.all(promises);
|
|
80
|
+
return concurrency.every((result) => result);
|
|
81
81
|
});
|
|
82
82
|
exports.runTestsParallel = runTestsParallel;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poku",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "🐷 Poku
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "🐷 Poku brings human-friendly testing and assertion to Node.js, Bun & Deno at the same time.",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "npx tsx --tsconfig ./tsconfig.test.json ./test/run.test.ts",
|
|
@@ -9,14 +9,16 @@
|
|
|
9
9
|
"test:node": "FILTER='node-' npm run test:ci",
|
|
10
10
|
"test:deno": "FILTER='deno-' npm run test:ci",
|
|
11
11
|
"test:bun": "FILTER='bun-' npm run test:ci",
|
|
12
|
-
"update": "npx npu;",
|
|
13
12
|
"prebuild": "rm -rf ./lib ./ci",
|
|
14
13
|
"build": "npx tsc; npx tsc -p tsconfig.test.json",
|
|
15
14
|
"postbuild": "npx tsx ./tools/compatibility/node.ts; chmod +x lib/bin/index.js; npm audit",
|
|
16
15
|
"eslint:checker": "npx eslint . --ext .js,.ts",
|
|
17
16
|
"eslint:fix": "npx eslint . --fix --config ./.eslintrc.json",
|
|
17
|
+
"lint:checker": "npm run eslint:checker; npm run prettier:checker",
|
|
18
|
+
"lint:fix": "npm run eslint:fix; npm run prettier:fix",
|
|
18
19
|
"prettier:checker": "npx prettier --check .",
|
|
19
|
-
"prettier:fix": "npx prettier --write .github/workflows/*.yml ."
|
|
20
|
+
"prettier:fix": "npx prettier --write .github/workflows/*.yml .",
|
|
21
|
+
"update": "npx npu; npm i; npm run lint:fix; npm audit"
|
|
20
22
|
},
|
|
21
23
|
"license": "MIT",
|
|
22
24
|
"repository": {
|
|
@@ -78,17 +80,18 @@
|
|
|
78
80
|
"engines": {
|
|
79
81
|
"node": ">=6.0.0",
|
|
80
82
|
"bun": ">=0.5.3",
|
|
81
|
-
"deno": ">=1.17.0"
|
|
83
|
+
"deno": ">=1.17.0",
|
|
84
|
+
"typescript": ">=5.0.2"
|
|
82
85
|
},
|
|
83
86
|
"files": [
|
|
84
87
|
"lib"
|
|
85
88
|
],
|
|
86
89
|
"type": "commonjs",
|
|
87
90
|
"devDependencies": {
|
|
88
|
-
"@types/node": "^20.11.
|
|
89
|
-
"@typescript-eslint/eslint-plugin": "^7.0
|
|
90
|
-
"@typescript-eslint/parser": "^7.0
|
|
91
|
-
"eslint": "^8.
|
|
91
|
+
"@types/node": "^20.11.21",
|
|
92
|
+
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
|
93
|
+
"@typescript-eslint/parser": "^7.1.0",
|
|
94
|
+
"eslint": "^8.57.0",
|
|
92
95
|
"eslint-config-prettier": "^9.1.0",
|
|
93
96
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
94
97
|
"eslint-plugin-import": "^2.29.1",
|