test: add draft workflow coverage and sqlite migration helpers

This commit is contained in:
cesnimda
2026-03-22 18:59:05 +01:00
parent 87c9a11edc
commit 7f4068518d
6 changed files with 191 additions and 6 deletions
@@ -0,0 +1,68 @@
import React from 'react';
import '@testing-library/jest-dom';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { ConfirmProvider } from './confirm';
import { PromptProvider } from './prompt';
import { ToastProvider } from './toast';
import JobDetailsDialog from './components/JobDetailsDialog';
import { api } from './api';
jest.mock('./api', () => ({
api: {
get: jest.fn(),
post: jest.fn(),
put: jest.fn(),
patch: jest.fn(),
delete: jest.fn(),
interceptors: { request: { use: jest.fn() }, response: { use: jest.fn() } },
},
}));
const mockedApi = api as jest.Mocked<typeof api>;
function renderDialog() {
return render(
<ToastProvider>
<ConfirmProvider>
<PromptProvider>
<JobDetailsDialog open jobId={42} onClose={() => {}} />
</PromptProvider>
</ConfirmProvider>
</ToastProvider>,
);
}
beforeEach(() => {
mockedApi.get.mockImplementation((url: string) => {
if (url === '/jobapplications/42') {
return Promise.resolve({ data: { id: 42, jobTitle: 'Backend Developer', status: 'Applied', dateApplied: new Date().toISOString(), daysSince: 3, company: { name: 'Acme', recruiterEmail: 'recruiter@acme.test' }, tailoredCvText: '', shortSummary: 'summary' } } as any);
}
if (url === '/auth/me') {
return Promise.resolve({ data: { roles: [], profileCvText: 'Master CV text' } } as any);
}
if (url === '/jobapplications/42/history') {
return Promise.resolve({ data: [] } as any);
}
return Promise.resolve({ data: [] } as any);
});
mockedApi.post.mockResolvedValue({ data: { tailoredCvText: 'Generated CV', coverLetterDraft: 'Draft letter', applicationAnswerDraft: 'Draft answer', recruiterMessageDraft: 'Recruiter hello', keyPoints: ['Lead with .NET'] } } as any);
mockedApi.put.mockResolvedValue({ data: {} } as any);
});
test('generated application package can be edited and saved', async () => {
renderDialog();
fireEvent.click(await screen.findByRole('tab', { name: /tailored cv/i }));
fireEvent.click(await screen.findByRole('button', { name: /generate application package/i }));
expect(await screen.findByDisplayValue('Generated CV')).toBeInTheDocument();
const coverLetter = await screen.findByDisplayValue('Draft letter');
fireEvent.change(coverLetter, { target: { value: 'Edited cover letter' } });
const saveButtons = screen.getAllByRole('button', { name: /^save$/i });
fireEvent.click(saveButtons[0]);
await waitFor(() => {
expect(mockedApi.put).toHaveBeenCalled();
});
});