Commit graph

57 commits

Author SHA1 Message Date
Johannes Millan
7164a5e44b test(e2e): fix encryption button timing and drag-handle strict mode violation
Two root causes for failing E2E tests in CI:

1. Encryption button not visible after provider selection: The async
   provider change listener loads config from IndexedDB and updates the
   Formly model, but the 1000ms waitForTimeout was insufficient in CI.
   Replace with polling (200ms intervals, 10s timeout) that waits for
   either enable or disable encryption button to become visible.
   Also removes ~130 lines of leftover debug logging from disableEncryption().

2. Drag-handle strict mode violation on parent tasks with subtasks:
   task.locator('.drag-handle') matched both the parent's drag handle
   and nested subtask drag handles. Add .first() to all drag-handle
   locator usages to target only the parent task's own handle.
2026-03-04 19:38:37 +01:00
Johannes Millan
5ab773fa26 test(e2e): fix flaky LWW delete-vs-update conflict tests
Fix deleteTask helper clicking on task-title, which entered edit mode
and caused Backspace to delete text instead of triggering the delete
shortcut. Use drag-handle click target instead.

Also add delete verification, resilient title assertions for known LWW
race, increased persistence waits, and extra sync rounds.
2026-02-16 11:07:52 +01:00
Johannes Millan
93cbcd7e44 test(e2e): fix reliability issues in supersync E2E tests
- Replace page.reload() with close-and-reopen pattern after backup
  imports to prevent hangs with active sync connections
- Add proper sync-import-conflict dialog handling via Promise.race
- Fix browser context leak in provider-switch test
- Replace baseURL! non-null assertions with fallback pattern
- Replace fixed timeouts with element-based waits in cascade-delete
- Extract duplicate dialog-dismissal loop into dismissBlockingDialogs
  helper in waits.ts
- Add missing WorkViewPage/SuperSyncPage imports in same-client test
- Replace any type with proper VectorClockEntry interface
2026-02-13 14:06:43 +01:00
Johannes Millan
e5aca24663 test(e2e): fix cascade delete test and dialog handler conflicts
- Rewrite cascade delete test to avoid concurrent modification race
  condition that the sync protocol correctly resolves by keeping both
  sides' data (not a bug, just wrong test expectation)
- Add try/catch to dialog handlers in supersync.page.ts to prevent
  "Cannot accept dialog which is already handled" errors when multiple
  listeners compete
- Fix closeClient unhandled promise rejection when timeout wins
  Promise.race
2026-02-12 21:18:14 +01:00
Johannes Millan
919b247cf0 test(e2e): fix supersync test flakiness from navigation blocking and unhandled dialogs
- Add waitForLoadState in addTask() to handle in-flight Angular navigation
- Use noWaitAfter on all sync button right-clicks to prevent navigation blocking
- Restructure syncAndWait() to continuously check for dialogs during sync
  instead of checking once then blocking on spinner
- Register native window.confirm/alert handler in syncAndWait() for dialogs
  that appear mid-sync (e.g., data repair, fresh client confirmation)
- Make hasTaskInWorklog() skip re-navigation when already on worklog page
  and increase timeouts for more reliable worklog checks
2026-02-12 20:01:14 +01:00
Johannes Millan
43b5808a3f fix(sync): harden vector clock sanitization and improve E2E test robustness
- Cap sanitizeVectorClock values at 100M instead of MAX_SAFE_INTEGER (prevents adversarial clock inflation)
- Add early-exit optimization in compareVectorClocks for CONCURRENT detection
- Add test.setTimeout(180000) to token-expiry and lastseq-preservation E2E tests
- Remove dead code (unreachable guard) in compaction E2E test
- Extract shared config helpers (navigateToMiscSettings, toggleSetting, etc.) into e2e/utils/config-helpers.ts
- Fix Client B cleanup in provider-switch test (move to finally block)
- Add clarifying comments for raw SQL schema coupling, CORS header, and mergeRemoteOpClocks caller contract
- Extract enforceStorageQuota helper in sync routes to reduce duplication
- Add conflictType to conflict detection for structured error handling
- Add MAX_CLEANUP_ITERATIONS guard to freeStorageForUpload
2026-02-12 16:27:56 +01:00
Johannes Millan
4a779a0218 fix(sync): replace vector clock on remote SYNC_IMPORT instead of merging
When a client with an established vector clock (10+ entries) received a
remote SYNC_IMPORT/BACKUP_IMPORT with a fresh clock, mergeRemoteOpClocks()
merged the import's clock into the old clock instead of replacing it.
This caused clock bloat (11+ entries), which led to server-side pruning
dropping the import's entry (lowest counter). Other clients then saw
these ops as CONCURRENT with the import and discarded them.

