Skip to content

Let fillField clear the QAN search box, not a separate clearField - #1190

Closed
claude[bot] wants to merge 1 commit into
mainfrom
claude/elegant-cerf-ma54gp
Closed

Let fillField clear the QAN search box, not a separate clearField#1190
claude[bot] wants to merge 1 commit into
mainfrom
claude/elegant-cerf-ma54gp

Conversation

@claude

@claude claude Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Failures fixed (investigator)

  • source: Nightly E2E tests Matrix (remote PMM Server) run 31981108239 (main @ 37a003d), job test execution / @qan|@menu|@valkey-nightly|@permissions-nightly|@pt-summary-nightly|@pbm-nightly (95247925371)
  • tests:
    • codeceptjs-e2e/tests/QAN/overview_test.js:31 / @qan — PMM-T1061 "Verify Plan and PlanID with pg_stat_monitor"
    • codeceptjs-e2e/tests/QAN/details_explain_test.js:103 / @qan — PMM-T1790 "Verify that there is any no error on Explains after switching between queries from different DB servers"

Not a one-off: both have failed the same way in the last three nightlies —
runs 262,
261,
260.

The run's third red test, PMM-T269, is a different failure and is already
covered by #1186 — this PR does not address it, so the lane needs both to go
green. The job's later Record launchable test results step failed only
because launchable gate saw these as Actionable Failures | 3 (0
quarantined); it is not a separate problem.

What failed

Clickable element "//input[contains(@name, "search")]" was not found by text|CSS|XPath
  ✖ I.click("//input[contains(@name, "search")]")   at QueryAnalyticsData.searchByValue (queryAnalyticsData.js:158)
  ✔ I.clearField("//input[contains(@name, "search")]") at QueryAnalyticsData.searchByValue (queryAnalyticsData.js:157)
  ✔ I.waitForVisible("//input[contains(@name, "search")]", 30) at QueryAnalyticsData.searchByValue (queryAnalyticsData.js:155)

The step that waits for the input passes, the step that clears it passes, and
then the step that clicks that same input reports it does not exist.

Root cause — pmm-qa test code, not the product

QAN's Overview search became debounced search-as-you-type in
percona/pmm#5537 (PMM-14848):
Search.tsx now fires handleSearch from onChange through a
SEARCH_DEBOUNCE_MS = 300 debounce, where before it only fired on form submit.
So clearing the field is itself a search.

That matters because of where the search box lives. It is rendered inside the
overview table's first column header
(DefaultColumns.tsxHeaderAccessor: () => <Dimension />Search), and
QanTable swaps the whole table out while a query is in flight:

{loading ? <div data-testid="table-loading"><Spinner /></div> : null}
{!loading ? <div {...getTableProps()} className="table"> …headerGroups.map(RenderHeader)… </div> : null}

So the reload that clearField kicks off unmounts the header row — and the
search input with it — for as long as the query takes. searchByValue cleared
the field and then went looking for that input again, i.e. it re-found an
element its own clear had just swept away.

Read straight out of the failing run's Playwright trace (monotonicTime, ms):

t event
588 070 queryCount('//input[contains(@name,"search")]')1
588 091 → 588 120 fill('') — codecept's clearField — succeeds
588 464.8 debounced empty search fires metrics:getReport (fill + ~345 ms ≈ the 300 ms debounce)
588 731 click probes queryCount(…)0 — the failure
~588 777 getReport responds (duration 311.8 ms), table remounts

The click landed 266 ms into a ~312 ms window in which the input did not
exist, and missed the response by ~46 ms.

This also explains why only the second search in each test fails. Both tests
call searchByValue earlier with the field already empty — fill('') on an
empty input changes nothing, fires no onChange, triggers no reload. The
failing calls (overview_test.js:61, after resetAllFilters();
details_explain_test.js:112, clearing 'SELECT') are the ones where the
field actually had a value to clear.

Reproduction (throwaway Linode VM)

PMM Server perconalab/pmm-server:3-dev-latest, digest
sha256:cba225bd21c7439ddef5971b4e470526c7d0e59ce9b1236e7ac84ff42430e305
byte-identical to the image the failing run recorded to Launchable — reporting
3.9.1-v3-c92cf5c93, same commit 11ff3856. Client latest-tarball,
--database ps --database psmdb,SETUP_TYPE=pss --database pdpgsql, Chromium
151.0.7922.34 (the runner's version).

condition PMM-T1061 PMM-T1790
main, VM as provisioned (PMM on loopback) ✔ pass ✔ pass
main, tc qdisc add dev lo root netem delay 80ms ✖ fail ✖ fail
this branch, same 80 ms ✔ pass ✔ pass

The latency is not a contrivance — this lane is "Nightly E2E tests Matrix
(remote PMM Server)"
: a GitHub-hosted runner driving a PMM Server across
the internet, where the trace shows getReport taking 312–529 ms. On a VM with
PMM on loopback and 3 of the nightly's 14 setups the same query returns fast
enough that the table is back before codecept looks, which is why the fresh box
passes. Restoring a realistic round trip reproduces the CI failure exactly —
same message, same step, same preceding scenario steps.

Fix

fillField (Playwright locator.fill) clears and types in one operation and
waits for actionability itself, so there is no moment between "cleared" and
"typed" for the test to re-find a re-rendering input. Drop the separate
clearField + click, and settle on waitForLoaded() so callers get a loaded
grid.

Backward-compatible with pre-#5537 builds (3.9.0-rc and the compatibility
legs), where search only fires on submit: fillField focuses the input, so the
retained I.pressKey('Enter') still submits exactly as before. The removed
I.click was only ever giving focus that fill already gives.

click() got the same treatment — it is currently unused, but it carried a
verbatim copy of the same racy sequence.

No assertion was loosened and no test was skipped.

Verification

Same VM, full --grep "@qan" lane run twice back to back — once on main,
once on this branch — so the comparison is like for like:

passed failed skipped
main @ 37a003d 46 17 2
this branch 47 16 2
  • Failures present on this branch but not on main: none. No regression
    across the lane, including the other 20 specs that call searchByValue.
  • One test goes the other way — PMM-T193/PMM-T256 (pagination page-size) fails
    on main and passes here.
  • The 16 shared failures are all pre-existing on main on this box and come
    from it having 3 of the nightly's 14 setups (e.g. the PMM-T2063 legs for
    mysql_pmm_, pgsql_pgss_pmm, pxc_node__1 fail in ~150 ms — those
    services are not registered here).
  • npx eslint clean on the changed file.

The red-to-green flip above is the direct evidence. Only the next nightly can
confirm it under the full 14-setup matrix against the real remote server.


Generated by Claude Code

PMM-T1061 and PMM-T1790 have failed the nightly QAN lane three runs
running with:

  Clickable element "//input[contains(@name, "search")]" was not found
    at QueryAnalyticsData.searchByValue (queryAnalyticsData.js:158)

QAN's Overview search became debounced search-as-you-type in
percona/pmm#5537, so clearing the field is itself a search. 300ms later
the empty search reloads the overview, and while it loads the QanTable
renders a spinner instead of the table -- taking the header row, and the
search input that lives in it, out of the DOM. searchByValue cleared the
field and then clicked it, so it was re-finding an element its own clear
had just swept away.

fillField clears and types in one operation, so the input is never
re-found mid-reload. Settle on waitForLoaded afterwards so callers see a
loaded grid.

Signed-off-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
@travagliad travagliad closed this Aug 17, 2026
@travagliad
travagliad deleted the claude/elegant-cerf-ma54gp branch August 17, 2026 07:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant