Commit Graph

13 Commits

Author SHA1 Message Date
Marcel
f6bbb08b26 test: cover PersonTypeBadge, ExpandableText, PersonChipRow branches
PersonTypeBadge: one test per switch arm (INSTITUTION, GROUP, UNKNOWN)
plus the two no-render branches (unrecognised type, empty type).

ExpandableText: clamp detection, toggle visibility logic, expand →
collapse round-trip, default maxLines fallback.

PersonChipRow: sender-only, sender+arrow, abbreviated naming, max-two
visible receivers, +N overflow pill presence/absence, receivers-only
case (no sender → no arrow).

19 tests across three files. Each file uses afterEach(cleanup) and
queries via getByRole/getByText so tests stay decoupled from CSS.

Refs #496.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 21:50:28 +02:00
Marcel
273bf5e5fa test(person): add PersonChip browser tests
Covers the abbreviated/full name branches, the firstName-null fallback
path, link href derivation from person id, initials rendering, and the
deterministic avatar palette colour. Six tests, six branches hit.

Refs #496.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 21:50:28 +02:00
Marcel
cd1c0b210e test(typeahead): note resetKey smoke-test limitation in spec comment
Some checks failed
CI / Unit & Component Tests (push) Failing after 4m19s
CI / OCR Service Tests (push) Successful in 42s
CI / Backend Unit Tests (push) Failing after 3m20s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 14:27:24 +02:00
Marcel
a239c16c31 fix(documents): sync filter display state with URL on navigation
Three root causes prevented filters from reflecting the URL after SvelteKit
client-side navigation:

1. +page.server.ts now resolves sender/receiver display names in parallel with
   the document search (UUID validation + silent 404 drop), so initialSenderName
   / initialReceiverName land in server data ready for the UI to use.

2. +page.svelte passes initialSenderName, initialReceiverName, and navKey
   (incremented via untrack on every navigation) down to SearchFilterBar.
   The untrack() prevents the effect from re-running due to its own navKey write.

3. SearchFilterBar forwards navKey as resetKey to each PersonTypeahead, which
   already had a void resetKey guard added in the previous commit.

Together these ensure that after navigating to /documents?senderId=<uuid> the
typeahead shows the person's display name, and clicking × reset clears it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 14:27:24 +02:00
Marcel
8a8205ad8d fix(person-typeahead): add resetKey prop to clear term on navigation reset
When the user types in the sender/receiver typeahead without selecting a
person and then clicks ×-reset (navigating back to /documents), the
manually-typed term was not cleared because initialName stayed '' between
navigations — the existing $effect tracking initialName never fired.

Adding `resetKey` (incremented by the page on every navigation) forces
the effect to re-run via `void resetKey`, clearing searchTerm=initialName
even when initialName is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 14:27:24 +02:00
Marcel
0c765d8112 fix(tests): fix 13 pre-existing vitest-browser spec failures
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 3m54s
CI / OCR Service Tests (pull_request) Successful in 33s
CI / Backend Unit Tests (pull_request) Failing after 3m13s
CI / Unit & Component Tests (push) Failing after 3m48s
CI / OCR Service Tests (push) Successful in 39s
CI / Backend Unit Tests (push) Failing after 3m24s
Fixes all remaining failing tests in the browser project. Root cause in
every case: Playwright CDP-based clicks/keyboard events do not reliably
trigger Svelte 5 onclick/onkeydown handlers. Pattern applied throughout:

- Buttons / result items: native `.element().click()` or
  `dispatchEvent(new MouseEvent('click', { bubbles: true }))`
- Keyboard events: `dispatchEvent(new KeyboardEvent('keydown', { key }))`
  on the target DOM element
- TipTap selection: `element.focus()` + Selection API +
  `document.dispatchEvent(new Event('selectionchange'))`
- ProseMirror focus for onFocus: `dispatchEvent(new FocusEvent('focus'))`

Also fixes pre-existing content/logic issues found during analysis:
- ChronikErrorCard, BulkDropZone, CorrespondenzHero: stale i18n strings
  and wrong ARIA role (combobox not textbox)
- RichtlinienRuleCard: beide beispielInput + beispielOutput required for
  arrow to render; querySelectorAll to get last code element
- admin/system/page: vi.unstubAllGlobals() in afterEach; strict-mode
  heading selector; per-call mockResolvedValueOnce for dual-card page
- DocumentList: add total prop + result count paragraph (test relied on it)
- PersonTypeahead keyboard navigation: pressKey() helper with native
  KeyboardEvent dispatch replaces userEvent.keyboard()
- PersonMultiSelect: native element clicks for result selection and
  chip removal; keydown dispatch on result div for Enter key test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 13:15:54 +02:00
Marcel
a1b89670c0 docs(legibility): add 18 per-domain README.md files (DOC-6)
Backend (9): document, person, tag, user, geschichte, notification,
ocr, audit, dashboard.
Frontend (8): document, person, tag, user, geschichte, notification,
ocr, shared.
OCR service (1): ocr-service/README.md.

Each README covers: what the domain owns, explicit non-ownership,
public surface (verified by grep against the codebase), internal
layout, and cross-domain dependencies.

Closes #400
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 07:36:38 +02:00
Marcel
0f613e49ce refactor(shared): move FieldLabelBadge primitive to shared/primitives
FieldLabelBadge is a generic UI primitive (additive/replace badge used in form
field labels). It lived in the document domain but was already imported by
PersonTypeahead (person domain), creating a person → document coupling.
Moving it to shared/primitives eliminates that cross-domain dependency.

Refs #410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 18:09:01 +02:00
Marcel
507fa088fd refactor(document): move statusDotClass and statusLabel to document domain
These functions describe DocumentStatus display logic (dot colours, readable
labels) and belong in the document domain. They were incorrectly placed in
personFormat.ts. Moving them to documentStatusLabel.ts removes the
person → document dependency and prepares the codebase for the
boundaries/dependencies ESLint rule.

Refs #410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 18:09:01 +02:00
Marcel
567612761d refactor: move lib-root files to lib/shared/ and finalize domain structure
- Move api.server.ts, errors.ts, types.ts, utils.ts, relativeTime.ts to lib/shared/
- Move person relationship components to lib/person/relationship/
- Move Stammbaum components to lib/person/genealogy/
- Move HelpPopover to lib/shared/primitives/
- Update all import paths across routes, specs, and lib files
- Update vi.mock() paths in server-project test files
- Remove now-empty legacy directories (components/, hooks/, server/, etc.)
- Update vite.config.ts coverage include paths for new structure
- Update frontend/CLAUDE.md to reflect domain-based lib/ layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:53:31 +02:00
Marcel
efcc347c00 refactor: move shared components to lib/shared/ sub-packages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:40:14 +02:00
Marcel
d6db7a07bd refactor: move shared utilities to lib/shared/ sub-packages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:35:15 +02:00
Marcel
d5d36e661a refactor: move person domain components and utils to lib/person/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:26:21 +02:00