feat(onboarding): migrate source-backed setup guidance
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import '@testing-library/jest-dom';
|
||||
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
|
||||
import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react';
|
||||
import { MemoryRouter, useLocation } from 'react-router-dom';
|
||||
import DashboardView from './components/DashboardView';
|
||||
import { I18nProvider } from './i18n/I18nProvider';
|
||||
import { api } from './api';
|
||||
|
||||
jest.mock('./components/OnboardingChecklist', () => () => <div>Setup retained</div>);
|
||||
jest.mock('./components/OnboardingChecklist', () => ({ hasJobs }: { hasJobs: boolean | null }) => <><div>Setup retained</div><output aria-label="Setup job status">{hasJobs === null ? 'unknown' : String(hasJobs)}</output></>);
|
||||
const mockedApi = api as jest.Mocked<typeof api>;
|
||||
const stats = { total: 9, active: 8, deleted: 1, byStatus: { Applied: 3, Interview: 2, Offer: 1, 'Faglig vurdering': 2 }, appliedLast30Days: 4 };
|
||||
const overview = { funnel: [{ label: 'Applied', count: 3 }, { label: 'Interview', count: 2 }, { label: 'Offer', count: 1 }], totalActive: 8, totalResponses: 3, responseRateBySource: [{ label: 'NAV', total: 8, responses: 3, rate: 37.5 }], topCompanies: [{ companyId: 7, company: 'Nordlys AS', count: 8, responses: 3, responseRate: 37.5 }], timeInStage: [{ stage: 'Applied', medianDays: 4, count: 3 }], salaryInsights: [{ currency: 'NOK', period: 'year', count: 2, minimum: 600000, maximum: 800000, averageMidpoint: 700000 }] };
|
||||
@@ -99,3 +99,26 @@ test('[PRES-S01] activity chart uses one shared zero-based scale and a readable
|
||||
const firstY = (path: Element) => Number(path.getAttribute('d')!.split(' ')[2]);
|
||||
expect(firstY(paths[0])).toBeLessThan(firstY(paths[1]));
|
||||
});
|
||||
|
||||
test('[P7-02 PRES-S01 S02] setup guidance treats pending and failed summaries as unknown until their owner retries', async () => {
|
||||
let resolveStats!: (response: { data: typeof stats }) => void;
|
||||
let fail = false;
|
||||
const pending = new Promise<{ data: typeof stats }>(resolve => { resolveStats = resolve; });
|
||||
mockedApi.get.mockImplementation((url: string) => url.endsWith('/stats')
|
||||
? fail ? Promise.reject(new Error('summary unavailable')) : pending
|
||||
: Promise.resolve({ data: data(url) }) as any);
|
||||
const view = open();
|
||||
expect(screen.getByLabelText('Setup job status')).toHaveTextContent('unknown');
|
||||
await screen.findByRole('region', { name: 'Application activity' });
|
||||
await act(async () => { resolveStats({ data: { ...stats, total: 0 } }); });
|
||||
await waitFor(() => expect(screen.getByLabelText('Setup job status')).toHaveTextContent('false'));
|
||||
view.unmount();
|
||||
fail = true;
|
||||
open();
|
||||
await screen.findByText('Unable to load dashboard summary');
|
||||
expect(screen.getByLabelText('Setup job status')).toHaveTextContent('unknown');
|
||||
mockedApi.get.mockImplementation((url: string) => Promise.resolve({ data: data(url) }) as any);
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Retry' }));
|
||||
await waitFor(() => expect(screen.getByLabelText('Setup job status')).toHaveTextContent('true'));
|
||||
expect(mockedApi.get).toHaveBeenCalledWith('/jobapplications/stats');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user