|
1 | 1 | import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; |
2 | 2 | import { tmpdir } from 'node:os'; |
3 | 3 | import path from 'node:path'; |
4 | | -import { Project } from 'ts-morph'; |
5 | 4 | import { afterEach, describe, expect, it } from 'vitest'; |
6 | 5 |
|
7 | 6 | import { getMigration } from '../src/migrations/index.js'; |
8 | 7 | import { run } from '../src/runner.js'; |
9 | | -import type { FileResult } from '../src/types.js'; |
10 | 8 | import { CODEMOD_ERROR_PREFIX } from '../src/utils/diagnostics.js'; |
11 | 9 |
|
12 | 10 | const migration = getMigration('v1-to-v2')!; |
@@ -189,33 +187,40 @@ describe('comment insertion', () => { |
189 | 187 | }); |
190 | 188 |
|
191 | 189 | it('merges same-line diagnostics into a single comment', () => { |
192 | | - // Test the merge logic directly with synthetic data via the Project API. |
193 | | - // Two diagnostics on the same line should produce one comment with joined messages. |
194 | | - const project = new Project({ useInMemoryFileSystem: true }); |
195 | | - const sf = project.createSourceFile('test.ts', 'const a = 1;\nconst b = 2;\n'); |
196 | | - |
197 | | - const fileResults: FileResult[] = [ |
198 | | - { |
199 | | - filePath: sf.getFilePath(), |
200 | | - changes: 0, |
201 | | - diagnostics: [ |
202 | | - { level: 'warning' as never, file: sf.getFilePath(), line: 2, message: 'First issue', insertComment: true }, |
203 | | - { level: 'warning' as never, file: sf.getFilePath(), line: 2, message: 'Second issue', insertComment: true } |
204 | | - ] |
205 | | - } |
206 | | - ]; |
207 | | - |
208 | | - // Import and call insertDiagnosticComments indirectly by checking the runner behavior. |
209 | | - // Since insertDiagnosticComments is not exported, we verify via integration: |
210 | | - // construct a scenario that produces two diagnostics for the same node. |
211 | | - // Instead, we verify the output format by checking the source file directly. |
212 | | - // For a true unit test, we'd need to export the function. For now, verify the |
213 | | - // merge behavior via the runner with a crafted input. |
214 | | - |
215 | | - // Actually, we can use a file that triggers two actionRequired diagnostics on the same line. |
216 | | - // This is hard to construct naturally, so we test the runner output instead. |
217 | | - // The key invariant is: if we ever get same-line diagnostics, only one comment appears. |
218 | | - // The earlier tests already cover the single-comment case. This test documents the intent. |
219 | | - expect(fileResults[0]!.diagnostics.filter(d => d.line === 2).length).toBe(2); |
| 190 | + const dir = createTempDir(); |
| 191 | + const input = [ |
| 192 | + `import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';`, |
| 193 | + `const a = CallToolRequestSchema.parse(data1); const b = ListToolsRequestSchema.parse(data2);`, |
| 194 | + `` |
| 195 | + ].join('\n'); |
| 196 | + writeFileSync(path.join(dir, 'server.ts'), input); |
| 197 | + |
| 198 | + const result = run(migration, { targetDir: dir }); |
| 199 | + |
| 200 | + const output = readFileSync(path.join(dir, 'server.ts'), 'utf8'); |
| 201 | + const commentLines = output.split('\n').filter(l => l.includes(CODEMOD_ERROR_PREFIX)); |
| 202 | + expect(commentLines.length).toBe(1); |
| 203 | + expect(commentLines[0]).toContain(' | '); |
| 204 | + expect(result.commentCount).toBe(1); |
| 205 | + }); |
| 206 | + |
| 207 | + it('handles CRLF line endings without corrupting the file', () => { |
| 208 | + const dir = createTempDir(); |
| 209 | + const input = [ |
| 210 | + `import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';`, |
| 211 | + `const a = CallToolRequestSchema.parse(data);`, |
| 212 | + `` |
| 213 | + ].join('\r\n'); |
| 214 | + writeFileSync(path.join(dir, 'server.ts'), input); |
| 215 | + |
| 216 | + run(migration, { targetDir: dir }); |
| 217 | + |
| 218 | + const output = readFileSync(path.join(dir, 'server.ts'), 'utf8'); |
| 219 | + expect(output).toContain(CODEMOD_ERROR_PREFIX); |
| 220 | + const lines = output.split(/\r?\n/); |
| 221 | + const commentIdx = lines.findIndex(l => l.includes(CODEMOD_ERROR_PREFIX)); |
| 222 | + expect(commentIdx).toBeGreaterThan(-1); |
| 223 | + expect(lines[commentIdx]!.trim()).toMatch(/^\/\*.*\*\/$/); |
| 224 | + expect(lines[commentIdx + 1]).toContain('.parse(data)'); |
220 | 225 | }); |
221 | 226 | }); |
0 commit comments