Skip to content

Commit 11570e1

Browse files
committed
[compiler][snap] Support pattern of files to test as CLI argument
Vibe-coded. When trying to use vibe coding on actual compiler work, the agent kept wanting to do `yarn snap <test>` to get the output of a file. It was tedious to tell it to use the testfilter file. This lets us quickly run a set of files or a specific path and get debug output. Open to feedback!
1 parent 189efa4 commit 11570e1

File tree

1 file changed

+71
-3
lines changed

1 file changed

+71
-3
lines changed

compiler/packages/snap/src/runner.ts

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import * as readline from 'readline';
1212
import ts from 'typescript';
1313
import yargs from 'yargs';
1414
import {hideBin} from 'yargs/helpers';
15-
import {FILTER_PATH, PROJECT_ROOT} from './constants';
15+
import {FILTER_PATH, FIXTURES_PATH, PROJECT_ROOT} from './constants';
1616
import {TestFilter, getFixtures, readTestFilter} from './fixture-utils';
1717
import {TestResult, TestResults, report, update} from './reporter';
1818
import {
@@ -23,6 +23,7 @@ import {
2323
} from './runner-watch';
2424
import * as runnerWorker from './runner-worker';
2525
import {execSync} from 'child_process';
26+
import * as glob from 'glob';
2627

2728
const WORKER_PATH = require.resolve('./runner-worker.js');
2829
const NUM_WORKERS = cpus().length - 1;
@@ -35,9 +36,17 @@ type RunnerOptions = {
3536
watch: boolean;
3637
filter: boolean;
3738
update: boolean;
39+
pattern?: string;
3840
};
3941

4042
const opts: RunnerOptions = yargs
43+
.command('$0 [pattern]', 'Run snapshot tests', yargs => {
44+
yargs.positional('pattern', {
45+
type: 'string',
46+
describe:
47+
'Optional glob pattern to filter fixtures (e.g., "error.*", "use-memo")',
48+
});
49+
})
4150
.boolean('sync')
4251
.describe(
4352
'sync',
@@ -66,6 +75,54 @@ const opts: RunnerOptions = yargs
6675
.strict()
6776
.parseSync(hideBin(process.argv));
6877

78+
/**
79+
* Create a TestFilter from a glob pattern
80+
*/
81+
async function createPatternFilter(pattern: string): Promise<TestFilter> {
82+
// The pattern works against the base fixture path (without extensions)
83+
// We need to append extensions to find the actual files, similar to how
84+
// readInputFixtures works in fixture-utils.ts
85+
const INPUT_EXTENSIONS = [
86+
'.js',
87+
'.cjs',
88+
'.mjs',
89+
'.ts',
90+
'.cts',
91+
'.mts',
92+
'.jsx',
93+
'.tsx',
94+
];
95+
const SNAPSHOT_EXTENSION = '.expect.md';
96+
97+
// Try to match both input files and snapshot files
98+
const [inputMatches, snapshotMatches] = await Promise.all([
99+
glob.glob(`${pattern}{${INPUT_EXTENSIONS.join(',')}}`, {
100+
cwd: FIXTURES_PATH,
101+
}),
102+
glob.glob(`${pattern}${SNAPSHOT_EXTENSION}`, {cwd: FIXTURES_PATH}),
103+
]);
104+
105+
// Remove file extensions to get the base paths
106+
const allMatches = [...inputMatches, ...snapshotMatches];
107+
const paths = allMatches.map((match: string) => {
108+
// Remove common test file extensions
109+
return match
110+
.replace(/\.(js|jsx|ts|tsx|mjs|cjs|mts|cts)$/, '')
111+
.replace(/\.expect\.md$/, '');
112+
});
113+
114+
// Deduplicate paths
115+
const uniquePaths = Array.from(new Set(paths)) as string[];
116+
117+
// Enable debug if there's only one unique match
118+
const debug = uniquePaths.length === 1;
119+
120+
return {
121+
debug,
122+
paths: uniquePaths,
123+
};
124+
}
125+
69126
/**
70127
* Do a test run and return the test results
71128
*/
@@ -171,7 +228,10 @@ export async function main(opts: RunnerOptions): Promise<void> {
171228
worker.getStderr().pipe(process.stderr);
172229
worker.getStdout().pipe(process.stdout);
173230

174-
if (opts.watch) {
231+
// If pattern is provided, force watch mode off and use pattern filter
232+
const shouldWatch = opts.pattern ? false : opts.watch;
233+
234+
if (shouldWatch) {
175235
makeWatchRunner(state => onChange(worker, state), opts.filter);
176236
if (opts.filter) {
177237
/**
@@ -216,7 +276,15 @@ export async function main(opts: RunnerOptions): Promise<void> {
216276
try {
217277
execSync('yarn build', {cwd: PROJECT_ROOT});
218278
console.log('Built compiler successfully with tsup');
219-
const testFilter = opts.filter ? await readTestFilter() : null;
279+
280+
// Determine which filter to use
281+
let testFilter: TestFilter | null = null;
282+
if (opts.pattern) {
283+
testFilter = await createPatternFilter(opts.pattern);
284+
} else if (opts.filter) {
285+
testFilter = await readTestFilter();
286+
}
287+
220288
const results = await runFixtures(worker, testFilter, 0);
221289
if (opts.update) {
222290
update(results);

0 commit comments

Comments
 (0)