Three admin/index pages (groups/tags/users) — each renders a single
"Wähle X aus der Liste" prompt for the desktop split-view layout.
AuthHeader: brand link href + wordmark.
PersonsEmptyState: empty heading + explanation text.
6 tests across five small files.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Listbox label, empty-state placeholder, create-new escape hatch with
noopener target, populated list, default aria-selected on first item,
life-date range visibility, position fallback when clientRect is null,
positioning from clientRect.
8 tests covering ~25 branches.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tag link href, document-count visibility branch, color-dot at depth 0
vs deeper, aria-current matrix, children list rendering, collapse-map
hides children, expand/collapse toggle for nodes with children.
9 tests covering ~30 branches in the recursive tree-node component.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backfill cards rendered, both backfill buttons enabled by default,
no success banner before any action. Smoke-level coverage of the
admin maintenance page.
5 tests covering basic render branches.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Year divider rendering, distinct-year branch, no-duplicate consecutive
years, no-divider for documents without documentDate, canWrite-gated
new-document link with senderId-only and senderId+receiverId href
variants.
7 tests covering ~20 branches.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All-sections render when full permissions, users/invites hidden when
!canManageUsers, groups hidden when !canManagePermissions, tags hidden
when !canManageTags, system/ocr hidden when !canRunMaintenance,
flyout closed by default.
6 tests covering ~30 branches in the permission matrix.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Hero state when no senderId set, results card when senderId set,
SinglePersonHintBar gating on senderId × !receiverId, empty-results
message branch.
5 tests covering ~15 branches in the orchestrator.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
One bar per filled bucket, singular vs plural aria-label, aria-pressed
matrix, drag-window visibility tied to isDragging, onbarclick callback,
minimum-height handling for zero-count buckets.
8 tests covering ~25 branches.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dialog with bell label, empty state vs populated list, mark-all-read
visibility branch, REPLY vs MENTION text, unread-dot rendering, all
three callback wirings (onMarkRead, onMarkAllRead, onClose).
10 tests covering the notification dropdown surface.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
register page (350 lines): hero render when no codeError, NO_INVITE_CODE
vs other-codeError card branches, form hidden when codeError set,
back-to-login link, form section rendering, prefill hydration of
firstName/lastName/email, prefill-hint visibility branch, hidden
code input with code-null fallback.
admin/users/new: heading, three card sections, group checkboxes
rendered, form-error banner branch, cancel link, submit button.
17 tests across two pages.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Brand link, four primary nav links, admin link gated on isAdmin,
hamburger menu open/close state via aria-expanded. Mocks $app/state
so the page URL drives the active-route highlighting.
6 tests, ~30 branches.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Title, all four section headings, secure Wikipedia link rel
attributes, five rule cards rendered, four klaerung chips rendered.
7 tests covering the static help page.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Heading with email, three card sections (profile/groups/password),
success vs error form banners, group preselection from editUser.groups,
cancel link, delete button. Mocks the confirm service.
7 tests, ~25 branches.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TimelineControls: empty render when neither flag is set, reset button
gated on isZoomed, clear button gated on hasSelection, both-on, both
callback wirings.
TimelineXAxis: empty filled → no ticks, populated → ticks render,
omit-year branch when all buckets share a year, show-year branch
across multiple years, length-4 bucket-string fallback.
11 tests across two timeline primitives.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UserPasswordSection: input rendering, type=password attribute,
required-prop propagation in both directions.
CorrespondenzFilterControls: dual date label rendering, both DateInput
ids, value hydration from fromDate/toDate, change-event smoke check.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four tests: discard link href, save button label, form attribute
wiring, formaction. Small focused component.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
enrich/done: heading, body, both CTA links.
documents/bulk-edit: empty-store onMount redirect to /documents,
loading spinner during in-flight fetch, error banner on backend error
code, error banner on fetch rejection. Mocks fetch via vi.spyOn so the
async branches are exercised without a real backend.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BackButton: visible vs aria-only label branches, custom class
application, history.back() click handler.
OverflowPillButton: +N pill render, aria-expanded matrix
(closed default → open after click), per-person link rendering with
correct href, Escape closes the dropdown.
Both are reused widely; their coverage closes the line and function gap
left after the DocumentTopBar split inflated the denominator.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sixteen tests covering the four-column drawer: details column always
renders, persons column branches (no-persons placeholder vs sender
vs receivers), receiver overflow + show-all toggle, tags column
branches (placeholder vs anchor list with /?tag href encoding),
geschichten column visibility (hidden by default, shown for
canBlogWrite, attach link gated on canBlogWrite + documentId, list
rendering, show-all overflow), inferred-relationship pill on the
single-receiver branch.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
admin/groups/new: heading, both permission group renderings (4 standard
+ 4 administrative checkboxes), form-error banner branch, cancel link
href, submit button form-attribute wiring, name input requiredness.
Mocks $app/navigation so beforeNavigate doesn't crash the test runner.
enrich/+: heading, empty placeholder vs populated count + start CTA,
start CTA href derived from documents[0].id, per-row title rendering,
bulk-select checkbox gated on canWrite.
16 tests across two files.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
users/[id]: full-name derivation across all four branches
(both/firstName-only/lastName-only/email fallback), avatar initials
matrix, email/contact row visibility tied to data presence.
admin/ocr/global: heading + back link, runs prop pass-through,
defensive default for missing history fields.
geschichten/[id]: title rendering, author full-name vs email fallback
vs null, publishedAt suffix conditional, persons and documents sections
gated on array length, edit/delete actions gated on canBlogWrite. Mocks
the confirm service since it requires a ConfirmDialog mounted in layout.
26 tests across three files.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PersonEditForm: PERSON vs INSTITUTION/GROUP visibility matrix (firstName,
title, alias, birth/deathYear toggle), lastName label switch, prop
hydration of all populated fields, fallback to PERSON for unknown type,
empty-string handling for null fields. 10 tests, ~30 branches.
SegmentationTrainingCard: trainingInfo null vs populated, block count
display, button disabled-state matrix (training × tooFewBlocks ×
serviceDown), too-few-blocks and service-down hints, success message
after a mocked fetch, training history heading. 10 tests, ~25 branches.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Third Phase 5 split. The desktop action buttons — transcribe,
transcribe-stop, edit link, download link — become their own component
with a focused props interface (documentId, canWrite, isPdf,
transcribeMode bindable, filePath, originalFilename, fileUrl).
TDD: 8 tests covering empty render, transcribe button gating
(canWrite × isPdf × transcribeMode), stop-transcribe rendering, edit
link with documentId href, download link with filePath gating, all
hidden when in transcribe mode. After the test was red the component
was created.
DocumentTopBar dropped from 303 lines to 166. The orchestrator now
just composes BackButton, DocumentTopBarTitle, PersonChipRow,
OverflowPillButton, the details toggle, DocumentTopBarActions,
DocumentMobileMenu, and DocumentMetadataDrawer — each visual region
named in one or two words.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Second step of the Phase 5 split. The kebab dropdown — including
clickOutside handling and its own mobileMenuOpen state — becomes its
own component named after its visual region. The mobile snippet
duplication inside DocumentTopBar is removed; the component owns its
mobile-specific markup.
TDD: DocumentMobileMenu.svelte.test.ts (7 tests) was red first. The
component then made it green (kebab trigger, dropdown open/close on
click, transcribe button gated on canWrite × isPdf × !transcribeMode,
download link gated on filePath). DocumentTopBar wraps the new
component in a md:hidden div so responsive behaviour is unchanged.
Existing 18-test DocumentTopBar suite still passes.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
First step of the Phase 5 split plan from issue #496. The 14-line title
+ date block becomes its own component named after the visual region.
TDD red/green: DocumentTopBarTitle.svelte.test.ts written first
(7 tests covering title, originalFilename fallback, empty-string
fallback, short-date rendering, no-date branch, title attribute
sourcing). After the test was red the component was created.
DocumentTopBar.svelte updated to use it; the existing 18-test suite
still passes.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eighteen tests covering the user-observable matrix without yet splitting
the component (Phase 5 of the plan): title vs originalFilename fallback,
short-date rendering and absence, transcribe-button gating
(canWrite × isPdf × transcribeMode), edit-link gating, download-link
gating on filePath, kebab-menu visibility on (canWrite & isPdf) || filePath,
details drawer toggle, mobile menu open/close.
The 83 raw branches in the source map mostly to combinations of the
above flags — each test isolates one branch. Per Sara's guidance the
test names read as sentences and verify what the user sees, not internal
state.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each status (active / exhausted / revoked / expired) maps to a distinct
visual treatment via statusColor() — one focused test per branch
asserts the correct background class on a tbody element so the test
verifies user-observable behaviour rather than the internal switch.
Also covers: empty placeholder, loadError banner, filter chip
selection state, new-invite form toggle on button click, createError
message visibility inside the open form, created-invite success card
with shareable URL, revoke button gating to active invites only,
unlimited-uses display, no-expiry display.
16 tests, ~50 branches covered.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
empty state vs. populated, zoom controls visibility tied to node count,
URL ?focus= preselection (matching id selects, missing id does not),
zoom-out clamping safety. $app/state mocked at module boundary so the
test can drive page.url and page.data.canWrite without a SvelteKit
runtime.
Six tests focused on user-observable behaviour — one logical behaviour
per test (Sara's guidance).
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DocumentViewer: loading / error / no-scan / image rendering branches.
filePath conditionally drives the direct-download link in the error
state; fileUrl + non-PDF contentType drives the <img> render.
PersonalInfoForm: default render, prop hydration including the German
date conversion path, success/error banner branches, form action wiring.
profile/+page: notification-checkbox enabled/disabled depending on
hasEmail, no-email hint visibility, prefsSuccess/prefsError banners,
fallback when notificationPrefs is null.
20 tests across three files.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PersonDocumentList: empty/populated, year-range derivation across
no-date/single-year/multi-year inputs, sort toggle visibility (>1 doc),
sort-direction round trip, preview-limit + show-more expansion,
title→originalFilename fallback, no-date and no-location branches.
persons/new: PERSON vs INSTITUTION/GROUP visibility matrix
(firstName/alias/life-year fields toggle), lastName label switching
between Vorname/Nachname/Name, form-error banner, prior-form hydration,
cancel link href, fallback to PERSON for unknown personType.
24 tests across two files, hitting the 32+28 = 60 branches at the top
of the issue's leverage list.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CorrespondentSuggestionsDropdown: empty list still renders the static
heading and 'Alle Korrespondenten' row, populated rows when not loading,
loading hides correspondent rows, initials fallback (lastName-only when
firstName is null), click + keyboard selection, Escape closes.
PersonCard: full matrix of conditional UI — title visibility for PERSON
vs non-PERSON, avatar initials path (firstName+lastName vs lastName-only
fallback), PersonTypeBadge presence for non-PERSON types, alias, life
dates, notes, and the canWrite=true/false branches that gate the edit
link (Nora's authorization-rendering rule).
21 tests covering ~50 branches.
Refs #496.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>