import React from 'react'; import '@testing-library/jest-dom'; import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { ToastProvider } from './toast'; import { I18nProvider } from './i18n/I18nProvider'; import { api } from './api'; // Avoid pulling the date-fns v4 ESM adapter into Jest; the picker isn't under test here. jest.mock('@mui/x-date-pickers/DatePicker', () => ({ DatePicker: ({ label }: any) =>
{label}
, })); // eslint-disable-next-line import/first import AddJobModal from './components/AddJobModal'; jest.setTimeout(15000); jest.mock('./api', () => ({ api: { get: jest.fn(() => Promise.resolve({ data: [] })), post: jest.fn(() => Promise.resolve({ data: {} })), put: jest.fn(() => Promise.resolve({ data: {} })), patch: jest.fn(() => Promise.resolve({ data: {} })), delete: jest.fn(() => Promise.resolve({ data: {} })), interceptors: { request: { use: jest.fn() }, response: { use: jest.fn() } }, }, getApiErrorMessage: jest.fn(() => 'error'), })); const mockedApi = api as jest.Mocked; function renderModal(initialUrl?: string) { return render( {}} onCreated={() => {}} /> , ); } beforeEach(() => { mockedApi.get.mockResolvedValue({ data: [] } as any); mockedApi.post.mockImplementation((url: string) => { if (url === '/jobimport/preview') { return Promise.resolve({ data: { success: true, title: 'Imported Backend Role', company: 'Acme', location: 'Oslo', description: 'desc', tags: ['C#'] } } as any); } return Promise.resolve({ data: {} } as any); }); }); afterEach(() => jest.clearAllMocks()); test('auto-imports from initialUrl and prefills the form', async () => { renderModal('https://example.com/jobs/123'); await waitFor(() => { expect(mockedApi.post).toHaveBeenCalledWith('/jobimport/preview', { url: 'https://example.com/jobs/123' }); }); expect(await screen.findByDisplayValue('Imported Backend Role')).toBeInTheDocument(); }); test('does not auto-import when no initialUrl is given', async () => { renderModal(undefined); // Wait for the modal to render, then confirm no import was triggered. expect(await screen.findByRole('dialog')).toBeInTheDocument(); expect(mockedApi.post).not.toHaveBeenCalledWith('/jobimport/preview', expect.anything()); }); test('can generate a tailored CV after creating a job', async () => { mockedApi.post.mockImplementation((url: string) => { if (url === '/jobimport/preview') return Promise.resolve({ data: { success: true, title: 'Imported Backend Role', company: 'Acme', description: 'desc' } } as any); if (url === '/companies') return Promise.resolve({ data: { id: 1, name: 'Acme' } } as any); if (url === '/jobapplications') return Promise.resolve({ data: { id: 42 } } as any); return Promise.resolve({ data: {} } as any); }); renderModal('https://example.com/jobs/123'); expect(await screen.findByDisplayValue('Imported Backend Role')).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: 'Continue' })); fireEvent.click(await screen.findByLabelText('Generate a tailored CV draft after creating this job')); for (let step = 0; step < 3; step += 1) fireEvent.click(screen.getByRole('button', { name: 'Skip and continue' })); fireEvent.click(screen.getByRole('button', { name: /create job/i })); await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith('/jobapplications/42/generate-tailored-cv-draft')); });