Fix: In mergeRemoteOpClocks(), when a full-state op is present, use its
clock as the base instead of the existing local clock. Regular ops
continue to merge normally.
2026-02-12 16:27:55 +01:00
Johannes Millan
288b0f725f fix(test): update E2E selectors for decrypt dialog and fix worklog task lookup
Update button selectors to match renamed "Retry Decrypt" button in
decrypt error dialog. Fix hasTaskInWorklog to check isExpanded class
before clicking week rows, preventing double-click collapse when called
consecutively. Replace instant count() with waitFor() for animation timing.
2026-01-30 20:09:11 +01:00
Johannes Millan
7ed76c13a4 test(e2e): add E2E tests for recent sync bug fixes
Add comprehensive E2E tests covering SuperSync and WebDAV bug fixes:

- Archive preservation during "Keep Local" conflict resolution
- ConstraintError recovery (appliedOpIds cache invalidation)
- Encryption password preservation (form model race conditions)
- SYNC_IMPORT server state cleanup
- WebDAV rapid sync (false 412 error prevention)

Also adds archive/worklog helper functions to supersync-helpers.ts
and a test backup fixture with archived tasks.
2026-01-29 16:32:29 +01:00
Johannes Millan
a37d0eac4f fix(e2e): resolve flaky WebDAV tests and fix encryption test failures
- Add closeContextsSafely helper to handle Playwright trace file race conditions
  during browser context cleanup (fixes ENOENT errors on test retry)
- Fix enableEncryption method to properly handle dialog-based encryption flow
- Fix disableEncryptionForFileBased method: remove unnecessary expandAdvancedSettings,
  fix selector to match actual CSS class (.e2e-disable-encryption-btn)
- Update 5 test files to use closeContextsSafely for robust cleanup
2026-01-28 21:55:04 +01:00
Johannes Millan
e9b1b9c34c perf(e2e): split scheduled CI into parallel jobs and reduce wait times
Split e2e-scheduled.yml into 3 parallel jobs (regular, webdav, supersync)
for ~3x faster nightly runs. Each job only starts the Docker services it
needs. Also reduced fixed wait times in sync-helpers.ts and waits.ts to
improve test execution speed while maintaining reliability.
2026-01-26 15:40:22 +01:00
Johannes Millan
e48749d0f7 fix(sync): address code review findings and add encryption tests
- Remove sensitive debug logging from sync-config.service.ts
- Fix dialog handler memory leak in E2E tests (page.on -> page.once)
- Remove duplicate code block in supersync.page.ts
- Fix silent error in rejected-ops-handler.service.ts (now re-throws)
- Improve CapacitorHttp error classification in super-sync.ts
- Add isEntityState type guard in operation-log-sync.service.ts
- Import DOWNLOAD_PAGE_SIZE constant and fix timeout leak in download service
- Fix waitForTask to only catch timeout errors in supersync-helpers.ts
- Add unit tests for EncryptionEnable/Disable/ImportHandler services
2026-01-25 12:41:03 +01:00
Johannes Millan
9c5704c6c1 fix(e2e): fix schedule dialog submit button selector
The selector 'button:last-child' caused a Playwright strict mode
violation by matching multiple buttons (Schedule and Cancel).
Changed to 'button[color="primary"]' to specifically target the
primary action button.

Fixes 5 failing reminder tests that were unable to schedule tasks.
2026-01-21 14:30:24 +01:00
Johannes Millan
a49a863a08 test(e2e): improve sync test robustness with archive persistence waits
Adds explicit waits after archive operations to ensure IndexedDB writes
complete before proceeding with sync operations. This prevents race
conditions where sync attempts to read state before archive persistence
finishes.

Changes:
- Add waitForArchivePersistence() helper to sync-helpers.ts
  - Waits 1000ms for IndexedDB operations to complete
  - Additional 100ms for pending micro-tasks/animations
