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

@rcompat/test

v0.8.0

Published

Standard library testing

Readme

@rcompat/test

Testing library for JavaScript runtimes.

What is @rcompat/test?

A cross-runtime testing library with a fluent assertion API. Provides deep equality checks, type assertions, and exception testing. Designed to work with the proby test runner. Works consistently across Node, Deno, and Bun.

Installation

npm install @rcompat/test
pnpm add @rcompat/test
yarn add @rcompat/test
bun add @rcompat/test

Usage

Writing tests

Create a .spec.ts or .spec.js file:

import test from "@rcompat/test";

test.case("addition works", assert => {
  assert(1 + 1).equals(2);
});

test.case("string concatenation", assert => {
  assert("hello" + " " + "world").equals("hello world");
});

Running tests

Use the proby test runner:

npx proby

Equality assertions

import test from "@rcompat/test";

test.case("equals", assert => {
  // primitives
  assert(42).equals(42);
  assert("hello").equals("hello");
  assert(true).equals(true);

  // objects (deep equality)
  assert({ a: 1, b: 2 }).equals({ a: 1, b: 2 });
  assert([1, 2, 3]).equals([1, 2, 3]);

  // nested structures
  assert({ users: [{ name: "Alice" }] }).equals({
    users: [{ name: "Alice" }],
  });
});

test.case("nequals", assert => {
  assert(1).nequals(2);
  assert("foo").nequals("bar");
  assert({ a: 1 }).nequals({ a: 2 });
});

Boolean assertions

import test from "@rcompat/test";

test.case("boolean checks", assert => {
  assert(1 === 1).true();
  assert(1 === 2).false();
  assert(null).null();
  assert(undefined).undefined();
});

Instance assertions

import test from "@rcompat/test";

test.case("instanceof", assert => {
  assert(new Date()).instance(Date);
  assert(new Map()).instance(Map);
  assert([1, 2, 3]).instance(Array);
});

Exception assertions

import test from "@rcompat/test";

test.case("throws", assert => {
  // check that function throws
  assert(() => {
    throw new Error("oops");
  }).throws();

  // Check specific error message
  assert(() => {
    throw new Error("invalid input");
  }).throws("invalid input");
});

test.case("tries (does not throw)", assert => {
  assert(() => {
    return 42;
  }).tries();
});

Type assertions

import test from "@rcompat/test";

test.case("type checking", assert => {
  // compile-time type checks
  assert<string>().type<string>();
  assert("hello").type<string>();

  // check types don't match
  assert<string>().nottype<number>();
  assert(42).nottype<string>();

  // literal types
  assert<"foo">().type<"foo">();
  assert<"foo">().nottype<"bar">();
});

Async tests

import test from "@rcompat/test";

test.case("async operations", async assert => {
  const result = await Promise.resolve(42);
  assert(result).equals(42);
});

test.case("fetch data", async assert => {
  const response = await fetch("https://api.example.com/data");
  assert(response.ok).true();
});

Cleanup with ended

import test from "@rcompat/test";

test.case("database test", async assert => {
  const db = await openDatabase();
  const user = await db.createUser({ name: "Alice" });
  assert(user.name).equals("Alice");
});

test.ended(async () => {
  // cleanup after all tests in this file
  await closeDatabase();
});

API Reference

test.case

test.case(name: string, body: (assert: Asserter) => void | Promise<void>): void;

Define a test case.

| Parameter | Type | Description | | --------- | ---------- | ------------------------------------- | | name | string | Test case name | | body | function | Test function receiving assert helper |

test.ended

test.ended(callback: () => void | Promise<void>): void;

Register a cleanup callback to run after all tests in the file.

Asserter

type Asserter = <T>(actual?: T) => Assert<T>;

The assert function passed to test cases.

Assert<T>

| Method | Description | | ----------------------- | ----------------------------------------- | | equals(expected) | Deep equality check | | nequals(expected) | Deep inequality check | | true() | Assert value is true | | false() | Assert value is false | | null() | Assert value is null | | undefined() | Assert value is undefined | | instance(constructor) | Assert value is instance of class | | throws(message?) | Assert function throws (optional message) | | tries() | Assert function does not throw | | type<T>() | Compile-time type assertion | | nottype<T>() | Compile-time negative type assertion | | pass() | Manually pass the assertion | | fail(reason?) | Manually fail the assertion |

Utilities

equals

import equals from "@rcompat/test/equals";

equals(a: unknown, b: unknown): boolean;

Deep equality check supporting primitives, objects, arrays, maps, sets, dates.

any

import any from "@rcompat/test/any";

any(value: unknown): never;

Cast any value to never type for testing purposes.

undef

import undef from "@rcompat/test/undef";

const value: never = undef;

Pre-cast undefined value typed as never.

E

import E from "@rcompat/test/E";

E(error: unknown): { message: string };

Extract error message from unknown error type.

Examples

Testing a utility function

// sum.ts
export default (a, b) => a + b;

// sum.spec.ts
import test from "@rcompat/test";
import sum from "./sum.js";

test.case("sum adds two numbers", assert => {
  assert(sum(1, 2)).equals(3);
  assert(sum(-1, 1)).equals(0);
  assert(sum(0, 0)).equals(0);
});

Testing a class

import test from "@rcompat/test";

class Calculator {
  #value = 0;
  add(n) {
    this.#value += n;
    return this;
  }
  subtract(n) {
    this.#value -= n;
    return this;
  }
  get value() {
    return this.#value;
  }
}

test.case("calculator operations", assert => {
  const calc = new Calculator();
  calc.add(10).subtract(3);
  assert(calc.value).equals(7);
});

test.case("calculator is instance", assert => {
  assert(new Calculator()).instance(Calculator);
});

Testing error handling

import test from "@rcompat/test";

function divide(a, b) {
  if (b === 0) throw new Error("Division by zero");
  return a / b;
}

test.case("divide throws on zero", assert => {
  assert(() => divide(10, 0)).throws("Division by zero");
});

test.case("divide works normally", assert => {
  assert(() => divide(10, 2)).tries();
  assert(divide(10, 2)).equals(5);
});

Cross-Runtime Compatibility

| Runtime | Supported | | ------- | --------- | | Node.js | ✓ | | Deno | ✓ | | Bun | ✓ |

No configuration required — just import and use.

License

MIT

Contributing

See CONTRIBUTING.md in the repository root.