node/test/wpt
Trivikram Kamat bfb2fa7756
test: mark hr-time WPT flaky on macos15-x64
The basic.any.js test compares elapsed performance.now() with elapsed
Date.now(). On macos15-x64 CI, Date.now() can shift relative to the
monotonic clock and exceed the test's 30 ms tolerance.

Convert the status file to .cjs so the flaky expectation is scoped to
macOS 15 on x64.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/64054
Refs: https://github.com/nodejs/reliability/issues?q=%22wpt%2Ftest-hr-time%22
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
Reviewed-By: Jason Zhang <xzha4350@gmail.com>
2026-06-24 05:09:17 +00:00
..
status test: mark hr-time WPT flaky on macos15-x64 2026-06-24 05:09:17 +00:00
README.md doc: update WPT test runner README.md 2026-04-12 19:49:17 +00:00
test-abort.js test: remove useless require('../common') from WPTs 2023-02-25 16:04:40 +00:00
test-atob.js test: remove useless require('../common') from WPTs 2023-02-25 16:04:40 +00:00
test-blob.js test: remove useless WPT init scripts 2023-02-25 17:03:18 +00:00
test-broadcastchannel.js test: remove useless WPT init scripts 2023-02-25 17:03:18 +00:00
test-compression.js test: update WPT files for WebIDL tests 2023-11-19 07:36:31 +00:00
test-console.js test: remove useless require('../common') from WPTs 2023-02-25 16:04:40 +00:00
test-encoding.js test: enable idlharness tests for encoding 2023-11-20 12:07:55 +00:00
test-events.js test: remove useless require('../common') from WPTs 2023-02-25 16:04:40 +00:00
test-file.js test: remove useless WPT init scripts 2023-03-28 16:18:50 +02:00
test-hr-time.js test: remove useless require('../common') from WPTs 2023-02-25 16:04:40 +00:00
test-microtask-queuing.js test: remove useless require('../common') from WPTs 2023-02-25 16:04:40 +00:00
test-performance-timeline.js perf_hooks: add deliveryType and responseStatus fields 2024-05-12 20:02:48 +02:00
test-resource-timing.js perf_hooks: add deliveryType and responseStatus fields 2024-05-12 20:02:48 +02:00
test-streams.js test: update WPT resources, common, streams, FileAPI, broadcastchannel 2023-03-07 10:19:23 +01:00
test-structured-clone.js test: remove useless WPT init scripts 2023-03-28 16:18:50 +02:00
test-timers.js test: reduce WPT concurrency 2023-05-05 08:40:33 +00:00
test-url.js test: skip url WPT subtests instead of modifying test script 2026-04-10 11:27:31 +00:00
test-urlpattern.js url: expose urlpattern as global 2025-02-09 15:32:59 +00:00
test-user-timing.js test: remove useless require('../common') from WPTs 2023-02-25 16:04:40 +00:00
test-wasm-jsapi.mjs test: wpt for Wasm jsapi including new ESM Integration tests 2026-03-31 09:59:23 -07:00
test-wasm-webapi.js test: remove useless require('../common') from WPTs 2023-02-25 16:04:40 +00:00
test-web-locks.js worker: add web locks api 2025-07-18 07:55:10 -07:00
test-webcrypto.js test: remove Float16Array flag 2025-05-07 20:20:10 +00:00
test-webidl.js test: add webidl web-platform tests 2026-01-15 16:51:10 +00:00
test-webstorage.js src: unflag --experimental-webstorage by default 2025-09-25 11:59:58 +00:00
testcfg.py test: reduce WPT concurrency 2023-05-05 08:40:33 +00:00
wpt.status

Web Platform Tests

This directory contains test runners that execute upstream Web Platform Tests against Node.js using the WPT harness. The actual test files live in test/fixtures/wpt, a subset of the upstream WPT repository containing only the modules relevant to Node.js. Each module is updated independently using git node wpt, so different modules may be pinned to different upstream commits.

Each module has a status file in the status folder that declares build requirements, expected failures, and tests to skip. See test/fixtures/wpt/README.md for the pinned WPT commit hashes for each module.

How to add tests for a new module

1. Create a status file

For example, to add the URL tests, add a test/wpt/status/url.cjs file.

In the beginning, it's fine to leave an empty object module.exports = {} in the file if it's not yet clear how compliant the implementation is, the requirements and expected failures can be figured out in a later step when the tests are run for the first time.

See Format of a status file for details.

2. Pull the WPT files

Use the git node wpt command to download the WPT files into test/fixtures/wpt. For example, to add URL tests:

cd /path/to/node/project
git node wpt url

3. Create the test runner

For example, for the URL tests, add a file test/wpt/test-url.js:

'use strict';

const { WPTRunner } = require('../common/wpt');

const runner = new WPTRunner('url');

runner.pretendGlobalThisAs('Window');
runner.runJsTests();

The runner loads the tests from test/fixtures/wpt/url, applies the status rules from test/wpt/status/url.cjs, and runs them using worker threads.

new WPTRunner(path[, options])

  • path {string} Relative path of the WPT module (e.g. 'url', 'html/webappapis/timers').
  • options {Object}
    • concurrency {number} Number of tests to run in parallel. Defaults to os.availableParallelism() - 1. Set to 1 for tests that require sequential execution (e.g. web-locks, webstorage).

runner.setFlags(flags)

  • flags {string[]} Node.js CLI flags passed to each worker thread (e.g. ['--expose-internals']).

runner.setInitScript(script)

  • script {string} JavaScript code executed in the worker before the tests run. Useful for setting up globals needed by the tests.

runner.setScriptModifier(modifier)

  • modifier {Function} A callback (meta) => void invoked for each script before it is run in the worker. meta is an object with code {string} and filename {string} properties that can be mutated.

runner.pretendGlobalThisAs(name)

  • name {string} Currently only 'Window' is supported. Sets up globalThis.Window so that WPT tests checking the global scope type work correctly.

runner.runJsTests()

Starts running the tests. Must be called last, after all configuration.

4. Run the tests

Run the test using tools/test.py and see if there are any failures. For example, to run all the URL tests under test/fixtures/wpt/url:

tools/test.py wpt/test-url

To run a specific test in WPT, for example, url/url-searchparams.any.js, pass the file name as argument to the corresponding test runner:

node test/wpt/test-url.js url-searchparams.any.js

If there are any failures, update the corresponding status file (in this case, test/wpt/status/url.cjs) to make the test pass.

For example, to mark url/url-searchparams.any.js as expected to fail, add this to test/wpt/status/url.cjs:

module.exports = {
  'url-searchparams.any.js': {
    fail: {
      expected: [
        'test name in the WPT test case, e.g. second argument passed to test()',
      ],
    },
  },
};

See Format of a status file for details.

5. Commit the changes and submit a Pull Request

See the contributing guide.

How to update tests for a module

The tests can be updated in a way similar to how they are added. Run Step 2 and Step 4 of adding tests for a new module.

The git node wpt command maintains the status of the local WPT subset. If no files are updated after running it for a module, the local subset is up to date and there is no need to create a PR. When files are updated, run the tests and update the status file to account for any new failures or passes before submitting.

Daily WPT report

A GitHub Actions workflow runs every night and uploads results to wpt.fyi. It tests all active Node.js release lines and the latest nightly build against the WPT epochs/daily branch, which is a daily snapshot of the upstream WPT repository.

Unlike the pinned fixtures used in CI, this workflow replaces test/fixtures/wpt with the full epochs/daily checkout so that results reflect the latest upstream tests. Results can be viewed on the wpt.fyi dashboard.

Format of a status file

The status file can be either a .json file or a .cjs module that exports the same object. Using CJS allows for conditional logic and regular expressions, which JSON does not support.

module.exports = {
  'something.scope.js': { // the file name
    // Optional: If the requirement is not met, this test will be skipped.
    // Supported values:
    //   'small-icu' - requires at least small-icu intl support
    //   'full-icu'  - requires full-icu intl support
    //   'crypto'    - requires crypto (OpenSSL) support
    //   'inspector' - requires the inspector to be available
    requires: ['small-icu'],

    // Optional: the entire file will be skipped with the reason printed.
    skip: 'explain why we cannot run a test that is supposed to pass',

    // Optional: failing tests.
    fail: {
      // Tests that are expected to fail consistently.
      expected: [
        'test name in the WPT test case, e.g. second argument passed to test()',
        'another test name',
      ],
      // Tests that fail intermittently. These are treated as expected
      // failures but are not flagged as unexpected passes when they
      // succeed.
      flaky: [
        'flaky test name',
      ],
    },
  },
};

A test should be marked with skip when it cannot be run at all, for example, because it depends on a browser-only Web API or a harness feature that has not been ported to the Node.js runner. Use fail instead when the test can run but produces incorrect results due to an implementation bug or missing feature.

Skipping individual subtests

To skip specific subtests within a file (rather than skipping the entire file), use skipTests with an array of exact test names or regular expressions:

module.exports = {
  'something.scope.js': {
    skipTests: [
      'exact test name to skip',
      /regexp pattern to match/,
    ],
  },
};

Skipped subtests are reported as [SKIP] in the output, recorded as NOTRUN in the WPT report, and counted separately in the summary line.

This is useful for skipping a particular subtest that crashes the runner, which would otherwise prevent the rest of the file from being run. Using CJS status files also enables conditionally skipping slow or resource-heavy subtests in CI on specific architectures.

Wildcard patterns in file names

File name keys can include a * character to match multiple test files with a single entry. For example, to skip all .window.js tests:

module.exports = {
  '*.window.js': {
    skip: 'window tests are not relevant for Node.js',
  },
};

The * is converted to a .* regular expression, so "subdir/*.any.js" would match all .any.js files under the subdir directory. A test file can match multiple rules (both an exact match and one or more wildcard patterns); all matched rules are merged.