hpcompaq435/accessaudit-scanner
0
1import { chromium } from "playwright";2import { AxeBuilder } from "@axe-core/playwright";3import type { ScanResult, ScannedViolation, Impact } from "./types.js";4import { computeScore, summarize } from "./score.js";5 6/**7 * The WCAG tag set we test against. axe-core groups rules by these tags.8 * wcag2a/2aa = WCAG 2.0, wcag21aa = 2.1, wcag22aa = 2.2 (the EAA reference level).9 */10const WCAG_TAGS = ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"];11 12export async function scanUrl(url: string): Promise<ScanResult> {13 const browser = await chromium.launch({14 args: ["--no-sandbox", "--disable-dev-shm-usage", "--disable-gpu"],15 });16 try {17 const context = await browser.newContext();18 const page = await context.newPage();19 await page.goto(url, { waitUntil: "networkidle", timeout: 60_000 });20 21 const results = await new AxeBuilder({ page })22 .withTags(WCAG_TAGS)23 .analyze();24 25 const violations: ScannedViolation[] = results.violations.map((v) => ({26 id: v.id,27 impact: (v.impact ?? "minor") as Impact,28 description: v.description,29 help: v.help,30 helpUrl: v.helpUrl,31 wcagTags: v.tags.filter((t) => t.startsWith("wcag")),32 nodeCount: v.nodes.length,33 nodes: v.nodes.slice(0, 10).map((n) => ({34 target: n.target.join(" "),35 html: n.html,36 failureSummary: n.failureSummary ?? "",37 })),38 }));39 40 return {41 url,42 scannedAt: new Date().toISOString(),43 score: computeScore(violations),44 summary: summarize(violations),45 violations,46 };47 } finally {48 await browser.close();49 }50}51 