@reporters/testwatch 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/index.js +8 -6
- package/package.json +3 -2
- package/tests/fixtures/not-test.js +6 -0
- package/tests/index.test.js +61 -25
- /package/tests/fixtures/{j.test.js → j.spec.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.2.0](https://github.com/MoLow/reporters/compare/testwatch-v1.1.1...testwatch-v1.2.0) (2023-06-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add test:watch script ([4357fbd](https://github.com/MoLow/reporters/commit/4357fbde5f337cfd39226497f8ce0f6760f8a62c))
|
|
9
|
+
* change default file filter ([5968235](https://github.com/MoLow/reporters/commit/596823529cd9a86e5eeada0523825fa215e49efe))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* don't exit when no tests on initial run ([66bcc2b](https://github.com/MoLow/reporters/commit/66bcc2bc6436b544900cfbceb4bbfb0d93973490))
|
|
15
|
+
|
|
16
|
+
## [1.1.1](https://github.com/MoLow/reporters/compare/testwatch-v1.1.0...testwatch-v1.1.1) (2023-06-12)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* increas maximum listeners of event emitters ([b16d2ab](https://github.com/MoLow/reporters/commit/b16d2ab3b55554e1aaa9b9ca2222254bac364803))
|
|
22
|
+
* support partial file name filter ([2b3f0ab](https://github.com/MoLow/reporters/commit/2b3f0abe0be37450c7b9189667ad47d4d39a4252))
|
|
23
|
+
|
|
3
24
|
## [1.1.0](https://github.com/MoLow/reporters/compare/testwatch-v1.0.0...testwatch-v1.1.0) (2023-06-08)
|
|
4
25
|
|
|
5
26
|
|
package/index.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const { run } = require('node:test');
|
|
4
4
|
const { pipeline } = require('node:stream/promises');
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
on, once, EventEmitter, setMaxListeners,
|
|
7
|
+
} = require('node:events');
|
|
6
8
|
const { glob } = require('glob');
|
|
7
9
|
const chalk = require('chalk');
|
|
8
10
|
const { isSupported } = require('./nodeVersion');
|
|
@@ -28,6 +30,7 @@ const KEY_NAMES = {
|
|
|
28
30
|
};
|
|
29
31
|
const UnknownCommand = Symbol('UnknownKey');
|
|
30
32
|
|
|
33
|
+
setMaxListeners(Infinity);
|
|
31
34
|
process.stdout.setMaxListeners(Infinity);
|
|
32
35
|
process.setMaxListeners(Infinity);
|
|
33
36
|
process.stdin.setEncoding('utf8');
|
|
@@ -36,7 +39,7 @@ process.stdin.setRawMode?.(true);
|
|
|
36
39
|
class REPL {
|
|
37
40
|
#controller = new AbortController();
|
|
38
41
|
|
|
39
|
-
#filesFilter = '';
|
|
42
|
+
#filesFilter = process.argv[2] || '';
|
|
40
43
|
|
|
41
44
|
#testsFilter = '';
|
|
42
45
|
|
|
@@ -56,7 +59,7 @@ class REPL {
|
|
|
56
59
|
async #runTests() {
|
|
57
60
|
this.#controller.abort();
|
|
58
61
|
this.#controller = new AbortController();
|
|
59
|
-
const filter = this.#filesFilter ? `**/${this.#filesFilter}
|
|
62
|
+
const filter = this.#filesFilter ? `**/${this.#filesFilter}*.*` : '**/?(*.)+(spec|test).[jt]s';
|
|
60
63
|
const files = await glob(filter, { ignore: 'node_modules/**' });
|
|
61
64
|
|
|
62
65
|
if (!files.length) {
|
|
@@ -200,7 +203,7 @@ class REPL {
|
|
|
200
203
|
if (this.#filesFilter || this.#testsFilter) {
|
|
201
204
|
const message = `
|
|
202
205
|
${chalk.white.bold('Active Filters:')} \
|
|
203
|
-
${this.#filesFilter ? `file name ${chalk.gray('**/')}${chalk.yellow(this.#filesFilter)}${chalk.gray('
|
|
206
|
+
${this.#filesFilter ? `file name ${chalk.gray('**/')}${chalk.yellow(this.#filesFilter)}${chalk.gray('*.*')}` : ''}\
|
|
204
207
|
${(this.#testsFilter && this.#filesFilter) ? ', ' : ''}\
|
|
205
208
|
${this.#testsFilter ? `test name ${chalk.yellow(`/${this.#testsFilter}/`)}` : ''}
|
|
206
209
|
`;
|
|
@@ -217,8 +220,7 @@ ${Object.entries(this.#currentCommands)
|
|
|
217
220
|
}
|
|
218
221
|
|
|
219
222
|
async run() {
|
|
220
|
-
await this.#runTests();
|
|
221
|
-
await once(this.#emitter, 'drained');
|
|
223
|
+
await Promise.all([once(this.#emitter, 'drained'), this.#runTests()]);
|
|
222
224
|
this.#emitter.on('drained', () => this.#compactHelp());
|
|
223
225
|
this.#help();
|
|
224
226
|
for await (const data of on(process.stdin, 'data')) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reporters/testwatch",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "An interactive repl for `node:test`",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node:test",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
],
|
|
11
11
|
"bin": "./index.js",
|
|
12
12
|
"scripts": {
|
|
13
|
-
"test": "node --test-reporter=spec --test-reporter-destination=stdout --test-reporter=../github/index.js --test-reporter-destination=stdout --test tests/index.test.js"
|
|
13
|
+
"test": "node --test-reporter=spec --test-reporter-destination=stdout --test-reporter=../github/index.js --test-reporter-destination=stdout --test tests/index.test.js",
|
|
14
|
+
"test:watch": "testwatch tests/index"
|
|
14
15
|
},
|
|
15
16
|
"bugs": {
|
|
16
17
|
"url": "https://github.com/MoLow/reporters/issues"
|
package/tests/index.test.js
CHANGED
|
@@ -35,11 +35,11 @@ Filter Test
|
|
|
35
35
|
pattern › `;
|
|
36
36
|
const filterFilesPrompt = filterTestsPrompt.replace('test', 'file').replace('Test', 'File');
|
|
37
37
|
|
|
38
|
-
async function spawnInteractive(commandSequence = 'q') {
|
|
38
|
+
async function spawnInteractive(commandSequence = 'q', args = []) {
|
|
39
39
|
let stderr = '';
|
|
40
40
|
let stdout = '';
|
|
41
|
-
const child = spawn(process.execPath, ['../../index.js'], {
|
|
42
|
-
env: {
|
|
41
|
+
const child = spawn(process.execPath, ['../../index.js', ...args], {
|
|
42
|
+
env: {}, cwd: path.resolve(__dirname, 'fixtures'),
|
|
43
43
|
});
|
|
44
44
|
child.stdin.setEncoding('utf8');
|
|
45
45
|
let writing = false;
|
|
@@ -62,7 +62,7 @@ async function spawnInteractive(commandSequence = 'q') {
|
|
|
62
62
|
child.stdout.setEncoding('utf8');
|
|
63
63
|
child.stdout.on('data', (data) => {
|
|
64
64
|
stdout += data;
|
|
65
|
-
if (stdout.includes(mainMenu)) {
|
|
65
|
+
if (stdout.includes(mainMenu) || stdout.includes(mainMenuWithFilters)) {
|
|
66
66
|
writeInput();
|
|
67
67
|
}
|
|
68
68
|
});
|
|
@@ -103,7 +103,7 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
|
|
|
103
103
|
});
|
|
104
104
|
it('should exit on sigkill', async () => {
|
|
105
105
|
const child = spawn(process.execPath, ['../../index.js'], {
|
|
106
|
-
env: {
|
|
106
|
+
env: {}, cwd: path.resolve(__dirname, 'fixtures'),
|
|
107
107
|
});
|
|
108
108
|
let stderr = '';
|
|
109
109
|
let stdout = '';
|
|
@@ -155,21 +155,57 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
|
|
|
155
155
|
]);
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
''
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
158
|
+
describe('files filter', () => {
|
|
159
|
+
it('should not exit if no test found on first run', async () => {
|
|
160
|
+
const { outputs, stderr } = await spawnInteractive('q', ['notexist']);
|
|
161
|
+
const activeFilters = '\nActive Filters: file name **/notexist*.*\n';
|
|
162
|
+
const notFound = '\nNo files found for pattern **/notexist*.*';
|
|
163
|
+
assert.strictEqual(stderr, '');
|
|
164
|
+
assert.deepStrictEqual(outputs, [
|
|
165
|
+
'',
|
|
166
|
+
`${notFound}\n${activeFilters}${mainMenuWithFilters}\n`,
|
|
167
|
+
]);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should set first argument as file filter', async () => {
|
|
171
|
+
const { outputs, stderr } = await spawnInteractive('q', ['ind']);
|
|
172
|
+
const activeFilters = '\nActive Filters: file name **/ind*.*\n';
|
|
173
|
+
assert.strictEqual(stderr, '');
|
|
174
|
+
assert.deepStrictEqual(outputs, [
|
|
175
|
+
'',
|
|
176
|
+
`${testsRun[1]}\n${activeFilters}${mainMenuWithFilters}\n`,
|
|
177
|
+
]);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should filter files on "p"', async () => {
|
|
181
|
+
const { outputs, stderr } = await spawnInteractive(['p', 'index', '\r', 'w', 'q'].join(''));
|
|
182
|
+
const activeFilters = '\nActive Filters: file name **/index*.*\n';
|
|
183
|
+
assert.strictEqual(stderr, '');
|
|
184
|
+
assert.deepStrictEqual(outputs, [
|
|
185
|
+
'',
|
|
186
|
+
`${tests}\n${mainMenu}`,
|
|
187
|
+
`${filterFilesPrompt}index`,
|
|
188
|
+
'',
|
|
189
|
+
`${testsRun[1]}\n${compactMenu}\n${clearLines}${activeFilters}${mainMenuWithFilters}\n`,
|
|
190
|
+
]);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should filter partial file names on "p"', async () => {
|
|
194
|
+
const { outputs, stderr } = await spawnInteractive(['p', 'ind', '\r', 'w', 'q'].join(''));
|
|
195
|
+
const activeFilters = '\nActive Filters: file name **/ind*.*\n';
|
|
196
|
+
assert.strictEqual(stderr, '');
|
|
197
|
+
assert.deepStrictEqual(outputs, [
|
|
198
|
+
'',
|
|
199
|
+
`${tests}\n${mainMenu}`,
|
|
200
|
+
`${filterFilesPrompt}ind`,
|
|
201
|
+
'',
|
|
202
|
+
`${testsRun[1]}\n${compactMenu}\n${clearLines}${activeFilters}${mainMenuWithFilters}\n`,
|
|
203
|
+
]);
|
|
204
|
+
});
|
|
169
205
|
});
|
|
170
206
|
it('should filter tests and files togetheer', async () => {
|
|
171
207
|
const { outputs, stderr } = await spawnInteractive(['p', 'index', '\r', 't', 'sum', '\r', 'w', 'q'].join(''));
|
|
172
|
-
const activeFilters = '\nActive Filters: file name **/index
|
|
208
|
+
const activeFilters = '\nActive Filters: file name **/index*.*, test name /sum/\n';
|
|
173
209
|
assert.strictEqual(stderr, '');
|
|
174
210
|
assert.strictEqual(outputs.length, 8);
|
|
175
211
|
assert.strictEqual(outputs[7], `${testsRun[1].replace('✔ index - subtraction (*ms)', '﹣ index - subtraction (*ms) # SKIP')}\n${compactMenu}\n${clearLines}${activeFilters}${mainMenuWithFilters}\n`);
|
|
@@ -177,8 +213,8 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
|
|
|
177
213
|
|
|
178
214
|
it('should mention when no files found', async () => {
|
|
179
215
|
const { outputs, stderr } = await spawnInteractive(['p', 'nothing', '\r', 'w', 'q'].join(''));
|
|
180
|
-
const activeFilters = '\nActive Filters: file name **/nothing
|
|
181
|
-
const notFound = '\nNo files found for pattern **/nothing
|
|
216
|
+
const activeFilters = '\nActive Filters: file name **/nothing*.*\n';
|
|
217
|
+
const notFound = '\nNo files found for pattern **/nothing*.*';
|
|
182
218
|
assert.strictEqual(stderr, '');
|
|
183
219
|
assert.deepStrictEqual(outputs, [
|
|
184
220
|
'',
|
|
@@ -194,16 +230,16 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
|
|
|
194
230
|
assert.strictEqual(stderr, '');
|
|
195
231
|
assert.strictEqual(outputs.length, 9);
|
|
196
232
|
|
|
197
|
-
assert.match(outputs[4], /Active Filters: file name \*\*\/index
|
|
198
|
-
assert.match(outputs[5], /Active Filters: file name \*\*\/index
|
|
199
|
-
assert.match(outputs[7], /Active Filters: file name \*\*\/index
|
|
233
|
+
assert.match(outputs[4], /Active Filters: file name \*\*\/index\*\.\*/);
|
|
234
|
+
assert.match(outputs[5], /Active Filters: file name \*\*\/index\*\.\*/);
|
|
235
|
+
assert.match(outputs[7], /Active Filters: file name \*\*\/index\*\.\*, test name \/sum\//);
|
|
200
236
|
assert.strictEqual(outputs[8], `${tests}\n${compactMenu}\n${clearLines}${mainMenu}\n`);
|
|
201
237
|
});
|
|
202
238
|
|
|
203
239
|
it('prompt ESC should preserve previous state', async () => {
|
|
204
240
|
const { outputs } = await spawnInteractive(['p', esc, 'p', 'filter', '\r', 'p', esc, 'q'].join(''));
|
|
205
|
-
const notFound = '\nNo files found for pattern **/filter
|
|
206
|
-
const activeFilters = '\nActive Filters: file name **/filter
|
|
241
|
+
const notFound = '\nNo files found for pattern **/filter*.*';
|
|
242
|
+
const activeFilters = '\nActive Filters: file name **/filter*.*\n';
|
|
207
243
|
assert.deepStrictEqual(outputs, [
|
|
208
244
|
'',
|
|
209
245
|
`${tests}\n${mainMenu}`,
|
|
@@ -224,7 +260,7 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
|
|
|
224
260
|
const { outputs, stderr } = await spawnInteractive(['p', `noth123${backspace}${backspace}ing`, '\r', 'w', 'q'].join(''));
|
|
225
261
|
assert.strictEqual(stderr, '');
|
|
226
262
|
assert.strictEqual(outputs.length, 5);
|
|
227
|
-
assert.match(outputs[4], /No files found for pattern \*\*\/noth1ing
|
|
263
|
+
assert.match(outputs[4], /No files found for pattern \*\*\/noth1ing\*\.\*/);
|
|
228
264
|
});
|
|
229
265
|
});
|
|
230
266
|
});
|
|
File without changes
|