Skip to content

test(teams): stop the teams landing from eating the test budget - #31932

Merged
harsh-vador merged 6 commits into
mainfrom
fix/teams-drag-drop-nightly-flake
Aug 24, 2026
Merged

test(teams): stop the teams landing from eating the test budget#31932
harsh-vador merged 6 commits into
mainfrom
fix/teams-drag-drop-nightly-flake

Conversation

@harsh-vador

@harsh-vador harsh-vador commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Problem

TeamsDragAndDrop.spec.ts fails on the nightly upgrade runs — AUT EKS/RDS MySQL 1.11.13 ➡ 1.13. The first failure is in beforeEach, before any test body runs:

Test timeout of 60000ms exceeded while running "beforeEach" hook.
  Expect "toHaveCount" locator('[data-testid="loader"]')   38.0s
  Expect "toHaveCount" locator('[data-testid="loader"]')   19.7s

RCA

The data-testid="loader" the hook waits on is the teams table's own spinner:

  • TeamHierarchy.tsxloading={isTableLoading || isTeamBasicDataLoading || isSearchLoading}
  • common/Table/Table.tsxloading={{ indicator: <Loader /> }}
  • common/Loader/Loader.tsxdata-testid="loader"

isTeamBasicDataLoading covers the per-team asset-count aggregation, which scales with the catalog. So the landing is genuinely slow on a loaded deployment — and the hook spent its budget on it twice: settingClick already ends in waitForAllLoadersToDisappear (30s), and the hook called it a second time. Two 30s waits against a 60s test timeout leaves nothing, the hook times out, and serial mode skips the rest of the file.

