diff --git a/frontend/src/routes/admin/system/+page.svelte b/frontend/src/routes/admin/system/+page.svelte index aa734abf..f7a61332 100644 --- a/frontend/src/routes/admin/system/+page.svelte +++ b/frontend/src/routes/admin/system/+page.svelte @@ -1,6 +1,7 @@ + +
+

{m.admin_system_import_heading()}

+

{m.admin_system_import_description()}

+ + {#if importStatus?.state === 'RUNNING'} +
+ +
+

{importStatus.processed}

+

+ {m.admin_system_import_status_running()} +

+
+
+ {:else if importStatus?.state === 'DONE'} +
+

{importStatus.processed}

+

+ {m.admin_system_import_status_done_label()} +

+

{m.admin_system_import_status_done()}

+
+ + {:else if importStatus?.state === 'FAILED'} +

+ {importStatus.statusCode === 'IMPORT_FAILED_NO_SPREADSHEET' + ? m.admin_system_import_failed_no_spreadsheet() + : m.admin_system_import_failed_internal()} +

+ + {:else} + {#if importStatus !== null} +

{m.admin_system_import_status_idle()}

+ {/if} + + {/if} +
diff --git a/frontend/src/routes/admin/system/ImportStatusCard.svelte.test.ts b/frontend/src/routes/admin/system/ImportStatusCard.svelte.test.ts new file mode 100644 index 00000000..1c98fe99 --- /dev/null +++ b/frontend/src/routes/admin/system/ImportStatusCard.svelte.test.ts @@ -0,0 +1,71 @@ +import { describe, it } from 'vitest'; +import { render } from 'vitest-browser-svelte'; +import { expect } from '@vitest/browser/context'; +import ImportStatusCard from './ImportStatusCard.svelte'; + +type ImportStatus = { + state: 'IDLE' | 'RUNNING' | 'DONE' | 'FAILED'; + statusCode: string; + message: string; + processed: number; + startedAt: string | null; +}; + +const makeStatus = (overrides: Partial = {}): ImportStatus => ({ + state: 'IDLE', + statusCode: 'IMPORT_IDLE', + message: '', + processed: 0, + startedAt: null, + ...overrides +}); + +describe('ImportStatusCard', () => { + it('shows spinner while state is RUNNING', async () => { + const { getByTestId } = render(ImportStatusCard, { + props: { + importStatus: makeStatus({ state: 'RUNNING', statusCode: 'IMPORT_RUNNING', processed: 3 }), + ontrigger: () => {} + } + }); + + await expect.element(getByTestId('spinner')).toBeVisible(); + }); + + it('shows processed count at text-base while RUNNING', async () => { + const { getByText } = render(ImportStatusCard, { + props: { + importStatus: makeStatus({ state: 'RUNNING', statusCode: 'IMPORT_RUNNING', processed: 7 }), + ontrigger: () => {} + } + }); + + await expect.element(getByText('7')).toBeVisible(); + }); + + it('shows processed count while DONE', async () => { + const { getByText } = render(ImportStatusCard, { + props: { + importStatus: makeStatus({ state: 'DONE', statusCode: 'IMPORT_DONE', processed: 42 }), + ontrigger: () => {} + } + }); + + await expect.element(getByText('42')).toBeVisible(); + }); + + it('shows no-spreadsheet message when statusCode is IMPORT_FAILED_NO_SPREADSHEET', async () => { + const { getByText } = render(ImportStatusCard, { + props: { + importStatus: makeStatus({ + state: 'FAILED', + statusCode: 'IMPORT_FAILED_NO_SPREADSHEET', + message: 'Keine Tabellendatei...' + }), + ontrigger: () => {} + } + }); + + await expect.element(getByText('No spreadsheet file found.')).toBeVisible(); + }); +});