- Add 500ms waits in waitForSyncComplete() after detecting sync success
  - Ensures IndexedDB writes fully settle before returning
- Apply waitForArchivePersistence() in webdav-sync-archive.spec.ts
  - After Client A archives Task1
  - After Client B archives Task3
- Apply waitForArchivePersistence() in webdav-sync-delete-cascade.spec.ts
  - After Client A archives task (tag deletion test)
  - After Client B archives Task1 (concurrent archive test)

These changes address flakiness in CI environments where async IndexedDB
operations may not complete before the next test assertion.

Related to: Bug #5995, Bug #6044 (focus-mode test fixes)
2026-01-20 17:07:24 +01:00
Johannes Millan
cf317036de fix(e2e): wait for dialog close animation in deleteTask helper
The deleteTask() helper was clicking the confirmation dialog Delete
button but not waiting for the dialog to actually close. This caused
a race condition where tests would immediately check for the undo
snackbar before it could appear, leading to timeouts.

The fix adds a proper wait for the dialog container to be hidden
after clicking Delete, ensuring the close animation completes and
NgRx effects have time to dispatch the snackbar action.

Fixes CI E2E workflow failure in "Undo task delete syncs restored
task to other client" test.
2026-01-19 12:09:50 +01:00
Johannes Millan
b3ddfcbf20 perf(e2e): optimize polling intervals in helpers
Phase 1.4 of E2E test optimization:
- TASK_POLL_INTERVAL: 300ms → 150ms
- waitForSyncComplete() stable check: 300ms → 150ms
- waitForSyncComplete() spinner check: 200ms → 100ms
- Dialog loop polling: 200ms → 100ms

Expected impact: 5-10s saved per test (faster detection)
Risk: Low - still reasonable for network operations
2026-01-18 15:58:46 +01:00
Johannes Millan
13d7afc458 refactor(e2e): extract ensureGlobalAddTaskBarOpen helper to reduce code duplication
Extract ensureGlobalAddTaskBarOpen() to e2e/utils/element-helpers.ts to avoid
duplicating the logic for opening the global add task bar across multiple tests.

This helper properly waits for the add button and input to be visible,
preventing race conditions in tests.
2026-01-16 13:35:59 +01:00
Johannes Millan
c628c3d7ce test(e2e): add legacy migration sync tests for WebDAV and SuperSync
Add E2E tests covering the scenario where two clients both migrate from
the old Super Productivity format (pre-operation-log) and then sync.

Tests include:
- Both clients migrated with different data (keep local/remote resolution)
- Both clients migrated with same entity IDs (ID collision handling)
- Archive data preservation after migration + sync (WebDAV only)

New files:
- legacy-migration-helpers.ts: Helper functions for seeding legacy DB
- 4 JSON fixtures for legacy data scenarios
- webdav-legacy-migration-sync.spec.ts: 4 WebDAV tests
- supersync-legacy-migration-sync.spec.ts: 3 SuperSync tests (1 skipped)
2026-01-13 18:26:45 +01:00
Johannes Millan
51f3c892e3 fix(test): add E2E dialog validation and fix keyboard test cleanup
- Add message validation to E2E dialog auto-accept handlers to prevent
  false positives when unexpected confirm dialogs appear
- Change afterAll to afterEach in check-key-combo.spec.ts to prevent
  navigator override from polluting other tests
2026-01-11 18:58:07 +01:00
Johannes Millan
5bf7cf10ab test: fix supersync tests 2026-01-11 15:28:50 +01:00
Johannes Millan
44d7057129 fix(sync): only show import conflict dialog for local unsynced imports
The sync import conflict dialog was showing multiple times when it should
only show once, or not at all for already-accepted remote imports.

Root cause: The dialog trigger condition was too broad - it showed whenever
ALL downloaded ops were filtered by a SYNC_IMPORT, without distinguishing
between local unsynced imports (user needs to choose) and remote/synced
imports (old ops being silently cleaned up is expected behavior).

