From 2759d9a36f44532b0cf52f749ce37b618e6c5d06 Mon Sep 17 00:00:00 2001 From: Bu5hm4nn Date: Thu, 26 Mar 2026 13:59:56 +0100 Subject: [PATCH] fix(settings): track dirty state across all inputs --- app/pages/settings.py | 13 ++++++++++++- ...3A-alerts-settings-entrypoint-normalization.yaml | 2 +- tests/test_settings_validation_playwright.py | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/pages/settings.py b/app/pages/settings.py index dbbee79..d77edf2 100644 --- a/app/pages/settings.py +++ b/app/pages/settings.py @@ -390,7 +390,18 @@ def settings_page(workspace_id: str) -> None: for element in (entry_basis_mode, entry_price, gold_value, gold_ounces): element.on_value_change(update_entry_basis) - for element in (loan_amount, margin_threshold, ltv_warning, email_alerts): + for element in ( + loan_amount, + margin_threshold, + monthly_budget, + ltv_warning, + vol_alert, + price_alert, + email_alerts, + primary_source, + fallback_source, + refresh_interval, + ): element.on_value_change(update_calculations) apply_entry_basis_mode() diff --git a/docs/roadmap/done/CORE-001D3A-alerts-settings-entrypoint-normalization.yaml b/docs/roadmap/done/CORE-001D3A-alerts-settings-entrypoint-normalization.yaml index 49d9e5d..f941264 100644 --- a/docs/roadmap/done/CORE-001D3A-alerts-settings-entrypoint-normalization.yaml +++ b/docs/roadmap/done/CORE-001D3A-alerts-settings-entrypoint-normalization.yaml @@ -18,4 +18,4 @@ completed_notes: - Settings save-status formatting now snapshots numeric boundary values through a named adapter before rendering. - Added focused regression tests for numeric-string coercion and bool fail-closed behavior in `tests/test_alerts.py` and `tests/test_settings.py`. - Hardened `/{workspace_id}/settings` so blank loan input no longer silently saves as a zero-loan portfolio; the loan field now preserves blank state until validation, keeps whole-dollar formatting stable, and marks the save card as `Last saved` / `Unsaved invalid changes` instead of presenting stale saved state as current. - - Validated with focused pytest coverage, browser-visible Playwright coverage, and `make build` on local Docker. + - Validated with focused pytest coverage, browser-driven Playwright coverage on local Docker, and `make build`. diff --git a/tests/test_settings_validation_playwright.py b/tests/test_settings_validation_playwright.py index 6f3e66d..50eab94 100644 --- a/tests/test_settings_validation_playwright.py +++ b/tests/test_settings_validation_playwright.py @@ -19,6 +19,13 @@ def test_settings_reject_invalid_loan_amount_without_silent_zero_fallback() -> N page.goto(f"{workspace_url}/settings", wait_until="domcontentloaded", timeout=30000) expect(page.locator("text=Settings").first).to_be_visible(timeout=15000) expect(page.locator("text=Last saved:").first).to_be_visible(timeout=15000) + + page.get_by_label("Refresh interval (seconds)").fill("7") + expect(page.locator("text=Unsaved changes — Last saved:").first).to_be_visible(timeout=15000) + page.reload(wait_until="domcontentloaded", timeout=30000) + expect(page.get_by_label("Refresh interval (seconds)")).to_have_value("5") + expect(page.locator("text=Last saved:").first).to_be_visible(timeout=15000) + loan_input = page.get_by_label("Loan amount ($)") loan_input.fill("") loan_input.press("Tab")