test(cross-file): verify live progress events are emitted with N/M format

Finding 2: frozen progress display was fixed by emitting onProgress every 25 files
with "Cross-file type propagation (N/M files)..." messages instead of calling it
once at phase start. This test verifies the fix with 50 candidate files: expects
onProgress called 3 times (1 initial + at 25 + at 50) with correct N/M counters.

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/3ab768d9-3993-4882-9d8f-17f7fcbd086e

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-05-16 08:37:14 +00:00 • committed by GitHub
parent cb9201d235
commit 0920628b7d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -210,6 +210,55 @@ describe('runCrossFileBindingPropagation', () => {
expect(caches[2]).toBe(caches[0]);
});
it('emits live onProgress events every 25 files with N/M format', async () => {
// Verifies that the frozen-progress-display fix is correctly wired:
// onProgress must be called multiple times from the processing loop,
// not just once at phase start, so large repos show real movement in
// the UI instead of a frozen percentage bar.
const graph = createKnowledgeGraph();
const ctx = createResolutionContext();
const exportedTypeMap: ExportedTypeMap = new Map([
['upstream.ts', new Map([['User', 'User']])],
]);
ctx.importMap.set('upstream.ts', new Set());
const allPaths = ['upstream.ts'];
for (let i = 0; i < 50; i++) {
const file = `downstream${i}.ts`;
allPaths.push(file);
const bindings = new Map();
bindings.set('User', { sourcePath: 'upstream.ts', exportedName: 'User' });
ctx.namedImportMap.set(file, bindings);
ctx.importMap.set(file, new Set(['upstream.ts']));
}
const progressMessages: string[] = [];
const onProgress = vi.fn((p: { phase: string; percent: number; message: string }) => {
progressMessages.push(p.message);
});
await runCrossFileBindingPropagation(
graph,
ctx,
exportedTypeMap,
new Set(allPaths),
allPaths.length,
'/repo',
Date.now(),
onProgress,
);
// 1 initial call at phase start + 2 loop calls (at 25 and 50 files).
expect(onProgress).toHaveBeenCalledTimes(3);
// Loop messages must carry the "N/M files" format so the UI is informative.
const loopMessages = progressMessages.filter((m) => m.match(/\(\d+\/\d+ files\)/));
expect(loopMessages).toHaveLength(2);
expect(loopMessages[0]).toContain('(25/50 files)');
expect(loopMessages[1]).toContain('(50/50 files)');
});
it('caps processing at MAX_CROSS_FILE_REPROCESS (2000)', async () => {
const graph = createKnowledgeGraph();
const ctx = createResolutionContext();