feat(dashboard): add EnrichmentBlock wrapper component
Composes UploadSuccessBanner + DashboardNeedsMetadata and reserves a 360px skeleton while \$navigating re-runs the loader with a fresh incomplete list. Prevents the layout-shift jump after a batch upload (Leonie's resolved decision #3 on issue #296). Renders nothing when there is nothing to show — keeps the clean empty dashboard. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
61
frontend/src/lib/components/EnrichmentBlock.svelte.spec.ts
Normal file
61
frontend/src/lib/components/EnrichmentBlock.svelte.spec.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { describe, it, expect, afterEach, vi } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page } from 'vitest/browser';
|
||||
|
||||
import EnrichmentBlock from './EnrichmentBlock.svelte';
|
||||
|
||||
vi.mock('$app/stores', async () => {
|
||||
const { writable } = await import('svelte/store');
|
||||
return { navigating: writable(null) };
|
||||
});
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
type Doc = { id: string; title: string; uploadedAt: string };
|
||||
|
||||
function doc(id: string, title = 'Doc'): Doc {
|
||||
return { id, title, uploadedAt: '2026-04-20T12:00:00' };
|
||||
}
|
||||
|
||||
describe('EnrichmentBlock', () => {
|
||||
it('renders nothing when topDocs is empty and banner count is 0', async () => {
|
||||
render(EnrichmentBlock, {
|
||||
topDocs: [],
|
||||
totalCount: 0,
|
||||
bannerCount: 0,
|
||||
onBannerClose: vi.fn()
|
||||
});
|
||||
await expect.element(page.getByTestId('enrichment-block')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the list component when topDocs is non-empty', async () => {
|
||||
render(EnrichmentBlock, {
|
||||
topDocs: [doc('d1')],
|
||||
totalCount: 1,
|
||||
bannerCount: 0,
|
||||
onBannerClose: vi.fn()
|
||||
});
|
||||
await expect.element(page.getByTestId('dashboard-needs-metadata')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the banner when bannerCount > 0', async () => {
|
||||
render(EnrichmentBlock, {
|
||||
topDocs: [],
|
||||
totalCount: 0,
|
||||
bannerCount: 3,
|
||||
onBannerClose: vi.fn()
|
||||
});
|
||||
await expect.element(page.getByRole('status')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('composes banner + list when both are present', async () => {
|
||||
render(EnrichmentBlock, {
|
||||
topDocs: [doc('d1')],
|
||||
totalCount: 1,
|
||||
bannerCount: 2,
|
||||
onBannerClose: vi.fn()
|
||||
});
|
||||
await expect.element(page.getByRole('status')).toBeInTheDocument();
|
||||
await expect.element(page.getByTestId('dashboard-needs-metadata')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user