cli-truncation.test.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { afterEach, beforeEach, describe, expect, it } from 'vitest';
  2. import { spawnSync } from 'child_process';
  3. import * as fs from 'fs';
  4. import * as os from 'os';
  5. import * as path from 'path';
  6. import { CodeGraph } from '../src';
  7. const BIN = path.resolve(__dirname, '../dist/bin/codegraph.js');
  8. function runCli(cwd: string, args: string[]) {
  9. return spawnSync(process.execPath, [BIN, ...args, '-p', cwd], {
  10. encoding: 'utf-8',
  11. env: { ...process.env, CODEGRAPH_NO_DAEMON: '1', CODEGRAPH_WASM_RELAUNCHED: '1', NO_COLOR: '1' },
  12. });
  13. }
  14. describe('CLI truncation reporting (#1639)', () => {
  15. let tempDir: string;
  16. beforeEach(async () => {
  17. tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-cli-truncation-'));
  18. fs.writeFileSync(
  19. path.join(tempDir, 'lib.ts'),
  20. [
  21. 'export function target() {}',
  22. 'export function helperA() {}',
  23. 'export function helperB() {}',
  24. 'export function helperC() {}',
  25. 'export function source() { helperA(); helperB(); helperC(); }',
  26. 'export function TargetHitOne() {}',
  27. 'export function TargetHitTwo() {}',
  28. 'export function TargetHitThree() {}',
  29. ].join('\n'),
  30. );
  31. for (let i = 0; i < 3; i++) {
  32. fs.writeFileSync(
  33. path.join(tempDir, `caller-${i}.ts`),
  34. `import { target } from './lib';\nexport function caller${i}() { target(); }\n`,
  35. );
  36. }
  37. const cg = CodeGraph.initSync(tempDir);
  38. await cg.indexAll();
  39. cg.close();
  40. });
  41. afterEach(() => {
  42. fs.rmSync(tempDir, { recursive: true, force: true });
  43. });
  44. it('reports exact callers metadata in JSON and human output', () => {
  45. const jsonRun = runCli(tempDir, ['callers', 'target', '--limit', '2', '--json']);
  46. expect(jsonRun.status).toBe(0);
  47. const parsed = JSON.parse(jsonRun.stdout);
  48. expect(parsed.callers).toHaveLength(2);
  49. expect(parsed.total).toBeGreaterThan(2);
  50. expect(parsed.limit).toBe(2);
  51. expect(parsed.truncated).toBe(true);
  52. const humanRun = runCli(tempDir, ['callers', 'target', '--limit', '2']);
  53. expect(humanRun.stdout).toMatch(/Callers of "target" \(2 of \d+\):/);
  54. expect(humanRun.stdout).toMatch(/Showing 2 of \d+; pass --limit to widen\./);
  55. const complete = JSON.parse(runCli(tempDir, ['callers', 'target', '--limit', '100', '--json']).stdout);
  56. expect(complete.total).toBe(complete.callers.length);
  57. expect(complete.limit).toBe(100);
  58. expect(complete.truncated).toBe(false);
  59. });
  60. it('reports exact callees metadata in JSON and human output', () => {
  61. const jsonRun = runCli(tempDir, ['callees', 'source', '--limit', '2', '--json']);
  62. expect(jsonRun.status).toBe(0);
  63. const parsed = JSON.parse(jsonRun.stdout);
  64. expect(parsed.callees).toHaveLength(2);
  65. expect(parsed.total).toBeGreaterThan(2);
  66. expect(parsed.limit).toBe(2);
  67. expect(parsed.truncated).toBe(true);
  68. const humanRun = runCli(tempDir, ['callees', 'source', '--limit', '2']);
  69. expect(humanRun.stdout).toMatch(/Callees of "source" \(2 of \d+\):/);
  70. expect(humanRun.stdout).toMatch(/Showing 2 of \d+; pass --limit to widen\./);
  71. const complete = JSON.parse(runCli(tempDir, ['callees', 'source', '--limit', '100', '--json']).stdout);
  72. expect(complete.total).toBe(complete.callees.length);
  73. expect(complete.limit).toBe(100);
  74. expect(complete.truncated).toBe(false);
  75. });
  76. it('keeps query --json as an array and reports truncation on stderr', () => {
  77. const jsonRun = runCli(tempDir, ['query', 'TargetHit', '--limit', '1', '--json']);
  78. expect(jsonRun.status).toBe(0);
  79. expect(JSON.parse(jsonRun.stdout)).toHaveLength(1);
  80. expect(jsonRun.stderr).toContain('Results truncated at 1; pass --limit to widen.');
  81. const humanRun = runCli(tempDir, ['query', 'TargetHit', '--limit', '1']);
  82. expect(humanRun.stdout).toContain('Results truncated at 1; pass --limit to widen.');
  83. const complete = runCli(tempDir, ['query', 'TargetHit', '--limit', '100', '--json']);
  84. expect(Array.isArray(JSON.parse(complete.stdout))).toBe(true);
  85. expect(complete.stderr).not.toContain('Results truncated');
  86. });
  87. });