Skip to content

Commit dfda0f2

Browse files
bitpshraduh95
authored andcommitted
test_runner: restore directory search for --test
Passing a directory to `node --test` (e.g. `node --test tests`) matched the directory itself as a glob pattern and then tried to run it as a test file, failing with MODULE_NOT_FOUND. Before glob patterns were supported, a directory argument was searched for test files within it. Expand a pattern that resolves to a directory into a search for the default test files inside it. Despite the report framing this as Windows-only, it reproduces on every platform: it is a plain regression from when directory arguments stopped being searched. Fixes: #64555 Signed-off-by: Paul Bouchon <mail@bitpshr.net> PR-URL: #64637 Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent 6c2d9a8 commit dfda0f2

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

lib/internal/test_runner/runner.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const {
1919
ObjectAssign,
2020
PromisePrototypeThen,
2121
PromiseWithResolvers,
22+
RegExpPrototypeSymbolReplace,
2223
SafeMap,
2324
SafePromiseAll,
2425
SafePromiseAllReturnVoid,
@@ -35,6 +36,7 @@ const {
3536
} = primordials;
3637

3738
const { spawn } = require('child_process');
39+
const { statSync } = require('fs');
3840
const { finished } = require('internal/streams/end-of-stream');
3941
const { availableParallelism } = require('os');
4042
const { resolve, sep, isAbsolute } = require('path');
@@ -154,6 +156,23 @@ function createTestFileList(patterns, cwd) {
154156
const hasUserSuppliedPattern = patterns != null;
155157
if (!patterns || patterns.length === 0) {
156158
patterns = [kDefaultPattern];
159+
} else {
160+
patterns = ArrayPrototypeMap(patterns, (pattern) => {
161+
// A directory argument is expanded to search for the default test files
162+
// within it, matching the behavior from before glob patterns were
163+
// supported. Glob patterns always use forward slashes, so a trailing
164+
// path separator (of either kind) is stripped before appending.
165+
const resolved = isAbsolute(pattern) ? pattern : resolve(cwd, pattern);
166+
try {
167+
if (statSync(resolved).isDirectory()) {
168+
return `${RegExpPrototypeSymbolReplace(/[\\/]+$/, pattern, '')}/${kDefaultPattern}`;
169+
}
170+
} catch {
171+
// Not a directory or not accessible; leave the pattern as-is so the
172+
// existing "Could not find" handling still applies.
173+
}
174+
return pattern;
175+
});
157176
}
158177
const glob = new Glob(patterns, {
159178
__proto__: null,

test/parallel/test-runner-cli.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,27 @@ for (const isolation of ['none', 'process']) {
6262
assert.doesNotMatch(stdout, /ok 4 - this should pass/);
6363
}
6464

65+
{
66+
// A directory argument is searched for the default test files within it,
67+
// both bare and with a trailing separator.
68+
// Refs: https://github.com/nodejs/node/issues/64555
69+
for (const dir of ['matching-patterns', 'matching-patterns/']) {
70+
const args = ['--test', '--test-reporter=tap',
71+
'--no-experimental-strip-types',
72+
`--test-isolation=${isolation}`, dir];
73+
const child = spawnSync(process.execPath, args, { cwd: testFixtures });
74+
75+
assert.strictEqual(child.status, 0);
76+
assert.strictEqual(child.signal, null);
77+
assert.strictEqual(child.stderr.toString(), '');
78+
const stdout = child.stdout.toString();
79+
80+
assert.match(stdout, /ok 1 - this should pass/);
81+
assert.match(stdout, /ok 2 - this should pass/);
82+
assert.match(stdout, /ok 3 - this should pass/);
83+
}
84+
}
85+
6586
{
6687
// Should match files with "-test.(c|m)(t|j)s" suffix when typescript support is enabled
6788
const args = ['--test', '--test-reporter=tap', '--no-warnings',

0 commit comments

Comments
 (0)