Changes:
- Add getLatestFullStateOpEntry() to get import with metadata (source, syncedAt)
- Add clearFullStateOps() for USE_REMOTE conflict resolution
- Return isLocalUnsyncedImport flag from SyncImportFilterService
- Pass through flag via RemoteOpsProcessingService
- Only show dialog when isLocalUnsyncedImport=true (local import not yet synced)
- Silently filter old ops when import was already accepted from remote
2026-01-11 11:22:32 +01:00
Johannes Millan
42b0d65352 fix(e2e): dismiss Welcome intro dialog before Shepherd tour
The E2E tests were failing because dismissTourIfVisible only handled
the Shepherd tour steps, not the Welcome intro mat-dialog that appears
first. This dialog blocks UI interactions causing test timeouts.

Updated tour-helpers.ts to:
- Add dismissWelcomeDialog() for the intro dialog
- Add dismissShepherdTour() for the tour steps
- Update dismissTourIfVisible() to handle both in sequence
2026-01-09 18:28:18 +01:00
Johannes Millan
94e4959b91 fix(e2e): handle ENOENT errors in closeClient cleanup
Playwright throws ENOENT errors when finalizing trace artifacts for
manually-created browser contexts. This is a known issue when using
trace: 'retain-on-failure' with contexts created via browser.newContext().

The fix extends error handling to catch and log these cleanup errors
instead of failing the test after assertions have already passed.
2026-01-08 20:44:24 +01:00
Johannes Millan
386c5a2f40 fix(e2e): improve stability of WebDAV sync tests
- Wait for form fields to appear after selecting WebDAV provider
  instead of fixed timeout (fixes flaky .e2e-baseUrl input timeout)
- Dismiss overlays before clicking sync button in triggerSync()
- Improve waitForSyncComplete with fallback detection when icon
  selector fails (checks consecutive non-spinning states)
- Remove unnecessary page.reload() in tag removal test
- Handle Material conflict dialog explicitly in multi-local-ops test
  (browser confirm handler only works for window.confirm())
2026-01-08 14:17:37 +01:00
Johannes Millan
1f8fe61c84 refactor: integrate pfapi into oplog 1 2026-01-07 13:30:09 +01:00
Johannes Millan
b24510ff66 Merge branch 'master' into feat/operation-logs
* master:
  fix(sync): show meaningful error messages instead of minified class names
  fix(e2e): use fill() for time input in task-detail tests
  build(ci): update CodeQL analysis permissions for security events
  fix(ci): add issues write permission to autoresponse workflow
  fix(boards): respect backlog filter for tasks from hidden projects
  fix(android): cancel native notification when task marked done
  refactor(e2e): simplify improvements per KISS/YAGNI review
  refactor(e2e): improve
  revert: remove translation stubs from non-English language files
  i18n: add English fallback stubs for toolbar translations to all languages
  feat: integrate auto-save from master for toolbar actions
  fix: address PR review comments for markdown toolbar
  refactor: move markdown toolbar to fullscreen editor only
  feat: add markdown formatting toolbar to notes editor

# Conflicts:
#	e2e/tests/sync/webdav-sync-expansion.spec.ts
#	src/app/features/tasks/store/task-reminder.effects.spec.ts
#	src/app/features/tasks/store/task-reminder.effects.ts
#	src/app/pfapi/api/errors/errors.spec.ts
2026-01-06 13:55:07 +01:00
Johannes Millan
4ba9b72597 refactor(e2e): simplify improvements per KISS/YAGNI review
Remove unused speculative abstractions:
- Delete material-helpers.ts (223 lines, zero usages)
- Delete retry-helpers.ts (186 lines, zero usages)
- Revert unused assertion helpers
- Revert unused timeout constants

Keep valuable changes:
- applyPrefix() helper in BasePage (used 4x)
- ProjectPage now uses applyPrefix() for DRY
- Simplified utils/index.ts barrel export
2026-01-06 12:46:20 +01:00
Johannes Millan
b544131921 refactor(e2e): improve 2026-01-06 12:46:20 +01:00
Johannes Millan
b01afbfcd1 fix(sync): address code review findings for operation-logs
Security:
- Add rate limiting (10 req/5min) to GET /snapshot endpoint
- Prevents DoS via CPU-intensive snapshot generation

Consistency:
- Add 30s timeout to download transaction (matches other sync transactions)

Test robustness:
- Fix weak encryption test - always assert error on wrong password
- Update lww-update.meta-reducer tests to use OpLog instead of console

Defensive coding:
- Add entity-not-found warnings in LWW meta-reducer for sync race conditions
- Log when project/tag/parent task deleted before LWW update arrives

