A universal JavaScript testing framework that works seamlessly across Bun, Deno, and Node.js. Write your tests once and run them anywhere.
- Universal API - Single test API that works across all three runtimes
- Zero Dependencies - Built on top of native testing frameworks
- Runtime Detection - Automatically uses the appropriate native test implementation
- Simple Assertions - Built-in assertion library for common testing needs
- Type Safe - Written with modern JavaScript/ESM modules
npm install test-anywherebun add test-anywhereNo installation needed! Import directly from npm:
import { test, assert } from 'npm:test-anywhere';Or from your local installation:
import { test, assert } from './node_modules/test-anywhere/index.js';You can use either test() or it() (Mocha/Jest style):
import { test, it, assert } from 'test-anywhere';
// Using test()
test('basic math works', () => {
assert.equal(1 + 1, 2);
});
// Using it() - same as test()
it('should compare objects', () => {
assert.deepEqual({ a: 1 }, { a: 1 });
});Group related tests using describe() blocks:
import { describe, it, assert } from 'test-anywhere';
describe('user module', () => {
describe('creation', () => {
it('should create a new user', () => {
assert.ok(true);
});
it('should validate email format', () => {
assert.match('[email protected]', /@/);
});
});
describe('deletion', () => {
it('should delete existing user', () => {
assert.ok(true);
});
});
});Run tests:
node --test
# or
npm testCreate a test file (e.g., example.test.js):
import { test, assert } from 'npm:test-anywhere';
test('basic math works', () => {
assert.equal(1 + 1, 2);
});
test('strings work', () => {
assert.ok('hello'.includes('ell'));
});Run tests:
deno test --allow-readThe --allow-read permission is needed for Deno to import the module.
Create a test file (e.g., example.test.js):
import { test, assert } from 'test-anywhere';
test('basic math works', () => {
assert.equal(1 + 1, 2);
});
test('async operations work', async () => {
const result = await Promise.resolve(42);
assert.equal(result, 42);
});Run tests:
bun testCreates a test with the given name and test function. it() is an alias for test().
Parameters:
name(string): The name/description of the testfn(function): The test function to execute
Example:
test('my test name', () => {
// test code here
});
// or using it() - Mocha/Jest style
it('should do something', () => {
// test code here
});Groups related tests together (BDD style).
Parameters:
name(string): The suite namefn(function): Function containing tests and setup/teardown hooks
Example:
describe('user authentication', () => {
it('should login with valid credentials', () => {
// test code
});
it('should reject invalid credentials', () => {
// test code
});
});Skip a test (won't be executed).
test.skip('broken test', () => {
// This test will be skipped
});Run only this test (useful for debugging).
test.only('debug this test', () => {
// Only this test will run
});Mark a test as pending/TODO.
test.todo('implement this feature');Skip or isolate an entire test suite.
describe.skip('integration tests', () => {
// All tests in this suite will be skipped
});
describe.only('unit tests', () => {
// Only tests in this suite will run
});Set the default timeout for all tests in milliseconds. This is useful when tests need more time to complete (e.g., integration tests, API calls).
Parameters:
timeout(number): Timeout in milliseconds
Example:
import { test, setDefaultTimeout } from 'test-anywhere';
// Set default timeout to 60 seconds
setDefaultTimeout(60000);
test('long running operation', async () => {
// This test can take up to 60 seconds
await someSlowOperation();
});Note:
- For Bun: Uses the native
setDefaultTimeoutfrombun:test - For Node.js and Deno: Not supported natively. A warning will be logged, and you should use timeout options in individual test calls instead.
Asserts that a value is truthy.
Example:
assert.ok(true);
assert.ok(1 === 1, 'one should equal one');Asserts that two values are strictly equal (===).
Example:
assert.equal(2 + 2, 4);
assert.equal('hello', 'hello');Asserts that two values are deeply equal (compares object/array contents).
Example:
assert.deepEqual({ a: 1, b: 2 }, { a: 1, b: 2 });
assert.deepEqual([1, 2, 3], [1, 2, 3]);Asserts that a function throws an error when called.
Example:
assert.throws(() => {
throw new Error('oops');
});test-anywhere supports three assertion styles to provide maximum compatibility and ease of migration:
Traditional Node.js-style assertions (see above sections for details):
import { assert } from 'test-anywhere';
assert.ok(true);
assert.equal(1, 1);
assert.deepEqual([1, 2], [1, 2]);
assert.notEqual(1, 2);
assert.throws(() => {
throw new Error();
});
assert.match('hello', /ell/);
assert.includes([1, 2, 3], 2);Modern chainable API inspired by Jest and Bun:
import { expect } from 'test-anywhere';
expect(value).toBe(expected); // Strict equality (===)
expect(value).toEqual(expected); // Deep equality
expect(value).not.toBe(expected); // Negation
expect(value).toBeNull(); // null check
expect(value).toBeUndefined(); // undefined check
expect(value).toBeTruthy(); // Truthy check
expect(value).toBeFalsy(); // Falsy check
expect(array).toContain(item); // Array/string contains
expect(string).toMatch(/pattern/); // Regex match
expect(fn).toThrow(); // Function throwsComplete Example:
import { describe, it, expect } from 'test-anywhere';
describe('Calculator', () => {
it('should add numbers', () => {
expect(2 + 2).toBe(4);
expect(2 + 2).toEqual(4);
});
it('should handle arrays', () => {
expect([1, 2, 3]).toContain(2);
expect([1, 2, 3]).toEqual([1, 2, 3]);
});
it('should validate strings', () => {
expect('hello world').toMatch(/world/);
expect('hello').not.toBe('goodbye');
});
});Deno-inspired assertion functions from @std/assert:
import {
assertEquals,
assertNotEquals,
assertStrictEquals,
assertExists,
assertMatch,
assertArrayIncludes,
assertThrows,
assertRejects,
} from 'test-anywhere';
assertEquals(actual, expected); // Deep equality
assertNotEquals(actual, expected); // Not equal
assertStrictEquals(actual, expected); // Strict equality (===)
assertNotStrictEquals(actual, expected); // Strict inequality (!==)
assertExists(value); // Not null/undefined
assertMatch(string, /pattern/); // Regex match
assertArrayIncludes(arr, [items]); // Array includes items
assertThrows(() => {
throw new Error();
}); // Sync throws
await assertRejects(async () => {
throw new Error();
}); // Async rejectsComplete Example:
import {
test,
assertEquals,
assertMatch,
assertArrayIncludes,
} from 'test-anywhere';
test('user validation', () => {
const user = { name: 'Alice', email: '[email protected]' };
assertEquals(user.name, 'Alice');
assertMatch(user.email, /@/);
});
test('array operations', () => {
const numbers = [1, 2, 3, 4, 5];
assertArrayIncludes(numbers, [2, 4]);
assertEquals(numbers.length, 5);
});All three styles can be used together in the same project:
import { describe, it, assert, expect, assertEquals } from 'test-anywhere';
describe('Multi-style assertions', () => {
it('supports all styles', () => {
const value = 42;
// Node style
assert.equal(value, 42);
// Bun/Jest style
expect(value).toBe(42);
// Deno style
assertEquals(value, 42);
});
});Setup and teardown hooks for test initialization and cleanup.
Runs once before all tests. before() is a Mocha-style alias.
import { beforeAll, describe, it } from 'test-anywhere';
describe('database tests', () => {
beforeAll(() => {
// Connect to database once
});
it('should query data', () => {
// test code
});
});Runs before each test.
beforeEach(() => {
// Reset state before each test
});Runs after each test.
afterEach(() => {
// Clean up after each test
});Runs once after all tests. after() is a Mocha-style alias.
afterAll(() => {
// Disconnect from database
});Returns the current runtime name.
Returns: 'node', 'bun', or 'deno'
Example:
import { getRuntime } from 'test-anywhere';
console.log(`Running on ${getRuntime()}`); // e.g., "Running on node"Check out the examples directory for complete working examples:
- Node.js:
examples/node-example.test.js - Deno:
examples/deno-example.test.js - Bun:
examples/bun-example.test.js
test-anywhere automatically detects the JavaScript runtime (Bun, Deno, or Node.js) and delegates to the appropriate native testing framework:
- Bun → Uses
bun:test - Deno → Uses
Deno.test - Node.js → Uses
node:test
This means you get the full performance and features of each runtime's native testing implementation while maintaining a consistent API across all platforms.
- Node.js: 20.0.0 or higher (for native test runner support)
- Deno: 1.x or higher (native Deno.test support)
- Bun: Any recent version (native bun:test support)
Unlicense - Public Domain
Contributions are welcome! Please feel free to submit a Pull Request.