Fix flaky UserDetails Playwright spec: visitUserProfilePage hangs on an undispatched search - #31647
Conversation
… search
visitUserProfilePage retried its user-list search by clearing the search box
and re-typing the same username inside an expect.poll. That retry can never
work: SearchBar debounces at 1s, so fill('') + fill(userName) collapse into a
single handleSearch(userName), and UserListPageV1 refetches only when its
searchValue changes. Re-entering the term already in the box leaves searchValue
untouched, so no request is dispatched and the poll's unbounded
waitForResponse waits forever.
The poll budget also equalled the 60s test timeout, so the test died mid-poll
and reported the raw 49s wait instead of the poll's own message.
Replace the loop with a single search: the box is empty on arrival, so one
fill is a real value change and always dispatches. Scope the response predicate
to the username so a stray query from another component cannot satisfy it, and
drop two dead waits that were created once and never meaningfully awaited.
Add test.slow() to the team-domain-inheritance test, which does two profile
visits plus five API round trips; its sibling using the same helper already
has it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
❌ PR checklist incompleteThis PR cannot be merged until the following are addressed on its linked issue:
The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically. Maintainers can bypass this check by adding the |
|
Good catch — accepted and fixed in
// src/rest/searchAPI.ts:187
const apiUrl = `/search/query?q=${apiQuery}${filters ?? ''}`;So there are two independent ways the predicate could miss:
Either one means Fixed as suggested, matching the URL shape rather than the term: const searchResponse = page.waitForResponse(
'/api/v1/search/query?q=*&index=user&from=0&size=*'
);Kept
|
✅ Playwright Results — workflow succeededValidated commit ✅ 559 passed · ❌ 0 failed · 🟡 1 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky PerformanceBlocking targets: ✅ met · Optimization targets: 🟡 in progress Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting. 🕒 Full workflow signal wall (to summary) 1h 9m 33s ⏱️ Max setup 2m 57s · max shard execution 20m 55s · max shard-job elapsed before upload 24m 19s · reporting 5s 🌐 213.02 requests/attempt · 2.81 app boots/UI scenario · 11.31% common-shard skew Optimization targets still in progress:
🟡 1 flaky test(s) (passed on retry)
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
🚦 Removed from the merge queue —
|
|
Changes have been cherry-picked to the 1.13 branch. |
…an undispatched search (#31647) * test(playwright): fix visitUserProfilePage hanging on an undispatched search visitUserProfilePage retried its user-list search by clearing the search box and re-typing the same username inside an expect.poll. That retry can never work: SearchBar debounces at 1s, so fill('') + fill(userName) collapse into a single handleSearch(userName), and UserListPageV1 refetches only when its searchValue changes. Re-entering the term already in the box leaves searchValue untouched, so no request is dispatched and the poll's unbounded waitForResponse waits forever. The poll budget also equalled the 60s test timeout, so the test died mid-poll and reported the raw 49s wait instead of the poll's own message. Replace the loop with a single search: the box is empty on arrival, so one fill is a real value change and always dispatches. Scope the response predicate to the username so a stray query from another component cannot satisfy it, and drop two dead waits that were created once and never meaningfully awaited. Add test.slow() to the team-domain-inheritance test, which does two profile visits plus five API round trips; its sibling using the same helper already has it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * address gitar --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit 7b4160c)
|
Changes have been cherry-picked to the 2.0 branch. |
…an undispatched search (#31647) * test(playwright): fix visitUserProfilePage hanging on an undispatched search visitUserProfilePage retried its user-list search by clearing the search box and re-typing the same username inside an expect.poll. That retry can never work: SearchBar debounces at 1s, so fill('') + fill(userName) collapse into a single handleSearch(userName), and UserListPageV1 refetches only when its searchValue changes. Re-entering the term already in the box leaves searchValue untouched, so no request is dispatched and the poll's unbounded waitForResponse waits forever. The poll budget also equalled the 60s test timeout, so the test died mid-poll and reported the raw 49s wait instead of the poll's own message. Replace the loop with a single search: the box is empty on arrival, so one fill is a real value change and always dispatches. Scope the response predicate to the username so a stray query from another component cannot satisfy it, and drop two dead waits that were created once and never meaningfully awaited. Add test.slow() to the team-domain-inheritance test, which does two profile visits plus five API round trips; its sibling using the same helper already has it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * address gitar --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit 7b4160c)
Code Review ✅ Approved 1 resolved / 1 findingsReplaces the deadlocking search retry loop in visitUserProfilePage with a deterministic single-username search and extends the team-domain test timeout, addressing the waitForResponse predicate matching issue. ✅ 1 resolved✅ Edge Case: waitForResponse predicate may not match encoded usernames
OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source |
Describe your changes:
I worked on the flaky
UserDetails.spec.tstest because it fails intermittently on the nightly run (2.0 nightly run 31918043673) with a 49s hang insidevisitUserProfilePage, not inside the spec itself.Failing test:
Create team with domain and verify visibility of inherited domain in user profile after team removalTrace:
Wait for event "response" — playwright/utils/user.ts:139→ 49.1s, followed byTimed out waiting for user <name> to become visible in the user list. The failure screenshot shows the user row rendered correctly — nothing was actually missing.Root cause
visitUserProfilePageretried its user-list search inside anexpect.pollby clearing the search box and re-typing the same username:That retry can never dispatch a second search:
SearchBar.component.tsx:131setstypingInterval: 1000, sofill('')andfill(userName)(~20ms apart) collapse into a single debouncedhandleSearch(userName).UserListPageV1.tsx:230—handleSearchonly callssetFilters({ user: value }).UserListPageV1.tsx:247-250— the fetch effect keys on[searchValue, currentPage, isDeleted]. Re-entering the term already held insearchValueleaves it unchanged, so the effect never re-runs and no request is made.The first iteration works (empty box →
'' → userNameis a real change). Every later iteration deadlocks on an unboundedwaitForResponsefor a request that will never be sent.Two aggravating factors:
60000, equal to the test timeout inplaywright.config.ts:386. The poll could never exhaust its own retries, so the test died mid-poll and reported the raw wait rather than the poll's diagnostic message.Admin user can edit teams from the user profilecalls the same helper but declarestest.slow(). This one did not, so it ran on the bare 60s budget.Why it surfaces on nightly and not locally: CI runs
workers: 3, which lengthens ES index lag and makes the helper reach retry 2+ far more often. Locally the first iteration usually succeeds and the latent deadlock never fires.The fix
Replace the retry loop with a single deterministic search. The search box is empty on arrival, so one
fill(userName)is always a real value change and always dispatches:search/queryfrom another component cannot satisfy the wait and mask an unpopulated list.userResponse, created and never meaningfully awaited;loaderPromise, created once outside the loop and re-awaited each iteration despite being already settled).test.slow()to the failing test, matching its sibling that uses the same helper.Net −12 lines; the helper now matches the shape of
searchUserByEmailin the same file.The removed poll was there to absorb ES index lag, but since its retry was inert the helper has in practice always been a single search — and it passes nearly always, which is itself the evidence that index lag is not a real factor on this path. If a user genuinely is not indexed,
expect(userRow).toBeVisible()now fails with a clear message pointing at a real bug rather than a loop hiding it.Type of change:
High-level design:
N/A — small change.
Tests:
Use cases covered
visitUserProfilePage, used byUserDetails.spec.tsand other specs).Unit tests
Not applicable — this PR only changes Playwright test code.
Backend integration tests
Ingestion integration tests
Playwright (UI) tests
This PR is a Playwright fix; no product code changed, so no new test is added.
openmetadata-ui/src/main/resources/ui/playwright/utils/user.tsopenmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/UserDetails.spec.tsManual testing performed
Static verification only — I do not have a live stack available:
npx tsc --noEmit -p playwright/tsconfig.json— no new errors. The two remainingTS6133 'displayName'reports are pre-existing, insoftDeleteUserProfilePage/hardDeleteUserProfilePage, untouched by this PR.npx eslint playwright/utils/user.ts playwright/e2e/Pages/UserDetails.spec.ts— 0 errors. The 2 warnings on the spec are pre-existingbrowser.newPage()notices that the rule itself documents as expected for multi-user tests.npx prettier --check— clean.handleSearch, and the fetch effect's dependency array are cited with line numbers above.Reviewer note: the flake is a race, so please run the spec against a live stack before merging to confirm —
yarn playwright:run playwright/e2e/Pages/UserDetails.spec.ts --repeat-each=5.UI screen recording / screenshots:
Not applicable — no product code changed, test-only.
Checklist:
visitUserProfilePagecovers the exact scenario that was hanging.🤖 Generated with Claude Code
Greptile Summary
The PR simplifies
visitUserProfilePageto issue one deterministic user search and increases the timeout for the previously flaky scenario.Confidence Score: 5/5
The PR appears safe to merge.
No blocking failure remains.
Important Files Changed
Reviews (3): Last reviewed commit: "address gitar" | Re-trigger Greptile