fix: resolve Playwright CI failures across 4 test suites#13014
Conversation
- cluster-admin: add etcd_status, dns_health, admission_webhooks cards to default layout (row 10) and update spec expected count 21→24 - find-and-search: defer Ctrl+K focus via requestAnimationFrame so input is guaranteed focusable after React commits the open state - a11y: associate cluster filter, namespace, and max-items form controls in CardConfigModal with explicit htmlFor/id pairs (axe label rule) - not-found: move wildcard NotFound route inside ProtectedRoute/Layout so the pathless layout route yields NotFound instead of an empty outlet Signed-off-by: Rajdeep Singh <rajdeep.kuswaha@s.amity.edu> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
✅ Deploy Preview for kubestellarconsole ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
👋 Hey @RajdeepKushwaha5 — thanks for opening this PR!
This is an automated message. |
There was a problem hiding this comment.
Pull request overview
Fixes several frontend issues that were causing Playwright CI failures by aligning the cluster-admin default dashboard layout with registered cards, stabilizing Ctrl/Cmd+K search focus behavior, addressing an a11y labeling violation, and ensuring authenticated unknown routes render a proper NotFound view.
Changes:
- Added
etcd_status,dns_health, andadmission_webhooksto the cluster-admin default dashboard layout and updated the corresponding Playwright expectations. - Fixed a Ctrl/Cmd+K focus race in the navbar search dropdown by deferring focus until after the open state commits.
- Associated
label/inputpairs inCardConfigModaland updated routing so authenticated unmatched paths renderNotFound.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/config/dashboards/cluster-admin.ts | Adds three infrastructure monitoring cards to the default cluster-admin layout. |
| web/e2e/cluster-admin-cards.spec.ts | Updates default-layout E2E expectations to include the added cards. |
| web/src/components/layout/navbar/SearchDropdown.tsx | Defers search input focus after opening to avoid Ctrl/Cmd+K race. |
| web/src/components/clusters/components/CardConfigModal.tsx | Adds htmlFor/id pairs to satisfy axe “label” rules. |
| web/src/App.tsx | Adds an authenticated wildcard route under Layout to render NotFound for unmatched paths. |
Comments suppressed due to low confidence (2)
web/e2e/cluster-admin-cards.spec.ts:701
- This block still contains several stale references to “21” cards (e.g., the surrounding describe/test labels and the inline comment just before the count assertion) even though EXPECTED_CARD_COUNT is now 24. Please update the remaining “21” references to 24 to avoid misleading future maintainers when the test fails.
// All 24 default card types from cluster-admin.ts config
const EXPECTED_CARD_TYPES = [
'kubectl',
'node_debug',
'cluster_health',
web/src/App.tsx:835
- Now that the Layout route has a nested
path="*"NotFound, the siblingpath="*"route immediately below is effectively unreachable (the pathless Layout route + child wildcard will match any remaining URL). Consider removing the sibling wildcard, or restructuring routes if you intended different 404 behavior for unauthenticated vs authenticated users.
<Route path="*" element={<SuspenseRoute><NotFound /></SuspenseRoute>} />
</Route>
<Route path="*" element={<SuspenseRoute><NotFound /></SuspenseRoute>} />
</Routes>
There was a problem hiding this comment.
Quality Review: Playwright CI Fixes
Overall assessment: High quality fixes addressing real root causes. All changes are surgical and follow best practices.
✅ Strengths
Proper Root-Cause Fixes (Not Masking)
- cluster-admin-cards: Adding the missing three cards to the default layout correctly addresses the test failure root cause (cards were registered but not in the default placement list)
- find-and-search: The race condition fix using
requestAnimationFrame()instead of synchronousfocus()is textbook correct — properly waits for React's paint cycle before focusing - CardConfigModal: Adding
htmlFor/idpairs fixes the actual WCAG accessibility violation (SC 1.3.1), not working around it - App.tsx: Nesting the wildcard route inside the layout correctly fixes the routing logic
Playwright Best Practices
- No
waitForTimeout,toBeTruthy,catch(() => {}), or other anti-patterns - Test expectations properly updated to match new card count (21 → 24)
- Accessibility fixes use semantic HTML improvements, not brittle workarounds
Clear Documentation
- Excellent root-cause traces in the PR description with before/after examples
- Good explanation of the React Router v6 route resolution order for the unmatched path fix
- Helpful context about where String.raw warnings came from (pre-existing)
🔍 Minor Observations
-
CardConfigModal IDs: The IDs follow a clear pattern (
card-config-*). Consider whether component reusability might benefit from these being props rather than hardcoded, but for a single-use form this is perfectly fine. -
SearchDropdown timing:
requestAnimationFrameis the right choice here. The comment explaining the deferral is helpful for future maintainers. -
Dashboard card positions: The three new cards use consistent positioning (
y=28,w=4,h=3). Verify the grid layout can accommodate row 10 without overflow or visual issues in the cluster-admin view.
Summary
This is a well-executed fix. Each change addresses a genuine failure point with minimal, appropriate modifications. The PR demonstrates good problem-solving (tracing failures to root causes rather than patching symptoms) and follows frontend best practices throughout.
There was a problem hiding this comment.
LGTM — all 4 fixes are well-targeted and correct:
- cluster-admin cards: 3 missing infrastructure cards properly registered + layout updated (21→24)
- Ctrl+K search:
requestAnimationFramedeferred focus is the right fix for the React render timing race - a11y: Proper
htmlFor/idpairing on CardConfigModal form controls - NotFound routing: Nested wildcard inside Layout route is correct React Router v6 nesting
CI is green. Nice work! 🎉
|
@kubestellar-hive[bot]: changing LGTM is restricted to collaborators DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
There was a problem hiding this comment.
Review: console#13014 — Fix Playwright CI Failures Across 4 Test Suites
Reviewer: scanner agent (flagging for operator approval)
✅ All CI Green
Build, coverage-gate, fullstack-smoke, pr-check, ts-null-safety, CodeQL, visual regression, route smoke — all passing. 24/24 checks successful (excluding skipped/pending tide).
Fix-by-Fix Analysis
1. cluster-admin dashboard config + test (cluster-admin-cards.spec.ts)
- Adds
etcd_status,dns_health,admission_webhookstocluster-admin.tsdefault layout (Row 10, y=28) - Updates test:
EXPECTED_CARD_COUNT21→24, adds the 3 card types toEXPECTED_CARD_TYPES - ✅ Correct — these cards are registered in
CARD_COMPONENTSand the cluster-admin bundle but were missing from the default placement. The layout grid positions (w=4, h=3) are consistent with the existing rows.
2. SearchDropdown.tsx — Ctrl+K focus race fix
// Before: focus() runs synchronously before React commits open state
inputRef.current?.focus()
openSearch()
// After: deferred past next paint
openSearch()
requestAnimationFrame(() => inputRef.current?.focus())- ✅ Correct fix.
openSearch()triggers async React state update; synchronousfocus()before the commit would target a not-yet-visible input.requestAnimationFramedefers to after paint. Also correctly movedopenSearch()before the focus call.
3. CardConfigModal.tsx — a11y label associations
- Adds
htmlFor/idpairs:card-config-cluster,card-config-namespace,card-config-max-items - ✅ Correct — satisfies axe
labelrule (WCAG 2.1 AA, SC 1.3.1). IDs are unique and descriptive.
4. App.tsx — NotFound route fix
// Added wildcard INSIDE the layout route
<Route path="*" element={<SuspenseRoute><NotFound /></SuspenseRoute>} />- ✅ Correct. The pathless layout
<Route element={<Layout/>}>matches everything, so a sibling<Route path="*">was unreachable for authenticated users. Moving it inside as a child route makes it the fallback when no specific child matches. - The outer
<Route path="*"><NotFound/>remains for unauthenticated routes — both wildcards are intentional and correct.
⚠️ Minor Observations (non-blocking)
- The PR description mentions pre-existing SonarCloud diagnostics (S6759, S1874, S3776, S6582) on
SearchDropdown.tsx— confirmed not introduced by this PR. - The
String.rawwarnings incluster-admin-cards.spec.tsat lines 509–547, 805 are pre-existing — not introduced here.
Verdict
Clean, surgical fixes with proper root-cause analysis. All 4 changes are correct and well-targeted. CI is fully green. Recommend merge — flagging for operator approval.
Automated review — do not merge without operator approval.
There was a problem hiding this comment.
Reviewed — all 4 fixes are correct and address real CI failures:
- Cluster admin cards: 3 missing cards added to default layout ✅
- Find-and-search focus:
requestAnimationFramefixes the React timing race ✅ - A11y labels: Proper
id/htmlForassociations on form controls ✅ - Not-found route: Wildcard moved inside layout route so it's reachable ✅
No test weakening, robust selectors, reasonable timeouts. LGTM ✅
|
@kubestellar-hive[bot]: changing LGTM is restricted to collaborators DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
f6e1257
into
kubestellar:main
❌ Post-Merge Verification: failedCommit: |
📌 Fixes
Related to #4190
📝 Summary of Changes
Resolves four categories of failing Playwright CI tests identified in the April 28 mentor triage:
cluster-admin-cards.spec.ts(25 tests),find-and-search.spec.ts(Ctrl+K shortcut),a11y.spec.ts(axelabelrule), andnot-found.spec.ts(2 tests). All fixes are surgical — no refactoring, no new abstractions.Changes Made
web/src/config/dashboards/cluster-admin.ts— Addedetcd_status,dns_health, andadmission_webhookscards to the cluster-admin default layout (row 10,y=28,w=4,h=3). The preset was not auto-pinning these three infrastructure monitoring cards, which are registered inCARD_COMPONENTSand the unified config but were absent from the default placement list.web/e2e/cluster-admin-cards.spec.ts— Updated the "Default Layout" test:EXPECTED_CARD_COUNT21 → 24, added'etcd_status','dns_health','admission_webhooks'toEXPECTED_CARD_TYPES. Pre-existingString.rawwarnings at lines 509–547, 805 were not introduced here.web/src/components/layout/navbar/SearchDropdown.tsx— Fixed Ctrl+K focus race.openSearch()triggers an async React state update; callinginputRef.current?.focus()synchronously before the state commits means the input is not yet in its open/focusable state. Deferred the focus call withrequestAnimationFrame(() => inputRef.current?.focus())so it runs after React's next paint.web/src/components/clusters/components/CardConfigModal.tsx— Three form controls (cluster<select>, namespace<input>, max-items<input>) had<label>elements with nohtmlForand controls with noid. Added matchinghtmlFor/idpairs (card-config-cluster,card-config-namespace,card-config-max-items) to satisfy axe'slabelrule (WCAG 2.1 AA, SC 1.3.1).web/src/App.tsx— The pathless layout route (<Route element={<ProtectedRoute><Layout/></ProtectedRoute>}>) matches every path. The sibling<Route path="*"><NotFound/></Route>at the bottom of the route tree was therefore unreachable for authenticated users — unmatched paths rendered Layout with an empty outlet instead ofNotFound. Moved the wildcard inside the layout route soNotFoundrenders correctly for any unmatched authenticated URL.Checklist
git commit -s)Screenshots or Logs (if applicable)
Root cause trace —
cluster-admin-cards(25 failures):The mentor's hint was: "The /cluster-admin dashboard presets may not be auto-pinning these cards."
Confirmed by tracing
useDashboardCards→CARD_COMPONENTSregistry →cluster-admin.tsdefault config.etcd_status,dns_health, andadmission_webhooksare all registered atcardRegistry.ts:733–736and in the lazy-loadedcluster-admin-bundle, but the default placement list only had 21 cards stopping at row 9.Root cause trace —
find-and-search(Ctrl+K focus):Root cause trace —
a11y(CardConfigModal label violations):Root cause trace —
not-found(empty outlet):After fix:
<Route path="*"><NotFound/></Route>is inside the layout route, so it wins the child-route match andNotFoundrenders insideLayout.👀 Reviewer Notes
App.tsxouter<Route path="*"><NotFound/></Route>(now at the sibling level) still covers the case where a user hits an unmatched route before authentication. Both wildcards are intentional.SearchDropdown.tsx(S6759, S1874, S3776, S6582) andcluster-admin-cards.spec.ts(String.raw warnings) were not introduced by this PR.