Why it degrades over time: this suite creates four team-ct-test-* teams and never deletes them (TeamsHierarchy.spec.ts deletes its parent team; this one doesn't). The EKS/RDS nightlies reuse a persistent database, so every run leaves four more teams under Organization, growing the aggregation the landing waits on. Matches the result spread — AUT kind/postgresql (fresh cluster) passed, both EKS/RDS runs failed.

Fix

  • utils/team.ts — new visitTeamsPage(): waits the two calls that gate the first paint (with .ok() rather than a bare status compare), asserts team-hierarchy-table, then waits out loaders. New hardDeleteTeamByName() for teams built through the UI, which have no TeamClass handle.
  • TeamsDragAndDrop.spec.tstest.slow(true) at describe level so the landing has headroom (replaces three per-test test.slow() calls); hook reduced to redirectToHomePage + visitTeamsPage; afterAll hard-deletes the four teams recursively so the deployment stops accumulating them.
  • TeamsHierarchy.spec.ts — same hook folded onto visitTeamsPage (it had the same shape with looser glob waits); drops a redundant settingClick in Delete Parent Team, since beforeEach already lands there.

Backport

1.13 additionally lacks the addTeamHierarchy hardening that main and 2.0 carry (#25894's team.ts hunk, #30334, #31734), which is what fails the retries at TeamsDragAndDrop.spec.ts:119. That is handled in the companion 1.13 PR. 2.0 needs only a cherry-pick of this one.

Verification

tsc --noEmit -p playwright/tsconfig.json, eslint, and prettier --check are clean on the touched files. The spec itself needs a live deployment and was not run locally.

🤖 Generated with Claude Code

Greptile Summary

The PR makes the Teams Playwright suites wait for the hierarchy page to settle and adds reliable teardown for teams created by the drag-and-drop suite.

  • Centralizes Teams-page navigation and readiness checks in visitTeamsPage.
  • Hard-deletes all generated teams while aggregating cleanup failures.
  • Ensures one cleanup failure does not prevent attempts for the remaining teams.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the cleanup now reports unsuccessful lookups and deletes while attempting every team before failing teardown.

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts Uses the shared Teams-page navigation helper and performs failure-reporting cleanup for all generated teams after the serial suite.
openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsHierarchy.spec.ts Replaces duplicated navigation waits with the shared helper and removes redundant navigation from the deletion test.
openmetadata-ui/src/main/resources/ui/playwright/utils/team.ts Adds settled Teams-page navigation and resilient cleanup helpers that validate responses, continue after individual failures, and assert aggregated failures.

Reviews (6): Last reviewed commit: "remove unwanted test.slow" | Re-trigger Greptile

TeamsDragAndDrop's beforeEach spent the whole 60s test timeout before any
test body ran. settingClick already ends in waitForAllLoadersToDisappear
(30s), and the hook then called it a second time. The Teams table's antd
spinner is the shared `data-testid="loader"`, and it stays up until both
the child-teams fetch and the per-team asset-count aggregation settle — on
a long-lived deployment that is tens of seconds, so the two waits together
consumed the budget and the hook timed out on the second one.

Give the suite test.slow(true) so the landing has headroom, and hard-delete
the four teams the suite creates. Without that cleanup every nightly run
left four more teams under Organization, growing the aggregation the
landing waits on and making the next run slower.

Fold the duplicated navigation into visitTeamsPage and reuse it from
TeamsHierarchy, which had the same hook with looser glob waits.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

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 skip-pr-checks label.

@github-actions github-actions Bot added the UI UI specific issues label Aug 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@harsh-vador harsh-vador self-assigned this Aug 24, 2026
@harsh-vador harsh-vador added the safe to test Add this label to run secure Github workflows on PRs label Aug 24, 2026
Comment thread openmetadata-ui/src/main/resources/ui/playwright/utils/team.ts Outdated
Comment thread openmetadata-ui/src/main/resources/ui/playwright/utils/team.ts Outdated
@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit 26dc0b9615b99738ef31a956ff0389ef26d2b3b3 in Playwright run 32727843407, attempt 1.

✅ 564 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky

Performance

Blocking 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) 46m 39s

⏱️ Max setup 4m 33s · max shard execution 19m 20s · max shard-job elapsed before upload 22m 49s · reporting 4s

🌐 214.58 requests/attempt · 2.79 app boots/UI scenario · 33.45% common-shard skew

Optimization targets still in progress:

  • Common shard skew was 33.45% (convergence target: at most 15%).
  • Browser traffic was 214.58 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 2.79 per UI scenario (1633 boots / 585 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
✅ Shard chromium-01 134 0 0 0 0 0
✅ Shard chromium-02 141 0 0 0 0 0
✅ Shard chromium-03 135 0 0 0 0 0
✅ Shard data-asset-rules-01 61 0 0 0 0 0
✅ Shard domain-isolation-01 16 0 0 0 0 0
✅ Shard global-state-01 34 0 0 0 0 0
✅ Shard ingestion-01 1 0 0 0 0 0
✅ Shard reindex-01 2 0 0 0 0 0
✅ Shard search-01 11 0 0 0 0 0
✅ Shard search-rbac-01 29 0 0 0 0 0

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

hardDeleteTeamByName issued the DELETE and ignored the result, so a delete
rejected on permissions or failing with a 500 left the team behind with no
signal in the run — quietly reintroducing the accumulation this cleanup
exists to prevent. Assert the response instead, with the status and body in
the message.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread openmetadata-ui/src/main/resources/ui/playwright/utils/team.ts Outdated
The lookup guard keyed off `ok()`, which is false for an auth error or a 500
just as it is for a 404. A broken lookup therefore took the same path as a
team that was already gone: return without deleting, and report success.

Tolerate 404 alone — the spec may have deleted the team itself, and a
recursive delete of its parent takes its children — and assert every other
lookup failure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The assertion sat inside hardDeleteTeamByName, so the first team that failed
to delete threw out of the caller's loop and the remaining names were never
attempted — leaving those teams on the deployment, which is the accumulation
the cleanup exists to prevent.

Move the assertion up into hardDeleteTeamsByName: the per-team helper now
reports a failure instead of throwing (network errors included), every name
is attempted, and one assertion at the end names every team that survived
along with the status and body that explain why.

Wrap the call in try/finally in the spec so the API context is disposed even
when cleanup fails.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
anuj-kumary pushed a commit that referenced this pull request Aug 24, 2026
* test(teams): backport addTeamHierarchy hardening to 1.13

1.13 never received the addTeamHierarchy waits that main and 2.0 carry, so
the helper returns while the teams table is still refetching: it opens the
modal on a plain click a toast can swallow, resolves on the first
`/api/v1/teams` response regardless of method or status, and never waits
for the modal to close or the row to render.

Backports the team.ts changes from #25894, #30334 and #31734.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(teams): stop the teams landing from eating the test budget

TeamsDragAndDrop's beforeEach spent the whole 60s test timeout before any
test body ran. settingClick already ends in waitForAllLoadersToDisappear
(30s), and the hook then called it a second time. The Teams table's antd
spinner is the shared `data-testid="loader"`, and it stays up until both
the child-teams fetch and the per-team asset-count aggregation settle — on
a long-lived deployment that is tens of seconds, so the two waits together
consumed the budget and the hook timed out on the second one.

Give the suite test.slow(true) so the landing has headroom, and hard-delete
the four teams the suite creates. Without that cleanup every nightly run
left four more teams under Organization, growing the aggregation the
landing waits on and making the next run slower.

Fold the duplicated navigation into visitTeamsPage and reuse it from
TeamsHierarchy, which had the same hook with looser glob waits.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(teams): surface a failed cleanup delete

hardDeleteTeamByName issued the DELETE and ignored the result, so a delete
rejected on permissions or failing with a 500 left the team behind with no
signal in the run — quietly reintroducing the accumulation this cleanup
exists to prevent. Assert the response instead, with the status and body in
the message.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(teams): only tolerate a 404 on the cleanup lookup

The lookup guard keyed off `ok()`, which is false for an auth error or a 500
just as it is for a 404. A broken lookup therefore took the same path as a
team that was already gone: return without deleting, and report success.

Tolerate 404 alone — the spec may have deleted the team itself, and a
recursive delete of its parent takes its children — and assert every other
lookup failure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(teams): attempt every cleanup delete before asserting

The assertion sat inside hardDeleteTeamByName, so the first team that failed
to delete threw out of the caller's loop and the remaining names were never
attempted — leaving those teams on the deployment, which is the accumulation
the cleanup exists to prevent.

Move the assertion up into hardDeleteTeamsByName: the per-team helper now
reports a failure instead of throwing (network errors included), every name
is attempted, and one assertion at the end names every team that survived
along with the status and body that explain why.

Wrap the call in try/finally in the spec so the API context is disposed even
when cleanup fails.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@harsh-vador
harsh-vador enabled auto-merge August 24, 2026 09:34
harsh-vador and others added 2 commits August 24, 2026 17:54
Review feedback: no test.slow at describe level. It also had to move for
correctness — hook time counts against the test timeout, so marking a test
slow from its body is too late when it is the beforeEach that overruns.
Calling test.slow() as the first statement of the hook applies it to the
current test before the hook does any waiting.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment on lines 94 to +97
test.beforeEach(async ({ page }) => {
await redirectToHomePage(page);
await visitTeamsPage(page);
});

@gitar-bot gitar-bot Bot Aug 24, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Bug: Per-test test.slow() leaves slow beforeEach on default 60s budget

This commit removes test.slow() from beforeEach and instead calls test.slow(true) inside individual test bodies. Two problems reintroduce the very flake this PR targets: (1) the three 'Should fail...' tests (lines 125, 135, 149) get no test.slow() at all, so they run the slow visitTeamsPage hook under the default 60s timeout; (2) even for tests that do call test.slow(true), the call runs only after beforeEach completes — if the hierarchy-table aggregation makes visitTeamsPage exceed 60s (the exact failure in the RCA), the hook times out before the body runs and the tripling never applies. The deleted comment made precisely this point. Restore test.slow() at the start of beforeEach so the tripled budget covers hook time for every test, and drop the redundant per-test calls.

Move test.slow() back into beforeEach so it covers hook time for all tests; remove the per-test test.slow(true) calls.:

test.beforeEach(async ({ page }) => {
  // Hook time counts against the test timeout, and visitTeamsPage waits on
  // the hierarchy table's asset-count aggregation, which grows with the
  // catalog. Mark slow here so the tripled budget covers the hook for every
  // test (a per-test-body test.slow() runs too late if the hook overruns).
  test.slow();

  await redirectToHomePage(page);
  await visitTeamsPage(page);
});

Was this helpful? React with 👍 / 👎

@gitar-bot

gitar-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown
Code Review ⚠️ Changes requested 1 resolved / 2 findings

Adds shared Teams page navigation and cleanup logic to resolve nightly timeouts, but removing per-test slow markers leaves the beforeEach hook vulnerable to the default 60-second budget.

⚠️ Bug: Per-test test.slow() leaves slow beforeEach on default 60s budget

📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:94-97 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:115 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:125 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:135 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:149 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:163 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:187

This commit removes test.slow() from beforeEach and instead calls test.slow(true) inside individual test bodies. Two problems reintroduce the very flake this PR targets: (1) the three 'Should fail...' tests (lines 125, 135, 149) get no test.slow() at all, so they run the slow visitTeamsPage hook under the default 60s timeout; (2) even for tests that do call test.slow(true), the call runs only after beforeEach completes — if the hierarchy-table aggregation makes visitTeamsPage exceed 60s (the exact failure in the RCA), the hook times out before the body runs and the tripling never applies. The deleted comment made precisely this point. Restore test.slow() at the start of beforeEach so the tripled budget covers hook time for every test, and drop the redundant per-test calls.

Move test.slow() back into beforeEach so it covers hook time for all tests; remove the per-test test.slow(true) calls.
test.beforeEach(async ({ page }) => {
  // Hook time counts against the test timeout, and visitTeamsPage waits on
  // the hierarchy table's asset-count aggregation, which grows with the
  // catalog. Mark slow here so the tripled budget covers the hook for every
  // test (a per-test-body test.slow() runs too late if the hook overruns).
  test.slow();

  await redirectToHomePage(page);
  await visitTeamsPage(page);
});
✅ 1 resolved
Edge Case: afterAll cleanup ignores delete failures

📄 openmetadata-ui/src/main/resources/ui/playwright/utils/team.ts:117-123
hardDeleteTeamByName issues the DELETE but never checks its result, so a failed delete (permission/ownership/500) is swallowed and the team survives — silently reintroducing exactly the accumulation this PR sets out to stop, with no signal in the run. Consider asserting the delete response is ok (or logging on failure) so a broken cleanup surfaces instead of quietly degrading future nightlies. Note this is afterAll cleanup, so failing hard is a tradeoff, but at minimum a non-ok response should not pass unnoticed.

🤖 Prompt for agents
Code Review: Adds shared Teams page navigation and cleanup logic to resolve nightly timeouts, but removing per-test slow markers leaves the `beforeEach` hook vulnerable to the default 60-second budget.

1. ⚠️ Bug: Per-test test.slow() leaves slow beforeEach on default 60s budget
   Files: openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:94-97, openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:115, openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:125, openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:135, openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:149, openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:163, openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/TeamsDragAndDrop.spec.ts:187

   This commit removes `test.slow()` from `beforeEach` and instead calls `test.slow(true)` inside individual test bodies. Two problems reintroduce the very flake this PR targets: (1) the three 'Should fail...' tests (lines 125, 135, 149) get no `test.slow()` at all, so they run the slow `visitTeamsPage` hook under the default 60s timeout; (2) even for tests that do call `test.slow(true)`, the call runs only after `beforeEach` completes — if the hierarchy-table aggregation makes `visitTeamsPage` exceed 60s (the exact failure in the RCA), the hook times out before the body runs and the tripling never applies. The deleted comment made precisely this point. Restore `test.slow()` at the start of `beforeEach` so the tripled budget covers hook time for every test, and drop the redundant per-test calls.

   Fix (Move test.slow() back into beforeEach so it covers hook time for all tests; remove the per-test test.slow(true) calls.):
   test.beforeEach(async ({ page }) => {
     // Hook time counts against the test timeout, and visitTeamsPage waits on
     // the hierarchy table's asset-count aggregation, which grows with the
     // catalog. Mark slow here so the tripled budget covers the hook for every
     // test (a per-test-body test.slow() runs too late if the hook overruns).
     test.slow();
   
     await redirectToHomePage(page);
     await visitTeamsPage(page);
   });

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@harsh-vador
harsh-vador added this pull request to the merge queue Aug 24, 2026
Merged via the queue into main with commit cc6af6d Aug 24, 2026
89 of 91 checks passed
@harsh-vador
harsh-vador deleted the fix/teams-drag-drop-nightly-flake branch August 24, 2026 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants