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

@litert/utils-test

v2.2.0

Published

The utility functions/classes/constants about test (using node:test) for NodeJS.

Readme

LiteRT/Utils - Test

Strict TypeScript Checked npm version License node GitHub issues GitHub Releases

The utility functions/classes/constants about test (using node:test) for NodeJS.

[TOC]

Requirement

  • TypeScript v5.0.0 (or newer)
  • Node.js v22.0.0 (or newer)

Installation

npm i @litert/utils-test --save

Getting Started

Both autoTick and autoTickMs work with the Node.js built-in timer mocking API (ctx.mock.timers). Before using either function inside a test, you must enable timer mocking on the test context and ensure node:timers/promises is imported in the correct form.

Step 1 — Enable timer mocking

At the beginning of your test, call:

ctx.mock.timers.enable({ apis: ['setTimeout', 'Date'] });

Include every timer API your code-under-test actually uses in the apis array (e.g., 'setInterval', 'setImmediate', 'Date').

Step 2 — Import node:timers/promises correctly

[!IMPORTANT] In some old Node.js versions, the namespace import form (import * as) bypasses timer mocking. Always use the default import form to guarantee that the timers are properly intercepted:

// Correct — timers will be mocked
import NodeTimer from 'node:timers/promises';

// Incorrect — timers may not be mocked in older Node.js versions
import * as NodeTimer from 'node:timers/promises';

APIs

Function autoTick

Advances all pending mocked timers at once on every event loop tick until the given promise settles.

Internally, autoTick calls ctx.mock.timers.runAll() in a loop — once per event loop tick. Each call to runAll() fires all currently pending timers, advancing the mock clock to the time of the last scheduled timer in one step.

Signature:

function autoTick<T>(
    ctx: TestContext,
    asyncTask: Promise<T> | (() => Promise<T>),
): Promise<T>

Parameters:

| Parameter | Type | Description | | --- | --- | --- | | ctx | TestContext | The test context provided by node:test, used to drive the mocked timers. | | asyncTask | Promise<T> \| (() => Promise<T>) | The async task to run, passed either as an already-created Promise or as a factory function that returns one. |

Returns: Resolves with the same value as asyncTask, or rejects with the same error.

[!WARNING] autoTick always fires every pending timer at its full scheduled duration via runAll(). If a timer is cancelled early by an AbortController signal, the mock clock still counts the full timer duration — not the elapsed time at the point of cancellation. Use autoTickMs instead if accurate abort-signal timing matters to your test.

Example — basic usage:

import * as NodeTest from 'node:test';
import NodeTimer from 'node:timers/promises';
import { autoTick } from '@litert/utils-test';

NodeTest.it('resolves correctly with mocked timers', async (ctx) => {
    ctx.mock.timers.enable({ apis: ['setTimeout', 'Date'] });

    const result = await autoTick(ctx, async () => {
        await NodeTimer.setTimeout(1000);
        await NodeTimer.setTimeout(2000);
        return 'done';
    });

    console.log(result); // 'done'
    // The test completes instantly — no real time elapsed
});

Example — passing a Promise directly:

NodeTest.it('accepts a pre-created promise', async (ctx) => {
    ctx.mock.timers.enable({ apis: ['setTimeout', 'Date'] });

    const task = (async () => {
        await NodeTimer.setTimeout(500);
        return 42;
    })();

    const result = await autoTick(ctx, task);
    console.log(result); // 42
});

Function autoTickMs

Advances the mocked clock by a fixed number of milliseconds on every event loop tick until the given promise settles.

Internally, autoTickMs calls ctx.mock.timers.tick(tickMs) in a loop — once per event loop tick. Because the clock advances in discrete steps, the mock time elapsed when the promise settles reflects only the ticks that actually ran up to that point, allowing abort-signal timing to be precise.

Signature:

function autoTickMs<T>(
    ctx: TestContext,
    asyncTask: Promise<T> | (() => Promise<T>),
    options?: IAutoTickMsOptions,
): Promise<T>

Parameters:

| Parameter | Type | Description | | --- | --- | --- | | ctx | TestContext | The test context provided by node:test, used to drive the mocked timers. | | asyncTask | Promise<T> \| (() => Promise<T>) | The async task to run, passed either as an already-created Promise or as a factory function that returns one. | | options | IAutoTickMsOptions | Optional settings that control the ticking behaviour. |

Returns: Resolves with the same value as asyncTask, or rejects with the same error.

