test: cover DocumentThumbnail, UnsavedWarningBanner, PersonsStatsBar
DocumentThumbnail: thumbnailUrl→img branch, no-thumbnail→placeholder icon branch, sm vs lg size container class, lazy/async loading attrs. UnsavedWarningBanner: warning text, discard button, callback wiring. PersonsStatsBar: count rendering, singular/plural label switching for both persons and documents (4 branches), zero-count plural fallback. 14 tests across three small primitive files. Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
61
frontend/src/lib/document/DocumentThumbnail.svelte.test.ts
Normal file
61
frontend/src/lib/document/DocumentThumbnail.svelte.test.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import DocumentThumbnail from './DocumentThumbnail.svelte';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
describe('DocumentThumbnail', () => {
|
||||
it('renders the supplied thumbnail image when thumbnailUrl is set', async () => {
|
||||
render(DocumentThumbnail, {
|
||||
props: {
|
||||
doc: { id: 'd1', thumbnailUrl: '/api/d1/thumb', contentType: 'application/pdf' }
|
||||
}
|
||||
});
|
||||
|
||||
const img = document.querySelector('img') as HTMLImageElement;
|
||||
expect(img).not.toBeNull();
|
||||
expect(img.src).toContain('/api/d1/thumb');
|
||||
});
|
||||
|
||||
it('renders the placeholder icon when thumbnailUrl is missing', async () => {
|
||||
render(DocumentThumbnail, {
|
||||
props: { doc: { id: 'd1', thumbnailUrl: null, contentType: 'application/pdf' } }
|
||||
});
|
||||
|
||||
const svg = document.querySelector('svg');
|
||||
expect(svg).not.toBeNull();
|
||||
});
|
||||
|
||||
it('uses the small container size by default', async () => {
|
||||
render(DocumentThumbnail, {
|
||||
props: { doc: { id: 'd1', thumbnailUrl: null, contentType: 'application/pdf' } }
|
||||
});
|
||||
|
||||
const container = document.querySelector('.h-\\[84px\\]');
|
||||
expect(container).not.toBeNull();
|
||||
});
|
||||
|
||||
it('uses the large container size when size="lg"', async () => {
|
||||
render(DocumentThumbnail, {
|
||||
props: {
|
||||
doc: { id: 'd1', thumbnailUrl: null, contentType: 'application/pdf' },
|
||||
size: 'lg'
|
||||
}
|
||||
});
|
||||
|
||||
const container = document.querySelector('.h-\\[168px\\]');
|
||||
expect(container).not.toBeNull();
|
||||
});
|
||||
|
||||
it('uses lazy loading attributes on the thumbnail image', async () => {
|
||||
render(DocumentThumbnail, {
|
||||
props: {
|
||||
doc: { id: 'd1', thumbnailUrl: '/api/d1/thumb', contentType: 'application/pdf' }
|
||||
}
|
||||
});
|
||||
|
||||
const img = document.querySelector('img') as HTMLImageElement;
|
||||
expect(img.loading).toBe('lazy');
|
||||
expect(img.decoding).toBe('async');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page } from 'vitest/browser';
|
||||
import UnsavedWarningBanner from './UnsavedWarningBanner.svelte';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
describe('UnsavedWarningBanner', () => {
|
||||
it('renders the warning text', async () => {
|
||||
render(UnsavedWarningBanner, { props: { onDiscard: () => {} } });
|
||||
|
||||
await expect.element(page.getByText(/ungespeicherte änderungen/i)).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders the discard action button', async () => {
|
||||
render(UnsavedWarningBanner, { props: { onDiscard: () => {} } });
|
||||
|
||||
await expect.element(page.getByRole('button', { name: /verwerfen/i })).toBeVisible();
|
||||
});
|
||||
|
||||
it('calls onDiscard when the discard button is clicked', async () => {
|
||||
const onDiscard = vi.fn();
|
||||
render(UnsavedWarningBanner, { props: { onDiscard } });
|
||||
|
||||
await page.getByRole('button', { name: /verwerfen/i }).click();
|
||||
|
||||
expect(onDiscard).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
46
frontend/src/routes/persons/PersonsStatsBar.svelte.test.ts
Normal file
46
frontend/src/routes/persons/PersonsStatsBar.svelte.test.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page } from 'vitest/browser';
|
||||
import PersonsStatsBar from './PersonsStatsBar.svelte';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
describe('PersonsStatsBar', () => {
|
||||
it('renders both counts', async () => {
|
||||
render(PersonsStatsBar, { props: { totalPersons: 42, totalDocuments: 99 } });
|
||||
|
||||
await expect.element(page.getByText('42')).toBeVisible();
|
||||
await expect.element(page.getByText('99')).toBeVisible();
|
||||
});
|
||||
|
||||
it('uses the singular person label when totalPersons is 1', async () => {
|
||||
render(PersonsStatsBar, { props: { totalPersons: 1, totalDocuments: 5 } });
|
||||
|
||||
await expect.element(page.getByText('Person', { exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
it('uses the plural person label when totalPersons is not 1', async () => {
|
||||
render(PersonsStatsBar, { props: { totalPersons: 5, totalDocuments: 5 } });
|
||||
|
||||
await expect.element(page.getByText('Personen', { exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
it('uses the singular document label when totalDocuments is 1', async () => {
|
||||
render(PersonsStatsBar, { props: { totalPersons: 5, totalDocuments: 1 } });
|
||||
|
||||
await expect.element(page.getByText('Dokument', { exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
it('uses the plural document label when totalDocuments is not 1', async () => {
|
||||
render(PersonsStatsBar, { props: { totalPersons: 5, totalDocuments: 5 } });
|
||||
|
||||
await expect.element(page.getByText('Dokumente', { exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
it('handles zero counts with plural labels', async () => {
|
||||
render(PersonsStatsBar, { props: { totalPersons: 0, totalDocuments: 0 } });
|
||||
|
||||
await expect.element(page.getByText('Personen', { exact: true })).toBeVisible();
|
||||
await expect.element(page.getByText('Dokumente', { exact: true })).toBeVisible();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user