test: cover enrich/done and documents/bulk-edit page branches
enrich/done: heading, body, both CTA links. documents/bulk-edit: empty-store onMount redirect to /documents, loading spinner during in-flight fetch, error banner on backend error code, error banner on fetch rejection. Mocks fetch via vi.spyOn so the async branches are exercised without a real backend. Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
80
frontend/src/routes/documents/bulk-edit/page.svelte.test.ts
Normal file
80
frontend/src/routes/documents/bulk-edit/page.svelte.test.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page } from 'vitest/browser';
|
||||
|
||||
const gotoSpy = vi.fn();
|
||||
vi.mock('$app/navigation', () => ({
|
||||
beforeNavigate: () => {},
|
||||
afterNavigate: () => {},
|
||||
goto: gotoSpy,
|
||||
invalidate: vi.fn(),
|
||||
invalidateAll: vi.fn(),
|
||||
preloadCode: vi.fn(),
|
||||
preloadData: vi.fn(),
|
||||
pushState: vi.fn(),
|
||||
replaceState: vi.fn(),
|
||||
disableScrollHandling: vi.fn(),
|
||||
onNavigate: () => () => {}
|
||||
}));
|
||||
|
||||
const { bulkSelectionStore } = await import('$lib/document/bulkSelection.svelte');
|
||||
const { default: BulkEditPage } = await import('./+page.svelte');
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
bulkSelectionStore.clear();
|
||||
gotoSpy.mockClear();
|
||||
});
|
||||
|
||||
describe('documents/bulk-edit page', () => {
|
||||
it('redirects to /documents when no documents are selected', async () => {
|
||||
render(BulkEditPage, { props: {} });
|
||||
|
||||
// onMount runs immediately — give it a tick
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
|
||||
expect(gotoSpy).toHaveBeenCalledWith('/documents');
|
||||
});
|
||||
|
||||
it('shows the loading spinner while fetching batch metadata', async () => {
|
||||
bulkSelectionStore.toggle('d1');
|
||||
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockImplementation(() => new Promise(() => {}));
|
||||
try {
|
||||
render(BulkEditPage, { props: {} });
|
||||
|
||||
await expect.element(page.getByRole('status')).toBeVisible();
|
||||
await expect.element(page.getByText('Dokumente werden geladen…')).toBeVisible();
|
||||
} finally {
|
||||
fetchSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it('shows the error banner when the fetch fails with a backend error code', async () => {
|
||||
bulkSelectionStore.toggle('d1');
|
||||
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
||||
new Response(JSON.stringify({ code: 'INTERNAL_ERROR' }), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
);
|
||||
try {
|
||||
render(BulkEditPage, { props: {} });
|
||||
|
||||
await expect.element(page.getByRole('alert')).toBeVisible();
|
||||
} finally {
|
||||
fetchSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it('shows the error banner when fetch throws an unexpected error', async () => {
|
||||
bulkSelectionStore.toggle('d1');
|
||||
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('Network down'));
|
||||
try {
|
||||
render(BulkEditPage, { props: {} });
|
||||
|
||||
await expect.element(page.getByRole('alert')).toBeVisible();
|
||||
} finally {
|
||||
fetchSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
36
frontend/src/routes/enrich/done/page.svelte.test.ts
Normal file
36
frontend/src/routes/enrich/done/page.svelte.test.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page } from 'vitest/browser';
|
||||
import EnrichDonePage from './+page.svelte';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
describe('enrich/done page', () => {
|
||||
it('renders the success heading', async () => {
|
||||
render(EnrichDonePage, { props: {} });
|
||||
|
||||
await expect.element(page.getByRole('heading', { name: /alles erledigt/i })).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders the body message', async () => {
|
||||
render(EnrichDonePage, { props: {} });
|
||||
|
||||
await expect.element(page.getByText('Alle Dokumente wurden bearbeitet.')).toBeVisible();
|
||||
});
|
||||
|
||||
it('links the primary CTA to the home page', async () => {
|
||||
render(EnrichDonePage, { props: {} });
|
||||
|
||||
await expect
|
||||
.element(page.getByRole('link', { name: /zurück zur übersicht/i }))
|
||||
.toHaveAttribute('href', '/');
|
||||
});
|
||||
|
||||
it('links the secondary CTA back to /enrich', async () => {
|
||||
render(EnrichDonePage, { props: {} });
|
||||
|
||||
await expect
|
||||
.element(page.getByRole('link', { name: /zurück zur liste/i }))
|
||||
.toHaveAttribute('href', '/enrich');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user