""" Backlog — Manual "Check for updates" button in Settings - test_check_for_update_button_visible: The button renders in the new Application card - test_check_for_update_calls_registration_update: Clicking the button forces a re-check (registration.update()) - test_check_for_update_shows_up_to_date_when_nothing_found: No update found -> a transient "up to date" message appears, then disappears - test_check_for_update_found_still_offers_choice: A manual check that finds an update still shows the Update now / Later modal, not an auto-apply - test_up_to_date_message_not_shown_when_update_found: The "up to date" heuristic does not fire when a check does find an update Uses the dev-only test hook `window.__appUpdateTest.mockCheckFn` (see src/composables/useAppUpdate.js) as a stand-in for `registration.update()` — simulating a real service-worker update in Playwright would require two production builds (see Step 24). page.clock drives the "no update found" timeout heuristic deterministically (as in Step 15/26). """ from playwright.sync_api import Page, expect def _wait_for_db(page: Page, app_url: str): page.goto(app_url) page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) def _go_to_settings(page: Page, app_url: str): """Navigate to Settings, waiting for DB and the dev test hook to be ready.""" _wait_for_db(page, app_url) page.click('a[href="#/settings"]') page.wait_for_selector('[data-testid="settings-language"]') page.wait_for_function("!!window.__appUpdateTest", timeout=10000) def _mock_check_fn_no_update(page: Page): """Mock registration.update() as a no-op: the check resolves but nothing changes.""" page.evaluate("""() => { window.__checkCalls = [] window.__appUpdateTest.mockCheckFn = () => { window.__checkCalls.push(true) return Promise.resolve() } }""") def _mock_check_fn_found_update(page: Page): """Mock registration.update() as if it found a new SW: flips `needRefresh`.""" page.evaluate("""() => { window.__checkCalls = [] window.__appUpdateTest.mockCheckFn = () => { window.__checkCalls.push(true) window.__appUpdateTest.trigger() return Promise.resolve() } }""") def test_check_for_update_button_visible(page: Page, app_url: str): """The 'Check for updates' button renders in the new Application card.""" _go_to_settings(page, app_url) expect(page.locator('[data-testid="settings-check-for-update"]')).to_be_visible() def test_check_for_update_calls_registration_update(page: Page, app_url: str): """Clicking the button calls through to registration.update().""" _go_to_settings(page, app_url) _mock_check_fn_no_update(page) page.locator('[data-testid="settings-check-for-update"]').click() calls = page.evaluate("window.__checkCalls") assert calls == [True], f"registration.update() should have been called, got {calls}" def test_check_for_update_shows_up_to_date_when_nothing_found(page: Page, app_url: str): """No update found: a transient 'up to date' message appears, then disappears.""" page.clock.install() _go_to_settings(page, app_url) _mock_check_fn_no_update(page) up_to_date = page.locator('[data-testid="settings-up-to-date"]') expect(up_to_date).not_to_be_visible() page.locator('[data-testid="settings-check-for-update"]').click() expect(up_to_date).not_to_be_visible() # not shown immediately page.clock.run_for(2100) page.wait_for_timeout(100) expect(up_to_date).to_be_visible() page.clock.run_for(3100) page.wait_for_timeout(100) expect(up_to_date).not_to_be_visible() def test_check_for_update_found_still_offers_choice(page: Page, app_url: str): """A manual check that finds an update still shows Update now / Later — updating stays optional.""" page.clock.install() _go_to_settings(page, app_url) _mock_check_fn_found_update(page) page.locator('[data-testid="settings-check-for-update"]').click() modal = page.locator('[data-testid="app-update-modal"]') expect(modal).to_be_visible() expect(page.locator('[data-testid="app-update-now"]')).to_be_visible() expect(page.locator('[data-testid="app-update-later"]')).to_be_visible() def test_up_to_date_message_not_shown_when_update_found(page: Page, app_url: str): """The 'up to date' heuristic does not fire when a check does find an update.""" page.clock.install() _go_to_settings(page, app_url) _mock_check_fn_found_update(page) page.locator('[data-testid="settings-check-for-update"]').click() expect(page.locator('[data-testid="app-update-modal"]')).to_be_visible() page.clock.run_for(2100) page.wait_for_timeout(100) expect(page.locator('[data-testid="settings-up-to-date"]')).not_to_be_visible()