Commit graph

595 commits

Author SHA1 Message Date
Johannes Millan
dbeca43876 test(e2e): fix done-toggle selector to use element instead of class
The done-toggle was refactored from an inline SVG with class="done-toggle"
into a standalone Angular component <done-toggle>. Update all e2e selectors
from '.done-toggle' (class) to 'done-toggle' (element) to match.
2026-03-24 16:25:42 +01:00
Johannes Millan
d316a684bb fix(sync): improve move operation reliability during sync
- moveItemAfterAnchor: preserve current position when anchor is
  concurrently deleted instead of appending to end (which corrupted
  ordering on remote clients). For cross-list moves, append to end
  as fallback to prevent data loss.
- Prevent double-write of deferred actions: track buffered actions in
  a WeakSet and filter them in the effect so they are only written
  once by processDeferredActions().
- Propagate skipDequeue through handleQuotaExceeded retry path to
  prevent queue desync when deferred actions hit storage quota.
- Add e2e tests for concurrent delete + reorder sync scenarios.
2026-03-24 16:25:42 +01:00
Johannes Millan
6d67d31ecb test(e2e): fix failing WebDAV and SuperSync E2E tests
- Suppress onboarding overlay for fresh Client B in WebDAV legacy
  migration test (onboarding-backdrop was blocking sync button clicks)
- Update play indicator selector from .play-icon-indicator to
  .play-indicator after done-toggle circle refactor removed the mat-icon
- Use markTaskDoneByKey in archive conflict tests for reliable done
  state verification (click-based markTaskDone was silently failing)
