feat: add correspondence inbox and gmail ingestion contract

This commit is contained in:
2026-04-01 16:50:14 +02:00
parent 289c2f47ad
commit 3f04849fe6
5 changed files with 317 additions and 1 deletions
@@ -0,0 +1,89 @@
import React from 'react';
import '@testing-library/jest-dom';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { ToastProvider } from './toast';
import { I18nProvider } from './i18n/I18nProvider';
import CorrespondenceInboxPage from './pages/CorrespondenceInboxPage';
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() } },
},
getApiErrorMessage: (error: any, fallback?: string) => fallback || 'Request failed.',
}));
const mockedApi = api as jest.Mocked<typeof api>;
function renderPage() {
return render(
<ToastProvider>
<I18nProvider>
<MemoryRouter>
<CorrespondenceInboxPage />
</MemoryRouter>
</I18nProvider>
</ToastProvider>,
);
}
describe('CorrespondenceInboxPage', () => {
beforeEach(() => {
mockedApi.get.mockResolvedValue({
data: [
{
id: 1,
jobApplicationId: 42,
companyName: 'Acme Systems',
jobTitle: 'Backend Engineer',
from: 'Company',
direction: 'inbound',
subject: 'Interview invite',
channel: 'Email',
date: new Date().toISOString(),
contentPreview: 'We would like to schedule an interview.',
externalThreadId: 'thread-1',
externalFrom: 'Maria Recruiter <maria@acme.test>',
externalTo: 'user@example.test',
labelCount: 2,
attachmentCount: 1,
},
],
} as any);
});
afterEach(() => {
jest.clearAllMocks();
});
test('renders correspondence inbox items and reloads with filters', async () => {
renderPage();
expect(await screen.findByText(/correspondence inbox/i)).toBeInTheDocument();
expect(await screen.findByText(/1 items/i)).toBeInTheDocument();
expect(await screen.findByText(/acme systems/i)).toBeInTheDocument();
expect(await screen.findByText(/backend engineer/i)).toBeInTheDocument();
expect(screen.getByText(/2 labels/i)).toBeInTheDocument();
expect(screen.getByText(/1 attachments/i)).toBeInTheDocument();
fireEvent.change(screen.getByLabelText(/search/i), { target: { value: 'Maria' } });
fireEvent.mouseDown(screen.getAllByRole('combobox')[0]);
fireEvent.click((await screen.findAllByRole('option', { name: /Inbound/i }))[0]);
fireEvent.click(screen.getByRole('button', { name: /refresh/i }));
await waitFor(() => {
expect(mockedApi.get).toHaveBeenLastCalledWith('/correspondence', expect.objectContaining({
params: expect.objectContaining({
q: 'Maria',
direction: 'inbound',
}),
}));
});
});
});