150 lines
6.1 KiB
Python
150 lines
6.1 KiB
Python
"""
|
|
Backlog — Manual "Check for updates" button in Settings
|
|
|
|
- test_check_for_update_button_visible: The button renders in the "Check Updates" section
|
|
- 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
|
|
- test_last_check_date_shown_never_checked_initially: Fresh DB shows "never checked manually"
|
|
- test_last_check_date_updates_after_click_and_persists: Clicking the button stamps the last-checked date, which survives a reload
|
|
|
|
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).
|
|
"""
|
|
import re
|
|
|
|
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()
|
|
|
|
|
|
def test_last_check_date_shown_never_checked_initially(page: Page, app_url: str):
|
|
"""A fresh DB has never been checked manually, so the fallback text is shown."""
|
|
_go_to_settings(page, app_url)
|
|
last_check = page.locator('[data-testid="settings-last-update-check"]')
|
|
expect(last_check).to_be_visible()
|
|
expect(last_check).to_have_text("Never checked manually")
|
|
|
|
|
|
def test_last_check_date_updates_after_click_and_persists(page: Page, app_url: str):
|
|
"""Clicking the button stamps a last-checked date, which survives a reload."""
|
|
_go_to_settings(page, app_url)
|
|
_mock_check_fn_no_update(page)
|
|
|
|
last_check = page.locator('[data-testid="settings-last-update-check"]')
|
|
expect(last_check).to_have_text("Never checked manually")
|
|
|
|
page.locator('[data-testid="settings-check-for-update"]').click()
|
|
expect(last_check).to_have_text(re.compile(r"^Last manual check: "))
|
|
|
|
page.reload()
|
|
page.wait_for_selector('[data-testid="settings-language"]')
|
|
expect(last_check).to_have_text(re.compile(r"^Last manual check: "))
|