> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Accessibility Testing

> Version: 1.0.0 Last Updated: 2026-02-09 Status: Active

**Version:** 1.0.0\
**Last Updated:** 2026-02-09\
**Status:** Active

**Purpose:** Document in-scope routes and patterns for accessibility audits (e.g. axe-core, jest-axe, manual a11y checks).

## Hub Pages (In Scope)

Tabbed hub pages are in scope for accessibility audits. These include:

| Module                 | Route               | Tabs                                                              |
| ---------------------- | ------------------- | ----------------------------------------------------------------- |
| HR Recruiting          | `/hr/ats`           | Dashboard, Postings, Applications, Candidates, Interviews, Offers |
| HR Credentialing       | `/hr/credentialing` | Dashboard, Report, Analytics, Renewals, My Credentials            |
| HR Workforce Analytics | `/hr/analytics`     | Dashboard, Trends, Retention Risk, Cost Analysis, Reports         |
| HR Clinical Oversight  | `/hr/oversight`     | Relationships, Sessions, Compliance, Reports                      |

When running axe or similar tools, include these routes (with at least one `?tab=` variant per hub) to verify tab panels, focus management, and keyboard navigation. See [UI/UX Standards § Tabbed Hub Accessibility Checklist](../development/UI_UX_STANDARDS.md#tabbed-hub-accessibility-checklist).

## Running Audits

### Manual Audits

1. Open the target hub route in Chrome DevTools (e.g. `/hr/ats?tab=applications`).
2. Run **Lighthouse → Accessibility** audit and verify score ≥ 90.
3. Alternatively, install the [axe DevTools browser extension](https://www.deque.com/axe/devtools/) and run a scan on each hub route.
4. Verify keyboard navigation: Tab through all triggers, confirm focus ring visibility, confirm Enter/Space activates tabs.

### Automated Audits (Optional)

#### jest-axe (Unit/Integration)

Create `__tests__/accessibility/hub-pages.test.tsx`:

```tsx theme={null}
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';

expect.extend(toHaveNoViolations);

// Wrap component in required providers (router, query client, etc.)
import { TestProviders } from '@/test-utils/providers';

describe('Hub Page Accessibility', () => {
  it('CredentialingHubPage has no a11y violations', async () => {
    const { default: CredentialingHubPage } = await import(
      '@/cores/hr/pages/CredentialingHubPage'
    );

    const { container } = render(
      <TestProviders>
        <CredentialingHubPage />
      </TestProviders>
    );

    const results = await axe(container);
    expect(results).toHaveNoViolations();
  });
});
```

#### Playwright-axe (E2E)

Create `e2e/accessibility/hub-pages.spec.ts`:

```ts theme={null}
import AxeBuilder from '@axe-core/playwright';
import { expect, test } from '@playwright/test';

const hubRoutes = [
  { route: '/hr/ats?tab=dashboard', name: 'ATS Hub' },
  { route: '/hr/credentialing?tab=dashboard', name: 'Credentialing Hub' },
  { route: '/hr/analytics?tab=dashboard', name: 'Workforce Analytics Hub' },
  { route: '/hr/oversight?tab=relationships', name: 'Oversight Hub' },
];

for (const { route, name } of hubRoutes) {
  test(`${name} (${route}) has no a11y violations`, async ({ page }) => {
    await page.goto(route);
    await page.waitForLoadState('networkidle');

    const results = await new AxeBuilder({ page }).analyze();

    expect(results.violations).toEqual([]);
  });
}
```
