Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@pagedjs/test-runner

PDF reftesting for paged-media engines with Playwright.

The runner processes a test document, prints it to PDF, prints its plain HTML reference, and compares the rendered pages. References use WPT match, mismatch, and fuzzy metadata.

Install

Requires Node.js 22.13 or newer and Chromium for Playwright.

npm install --save-dev @pagedjs/test-runner @playwright/test
npx playwright install chromium

No system PDF tools or build step are required.

Configure

Create reftest.config.js in the repository root:

import { defineConfig } from "@pagedjs/test-runner";

export default defineConfig({
	suites: ["specs/*"],
	server: {
		command: "serve . -p 8080 --no-clipboard",
		port: 8080,
		cwd: ".",
		reuseExistingServer: true,
	},
	processor: "/specs/helpers/process.js",
	importMap: {
		imports: {
			"@pagedjs/engine": "/src/index.js",
		},
	},
});

Config discovery checks .js, .mjs, and .cjs files under .config/. Use --config <path> for any other location.

Add a suite

Each suite is a directory containing tests.yml and its HTML files:

specs/
  css-page/
    tests.yml
    basic-pagination-001.html
    basic-pagination-001-ref.html
# specs/css-page/tests.yml
tests:
  - name: basic-pagination-001
  - name: widows-orphans
    fuzzy: maxDifference=0-2;totalPixels=0-400
  - name: long-table
    skip: "table row splitting is not implemented"

name is a filename stem, without a path or .html suffix.

Declare the reference in the test document:

<link rel="match" href="basic-pagination-001-ref.html">

The test is loaded through processor. The reference is loaded and printed as authored; it does not receive the processor, import map, manifest data, or testPrintCSS.

Processor

processor is a browser module that paginates the test document. It reads the manifest entry from data-reftest-entry and marks the document ready when processing finishes:

const root = document.documentElement;

try {
	const entry = JSON.parse(root.dataset.reftestEntry || "{}");
	await paginate(entry);
	root.dataset.reftestReady = "true";
} catch (error) {
	root.dataset.reftestError = `${error.message}\n${error.stack}`;
}

The attribute names are configurable. A processor error or readiness timeout fails the test.

Run

npx pagedjs-test-runner validate
npx pagedjs-test-runner list
npx pagedjs-test-runner run

Filter by suite name:

npx pagedjs-test-runner run css-page css-break

Run options:

npx pagedjs-test-runner run --workers 4
npx pagedjs-test-runner run --grep "widows"
npx pagedjs-test-runner run --reporter html

Pass additional arguments to Playwright after --.

References

Use standard WPT metadata:

<link rel="match" href="expected.html">
<link rel="mismatch" href="must-differ.html">
<meta name="fuzzy" content="maxDifference=0-2;totalPixels=0-400">
  • Match references are alternatives; one must match.
  • Every mismatch reference must differ.
  • maxDifference and totalPixels ranges are inclusive.
  • A PDF page-count difference does not match.

Reference-specific fuzzy metadata uses the WPT prefix form:

<meta name="fuzzy" content="expected.html:maxDifference=0-2;totalPixels=0-400">

Fuzzy settings are resolved in this order: manifest entry, reference-specific metadata, document metadata, suite default, repository default.

Asynchronous rendering

For documents that need additional work before printing, add reftest-wait to the root element. The runner dispatches one bubbling TestRendered event and waits for the class to be removed.

<html class="reftest-wait">
<script>
	document.addEventListener("TestRendered", () => {
		document.documentElement.classList.remove("reftest-wait");
	});
</script>

Test and reference documents both support reftest-wait. Set the timeout with readyTimeout.

Test-only print CSS

Use testPrintCSS for CSS required by the processed output but not by the reference:

export default defineConfig({
	// ...
	testPrintCSS: `
		paged-page { break-after: page }
		paged-page:last-child { break-after: auto }
	`,
});

Page size and reference layout CSS should remain in the test files or their stylesheets.

Configuration

Key Default Description
suites required Suite directories. A trailing /* expands directories containing tests.yml.
server Playwright web server configuration.
baseURL derived from server.port HTTP(S) URL used to load documents. Path prefixes are supported.
rootDir config directory Base directory for relative paths.
serverRoot rootDir Filesystem directory served at baseURL.
processor null Browser module loaded in test documents.
importMap null Import map installed before the processor.
testPrintCSS "" CSS added to processed tests only.
fuzzy exact Default WPT fuzzy tolerance.
entryAttribute data-reftest-entry Attribute containing the manifest entry as JSON.
readyAttribute data-reftest-ready Processor completion attribute.
errorAttribute data-reftest-error Processor error attribute.
timeout 30000 Playwright test timeout in milliseconds.
readyTimeout 15000 Processor and reftest-wait timeout in milliseconds.
pdf.scale 2 PDF rasterization scale.
artifactsDir .pagedjs-test-runner Parent directory for run output.

baseURL must be an HTTP(S) URL without credentials, a query, or a fragment.

Artifacts

Each run writes to a unique directory and prints its path:

.pagedjs-test-runner/runs/<uuid>/
  results/
  report/

results/ contains Playwright output and comparison attachments. report/ contains the HTML report. Artifacts are not pruned automatically.

Exact failures include Playwright expected, actual, and diff images for the failing page. Fuzzy failures include WPT comparison details and page images. No image or PDF baselines are committed or updated by the runner.

Library API

Use the runner from a repository-owned Playwright suite:

// reftest.spec.js
import { loadConfig, registerSuites } from "@pagedjs/test-runner";

const config = await loadConfig("./reftest.config.js");
registerSuites(config);

Filter suites with registerSuites(config, { suites: ["css-page"] }).

Use the supplied Playwright settings from a repository config:

// playwright.config.js
import { defineConfig } from "@playwright/test";
import { loadConfig, playwrightConfig } from "@pagedjs/test-runner";

const config = await loadConfig("./reftest.config.js");

export default defineConfig({
	...playwrightConfig(config),
	testDir: ".",
	testMatch: "reftest.spec.js",
});

The runner uses one headless Chromium project.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages