test(coverage): drive browser tests to 80% on all metrics (#496) #505

Merged
marcel merged 189 commits from feat/issue-496-browser-coverage-tests into main 2026-05-11 21:50:39 +02:00
Showing only changes of commit 81fe998c17 - Show all commits

View File

@@ -41,6 +41,11 @@ afterEach(() => {
lastSource = null; lastSource = null;
}); });
async function waitForSource(): Promise<MockEventSource> {
await vi.waitFor(() => expect(lastSource).not.toBeNull());
return lastSource as MockEventSource;
}
describe('OcrProgress', () => { describe('OcrProgress', () => {
it('renders the running progress block by default', async () => { it('renders the running progress block by default', async () => {
render(OcrProgress, { props: { jobId: 'job-1', onDone: () => {} } }); render(OcrProgress, { props: { jobId: 'job-1', onDone: () => {} } });
@@ -57,33 +62,31 @@ describe('OcrProgress', () => {
it('updates the progress bar when document events arrive', async () => { it('updates the progress bar when document events arrive', async () => {
render(OcrProgress, { props: { jobId: 'job-1', onDone: () => {} } }); render(OcrProgress, { props: { jobId: 'job-1', onDone: () => {} } });
// Wait a tick for $effect to run and EventSource to be created. const src = await waitForSource();
await new Promise((r) => setTimeout(r, 50)); src.dispatch('document', { processed: 5, total: 10 });
lastSource?.dispatch('document', { processed: 5, total: 10 });
await new Promise((r) => setTimeout(r, 50));
const bar = (await page.getByRole('progressbar').element()) as HTMLElement; await vi.waitFor(async () => {
expect(bar.getAttribute('aria-valuenow')).toBe('50'); const bar = (await page.getByRole('progressbar').element()) as HTMLElement;
expect(bar.getAttribute('aria-valuenow')).toBe('50');
});
}); });
it('switches to the done state and calls onDone when the done event arrives', async () => { it('switches to the done state and calls onDone when the done event arrives', async () => {
const onDone = vi.fn(); const onDone = vi.fn();
render(OcrProgress, { props: { jobId: 'job-1', onDone } }); render(OcrProgress, { props: { jobId: 'job-1', onDone } });
await new Promise((r) => setTimeout(r, 50)); const src = await waitForSource();
lastSource?.dispatch('done', {}); src.dispatch('done', {});
await new Promise((r) => setTimeout(r, 50));
expect(onDone).toHaveBeenCalledOnce(); await vi.waitFor(() => expect(onDone).toHaveBeenCalledOnce());
await expect.element(page.getByRole('heading', { name: /ocr läuft/i })).not.toBeInTheDocument(); await expect.element(page.getByRole('heading', { name: /ocr läuft/i })).not.toBeInTheDocument();
}); });
it('switches to the error state when the error event arrives', async () => { it('switches to the error state when the error event arrives', async () => {
render(OcrProgress, { props: { jobId: 'job-1', onDone: () => {} } }); render(OcrProgress, { props: { jobId: 'job-1', onDone: () => {} } });
await new Promise((r) => setTimeout(r, 50)); const src = await waitForSource();
lastSource?.dispatch('error', {}); src.dispatch('error', {});
await new Promise((r) => setTimeout(r, 50));
await expect.element(page.getByRole('heading', { name: /ocr fehlgeschlagen/i })).toBeVisible(); await expect.element(page.getByRole('heading', { name: /ocr fehlgeschlagen/i })).toBeVisible();
}); });
@@ -91,9 +94,8 @@ describe('OcrProgress', () => {
it('renders the retry button in the error state', async () => { it('renders the retry button in the error state', async () => {
render(OcrProgress, { props: { jobId: 'job-1', onDone: () => {} } }); render(OcrProgress, { props: { jobId: 'job-1', onDone: () => {} } });
await new Promise((r) => setTimeout(r, 50)); const src = await waitForSource();
lastSource?.dispatch('error', {}); src.dispatch('error', {});
await new Promise((r) => setTimeout(r, 50));
await expect.element(page.getByRole('button', { name: /erneut versuchen/i })).toBeVisible(); await expect.element(page.getByRole('button', { name: /erneut versuchen/i })).toBeVisible();
}); });