Skip to content

Commit 87c2473

Browse files
mizdraclaude
andauthored
test(ts-plugin): move named exports tests into per-feature test files (#359)
* test: fix test case names * test(ts-plugin): move named exports tests into per-feature test files Previously, named exports tests were consolidated in a single file (named-exports.test.ts) with only limited coverage. This commit moves those tests into the corresponding per-feature test files (code-fix, completion, find-all-references, go-to-definition) and adds test cases for behaviors that differ between named exports and default exports. Note: not all feature test files received named exports test cases — only features with code paths or behaviors that differ between the two export modes were updated. Features that share the same code path or are already sufficiently covered by other tests were left unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7ae3ebc commit 87c2473

6 files changed

Lines changed: 944 additions & 1170 deletions

File tree

packages/ts-plugin/e2e-test/feature/code-fix.test.ts

Lines changed: 222 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,184 @@ import {
88
import { createIFF } from '../test-util/fixture.js';
99
import { formatPath, launchTsserver, normalizeCodeFixActions } from '../test-util/tsserver.js';
1010

11-
describe('Get Code Fixes', async () => {
11+
test.each([
12+
{
13+
namedExports: false,
14+
importStatement: "import styles from './a.module.css';",
15+
},
16+
{
17+
namedExports: true,
18+
importStatement: "import * as styles from './a.module.css';",
19+
},
20+
])(
21+
'fixMissingCSSRule inserts a new CSS rule for a missing class property (namedExports: $namedExports)',
22+
async ({ namedExports, importStatement }) => {
23+
const tsserver = launchTsserver();
24+
const iff = await createIFF({
25+
'a.tsx': dedent`
26+
${importStatement}
27+
import bStyles from './b.module.css';
28+
styles.a_1;
29+
bStyles.b_2;
30+
`,
31+
'a.module.css': '',
32+
'b.module.css': dedent`
33+
.b_1 {
34+
color: red;
35+
}
36+
`,
37+
'tsconfig.json': dedent`
38+
{
39+
"cmkOptions": {
40+
"enabled": true,
41+
"namedExports": ${namedExports}
42+
}
43+
}
44+
`,
45+
});
46+
await tsserver.sendUpdateOpen({
47+
openFiles: [{ file: iff.paths['tsconfig.json'] }],
48+
});
49+
50+
const res1 = await tsserver.sendGetCodeFixes({
51+
errorCodes: [PROPERTY_DOES_NOT_EXIST_ERROR_CODES[0]],
52+
file: iff.paths['a.tsx'],
53+
startLine: 3,
54+
startOffset: 11,
55+
endLine: 3,
56+
endOffset: 11,
57+
});
58+
expect(normalizeCodeFixActions(res1.body!)).toStrictEqual(
59+
normalizeCodeFixActions([
60+
{
61+
fixName: 'fixMissingCSSRule',
62+
changes: [
63+
{
64+
fileName: formatPath(iff.paths['a.module.css']),
65+
textChanges: [{ start: { line: 1, offset: 1 }, end: { line: 1, offset: 1 }, newText: '\n.a_1 {\n \n}' }],
66+
},
67+
],
68+
},
69+
]),
70+
);
71+
72+
const res2 = await tsserver.sendGetCodeFixes({
73+
errorCodes: [PROPERTY_DOES_NOT_EXIST_ERROR_CODES[1]],
74+
file: iff.paths['a.tsx'],
75+
startLine: 3,
76+
startOffset: 11,
77+
endLine: 3,
78+
endOffset: 11,
79+
});
80+
expect(normalizeCodeFixActions(res2.body!)).toStrictEqual(
81+
normalizeCodeFixActions([
82+
{
83+
fixName: 'fixMissingCSSRule',
84+
changes: [
85+
{
86+
fileName: formatPath(iff.paths['a.module.css']),
87+
textChanges: [{ start: { line: 1, offset: 1 }, end: { line: 1, offset: 1 }, newText: '\n.a_1 {\n \n}' }],
88+
},
89+
],
90+
},
91+
]),
92+
);
93+
94+
const res3 = await tsserver.sendGetCodeFixes({
95+
errorCodes: [PROPERTY_DOES_NOT_EXIST_ERROR_CODES[0]],
96+
file: iff.paths['a.tsx'],
97+
startLine: 4,
98+
startOffset: 12,
99+
endLine: 4,
100+
endOffset: 12,
101+
});
102+
expect(normalizeCodeFixActions(res3.body!)).toStrictEqual(
103+
normalizeCodeFixActions([
104+
{
105+
fixName: 'fixMissingCSSRule',
106+
changes: [
107+
{
108+
fileName: formatPath(iff.paths['b.module.css']),
109+
textChanges: [{ start: { line: 3, offset: 2 }, end: { line: 3, offset: 2 }, newText: '\n.b_2 {\n \n}' }],
110+
},
111+
],
112+
},
113+
]),
114+
);
115+
},
116+
);
117+
118+
test.each([
119+
{
120+
name: 'auto-import inserts default import statement if namedExports is false',
121+
namedExports: false,
122+
importStatement: `import styles from "./a.module.css";`,
123+
},
124+
{
125+
name: 'auto-import inserts namespace import statement if namedExports is true',
126+
namedExports: true,
127+
importStatement: `import * as styles from "./a.module.css";`,
128+
},
129+
])('$name', async ({ namedExports, importStatement }) => {
12130
const tsserver = launchTsserver();
13131
const iff = await createIFF({
14-
'a.tsx': dedent`
15-
import styles from './a.module.css';
16-
import bStyles from './b.module.css';
17-
styles.a_1;
18-
bStyles.b_2;
19-
`,
20-
'b.tsx': dedent`
132+
'index.ts': dedent`
21133
styles;
22134
`,
23135
'a.module.css': '',
24-
'b.module.css': dedent`
25-
.b_1 {
26-
color: red;
136+
'tsconfig.json': dedent`
137+
{
138+
"cmkOptions": {
139+
"enabled": true,
140+
"namedExports": ${namedExports}
141+
}
27142
}
28143
`,
29-
// Generated files should be excluded from completion candidates.
30-
'generated/generated.module.css.d.ts': dedent`
144+
});
145+
await tsserver.sendUpdateOpen({
146+
openFiles: [{ file: iff.paths['tsconfig.json'] }],
147+
});
148+
const res = await tsserver.sendGetCodeFixes({
149+
errorCodes: [CANNOT_FIND_NAME_ERROR_CODE],
150+
file: iff.paths['index.ts'],
151+
startLine: 1,
152+
startOffset: 1,
153+
endLine: 1,
154+
endOffset: 7,
155+
});
156+
expect(normalizeCodeFixActions(res.body!)).toStrictEqual(
157+
normalizeCodeFixActions([
158+
{
159+
fixName: 'import',
160+
changes: [
161+
{
162+
fileName: formatPath(iff.paths['index.ts']),
163+
textChanges: [
164+
{
165+
start: { line: 1, offset: 1 },
166+
end: { line: 1, offset: 1 },
167+
newText: `${importStatement}${ts.sys.newLine}${ts.sys.newLine}`,
168+
},
169+
],
170+
},
171+
],
172+
},
173+
]),
174+
);
175+
});
176+
177+
test('auto-import excludes generated files from suggestions', async () => {
178+
const tsserver = launchTsserver();
179+
const iff = await createIFF({
180+
'index.ts': dedent`
181+
styles;
182+
`,
183+
'generated/a.module.css.d.ts': dedent`
31184
const styles: {};
32185
export default styles;
33186
`,
34187
'tsconfig.json': dedent`
35188
{
36-
"compilerOptions": {},
37189
"cmkOptions": {
38190
"enabled": true,
39191
"dtsOutDir": "generated"
@@ -44,108 +196,83 @@ describe('Get Code Fixes', async () => {
44196
await tsserver.sendUpdateOpen({
45197
openFiles: [{ file: iff.paths['tsconfig.json'] }],
46198
});
199+
const res = await tsserver.sendGetCodeFixes({
200+
errorCodes: [CANNOT_FIND_NAME_ERROR_CODE],
201+
file: iff.paths['index.ts'],
202+
startLine: 1,
203+
startOffset: 1,
204+
endLine: 1,
205+
endOffset: 7,
206+
});
207+
expect(normalizeCodeFixActions(res.body!)).toStrictEqual([]);
208+
});
209+
210+
describe('auto-import suggests named exports instead of namespace import when prioritizeNamedImports is true', async () => {
211+
const tsserver = launchTsserver();
212+
const iff = await createIFF({
213+
'index.ts': dedent`
214+
styles;
215+
a_1;
216+
`,
217+
'a.module.css': dedent`
218+
.a_1 { color: red; }
219+
`,
220+
'tsconfig.json': dedent`
221+
{
222+
"cmkOptions": {
223+
"enabled": true,
224+
"namedExports": true,
225+
"prioritizeNamedImports": true
226+
}
227+
}
228+
`,
229+
});
230+
await tsserver.sendUpdateOpen({
231+
openFiles: [{ file: iff.paths['tsconfig.json'] }],
232+
});
47233
test.each([
48234
{
49235
name: 'styles',
50-
file: iff.paths['b.tsx'],
51-
line: 1,
52-
offset: 1,
53-
errorCodes: [CANNOT_FIND_NAME_ERROR_CODE],
236+
file: iff.paths['index.ts'],
237+
startLine: 1,
238+
startOffset: 1,
239+
endLine: 1,
240+
endOffset: 7,
241+
expected: [],
242+
},
243+
{
244+
name: 'a_1',
245+
file: iff.paths['index.ts'],
246+
startLine: 2,
247+
startOffset: 1,
248+
endLine: 2,
249+
endOffset: 4,
54250
expected: [
55251
{
56252
fixName: 'import',
57253
changes: [
58254
{
59-
fileName: formatPath(iff.paths['b.tsx']),
60-
textChanges: [
61-
{
62-
start: { line: 1, offset: 1 },
63-
end: { line: 1, offset: 1 },
64-
newText: `import styles from "./a.module.css";${ts.sys.newLine}${ts.sys.newLine}`,
65-
},
66-
],
67-
},
68-
],
69-
},
70-
{
71-
fixName: 'import',
72-
changes: [
73-
{
74-
fileName: formatPath(iff.paths['b.tsx']),
255+
fileName: formatPath(iff.paths['index.ts']),
75256
textChanges: [
76257
{
77258
start: { line: 1, offset: 1 },
78259
end: { line: 1, offset: 1 },
79-
newText: `import styles from "./b.module.css";${ts.sys.newLine}${ts.sys.newLine}`,
260+
newText: `import { a_1 } from "./a.module.css";${ts.sys.newLine}${ts.sys.newLine}`,
80261
},
81262
],
82263
},
83264
],
84265
},
85266
],
86267
},
87-
{
88-
name: 'styles.a_1',
89-
file: iff.paths['a.tsx'],
90-
line: 3,
91-
offset: 11,
92-
errorCodes: [PROPERTY_DOES_NOT_EXIST_ERROR_CODES[0]],
93-
expected: [
94-
{
95-
fixName: 'fixMissingCSSRule',
96-
changes: [
97-
{
98-
fileName: formatPath(iff.paths['a.module.css']),
99-
textChanges: [{ start: { line: 1, offset: 1 }, end: { line: 1, offset: 1 }, newText: '\n.a_1 {\n \n}' }],
100-
},
101-
],
102-
},
103-
],
104-
},
105-
{
106-
name: 'styles.a_1',
107-
file: iff.paths['a.tsx'],
108-
line: 3,
109-
offset: 11,
110-
errorCodes: [PROPERTY_DOES_NOT_EXIST_ERROR_CODES[1]],
111-
expected: [
112-
{
113-
fixName: 'fixMissingCSSRule',
114-
changes: [
115-
{
116-
fileName: formatPath(iff.paths['a.module.css']),
117-
textChanges: [{ start: { line: 1, offset: 1 }, end: { line: 1, offset: 1 }, newText: '\n.a_1 {\n \n}' }],
118-
},
119-
],
120-
},
121-
],
122-
},
123-
{
124-
name: 'bStyles.b_2',
125-
file: iff.paths['a.tsx'],
126-
line: 4,
127-
offset: 12,
128-
errorCodes: [PROPERTY_DOES_NOT_EXIST_ERROR_CODES[0]],
129-
expected: [
130-
{
131-
fixName: 'fixMissingCSSRule',
132-
changes: [
133-
{
134-
fileName: formatPath(iff.paths['b.module.css']),
135-
textChanges: [{ start: { line: 3, offset: 2 }, end: { line: 3, offset: 2 }, newText: '\n.b_2 {\n \n}' }],
136-
},
137-
],
138-
},
139-
],
140-
},
141-
])('$name', async ({ file, line, offset, errorCodes, expected }) => {
268+
])('$name', async ({ file, startLine, startOffset, endLine, endOffset, expected }) => {
142269
const res = await tsserver.sendGetCodeFixes({
143-
errorCodes,
270+
errorCodes: [2304],
144271
file,
145-
startLine: line,
146-
startOffset: offset,
147-
endLine: line,
148-
endOffset: offset,
272+
startLine,
273+
startOffset,
274+
endLine,
275+
endOffset,
149276
});
150277
expect(normalizeCodeFixActions(res.body!)).toStrictEqual(normalizeCodeFixActions(expected));
151278
});

0 commit comments

Comments
 (0)