Skip to content

Commit e974f06

Browse files
authored
Merge pull request #933 from coseeian/axe-core-playwright
Add Foundation for Automated Accessibility Testing
2 parents fdffeaf + 3c5eec6 commit e974f06

File tree

6 files changed

+196
-7
lines changed

6 files changed

+196
-7
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,8 @@ in/
2525
out/
2626
translator/
2727

28+
playwright-report/
29+
test-results/
30+
2831
# Don't commit custom dev builds
2932
public/p5.min.js

package-lock.json

Lines changed: 93 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"build:search": "tsx ./src/scripts/builders/search.ts",
1818
"build:p5-version": "tsx ./src/scripts/p5-version.ts",
1919
"custom:dev": "tsx ./src/scripts/branchTest.ts",
20-
"custom:cleanup": "tsx ./src/scripts/resetBranchTest.ts"
20+
"custom:cleanup": "tsx ./src/scripts/resetBranchTest.ts",
21+
"test:a11y": "playwright test test/a11y"
2122
},
2223
"dependencies": {
2324
"@astrojs/check": "^0.5.5",
@@ -51,7 +52,9 @@
5152
}
5253
},
5354
"devDependencies": {
55+
"@axe-core/playwright": "^4.10.2",
5456
"@codemirror/lang-javascript": "^6.2.2",
57+
"@playwright/test": "^1.54.1",
5558
"@preact/preset-vite": "^2.8.2",
5659
"@swc/html": "^1.10.9",
5760
"@testing-library/preact": "^3.2.3",

playwright.config.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
3+
// --- Runtime modes ---
4+
// RUN_MODE=LOCAL -> Start Astro dev server (local development)
5+
// RUN_MODE=BUILD -> Build Astro site and serve from "dist" (CI / closest to production)
6+
// RUN_MODE=REMOTE -> Do not start any local server, test directly against remote URL
7+
const RUN_MODE = process.env.RUN_MODE ?? (process.env.CI ? 'BUILD' : 'LOCAL');
8+
9+
// Allow overriding test directory via environment variable (default: ./tests)
10+
const testDir = process.env.TEST_DIR ?? './test';
11+
12+
// Base URL changes depending on the mode
13+
// LOCAL -> http://localhost:4321 (Astro dev server)
14+
// BUILD -> http://localhost:4173 (served "dist")
15+
// REMOTE -> PROD_BASE_URL (falls back to p5js.org)
16+
const baseURL =
17+
RUN_MODE === 'LOCAL'
18+
? 'http://localhost:4321'
19+
: RUN_MODE === 'BUILD'
20+
? 'http://localhost:4173'
21+
: process.env.PROD_BASE_URL ?? 'https://p5js.org';
22+
23+
24+
export default defineConfig({
25+
// Use dynamic testDir (default ./tests)
26+
testDir,
27+
outputDir: 'test-results',
28+
// Global timeout for each test to improve stability
29+
timeout: 30 * 1000,
30+
fullyParallel: true,
31+
forbidOnly: !!process.env.CI,
32+
// Retry failed tests in CI
33+
retries: process.env.CI ? 2 : 0,
34+
// Force single worker in CI to avoid port/resource conflicts
35+
workers: process.env.CI ? 1 : undefined,
36+
// Reporters: "list" for readable console logs + "html" for detailed report
37+
reporter: [
38+
['list'],
39+
['html', { outputFolder: 'playwright-report', open: 'never' }],
40+
],
41+
use: {
42+
baseURL,
43+
// Save trace only on first retry for debugging failed tests
44+
trace: 'on-first-retry',
45+
// Capture screenshot only on failure
46+
screenshot: 'only-on-failure',
47+
// Keep video only on failure in CI
48+
video: process.env.CI ? 'retain-on-failure' : 'off',
49+
},
50+
51+
// Test projects: three major engines + iPhone 15 viewport
52+
projects: [
53+
{ name: 'Desktop Chrome', use: { ...devices['Desktop Chrome'] } },
54+
{ name: 'Desktop Firefox', use: { ...devices['Desktop Firefox'] } },
55+
{ name: 'Desktop Safari', use: { ...devices['Desktop Safari'] } },
56+
{ name: 'iPhone 15', use: { ...devices['iPhone 15'] } },
57+
{ name: 'Pixel 7', use: { ...devices['Pixel 7'] } },
58+
],
59+
60+
// Start appropriate webServer depending on the mode
61+
webServer:
62+
RUN_MODE === 'LOCAL'
63+
? {
64+
// Start Astro dev server for local development
65+
command: 'npm run dev',
66+
port: 4321,
67+
reuseExistingServer: !process.env.CI,
68+
timeout: 180_000,
69+
}
70+
: RUN_MODE === 'BUILD'
71+
? {
72+
command: 'npm run build && npm run preview -- --port 4173 --host',
73+
port: 4173, // choose port OR url (not both)
74+
reuseExistingServer: !process.env.CI,
75+
timeout: 180_000,
76+
}
77+
: undefined, // REMOTE mode → no server started
78+
});
79+

test/a11y/HomePage.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import AxeBuilder from "@axe-core/playwright";
2+
import { expect, test } from "@playwright/test";
3+
4+
test.describe("a11y-home-page", () => {
5+
test("should not have any automatically detectable accessibility issues", async ({ page }) => {
6+
await page.goto("/");
7+
const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
8+
expect(accessibilityScanResults.violations).toEqual([]);
9+
});
10+
});

vitest.config.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/// <reference types="vitest" />
2+
import { defineConfig, configDefaults } from 'vitest/config';
23
import { getViteConfig } from "astro/config";
34
import preact from "@preact/preset-vite";
45

5-
export default getViteConfig({
6+
export default getViteConfig(defineConfig({
67
// needed to ensure react 3rd party libraries work with preact
78
plugins: [preact()],
89
resolve: {
@@ -12,5 +13,9 @@ export default getViteConfig({
1213
/* for example, use global to avoid globals imports (describe, test, expect): */
1314
// globals: true,
1415
environment: "jsdom",
16+
exclude: [
17+
...configDefaults.exclude,
18+
'test/a11y/**',
19+
],
1520
},
16-
});
21+
}));

0 commit comments

Comments
 (0)