-
Notifications
You must be signed in to change notification settings - Fork 15
Open
Labels
Description
User story
As a Code PushUp user, I want to test accessibility of authenticated pages using axe-core so that I can ensure my login-protected web applications meet WCAG compliance requirements.
Acceptance criteria
-
setupScriptoption added toAxePluginOptionsschema -
setupScriptoption accepts file paths in plugin configuration - Setup script runs once before URL analysis, receiving a Playwright Page instance
- Setup script can perform any Playwright operations, including navigation, form filling, clicking, waiting for elements, cookie manipulation, localStorage access, and multi-tab handling
- Authentication state persists across all URL analyses via shared browser context
- Plugin aborts with descriptive error when:
- setup script is not found
- setup script lacks default function export
- setup script execution throws
- Setup execution logged via logger.task() for progress visibility
- Unit tests cover config validation, path resolution, script validation, and context sharing
- Integration test demonstrates authenticated page analysis workflow
Setup script contract
- Scripts must export a default async function
- Receives a Playwright Page instance within a shared browser context
- Access to
page.context()available for cookie/storage manipulation - Existing
timeoutoption from AxePluginOptions applies to setup navigation
Script execution flow
- Browser launch:
chromium.launch({ headless: true })fromplaywright-core - Context creation: Single shared context via
browser.newContext() - Setup execution:
- Resolve script path (relative to
process.cwd()) - Dynamic import of setup module using the resolved path
- Create page:
context.newPage() - Execute:
await setupFn(page) - Close setup page (context retains auth state)
- Resolve script path (relative to
- URL analysis (for each URL):
- Create page in shared context (inherits auth state)
- Navigate and run
AxeBuilder.analyze()from @axe-core/playwright - Close page
- Cleanup
- The browser session is maintained across all URL analyses to preserve authentication state (cookies, localStorage, etc.)
- The browser closes only after all URLs have been analyzed, regardless of success or failure
Error handling
| Error Type | Behavior | Log Level |
|---|---|---|
| Script not found | Abort plugin | error via thrown exception |
| Missing default export | Abort plugin | error via thrown exception |
| Setup execution failure | Abort plugin | error via thrown exception |
| URL navigation/analysis failure | Skip URL, continue | warn (existing behavior) |
Setup failures cause the plugin to abort, as continuing would test unauthenticated pages, producing misleading results.
Error messages:
Setup script not found: {resolvedPath}Setup script must export a default function: {resolvedPath}Setup script failed: {stringifyError(error)}
Testing
Unit tests
- Configuration validation accepts/rejects
setupScriptvalues - Path resolution (relative and absolute)
- Script validation (missing file, missing export, non-function export)
- Setup function receives Page instance before navigation to target URLs
- Context sharing preserves auth state across multiple URL analyses
E2E tests
- A test fixture exists with the following structure:
e2e/plugin-axe-e2e/mocks/fixtures/auth-setup/
├── test-app/
│ ├── login.html Login form
│ └── protected.html Protected page (requires auth cookie)
├── axe-setup-script.ts Playwright script that logs in
└── code-pushup.config.ts Config using axe plugin with setupScript
- The
protected.htmlfile contains accessibility violations that can only be detected after authentication - The
axe-setup-script.tsnavigates tologin.html, fills the form, submits it, and waits for successful authentication - The
code-pushup.config.tsuses the axe plugin withsetupScript: './axe-setup-script.ts'pointing to the authentication script - The E2E test starts a local HTTP server that serves the test app and validates authentication via cookies
- When the collect command runs, it executes the setup script, successfully authenticates, navigates to the protected page, and analyzes it with axe
- The generated
report.jsoncontains audit results from the authenticated protected page - The test verifies that without the setup script, the protected page would not be accessible (returns 401 or redirects to login)
Documentation
- The
README.mdincludes a "Testing authenticated pages" section with setup script examples - Code examples are provided for common scenarios:
- Basic username/password login with environment variables
- OAuth/SSO flow (e.g., GitHub login)
- Multi-step navigation to nested authenticated pages
- Testing multiple authenticated pages with a shared session
- Documentation includes environment variable setup instructions for local development (
.envfile), GitHub Actions (secrets configuration), and GitLab CI (variables configuration) - The
READMEclarifies that setup scripts use Playwright API for authentication, then@axe-core/playwrightruns the axe analysis
Documentation examples
Basic login:
// axe-setup.ts
import type { Page } from 'playwright-core';
export default async function setup(page: Page): Promise<void> {
await page.goto('https://example.com/login');
await page.fill('[name="username"]', process.env['TEST_USERNAME']);
await page.fill('[name="password"]', process.env['TEST_PASSWORD']);
await page.click('button[type="submit"]');
await page.waitForURL('**/dashboard');
}Cookie-based auth:
import type { Page } from 'playwright-core';
export default async function setup(page: Page): Promise<void> {
await page.context().addCookies([
{
name: 'session_token',
value: process.env['SESSION_TOKEN']!,
domain: 'example.com',
path: '/',
},
]);
}CI configuration (GitHub Actions):
- name: Run Code PushUp
uses: code-pushup/github-action@v0
env:
LOGIN_URL: https://staging.example.com/login
TEST_USER: ${{ secrets.E2E_TEST_USER }}
TEST_PASSWORD: ${{ secrets.E2E_TEST_PASSWORD }}// code-pushup.config.ts
import axePlugin from '@code-pushup/axe-plugin';
export default {
plugins: [
await axePlugin(
[
'https://example.com/dashboard',
'https://example.com/profile',
'https://example.com/settings'
],
{ setupScript: './axe-setup.ts' }
)
],
}