fix(career): preserve edits during polling
Refresh extraction runs without reloading controlled profile fields. Keep stored-profile AI actions gated until pending edits are saved.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import '@testing-library/jest-dom';
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { ToastProvider } from './toast';
|
||||
import { I18nProvider } from './i18n/I18nProvider';
|
||||
import ProfilePage from './views/ProfilePage';
|
||||
@@ -284,6 +284,55 @@ test('profile page can reprocess from stored artifact history', async () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('active extraction polling refreshes run status without resetting unsaved career fields', async () => {
|
||||
extractionRunsResponse = [{
|
||||
id: 15,
|
||||
trigger: 'upload',
|
||||
status: 'queued',
|
||||
artifactFileName: 'active-cv.pdf',
|
||||
startedAtUtc: '2026-03-28T12:00:00Z',
|
||||
parserVersion: 'm005-s01',
|
||||
normalizerVersion: 'm005-s01',
|
||||
llmPromptVersion: 'm005-s01',
|
||||
operation: {
|
||||
id: '00000000-0000-0000-0000-000000000015',
|
||||
taskType: 'cv.process',
|
||||
status: 'queued',
|
||||
createdAtUtc: '2026-03-28T12:00:00Z',
|
||||
canCancel: true,
|
||||
canRetry: false,
|
||||
},
|
||||
}];
|
||||
let poll: (() => void) | undefined;
|
||||
const interval = jest.spyOn(window, 'setInterval').mockImplementation((handler: TimerHandler, timeout?: number) => {
|
||||
if (timeout === 4000 && typeof handler === 'function') poll = handler as () => void;
|
||||
return 1 as any;
|
||||
});
|
||||
|
||||
renderPage();
|
||||
const nameField = await screen.findByLabelText(/full name/i);
|
||||
await waitFor(() => expect(poll).toBeDefined());
|
||||
fireEvent.change(nameField, { target: { value: 'Unsaved Poll-Safe Name' } });
|
||||
|
||||
extractionRunsResponse = [{ ...extractionRunsResponse[0], status: 'running', operation: { ...extractionRunsResponse[0].operation, status: 'running' } }];
|
||||
await act(async () => {
|
||||
poll?.();
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
await waitFor(() => expect(mockedApi.get.mock.calls.filter(([url]) => url === '/profile-cv/runs').length).toBeGreaterThanOrEqual(2));
|
||||
expect(mockedApi.get.mock.calls.filter(([url]) => url === '/career/profile')).toHaveLength(1);
|
||||
expect(nameField).toHaveValue('Unsaved Poll-Safe Name');
|
||||
expect(screen.getByText('Unsaved changes')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /save changes/i }));
|
||||
await waitFor(() => expect(mockedApi.put).toHaveBeenCalledWith('/career/profile', expect.objectContaining({
|
||||
profile: expect.objectContaining({ contact: expect.objectContaining({ fullName: 'Unsaved Poll-Safe Name' }) }),
|
||||
})));
|
||||
interval.mockRestore();
|
||||
});
|
||||
|
||||
test('profile page shows durable CV operation state and retries a failed run', async () => {
|
||||
extractionRunsResponse = [{
|
||||
id: 14,
|
||||
|
||||
Reference in New Issue
Block a user