diff --git a/apps/penpal/frontend/src/pages/FilePage.test.tsx b/apps/penpal/frontend/src/pages/FilePage.test.tsx index 0dfe82b9..d863d823 100644 --- a/apps/penpal/frontend/src/pages/FilePage.test.tsx +++ b/apps/penpal/frontend/src/pages/FilePage.test.tsx @@ -150,7 +150,7 @@ describe('FilePage', () => { expect(api.startAgent).not.toHaveBeenCalled(); }); - it('refreshes agent status and threads on SSE reconnect', async () => { + it('refreshes content, agent status, and threads on SSE reconnect', async () => { vi.mocked(api.getAgentStatus).mockResolvedValue(agentNotRunning); renderFilePage(); @@ -159,6 +159,7 @@ describe('FilePage', () => { await waitFor(() => { expect(api.getAgentStatus).toHaveBeenCalledTimes(1); expect(api.getThreads).toHaveBeenCalledTimes(1); + expect(api.getRawFile).toHaveBeenCalledTimes(1); }); // Get the onReconnect callback (2nd argument to useSSE) @@ -169,13 +170,41 @@ describe('FilePage', () => { // Simulate SSE reconnect vi.mocked(api.getAgentStatus).mockClear(); vi.mocked(api.getThreads).mockClear(); + vi.mocked(api.getRawFile).mockClear(); act(() => { onReconnect!(); }); await waitFor(() => { + expect(api.getRawFile).toHaveBeenCalledTimes(1); expect(api.getAgentStatus).toHaveBeenCalledTimes(1); expect(api.getThreads).toHaveBeenCalledTimes(1); }); }); + + it('refreshes content on SSE files event', async () => { + vi.mocked(api.getAgentStatus).mockResolvedValue(agentNotRunning); + + renderFilePage(); + + // Wait for initial load + await waitFor(() => { + expect(api.getRawFile).toHaveBeenCalledTimes(1); + }); + + // Get the onEvent callback (1st argument to useSSE) + const useSSEMock = vi.mocked(useSSE); + const onEvent = useSSEMock.mock.calls[0]?.[0]; + expect(onEvent).toBeDefined(); + + // Simulate a 'files' SSE event for our project + vi.mocked(api.getRawFile).mockClear(); + act(() => { + onEvent!({ type: 'files', project: 'ws/proj' }); + }); + + await waitFor(() => { + expect(api.getRawFile).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/apps/penpal/frontend/src/pages/FilePage.tsx b/apps/penpal/frontend/src/pages/FilePage.tsx index 5ef64bea..59a92242 100644 --- a/apps/penpal/frontend/src/pages/FilePage.tsx +++ b/apps/penpal/frontend/src/pages/FilePage.tsx @@ -122,14 +122,16 @@ export default function FilePage() { }, [location.pathname, projects]); // Fetch raw file content - const fetchContent = useCallback(async () => { + const fetchContent = useCallback(async (opts?: { silent?: boolean }) => { if (!project || !path) return; try { const content = await api.getRawFile(project, path); setRawMarkdown(content); setError(null); } catch (err) { - setError('Failed to load file'); + if (!opts?.silent) { + setError('Failed to load file'); + } console.error(err); } finally { setLoading(false); @@ -262,9 +264,10 @@ export default function FilePage() { [project, fetchThreads, fetchContent, fetchAgentStatus], ), useCallback(() => { + fetchContent({ silent: true }); fetchAgentStatus(); fetchThreads(); - }, [fetchAgentStatus, fetchThreads]), + }, [fetchContent, fetchAgentStatus, fetchThreads]), ); const handleComment = useCallback((anchor: Anchor, selectedText: string) => {