Commit Graph

204 Commits

Author SHA1 Message Date
Marcel
aaa9286612 feat(comments): warn before deleting annotation with comments
Show a native confirm() dialog when the annotation has ≥1 comment,
listing the count so the user knows what will be lost.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 11:20:55 +01:00
Marcel
646674b06a fix(comments): open panel on annotation creation and enlarge comment count pill
- Auto-open AnnotationCommentPanel immediately after drawing a new annotation
- Move comment count pill to bottom-right corner (was centered at bottom)
- Increase pill size: font 11px bold, padding 2px 6px, min-width 20px, drop shadow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 11:11:36 +01:00
Marcel
1070e6e9ec feat(comments): add CommentThread, annotation panel, Diskussion section, and i18n keys
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 11:02:38 +01:00
Marcel
3e5d296b09 feat(comments): add CommentController and CreateCommentDTO (green)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 10:36:33 +01:00
Marcel
ee49bac2ef test(comments): add failing CommentControllerTest (red)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 10:34:47 +01:00
Marcel
48040dc7e4 feat(comments): add DocumentComment entity, CommentRepository, and CommentService (green)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 10:33:39 +01:00
Marcel
83e5a1fde5 test(comments): add failing CommentServiceTest and V12 migration (red)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 10:32:11 +01:00
Marcel
37f5c3d005 feat(db): add migration to grant ANNOTATE_ALL to existing admin groups
All checks were successful
CI / Unit & Component Tests (pull_request) Successful in 2m27s
CI / Backend Unit Tests (pull_request) Successful in 2m12s
CI / E2E Tests (pull_request) Successful in 23m43s
CI / Unit & Component Tests (push) Successful in 2m28s
CI / Backend Unit Tests (push) Successful in 2m15s
CI / E2E Tests (push) Successful in 22m17s
Covers existing deployments where the Administrators group was created
before DataInitializer started including ANNOTATE_ALL.

Refs #40
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 08:52:32 +01:00
Marcel
eb8bcdb426 fix(frontend): make annotation delete button fully opaque
Some checks failed
CI / Backend Unit Tests (pull_request) Successful in 2m15s
CI / E2E Tests (pull_request) Successful in 22m58s
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 2m29s
Replace opacity: 0.3 on the annotation container with an rgba
background so child elements (the × button) are not affected by
the parent's opacity and render at full opacity.

Refs #40
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 08:49:52 +01:00
Marcel
05f3ce687f test(e2e): rewrite PDF viewer and annotation beforeAll to use API calls
Some checks failed
CI / E2E Tests (pull_request) Waiting to run
CI / Unit & Component Tests (push) Successful in 2m27s
CI / Backend Unit Tests (push) Successful in 2m17s
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (push) Has started running
- Replace UI-based document setup in beforeAll hooks with direct API
  calls via Playwright's request fixture — avoids the 90s timeout from
  navigating + uploading through the Docker dev server
- Fix non-PDF test: create a file-less document in beforeAll instead of
  relying on seed data that may not exist
- Share annotationDocId across describe blocks so the read-only user
  test can navigate to a known PDF document
- Add annotation visibility check before enabling annotate mode in the
  delete test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 08:26:59 +01:00
Marcel
06e846f2f8 fix(frontend): use closest() to skip pointer capture on annotation children
When a child element inside an annotation div (e.g. the delete button)
was clicked, the AnnotationLayer's pointerdown handler would call
setPointerCapture, preventing the child's click event from firing.
Using closest('[data-annotation]') instead of checking dataset.annotation
on the target directly fixes delete buttons inside annotation elements.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 08:26:26 +01:00
Marcel
ea1c097ae0 fix(e2e): activate e2e profile in dev mode and create reader user idempotently
- Add e2e to the dev Maven profile's spring.profiles.active so
  DataInitializer always runs when developing/testing locally
- Create the reader test user independently of the person-seed guard
  so it survives restarts where seed data already exists
