Integrate Oobee with Playwright
What this guide covers
The Oobee npm module lets a Playwright script scan any page it opens. You inject Oobee’s scripts into the page, run a scan, and send the results back to an Oobee instance in Node.js. At the end, Oobee writes one report for all the pages you scanned. This guide covers a JavaScript script. It does not cover Cypress or scanning raw HTML.
Prerequisites
- Node.js 20 or later.
- A project that runs ES modules: set
"type": "module"inpackage.json, or use.mjsfiles. The samples useimportand top-levelawait. - A Playwright project. Refer to Playwright for setup.
- Playwright’s Chromium browser:
npx playwright install chromium. - The reference for every option: npm API.
Step 1: Install Oobee
Add the module to your project:
npm install --save-dev @govtechsg/oobeeThe repository’s integration guide also builds Oobee inside node_modules. Run this if import fails because dist is missing:
cd node_modules/@govtechsg/oobee
npm install
npm run build
cd ../../..Step 2: Create an Oobee instance
Import Oobee in a script that runs in Node.js, and create an instance. thresholds sets the number of issue occurrences that fails the test.
import { chromium } from "playwright";
import oobeeA11yInit from "@govtechsg/oobee";
const oobeeA11y = await oobeeA11yInit({
entryUrl: "<ENTRY_URL>",
testLabel: "Demo Playwright Scan",
name: "<YOUR_NAME>",
email: "<YOUR_EMAIL>",
includeScreenshots: true,
viewportSettings: { width: 1920, height: 1040 },
thresholds: { mustFix: 20, goodToFix: 25 },
scanAboutMetadata: { browser: "Chrome (Desktop)" },
zip: "oobee-scan-results.zip",
deviceChosen: "E2E Test Device",
ruleset: ["enable-wcag-aaa"],
});Leave out thresholds to never fail a test on issue counts. Remove "enable-wcag-aaa" from ruleset to scan Level A and AA rules only.
Step 3: Inject the scripts and run a scan
Open a page, inject the axe-core engine and the Oobee functions, then run the scan in the page. Repeat the injection for every page you visit. Pass page to pushScanResults so Oobee reuses your browser for screenshots.
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
const runOobeeA11yScan = async (elementsToScan, gradingReadabilityFlag) => {
const scanRes = await page.evaluate(
async ({ elementsToScan, gradingReadabilityFlag }) =>
await runA11yScan(elementsToScan, gradingReadabilityFlag),
{ elementsToScan, gradingReadabilityFlag },
);
await oobeeA11y.pushScanResults(scanRes, undefined, undefined, page);
oobeeA11y.testThresholds();
};
await page.goto("<PAGE_URL>");
await page.evaluate(oobeeA11y.getAxeScript());
await page.evaluate(oobeeA11y.getOobeeFunctions());pushScanResults returns the Must Fix and Good to Fix counts for that scan. testThresholds compares the running totals with thresholds. If a total is over, it ends the Oobee instance and throws an error that lists the counts.
Step 4: Scan the whole page and parts of it
Run runOobeeA11yScan with an empty array to scan the whole page. To grade readability, extract the page text, grade it in Node.js and pass the score:
const sentences = await page.evaluate(() => extractText());
const gradingReadabilityFlag = await oobeeA11y.gradeReadability(sentences);
await runOobeeA11yScan([], gradingReadabilityFlag);To scan only some elements, pass CSS selectors. Other accepted forms are in the axe-core context parameter documentation.
await page.getByRole("button", { name: "<BUTTON_NAME>" }).click();
await runOobeeA11yScan(["input", "button"]);Step 5: End the scan and get the report
Close the browser, then terminate Oobee. Oobee builds the report and writes it to a folder under results in your project’s root folder.
await context.close();
await browser.close();
await oobeeA11y.terminate();terminate returns the name of the results folder. Run the script with node <SCRIPT_NAME>.js. For the report files, refer to Read and export scan reports.
Constraints and limitations
| Constraint | Detail |
|---|---|
| Node.js only | Import Oobee in a script that runs in Node.js, not in the page. |
| Script injection | Inject both scripts into every page you visit, after each navigation. |
| Order of scripts | Inject getAxeScript() before getOobeeFunctions(). |
| Cumulative thresholds | testThresholds totals the counts across all pages in the instance. |
| One report per instance | An instance cannot be reused after terminate. Create a new instance for a new report. |
| Readability grading | Grading runs only when AAA rules are enabled. |
Related content
- npm API — every option and method.
- Integrate Oobee with Cypress — the same flow for Cypress tests.
- Gate a CI build on accessibility thresholds — fail a pipeline on issue counts.