Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ name: Test, typecheck, and lint
on:
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read

Expand Down Expand Up @@ -48,6 +52,7 @@ jobs:
run: npm run check
build:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout your repository using git
uses: actions/checkout@v6
Expand All @@ -62,3 +67,17 @@ jobs:
SKIP_BUILD_COMPRESS: 1
NODE_OPTIONS: "--max_old_space_size=4096"
run: npm run build
- name: Install Playwright browser
run: npx playwright install --with-deps chromium
- name: Run accessibility tests
continue-on-error: true
run: npm run test:a11y
- name: Upload Playwright report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: |
playwright-report/
test-results/
retention-days: 14
22 changes: 16 additions & 6 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@ import { defineConfig, devices } from "@playwright/test";

const PORT = 4321;
const BASE_URL = `http://localhost:${PORT}`;
const isCI = Boolean(process.env.CI);

export default defineConfig({
testDir: "./test/a11y",
testMatch: "**/*.spec.ts",
outputDir: "./test-results",
fullyParallel: true,
reporter: [
["list"],
['html', { outputFolder: 'playwright-report', open: 'never' }]
],
forbidOnly: isCI,
reporter: isCI
? [
["github"],
["list"],
["html", { outputFolder: "playwright-report", open: "never" }],
]
: [
["list"],
['html', { outputFolder: 'playwright-report', open: 'never' }]
],

use: {
baseURL: BASE_URL,
Expand All @@ -34,10 +42,12 @@ export default defineConfig({
],

webServer: {
command: "npm run dev",
// CI serves the dist/ built by an earlier step; see .github/workflows/test.yml.
command: isCI ? "npm run preview" : "npm run dev",
url: BASE_URL,
reuseExistingServer: true,
reuseExistingServer: !isCI,
timeout: 180_000,
stdout: isCI ? "pipe" : "ignore",
env: {
A11Y_TEST: "1",
},
Expand Down
12 changes: 0 additions & 12 deletions test/a11y/homepage.spec.ts

This file was deleted.

36 changes: 36 additions & 0 deletions test/a11y/pages.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import AxeBuilder from "@axe-core/playwright";
import { expect, test } from "@playwright/test";

const pagesToScan = [
{ name: "home", path: "/" },
{ name: "about", path: "/about/" },
{ name: "community", path: "/community/" },
{ name: "contribute", path: "/contribute/" },
{ name: "education resources", path: "/education-resources/" },
{ name: "events", path: "/events/" },
{ name: "libraries", path: "/libraries/" },
{ name: "people", path: "/people/" },
{ name: "sketches", path: "/sketches/" },
{ name: "search", path: "/search/" },
{ name: "tutorials index", path: "/tutorials/" },
{ name: "tutorial", path: "/tutorials/get-started/" },
{ name: "examples index", path: "/examples/" },
{ name: "example", path: "/examples/Shapes-And-Color-Shape-Primitives/" },
{ name: "reference index", path: "/reference/" },
{ name: "reference function", path: "/reference/p5/ellipse/" },
{ name: "reference class method", path: "/reference/p5.Vector/add/" },
{ name: "reference p5.sound", path: "/reference/p5.sound/" },
{ name: "404", path: "/no-such-page/" },
];

test.describe("a11y", () => {
for (const { name, path } of pagesToScan) {
test(`${name} should not have any automatically detectable accessibility issues`, async ({
page,
}) => {
await page.goto(path);
const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
expect(accessibilityScanResults.violations).toEqual([]);

Check failure on line 33 in test/a11y/pages.spec.ts

View workflow job for this annotation

GitHub Actions / build

[mobile] › test/a11y/pages.spec.ts:28:5 › a11y › tutorial should not have any automatically detectable accessibility issues

5) [mobile] › test/a11y/pages.spec.ts:28:5 › a11y › tutorial should not have any automatically detectable accessibility issues Error: expect(received).toEqual(expected) // deep equality - Expected - 1 + Received + 155 - Array [] + Array [ + Object { + "description": "Ensure the order of headings is semantically correct", + "help": "Heading levels should only increase by one", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.12/heading-order?application=playwright", + "id": "heading-order", + "impact": "moderate", + "nodes": Array [ + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h4 id=\"default-code\">Default Code</h4>", + "impact": "moderate", + "none": Array [], + "target": Array [ + "#default-code", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h5>Tip</h5>", + "impact": "moderate", + "none": Array [], + "target": Array [ + ".callout.callout-note:nth-child(37) > h5", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h4 id=\"tip\">Tip</h4>", + "impact": "moderate", + "none": Array [], + "target": Array [ + "#tip", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h5>Note</h5>", + "impact": "moderate", + "none": Array [], + "target": Array [ + ".callout.callout-note:nth-child(62) > h5", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h5>Note</h5>", + "impact": "moderate", + "none": Array [], + "target": Array [ + ".callout.callout-note:nth-child(82) > h5", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { +

Check failure on line 33 in test/a11y/pages.spec.ts

View workflow job for this annotation

GitHub Actions / build

[desktop] › test/a11y/pages.spec.ts:28:5 › a11y › reference class method should not have any automatically detectable accessibility issues

4) [desktop] › test/a11y/pages.spec.ts:28:5 › a11y › reference class method should not have any automatically detectable accessibility issues Error: expect(received).toEqual(expected) // deep equality - Expected - 1 + Received + 84 - Array [] + Array [ + Object { + "description": "Ensure links have discernible text", + "help": "Links must have discernible text", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.12/link-name?application=playwright", + "id": "link-name", + "impact": "serious", + "nodes": Array [ + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "has-visible-text", + "impact": "serious", + "message": "Element does not have text that is visible to screen readers", + "relatedNodes": Array [], + }, + Object { + "data": null, + "id": "aria-label", + "impact": "serious", + "message": "aria-label attribute does not exist or is empty", + "relatedNodes": Array [], + }, + Object { + "data": null, + "id": "aria-labelledby", + "impact": "serious", + "message": "aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty", + "relatedNodes": Array [], + }, + Object { + "data": Object { + "messageKey": "noAttr", + }, + "id": "non-empty-title", + "impact": "serious", + "message": "Element has no title attribute", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix all of the following: + Element is in tab order and does not have accessible text + + Fix any of the following: + Element does not have text that is visible to screen readers + aria-label attribute does not exist or is empty + aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty + Element has no title attribute", + "html": "<a href=\"/reference/#\" class=\"\"></a>", + "impact": "serious", + "none": Array [ + Object { + "data": null, + "id": "focusable-no-name", + "impact": "serious", + "message": "Element is in tab order and does not have accessible text", + "relatedNodes": Array [], + }, + ], + "target": Array [ + "a[href$=\"reference/#\"]", + ], + }, + ], + "tags": Array [ + "cat.name-role-value", + "wcag2a", + "wcag244", + "wcag412", + "section508", + "section508.22.a", + "TTv5", + "TT6.a", + "EN-301-549", + "EN-9.2.4.4", + "EN-9.4.1.2", + "ACT", + "RGAAv4", + "RGAA-6.2.1", + ], + }, + ] 31 | await page.goto(path); 32 | const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); > 33 | expect(accessibilityScanResults.violations).toEqual([]); | ^ 34 | }); 35 | } 36 | }); at /home/runner/work/p5.js-website/p5.js-website/test/a11y/pages.spec.ts:33:51

Check failure on line 33 in test/a11y/pages.spec.ts

View workflow job for this annotation

GitHub Actions / build

[desktop] › test/a11y/pages.spec.ts:28:5 › a11y › reference function should not have any automatically detectable accessibility issues

3) [desktop] › test/a11y/pages.spec.ts:28:5 › a11y › reference function should not have any automatically detectable accessibility issues Error: expect(received).toEqual(expected) // deep equality - Expected - 1 + Received + 46 - Array [] + Array [ + Object { + "description": "Ensure landmarks are unique", + "help": "Landmarks should have a unique role or role/label/title (i.e. accessible name) combination", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.12/landmark-unique?application=playwright", + "id": "landmark-unique", + "impact": "moderate", + "nodes": Array [ + Object { + "all": Array [], + "any": Array [ + Object { + "data": Object { + "accessibleText": null, + "role": "main", + }, + "id": "landmark-is-unique", + "impact": "moderate", + "message": "The landmark must have a unique aria-label, aria-labelledby, or title to make landmarks distinguishable", + "relatedNodes": Array [ + Object { + "html": "<main>", + "target": Array [ + "astro-island[uid=\"1GttvS\"] > .overflow-hidden.lg\\:flex-row.my-md > .ml-0.w-fit.gap-\\[20px\\] > div:nth-child(1) > div > iframe", + "main", + ], + }, + ], + }, + ], + "failureSummary": "Fix any of the following: + The landmark must have a unique aria-label, aria-labelledby, or title to make landmarks distinguishable", + "html": "<main class=\"relative\" id=\"main-content\">", + "impact": "moderate", + "none": Array [], + "target": Array [ + "#main-content", + ], + }, + ], + "tags": Array [ + "cat.semantics", + "best-practice", + ], + }, + ] 31 | await page.goto(path); 32 | const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); > 33 | expect(accessibilityScanResults.violations).toEqual([]); | ^ 34 | }); 35 | } 36 | }); at /home/runner/work/p5.js-website/p5.js-website/test/a11y/pages.spec.ts:33:51

Check failure on line 33 in test/a11y/pages.spec.ts

View workflow job for this annotation

GitHub Actions / build

[desktop] › test/a11y/pages.spec.ts:28:5 › a11y › example should not have any automatically detectable accessibility issues

2) [desktop] › test/a11y/pages.spec.ts:28:5 › a11y › example should not have any automatically detectable accessibility issues Error: expect(received).toEqual(expected) // deep equality - Expected - 1 + Received + 46 - Array [] + Array [ + Object { + "description": "Ensure landmarks are unique", + "help": "Landmarks should have a unique role or role/label/title (i.e. accessible name) combination", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.12/landmark-unique?application=playwright", + "id": "landmark-unique", + "impact": "moderate", + "nodes": Array [ + Object { + "all": Array [], + "any": Array [ + Object { + "data": Object { + "accessibleText": null, + "role": "main", + }, + "id": "landmark-is-unique", + "impact": "moderate", + "message": "The landmark must have a unique aria-label, aria-labelledby, or title to make landmarks distinguishable", + "relatedNodes": Array [ + Object { + "html": "<main><canvas id=\"defaultCanvas1\" class=\"p5Canvas\" width=\"720\" height=\"400\" style=\"width: 720px; height: 400px; touch-action: none;\"></canvas></main>", + "target": Array [ + "iframe", + "main", + ], + }, + ], + }, + ], + "failureSummary": "Fix any of the following: + The landmark must have a unique aria-label, aria-labelledby, or title to make landmarks distinguishable", + "html": "<main class=\"relative\" id=\"main-content\">", + "impact": "moderate", + "none": Array [], + "target": Array [ + "#main-content", + ], + }, + ], + "tags": Array [ + "cat.semantics", + "best-practice", + ], + }, + ] 31 | await page.goto(path); 32 | const accessibilityScanResults = await new AxeBuilder({ page }).analyze(); > 33 | expect(accessibilityScanResults.violations).toEqual([]); | ^ 34 | }); 35 | } 36 | }); at /home/runner/work/p5.js-website/p5.js-website/test/a11y/pages.spec.ts:33:51

Check failure on line 33 in test/a11y/pages.spec.ts

View workflow job for this annotation

GitHub Actions / build

[desktop] › test/a11y/pages.spec.ts:28:5 › a11y › tutorial should not have any automatically detectable accessibility issues

1) [desktop] › test/a11y/pages.spec.ts:28:5 › a11y › tutorial should not have any automatically detectable accessibility issues Error: expect(received).toEqual(expected) // deep equality - Expected - 1 + Received + 155 - Array [] + Array [ + Object { + "description": "Ensure the order of headings is semantically correct", + "help": "Heading levels should only increase by one", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.12/heading-order?application=playwright", + "id": "heading-order", + "impact": "moderate", + "nodes": Array [ + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h4 id=\"default-code\">Default Code</h4>", + "impact": "moderate", + "none": Array [], + "target": Array [ + "#default-code", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h5>Tip</h5>", + "impact": "moderate", + "none": Array [], + "target": Array [ + ".callout.callout-note:nth-child(37) > h5", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h4 id=\"tip\">Tip</h4>", + "impact": "moderate", + "none": Array [], + "target": Array [ + "#tip", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h5>Note</h5>", + "impact": "moderate", + "none": Array [], + "target": Array [ + ".callout.callout-note:nth-child(62) > h5", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { + "data": null, + "id": "heading-order", + "impact": "moderate", + "message": "Heading order invalid", + "relatedNodes": Array [], + }, + ], + "failureSummary": "Fix any of the following: + Heading order invalid", + "html": "<h5>Note</h5>", + "impact": "moderate", + "none": Array [], + "target": Array [ + ".callout.callout-note:nth-child(82) > h5", + ], + }, + Object { + "all": Array [], + "any": Array [ + Object { +
});
}
});
Loading