- Set SPRING_PROFILES_ACTIVE=dev,e2e in docker-compose backend service

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 08:25:54 +01:00
Marcel
b45ec744b2 feat: add PDF annotation feature (#40)
Backend:
- Add ANNOTATE_ALL permission
- Add ANNOTATION_NOT_FOUND and ANNOTATION_OVERLAP error codes
- V10 migration: document_annotations table with page/rect/color/owner
- DocumentAnnotation entity, AnnotationRepository, CreateAnnotationDTO
- AnnotationService: overlap detection (rectangle intersection), ownership enforcement on delete
- AnnotationController: GET (authenticated), POST/DELETE (ANNOTATE_ALL)
- 15 new tests (AnnotationServiceTest, AnnotationControllerTest) — TDD red/green

Frontend:
- AnnotationLayer.svelte: pointer-event drawing, colored rect overlays, delete buttons
- PdfViewer.svelte: annotate toggle, color picker, loads/saves/deletes annotations via API
- Disabled annotate button with tooltip for users without ANNOTATE_ALL
- canAnnotate exposed from layout server, passed to PdfViewer
- errors.ts + de/en/es translations for new error codes
- 3 new unit tests for AnnotationLayer — TDD red/green

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:27:21 +01:00
Marcel
ca5726e7c3 fix(frontend): zoom buttons now re-render immediately (#39)
Some checks failed
CI / Unit & Component Tests (pull_request) Successful in 4m42s
CI / Backend Unit Tests (pull_request) Successful in 2m18s
CI / E2E Tests (pull_request) Failing after 13m15s
CI / Unit & Component Tests (push) Successful in 2m20s
CI / Backend Unit Tests (push) Successful in 2m11s
CI / E2E Tests (push) Failing after 13m25s
scale was only read inside the async renderPage function, so Svelte 5
never tracked it as a reactive dependency of the effect. Reading scale
synchronously in the effect condition registers it as a dependency and
triggers a re-render on every zoom change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 22:45:25 +01:00
Marcel
0ef81e20f6 devops: add rebuild-frontend.sh script
Some checks are pending
CI / Unit & Component Tests (push) Successful in 2m36s
CI / Backend Unit Tests (push) Successful in 2m3s
CI / E2E Tests (push) Has started running
Stops the container, removes the stale node_modules volume, and
rebuilds the image. Run this after adding or updating npm dependencies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 22:39:53 +01:00
Marcel
1ad8fffd1b fix(frontend): load pdfjs-dist dynamically to avoid SSR crash (#39)
Static import of pdfjs-dist fails during SSR because DOMMatrix and
other browser globals are unavailable in Node.js. Move the import into
onMount so it only ever executes in the browser. A plain pdfjsLib
variable holds the module; a $state boolean pdfjsReady triggers the
load-document effect once the library is available.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 22:39:40 +01:00
Marcel
5fb6a1eec0 feat(frontend): replace iframe with PDF.js viewer (#39)
- Install pdfjs-dist v5 and add optimizeDeps pre-bundle config
- New PdfViewer.svelte component: renders each page on a <canvas> with
  correct device-pixel-ratio scaling, overlays a text layer (enables
  text selection; foundation for annotations in #40), prev/next
  navigation, zoom controls, and lazy page rendering (only current ±1
  pre-fetched — avoids freezing on multi-page documents)
- Replace the <iframe> in documents/[id]/+page.svelte with PdfViewer;
  image attachments continue to use <img>; detection now uses
  doc.contentType instead of filename extension
- Unit tests for navigation controls and page counter (pdfjs mocked)
- E2E tests: PDF renders as canvas (not iframe), nav controls visible,
  image fallback stays as <img>; minimal.pdf fixture for upload tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 19:10:02 +01:00
Marcel
4f69457a68 fix(dev): inject Authorization header from cookie in Vite dev proxy
Some checks failed
CI / Unit & Component Tests (pull_request) Successful in 2m13s
CI / Backend Unit Tests (pull_request) Successful in 2m9s
CI / E2E Tests (pull_request) Successful in 20m15s
CI / Unit & Component Tests (push) Successful in 2m4s
CI / Backend Unit Tests (push) Successful in 2m8s
CI / E2E Tests (push) Failing after 23s
Browser-side fetch('/api/...') calls bypass SvelteKit's handleFetch hook
(which adds the Authorization header from the auth_token cookie for SSR).
As a result, client-side API calls in the dev server always got a 401.

Add a proxy configure hook that extracts the auth_token cookie from incoming
requests and sets it as the Authorization header before forwarding to the
backend. This makes browser-side fetches (history panel, file preview, etc.)
work correctly in dev mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:05:20 +01:00
Marcel
62f62a89a1 fix(e2e): wait for hydration on document detail page in history tests
Some checks failed
CI / Backend Unit Tests (pull_request) Waiting to run
CI / E2E Tests (pull_request) Waiting to run
CI / Unit & Component Tests (push) Successful in 2m11s
CI / Backend Unit Tests (push) Successful in 2m15s
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / E2E Tests (push) Failing after 28m46s
All three history tests navigated to the doc page but didn't wait for
SvelteKit hydration, so the toggle onclick wasn't registered yet. Also
wait for versions to load (API call) before asserting on version items
or the compare button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 16:03:37 +01:00
Marcel
d84b997965 fix(frontend): show version numbers oldest-first (1 = oldest)
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 2m11s
CI / E2E Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 13:05:31 +01:00
Marcel
8c86beb9f9 feat(frontend): add expandable text component for long fields
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
Adds ExpandableText.svelte which clamps text to 10 lines and shows a
toggle button only when the content actually overflows. Applied to the
summary and transcription fields on the document detail page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 12:53:04 +01:00
Marcel
0020d1e773 fix(frontend): improve PDF zoom and diff readability
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
- PDF viewer: append #zoom=page-width to iframe src so A4 letters fill
  the panel width instead of leaving large grey gutters
- Diff view: trim unchanged context to 4 words either side of each
  change, replacing long runs with '…' so edits are easy to spot

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 12:46:56 +01:00
Marcel
47b8cc9340 feat(frontend): add System tab to admin panel with backfill-versions action
Some checks failed
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 2m13s
CI / Backend Unit Tests (pull_request) Successful in 2m17s
CI / E2E Tests (pull_request) Failing after 22m45s
Admin can trigger an initial history snapshot for all documents without
version history. Shows count of backfilled documents after completion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 12:33:39 +01:00
Marcel
3e65b2feb3 feat: add admin backfill-versions endpoint for documents without history
Adds POST /api/admin/backfill-versions which creates an initial snapshot
(editorName="Datenimport", changedFields=[]) for every document that has
no version entry yet, using the document's createdAt as the version timestamp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 12:27:21 +01:00
Marcel
f32ed32f67 fix(frontend): correct diff direction in history panel
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 2m9s
CI / Backend Unit Tests (pull_request) Successful in 2m4s
CI / E2E Tests (pull_request) Failing after 22m54s
versions array is ascending (oldest first), so the previous version
is at idx-1, not idx+1. Using idx+1 caused added/removed to be swapped,
showing new text as red and old text as green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 12:13:11 +01:00
Marcel
4a0d3b3bea test(e2e): add history panel playwright spec
Some checks failed
CI / Unit & Component Tests (push) Successful in 2m19s
CI / Backend Unit Tests (push) Successful in 2m11s
CI / E2E Tests (push) Has started running
CI / Unit & Component Tests (pull_request) Successful in 2m7s
CI / Backend Unit Tests (pull_request) Successful in 2m0s
CI / E2E Tests (pull_request) Failing after 21m58s
Three scenarios: versions list appears after edits, diff shows changed
field, compare mode displays diff between two selected versions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 11:59:43 +01:00
Marcel
d4b1a709d7 feat(frontend): add document history panel with diff and compare mode
Adds a collapsible history section to the document detail view, showing
all saved versions with changed-field labels, word-level diff between
adjacent versions, and a compare mode for any two arbitrary versions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 11:57:33 +01:00
Marcel
7af49daf9c fix: use tools.jackson (Jackson 3) instead of com.fasterxml.jackson in DocumentVersionService
Spring Boot 4 auto-configures a tools.jackson.databind.ObjectMapper bean.
The service was importing the Jackson 2 package, causing a no-qualifying-bean
error at startup.

Refs #38
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 11:41:16 +01:00
Marcel
28256dbd08 feat: wire document versioning into DocumentService and DocumentController
DocumentService now calls documentVersionService.recordVersion() after
createDocument and updateDocument. DocumentController exposes two new
read-only endpoints: GET /{id}/versions and GET /{id}/versions/{versionId}.

Refs #38
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 11:30:05 +01:00
Marcel
315b368f88 feat: add DocumentVersion entity, repository, service, and migration
Creates the document_versions table (V9) with JSONB snapshot and
changed_fields columns. DocumentVersionService records a version on
every create/update, resolves the editor name from the security context,
and computes changedFields by diffing against the previous snapshot.

Refs #38
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 11:29:41 +01:00
Marcel
43defa41c4 fix(e2e): wait for hydration before clicking nav dropdown in logout test
Some checks failed
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Successful in 2m8s
CI / Backend Unit Tests (push) Successful in 2m10s
CI / E2E Tests (push) Successful in 20m18s
waitForURL('/') resolves as soon as the URL changes but before SvelteKit
finishes hydrating — the avatar button's onclick is not yet registered,
so the click has no effect and the dropdown never opens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 09:48:05 +01:00
Marcel
17db73d900 fix(frontend): hide nav header on forgot-password and reset-password routes
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 09:28:03 +01:00
Marcel
88e3fb32b3 docs: add mail configuration guide
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
Covers dev (Mailpit), production SMTP, all env vars with defaults,
common provider settings, and how to disable mail entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 09:20:43 +01:00
Marcel
c18cdbfac1 feat(dev): add Mailpit mail catcher to docker-compose
Some checks failed
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 2m6s
CI / Backend Unit Tests (pull_request) Successful in 2m7s
CI / E2E Tests (pull_request) Has been cancelled
Adds a Mailpit container that catches all outgoing emails locally so
password reset links can be tested without a real SMTP server.

- Backend defaults to MAIL_HOST=mailpit / MAIL_PORT=1025 in compose
- SMTP auth and STARTTLS disabled for Mailpit (no credentials needed)
- Web inbox available at http://localhost:8025
- Production SMTP still works by overriding MAIL_HOST, MAIL_PORT,
  MAIL_USERNAME, MAIL_SMTP_AUTH, and MAIL_STARTTLS_ENABLE in .env

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 09:10:17 +01:00
Marcel
b9aff799fa fix(e2e): use username check instead of count() for admin user creation
Some checks failed
CI / Unit & Component Tests (push) Successful in 2m3s
CI / Backend Unit Tests (push) Successful in 2m5s
CI / E2E Tests (push) Has started running
CI / Unit & Component Tests (pull_request) Successful in 2m5s
CI / Backend Unit Tests (pull_request) Successful in 1m56s
CI / E2E Tests (pull_request) Failing after 18m40s
When the e2e profile is active, initE2EData (which creates a reader user)
can run before initAdminUser. The old count() == 0 guard then skips admin
creation entirely, causing every login test to fail with 401.

Switch to findByUsername(adminUsername).isEmpty() so the admin is created
regardless of which CommandLineRunner runs first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 08:46:13 +01:00
Marcel
908221f04d feat(frontend): add forgot-password and reset-password pages
Some checks failed
CI / Unit & Component Tests (push) Successful in 2m7s
CI / Backend Unit Tests (push) Successful in 2m3s
CI / E2E Tests (push) Failing after 14m54s
CI / Unit & Component Tests (pull_request) Successful in 2m4s
CI / E2E Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
- /forgot-password: email form → sends POST /api/auth/forgot-password → success banner
- /reset-password: password form reads token from URL → sends POST /api/auth/reset-password
- Login page: add "Passwort vergessen?" link
- hooks.server.ts: add /forgot-password and /reset-password to PUBLIC_PATHS; skip auth
  injection for public auth API endpoints
- errors.ts: add INVALID_RESET_TOKEN error code
- i18n: add all new message keys in de/en/es
- playwright.config.ts: use E2E_BASE_URL for webServer check URL (allows reusing docker
  dev server at port 5173 locally)
- ci.yml: pass E2E_BACKEND_URL=http://localhost:8080 to E2E test step
- e2e/password-reset.spec.ts: 5 tests (4 pass locally, full flow requires e2e profile in CI)
- Regenerated OpenAPI types including new /api/auth/* endpoints

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 07:26:35 +01:00
Marcel
5f49a5787c feat(backend): add password reset via email
- Add PasswordResetToken entity, repository (Flyway V8 migration)
- PasswordResetService: token generation, validation, nightly cleanup
- AuthController: POST /api/auth/forgot-password and /api/auth/reset-password (both permitAll)
- AuthE2EController (@Profile("e2e")): GET /api/auth/reset-token-for-test for CI testing
- spring-boot-starter-mail dependency; JavaMailSender optional (@Autowired required=false)
- mail health indicator disabled; mail config via MAIL_HOST/PORT/USERNAME/PASSWORD env vars
- 5 unit tests written TDD-style (all pass)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 07:26:35 +01:00
Marcel
6400cef390 fix(e2e): fix tag rename and flaky logout tests
Some checks failed
CI / Unit & Component Tests (pull_request) Successful in 2m11s
CI / Backend Unit Tests (pull_request) Successful in 2m7s
CI / E2E Tests (pull_request) Successful in 19m47s
CI / Unit & Component Tests (push) Successful in 2m2s
CI / Backend Unit Tests (push) Successful in 2m3s
CI / E2E Tests (push) Failing after 15m22s
admin.spec.ts: after clicking "Schlagwort bearbeiten", Svelte's {#if editingTagId}
replaces the span with a form, so familieRow (filtered by the span) no longer matches.
Find input[name="name"] and the save button directly instead.

auth.spec.ts: dropdown opens via {#if userMenuOpen} which renders asynchronously.
Wait for the Abmelden button to be visible before clicking to prevent a race condition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 07:25:34 +01:00
Marcel
f98792f10b fix(permissions): redirect read-only users from /documents/new to home
Some checks failed
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Successful in 2m5s
CI / Backend Unit Tests (push) Successful in 2m0s
CI / E2E Tests (push) Failing after 21m36s
throw error(403) kept the URL at /documents/new (the error page renders
in-place). Changed to throw redirect(303, '/') so the URL actually changes,
matching the E2E test expectation that a read-only user is redirected away.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 23:01:45 +01:00
Marcel
70d858b65a fix(tests): add missing user/canWrite/form props to admin spec fixtures
After the layout load function started injecting user+canWrite into all
page data, the admin spec files failed svelte-check with missing property
errors. Add user:undefined, canWrite:true, and form:null to all fixture
data objects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 23:01:25 +01:00
Marcel
c1e82a7edf fix(e2e): fix 8 failing E2E tests on feat/35-profile-page
- admin: add exact:true to tab button assertions to avoid strict-mode
  violations from "Benutzer löschen" title buttons matching "Benutzer"
- admin: change tag-row locator from hasText regex on <li> to has: span
  filter (more robust against whitespace differences); add waitForSelector
  after tab click to ensure panel is rendered before hovering
- auth: replace page.request.get('/api/users/me') with a profile page
  navigation — direct browser requests don't carry Basic Auth, only
  server-side SvelteKit fetches do
- documents: use getByRole('heading') instead of getByText to avoid strict
  mode violation when the title appears in both h1 and breadcrumb
- persons: same heading fix for person creation landing page
- profile: remove success-message assertion after password change; the
  auth_token cookie still holds old credentials so use:enhance's update()
  immediately gets a 401 and redirects to /login before the message renders
  — test now asserts the redirect directly, then re-logs in

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 23:01:04 +01:00
Marcel
7fbfeb3b39 chore(hooks): remove pre-push E2E hook
Some checks failed
CI / Unit & Component Tests (pull_request) Successful in 2m10s
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Backend Unit Tests (pull_request) Successful in 2m11s
CI / E2E Tests (pull_request) Failing after 25m47s
E2E tests run on CI anyway — running them locally before every push
adds too much friction. Removed the hook; CI remains the safety net.

Refs #48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 22:15:00 +01:00
Marcel
bbac351f03 test(e2e): add read-only user permissions journey
Logs in as the seeded "reader" user (READ_ALL only) and asserts
that all write controls are absent from every page.

Refs #48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 20:01:04 +01:00
Marcel
2411c330a2 test(e2e): add admin management journey (users, groups, tags)
Full lifecycle: create group → create user → edit user → reset
password → verify login → delete user → delete group → rename tag.
Self-contained: everything created is also deleted.

Refs #48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 20:00:41 +01:00
Marcel
7d095e159e test(e2e): add profile page journey (view, update, password change)
Includes self-healing password change test that restores admin123
at the end so the shared session remains valid for subsequent specs.

Refs #48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 20:00:23 +01:00
Marcel
ca73777010 test(e2e): add person creation journey
Refs #48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 20:00:03 +01:00
Marcel
0221382c8a test(e2e): add document creation and edit mutation journeys
Refs #48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 19:59:46 +01:00
Marcel
ea6b727e44 test(e2e): verify login establishes a working API session
Guards against regressions where the session cookie is set but
the backend rejects it — a URL redirect alone is not enough.

Refs #48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 19:59:27 +01:00
Marcel
2a46136f61 test(e2e): seed read-only "reader" user in e2e profile
Adds a "Leser" group (READ_ALL only) and "reader" / "reader123"
user to the deterministic e2e seed so the permissions spec can log
in as a read-only user without relying on admin-created test data.

Refs #48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 19:59:07 +01:00
Marcel
c0b9d979ea fix(e2e): wait for swapped senderId in URL instead of any senderId
waitForURL(/senderId=/) resolved immediately because the URL already
contained senderId= before the swap navigation. Use a predicate that
waits for the specific swapped ID value.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 19:44:54 +01:00