@dannysir/js-te
v0.9.1
Published
JavaScript test library
Downloads
668
Maintainers
Readme
js-te
A lightweight JavaScript test framework inspired by Jest.
📎 Latest Update — 0.9.1
Browser bundle drops the node:url import (0.9.1)
- The
@dannysir/js-te/browserbundle no longer imports thenode:urlbuiltin, so it loads correctly in browser/Web Worker bundlers (Vite, Turbopack, …). Node CLI behavior (--testLocation) is unchanged. See Browser usage.
Focus & skip modifiers (0.9.0)
.only/.skip/.todo— Jest/Vitest-style focus and skip modifiers fortestanddescribe. See Focusing & Skipping.
Location filter & JSON reporter (0.8.0)
--testLocation <path>:<line>runs a single test by file and line;--reporter jsonprints machine-readable results for IDE/CI.
See the full CHANGELOG for earlier releases.
Requirements
- Node.js >= 22.15.0 (version that introduced
module.registerHooks)
Installation
npm install --save-dev @dannysir/js-teQuick Start
1. Create a test file
Any *.test.js file is picked up and run automatically. No import needed — describe, test, expect, and friends are available globally.
// math.test.js
describe('[arithmetic]', () => {
test('addition', () => {
expect(1 + 2).toBe(3);
});
});2. Add a script to package.json
Both ESM and CommonJS projects are supported.
{
"scripts": {
"test": "js-te"
}
}3. Run
npm testExample output
Running a subset
js-te # all tests
js-te user # files whose path includes "user"
js-te -t "login" # tests whose full name includes "login"
js-te auth -t "token" # combine both
js-te --testLocation test/user.test.js:42 # single test by file and line
js-te --reporter json # JSON output for IDE/CI
js-te --help # helpSee the CLI reference for full options, matching rules, and exit codes.
--help output
Features
- Test writing —
test(),describe(),beforeEach(),test.each(),test.only,test.skip,test.todo,describe.only,describe.skip - Matchers —
toBe,toEqual,toThrow,toBeTruthy,toBeFalsy,toContain,toBeInstanceOf,toBeNull,toBeUndefined,toBeDefined,toHaveBeenCalled,toHaveBeenCalledWith,toHaveBeenCalledTimes,.notchaining - Mock Functions —
fn(),mockImplementation,mockReturnValue,mockReturnValueOnce,mockClear,mock.calls - Module Mocking —
mock(path, mockObj)(relative & absolute paths),clearAllMocks,unmock,isMocked - Module systems — ESM (
import) and CommonJS (require) - CLI — single
js-tecommand - Browser entry —
@dannysir/js-te/browserexposes the core API for browsers and Web Workers - TypeScript — bundled
.d.tsdeclarations for the main and/browserentries
Examples
Tests & Matchers
describe('calculator', () => {
test('addition', () => {
expect(2 + 3).toBe(5);
});
test('object equality', () => {
expect({ name: 'Alice' }).toEqual({ name: 'Alice' });
});
});Focusing & Skipping
describe('user', () => {
test.only('focused — only this runs in this file', () => {
expect(1 + 1).toBe(2);
});
test('skipped while .only exists in the same file', () => {
// not executed
});
test.skip('explicitly skipped', () => {
// not executed
});
test.todo('write reset-password test');
});
describe.only('whole group runs in focus mode', () => {
test('a', () => {});
test('b', () => {});
});
describe.skip('temporarily disabled suite', () => {
test('all tests inside are reported as skipped', () => {});
});.only is scoped to a single file: a file with at least one .only runs only the focused tests there, while other files are unaffected. The closest explicit modifier wins — test.skip inside describe.only stays skipped, and test.only inside describe.skip runs.
Module Mocking
// game.js
import { random } from './random.js';
export const play = () => random() * 10;
// game.test.js
import { play } from './game.js';
test('mock random function', () => {
const mocked = mock('./random.js', {
random: () => 0.5,
});
expect(play()).toBe(5);
// dynamically change return value via mock function methods
mocked.random.mockReturnValue(0.3);
expect(play()).toBe(3);
});⚠️ Mock function methods (
mockReturnValue, etc.) are only accessible through the object returned bymock(). See why in the API docs.
Browser usage
@dannysir/js-te/browser is a browser/Web Worker-safe entry that re-exports the pure test core. Reach for it when you run js-te test code directly in the browser (interactive demos, playgrounds) — the default @dannysir/js-te entry depends on the Node CLI runner and can't run there.
import { describe, test, expect, fn, beforeEach, testManager } from '@dannysir/js-te/browser';
describe('math', () => {
test('addition', () => {
expect(1 + 2).toBe(3);
});
});
await testManager.run();Exported: test (with test.each), describe, beforeEach, expect, fn, testManager.
Not exported: module mocking (mock, unmock, isMocked, clearAllMocks, mockStore) and the CLI runner (run) — these are Node-only and intentionally left out.
testManageris a module-level singleton. If you collect tests more than once on the same page, calltestManager.clearTests()between runs.
Node guard — importing this entry from a Node runtime throws immediately, pointing you to the main @dannysir/js-te entry (or the js-te CLI):
@dannysir/js-te/browser cannot be used in a Node.js runtime.
It is designed for browsers and Web Workers only.TypeScript — type declarations ship with the package (types/browser.d.ts), so the entry is fully typed with no extra setup.
Test File Discovery
The following files are found and run automatically:
*.test.jsfiles anywhere in the project- All
.jsfiles inside atest/folder
project/
├── src/
│ ├── utils.js
│ └── utils.test.js ✅
├── test/
│ ├── integration.js ✅
│ └── e2e.js ✅
└── calculator.test.js ✅Documentation
- API Reference — full usage for
test,expect,mock,fn,beforeEach,test.each - CLI Reference — command-line options, matching rules, and exit codes
- Loader hook-based in-memory transform — 0.5.0 internals (Korean)
- CHANGELOG — version history
Links
Motivation
Built out of curiosity about how JavaScript test frameworks like Jest work under the hood.
License
ISC
