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.
- 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.
- 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)
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>
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.
- 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
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
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
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
* 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>
- 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
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.
- 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
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.
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
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().
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.
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).
- 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
- 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
- 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
- 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
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.
* 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>
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.
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.
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().
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.
* fixes to the profile system storage which worked unreliable across multiple storage backends
* fix tests
* fix issues with tests
* address copilot reviews
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.
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.
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.
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.
- 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