diff --git a/frontend/src/lib/document/transcription/TranscriptionEditView.svelte.spec.ts b/frontend/src/lib/document/transcription/TranscriptionEditView.svelte.spec.ts index ec53e911..ad320cd5 100644 --- a/frontend/src/lib/document/transcription/TranscriptionEditView.svelte.spec.ts +++ b/frontend/src/lib/document/transcription/TranscriptionEditView.svelte.spec.ts @@ -3,6 +3,7 @@ import { cleanup, render } from 'vitest-browser-svelte'; import { page, userEvent } from 'vitest/browser'; import TranscriptionEditView from './TranscriptionEditView.svelte'; import { createConfirmService, CONFIRM_KEY } from '$lib/shared/services/confirm.svelte.js'; +import { m } from '$lib/paraglide/messages.js'; afterEach(cleanup); @@ -369,4 +370,67 @@ describe('TranscriptionEditView — mark all reviewed', () => { .toBeDisabled(); resolveMarkAll(); }); + + it('shows error message when onMarkAllReviewed callback rejects', async () => { + const onMarkAllReviewed = vi.fn().mockRejectedValue(new Error('INTERNAL_ERROR')); + renderView({ blocks: [unreviewedBlock1, unreviewedBlock2], onMarkAllReviewed }); + + const btnEl = (await page + .getByRole('button', { name: /Alle als fertig markieren/ }) + .element()) as HTMLButtonElement; + btnEl.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + + await expect.element(page.getByRole('alert')).toBeInTheDocument(); + }); + + it('clears error when dismiss button is clicked', async () => { + const onMarkAllReviewed = vi.fn().mockRejectedValue(new Error('INTERNAL_ERROR')); + renderView({ blocks: [unreviewedBlock1, unreviewedBlock2], onMarkAllReviewed }); + + const btnEl = (await page + .getByRole('button', { name: /Alle als fertig markieren/ }) + .element()) as HTMLButtonElement; + btnEl.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + await expect.element(page.getByRole('alert')).toBeInTheDocument(); + + const dismissEl = (await page + .getByRole('button', { name: m.comp_dismiss() }) + .element()) as HTMLButtonElement; + dismissEl.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + + await expect.element(page.getByRole('alert')).not.toBeInTheDocument(); + }); + + it('clears error on next successful markAllReviewed call', async () => { + const onMarkAllReviewed = vi + .fn() + .mockRejectedValueOnce(new Error('INTERNAL_ERROR')) + .mockResolvedValue(undefined); + renderView({ blocks: [unreviewedBlock1, unreviewedBlock2], onMarkAllReviewed }); + + const btnEl = (await page + .getByRole('button', { name: /Alle als fertig markieren/ }) + .element()) as HTMLButtonElement; + btnEl.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + await expect.element(page.getByRole('alert')).toBeInTheDocument(); + + btnEl.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + + await expect.element(page.getByRole('alert')).not.toBeInTheDocument(); + }); + + it('re-enables button after markAllReviewed failure', async () => { + const onMarkAllReviewed = vi.fn().mockRejectedValue(new Error('INTERNAL_ERROR')); + renderView({ blocks: [unreviewedBlock1, unreviewedBlock2], onMarkAllReviewed }); + + const btnEl = (await page + .getByRole('button', { name: /Alle als fertig markieren/ }) + .element()) as HTMLButtonElement; + btnEl.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + await expect.element(page.getByRole('alert')).toBeInTheDocument(); + + await expect + .element(page.getByRole('button', { name: /Alle als fertig markieren/ })) + .not.toBeDisabled(); + }); });