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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@yamf/test

v0.1.3

Published

Functional testing module - with polymorphic async/await and simultaneous assertion reports

Downloads

387

Readme

@yamf/test

A minimal, zero-dependency testing library with polymorphic async/await and simultaneous assertion reports.

Node License

Features

Zero Dependencies - Pure Node.js implementation
🔄 Automatic Async Detection - Just add await when needed
📊 Multi-Assertion Reports - All failures reported simultaneously
🏃 Sequential Test Execution - Predictable, ordered test runs
🎯 Solo/Mute Flags - Focus on specific tests or skip others
📦 Suite Support - Organize tests into logical groups
🎨 Colorized Output - Clear pass/fail visualization

Installation

npm install @yamf/test

Quick Start

import { assert, runTests } from '@yamf/test'

function testAddition() {
  assert(2 + 2, n => n === 4)
}

async function testAsyncFetch() {
  await assert(
    async () => await fetchData(),
    data => data.status === 'ok'
  )
}

runTests({ testAddition, testAsyncFetch })

Core Assertions

assert(value, ...assertFns)

Assert that a value or function result passes all assertion functions.

// Direct value
assert(5, n => n > 0, n => n < 10)

// Function result
assert(() => getValue(), n => n === 42)

// Multiple conditions
const user = { name: 'Alice', age: 30 }
assert(user,
  u => u.name === 'Alice',
  u => u.age > 18
)

// Async (auto-detected - just add await)
await assert(Promise.resolve(10), n => n === 10)
await assert(async () => await fetchData(), d => d.status === 'ok')
await assert(() => fetchData(), d => d.status === 'ok') // Promise-returning

assertErr(error, ...assertFns)

Assert that a function throws an error matching all assertion functions.

// Direct error
assertErr(new Error('test'), err => err.message === 'test')

// Throwing function
assertErr(
  () => { throw new Error('expected') },
  err => err.message === 'expected',
  err => err instanceof Error
)

// Async throwing (auto-detected)
await assertErr(
  async () => { throw new Error('async failure') },
  err => err.message === 'async failure'
)

// Promise rejection
await assertErr(
  () => Promise.reject(new Error('rejected')),
  err => err.message === 'rejected'
)

Array Assertions

assertEach(values, ...assertFns)

Assert that each value in an array passes all assertion functions.

// All values must pass all assertions
assertEach([1, 2, 3, 4, 5],
  n => n > 0,
  n => n < 10
)

// Async values
await assertEach([promise1, promise2, promise3],
  r => r.status === 'ok',
  r => r.code === 200
)

assertSequence(values, ...assertFns)

Assert that each value passes its corresponding assertion function.

// 1:1 mapping of values to assertions
assertSequence(['first', 'second', 'third'],
  v => v === 'first',
  v => v === 'second',
  v => v === 'third'
)

// Async sequence
await assertSequence([promise1, promise2, promise3],
  n => n === 10,
  n => n === 20,
  n => n === 30
)

assertErrEach(errors, ...assertFns)

Assert that each error in an array passes all assertion functions.

// Error objects
assertErrEach([
  new Error('Connection failed'),
  new Error('Timeout occurred')
],
  err => err instanceof Error,
  err => err.message.length > 0
)

// Throwing functions
assertErrEach([
  () => { throw new Error('error1') },
  () => { throw new Error('error2') }
],
  err => err instanceof Error,
  err => err.message.includes('error')
)

assertErrSequence(errors, ...assertFns)

Assert that each error passes its corresponding assertion function.

assertErrSequence([
  () => { throw new Error('Step 1 failed') },
  () => { throw new Error('Step 2 failed') }
],
  err => err.message.includes('Step 1'),
  err => err.message.includes('Step 2')
)

Test Runners

runTests(tests)

Run tests directly without organizing into suites.

import { runTests } from '@yamf/test'

const tests = {
  testOne() { assert(1, n => n === 1) },
  testTwo() { assert(2, n => n === 2) }
}

runTests(tests)
  .then(() => process.exit(0))
  .catch(err => process.exit(err.code || 1))

TestRunner Class

Organize tests into suites for better organization.

import { TestRunner } from '@yamf/test'

const runner = new TestRunner()

// Add individual suite
runner.addSuite('math', {
  testAddition() { assert(2 + 2, n => n === 4) },
  testSubtraction() { assert(5 - 3, n => n === 2) }
})

