test(dashboard): exercise the EnrichmentBlock skeleton branch
Hoists the $navigating store into a shared __mocks__ module so tests can drive it through real transitions. Adds two specs covering (a) skeleton visible while $navigating && topDocs empty and (b) skeleton hidden when topDocs is non-empty. Also sets aria-busy="true" on the skeleton so screen readers announce the loading state (Leonie's a11y suggestion). Addresses Sara's and Felix's review concern that the skeleton branch was dead code in the test world. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,8 +31,10 @@ const showBlock = $derived(topDocs.length > 0 || bannerCount > 0 || showSkeleton
|
|||||||
<DashboardNeedsMetadata topDocs={topDocs} totalCount={totalCount} />
|
<DashboardNeedsMetadata topDocs={topDocs} totalCount={totalCount} />
|
||||||
{:else if showSkeleton}
|
{:else if showSkeleton}
|
||||||
<div
|
<div
|
||||||
|
data-testid="enrichment-block-skeleton"
|
||||||
class="h-[360px] animate-pulse rounded-sm border border-line bg-surface/50 motion-reduce:animate-none"
|
class="h-[360px] animate-pulse rounded-sm border border-line bg-surface/50 motion-reduce:animate-none"
|
||||||
aria-hidden="true"
|
aria-busy="true"
|
||||||
|
aria-label="Lade aktualisierte Liste"
|
||||||
></div>
|
></div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,14 +2,20 @@ import { describe, it, expect, afterEach, vi } from 'vitest';
|
|||||||
import { cleanup, render } from 'vitest-browser-svelte';
|
import { cleanup, render } from 'vitest-browser-svelte';
|
||||||
import { page } from 'vitest/browser';
|
import { page } from 'vitest/browser';
|
||||||
|
|
||||||
|
// The store must live in a separate module because vi.mock factories are
|
||||||
|
// hoisted and cannot reference top-level variables defined in this file.
|
||||||
|
import { navigatingStore } from './__mocks__/navigatingStore';
|
||||||
import EnrichmentBlock from './EnrichmentBlock.svelte';
|
import EnrichmentBlock from './EnrichmentBlock.svelte';
|
||||||
|
|
||||||
vi.mock('$app/stores', async () => {
|
vi.mock('$app/stores', async () => {
|
||||||
const { writable } = await import('svelte/store');
|
const mod = await import('./__mocks__/navigatingStore');
|
||||||
return { navigating: writable(null) };
|
return { navigating: mod.navigatingStore };
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(cleanup);
|
afterEach(() => {
|
||||||
|
cleanup();
|
||||||
|
navigatingStore.set(null);
|
||||||
|
});
|
||||||
|
|
||||||
type Doc = { id: string; title: string; uploadedAt: string };
|
type Doc = { id: string; title: string; uploadedAt: string };
|
||||||
|
|
||||||
@@ -58,4 +64,26 @@ describe('EnrichmentBlock', () => {
|
|||||||
await expect.element(page.getByRole('status')).toBeInTheDocument();
|
await expect.element(page.getByRole('status')).toBeInTheDocument();
|
||||||
await expect.element(page.getByTestId('dashboard-needs-metadata')).toBeInTheDocument();
|
await expect.element(page.getByTestId('dashboard-needs-metadata')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders the skeleton when $navigating is active and topDocs is empty', async () => {
|
||||||
|
navigatingStore.set({ type: 'link' });
|
||||||
|
render(EnrichmentBlock, {
|
||||||
|
topDocs: [],
|
||||||
|
totalCount: 0,
|
||||||
|
bannerCount: 0,
|
||||||
|
onBannerClose: vi.fn()
|
||||||
|
});
|
||||||
|
await expect.element(page.getByTestId('enrichment-block-skeleton')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render the skeleton when topDocs is non-empty even during $navigating', async () => {
|
||||||
|
navigatingStore.set({ type: 'link' });
|
||||||
|
render(EnrichmentBlock, {
|
||||||
|
topDocs: [doc('d1')],
|
||||||
|
totalCount: 1,
|
||||||
|
bannerCount: 0,
|
||||||
|
onBannerClose: vi.fn()
|
||||||
|
});
|
||||||
|
await expect.element(page.getByTestId('enrichment-block-skeleton')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
3
frontend/src/lib/components/__mocks__/navigatingStore.ts
Normal file
3
frontend/src/lib/components/__mocks__/navigatingStore.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
export const navigatingStore = writable<unknown | null>(null);
|
||||||
Reference in New Issue
Block a user