Skip to content

Commit 442a33a

Browse files
committed
test(frontend): parse mock module calls
Signed-off-by: zebbern <185730623+zebbern@users.noreply.github.com>
1 parent 256c733 commit 442a33a

2 files changed

Lines changed: 58 additions & 2 deletions

File tree

frontend/src/test/run-tests-plan.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ describe('frontend test runner planning', () => {
4848
expect(usesMockModule(plain)).toBe(false);
4949
});
5050

51+
it('ignores mock.module text inside comments and string literals', () => {
52+
tempDir = mkdtempSync(path.join(tmpdir(), 'sentris-test-plan-'));
53+
const file = path.join(tempDir, 'fixture.test.ts');
54+
55+
writeFileSync(
56+
file,
57+
[
58+
'const fixture = "mock.module(\'@/store\', () => ({}));";',
59+
"// mock.module('@/commented', () => ({}));",
60+
].join('\n'),
61+
);
62+
63+
expect(usesMockModule(file)).toBe(false);
64+
});
65+
5166
it('batches adjacent non-mocked files while isolating mock.module files', () => {
5267
const files = [
5368
'src/a.test.ts',

frontend/src/test/run-tests-plan.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { readFileSync, readdirSync } from 'node:fs';
22
import path from 'node:path';
3+
import * as ts from 'typescript';
34

45
const TEST_FILE_PATTERN = /\.(test|spec)\.[jt]sx?$/;
5-
const MOCK_MODULE_PATTERN = /\bmock\.module\s*\(/;
66

77
export interface FrontendTestRun {
88
label: string;
@@ -36,8 +36,49 @@ export function toPosixRelative(filePath: string, cwd = process.cwd()): string {
3636
return path.relative(cwd, filePath).split(path.sep).join(path.posix.sep);
3737
}
3838

39+
function getScriptKind(filePath: string): ts.ScriptKind {
40+
switch (path.extname(filePath).toLowerCase()) {
41+
case '.tsx':
42+
return ts.ScriptKind.TSX;
43+
case '.jsx':
44+
return ts.ScriptKind.JSX;
45+
case '.js':
46+
return ts.ScriptKind.JS;
47+
default:
48+
return ts.ScriptKind.TS;
49+
}
50+
}
51+
3952
export function usesMockModule(filePath: string): boolean {
40-
return MOCK_MODULE_PATTERN.test(readFileSync(filePath, 'utf8'));
53+
const sourceFile = ts.createSourceFile(
54+
filePath,
55+
readFileSync(filePath, 'utf8'),
56+
ts.ScriptTarget.Latest,
57+
false,
58+
getScriptKind(filePath),
59+
);
60+
61+
let found = false;
62+
63+
const visit = (node: ts.Node): void => {
64+
if (found) return;
65+
66+
if (
67+
ts.isCallExpression(node) &&
68+
ts.isPropertyAccessExpression(node.expression) &&
69+
ts.isIdentifier(node.expression.expression) &&
70+
node.expression.expression.text === 'mock' &&
71+
node.expression.name.text === 'module'
72+
) {
73+
found = true;
74+
return;
75+
}
76+
77+
ts.forEachChild(node, visit);
78+
};
79+
80+
visit(sourceFile);
81+
return found;
4182
}
4283

4384
export function planFrontendTestRuns(

0 commit comments

Comments
 (0)