feat(frontend): add jest-axe automated accessibility testing (closes #383) - #458
feat(frontend): add jest-axe automated accessibility testing (closes #383)#458Olajcodes wants to merge 7 commits into
Conversation
…tellar-Ecosystem#383) Add automated a11y testing with jest-axe to the test suite: Setup: - Install jest-axe dev dependency - Add jest-axe/extend-expect to jest.setup.js - Add TypeScript declaration for jest-axe module A11y fixes found and resolved: - WalletPickerModal: add role='dialog', aria-modal='true', aria-label to dialog and close button - WalletConnect: add aria-label='Disconnect wallet' to close button - ServiceCard: add aria-label to upvote/downvote buttons - ServiceCard: fix heading order (h3→h2 for card title) - RegistryPage: add aria-label='Sort services' to sort select - RegistryPage: add registered_at to test mock data (pre-existing bug) Axe assertions added to page-level tests: - Navbar, WalletPickerModal, ActivityFeed, AgentsPage, RegistryPage - Each test renders the component and asserts no axe violations CI will now catch a11y regressions on these components automatically.
|
@Olajcodes Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
|
Warning Review limit reached
Next review available in: 40 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (8)
📝 WalkthroughWalkthroughThe frontend adds ChangesFrontend accessibility
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant WalletPickerModal
participant DocumentBody
User->>WalletPickerModal: Open modal
WalletPickerModal->>DocumentBody: Portal dialog and mark background inert
WalletPickerModal->>WalletPickerModal: Move focus into dialog
User->>WalletPickerModal: Press Tab, Shift+Tab, or Escape
WalletPickerModal->>WalletPickerModal: Trap focus or close dialog
WalletPickerModal->>DocumentBody: Restore background and previous focus
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hi @Olajcodes, This PR could not be merged because it has merge conflicts with the target branch. Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged. Thank you! |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/components/WalletPickerModal.tsx`:
- Around line 45-54: Update the WalletPickerModal component to use an accessible
dialog primitive or equivalent focus-management logic: move focus into the
dialog on open, trap Tab navigation, close on Escape, and mark background
content inert while open. Preserve the existing onClose behavior and restore
focus to the opening “Connect Wallet” control when the modal closes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8959d633-2271-4040-83b2-7ef704dcdbcd
📒 Files selected for processing (12)
frontend/__tests__/ActivityFeed.test.tsxfrontend/__tests__/AgentsPage.test.tsxfrontend/__tests__/Navbar.test.tsxfrontend/__tests__/RegistryPage.test.tsxfrontend/__tests__/WalletPickerModal.test.tsxfrontend/app/registry/page.tsxfrontend/components/ServiceCard.tsxfrontend/components/WalletConnect.tsxfrontend/components/WalletPickerModal.tsxfrontend/jest.setup.jsfrontend/package.jsonfrontend/types/jest-axe.d.ts
|
@ritik4ever I have resolved the conflicts. Kindly check through and merge |
…loses Stellar-Ecosystem#383 review) Address CodeRabbit/maintainer review on PR Stellar-Ecosystem#458: the dialog declared role=dialog/aria-modal but had no focus management. The modal now renders via a portal to document.body (the modal lives inside the Navbar subtree, so marking any ancestor inert would make the dialog itself inert), moves focus into the dialog on open, traps Tab/Shift+Tab within it, closes on Escape via the existing onClose, marks all background body children inert while open, and restores focus to the opener on close. Adds 5 focus-management tests (focus-in, Tab trap, Escape, inert background, focus restore) and rescopes the axe test to the dialog subtree since portal content renders outside the RTL container. Also commits the jest-axe package-lock.json sync that belongs to this PR (package.json declares jest-axe but the lockfile at HEAD had no entry for it). Note: a lib/sort.test.ts makeAgent fix was not needed here - upstream main (bf3d21b) already added the missing makeAgent factory.
…d CI green) The maintainer merged main into this branch, which reintroduced 5 pre-existing frontend bugs (all identical to fixes previously made on the fix/381 branch but never merged to main): 1. globals.css: focus:ring-primary/30 -> focus:ring-primary (Tailwind cannot alpha-modify a CSS-var color in @apply; broke next build). 2. ThemeProvider: remove the `if (!mounted) return <>{children}>` early return so ThemeContext.Provider always renders - SSR/prerender had mounted=false, so Navbar useTheme() threw on every page and broke the build. 3. RegisterForm.test.tsx: fix 2 syntax errors (render(<RegisterForm ... }); -> />);) that prevented the suite from running. 4. RegisterForm.tsx: add id/htmlFor label associations for getByLabelText, change price input to type=text inputMode=decimal so string-based validation is not sanitized by the number input, and disable submit via live validate(form) so an empty form is disabled on first render. 5. Navbar.test.tsx: mock useTheme from ThemeProvider (jsdom lacks matchMedia, so wrapping in the real provider would crash); Navbar gained a theme toggle in main. Validated: full jest suite 20/20 suites / 122 tests, next build, and tsc all pass.
…erge (backend CI green) The maintainer merged current upstream/main into this branch, which brought in upstream main bugs (main itself is red on Backend/Frontend/Contract). Fixed on this branch so the merge-ref CI can go green: 1. registry.js: removed a duplicate annotateTtlWarning function left by the merge (old simple version + upstream new parseFiniteNumericValue version in the same strict-mode module) that threw SyntaxError and killed the whole 68-test registry suite. Kept the improved upstream version. 2. demo.test.js: (a) mocked the global fetch() to reject with AbortError - buildHttpClient() overwrites x402HTTPClient.fetchWithTx with a real-fetch implementation, so the old x402HTTPClient.mockImplementationOnce never fired (route returned 500 instead of 499); (b) added vi.mock for @x402/express (paymentMiddlewareFromConfig no-op), @x402/core/server and @x402/stellar/exact/server - mirroring services.test.js - so the real x402 server/facilitator is not contacted and no unhandled rejection occurs at services.js module load. 3. backend/package.json + package-lock.json: restored valid JSON (upstream main had corrupted them with a trailing comma + blank line after removing pino-pretty/rate-limit-redis, breaking npm ci EUSAGE on the merge ref) and regenerated the lockfile including pino-http ^10.5.0 for the new requestContext.js.
Current stable Rust cannot compile ethnum 1.5.2 (E0512 transmute), which fails the Contract build & test check on this PR. Bump to 1.5.3 — the same proven fix already applied on the fix/382 branch where all checks pass, and matching contract/agents/Cargo.lock which already pins 1.5.3 with this checksum.
|
@ritik4ever kindly merge. All checks have passed already. |
Summary
Closes #383
Adds automated accessibility testing with
jest-axeto the frontend test suite, including fixing a11y violations found during the audit and adding axe assertions to all page-level component tests.Changes
Infrastructure
package.json: Addedjest-axedev dependencyjest.setup.js: Addedimport 'jest-axe/extend-expect'to register thetoHaveNoViolationsmatchertypes/jest-axe.d.ts: TypeScript declaration for jest-axe moduleA11y Violations Fixed
WalletPickerModalrole="dialog",aria-modal="true",aria-labelon dialog and close buttonWalletConnectaria-label="Disconnect wallet"ServiceCardaria-labelto upvote/downvote buttons;h3→h2for card titleRegistryPage<select>has no accessible namearia-label="Sort services"RegistryPagetestregistered_atfieldmakeServices()helperAxe Assertions Added (5 test files)
Navbar.test.tsx— verifies nav has no violationsWalletPickerModal.test.tsx— verifies modal dialog is accessibleActivityFeed.test.tsx— verifies activity list has no violationsAgentsPage.test.tsx— verifies agent listing page is accessibleRegistryPage.test.tsx— verifies service registry page is accessibleEach test renders the component, waits for content to load, then asserts
expect(await axe(container)).toHaveNoViolations().Test Results
lib/sort.test.ts— unrelated)Summary by CodeRabbit
Accessibility
Tests