diff --git a/frontend/src/lib/document/TimelineYAxis.svelte.test.ts b/frontend/src/lib/document/TimelineYAxis.svelte.test.ts new file mode 100644 index 00000000..d5d55600 --- /dev/null +++ b/frontend/src/lib/document/TimelineYAxis.svelte.test.ts @@ -0,0 +1,29 @@ +import { describe, it, expect, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import TimelineYAxis from './TimelineYAxis.svelte'; + +afterEach(cleanup); + +describe('TimelineYAxis', () => { + it('renders the maxCount and 0 labels', async () => { + render(TimelineYAxis, { props: { maxCount: 42, barAreaHeight: 100 } }); + + const axis = document.querySelector('[data-testid="timeline-y-axis"]') as HTMLElement; + expect(axis.textContent).toContain('42'); + expect(axis.textContent).toContain('0'); + }); + + it('applies the supplied barAreaHeight as inline style', async () => { + render(TimelineYAxis, { props: { maxCount: 10, barAreaHeight: 250 } }); + + const axis = document.querySelector('[data-testid="timeline-y-axis"]') as HTMLElement; + expect(axis.style.height).toBe('250px'); + }); + + it('renders zero count without crashing', async () => { + render(TimelineYAxis, { props: { maxCount: 0, barAreaHeight: 100 } }); + + const axis = document.querySelector('[data-testid="timeline-y-axis"]') as HTMLElement; + expect(axis).not.toBeNull(); + }); +}); diff --git a/frontend/src/lib/document/transcription/TranscriptionSection.svelte.test.ts b/frontend/src/lib/document/transcription/TranscriptionSection.svelte.test.ts new file mode 100644 index 00000000..53d4a2f4 --- /dev/null +++ b/frontend/src/lib/document/transcription/TranscriptionSection.svelte.test.ts @@ -0,0 +1,36 @@ +import { describe, it, expect, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import { page } from 'vitest/browser'; +import TranscriptionSection from './TranscriptionSection.svelte'; + +afterEach(cleanup); + +describe('TranscriptionSection', () => { + it('renders the section heading and textarea', async () => { + render(TranscriptionSection, { props: {} }); + + await expect.element(page.getByRole('heading', { name: /transkription/i })).toBeVisible(); + const textarea = document.querySelector( + 'textarea[name="transcription"]' + ) as HTMLTextAreaElement; + expect(textarea).not.toBeNull(); + }); + + it('hydrates the textarea with the initial transcription value', async () => { + render(TranscriptionSection, { props: { initialTranscription: 'Hello World' } }); + + const textarea = document.querySelector( + 'textarea[name="transcription"]' + ) as HTMLTextAreaElement; + expect(textarea.value).toBe('Hello World'); + }); + + it('renders an empty textarea by default', async () => { + render(TranscriptionSection, { props: {} }); + + const textarea = document.querySelector( + 'textarea[name="transcription"]' + ) as HTMLTextAreaElement; + expect(textarea.value).toBe(''); + }); +}); diff --git a/frontend/src/lib/person/relationship/RelationshipPill.svelte.test.ts b/frontend/src/lib/person/relationship/RelationshipPill.svelte.test.ts new file mode 100644 index 00000000..b8240740 --- /dev/null +++ b/frontend/src/lib/person/relationship/RelationshipPill.svelte.test.ts @@ -0,0 +1,21 @@ +import { describe, it, expect, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import { page } from 'vitest/browser'; +import RelationshipPill from './RelationshipPill.svelte'; + +afterEach(cleanup); + +describe('RelationshipPill', () => { + it('renders the supplied label', async () => { + render(RelationshipPill, { props: { label: 'Vater' } }); + + await expect.element(page.getByText('Vater')).toBeVisible(); + }); + + it('renders an empty string label without crashing', async () => { + render(RelationshipPill, { props: { label: '' } }); + + const span = document.querySelector('span'); + expect(span).not.toBeNull(); + }); +}); diff --git a/frontend/src/lib/shared/primitives/OverflowPillDisplay.svelte.test.ts b/frontend/src/lib/shared/primitives/OverflowPillDisplay.svelte.test.ts new file mode 100644 index 00000000..f9106ce1 --- /dev/null +++ b/frontend/src/lib/shared/primitives/OverflowPillDisplay.svelte.test.ts @@ -0,0 +1,28 @@ +import { describe, it, expect, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import OverflowPillDisplay from './OverflowPillDisplay.svelte'; + +afterEach(cleanup); + +describe('OverflowPillDisplay', () => { + it('renders the +N count', async () => { + render(OverflowPillDisplay, { props: { extraCount: 3 } }); + + const span = document.querySelector('span') as HTMLElement; + expect(span.textContent?.trim()).toBe('+3'); + }); + + it('renders +0 when extraCount is 0', async () => { + render(OverflowPillDisplay, { props: { extraCount: 0 } }); + + const span = document.querySelector('span') as HTMLElement; + expect(span.textContent?.trim()).toBe('+0'); + }); + + it('marks the pill as aria-hidden (decorative)', async () => { + render(OverflowPillDisplay, { props: { extraCount: 5 } }); + + const span = document.querySelector('span') as HTMLElement; + expect(span.getAttribute('aria-hidden')).toBe('true'); + }); +});