feat(email): add new-message drafting
This commit is contained in:
@@ -321,6 +321,56 @@ describe('CorrespondenceInboxPage', () => {
|
||||
expect(screen.getByRole('button', { name: /review and send/i })).toBeEnabled();
|
||||
});
|
||||
|
||||
test('starts a new-message draft only from an owned job and send-capable provider choice', async () => {
|
||||
const original = mockedApi.get.getMockImplementation();
|
||||
mockedApi.get.mockImplementation((url: string, config?: any) => {
|
||||
if (url === '/email/providers') return Promise.resolve({ data: [
|
||||
{ provider: 'gmail', displayName: 'Gmail', connected: true, address: 'owner@gmail.test', canRead: true, canSend: true },
|
||||
{ provider: 'microsoft', displayName: 'Outlook', connected: true, address: 'owner@outlook.test', canRead: true, canSend: false },
|
||||
] } as any);
|
||||
if (url === '/jobapplications') return Promise.resolve({ data: { items: [
|
||||
{ id: 42, jobTitle: 'Backend Engineer', company: { name: 'Acme Systems' } },
|
||||
] } } as any);
|
||||
return original!(url, config);
|
||||
});
|
||||
mockedApi.post.mockImplementation((url: string) => {
|
||||
if (url === '/email/drafts') return Promise.resolve({ data: {
|
||||
id: 'draft-new', jobApplicationId: 42, provider: 'gmail', to: 'recruiter@acme.test', subject: 'Application question', bodyText: 'Hello from a synthetic draft.',
|
||||
threadId: null, clientRequestId: 'server-request-id', revision: 1, createdAtUtc: new Date().toISOString(), updatedAtUtc: new Date().toISOString(),
|
||||
} } as any);
|
||||
return Promise.reject(new Error(`Unexpected POST ${url}`));
|
||||
});
|
||||
|
||||
renderPage();
|
||||
const compose = await screen.findByRole('button', { name: /compose new email/i });
|
||||
await waitFor(() => expect(compose).toBeEnabled());
|
||||
fireEvent.click(compose);
|
||||
expect(await screen.findByRole('heading', { name: /compose new email/i })).toBeInTheDocument();
|
||||
const providerSelect = screen.getByRole('combobox', { name: /sending provider/i });
|
||||
expect(providerSelect).toHaveTextContent(/Gmail/i);
|
||||
fireEvent.mouseDown(providerSelect);
|
||||
const gmailOption = await screen.findByRole('option', { name: /Gmail/i });
|
||||
expect(screen.queryByRole('option', { name: /Outlook/i })).not.toBeInTheDocument();
|
||||
fireEvent.click(gmailOption);
|
||||
fireEvent.click(screen.getByRole('button', { name: /start draft/i }));
|
||||
|
||||
expect(screen.getByRole('textbox', { name: /^provider$/i })).toHaveValue('Gmail · owner@gmail.test');
|
||||
expect(screen.getByLabelText(/thread/i)).toHaveValue('New message');
|
||||
fireEvent.change(screen.getByLabelText(/recipient/i), { target: { value: 'recruiter@acme.test' } });
|
||||
fireEvent.change(screen.getByLabelText(/subject/i), { target: { value: 'Application question' } });
|
||||
fireEvent.change(screen.getByLabelText(/message/i), { target: { value: 'Hello from a synthetic draft.' } });
|
||||
fireEvent.click(screen.getByRole('button', { name: /^save draft$/i }));
|
||||
|
||||
await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith('/email/drafts', {
|
||||
jobApplicationId: 42,
|
||||
provider: 'gmail',
|
||||
to: 'recruiter@acme.test',
|
||||
subject: 'Application question',
|
||||
bodyText: 'Hello from a synthetic draft.',
|
||||
threadId: null,
|
||||
}));
|
||||
});
|
||||
|
||||
test('does not offer retry when delivery is uncertain', async () => {
|
||||
const original = mockedApi.get.getMockImplementation();
|
||||
mockedApi.get.mockImplementation((url: string, config?: any) => {
|
||||
|
||||
Reference in New Issue
Block a user