Files
ecw-charge-validation/tests/test_login_username_step.py
T

110 lines
3.6 KiB
Python

r"""
auth/login.py `wait_after_username()` — what comes after the username's
Next (live 2026-10-28 17:59: the security image page came late, the old
one-look check missed it, and the bot clicked a password box that stayed
disabled until it timed out).
It waits, up to its timeout, for whichever comes first: eCW's "VERIFY YOUR
SECURITY IMAGE" page or a password box that is visible AND enabled. Neither
→ a screenshot (with the DOM) and an error that says so.
python tests\test_login_username_step.py
Local headless chromium, `page.set_content()` only. No eCW, no login.
"""
import sys
import time
import pathlib
import tempfile
ROOT = pathlib.Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "src"))
from ecw_bot import settings as cfg # noqa: E402
from ecw_bot.auth import login # noqa: E402
CASES = []
def case(fn):
CASES.append(fn)
return fn
# The password box is on the page from the start, disabled — the shape
# seen live; eCW enables it once the username step is done.
_PAGE = """
<input id="doctorID" value="someone">
<input disabled type="password" id="passwordField">
<div id="img" style="display:none">VERIFY YOUR SECURITY IMAGE</div>
<script>%s</script>
"""
@case
def a_late_security_image_page_is_seen(page):
page.set_content(_PAGE % "setTimeout(() => document.getElementById("
"'img').style.display = '', 3000);")
assert login.wait_after_username(page, 10_000) == "image"
@case
def a_password_box_enabled_late_is_waited_for(page):
page.set_content(_PAGE % "setTimeout(() => document.getElementById("
"'passwordField').disabled = false, 2500);")
t0 = time.monotonic()
assert login.wait_after_username(page, 10_000) == "password"
assert time.monotonic() - t0 >= 2, "returned before it was enabled"
@case
def after_the_image_only_the_password_box_counts(page):
page.set_content(_PAGE % "document.getElementById('img').style.display"
" = ''; setTimeout(() => document.getElementById("
"'passwordField').disabled = false, 1500);")
assert login.wait_after_username(page, 10_000, image=False) == "password"
@case
def a_password_box_that_stays_disabled_is_an_error_with_a_screenshot(page):
page.set_content(_PAGE % "")
try:
login.wait_after_username(page, 2_000)
except RuntimeError as exc:
assert "password box stayed disabled" in str(exc), exc
else:
raise AssertionError("no error for a box that never enabled")
shots = list(pathlib.Path(cfg.SCREENSHOTS).glob("*_username_step_disabled.*"))
assert {p.suffix for p in shots} == {".png", ".html"}, shots
def main() -> int:
from playwright.sync_api import sync_playwright
failures = 0
with tempfile.TemporaryDirectory() as tmp:
cfg.SCREENSHOTS = pathlib.Path(tmp) # never the real folder
with sync_playwright() as pw:
browser = pw.chromium.launch(headless=True)
page = browser.new_page()
for fn in CASES:
name = fn.__name__.replace("_", " ")
try:
fn(page)
print(f" ok {name}")
except AssertionError as exc:
print(f" FAIL {name}: {exc}")
failures += 1
except Exception as exc:
print(f" ERROR {name}: {type(exc).__name__}: {exc}")
failures += 1
browser.close()
print(f"\n{len(CASES) - failures}/{len(CASES)} passed")
return 1 if failures else 0
if __name__ == "__main__":
sys.exit(main())