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 = """
""" @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 # The security image page with its own Continue: clicking it is what lets # eCW enable the password box (operator, 2026-10-30: no manual click). _IMAGE_PAGE = """