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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uiverify/bun

v0.1.0

Published

Bun capture SDK for UI Verify (uiverify.ai): write visual tests with bun test that drive the installed Chrome through Bun.WebView, and each test archives its final DOM (serialized DOM + resource bytes) to be replayed + visually diffed by UI Verify. Produc

Readme

@uiverify/bun

The UI Verify capture SDK for Bun. Visual tests run on bun test and drive the Chrome you have installed through Bun.WebView; each test archives its final page (the serialized DOM plus the bytes of its images, fonts and stylesheets) for UI Verify to replay and diff. It talks to nothing at runtime: uiverify upload --static-dir uiverify-archive ships the archive.

Needs Bun 1.3.12 or later and Google Chrome or Chromium (BUN_CHROME_PATH points at another).

bun add -d @uiverify/bun

A suite and a test

// tests/visual/fixtures.ts
import { DEFAULT_VIEWPORT, defineSuite } from "@uiverify/bun";

export const visualSuite = defineSuite(
  { viewports: { "": DEFAULT_VIEWPORT, mobile: { width: 390, height: 844 } } },
  (page) => {
    // Runs at the start of every test.
    page.route("**/api/flags", (route) => route.fulfill({ json: { newCheckout: false } }));
  },
);

// tests/visual/home.visual.ts
import { expect, takeSnapshot } from "@uiverify/bun";
import { visualSuite } from "./fixtures";

const { describe, test } = visualSuite(import.meta.path);

describe("Home", () => {
  test("signed out", async (page) => {
    await page.goto("/");
    await expect(page.getByRole("heading", { name: "Welcome" })).toBeVisible();
  });

  test("menu", async (page) => {
    await page.goto("/");
    await page.getByRole("button", { name: "Menu" }).click();
    await takeSnapshot("open");
  });
});

A test that never calls takeSnapshot() is snapshotted once when it ends. Each viewport entry runs the test once; a snapshot's id is <file> > <describe>… > <test>, plus ::<name> and ::<viewport key>.

expect is bun:test's, with retrying assertions for a locator (toBeVisible, toBeAttached, toHaveCount, toBeDisabled, toHaveValue, toHaveAttribute, and .not). Await them, and pass them a locator: with @testing-library/jest-dom's types installed, expect(element).toBeVisible() on a DOM element is jest-dom's matcher.

Running

// tests/visual/run.ts — `bun tests/visual/run.ts [files…] [-t <name pattern>]`
import { run } from "@uiverify/bun/run";

process.exitCode = await run({
  shards: { "tests/visual/home.visual.ts": 2 },
  webServer: { command: ["bun", "server.ts"], port: 3000, ready: "Listening" },
});

run() starts the web servers (with PORT and UI_VERIFY=1 set), runs every *.visual.ts in its own bun test process, and writes the archive's index. Its test processes ignore the app's bunfig.toml (a test preload such as happy-dom replaces fetch), so fixtures must not import modules that need a loader or define registered there.

What every capture pins

The page clock starts at the suite's now (default 2026-01-01T00:00:00Z, read as UTC unless it names an offset) and runs until page.pauseClock(); Math.random is seeded; animations and transitions finish instantly; the timezone is UTC, the locale en-US, motion reduced, and the colour scheme the suite's colorScheme. Before a snapshot it waits up to 3 s for the fonts in use, then up to 3 s for every image and CSS background to load, then for the page to stop moving: a page whose elements keep moving (a requestAnimationFrame loop, a Lottie) fails after 10 s. A canvas that keeps redrawing in place isn't detected and is captured mid-frame. Stop either while UI Verify captures, by checking isUIVerify().

Each test starts on a blank page with no routes or init scripts, the storage of every origin the previous test requested cleared, no cookies and no history. Chrome's caches persist, but a route always sees the requests of a test's first page; a second goto in the same test may take assets from memory, so register routes before the first.

Notes

  • page.addInitScript(fn) sends fn as source: it can't use variables from around it.
  • serveBundle({ entrypoint, plugins, define }) builds and serves a component page. Bun.build inlines no env, so a process.env.PUBLIC_* the components read goes in define. Fonts are waited for once they are in use: a component that measures its text on mount should have its entry await document.fonts.load(…) before rendering.
  • A tab the page opens (a target=_blank link, window.open) is closed at once; the test stays on its page.
  • A cross-site iframe runs in a process of its own: its requests aren't routed, it gets no init scripts or clock, and its storage isn't reset between tests.
  • Capture in CI on Linux: a baseline captured on a Mac renders text differently.