Files
Mario Heiderich 5e23a03688 chore(test): migrate from Karma to Playwright for browser tests
Karma has been deprecated since April 2023 and has been blocking
Dependabot updates across the dev-dependency tree. This migration
replaces it with Playwright while preserving all existing test logic.

Changes:
- Replace Karma + karma-* plugin ecosystem with @playwright/test
- Add tiny zero-dep static file server for the Playwright webServer
- Add HTML runner pages for dist/purify.js and dist/purify.min.js that
  load QUnit, jQuery, DOMPurify, test-suite.js, and an ES module entry
- Add Playwright spec that drives each runner, waits for QUnit.done,
  and surfaces per-assertion failure detail on error
- Drop rollup-plugin-includepaths (was only aliasing 'purify' for Karma)
- Drop minimist (was only used by the old custom-launchers config)
- Update build-and-test.yml to install Playwright browsers and upload
  playwright-report/ artifact on failure

Unchanged:
- test/test-suite.js (2398 lines of QUnit assertions)
- test/bootstrap-test-suite.js
- test/fixtures/expect.mjs
- test/config/setup.js
- test/jsdom-node-runner.js, test/jsdom-node.js
- test/fuzz/**
- rollup.config.js, src/**, scripts/**

Browser coverage: chromium, firefox, and webkit run locally and on
non-BrowserStack CI (3 rendering engines: Blink, Gecko, WebKit).
The 28-browser BrowserStack matrix is temporarily disabled and will
be restored in a follow-up PR via browserstack-node-sdk.

Test counts verified identical pre/post migration:
911 QUnit tests × 2 suites, all passing.
2026-04-16 12:46:30 +02:00

52 lines
1.4 KiB
JavaScript

/* Browser test entry. Loaded as an ES module by index.html and index.min.html.
* Runs after the classic scripts (QUnit, jQuery, DOMPurify, setup, test-suite)
* have executed and populated window globals.
*/
import tests from '/test/fixtures/expect.mjs';
const xssTests = tests.filter((element) => /alert/.test(element.payload));
/* Expose hooks that the Playwright runner polls. */
window.__qunitDone__ = false;
window.__qunitResult__ = null;
window.__qunitFailures__ = [];
QUnit.testDone((details) => {
if (details.failed > 0) {
window.__qunitFailures__.push({
module: details.module,
name: details.name,
failed: details.failed,
total: details.total,
assertions: details.assertions
.filter((a) => !a.result)
.map((a) => ({
message: a.message || null,
expected: a.expected,
actual: a.actual,
source: a.source || null,
})),
});
}
});
QUnit.done((details) => {
window.__qunitResult__ = {
passed: details.passed,
failed: details.failed,
total: details.total,
runtime: details.runtime,
};
window.__qunitDone__ = true;
});
QUnit.module(window.__SUITE_NAME__ || 'DOMPurify');
/* testSuite is a UMD-exported function defined in /test/test-suite.js. In a
* plain browser context it attaches itself to globalThis. */
// eslint-disable-next-line no-undef
testSuite(DOMPurify, window, tests, xssTests);
QUnit.start();