From af413587f58659cc31a46966d8332380211e5428 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Thu, 18 Jun 2026 01:52:20 +0200 Subject: [PATCH] test(login-flow): disambiguate "Log in" button for NC33 connect page Enabling NC33 surfaced that every login-flow test failed with "Login Flow v2 did not complete after 15 attempts". Root cause: NC33's "Connect to your account" page renders BOTH a "Log in" button and an "Alternative log in using app password" button. The Step-1 locator `get_by_role("button", name="Log in")` is a non-exact (substring) match, so it matched both -> Playwright strict-mode error, which the surrounding try/except silently swallowed. The flow stayed on the connect page, never reached "Grant access", and the poll timed out. Fix: add exact=True to the Step-1 "Log in" locator in both login-flow helpers. NC32's connect page has a single match, so exact=True is safe there. Verified on a live NC33 stack: the exact click reaches the grant page cleanly. Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/server/login_flow/conftest.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/server/login_flow/conftest.py b/tests/server/login_flow/conftest.py index 2906e9e9..3f6e0d41 100644 --- a/tests/server/login_flow/conftest.py +++ b/tests/server/login_flow/conftest.py @@ -246,8 +246,14 @@ async def _complete_login_flow_v2(browser, login_url: str) -> None: await page.goto(login_url, wait_until="networkidle", timeout=60000) logger.info("Step 1 - Current URL: %s", page.url) - # Step 1: "Connect to your account" page - click "Log in" - login_btn = page.get_by_role("button", name="Log in") + # Step 1: "Connect to your account" page - click "Log in". + # exact=True is required: NC33's connect page also renders an + # "Alternative log in using app password" button, and a non-exact + # "Log in" name substring-matches both -> Playwright strict-mode error + # that was silently swallowed below, leaving the flow stuck on the + # connect page (every login-flow test then times out "Login Flow v2 did + # not complete"). NC32 has a single match, so exact=True is safe there. + login_btn = page.get_by_role("button", name="Log in", exact=True) try: await login_btn.wait_for(timeout=10000) await login_btn.click() @@ -803,8 +809,14 @@ async def _complete_login_flow_v2_as_user( await page.goto(login_url, wait_until="networkidle", timeout=60000) logger.info("[%s] Step 1 - Current URL: %s", username, page.url) - # Step 1: "Connect to your account" page - click "Log in" - login_btn = page.get_by_role("button", name="Log in") + # Step 1: "Connect to your account" page - click "Log in". + # exact=True is required: NC33's connect page also renders an + # "Alternative log in using app password" button, and a non-exact + # "Log in" name substring-matches both -> Playwright strict-mode error + # that was silently swallowed below, leaving the flow stuck on the + # connect page (every login-flow test then times out "Login Flow v2 did + # not complete"). NC32 has a single match, so exact=True is safe there. + login_btn = page.get_by_role("button", name="Log in", exact=True) try: await login_btn.wait_for(timeout=10000) await login_btn.click()