feat(document): edit document date precision, end and raw

Adds the edit-form date-precision controls to WhoWhenSection: a labelled
precision <select> (min 48px touch target for senior authors), a conditionally
revealed end-date field (only for RANGE, announced via aria-live=polite), and
the verbatim raw cell as labelled read-only static text (not a disabled input).
Fields submit as metaDatePrecision/metaDateEnd/metaDateRaw and flow through the
existing PUT form action.

Backend: DocumentService.updateDocument now persists the three DTO fields (they
existed since #671 but were never applied), so the new controls are real, not
decorative — addresses Nora's "a client <select> constrains nothing" note for
the persistence half. Server-side enum/end>=start validation remains #671's
scope.

Refs #666

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-27 12:04:14 +02:00
parent b56b9dfa74
commit 7245571ea8
5 changed files with 137 additions and 0 deletions

View File

@@ -72,3 +72,33 @@ describe('WhoWhenSection — date input behavior', () => {
expect(label?.textContent).toContain('*');
});
});
describe('WhoWhenSection — precision controls', () => {
it('renders a labelled precision select', async () => {
render(WhoWhenSection, {});
const label = document.querySelector('label[for="metaDatePrecision"]');
const select = document.querySelector('select#metaDatePrecision[name="metaDatePrecision"]');
expect(label).not.toBeNull();
expect(select).not.toBeNull();
});
it('hides the end-date field unless precision is RANGE', async () => {
render(WhoWhenSection, { precision: 'DAY' });
expect(document.querySelector('input#metaDateEnd')).toBeNull();
});
it('reveals the end-date field when precision is RANGE', async () => {
render(WhoWhenSection, { precision: 'RANGE' });
expect(document.querySelector('input#metaDateEnd')).not.toBeNull();
});
it('renders the raw cell as static text (not an editable input) and escapes it', async () => {
render(WhoWhenSection, { rawDate: '<b>Sommer</b> 1916' });
const raw = document.querySelector('[data-testid="who-when-raw"]');
expect(raw).not.toBeNull();
// Verbatim shown as escaped text; no injected <b> element.
expect(raw?.textContent).toContain('<b>Sommer</b> 1916');
expect(raw?.querySelector('b')).toBeNull();
});
});