Options — IAutoTickMsOptions:

| Property | Type | Default | Description | | --- | --- | --- | --- | | tickMs | number | 1 | Milliseconds to advance the mock clock per event loop tick. Increase this for tests that involve long total timer durations to reduce the number of iterations and keep the test fast. |

[!NOTE] Because autoTickMs checks whether the promise has settled only after each tick, at most one extra tick may occur after the promise settles. The final mock clock value might therefore be up to tickMs milliseconds ahead of the exact settlement point.

Example — basic usage:

import * as NodeTest from 'node:test';
import NodeTimer from 'node:timers/promises';
import { autoTickMs } from '@litert/utils-test';

NodeTest.it('resolves correctly with mocked timers', async (ctx) => {
    ctx.mock.timers.enable({ apis: ['setTimeout', 'Date'] });

    const result = await autoTickMs(ctx, async () => {
        await NodeTimer.setTimeout(1000);
        await NodeTimer.setTimeout(2000);
        return 'done';
    });

    console.log(result); // 'done'
});

Example — precise abort-signal timing:

NodeTest.it('timer aborted at 50ms counts only ~50ms of mock time', async (ctx) => {
    ctx.mock.timers.enable({ apis: ['setTimeout', 'Date'] });

    const t0 = Date.now();
    const ac = new AbortController();

    try {
        await autoTickMs(ctx, async () => {
            setTimeout(() => ac.abort(new Error('abort')), 50);
            await NodeTimer.setTimeout(1000, null, { signal: ac.signal });
        });
    }
    catch { // AbortError expected
    }

    // The promise settled when the abort fired at 50ms,
    // so the mock clock advanced only ~50ms — not the full 1000ms
    console.log(Date.now() - t0); // ~50
});

Example — large tickMs for long-duration timers:

NodeTest.it('handles a 24-hour timer without performance issues', async (ctx) => {
    ctx.mock.timers.enable({ apis: ['setTimeout', 'Date'] });

    // Without tickMs override: tick(1) would run 86,400,000 times
    // With tickMs = 3_600_000: tick(3_600_000) runs only 24 times
    await autoTickMs(
        ctx,
        NodeTimer.setTimeout(3_600_000 * 24),
        { tickMs: 3_600_000 },
    );
});

Function withEnv

Temporarily sets environment variables for the duration of a callback and restores them afterward.

Works with both synchronous and asynchronous callbacks. If the callback returns a Promise, the environment variables are restored once the promise settles (resolves or rejects). Any error thrown by the callback is re-thrown after the environment variables are restored.

Signature:

function withEnv<T extends () => any>(env: IDict, cb: T): ReturnType<T>

Parameters:

| Parameter | Type | Description | | --- | --- | --- | | env | IDict | An object of environment variable key-value pairs to set for the duration of the callback. | | cb | T | The callback function to execute with the temporary environment variables. |

Returns: The return value of the callback (including Promise if the callback is async).

Example — synchronous callback:

import { withEnv } from '@litert/utils-test';

withEnv({ MY_VAR: 'hello' }, () => {
    console.log(process.env.MY_VAR); // 'hello'
});

console.log(process.env.MY_VAR); // undefined (restored)

Example — asynchronous callback:

import { withEnv } from '@litert/utils-test';

await withEnv({ NODE_ENV: 'test' }, async () => {
    await someAsyncOperation();
    console.log(process.env.NODE_ENV); // 'test'
});

console.log(process.env.NODE_ENV); // restored to original

Choosing Between autoTick and autoTickMs

| | autoTick | autoTickMs | | --- | --- | --- | | Timer advancement | Fires all pending timers at once (runAll()) | Advances by fixed tickMs increments (tick(ms)) | | Speed | Fastest — constant iterations regardless of total duration | Proportional to total duration ÷ tickMs | | Abort-signal precision | Full timer duration always counted | Counts only the ticks up to the abort point | | Timer ordering control | Not possible | Possible with small tickMs | | Long-duration timers | No special concern | Use a larger tickMs for efficiency |

Rule of thumb:

  • Use autoTick when you want the simplest possible way to advance all timers and don't care about abort-signal timing.
  • Use autoTickMs when you need to test abort/cancellation scenarios, timer ordering, or want the mock time to reflect reality as closely as possible.

Documentation

License

This library is published under Apache-2.0 license.

AI Disclaimer

This project may use AI tools to assist in documentation writing and inspiration for unit test cases, but all code is written and reviewed by human developers.