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

@metamesh/testkit

v0.20.0

Published

Runner-neutral MetaMesh model and Generator testing helpers, assertions, and local font fixtures.

Readme

@metamesh/testkit

Check that your MetaMesh models produce the geometry you expect. Run models and Generators with the production engine, check their measurements, and test definitions and presets with your preferred test runner.

Preview: 0.x minor releases may break compatibility. Patches remain compatible within the same minor line.

Installation

Install matching SDK, Modeling, and Testkit releases, with Testkit as a development dependency:

pnpm add @metamesh/generator-sdk @metamesh/modeling
pnpm add -D @metamesh/testkit

The package publishes ES modules only. Use Node.js 24 or newer. TypeScript consumers need TypeScript 6.0 or newer, strict checking, and NodeNext or Bundler module resolution.

The assertions work without a test framework and don't register globals. Testkit has no compiler, renderer, or browser dependency. Use the CLI to check source files, save captured runs, or render images.

Test a model

Build a plate, check its volume and shell count, then check that its meshes reconstruct correctly:

import { box } from "@metamesh/modeling";
import { assertMeshMeasurements, assertValidParts, runModel } from "@metamesh/testkit";

const result = await runModel<{ width: number }>(
  ({ params, part }) => part("plate", box({ size: [params.width, 20, 4] })),
  { width: 30 }
);

assertMeshMeasurements(
  result.part("plate"),
  { signedVolume: 2400, shellCount: 1 },
  { signedVolume: 0.05 }
);
await assertValidParts(result.parts);

runModel returns immutable parts, measurements, diagnostics, and dependencies. Results need no cleanup. Use result.part(id) to find a required part by its ID, or iterate over result.parts.

Always await assertValidParts(parts). It checks the world-space buffers for closed topology, then reconstructs each part from its local geometry and rigid transform and compares the positions and indices exactly. It resolves to the same parts or rejects on failure. Pass an engine as the second argument to reuse one you own; otherwise, the shared test engine initializes when needed.

You can pass an existing Modeling program: await runModel(program, parameters) uses the same program and parameter types as engine.run. For a small test, pass a synchronous callback directly. Without parameters, no type argument or wrapper is needed: await runModel(({ part }) => part("cube", box({ size: 2 }))). Parameters keep the program or callback's declared type. Use GenerateCallback<Parameters, Services> for a reusable callback or supply runModel<Parameters, Services> inline. Options stay in the third argument; use undefined for omitted parameters when supplying an engine, limits, or prepared services.

Assertions

| Helper | Checks | | ------------------------ | -------------------------------------------------------------- | | assertValidDefinition | Strict parsing and a canonical JSON round trip. | | assertValidDefaults | Strict decoding and agreement with definition defaults. | | assertValidPresets | Complete, normalized preset metadata. | | assertValidParts | Part metadata, closed topology, and native reconstruction. | | assertMeshMeasurements | Bounds, surface area, signed volume, and surface shell count. | | assertEqualBuffer | Exact ordered numeric buffer contents without copying storage. | | assertEqualMesh | Exact positions and indices, independently of mesh metadata. |

assertValidDefinition requires strict SDK parsing and a canonical JSON round trip; it does not execute the Generator. Check model assertions and domain constraints through the Generator runner.

Measurement tolerances are absolute: millimetres for bounds, mm² for area, and mm³ for volume. They default to zero; shell counts are exact. Matching measurements do not prove geometric equivalence or rule out self-intersections. Use native reconstruction checks alongside them.

Use assertEqualBuffer(actual, expected) or assertEqualMesh(actual, expected) for exact content comparisons. They read length and at(index) without copying storage and throw ContentMismatchError with the first differing index or length. Malformed representations throw TypeError; reader failures propagate. Numeric equality uses Object.is: NaN equals NaN and signed zero differs. Mesh comparisons ignore metadata and require identical position and index contents. Geometrically equivalent meshes with different triangulation or ordering can fail.

Register contentMatchers with your runner's expect.extend(contentMatchers) to use toEqualBuffer and toEqualMesh, including .not. Only ContentMismatchError becomes a failed matcher result; invalid inputs and unexpected errors still throw. Follow your runner's matcher extension guidance for TypeScript declarations.

Test Generators and repeated edits

For a Generator, import its definition and default runtime, then call runModel({ definition, runtime }, parameters). This validates the inputs and prepares services before generation. Omit parameters or pass undefined to use defaults. Supplied inputs use the definition's inferred types and must form a complete canonical map.

To change one value, spread getDefaultParameters(definition) and apply your override. The runner doesn't merge defaults into supplied values. Use SDK normalizeParameters when recovering saved values. Plain model parameters pass through directly.

Import the actual Generator entry point in integration tests so they exercise its input handling and model together. Direct callbacks are useful for testing construction helpers or mesh reconstruction. For a deliberate schema bypass, runModel(runtime, parameters, { services }) executes the Generator's model behavior without claiming those values pass its parameter schema. See the SDK example.

Use createGeneratorTestRunner(definition, runtime) for repeated parameter cases. Its run method returns a generated result or a structured validation failure. Call runner.run(record) to test unknown keys, missing fields, or wrong value types. Use check to test declarations and reached assertions without finalizing parts; geometry observations can still require the engine. Dispose the runner in finally; returned results remain usable. Use check(parameters, { validateInput: false }) only to probe model assertions with deliberately invalid typed values, bypassing the parameter schema.

Check cache reuse

For models using memo, include repeated-edit tests with { verifyCache: true } on the runner. Change geometry inputs and placement inputs independently. Verification reruns cached calculations and rejects changed results for unchanged inputs. Keep pure helpers stable and pass changing values as arguments; pass the current params/context to track fields read inside the helper. Verification has bounded comparison work. For outputs it can't compare, use { cache: false } on a separate runner and compare the resulting geometry. Neither check proves arbitrary JavaScript pure. Keep prepared service identity stable for unchanged assets; replacing services creates a new session and prevents testing cache reuse. Isolated runModel calls do not verify repeated-edit correctness.

For plain models, use engine.createSession(program, options) for repeated edits or cache tests and dispose the session in finally. Session results remain usable after later runs and disposal. Both runModel and Generator runners can reuse a test-owned engine and lower its resource ceilings. They accept the same physical resolution, meshValidation, and meshTopologyMode policy.

Fonts and entry points

| Import | Responsibility | | --------------------------------- | ------------------------------------------------------------------------------ | | @metamesh/testkit | Model execution, Generator runners, assertions, and optional content matchers. | | @metamesh/testkit/fonts | Prepared font services from supplied fixture bytes. | | @metamesh/testkit/font-fixtures | Node-only JSON fixture loading with SHA-256 verification. |

For a Generator with Font parameters, supply prepareServices to prepare its font services before generation. Tests use checked-in bytes without CDN access; retain their licenses. Font preparation needs Modeling's optional fontkit peer, plus woff2-encoder for WOFF2 fixtures.

Documentation

Resolve @metamesh/testkit/docs/manifest.json for exact-version Markdown guidance and annotated API references. With CLI installed, read pnpm exec metamesh docs show testkit/guide/testing. See Modeling for geometry and Contributing for package development.

License

Apache-2.0.