@reporters/testwatch 1.1.1 → 1.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.2.1](https://github.com/MoLow/reporters/compare/testwatch-v1.2.0...testwatch-v1.2.1) (2023-07-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * clear screen before tests ([3d3f67c](https://github.com/MoLow/reporters/commit/3d3f67cddd7047c857e001066021933eb1381ec3))
9
+
10
+ ## [1.2.0](https://github.com/MoLow/reporters/compare/testwatch-v1.1.1...testwatch-v1.2.0) (2023-06-19)
11
+
12
+
13
+ ### Features
14
+
15
+ * add test:watch script ([4357fbd](https://github.com/MoLow/reporters/commit/4357fbde5f337cfd39226497f8ce0f6760f8a62c))
16
+ * change default file filter ([5968235](https://github.com/MoLow/reporters/commit/596823529cd9a86e5eeada0523825fa215e49efe))
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * don't exit when no tests on initial run ([66bcc2b](https://github.com/MoLow/reporters/commit/66bcc2bc6436b544900cfbceb4bbfb0d93973490))
22
+
3
23
  ## [1.1.1](https://github.com/MoLow/reporters/compare/testwatch-v1.1.0...testwatch-v1.1.1) (2023-06-12)
4
24
 
5
25
 
package/index.js CHANGED
@@ -39,7 +39,7 @@ process.stdin.setRawMode?.(true);
39
39
  class REPL {
40
40
  #controller = new AbortController();
41
41
 
42
- #filesFilter = '';
42
+ #filesFilter = process.argv[2] || '';
43
43
 
44
44
  #testsFilter = '';
45
45
 
@@ -57,13 +57,13 @@ class REPL {
57
57
  #emitter = new EventEmitter();
58
58
 
59
59
  async #runTests() {
60
+ this.#clear();
60
61
  this.#controller.abort();
61
62
  this.#controller = new AbortController();
62
- const filter = this.#filesFilter ? `**/${this.#filesFilter}*.*` : '**/*.test.js';
63
+ const filter = this.#filesFilter ? `**/${this.#filesFilter}*.*` : '**/?(*.)+(spec|test).[jt]s';
63
64
  const files = await glob(filter, { ignore: 'node_modules/**' });
64
65
 
65
66
  if (!files.length) {
66
- this.#clear();
67
67
  process.stdout.write(chalk.red(`\nNo files found for pattern ${filter}\n`));
68
68
  this.#emitter.emit('drained');
69
69
  return;
@@ -220,8 +220,7 @@ ${Object.entries(this.#currentCommands)
220
220
  }
221
221
 
222
222
  async run() {
223
- await this.#runTests();
224
- await once(this.#emitter, 'drained');
223
+ await Promise.all([once(this.#emitter, 'drained'), this.#runTests()]);
225
224
  this.#emitter.on('drained', () => this.#compactHelp());
226
225
  this.#help();
227
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.1.1",
3
+ "version": "1.2.1",
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"
@@ -0,0 +1,6 @@
1
+ const { test } = require('node:test');
2
+ const assert = require('node:assert');
3
+
4
+ test('should not run', () => {
5
+ assert.strictEqual(1 + 2, 3);
6
+ });
@@ -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: { }, cwd: path.resolve(__dirname, 'fixtures'),
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
  });
@@ -89,21 +89,21 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
89
89
  it('should run all tests on initialization', async () => {
90
90
  const { outputs, stderr } = await spawnInteractive('q');
91
91
  assert.strictEqual(stderr, '');
92
- assert.deepStrictEqual(outputs, ['', `${tests}\n${mainMenu}\n`]);
92
+ assert.deepStrictEqual(outputs, ['', '', `${tests}\n${mainMenu}\n`]);
93
93
  });
94
94
  it('should handle CTR + C', async () => {
95
95
  const { outputs, stderr } = await spawnInteractive('\x03');
96
96
  assert.strictEqual(stderr, '');
97
- assert.deepStrictEqual(outputs, ['', `${tests}\n${mainMenu}\n`]);
97
+ assert.deepStrictEqual(outputs, ['', '', `${tests}\n${mainMenu}\n`]);
98
98
  });
99
99
  it('should handle CTR + D', async () => {
100
100
  const { outputs, stderr } = await spawnInteractive('\x04');
101
101
  assert.strictEqual(stderr, '');
102
- assert.deepStrictEqual(outputs, ['', `${tests}\n${mainMenu}\n`]);
102
+ assert.deepStrictEqual(outputs, ['', '', `${tests}\n${mainMenu}\n`]);
103
103
  });
104
104
  it('should exit on sigkill', async () => {
105
105
  const child = spawn(process.execPath, ['../../index.js'], {
106
- env: { }, cwd: path.resolve(__dirname, 'fixtures'),
106
+ env: {}, cwd: path.resolve(__dirname, 'fixtures'),
107
107
  });
108
108
  let stderr = '';
109
109
  let stdout = '';
@@ -121,19 +121,21 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
121
121
  it('should run all tests on "a"', async () => {
122
122
  const { outputs, stderr } = await spawnInteractive('aq');
123
123
  assert.strictEqual(stderr, '');
124
- assert.deepStrictEqual(outputs, ['', `${tests}\n${mainMenu}`, `${tests}\n${compactMenu}\n`]);
124
+ assert.deepStrictEqual(outputs, ['', '', `${tests}\n${mainMenu}`, '', `${tests}\n${compactMenu}\n`]);
125
125
  });
126
126
  it('should run all tests on Enter', async () => {
127
127
  const { outputs, stderr } = await spawnInteractive('\rq');
128
128
  assert.strictEqual(stderr, '');
129
- assert.deepStrictEqual(outputs, ['', `${tests}\n${mainMenu}`, `${tests}\n${compactMenu}\n`]);
129
+ assert.deepStrictEqual(outputs, ['', '', `${tests}\n${mainMenu}`, '', `${tests}\n${compactMenu}\n`]);
130
130
  });
131
131
  it('should show full menu on "w" after running tests', async () => {
132
132
  const { outputs, stderr } = await spawnInteractive('awq');
133
133
  assert.strictEqual(stderr, '');
134
134
  assert.deepStrictEqual(outputs, [
135
+ '',
135
136
  '',
136
137
  `${tests}\n${mainMenu}`,
138
+ '',
137
139
  `${tests}\n${compactMenu}\n${clearLines}${mainMenu}\n`,
138
140
  ]);
139
141
  });
@@ -144,10 +146,12 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
144
146
  const activeFilters = '\nActive Filters: test name /sub/\n';
145
147
  assert.strictEqual(stderr, '');
146
148
  assert.deepStrictEqual(outputs, [
149
+ '',
147
150
  '',
148
151
  `${tests}\n${mainMenu}`,
149
152
  `${filterTestsPrompt}sub`,
150
153
  '',
154
+ '',
151
155
  `${tests
152
156
  .replace('✔ j - sum (*ms)', '﹣ j - sum (*ms) # SKIP')
153
157
  .replace('✔ index - sum (*ms)', '﹣ index - sum (*ms) # SKIP')
@@ -156,15 +160,39 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
156
160
  });
157
161
 
158
162
  describe('files filter', () => {
163
+ it('should not exit if no test found on first run', async () => {
164
+ const { outputs, stderr } = await spawnInteractive('q', ['notexist']);
165
+ const activeFilters = '\nActive Filters: file name **/notexist*.*\n';
166
+ const notFound = '\nNo files found for pattern **/notexist*.*';
167
+ assert.strictEqual(stderr, '');
168
+ assert.deepStrictEqual(outputs, [
169
+ '',
170
+ `${notFound}\n${activeFilters}${mainMenuWithFilters}\n`,
171
+ ]);
172
+ });
173
+
174
+ it('should set first argument as file filter', async () => {
175
+ const { outputs, stderr } = await spawnInteractive('q', ['ind']);
176
+ const activeFilters = '\nActive Filters: file name **/ind*.*\n';
177
+ assert.strictEqual(stderr, '');
178
+ assert.deepStrictEqual(outputs, [
179
+ '',
180
+ '',
181
+ `${testsRun[1]}\n${activeFilters}${mainMenuWithFilters}\n`,
182
+ ]);
183
+ });
184
+
159
185
  it('should filter files on "p"', async () => {
160
186
  const { outputs, stderr } = await spawnInteractive(['p', 'index', '\r', 'w', 'q'].join(''));
161
187
  const activeFilters = '\nActive Filters: file name **/index*.*\n';
162
188
  assert.strictEqual(stderr, '');
163
189
  assert.deepStrictEqual(outputs, [
190
+ '',
164
191
  '',
165
192
  `${tests}\n${mainMenu}`,
166
193
  `${filterFilesPrompt}index`,
167
194
  '',
195
+ '',
168
196
  `${testsRun[1]}\n${compactMenu}\n${clearLines}${activeFilters}${mainMenuWithFilters}\n`,
169
197
  ]);
170
198
  });
@@ -174,10 +202,12 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
174
202
  const activeFilters = '\nActive Filters: file name **/ind*.*\n';
175
203
  assert.strictEqual(stderr, '');
176
204
  assert.deepStrictEqual(outputs, [
205
+ '',
177
206
  '',
178
207
  `${tests}\n${mainMenu}`,
179
208
  `${filterFilesPrompt}ind`,
180
209
  '',
210
+ '',
181
211
  `${testsRun[1]}\n${compactMenu}\n${clearLines}${activeFilters}${mainMenuWithFilters}\n`,
182
212
  ]);
183
213
  });
@@ -186,8 +216,8 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
186
216
  const { outputs, stderr } = await spawnInteractive(['p', 'index', '\r', 't', 'sum', '\r', 'w', 'q'].join(''));
187
217
  const activeFilters = '\nActive Filters: file name **/index*.*, test name /sum/\n';
188
218
  assert.strictEqual(stderr, '');
189
- assert.strictEqual(outputs.length, 8);
190
- assert.strictEqual(outputs[7], `${testsRun[1].replace('✔ index - subtraction (*ms)', '﹣ index - subtraction (*ms) # SKIP')}\n${compactMenu}\n${clearLines}${activeFilters}${mainMenuWithFilters}\n`);
219
+ assert.strictEqual(outputs.length, 11);
220
+ assert.strictEqual(outputs[10], `${testsRun[1].replace('✔ index - subtraction (*ms)', '﹣ index - subtraction (*ms) # SKIP')}\n${compactMenu}\n${clearLines}${activeFilters}${mainMenuWithFilters}\n`);
191
221
  });
192
222
 
193
223
  it('should mention when no files found', async () => {
@@ -196,6 +226,7 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
196
226
  const notFound = '\nNo files found for pattern **/nothing*.*';
197
227
  assert.strictEqual(stderr, '');
198
228
  assert.deepStrictEqual(outputs, [
229
+ '',
199
230
  '',
200
231
  `${tests}\n${mainMenu}`,
201
232
  `${filterFilesPrompt}nothing`,
@@ -207,12 +238,12 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
207
238
  it('should clear filters on "c"', async () => {
208
239
  const { outputs, stderr } = await spawnInteractive(['p', 'index', '\r', 'w', 't', 'sum', '\r', 'w', 'c', 'w', 'q'].join(''));
209
240
  assert.strictEqual(stderr, '');
210
- assert.strictEqual(outputs.length, 9);
241
+ assert.strictEqual(outputs.length, 13);
211
242
 
212
- assert.match(outputs[4], /Active Filters: file name \*\*\/index\*\.\*/);
213
- assert.match(outputs[5], /Active Filters: file name \*\*\/index\*\.\*/);
214
- assert.match(outputs[7], /Active Filters: file name \*\*\/index\*\.\*, test name \/sum\//);
215
- assert.strictEqual(outputs[8], `${tests}\n${compactMenu}\n${clearLines}${mainMenu}\n`);
243
+ assert.match(outputs[6], /Active Filters: file name \*\*\/index\*\.\*/);
244
+ assert.match(outputs[7], /Active Filters: file name \*\*\/index\*\.\*/);
245
+ assert.match(outputs[10], /Active Filters: file name \*\*\/index\*\.\*, test name \/sum\//);
246
+ assert.strictEqual(outputs[12], `${tests}\n${compactMenu}\n${clearLines}${mainMenu}\n`);
216
247
  });
217
248
 
218
249
  it('prompt ESC should preserve previous state', async () => {
@@ -220,10 +251,12 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
220
251
  const notFound = '\nNo files found for pattern **/filter*.*';
221
252
  const activeFilters = '\nActive Filters: file name **/filter*.*\n';
222
253
  assert.deepStrictEqual(outputs, [
254
+ '',
223
255
  '',
224
256
  `${tests}\n${mainMenu}`,
225
257
  `${filterFilesPrompt}`,
226
258
  '',
259
+ '',
227
260
  `${tests}\n${compactMenu}`,
228
261
  `${filterFilesPrompt}filter`,
229
262
  '',
@@ -234,12 +267,12 @@ describe('testwatch', { concurrency: true, skip: !isSupported ? 'unsupported nod
234
267
  ]);
235
268
  });
236
269
 
237
- it('backspace shoud remove last character', async () => {
270
+ it('backspace should remove last character', async () => {
238
271
  const backspace = '\x7f';
239
272
  const { outputs, stderr } = await spawnInteractive(['p', `noth123${backspace}${backspace}ing`, '\r', 'w', 'q'].join(''));
240
273
  assert.strictEqual(stderr, '');
241
- assert.strictEqual(outputs.length, 5);
242
- assert.match(outputs[4], /No files found for pattern \*\*\/noth1ing\*\.\*/);
274
+ assert.strictEqual(outputs.length, 6);
275
+ assert.match(outputs[5], /No files found for pattern \*\*\/noth1ing\*\.\*/);
243
276
  });
244
277
  });
245
278
  });
File without changes