2026-03-23 11:07:25 +01:00
Johannes Millan
beba140d9f
test(e2e): suppress onboarding in WebDAV and SuperSync client helpers (#6922)
The previous fix (1cf7cff) added onboarding suppression via addInitScript
to test.fixture.ts, but WebDAV and SuperSync tests create their own
browser contexts via setupSyncClient() and createSimulatedClient() which
don't use that fixture. Without the suppression, onboarding overlays
interfere with sync tests causing timeouts and failures.

https://claude.ai/code/session_01AgeFLhcokw7y2tkTpeQMUz

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-22 23:15:26 +01:00
Johannes Millan
1cf7cffa8e test(e2e): fix failing tests by suppressing onboarding and example tasks
Set localStorage flags (onboarding preset, hints, tour, example tasks)
via addInitScript before app boots, preventing onboarding overlays and
example tasks from interfering with e2e tests. Also switch archive
import/subtask specs to use the shared test fixture for proper isolation.
2026-03-22 21:20:09 +01:00
Johannes Millan
31480a5fab feat(tasks): replace drag handle with done toggle circle and improve mobile UX
- Replace drag handle with SVG done-toggle circle with checkmark draw-on animation
- Improve mobile UX: cdkDragStartDelay for touch, bottom-sheet context menu
- Move issue/repeat indicators from drag handle to tag-list as chips
- Add isFinishDayEnabled config toggle
- Reorder context menu: add sub task before duplicate, deadline as own entry
- Fix context menu not opening on swipe left
- Fix race condition in done toggle animation timeout
2026-03-22 18:14:16 +01:00
Johannes Millan
2f8d871042 feat(shepherd): remove all tours except keyboard navigation
Remove the full welcome tour (Welcome, AddTask, DeleteTask, Projects,
Sync, IssueProviders, ProductivityHelper, FinalCongrats, StartTourAgain)
and keep only the KeyboardNav tour, triggered from the Help menu.

- Delete ShepherdComponent (auto-start on load)
- Strip shepherd-steps.const.ts to KeyboardNav steps only
- Simplify ShepherdService with _initPromise guard and fresh tour on re-open
- Remove 3 tour menu items from Help menu, keep keyboard tour
- Remove waitForEl/waitForElObs$ helpers (unused by KeyboardNav)
- Delete e2e/utils/tour-helpers.ts and all tour dismissal calls
- Clean up stale tour comments across e2e tests
- Fix pre-existing build error: add isFinishDayEnabled to AppFeaturesConfig
  type, defaults, form toggle, component signal, and translations
2026-03-22 17:00:42 +01:00
Johannes Millan
cbebb551aa feat(work-view): remove planning mode, always use global add-task-bar
Planning mode added unnecessary UI complexity — the global add-task-bar
provides the same functionality and is always accessible via the header
button, keyboard shortcut, or mobile FAB.

- Remove PlanningModeService entirely
- Always show status bar and finish-day button
- 'Add more' button now opens the global add-task-bar
- Relocate 'add scheduled for tomorrow' button into empty state
- Remove E2E workarounds for planning mode exit
- Remove orphaned translation keys from t.const.ts and en.json
- Fix decorative image alt text for screen readers
2026-03-22 10:10:19 +01:00
Johannes Millan
a578cbfa86 test(e2e): fix recurring task tests failing in CI production builds
Replace window.ng.getComponent() calls with UI-based interactions.
Angular debug APIs are unavailable in production builds (CI uses
ng build which defaults to production config with enableProdMode).

- Use calendar picker instead of signal manipulation for date setting
- Remove page.evaluate() model verification (input value checks suffice)
- Replace waitForTimeout with proper toBeVisible/toBeEnabled waits
- Fix date input focus issues with click + pressSequentially
- Use en-GB date format (DD/MM/YYYY) matching app default locale
2026-03-19 12:15:47 +01:00
Johannes Millan
fc70665861
Fix recurring task tests and update GitHub Actions output syntax (#6871)
* fix(ci): replace deprecated set-output and fix E2E test failures

- Replace deprecated `::set-output` with `$GITHUB_OUTPUT` in all
  workflow files (build.yml, ci.yml, build-android.yml, manual-build.yml)
- Fix recurring-start-date-epoch-bug-6860 E2E test: use en-GB date
  format (DD/MM/YYYY) instead of US format since app defaults to en-GB
- Fix recurring-future-start-date-bug-6856 E2E test: wait for Save
  button to be enabled, increase persistence wait, and fix
  reload/navigation ordering for more reliable state verification

https://claude.ai/code/session_01JovQ5nVMSVQXUBFVknZtSm

* fix(ci): replace deprecated set-output in remaining workflow files

Fix 3 additional workflow files that still used the deprecated
::set-output syntax: build-create-windows-store-on-release.yml,
build-publish-to-mac-store-on-release.yml, and
build-update-web-app-on-release.yml.

https://claude.ai/code/session_01JovQ5nVMSVQXUBFVknZtSm

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-19 01:42:57 +01:00
Johannes Millan
a01a511c25 feat(sync): add backup strategy with accounts-only dump and disaster recovery docs
- Add accounts-only pg_dump (users + passkeys) to backup script for
  lightweight disaster recovery when clients still have data
- Add pipefail to backup script to catch silent dump failures
- Add test endpoint to simulate partial server revert (ops-after/:serverSeq)
- Add 6 e2e tests covering all disaster recovery scenarios:
  complete data loss, partial revert, accounts-only restore (API + SQL),
  full dump restore + reset account, and all-clients-lost recovery
- Add backup-and-recovery.md with setup, recovery procedures, and
  decision tree
2026-03-18 20:15:45 +01:00
Johannes Millan
b7e369d512 fix(recurring): prevent start date from reverting to 1970-01-01 (#6860)
When FormlyDatePickerComponent bound [min]="props.min" with an
undefined value, Angular overrode the signal input default, causing
DatePickerInputComponent.validateDate() to compare against Invalid
Date. Every date failed validation, emitting null, which the formly
parser getDbDateStr(null) converted to '1970-01-01' (Unix epoch).

Fix at three layers:
- FormlyDatePickerComponent: use ?? fallbacks so undefined never
  reaches the signal inputs
- DatePickerInputComponent.validateDate(): handle undefined/invalid
  min/max with nullish checks and isNaN guards
- Formly parser: only convert Date objects via getDbDateStr, pass
  null/string values through for the required validator to handle

Also extract shared DATE_PICKER_MIN/MAX_DEFAULT constants and widen
signal input types to include undefined for type-honest code.
2026-03-18 13:14:10 +01:00
Johannes Millan
f7a26fd332 test(e2e): increase webServer startup timeout to 2 minutes
The CI timeout of 90s was too short for the production build to complete,
causing false test failures.
2026-03-18 13:14:10 +01:00
Johannes Millan
f3585b5dc1 test(e2e): fix recurring future-start-date and supersync encryption tests
- Rewrite recurring-future-start-date test to set startDate via the
  repeat dialog's model signal instead of the broken schedule-dialog
  approach (mat-datepicker signals don't work from page.evaluate)
- Fix supersync encryption password-change test by clicking syncBtn
  directly instead of triggerSync() which throws on error state before
  the async decrypt dialog renders
2026-03-18 13:14:10 +01:00
Johannes Millan
1b12484c1e fix(recurring): schedule task for start date when made recurring with future date
When making a task recurring with a future start date, set dueDay
immediately so the task no longer appears in today's view (#6856).
2026-03-17 13:59:40 +01:00
Johannes Millan
1a0e38fb17 test(e2e): use correct route /#/tag/TODAY/tasks instead of /#/tag/TODAY
The deadlines feature commit accidentally reverted e2e URL fixes.
The route /#/tag/TODAY has no default child component — only
/#/tag/TODAY/tasks renders the work view with task-list.
2026-03-15 18:48:00 +01:00
Johannes Millan
d401e6169e feat(tasks): add deadlines feature with reminders and planner integration
Add deadline support for tasks with date-only and time-specific deadlines.

Core:
- Add deadlineDay, deadlineWithTime, deadlineRemindAt fields to task model
- Add NgRx actions (setDeadline, removeDeadline, clearDeadlineReminder)
- Add meta-reducer with mutual exclusivity and input validation
- Register deadline actions in ActionType enum and op-log codes

UI:
- Create deadline dialog with calendar, time input, and reminder options
- Add deadline badge to task list row with overdue warning color
- Add deadline item to task detail panel with flag icon
- Add deadline options to task context menu
- Show deadlines in scheduled list page

Reminders:
- Add deadline reminder effects and selectors
- Show reminder dialog with grouped deadline/schedule sections
- Handle deadline reminder clearing on dismiss, done, add-to-today
- Cancel Android native deadline notifications on delete/archive

Planner:
- Show deadline tasks in planner day view and overdue section
- Create dedicated planner-deadline-task component
- Optimize deadline grouping with O(N) single-pass selector

Other:
- Add deadline-today banner effect for unplanned deadline tasks
- Add translation keys for all deadline UI strings
- Add E2E tests for deadline reminder flows
- Add unit tests for deadline reducer and overdue utility
- Extract shared isDeadlineOverdue utility function
- Guard app-state selectors against undefined during teardown
2026-03-15 18:48:00 +01:00
Johannes Millan
a276ccb3f4 fix: resolve pre-existing lint and prettier errors blocking commits (#6840) 2026-03-15 16:47:52 +01:00
Johannes Millan
da6d70bae5 fix(recurring): preserve due date when selecting quick setting (#6766)
Selecting a monthly/yearly quick setting overwrote startDate with
today's date because the change callback called getQuickSettingUpdates
without a reference date. Now passes the model's current startDate.
Also adds dueWithTime fallback in _getReferenceDate().
2026-03-15 16:47:52 +01:00
Johannes Millan
c248d54508 test(e2e): add deadline reminder e2e test
Verifies that a deadline reminder shows the task in the dialog and
does not re-trigger infinitely after dismissal.
2026-03-14 13:04:44 +01:00
Johannes Millan
80c178cf03 test(e2e): use correct route /#/tag/TODAY/tasks instead of /#/tag/TODAY
The route /#/tag/TODAY has no default child component — only sub-routes
like /worklog, /quick-history render content. The /tasks route is defined
as a separate eagerly-loaded route, not as a child of /tag/:id. Navigating
to /#/tag/TODAY leaves an empty router-outlet, causing 6 test failures
and 1 flaky test.
2026-03-13 19:33:17 +01:00
Johannes Millan
66d051ec28 test(e2e): fix flaky project creation and context switching tests
Replace broken getByRole selector for project name input with a
direct DOM selector, replace hardcoded waitForTimeout calls with
proper element-based waits (waitForTaskList, waitFor visible, toBeEnabled).
2026-03-10 21:56:40 +01:00
Johannes Millan
cf7fa73e5b test(e2e): fix flaky delete-vs-update test and remove obsolete encryption tests
- Fix flaky "Concurrent Delete vs. Update" test with deterministic
  delete-wins assertion instead of permissive either-outcome check
- Delete supersync-encryption-enable-disable.spec.ts (4 tests) and
  supersync-encryption-prompt-loop.spec.ts (2 tests) — these tested
  optional encryption flows that no longer exist since encryption
  became mandatory for SuperSync
2026-03-07 22:32:03 +01:00
Johannes Millan
a54de5f90d test(e2e): fix failing supersync E2E tests
- Wrong-password overwrite: remove Client A sync blocked by decrypt dialog
- Complex chain (4.1): rewrite without unreliable renameTask helper
- Delete vs Update race: fix assertions to expect delete wins
- Deleted task dueDay=today: same delete-wins fix, rename test
- Subtask conflicts: restructure so A marks done subtask from B
- Import tests: add syncImportChoice 'local' to preserve imported data
- Various other test fixes for reliability
2026-03-07 22:32:03 +01:00
Johannes Millan
5401bb7f1d test(e2e): fix 11 failing supersync import tests
- Fix importBackupFile() to wait for actual import completion via console
  event instead of unreliable URL polling
- Fix setupSuperSync to respect syncImportChoice config in all code paths
- Add .first() to task locators that resolve to multiple elements on
  project pages (backlog + active sections)
- Add decryptionFailedPassword config to handle "Decryption Failed" dialog
  when server has old encrypted ops from before encryption changes
- Skip 1 test (unencrypted→encrypted) that needs server-side isCleanSlate fix
2026-03-07 13:28:20 +01:00
Johannes Millan
069873126d test(e2e): fix supersync error scenario tests and skip failing import tests
- Update error scenario mocks to use new OpUploadResponse format
  ({ results: OpUploadResult[] } instead of { piggybacked, rejectedOps })
- Use route.fetch() to get real op IDs from server for mock responses
- Add syncImportChoice option to SuperSyncConfig for import test control
- Skip 3 import-clean-server-state tests pending server-side isCleanSlate fix
2026-03-06 23:08:37 +01:00
Johannes Millan
e8f5f1d404 test(e2e): fix supersync encryption tests for mandatory encryption
- Skip "disable encryption" test: button is hidden for SuperSync
- Skip "encryption prompt loop" tests: unencrypted SuperSync no longer possible
- Fix "wrong password" test: assert decrypt error dialog directly instead
  of checking for post-dialog snackbar/error indicators
- Fix "password change recovery" test: handle sync-import-conflict dialog
  that appears after retry decrypt due to clean slate from password change
2026-03-06 18:19:26 +01:00
Johannes Millan
cce9576946 test(e2e): fix supersync E2E tests for mandatory encryption flow
- Extract shared encryption warning helper and fix race conditions
- Restructure concurrent-import tests to import before enabling sync
- Fix encryption password preservation and change tests
- Add "Change Password" button detection in supersync page object
- Mark backup-import ID mismatch test as fixme (known limitation)
2026-03-06 16:36:38 +01:00
Johannes Millan
755cd705f5
Fix/run 22683814946 (#6740)
test(e2e): fix e2e tests
2026-03-05 19:37:48 +01:00
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
6394fa4363
Claude/fix failing e2e tests ov lxs (#6721)
* test(e2e): fix SuperSync encryption overlay and plugin build in CI

Two root causes for failing e2e tests:

1. Plugin build failure in global-setup.ts: The plugin manifest check
   only looked at the dev path (src/assets/bundled-plugins/) but not the
   CI pre-built path (.tmp/angular-dist/browser/assets/bundled-plugins/).
   In CI, the frontend is pre-built and downloaded as an artifact, so the
   dev path doesn't exist. This caused all WebDAV tests to fail.

2. SuperSync enableEncryption overlay blocking: The sync wrapper opens
   a mandatory encryption dialog with disableClose:true after a successful
   sync when encryption is not yet configured. ensureOverlaysClosed()
   uses Escape key which cannot dismiss disableClose dialogs.

   Fixes:
   - Add enableEncryptionDialog to the sync outcome race so the mandatory
     dialog is detected immediately instead of waiting for a 30s timeout
   - enableEncryption() now checks if the dialog is already open and
     handles it directly instead of trying to right-click the sync button
   - Extract _fillAndConfirmEncryptionDialog() and
     _waitForEncryptionSyncComplete() helpers for reuse
   - Improve enable encryption button lookup to check both top-level
     (SuperSync) and Advanced collapsible positions

https://claude.ai/code/session_01CnQXCAB3WYnYdKPbNEqUS3

* chore: update package-lock.json after npm install

Regenerated lock file to resolve workspace dependencies including
vite-plugin's devDependencies (@types/node, vite, typescript).

https://claude.ai/code/session_01CnQXCAB3WYnYdKPbNEqUS3

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 00:59:02 +01:00
Johannes Millan
68a2d8a9b7 test(e2e): fix flaky tests with better waits and focus handling
Replace unreliable networkidle waits with explicit element/URL waits,
improve keyboard focus handling with retry logic, fix strict mode
violations, and add hover before note menu interactions.
2026-03-03 21:46:11 +01:00
Johannes Millan
7c746fb48d fix(e2e): disable reuseExistingServer to prevent stale server issues
With reuseExistingServer: true, Playwright silently reuses whatever
is on port 4242 without health checks. A stale ng serve that no
longer serves assets causes all tests to fail with cryptic 404s.
Setting false makes Playwright fail fast with a clear error message.
2026-03-03 20:31:37 +01:00
Johannes Millan
855079b353 test(e2e): fix skip break button selector in pomodoro tests
The regex /skip|start/i matched "restart_alt" (mat-icon text in
the "Reset session counter" button) before "Skip break", causing
the wrong button to be clicked and the break screen to stay visible.
2026-03-03 20:14:54 +01:00
Johannes Millan
0a1fc28067 fix(sync): preserve SuperSync encryption config during form saves
The Formly form model defaults isEncryptionEnabled to false. When
_updatePrivateConfig() merges form values over the saved config,
this overwrites the true value set by the EnableEncryption dialog.
Every subsequent sync then triggers _promptSuperSyncEncryptionIfNeeded(),
re-opening the encryption dialog and causing DecryptNoPasswordError
on other clients.

For SuperSync, isEncryptionEnabled is now preserved from the saved
config since it is managed exclusively by dedicated dialogs
(EnableEncryption, DisableEncryption, HandleDecryptError).

Also hardens the E2E page object to handle encryption dialogs that
appear mid-sync (enter_password, enable_encryption) using a stored
password from setupSuperSync().
2026-03-03 20:14:54 +01:00
Florian Bachmann
729d35501f
Fix immutable caldav task (#6705)
* Fix immutable CalDAV task after completion

* Linting

* Resolves Claude suggestions
2026-03-03 15:05:57 +01:00
Johannes Millan
8a6df3634d test(e2e): fix strict mode violation in encryption password dialog locator
The dialog-enter-encryption-password now has two mat-flat-button buttons
when SuperSync is active (Save & Sync + Force Overwrite). The e2e locator
'button[mat-flat-button]' resolved to 2 elements causing Playwright strict
mode failures across all encryption-related SuperSync tests. Added
[color="primary"] to uniquely target the Save & Sync button.
2026-03-03 11:27:19 +01:00
Johannes Millan
ff444c1b77 test(sync): add E2E tests for max retry rejection and import encryption preservation 2026-03-01 21:27:08 +01:00
Johannes Millan
baa9a46935 test(sync): add encryption and supersync e2e test coverage
Add comprehensive test coverage for the encryption and SuperSync features:

- Add e2e tests for encryption prompt loop, error scenarios, no-op sync
- Add e2e tests for provider switch, re-enable, account reset, server migration
- Add e2e tests for import clean-slate scenario
- Add unit tests for encryption dialogs, toggle, enable/disable services
- Add unit tests for sync-config, sync-wrapper, file-based-encryption
- Add unit tests for operation-log-sync, sync-import-filter, clean-slate
- Update supersync page object for mandatory encryption flows
2026-03-01 21:27:08 +01:00
Johannes Millan
8a15d3a477 test(e2e): fix note edit test clicking wrong element
Click .markdown-preview instead of the note element, since the
editFullscreen handler is on the inner div, not the note component.
2026-02-25 16:32:15 +01:00
overcuriousity
dc7742d354
fix: profile system bugs (#6614)
* fixes to the profile system storage which worked unreliable across multiple storage backends

* fix tests

* fix issues with tests

* address copilot reviews
2026-02-23 17:43:04 +01:00
Johannes Millan
60e9b27c1b fix: improve date format reactivity, e2e error logging, and type annotation
Make MAT_DATE_FORMATS dateInput reactive via getter properties so locale
changes take effect without app reload. Always log uncaught page errors
in E2E tests while keeping verbose console output behind E2E_VERBOSE.
Add eslint-disable comment for interface-required `any` in CustomDateAdapter.
2026-02-21 11:29:44 +01:00
Johannes Millan
121ef9f7cd fix(timepicker): add missing parse.timeInput to MAT_DATE_FORMATS
MatTimepicker requires parse.timeInput in MAT_DATE_FORMATS but only
parse.dateInput was provided, causing the date-time dialog to crash.
Also simplify flaky planner visibility test assertions.
2026-02-21 11:29:44 +01:00
Johannes Millan
233773c11d chore(e2e): suppress console/page error logging behind E2E_VERBOSE 2026-02-21 11:29:44 +01:00
Johannes Millan
ee08464a49 chore(e2e): remove temporary 404 diagnostic logging 2026-02-21 11:29:44 +01:00
Johannes Millan
80540d8371 test(e2e): add detail panel focus sync tests (#6578) 2026-02-21 11:29:44 +01:00
Johannes Millan
141a229bd9 test(sync): add vector clock pruning and migration persistClientId tests
Add integration tests for mergeRemoteOpClocks pruning against real
IndexedDB (25+ clients pruned, <MAX preserved, null client ID fallback).
Add unit tests for migration persistClientId call with legacy ID and
generate-new-ID path. Fix flaky planner E2E test by waiting for task
render after route change.
2026-02-17 18:34:30 +01:00
Johannes Millan
54197c66b4 style(e2e): fix prettier formatting in planner spec 2026-02-16 18:44:27 +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
efd307ab84 test(sync): add encryption and gap detection tests, fix E2E navigation race
- Add E2E test for encryption + USE_LOCAL conflict resolution, validating
  the double-encryption bug fix (b70a0e5634) end-to-end
- Add integration tests for partial trimming gap detection with
  syncVersion-based check across multi-client scenarios
- Add integration tests for encrypted sync round-trips (ops, snapshots,
  concurrent uploads)
- Fix systemic "waiting for navigation to finish" failures in WebDAV E2E
  tests by adding noWaitAfter and waitForURL to SyncPage methods,
  matching the pattern already used in SuperSyncPage
2026-02-15 11:19:22 +01:00