diff --git a/frontend/src/lib/components/TranscriptionPanelHeader.svelte b/frontend/src/lib/components/TranscriptionPanelHeader.svelte new file mode 100644 index 00000000..6b001378 --- /dev/null +++ b/frontend/src/lib/components/TranscriptionPanelHeader.svelte @@ -0,0 +1,94 @@ + + +
+ +
+ + +
+ + +

+ {#if blockCount === 1} + {m.transcription_status_section()} + {:else} + {m.transcription_status_sections({ count: blockCount })} + {/if} + {#if formattedDate} + · {m.transcription_status_last_edited({ time: formattedDate })} + {/if} +

+ + + +
diff --git a/frontend/src/lib/components/TranscriptionPanelHeader.svelte.test.ts b/frontend/src/lib/components/TranscriptionPanelHeader.svelte.test.ts new file mode 100644 index 00000000..c2d12e9d --- /dev/null +++ b/frontend/src/lib/components/TranscriptionPanelHeader.svelte.test.ts @@ -0,0 +1,108 @@ +import { describe, it, expect, vi } from 'vitest'; +import { render } from 'vitest-browser-svelte'; +import { page } from 'vitest/browser'; +import TranscriptionPanelHeader from './TranscriptionPanelHeader.svelte'; + +describe('TranscriptionPanelHeader', () => { + it('should render Lesen and Bearbeiten buttons', async () => { + render(TranscriptionPanelHeader, { + mode: 'read', + hasBlocks: true, + blockCount: 3, + lastEditedAt: null, + onModeChange: () => {}, + onClose: () => {} + }); + + await expect.element(page.getByText('Lesen')).toBeInTheDocument(); + await expect.element(page.getByText('Bearbeiten')).toBeInTheDocument(); + }); + + it('should disable Lesen button when hasBlocks is false', async () => { + render(TranscriptionPanelHeader, { + mode: 'edit', + hasBlocks: false, + blockCount: 0, + lastEditedAt: null, + onModeChange: () => {}, + onClose: () => {} + }); + + const lesenBtn = document.querySelector('[data-testid="mode-read"]') as HTMLButtonElement; + expect(lesenBtn.getAttribute('aria-disabled')).toBe('true'); + }); + + it('should call onModeChange when clicking Bearbeiten', async () => { + const onModeChange = vi.fn(); + render(TranscriptionPanelHeader, { + mode: 'read', + hasBlocks: true, + blockCount: 3, + lastEditedAt: null, + onModeChange, + onClose: () => {} + }); + + const editBtn = document.querySelector('[data-testid="mode-edit"]')!; + editBtn.dispatchEvent(new MouseEvent('click', { bubbles: true })); + expect(onModeChange).toHaveBeenCalledWith('edit'); + }); + + it('should not call onModeChange when clicking disabled Lesen', async () => { + const onModeChange = vi.fn(); + render(TranscriptionPanelHeader, { + mode: 'edit', + hasBlocks: false, + blockCount: 0, + lastEditedAt: null, + onModeChange, + onClose: () => {} + }); + + const readBtn = document.querySelector('[data-testid="mode-read"]')!; + readBtn.dispatchEvent(new MouseEvent('click', { bubbles: true })); + expect(onModeChange).not.toHaveBeenCalled(); + }); + + it('should call onClose when clicking close button', async () => { + const onClose = vi.fn(); + render(TranscriptionPanelHeader, { + mode: 'read', + hasBlocks: true, + blockCount: 3, + lastEditedAt: null, + onModeChange: () => {}, + onClose + }); + + const closeBtn = document.querySelector('[data-testid="panel-close"]')!; + closeBtn.dispatchEvent(new MouseEvent('click', { bubbles: true })); + expect(onClose).toHaveBeenCalled(); + }); + + it('should show singular block count for 1 block', async () => { + render(TranscriptionPanelHeader, { + mode: 'read', + hasBlocks: true, + blockCount: 1, + lastEditedAt: null, + onModeChange: () => {}, + onClose: () => {} + }); + + await expect.element(page.getByText('1 Abschnitt')).toBeInTheDocument(); + }); + + it('should show plural block count for multiple blocks', async () => { + render(TranscriptionPanelHeader, { + mode: 'read', + hasBlocks: true, + blockCount: 5, + lastEditedAt: null, + onModeChange: () => {}, + onClose: () => {} + }); + + await expect.element(page.getByText('5 Abschnitte')).toBeInTheDocument(); + }); +});