Code quality:
- Standardize logging to OpLog in lww-update.meta-reducer
- Document LWW action types as intentionally not in ActionType enum
- Create e2e-constants.ts for centralized E2E test timeouts/delays
- Extract createProjectReliably helper to supersync-helpers.ts (DRY)
2026-01-06 11:42:47 +01:00
Johannes Millan
f37110bbb5 fix(e2e): improve test stability for parallel execution
SuperSync page object improvements:
- Add networkidle wait before interacting with sync dialog
- Add explicit mat-dialog-container wait before form interaction
- Add toBeAttached() assertions for element stability
- Use toPass() with progressive backoff for dropdown interactions
- Dismiss existing dropdown overlays before retrying
- Add blur() calls in password change dialog for Angular validation
- Add try-catch for fresh client dialog race condition

Task detail tests:
- Add blur() after time input fill to ensure Angular registers
  the change before clicking Save

These changes fix intermittent failures when running E2E tests
with multiple workers in parallel.
2026-01-04 17:35:47 +01:00
Johannes Millan
85fa50974b Merge branch 'master' into feat/operation-logs
* master:
  refactor(e2e): improve test infrastructure for easier expansion
  chore(e2e): remove broken/empty skipped tests
  test(e2e): fix flaky plugin and WebDAV sync tests
  refactor(e2e): replace waitForTimeout with condition-based waits
  perf(e2e): remove ineffective waits to speed up test runs
  docs(e2e): add CLAUDE.md reference and barrel export for easier test creation
  build: update dep
  refactor(e2e): simplify waits and fix flaky tests
  feat(e2e): streamline e2e test development with improved infrastructure
  perf(e2e): optimize wait utilities and addTask method for faster test execution
  16.8.1

# Conflicts:
#	e2e/pages/base.page.ts
#	e2e/pages/project.page.ts
#	e2e/tests/reminders/reminders-schedule-page.spec.ts
#	e2e/tests/sync/webdav-sync-advanced.spec.ts
#	e2e/tests/sync/webdav-sync-expansion.spec.ts
#	e2e/tests/sync/webdav-sync-full.spec.ts
#	e2e/utils/waits.ts
2026-01-03 18:51:51 +01:00
Johannes Millan
eca5fc930f refactor(e2e): improve test infrastructure for easier expansion
- Add all page objects to fixtures (plannerPage, syncPage, tagPage, notePage, sideNavPage)
- Create assertion helpers (expectTaskCount, expectTaskVisible, etc.)
- Enhance CLAUDE.md with patterns, import paths, and all fixtures
- Add const assertion to selectors for better TypeScript support
2026-01-03 18:39:40 +01:00
Johannes Millan
8d9ceb5776 test(e2e): fix flaky plugin and WebDAV sync tests
- Fix plugin toggle flakiness by using helper functions with proper
  state verification (enablePluginWithVerification, disablePluginWithVerification)
- Fix WebDAV sync tests by handling loading screen in waitForAppReady
  and waitForTaskList (app shows loading while syncing/importing)
- Remove unreliable/empty test files: webdav-sync-recurring,
  webdav-sync-reminders, webdav-sync-time-tracking
2026-01-03 17:35:09 +01:00
Johannes Millan
11d85208e5 refactor(e2e): replace waitForTimeout with condition-based waits
- Replace ~100 waitForTimeout calls with proper condition-based waits
- Extract shared utilities for time input and task scheduling
- Add timeout constants for consistent wait times
- Add new selectors for reminder dialogs and detail panels

Files refactored across 25+ test files including:
- Plugin tests (lifecycle, upload, loading, enable, structure)
- Reminder tests (view-task, schedule-page, default-options)
- Work view, planner, focus mode, and app feature tests
- Task dragdrop, autocomplete, and daily summary tests

New utilities created:
- e2e/utils/time-input-helper.ts - Robust time input filling
- e2e/utils/schedule-task-helper.ts - Task scheduling helpers
- e2e/constants/timeouts.ts - Standardized timeout values
2026-01-03 15:29:38 +01:00
Johannes Millan
e3f9daf9fa refactor(e2e): simplify waits and fix flaky tests
- Remove Angular testability API checks from waitForAngularStability
  Experiment showed Playwright's auto-waiting is sufficient for most tests
