9edcbfc5de
Make job/CV comparisons language-aware and filter recruitment noise. Improve responsive career navigation, shared spacing, dashboard priorities, settings, localized workspace controls, and portable browser tests.
58 lines
2.9 KiB
TypeScript
58 lines
2.9 KiB
TypeScript
import React from 'react';
|
|
import '@testing-library/jest-dom';
|
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
|
|
import { api } from './api';
|
|
import { AccountPlanProvider } from './accountPlan';
|
|
import { ApplicationStatusSuggestion, ApplicationStrategySnapshot } from './components/ApplicationWorkflowAssist';
|
|
import { I18nProvider } from './i18n/I18nProvider';
|
|
import { ToastProvider } from './toast';
|
|
|
|
jest.mock('./api', () => ({
|
|
api: { get: jest.fn(), post: jest.fn(), patch: jest.fn() },
|
|
getApiErrorMessage: (_error: unknown, fallback?: string) => fallback || 'Request failed.',
|
|
}));
|
|
|
|
const mockedApi = api as jest.Mocked<typeof api>;
|
|
|
|
beforeEach(() => jest.clearAllMocks());
|
|
|
|
test('recruiter status suggestions require an explicit apply action', async () => {
|
|
const applied = jest.fn();
|
|
mockedApi.get.mockResolvedValue({ data: { hasSuggestion: true, currentStatus: 'Applied', suggestedStatus: 'Interview' } } as any);
|
|
mockedApi.patch.mockResolvedValue({ data: {} } as any);
|
|
render(<I18nProvider><ToastProvider><ApplicationStatusSuggestion jobId={42} onApplied={applied} /></ToastProvider></I18nProvider>);
|
|
|
|
const button = await screen.findByRole('button', { name: 'Apply Interview' });
|
|
expect(mockedApi.patch).not.toHaveBeenCalled();
|
|
fireEvent.click(button);
|
|
await waitFor(() => expect(mockedApi.patch).toHaveBeenCalledWith('/jobapplications/42/status', { status: 'Interview' }));
|
|
expect(applied).toHaveBeenCalled();
|
|
});
|
|
|
|
test('strategy snapshot shows saved output and queues regeneration only on request', async () => {
|
|
mockedApi.get.mockImplementation((url: string) => {
|
|
if (url.endsWith('/focus-plan')) return Promise.resolve({ data: {
|
|
strategicSummary: 'Lead with delivery evidence.',
|
|
immediatePriorities: ['Tailor the summary'],
|
|
proofPointsToLeadWith: ['Reduced lead time'],
|
|
cvBulletIdeas: ['Quantify the migration'],
|
|
coverLetterAngles: ['Public-service impact'],
|
|
followUpApproach: ['Follow up after five days'],
|
|
} } as any);
|
|
return Promise.reject(new Error('no operation'));
|
|
});
|
|
mockedApi.post.mockResolvedValue({ data: {
|
|
created: true,
|
|
statusUrl: '/operations/op-1',
|
|
operation: { id: 'op-1', taskType: 'focus-plan', status: 'queued', createdAtUtc: '', canCancel: true, canRetry: false },
|
|
} } as any);
|
|
|
|
render(<I18nProvider><ToastProvider><AccountPlanProvider value={{ plan: 'pro', canUseAi: true, canUseProThemes: true }}><ApplicationStrategySnapshot jobId={42} /></AccountPlanProvider></ToastProvider></I18nProvider>);
|
|
expect(await screen.findByText('Lead with delivery evidence.')).toBeInTheDocument();
|
|
expect(mockedApi.post).not.toHaveBeenCalled();
|
|
fireEvent.click(screen.getByRole('button', { name: 'Regenerate' }));
|
|
await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith('/jobapplications/42/focus-plan/operations', { attachmentIds: null }));
|
|
expect(await screen.findByText('queued')).toBeInTheDocument();
|
|
});
|