Skip to content

[NA] [QA] test(e2e): retry model-picker click to fix Playground flake#7401

Merged
AndreiCautisanu merged 1 commit into
mainfrom
andreic/NA-playground-model-picker-flake
Jul 9, 2026
Merged

[NA] [QA] test(e2e): retry model-picker click to fix Playground flake#7401
AndreiCautisanu merged 1 commit into
mainfrom
andreic/NA-playground-model-picker-flake

Conversation

@AndreiCautisanu

Copy link
Copy Markdown
Contributor

Problem

PlaygroundPage.setModelForVariant clicks the model picker once, then waits for the options listbox to appear. On higher-latency environments the first click sometimes registers as a hover — surfacing the model's tooltip instead of opening the popover — so the listbox never becomes visible and the step times out after 15s.

Observed as a repeated failure (initial attempt + both retries) on the Bayer stsaas regression run (playground-smoke → "Run prompts against a dataset auto-creates an experiment"). The failure snapshot showed the trigger [active] with a tooltip rendered but no listbox — the click landed but didn't open the popover. The test has a long clean pass streak on every other environment and is flagged flaky in TestOps.

Fix

Wrap the click in expect(async () => { … }).toPass() so it re-clicks the trigger until the listbox actually opens, instead of firing once and waiting. Strictly safer than the original — same selectors, same assertions, just resilient to a click that doesn't register as opening the popover.

const listbox = this.page.getByRole('listbox');
await expect(async () => {
  await this.modelPicker(index).click();
  await expect(listbox).toBeVisible({ timeout: 2_000 });
}).toPass({ timeout: 15_000 });

Testing

  • tsc --noEmit clean; playground-smoke verified green locally 3× against a 2.1.13 instance.
  • The same guard was applied to the Optimization Studio POM's selectModel on the e2e-compat/2.1.13 branch (that POM doesn't exist on main yet), which has the identical single-click-then-wait shape.

🤖 Generated with Claude Code

setModelForVariant clicked the model picker once then waited for the listbox,
but on higher-latency environments the first click sometimes registers as a
hover (surfacing a tooltip instead of opening the popover), so the listbox
never appears and the step times out. Wrap the click in an expect().toPass()
loop that re-clicks until the popover actually opens.

Observed as a repeated failure (initial + 2 retries) on the Bayer stsaas
regression run; the test has a long clean streak everywhere else and is flagged
flaky in TestOps. Change is strictly safer than the original (retries the click
rather than firing once). Verified green locally 3x.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@AndreiCautisanu AndreiCautisanu requested review from a team as code owners July 8, 2026 12:31
@github-actions github-actions Bot added tests Including test files, or tests related like configuration. typescript *.ts *.tsx labels Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

📋 PR Linter Failed

Missing Section. The description is missing the ## Details section.


Missing Section. The description is missing the ## Change checklist section.


Missing Section. The description is missing the ## Issues section.


Missing Section. The description is missing the ## Documentation section.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

⏱️ pre-commit per-hook timing

No linted files changed — nothing to run.

