diff --git a/docs/redesign/phase-5/p5-15/p5-15-01/INTERMITTENT_FAILURES.md b/docs/redesign/phase-5/p5-15/p5-15-01/INTERMITTENT_FAILURES.md index 7c3d0e6..075bd92 100644 --- a/docs/redesign/phase-5/p5-15/p5-15-01/INTERMITTENT_FAILURES.md +++ b/docs/redesign/phase-5/p5-15/p5-15-01/INTERMITTENT_FAILURES.md @@ -1,5 +1,11 @@ # P5-15-01 intermittent observations +## P5-15-03 temporal qualification successor + +The pending-draft preview-exit regression used real time, while the actual editor schedules autosave after 800 ms. A slow assertion can legitimately observe Saved instead of Unsaved. The test now controls that editing-session clock, retains the original pending value/focus/Unsaved/no-write assertions, then crosses the existing debounce boundary and verifies the exact retained headline, expected revision 4, successful Saved state and unchanged editor value. The affected CV/Analytics suites pass 46/46; test count is unchanged. No CV save implementation, timeout or success assertion was weakened. + +This establishes the temporal contract and removes the test's dependency on machine speed. It does not reconstruct the historical failing run's missing timing trace: IF-CV-UNSAVED-01 remains OPEN as an incident observation, with this bounded test qualification recorded separately. Preserve a future failing save/version trace if it recurs. + ## IF-CV-UNSAVED-01 — Preview exit “Unsaved” assertion **OPEN; cause not established; no CV repair.** PRES-C06/C10/E08. R-01's first complete frontend rerun passed463/failed1 of464. The case `[P5-11 PRES-C06 C10 E08] returning from preview focuses the existing editor without changing the pending draft` failed its `getByText('Unsaved')` assertion in `cv-builder-deep-link.test.tsx` (recorded line751). diff --git a/job-tracker-ui/src/cv-builder-deep-link.test.tsx b/job-tracker-ui/src/cv-builder-deep-link.test.tsx index 9bc73e3..df0243c 100644 --- a/job-tracker-ui/src/cv-builder-deep-link.test.tsx +++ b/job-tracker-ui/src/cv-builder-deep-link.test.tsx @@ -742,14 +742,21 @@ test('[P5-11 PRES-C06 C10 E08] returning from preview focuses the existing edito renderAt(3); await openContentTab(); const headline = screen.getByLabelText('Headline override'); - fireEvent.change(headline, { target: { value: 'Retained preview draft' } }); - const editor = screen.getByRole('region', { name: 'CV editing controls' }); - editor.scrollIntoView = jest.fn(); - fireEvent.click(screen.getByRole('button', { name: 'Go to editor' })); - await waitFor(() => expect(editor).toHaveFocus()); - expect(headline).toHaveValue('Retained preview draft'); - expect(screen.getByText('Unsaved')).toBeInTheDocument(); - expect(mockedApi.put).not.toHaveBeenCalled(); + jest.useFakeTimers(); + try { + fireEvent.change(headline, { target: { value: 'Retained preview draft' } }); + const editor = screen.getByRole('region', { name: 'CV editing controls' }); + editor.scrollIntoView = jest.fn(); + fireEvent.click(screen.getByRole('button', { name: 'Go to editor' })); + await waitFor(() => expect(editor).toHaveFocus()); + expect(headline).toHaveValue('Retained preview draft'); + expect(screen.getByText('Unsaved')).toBeInTheDocument(); + expect(mockedApi.put).not.toHaveBeenCalled(); + await act(async () => { jest.advanceTimersByTime(800); }); + expect(mockedApi.put).toHaveBeenCalledWith('/cv/variants/3', expect.objectContaining({ expectedVersion: 4, settings: expect.objectContaining({ headline: 'Retained preview draft' }) })); + expect(screen.getByText('Saved')).toBeInTheDocument(); + expect(headline).toHaveValue('Retained preview draft'); + } finally { jest.useRealTimers(); } }); async function reviewDocumentSuggestion(result: string) {