mirror of
https://github.com/Sea-Haven-Industries/meal-order-manager.git
synced 2026-10-07 16:18:54 +00:00
test(form): cover sticky footer at narrow widths
This commit is contained in:
parent
fca2ec6044
commit
38a743db37
1 changed files with 139 additions and 25 deletions
|
|
@ -82,6 +82,27 @@ def _google_credential() -> str:
|
|||
return f"e30.{encoded}.signature"
|
||||
|
||||
|
||||
def _mock_form_routes(page):
|
||||
page.route(
|
||||
"**/api/form-status/**",
|
||||
lambda route: route.fulfill(
|
||||
status=200,
|
||||
content_type="application/json",
|
||||
body='{"status":"open"}',
|
||||
),
|
||||
)
|
||||
page.route(
|
||||
"**/api/roster**",
|
||||
lambda route: route.fulfill(
|
||||
status=200,
|
||||
content_type="application/json",
|
||||
body=json.dumps(
|
||||
{"employees": [{"name": "Ada Lovelace", "email": "ada@example.com"}]}
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class TestGenerateFormStructural:
|
||||
def test_local_and_google_render(self):
|
||||
local = _render(google=False)
|
||||
|
|
@ -140,6 +161,18 @@ class TestGenerateFormStructural:
|
|||
local = _render(google=False)
|
||||
assert "<script src=" not in local
|
||||
|
||||
def test_mobile_viewport_and_safe_area_clearance_are_preserved(self):
|
||||
html = _render()
|
||||
css = (SERVER_DIR / "templates" / "form.css").read_text()
|
||||
assert (
|
||||
'content="width=device-width, initial-scale=1.0, viewport-fit=cover"'
|
||||
in html
|
||||
)
|
||||
assert "padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px));" in css
|
||||
assert (
|
||||
"padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));"
|
||||
) in css
|
||||
|
||||
def test_script_order_form_then_admin(self):
|
||||
html = _render()
|
||||
form_pos = html.index("FORM_JS_MARKER")
|
||||
|
|
@ -224,37 +257,118 @@ class TestGenerateFormPlaywright:
|
|||
) from exc
|
||||
try:
|
||||
page = browser.new_page()
|
||||
page.route(
|
||||
"**/api/form-status/**",
|
||||
lambda route: route.fulfill(
|
||||
status=200,
|
||||
content_type="application/json",
|
||||
body='{"status":"open"}',
|
||||
),
|
||||
)
|
||||
page.route(
|
||||
"**/api/roster**",
|
||||
lambda route: route.fulfill(
|
||||
status=200,
|
||||
content_type="application/json",
|
||||
body=json.dumps(
|
||||
{
|
||||
"employees": [
|
||||
{
|
||||
"name": "Ada Lovelace",
|
||||
"email": "ada@example.com",
|
||||
}
|
||||
]
|
||||
}
|
||||
),
|
||||
),
|
||||
)
|
||||
_mock_form_routes(page)
|
||||
page.goto(out.as_uri())
|
||||
page.wait_for_selector('[data-meal-index="0"]')
|
||||
yield page
|
||||
finally:
|
||||
browser.close()
|
||||
|
||||
@pytest.mark.parametrize("width", [320, 375, 480])
|
||||
@pytest.mark.parametrize("google", [False, True], ids=["local", "google"])
|
||||
def test_sticky_footer_fits_narrow_viewports(self, tmp_path, width, google):
|
||||
sync_api = pytest.importorskip("playwright.sync_api")
|
||||
sync_playwright = sync_api.sync_playwright
|
||||
|
||||
html_path = tmp_path / f"order-form-{'google' if google else 'local'}.html"
|
||||
html_path.write_text(_render(google=google, api_key=""))
|
||||
|
||||
with sync_playwright() as p:
|
||||
try:
|
||||
browser = p.chromium.launch(headless=True)
|
||||
except Exception as exc:
|
||||
raise RuntimeError(
|
||||
"Chromium is required for form Playwright tests. "
|
||||
"Run: playwright install --with-deps chromium"
|
||||
) from exc
|
||||
try:
|
||||
page = browser.new_page(viewport={"width": width, "height": 800})
|
||||
page.add_init_script(
|
||||
"""window.google = {
|
||||
accounts: {
|
||||
id: {
|
||||
initialize() {},
|
||||
renderButton() {},
|
||||
disableAutoSelect() {},
|
||||
},
|
||||
},
|
||||
};"""
|
||||
)
|
||||
page.route(
|
||||
"https://accounts.google.com/gsi/client",
|
||||
lambda route: route.abort(),
|
||||
)
|
||||
_mock_form_routes(page)
|
||||
|
||||
page.goto(html_path.as_uri(), wait_until="domcontentloaded")
|
||||
page.wait_for_selector('[data-meal-index="0"]', state="attached")
|
||||
if google:
|
||||
page.evaluate(
|
||||
"(credential) => handleCredentialResponse({ credential })",
|
||||
_google_credential(),
|
||||
)
|
||||
page.wait_for_selector('[data-meal-index="0"]', state="visible")
|
||||
|
||||
first_increment = page.locator(
|
||||
'[data-meal-index="0"] [data-qty-delta="1"]'
|
||||
)
|
||||
first_increment.click()
|
||||
first_increment.click()
|
||||
page.wait_for_function(
|
||||
"() => document.getElementById('count-display').textContent === "
|
||||
"'2 meals'"
|
||||
)
|
||||
page.evaluate("() => document.fonts.ready")
|
||||
|
||||
total = page.locator("#total-display")
|
||||
count = page.locator("#count-display")
|
||||
submit = page.locator("#submit-btn")
|
||||
assert total.inner_text() == "$10.80"
|
||||
assert count.inner_text() == "2 meals"
|
||||
assert total.is_visible()
|
||||
assert count.is_visible()
|
||||
assert submit.is_visible()
|
||||
assert submit.is_enabled()
|
||||
submit.focus()
|
||||
assert submit.evaluate(
|
||||
"(element) => element === document.activeElement"
|
||||
)
|
||||
|
||||
page.evaluate(
|
||||
"() => window.scrollTo(0, document.documentElement.scrollHeight)"
|
||||
)
|
||||
layout = page.evaluate(
|
||||
"""() => {
|
||||
const rect = (selector) => {
|
||||
const box = document.querySelector(selector)
|
||||
.getBoundingClientRect();
|
||||
return {
|
||||
left: box.left,
|
||||
right: box.right,
|
||||
top: box.top,
|
||||
bottom: box.bottom,
|
||||
};
|
||||
};
|
||||
return {
|
||||
clientWidth: document.documentElement.clientWidth,
|
||||
scrollWidth: document.documentElement.scrollWidth,
|
||||
footer: rect('#sticky-footer'),
|
||||
total: rect('#total-display'),
|
||||
count: rect('#count-display'),
|
||||
submit: rect('#submit-btn'),
|
||||
lastCard: rect('#meals-list .meal-card:last-child'),
|
||||
};
|
||||
}"""
|
||||
)
|
||||
|
||||
assert layout["scrollWidth"] == layout["clientWidth"]
|
||||
for selector in ("footer", "total", "count", "submit"):
|
||||
assert layout[selector]["left"] >= 0
|
||||
assert layout[selector]["right"] <= layout["clientWidth"]
|
||||
assert layout["lastCard"]["bottom"] <= layout["footer"]["top"]
|
||||
finally:
|
||||
browser.close()
|
||||
|
||||
def test_admin_bundle_loads(self, browser_page):
|
||||
assert browser_page.evaluate("typeof window.loadWeekOrders") == "function"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue