From bbe53c68efcfb0676b63e17ec31c58bd5e9fff1d Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Mon, 11 May 2026 05:25:57 -0700 Subject: [PATCH] studio/tests: make Playwright model-selector probe best-effort (#5371) * studio/tests: make Playwright model-selector probe best-effort The Mac Studio UI CI run 25664825320 / job 75334476211 failed at playwright_chat_ui.py:483 with: playwright._impl._errors.TimeoutError: Locator.text_content: Timeout 60000ms exceeded. Timeline from that job's log: 11:40:51 [ui] OK default_models[0] = unsloth/gemma-4-E2B-it-GGUF 11:41:51 TimeoutError (exactly 60 s later) Root cause: count() and text_content() are two independent queries against the live DOM. The chat surface re-mounts the model selector while /api/models/list resolves the default-model badge, so the button matches the OR-selector at count() time but is briefly detached when text_content() re-queries. The page-wide default action timeout was bumped to 60 s on line 177, so the informational probe blocked for a full minute and then hard-failed. The block is clearly best-effort: it is gated on if count() > 0 and the only side effects are info(...) and shoot(...). Replace the count-then-text dance with a single text_content(timeout=2_000) inside a try/except, matching the pattern the rest of this file already uses for networkidle, screenshot capture, and composer wait. Happy path still prints the button text and snaps 03b-default-model-button; a miss now logs WARN and continues to the /api/inference/load step. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- tests/studio/playwright_chat_ui.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/studio/playwright_chat_ui.py b/tests/studio/playwright_chat_ui.py index 3f4ee6704c..8f7dafa2a4 100644 --- a/tests/studio/playwright_chat_ui.py +++ b/tests/studio/playwright_chat_ui.py @@ -479,8 +479,16 @@ with sync_playwright() as p: 'button:has-text("Qwen"), ' 'button:has-text("Llama")' ).first - if selector_btn.count() > 0: - sel_text = (selector_btn.text_content() or "").strip() + # Best-effort: the selector re-mounts as /api/models/list resolves, + # so use a short timeout and skip the snapshot on miss. + sel_text = "" + try: + sel_text = (selector_btn.text_content(timeout = 2_000) or "").strip() + except Exception as _sel_err: + info( + f"WARN: model-selector probe skipped: {type(_sel_err).__name__}: {_sel_err}" + ) + if sel_text: info(f"model selector button text: {sel_text!r}") shoot("03b-default-model-button")