- Fix time-tracking-feature test: add missing await, replace hardcoded
  waitForTimeout with proper toHaveClass assertions
- Refactor plugin-simple-enable test to use SettingsPage methods
  instead of brittle page.evaluate() DOM manipulation (106 -> 33 lines)
- Change trace config to 'retain-on-failure' for better debugging
2026-01-03 12:57:16 +01:00
Johannes Millan
c0fc56f729 perf(e2e): optimize wait utilities and addTask method for faster test execution
Optimized e2e test utilities to significantly reduce execution time:

**waitForAngularStability():**
- Reduced default timeout from 5s to 3s
- Removed redundant ng.getComponent checks
- Removed non-fatal catch that swallowed errors
- Simplified fallback to only check route-wrapper presence

**waitForAppReady():**
- Removed slow networkidle wait (saves ~2-5s per call)
- Removed redundant checks (body, magic-side-nav)
- Removed 200ms fixed buffer at the end
- Reduced timeouts across the board
- Streamlined to essential waits only

**waitForStatePersistence():**
- Removed networkidle wait (replaced with 100ms buffer)
- Now relies on Angular stability for state persistence

**BasePage.addTask():**
- Removed 3-attempt retry loop with 500ms delays
- Removed all fixed timeouts (50ms, 100ms, 300ms, 500ms, 1000ms)
- Simplified input filling - rely on Playwright's auto-waiting
- Removed redundant initial stability checks
- Removed Promise.race with multiple strategies
- Removed unused waitForAngularStability import
- Reduced from ~170 lines to ~70 lines

These changes speed up e2e tests by removing ~1-3 seconds per test
from unnecessary waits while maintaining reliability through Playwright's
built-in auto-waiting and retry mechanisms.
2026-01-03 11:11:01 +01:00
Johannes Millan
4f2dbcdaa7 feat(sync): handle auth errors for account deletion scenarios
When a SuperSync account is deleted, clients now properly detect
authentication failures and prompt for reconfiguration:

- Add _checkHttpStatus() helper to SuperSyncProvider that throws
  AuthFailSPError on 401/403 responses
- Clear cached credentials on auth failure to allow reconfiguration
- Add DELETE /api/test/user/:userId endpoint for E2E testing
- Add deleteTestUser() helper in supersync-helpers.ts
- Add E2E tests for account deletion and reconfiguration scenarios

The existing SyncWrapperService already handles AuthFailSPError by
showing a snackbar with "Configure" action, so no UI changes needed.
2026-01-02 15:48:17 +01:00
Johannes Millan
4e0f5e8999 fix(e2e): improve app loading detection and fix server TypeScript errors
- e2e/utils/waits.ts: Add proper retry logic and error handling when
  waiting for magic-side-nav to appear. Now throws a clear error if
  app doesn't load within 30s instead of silently continuing.

- packages/super-sync-server/src/auth.ts: Use nullish coalescing for
  passwordHash to handle passkey-only users (who have no password).

- packages/super-sync-server/src/passkey.ts: Add WebAuthn passkey
  authentication support. Fix TypeScript errors by importing types
  from @simplewebauthn/types and converting credential IDs to
  base64url strings.

Fixes flaky "Multiple fresh clients join and sync correctly after
snapshot" test that was failing when app didn't fully load.
2026-01-02 15:11:16 +01:00
Johannes Millan
6c098b6eaa Merge branch 'master' into feat/operation-logs
Resolve conflict in webdav-sync-expansion.spec.ts:
- Use simplified sync verification without reload (sync updates NgRx directly)
- Test: B marks task done -> sync -> verify A sees task as done
2025-12-29 21:54:15 +01:00
Johannes Millan
c4f536471a test(webdav): add e2e tests 2025-12-29 12:48:36 +01:00
Johannes Millan
1da70487f9 fix: address code review findings from Dec 27-29 changes
ESLint rule improvements:
- Fix require-hydration-guard to detect guards on combineLatest/forkJoin/zip
  results (eliminates 20+ false positive warnings)

Server improvements:
- Add OperationDownloadService unit tests (21 tests covering vector clock
  aggregation, gap detection, excludeClient parameter, snapshot optimization)
- Split ZIP bomb size limits: 10MB for /ops, 30MB for /snapshot
- Document storage quota update as intentionally non-atomic