// Add multiple suites
runner.addSuites({
  strings: {
    testConcat() { assert('a' + 'b', s => s === 'ab') }
  },
  arrays: {
    testPush() {
      const arr = [1, 2]
      arr.push(3)
      assert(arr.length, n => n === 3)
    }
  }
})

runner.run()

Test Helpers

sleep(ms)

Simple promise-based delay.

import { sleep } from '@yamf/test'

async function testWithDelay() {
  await sleep(100) // Wait 100ms
  assert(true, v => v === true)
}

terminateAfter(...servers, testFn)

Run tests with automatic server cleanup. Terminates all servers after the test completes (success or failure).

import { terminateAfter } from '@yamf/test'
import { registryServer, createService } from '@yamf/core'

async function testServices() {
  await terminateAfter(
    registryServer(),
    createService(function myService(p) { return { ok: true } }),
    async (registry, service) => {
      const result = await callService('myService', {})
      assert(result.ok, v => v === true)
    }
  )
}

withEnv(envVars, testFn)

Run a test with temporary environment variables that are restored after.

import { withEnv } from '@yamf/test'

async function testWithEnv() {
  await withEnv(
    { NODE_ENV: 'test', API_KEY: 'secret' },
    async () => {
      assert(process.env.NODE_ENV, v => v === 'test')
      assert(process.env.API_KEY, v => v === 'secret')
    }
  )
  // Original env vars restored here
}

Solo and Mute Flags

Focus on specific tests or skip others during development.

function testNormal() {
  assert(1, n => n === 1)
}

// Only run this test (and others marked solo)
function testFocused() {
  assert(2, n => n === 2)
}
testFocused.solo = true

// Skip this test
function testSkipped() {
  assert(3, n => n === 3)
}
testSkipped.mute = true

runTests({ testNormal, testFocused, testSkipped })
// Only testFocused will run

Error Types

AssertionFailure

Thrown when an assertion fails with details about the failure.

MultiAssertionFailure

Thrown when multiple assertions fail in a single test, containing all failure details.

Best Practices

Name Test Functions

Named functions provide clear test output:

// Good - clear output: "✔ testUserValidation"
function testUserValidation() {
  assert(user.isValid, v => v === true)
}

// Avoid - unclear output
const test1 = () => assert(user.isValid, v => v === true)

Export Test Functions

Export tests for CLI usage and composability:

// user-tests.js
export function testUserCreation() { /* ... */ }
export function testUserDeletion() { /* ... */ }

// run-all.js
import * as userTests from './user-tests.js'
import * as authTests from './auth-tests.js'

runTests({ ...userTests, ...authTests })

Use TODO for Pending Tests

Mark incomplete tests with TODO in the name:

function TODOtestNewFeature() {
  throw new Error('TODO: implement this test')
}
// Test will be counted but not run

Example Output

✔ testDirectValue (1ms)
✔ testFunctionResult (0ms)
✔ testAsyncFunction (15ms)
✘ testFailingAssertion

----- Testing Complete -----
✔ ✔ ✔  Success Report  ✔ ✔ ✔

  testDirectValue
  testFunctionResult
  testAsyncFunction

✘ ✘ ✘  Failure Report  ✘ ✘ ✘

  testFailingAssertion

testFailingAssertion failed with error: AssertionFailure: ...

----- Test Overview -----
ℹ tests 4
ℹ pass 3
ℹ fail 1
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 42

API Reference

Assertions

| Function | Description | |----------|-------------| | assert(value, ...fns) | Assert value passes all assertion functions | | assertErr(error, ...fns) | Assert error matches all assertion functions | | assertEach(values, ...fns) | Assert each value passes all assertions | | assertSequence(values, ...fns) | Assert each value passes corresponding assertion | | assertErrEach(errors, ...fns) | Assert each error passes all assertions | | assertErrSequence(errors, ...fns) | Assert each error passes corresponding assertion |

Runners

| Function | Description | |----------|-------------| | runTests(tests) | Run tests directly | | TestRunner | Class for organizing tests into suites | | runTestFnsSequentially(fns) | Low-level sequential test execution | | mergeAllTestsSafely(...tests) | Merge test objects with duplicate detection |

Helpers

| Function | Description | |----------|-------------| | sleep(ms) | Promise-based delay | | terminateAfter(...servers, fn) | Run test with server cleanup | | withEnv(vars, fn) | Run test with temporary env vars |

Error Types

| Type | Description | |------|-------------| | AssertionFailure | Single assertion failure | | AssertionFailureDetail | Detailed failure information | | MultiAssertionFailure | Multiple assertion failures |

License

MIT