feat(lesereisen): implement lesereisen
All checks were successful
CI / Unit & Component Tests (push) Successful in 4m34s
CI / OCR Service Tests (push) Successful in 27s
CI / Backend Unit Tests (push) Successful in 5m1s
CI / fail2ban Regex (push) Successful in 47s
CI / Semgrep Security Scan (push) Successful in 23s
CI / Compose Bucket Idempotency (push) Successful in 1m11s
All checks were successful
CI / Unit & Component Tests (push) Successful in 4m34s
CI / OCR Service Tests (push) Successful in 27s
CI / Backend Unit Tests (push) Successful in 5m1s
CI / fail2ban Regex (push) Successful in 47s
CI / Semgrep Security Scan (push) Successful in 23s
CI / Compose Bucket Idempotency (push) Successful in 1m11s
This commit was merged in pull request #787.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page, userEvent } from 'vitest/browser';
|
||||
import { m } from '$lib/paraglide/messages.js';
|
||||
import GeschichteEditor from './GeschichteEditor.svelte';
|
||||
|
||||
const personFactory = (id: string, displayName: string) => ({
|
||||
@@ -8,19 +9,9 @@ const personFactory = (id: string, displayName: string) => ({
|
||||
firstName: displayName.split(' ')[0],
|
||||
lastName: displayName.split(' ').slice(1).join(' ') || displayName,
|
||||
displayName,
|
||||
personType: 'PERSON' as const
|
||||
});
|
||||
|
||||
const docFactory = (id: string, title: string, date = '1882-01-01') => ({
|
||||
id,
|
||||
title,
|
||||
documentDate: date,
|
||||
originalFilename: `${title}.pdf`,
|
||||
status: 'UPLOADED' as const,
|
||||
metadataComplete: false,
|
||||
scriptType: 'UNKNOWN' as const,
|
||||
createdAt: '2024-01-01T00:00:00',
|
||||
updatedAt: '2024-01-01T00:00:00'
|
||||
personType: 'PERSON' as const,
|
||||
familyMember: false,
|
||||
provisional: false
|
||||
});
|
||||
|
||||
const draftFactory = (overrides: Record<string, unknown> = {}) => ({
|
||||
@@ -28,8 +19,9 @@ const draftFactory = (overrides: Record<string, unknown> = {}) => ({
|
||||
title: 'Existing draft',
|
||||
body: '<p>Hello world</p>',
|
||||
status: 'DRAFT' as const,
|
||||
type: 'STORY' as const,
|
||||
persons: [],
|
||||
documents: [],
|
||||
items: [],
|
||||
createdAt: '2024-01-01T00:00:00',
|
||||
updatedAt: '2024-01-01T00:00:00',
|
||||
...overrides
|
||||
@@ -63,6 +55,22 @@ describe('GeschichteEditor — title-required guard', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('GeschichteEditor — onSubmit rejects on failure', () => {
|
||||
it('catches a rejecting onSubmit (no unhandled rejection) and stays editable', async () => {
|
||||
// Contract: onSubmit rejects on failure. Without the catch in save(), this
|
||||
// click would surface as an unhandled promise rejection and fail the run.
|
||||
const onSubmit = vi.fn().mockRejectedValue(new Error('save failed'));
|
||||
render(GeschichteEditor, { geschichte: draftFactory(), onSubmit });
|
||||
|
||||
await userEvent.click(page.getByRole('button', { name: 'Entwurf speichern' }));
|
||||
await vi.waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1));
|
||||
|
||||
// Editor still functional — a second save attempt goes through
|
||||
await userEvent.click(page.getByRole('button', { name: 'Entwurf speichern' }));
|
||||
await vi.waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(2));
|
||||
});
|
||||
});
|
||||
|
||||
describe('GeschichteEditor — save bar adapts to status', () => {
|
||||
it('renders DRAFT mode buttons when no geschichte prop is supplied', async () => {
|
||||
render(GeschichteEditor, { onSubmit: vi.fn() });
|
||||
@@ -93,14 +101,6 @@ describe('GeschichteEditor — pre-fill', () => {
|
||||
await expect.element(page.getByText('Franz Raddatz')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders initial documents as chips', async () => {
|
||||
render(GeschichteEditor, {
|
||||
initialDocuments: [docFactory('d1', 'Brief von Eugenie')],
|
||||
onSubmit: vi.fn()
|
||||
});
|
||||
await expect.element(page.getByText(/Brief von Eugenie/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('populates the title input from a geschichte prop', async () => {
|
||||
render(GeschichteEditor, {
|
||||
geschichte: draftFactory({ title: 'My existing story' }),
|
||||
@@ -154,11 +154,10 @@ describe('GeschichteEditor — onSubmit payload', () => {
|
||||
expect(onSubmit.mock.calls[0][0].status).toBe('PUBLISHED');
|
||||
});
|
||||
|
||||
it('passes the personIds and documentIds from initial props through onSubmit', async () => {
|
||||
it('passes personIds from initial props through onSubmit', async () => {
|
||||
const onSubmit = vi.fn().mockResolvedValue(undefined);
|
||||
render(GeschichteEditor, {
|
||||
initialPersons: [personFactory('p1', 'Franz Raddatz')],
|
||||
initialDocuments: [docFactory('d1', 'Brief A')],
|
||||
onSubmit
|
||||
});
|
||||
|
||||
@@ -171,6 +170,38 @@ describe('GeschichteEditor — onSubmit payload', () => {
|
||||
expect(onSubmit).toHaveBeenCalledTimes(1);
|
||||
const payload = onSubmit.mock.calls[0][0];
|
||||
expect(payload.personIds).toEqual(['p1']);
|
||||
expect(payload.documentIds).toEqual(['d1']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GeschichteEditor — story document panel (#795)', () => {
|
||||
it('shows the document panel with the story items when editing an existing story', async () => {
|
||||
render(GeschichteEditor, {
|
||||
geschichte: draftFactory({
|
||||
items: [
|
||||
{
|
||||
id: 'i1',
|
||||
position: 10,
|
||||
document: {
|
||||
id: 'd1',
|
||||
title: 'Brief von Eugenie',
|
||||
datePrecision: 'DAY' as const,
|
||||
receiverCount: 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}),
|
||||
onSubmit: vi.fn().mockResolvedValue(undefined)
|
||||
});
|
||||
|
||||
await expect
|
||||
.element(page.getByRole('heading', { name: m.geschichte_documents_heading() }))
|
||||
.toBeInTheDocument();
|
||||
await expect.element(page.getByText('Brief von Eugenie')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('hides the document panel when no geschichte is set (creation flow)', async () => {
|
||||
render(GeschichteEditor, { onSubmit: vi.fn() });
|
||||
|
||||
expect(document.body.textContent).not.toContain(m.geschichte_documents_heading());
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user