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

@fr0/testing

v0.1.0

Published

Snapshot / visual regression / determinism testing utilities for fr0.

Downloads

145

Readme

@fr0/testing

Snapshot and diff utilities for Timeline IR regression testing.

Status

✅ Phase α-3 — done (JSON snapshot / diff / sampling) ⏳ Visual regression (pixel-level) — planned alongside the Phase β+ canvas renderer / encoder

Purpose

Catch unintended changes in what @fr0/core's resolve() produces, without standing up a browser for every test.

Two complementary entry points:

  • snapshotState / snapshotTimeline — canonical, deterministic JSON snapshots of ResolvedState, ready for vitest's toMatchSnapshot / toMatchInlineSnapshot.
  • diffResolved / formatDiff — human-readable diff of two resolved states with dotted paths and stable (alphabetically sorted) output, for debugging failed assertions.

Pure TypeScript, no DOM, no jsdom.

Quick start

import { resolve } from '@fr0/core';
import { snapshotTimeline, snapshotState, diffResolved, formatDiff } from '@fr0/testing';
import { describe, expect, it } from 'vitest';
import { titleCard } from '@fr0/templates';

describe('titleCard', () => {
  it('matches the approved snapshot', () => {
    expect(snapshotTimeline(titleCard.timeline as never)).toMatchSnapshot();
  });

  it('frame 0 opacity is 0 (fadeIn start)', () => {
    const state = resolve(titleCard.timeline as never, 0);
    expect(snapshotState(state).title.transform.opacity).toBe(0);
  });
});

// On failure:
const actual = resolve(timeline, 10);
const baseline = resolve(timeline, 10); // or reference state
console.log(formatDiff(diffResolved(baseline, actual)));
// → 'title.transform.opacity: 0.333333 -> 0.5'

Public API

| Export | Purpose | |---|---| | canonicalize(value, options?) | Recursively rewrite a JSON-like value into canonical form: keys sorted alphabetically at every level, finite numbers rounded to precision (default 6), -0 normalized to 0, undefined fields dropped, arrays preserve order. | | sampleFrames(timeline, count) | Pick count evenly-spaced integer frame indices across [0, totalFrames). Always includes frame 0 and totalFrames - 1. | | snapshotState(state, options?) | Canonicalize a single ResolvedState for snapshotting. | | snapshotTimeline(timeline, options?) | Resolve the timeline at multiple frames (explicit list or sample count) and wrap the results with width / height / fps / totalFrames metadata. | | diffResolved(a, b, options?) | Recursive diff between two ResolvedState values. Returns a stable, flat list of DiffEntry. Numeric tolerance controlled by epsilon (default 1e-6). | | formatDiff(entries) | Pretty-print a DiffEntry[] as one line per entry (path: a -> b). Returns (identical) on empty input. |

Design notes

  • Deterministic output: object keys are sorted before serialization and finite numbers are rounded, so two runs of the same code produce byte-identical snapshots even when easing math produces sub-precision jitter.
  • JSON-safe: undefined fields are dropped from canonicalized output so the result round-trips through JSON.stringify without losing information.
  • No tree-circularity handling: Timeline IR and ResolvedState are tree-shaped. Cycles would indicate a bug elsewhere and should surface loudly via a stack overflow rather than being silently papered over.
  • Pure Node: no jsdom, no DOM, no canvas dependencies. Runs instantly in any vitest environment.

Testing

pnpm --filter @fr0/testing test

31 tests across 4 files (canonicalize, sample-frames, snapshot, diff).

What this package is NOT

  • Not a test runner (use vitest / jest / etc.)
  • Not a pixel-level visual regression tool yet (Phase β+, once the canvas renderer / encoder lands server-side)
  • Not tied to a specific framework — returns plain JS values, so any assertion library works