⏭️ 41 skipped (no matching files changed)
Hook Description Result
🐍 trim trailing whitespace — python sdk Strip trailing whitespace ⏭️
🐍 fix end of files — python sdk Ensure files end in a newline ⏭️
🐍 ruff — python sdk Lint + autofix Python (ruff) ⏭️
🐍 ruff-format — python sdk Format Python code (ruff) ⏭️
🐍 mypy — python sdk Static type check ⏭️
🤖 trim trailing whitespace — optimizer Strip trailing whitespace ⏭️
🤖 fix end of files — optimizer Ensure files end in a newline ⏭️
🤖 check yaml — optimizer Validate YAML syntax ⏭️
🤖 check json — optimizer Validate JSON syntax ⏭️
🤖 check toml — optimizer Validate TOML syntax ⏭️
🤖 check for added large files — optimizer Block large files (>1MB) ⏭️
🔐 detect private key — optimizer Block committed private keys ⏭️
🤖 check for merge conflicts — optimizer Block merge-conflict markers ⏭️
🤖 check for case conflicts — optimizer Block case-only name clashes ⏭️
🤖 pyupgrade — optimizer Modernize Python syntax ⏭️
🤖 ruff — optimizer Lint + autofix Python (ruff) ⏭️
🤖 ruff-format — optimizer Format Python code (ruff) ⏭️
🤖 mypy — optimizer Static type check ⏭️
📓 nbstripout — optimizer notebooks Strip notebook output ⏭️
📝 markdownlint — optimizer Lint Markdown ⏭️
🔤 codespell — optimizer Fix common misspellings ⏭️
📊 radon cc — optimizer Cyclomatic-complexity gate ⏭️
📊 radon raw — optimizer Raw size metrics gate ⏭️
📊 xenon — optimizer Fail on complexity thresholds ⏭️
📊 lizard — optimizer Cyclomatic-complexity gate ⏭️
🧹 vulture — optimizer Find dead code ⏭️
🛡️ trim trailing whitespace — guardrails Strip trailing whitespace ⏭️
🛡️ fix end of files — guardrails Ensure files end in a newline ⏭️
🛡️ ruff — guardrails Lint + autofix Python (ruff) ⏭️
🛡️ ruff-format — guardrails Format Python code (ruff) ⏭️
🛡️ mypy — guardrails Static type check ⏭️
⚓ helm-docs Regenerate Helm chart README ⏭️
block non-public FE plugins Block non-public FE plugins ⏭️
☕ spotless — java backend Format Java code ⏭️
🧪 pre-commit wrapper smoke tests Self-test the wrapper scripts ⏭️
🌐 eslint — frontend Lint + autofix JS/TS ⏭️
🌐 typecheck — frontend Whole-project tsc type check ⏭️
📘 eslint — typescript sdk Lint + autofix JS/TS ⏭️
📘 typecheck — typescript sdk Whole-project tsc type check ⏭️
⚙️ actionlint — github workflows Lint GitHub Actions workflows ⏭️
🐳 hadolint — dockerfiles Lint Dockerfiles ⏭️

Comment on lines 470 to +474
private async setModelForVariant(index: number, modelDisplayName: string): Promise<void> {
await this.modelPicker(index).click();
const listbox = this.page.getByRole('listbox');
await listbox.waitFor({ state: 'visible' });
// The trigger occasionally swallows the first click as a hover (surfacing a
// tooltip instead of opening the popover), so retry the click until the
// listbox actually opens rather than firing once and waiting.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing POM step tracing

setModelForVariant() now does the click/retry sequence inline, so Playwright only records the outer callers and we lose a dedicated step for model selection, which makes flakes harder to isolate — should we wrap the helper body in test.step(...) like the other POM methods, as .agents/skills/writing-e2e-tests/conventions.md asks?

Severity

Want Baz to fix this for you? Activate Fixer You can also update your AI coding guidelines based on this comment by apply pr to [branch name]

Other fix methods

Fix in Cursor

Prompt for AI Agents
Before applying, verify this suggestion against the current code. In
tests_end_to_end/e2e/pom/playground.page.ts around lines 470-481, in the private helper
`setModelForVariant(index: number, modelDisplayName: string)`, wrap the entire method
body in a dedicated `test.step(...)` block (including the click/retry logic and the
listbox fill/option click). Use a clear step description like `select model for variant
{index}` (or similar) so the Playwright report includes a trace specifically for this
interaction. Ensure the existing retry behavior remains unchanged inside the step.

@AndreiCautisanu AndreiCautisanu merged commit d9a6920 into main Jul 9, 2026
11 of 12 checks passed
@AndreiCautisanu AndreiCautisanu deleted the andreic/NA-playground-model-picker-flake branch July 9, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests Including test files, or tests related like configuration. typescript *.ts *.tsx

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants