npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

wrightplay

v0.6.5

Published

playwright, but unit test

Downloads

15

Readme

wrightplay

Build Status npm Package

Experience the seamless synergy of Playwright with wrightplay: while Playwright takes the center stage for Node.js (e2e testing), wrightplay puts the spotlight back on browsers (unit testing).

For a complete example showing how to use wrightplay, check out wrightplay-demo.

Project Under Development

But feel free to try! All APIs should work, they just lack test cases and documentations.

When should I choose wrightplay?

  • You want Node.js native coverage reports
  • You want full TypeScript supports
  • You want NET interceptor that intercepts all page requests, with in-page control
  • You want source mapped error stack traces
  • You don't want the error stack mapping to happen inside the browser
  • You don't want the interceptor to occupy Service Worker
  • You don't want to find, choose, and install a “loader” dependency for each browser

The key features come from:

  • It converts chromium coverage output to Node.js format
  • The source mapping of error traces happens outside the browser, affecting no page script but only the Node.js console output
  • Everything written in TypeScript
  • Browsers from Playwright
  • Proxies page.route through WebSocket to a specific module within the page to intercept page requests with in-page control and without occupying Service Worker

Installation

npm i -D wrightplay

Install test browsers with Playwright's cli.

# Default browsers (chromium, firefox, and webkit)
npx playwright install

# Specific browser(s)
# browser: one of: chromium, chrome, chrome-beta, msedge, msedge-beta, msedge-dev, firefox, webkit
# E.g., npx playwright install chromium
npx playwright install <browser...>

To use browsers available on the machine, use channel via browserServerOptions.

For CI environments, check out

For more available options and descriptions, check out

Basic

Write a test setup

Listen to test ready

import { onInit } from 'wrightplay';

onInit(() => {
  startTesting();
});

Pass a callback to onInit to act when all the test files got successfully imported. If called multiple times, onInit will call the callbacks in order. If a callback returns a promise, it will wait until the promise get fulfilled before calling the next callback. If a callback throws an error, the process will exit unsuccessfully.

Indicate the result of your tests

import { done } from 'wrightplay';

onTestEnd((failures) => {
  // Pass the desired process exit number to `done`.
  done(failures > 0 ? 1 : 0);
});

The process may never exit if you don't call this function.

Some test runners like Mocha require additional steps to run in browsers, see Working with... part for examples.

Start

If the tests inject the setup on their own,

wrightplay test/**/*.spec.ts

If the setup is separate and the tests don't inject it themselves,

wrightplay -s test/setup.ts test/**/*.spec.ts

If you want Node.js API,

import { Runner } from 'wrightplay/node';

const runner = new Runner({
  setup: 'test/setup.ts',
  tests: 'test/**/*.spec.ts',
});

process.exit(await runner.runTests());

Check Options for full option list.

HostHandle

APIs similar to JSHandle in Playwright.

Just like you can pass a function from node to browser to run via page.evaluate in Playwright, you can pass a function from browser to node via pageHandle.evaluate in wrightplay.

pageHandle and contextHandle represent the Page and BrowserContext Playwright instance that controls the current page respectively.

Evaluate

Similar to JSHandle.evaluate in Playwright.

import { pageHandle } from 'wrightplay';

const screenshotPath = 'screenshots/1.png';
await pageHandle.evaluate(async (page, path) => {
  await page.screenshot({ path });
}, screenshotPath);

EvaluateHandle

Similar to JSHandle.evaluateHandle in Playwright.

import { pageHandle } from 'wrightplay';

const browserHandle = await pageHandle
  .evaluateHandle((page) => page.context().browser());

// "103.0.5060.42" on chromium as of writing
await browserHandle.evaluate((b) => b.version());

Dispose

Similar to JSHandle.dispose in Playwright.

getProperties

Similar to JSHandle.getProperties in Playwright.

getProperty

Similar to JSHandle.getProperty in Playwright.

jsonValue

Similar to JSHandle.jsonValue in Playwright.

Route

Dedicated API faster than wrapping contextRoute.evaluate for routing, uses ArrayBuffer and Blob for binary data. The handler callback stays in the browser and has access to all the scopes like a normal function has.

Similar to browserContext.route in Playwright.

import { contextRoute } from 'wrightplay';

const body = new Blob(['routed!']);
await contextRoute('hello', (r) => {
  r.fulfill({ body });
}, { times: 1 });

// "routed!"
await (await fetch('hello')).text();

All the routes by this API will auto “unroute” on page unload.

Unroute

Similar to browserContext.unroute in Playwright.

Coverage

Use NODE_V8_COVERAGE environment variable to get coverage results. Tools like c8 that use NODE_V8_COVERAGE internally work as well.

Note that firefox and webkit don't support coverage recording.

# Generate Node.js format coverage output to ./coverage/tmp/
cross-env NODE_V8_COVERAGE=coverage/tmp wrightplay test/*.spec.*

# Or use c8 coverage reports
c8 -a wrightplay test/*.spec.*

-a, --exclude-after-remap option enables c8 to properly parse 1:many source maps for wrightplay. c8 should enable this option by default, but they haven't yet.

Configuration file

You can put the test options (see Options) in a config file, and wrightplay will read it as the option base. See config option for how the CLI resolves the config file path.

You can use an array of option objects to represent multiple test runs that should run in order.

JS

export default {
  tests: 'test/**/*.spec.*',
};

JSON

{
  "tests": "test/**/*.spec.*"
}

TS

import { ConfigOptions } from 'wrightplay/node';

const config: ConfigOptions = {
  tests: 'test/**/*.spec.*',
};

export default config;

Options

config

wrightplay --config path/to/config/file

# Omit to use default
wrightplay

CLI-only option.

Path to config file. The CLI checks these files by default:

[
  'package.json', // "wrightplay" property
  '.wrightplayrc',
  '.wrightplayrc.json',
  '.wrightplayrc.ts',
  '.wrightplayrc.mts',
  '.wrightplayrc.cts',
  '.wrightplayrc.js',
  '.wrightplayrc.mjs',
  '.wrightplayrc.cjs',
  '.config/wrightplayrc',
  '.config/wrightplayrc.json',
  '.config/wrightplayrc.ts',
  '.config/wrightplayrc.mts',
  '.config/wrightplayrc.cts',
  '.config/wrightplayrc.js',
  '.config/wrightplayrc.mjs',
  '.config/wrightplayrc.cjs',
  'wrightplay.config.ts',
  'wrightplay.config.mts',
  'wrightplay.config.cts',
  'wrightplay.config.js',
  'wrightplay.config.mjs',
  'wrightplay.config.cjs',
]

setup

wrightplay -s <path/to/setup>
wrightplay --setup <path/to/setup>

File to run before the test files.

tests

wrightplay [pattern...]

Patterns for the target test files. Check out globby for supported patterns.

entryPoints

wrightplay [entry...]

Additional entry points to build. You can use this option to build workers.

In CLI, use format name=path/to/entry. For example,

wrightplay worker=test/web-worker-helper.ts

or config file

{
  "entryPoints": {
    "worker": "test/web-worker.ts"
  }
}

will make this available:

const worker = new Worker('/worker.js');
// ...

watch

wrightplay -w
wrightplay --watch

Monitor test file changes and trigger automatic test reruns. Defaults to false.

Please be aware that on certain platforms, particularly in the context of large-scale projects, this feature might silently fail or raise some errors.

browser

wrightplay -b <browser>
wrightplay --browser <browser>

Browser type. One of: chromium, firefox, webkit. Defaults to chromium.

browserServerOptions

wrightplay --browser-server-options <json>

Options used to launch the browser server. See browserType.launchServer([options]) in Playwright for details.

headless

In CLI, use --debug.

Run the browser in headless mode. Defaults to true unless the devtools option (in browserServerOptions) is true.

debug

wrightplay -d
wrightplay --debug

CLI-only option.

This sets devtools (in browserServerOptions) to true and headless to false.

noCov

wrightplay --no-cov

Disable coverage file output. This only matters when NODE_V8_COVERAGE is set. Defaults to false on chromium, true on firefox and webkit.

cwd

Current working directory. Defaults to process.cwd().

Working with...

Mocha

Reference:

Use mocha.js

In your package.json, add:

{
  "browser": {
    "mocha": "mocha/mocha.js"
  }
}

Write mocha setup like

import 'mocha';
import { onInit, done } from 'wrightplay';

mocha.setup({
  color: true,
  fullTrace: true,
  reporter: 'spec',
  ui: 'bdd',
});

onInit(() => {
  mocha.run((failures) => {
    done(failures > 0 ? 1 : 0);
  });
});

uvu

uvu has no reliable or future-proof way to run and get the test results programmatically. Track lukeed/uvu · Issue #113.

Click here for an example setup that reads the test results by proxying the console messages.

tape

tape needs some node-specific modules to work: path, stream, events, and process. So we need polyfills to get it to work in browsers.

Steps below may differ if you choose different providers.

Install polyfills

npm i -D path stream events process

In package.json, add:

{
  "browser": {
    "process": "process/browser.js"
  }
}

Write tape setup like

import process from 'process';
import { done } from 'wrightplay';

globalThis.process = process;

const { onFailure, onFinish } = await import('tape');

let exitCode = 0;
onFailure(() => {
  exitCode = 1;
});
onFinish(() => {
  done(exitCode);
});

Zora

Process zora messages

To setup zora, pipe zora reporters to read test results:

import { hold, report, createTAPReporter } from 'zora';
import { done, onInit } from 'wrightplay';

// Hold zora default run
hold();

// Record failed assertion
const tapReporter = createTAPReporter();
async function* record(stream: Parameters<typeof tapReporter>[0]) {
  let exitCode = 0;
  for await (const msg of stream) {
    if (msg.type === 'ASSERTION' && !msg.data.pass) {
      exitCode = 1;
    } else if (msg.type === 'ERROR') {
      done(1);
    } if (msg.type === 'TEST_END') {
      done(exitCode);
    }
    yield msg;
  }
}

onInit(async () => {
  // Run zora with piped reporter
  await report({
    reporter: (stream) => tapReporter(record(stream)),
  });
});