Просмотр исходного кода

test(ui): pin CRLF source slices to the index line numbering (CG-42)

A CRLF file must come back with the graph's own line numbers and without a
trailing carriage return on every line — the case a Windows checkout with
core.autocrlf produces. It is decided by bytes rather than by the OS, so it
is covered here rather than only on the VM.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Colby McHenry 1 неделя назад
Родитель
Сommit
e7288ffa36
1 измененных файлов с 30 добавлено и 0 удалено
  1. 30 0
      __tests__/ui-server-api.test.ts

+ 30 - 0
__tests__/ui-server-api.test.ts

@@ -192,6 +192,15 @@ ${callers}
 `
   );
 
+  // CRLF on purpose: tree-sitter numbers rows by `\n`, so a CRLF file must come
+  // back with the same line numbers the graph recorded — and without the stray
+  // `\r` rendering at the end of every line. This is what a Windows checkout
+  // with core.autocrlf looks like, and it is decided by bytes, not by the OS.
+  fs.writeFileSync(
+    path.join(srcDir, 'crlf.ts'),
+    ['export function windowsStyle(n: number): number {', '  return n + 1;', '}', ''].join('\r\n')
+  );
+
   fs.writeFileSync(
     path.join(testsDir, 'service.test.ts'),
     `import { Service } from '../src/service';
@@ -613,6 +622,27 @@ describe('GET /api/source', () => {
     expect(body.lines).toHaveLength(2);
   });
 
+  it('keeps a CRLF file on the index line numbering, without the stray carriage returns', async () => {
+    const node = await getJson(`/api/node/${await idOf('windowsStyle', 'function')}`);
+    expect(node.node.file).toBe('src/crlf.ts');
+
+    const body = await getJson('/api/source?file=src/crlf.ts');
+    expect(body.drift).toBe(false);
+    expect(body.totalLines).toBe(3);
+    expect(body.lines).toEqual([
+      'export function windowsStyle(n: number): number {',
+      '  return n + 1;',
+      '}',
+    ]);
+    expect(body.lines.some((l: string) => l.includes('\r'))).toBe(false);
+
+    // The symbol's indexed range still names its own body.
+    const slice = await getJson(
+      `/api/source?file=src/crlf.ts&from=${node.node.line}&to=${node.node.endLine}`
+    );
+    expect(slice.lines[0]).toContain('windowsStyle');
+  });
+
   it('refuses a path that escapes the project', async () => {
     const traversal = await getStatusAndJson(
       '/api/source?file=' + encodeURIComponent('../../../etc/passwd')