diff --git a/frontend/e2e/documents.spec.ts b/frontend/e2e/documents.spec.ts index 20c9a976..3f122c29 100644 --- a/frontend/e2e/documents.spec.ts +++ b/frontend/e2e/documents.spec.ts @@ -77,12 +77,49 @@ test.describe('Document detail', () => { }); test.describe('New document', () => { - test('renders the upload form', async ({ page }) => { + test('renders the upload form with file input first', async ({ page }) => { await page.goto('/documents/new'); + await page.waitForSelector('[data-hydrated]'); await expect(page.getByRole('heading', { name: /Neues Dokument/i })).toBeVisible(); - await expect(page.getByLabel('Titel')).toBeVisible(); + // File input comes before the title field in DOM order + const fileInput = page.locator('input[type="file"]'); + const titleInput = page.getByLabel('Titel'); + await expect(fileInput).toBeVisible(); + await expect(titleInput).toBeVisible(); + const fileBox = await fileInput.boundingBox(); + const titleBox = await titleInput.boundingBox(); + expect(fileBox!.y).toBeLessThan(titleBox!.y); await page.screenshot({ path: 'test-results/e2e/document-new.png' }); }); + + test('title field is pre-filled from filename when a file is selected', async ({ page }) => { + await page.goto('/documents/new'); + await page.waitForSelector('[data-hydrated]'); + const PDF_FIXTURE = path.resolve(__dirname, 'fixtures/minimal.pdf'); + const fileInput = page.locator('input[type="file"]'); + await fileInput.setInputFiles({ + name: 'Brief_1965.pdf', + mimeType: 'application/pdf', + buffer: fs.readFileSync(PDF_FIXTURE) + }); + await expect(page.getByLabel('Titel')).toHaveValue('Brief_1965'); + await page.screenshot({ path: 'test-results/e2e/document-new-filename-prefill.png' }); + }); + + test('typed title is not overwritten when a file is selected', async ({ page }) => { + await page.goto('/documents/new'); + await page.waitForSelector('[data-hydrated]'); + await page.getByLabel('Titel').fill('Weihnachtsbrief 1965'); + const PDF_FIXTURE = path.resolve(__dirname, 'fixtures/minimal.pdf'); + const fileInput = page.locator('input[type="file"]'); + await fileInput.setInputFiles({ + name: 'Brief_1965.pdf', + mimeType: 'application/pdf', + buffer: fs.readFileSync(PDF_FIXTURE) + }); + await expect(page.getByLabel('Titel')).toHaveValue('Weihnachtsbrief 1965'); + await page.screenshot({ path: 'test-results/e2e/document-new-title-not-overwritten.png' }); + }); }); test.describe('Document creation', () => { @@ -97,6 +134,21 @@ test.describe('Document creation', () => { await expect(page.getByRole('heading', { name: 'E2E Testbrief' })).toBeVisible(); await page.screenshot({ path: 'test-results/e2e/document-create.png' }); }); + + test('user saves a document with only a file — title comes from filename', async ({ page }) => { + await page.goto('/documents/new'); + await page.waitForSelector('[data-hydrated]'); + const PDF_FIXTURE = path.resolve(__dirname, 'fixtures/minimal.pdf'); + await page.locator('input[type="file"]').setInputFiles({ + name: 'Brief_1965.pdf', + mimeType: 'application/pdf', + buffer: fs.readFileSync(PDF_FIXTURE) + }); + await page.getByRole('button', { name: 'Speichern', exact: true }).click(); + await expect(page).toHaveURL(/\/documents\/[^/]+$/); + await expect(page.getByRole('heading', { name: 'Brief_1965' })).toBeVisible(); + await page.screenshot({ path: 'test-results/e2e/document-create-file-only.png' }); + }); }); test.describe('Document editing', () => { diff --git a/frontend/messages/de.json b/frontend/messages/de.json index e9d4d967..16718738 100644 --- a/frontend/messages/de.json +++ b/frontend/messages/de.json @@ -39,7 +39,7 @@ "form_placeholder_location": "z.B. Berlin, Wien…", "form_label_sender": "Absender", "form_label_receivers": "Empfänger", - "form_label_title": "Titel *", + "form_label_title": "Titel", "form_label_tags": "Schlagworte", "form_label_content": "Inhalt", "form_placeholder_content": "Kurze Beschreibung des Inhalts…", @@ -75,6 +75,7 @@ "doc_file_replace_label": "Neue Datei hochladen", "doc_file_replace_note": "(ersetzt die aktuelle Datei)", "doc_current_file_label": "Aktuelle Datei:", + "doc_more_details": "Weitere Details", "doc_new_heading": "Neues Dokument", "doc_edit_heading": "Bearbeiten", "doc_section_details": "Details", diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 61e34dc9..462dea3b 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -39,7 +39,7 @@ "form_placeholder_location": "e.g. Berlin, Vienna…", "form_label_sender": "Sender", "form_label_receivers": "Recipients", - "form_label_title": "Title *", + "form_label_title": "Title", "form_label_tags": "Tags", "form_label_content": "Content", "form_placeholder_content": "Brief description of the content…", @@ -75,6 +75,7 @@ "doc_file_replace_label": "Upload new file", "doc_file_replace_note": "(replaces the current file)", "doc_current_file_label": "Current file:", + "doc_more_details": "More details", "doc_new_heading": "New document", "doc_edit_heading": "Edit", "doc_section_details": "Details", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index 51d7ebe8..0ae0b91a 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -39,7 +39,7 @@ "form_placeholder_location": "p.ej. Berlín, Viena…", "form_label_sender": "Remitente", "form_label_receivers": "Destinatarios", - "form_label_title": "Título *", + "form_label_title": "Título", "form_label_tags": "Etiquetas", "form_label_content": "Contenido", "form_placeholder_content": "Breve descripción del contenido…", @@ -75,6 +75,7 @@ "doc_file_replace_label": "Subir nuevo archivo", "doc_file_replace_note": "(reemplaza el archivo actual)", "doc_current_file_label": "Archivo actual:", + "doc_more_details": "Más detalles", "doc_new_heading": "Nuevo documento", "doc_edit_heading": "Editar", "doc_section_details": "Detalles", diff --git a/frontend/src/lib/components/document/DescriptionSection.svelte b/frontend/src/lib/components/document/DescriptionSection.svelte index 6d2c13c4..b83ac296 100644 --- a/frontend/src/lib/components/document/DescriptionSection.svelte +++ b/frontend/src/lib/components/document/DescriptionSection.svelte @@ -9,7 +9,8 @@ let { initialDocumentLocation = '', initialSummary = '', titleRequired = false, - suggestedTitle = '' + suggestedTitle = '', + hideTitle = false }: { tags?: string[]; initialTitle?: string; @@ -17,17 +18,12 @@ let { initialSummary?: string; titleRequired?: boolean; suggestedTitle?: string; + hideTitle?: boolean; } = $props(); -let titleValue = $state(untrack(() => initialTitle)); let titleDirty = $state(false); - -$effect(() => { - const suggested = suggestedTitle; - if (suggested && !untrack(() => titleDirty)) { - titleValue = suggested; - } -}); +let titleOverride = $state(untrack(() => initialTitle)); +let titleValue = $derived(titleDirty ? titleOverride : suggestedTitle || titleOverride);