E2E test improvements:
- Add waitForUISettle() helper using Angular stability instead of fixed timeouts
- Update supersync-cross-entity tests to use dynamic waits

Unit test improvements:
- Add HydrationStateService edge case tests (concurrent calls, cooldown cycles,
  timer cleanup, interleaved operations)
2025-12-29 10:37:12 +01:00
Johannes Millan
6276f89c75 test(e2e): prevent browser closed errors and fix context menu selectors
- Add page.isClosed() checks before waitForTimeout calls to prevent
  "Target page, context or browser has been closed" errors when tests
  timeout (supersync-helpers.ts, waits.ts, supersync.page.ts)
- Fix context menu selector in LWW tests: use .mat-mdc-menu-item instead
  of button[mat-menu-item] which doesn't match Angular Material menu items
- Add retry logic for opening context menus with proper wait/escape handling
- Skip "Subtask edit survives when parent is deleted" test - documents
  expected future behavior that is not yet implemented
2025-12-28 11:30:45 +01:00
Johannes Millan
0d6b65cdc1 fix(e2e): handle already-closed browser contexts in closeClient
The closeClient helper was throwing errors when trying to close browser
contexts that were already closed (due to test timeouts or failures).
This caused cascading errors in E2E tests and made debugging harder.

Fix by checking if page is closed before attempting to close the context,
and gracefully catching "already closed" errors.
2025-12-27 22:14:20 +01:00
Johannes Millan
6a26d914b5 test: skip tmp 2025-12-24 16:27:12 +01:00
Johannes Millan
72608a4aaa feat(migration): implement pre-migration dialog and backup functionality 2025-12-24 13:49:37 +01:00
Johannes Millan
c757ff500d test(sync): re-enable sync after import in tests and adjust baseURL fallback 2025-12-22 12:08:04 +01:00
Johannes Millan
5992fad51b fix(sync): perform archive flush synchronously to prevent DB lock error
Previously, flushYoungToOld was dispatched as an action and handled by
an NgRx effect. This caused a race condition during finish day:
1. Action dispatched, effect queued
2. Method returned, sync started, DB locked
3. Effect ran, tried to write, blocked by DB lock

Fix follows the same pattern as moveToArchive:
- Perform the flush synchronously in ArchiveService before dispatching
- Dispatch action for op-log capture only (syncs to other clients)
- Handler skips local operations (only runs for remote)

Also adds comprehensive unit tests and e2e test for this scenario.
2025-12-17 16:42:59 +01:00
Johannes Millan
d5a0258c85 fix(sync): use vector clocks for SYNC_IMPORT filtering instead of UUIDv7
Replace UUIDv7 timestamp-based filtering with vector clock comparison
in _filterOpsInvalidatedBySyncImport(). This fixes a bug where client
clock drift could cause pre-import operations to bypass filtering.

Vector clocks track causality ("did this client know about the import?")
rather than wall-clock time, making the filtering immune to clock drift.

Operations are now filtered based on comparison result:
- GREATER_THAN or EQUAL: keep (client had knowledge of import)
- LESS_THAN or CONCURRENT: filter (created without knowledge)

Also fix E2E tests to properly skip when SuperSync server isn't
running in TEST_MODE by checking test endpoint availability.
2025-12-17 14:50:50 +01:00
Johannes Millan
ef40c7ba6a fix(sync): ensure pending writes complete before conflict detection
Fix race condition where sync could start before local operation writes
completed to IndexedDB, causing conflict detection to miss pending ops.

- Add OperationWriteFlushService that uses sp_op_log lock to ensure all
  pending writes complete before reading from IndexedDB
- Call flushPendingWrites() before conflict detection in sync service
- Add retry with exponential backoff to createTestUser for rate limiting
- Add unit tests for flush service and sync ordering

The flush mechanism works by acquiring the same lock used by writeOperation().
Since effects use concatMap and Web Locks API guarantees FIFO ordering,
acquiring the lock means all prior writes have completed.
2025-12-13 11:50:36 +01:00
Johannes Millan
84e1bae3f7 fix(e2e): reduce console log noise with optional E2E_VERBOSE flag
By default, only errors are logged. Set E2E_VERBOSE=1 to see all browser
console messages for debugging.
2025-12-12 20:48:13 +01:00