esm-test-parser
v1.0.0
Published
A library for converting esm modules in to tests
Maintainers
Readme
Esm test parser
This library is not a test runner. It's a utility for creating test runner plugins.
esm-test-parser is a library for converting ESM modules, classes, and objects into a structured collection of tests.
It analyzes a given JavaScript module/object and returns an array of tests which can then be added to test runners that support dynamic test creation.
Features
Parameterized Tests: Define multiple test cases.
Execution Filtering: Built-in support for
onlyto isolate specific tests.Nested Test Context Support: Tracks the full hierarchy of test groups, allowing you to provide a specific context (
this) for each level of nesting viatestContextLookup.Flexible Identification: Detects tests from functions, objects, and class instances.
Built-in Hooks: Ability to specify nested custom hooks like
beforeEach,afterEach,beforeAll, andafterAll.Nested Test Objects Specific
- Hierarchical Grouping: Organise tests into logical suites using nested object structures.
- Sequential Filtering: Use
only: true,only: number, oronly: '*'to control execution flow within objects. - Implicit Titles: Object keys automatically serve as test and group titles.
- Parameterized Tests: Use arrays of arguments to define multiple cases for a single test key.
- Metadata via Properties: Use
[test.title],[test.cases], and[only]directly on object and function members to override titles or define filtering and cases.
Pure Test Functions Specific
- Metadata via Properties: Attach
[test.title],[test.cases], and[only]directly to function objects. - Automatic Discovery: All exported functions (except reserved hooks) are treated as tests.
- Reserved Hooks: Export functions named
beforeEach,afterEach,beforeAll, orafterAllfor setup/teardown.
- Metadata via Properties: Attach
Test Classes Specific
- Declarative Testing: Use classes as suites and methods as tests.
- Rich Metadata Decorators: Use
@testCase,@testOnly, and@testTitlefor clean, expressive definitions. - Instance Context: Tests run within the class instance context, allowing for shared state via
this. - Flexible Filtering: Apply
@testOnlyto individual methods or the entire class.
Installation
npm install esm-test-parser --save-devAdvanced Examples
Nested Object Tests
The most flexible way to define tests is using nested objects. This allows for clear grouping and hierarchy.
// Parse a module
import * as MyTests from './test-module.js' // see some examples of the test-module.js below
const tests = extractTestsFromModule(MyTests);// test-module.js
import { extractTestsFromModule } from 'esm-test-parser';
// 1. Define your tests using objects
export const MyMathTests = {
'Basic Operations': {
'Addition': {
'1 + 1 = 2': () => { /* assert logic */ },
'2 + 2 = 4': () => { /* assert logic */ }
},
'Multiplication': {
'3 * 3 = 9': () => { /* assert logic */ }
},
// Optional: Run test(s) in isolation.
// true: run the first preceding test, number: run [number]] preceding tests, '*': run all preceding tests.
only: true, // can also be a number (e.g., 2) or '*'
// Parameterized tests in objects
'Calculate Square Root ($i)': [
[9, 3],
[16, 4],
function(input, expected) {
// assert(Math.sqrt(input) === expected)
}
],
// Optional: Built-in hooks
beforeEach: () => { /* setup */ },
afterEach: () => { /* teardown */ }
};Classes with Decorators
// test-module.js
import { testCase, testTitle, testOnly } from 'esm-test-parser';
@testTitle('Math Suite')
export class MathTests {
// Optional: Test cases
@testCase(1, 1, 2)
@testCase(2, 3, 5)
['add $1 + $2 = $3'](a, b, expected) {
// test logic
}
// Optional: Run test methods in isolation.
@testOnly(true | number | '*')
onlyThisTest() {
// only this test will run
}
}Functional Tests
Pure functions can be used as tests. You can attach metadata using the test and only keywords.
// test-module.js
import { only, test } from 'esm-test-parser';
// A simple test function
export function basicTest() { /* ... */ }
// Optional: Run test functions in isolation.
// true: run preceding test, number: run N preceding tests, '*': run all preceding tests.
customTest[only] = true; // can also be a number or '*'
// Optional: Set a custom title
customTest[test.title] = "This is a custom title";
export function customTest() { /* ... */ }
// Optional: Parameterized functional tests
parameterizedTest[test.title] = "Testing $1";
parameterizedTest[test.cases] = [
['case A'],
['case B']
];
export function parameterizedTest(value) {
// Runs twice with 'case A' and 'case B'
}
// Hooks are exported as functions
export function beforeAll() { /* ... */ }API
extractTestsFromModule(moduleToParse, options)
Extracts tests from a given module based on the provided options.
moduleToParse: The JavaScript module or object containing test definitions.options: ATestParserOptionsobject.builtInFunctions: Array of function names to treat as hooks.testContextLookup: Function to resolvethiscontext for tests.sort: Sorting method ('all','groupsOnly','testsOnly','none').parserFlags: Flags to enable/disable literal property detection (e.g.,allowLiteralOnly).
Returns a TestCollection (an array of Test objects).
Documentation
For more detailed guides, see:


