New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

micro-should

Package Overview
Dependencies
Maintainers
0
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

micro-should - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

index.ts

84

index.d.ts

@@ -1,11 +0,73 @@

type ShouldRunner = {
(message: string, test: () => void | Promise<void>): void;
only(message: string, test: () => void | Promise<void>): void;
skip(message: string, test: () => void | Promise<void>): void;
run(): void;
};
declare const should: ShouldRunner;
declare const it: ShouldRunner;
export function describe(prefix: string, fn: () => void): void;
export { should, it };
export default should;
/*! micro-should - MIT License (c) 2019 Paul Miller (paulmillr.com) */
/**
* Micro testing framework with familiar syntax for browsers, node and others.
* Supports fast mode (parallel), quiet mode (dot reporter), tree structures, CLI self-run auto-detection.
*/
export interface StackItem {
message: string;
test?: () => Promise<any> | any;
skip?: boolean;
only?: boolean;
prefix?: string;
childPrefix?: string;
path?: StackItem[];
beforeEach?: () => Promise<void> | void;
afterEach?: () => Promise<void> | void;
children: StackItem[];
}
export interface Options {
PRINT_TREE: boolean;
PRINT_MULTILINE: boolean;
STOP_AT_ERROR: boolean;
MSHOULD_QUIET: boolean;
}
export interface DescribeFunction {
(message: string, testFunctions: () => Promise<any> | any): void;
skip: (message: string, test: () => Promise<any> | any) => void;
}
export interface TestFunction {
(message: string, test: () => Promise<any> | any): void;
/**
* Registers test for "only" queue. When the queue is not empty,
* it would ignore all other tests. Is limited to just one registered test.
*/
only: (message: string, test: () => Promise<any> | any) => void;
/** Registers test, but skips it while running. Can be used instead of commenting out the code. */
skip: (message: string, test: () => Promise<any> | any) => void;
/**
* Runs all registered tests.
* After run, allows to run new tests without duplication: old test queue is cleaned up.
* @param forceSequential - when `true`, disables automatic parallelization even when MSHOULD_FAST=1.
* @returns resolved promise, after all tests have finished
*/
run: (forceSequential?: boolean) => Promise<number>;
/**
* Executes .run() when passed argument is equal to CLI-passed file name.
* Consider a project with 3 test files: a.test.js, b.test.js, all.js.
* all.js imports a.test.js and b.test.js.
* User runs node a.test.js; then node all.js;
* Writing `it.run()` everywhere would fail, because it would try to run same tests twice.
* However, `it.runWhen(import.meta.url)` would succeed, because it detects whether
* current file is launched from CLI and not imported.
* @example
* it.runWhen(import.meta.url)
*/
runWhen: (importMetaUrl: string) => Promise<number | undefined>;
/** Parallel version, using node:cluster. Auto-selected when env var MSHOULD_FAST=1 is set. */
runParallel: () => Promise<number>;
opts: Options;
}
export type EmptyFn = () => Promise<void> | void;
declare const describe: DescribeFunction;
declare function beforeEach(fn: EmptyFn): void;
declare function afterEach(fn: EmptyFn): void;
/**
* Registers test for future running.
* Would not auto-run, needs `it.run()` to be called at some point.
* See {@link TestFunction} for methods.
* @param message test title
* @param test function, may be async
*/
declare const it: TestFunction;
export { it, describe, beforeEach, afterEach, it as should };
export default it;

527

index.js

@@ -1,4 +0,28 @@

const red = '\x1b[31m';
const green = '\x1b[32m';
const reset = '\x1b[0m';
/*! micro-should - MIT License (c) 2019 Paul Miller (paulmillr.com) */
/**
* Micro testing framework with familiar syntax for browsers, node and others.
* Supports fast mode (parallel), quiet mode (dot reporter), tree structures, CLI self-run auto-detection.
*/
const stack = [{ message: '', children: [] }];
const errorLog = [];
let onlyStack;
let running = false;
const isCli = 'process' in globalThis;
const opts = {
PRINT_TREE: true,
PRINT_MULTILINE: true,
STOP_AT_ERROR: true,
MSHOULD_QUIET: isCli && process.env.MSHOULD_QUIET,
};
function isQuiet() {
return opts.MSHOULD_QUIET;
}
// String formatting utils
const _c = String.fromCharCode(27); // x1b, control code for terminal colors
const c = {
// colors
red: _c + '[31m',
green: _c + '[32m',
reset: _c + '[0m',
};
// We can write 'pending' test name and then overwrite it with actual result by using ${up}.

@@ -8,4 +32,3 @@ // However, if test prints something to STDOUT, last line would get removed.

// But we already use node modules for parallel cases, so maybe worth investigating.
const up = '\x1b[A';
// const up = _c + '[A';
const LEAF_N = '├─';

@@ -20,165 +43,355 @@ const LEAF_E = '│ ';

// const LEAF_S = ' ';
async function run(info, printTree = false, multiLine = false, stopAtError = true) {
if (!printTree && multiLine) console.log();
let output = info.message;
if (printTree && info.only) {
for (const parent of info.path) console.log(`${parent.prefix}${parent.message}`);
}
const path = `${info.path.map((i) => i.message).join('/')}/`;
// Skip is always single-line
if (multiLine && !info.skip) {
console.log(printTree ? `${info.prefix}${output}: ☆` : `☆ ${path}${output}:`);
} else if (info.skip) {
console.log(printTree ? `${info.prefix}${output} (skip)` : `☆ ${path}${output} (skip)`);
return true;
}
const printResult = (color, symbol) =>
console.log(
printTree
? `${info.childPrefix}${color}${output}: ${symbol}${reset}`
: `${color}${symbol} ${path}${output}${reset}`
);
try {
let result = await info.test();
printResult(green, '✓');
return true;
} catch (error) {
printResult(red, '☓');
if (stopAtError) throw error;
else console.log(`${red}ERROR:${reset}`, error);
}
// Colorize string for terminal.
function color(colorName, title) {
return isCli ? `${c[colorName]}${title}${c.reset}` : title.toString();
}
async function runParallel(tasks, cb) {
// node.js / common.js-only
const os = require('os');
const cluster = require('cluster');
tasks = tasks.filter((i) => !!i.test); // Filter describe elements
const clusterId = cluster && cluster.worker ? `W${cluster.worker.id}` : 'M';
let WORKERS = +process.env.WORKERS || os.cpus().length;
// Workers
if (!cluster.isMaster) {
process.on('error', (err) => console.log('Error (child crashed?):', err));
let tasksDone = 0;
for (let i = 0; i < tasks.length; i++) {
if (cluster.worker.id - 1 !== i % WORKERS) continue;
await cb(tasks[i], false, false);
tasksDone++;
function log(...args) {
if (isQuiet())
return logQuiet(false);
// @ts-ignore
console.log(...args);
}
function logQuiet(fail = false) {
if (fail) {
process.stderr.write(color('red', '!'));
}
process.send({ name: 'parallelTests', worker: clusterId, tasksDone });
process.exit();
}
// Master
return await new Promise((resolve, reject) => {
console.log(`Starting parallel tests with ${WORKERS} workers and ${tasks.length} tasks`);
cluster.on('exit', (worker, code) => {
if (!code) return;
console.error(
`${red}Worker W${worker.id} (pid: ${worker.process.pid}) died with code: ${code}${reset}`
);
reject(new Error('Test worker died in agony'));
});
let tasksDone = 0;
let workersDone = 0;
for (let i = 0; i < WORKERS; i++) {
const worker = cluster.fork();
worker.on('error', (err) => reject(err));
worker.on('message', (msg) => {
if (!msg || msg.name !== 'parallelTests') return;
workersDone++;
tasksDone += msg.tasksDone;
if (workersDone === WORKERS) {
if (tasksDone !== tasks.length) reject(new Error('Not all tasks finished.'));
else resolve(tasksDone);
}
});
else {
process.stdout.write('.');
}
});
}
const stack = [{ children: [] }];
const stackTop = () => stack[stack.length - 1];
const stackPop = () => stack.pop();
const stackClean = () => {
stack.splice(0, stack.length);
stack.push({ children: [] });
};
const stackAdd = (info) => {
const c = { ...info, children: [] };
stackTop().children.push(c);
stack.push(c);
};
function addToErrorLog(title = '', error) {
errorLog.push(`${title} ${error?.stack ? error.stack : error}`);
// @ts-ignore
if (!isQuiet())
console.error(error); // loud = show error now. quiet = show in the end
}
function formatPrefix(depth, prefix, isLast) {
if (depth === 0) return { prefix: '', childPrefix: '' };
return {
prefix: `${prefix}${isLast ? LEAF_L : LEAF_N}`,
childPrefix: `${prefix}${isLast ? LEAF_S : LEAF_E}`,
};
if (depth === 0)
return { prefix: '', childPrefix: '' };
return {
prefix: `${prefix}${isLast ? LEAF_L : LEAF_N}`,
childPrefix: `${prefix}${isLast ? LEAF_S : LEAF_E}`,
};
}
function tdiff(start) {
const sec = Math.round((Date.now() - start) / 1000);
return sec < 60 ? `${sec} sec` : `${Math.floor(sec / 60)} min ${sec % 60} sec`;
}
async function runTest(info, printTree = false, multiLine = false, stopAtError = true) {
if (!printTree && multiLine)
log();
let title = info.message;
if (typeof info.test !== 'function')
throw new Error('internal test error: invalid info.test');
let messages = [];
let onlyLogsToPrint = [];
let beforeEachFns = [];
let afterEachFns = []; // will be reversed
for (const parent of info.path) {
messages.push(parent.message);
if (printTree && info.only)
onlyLogsToPrint.push(`${parent.prefix}${parent.message}`);
if (parent.beforeEach)
beforeEachFns.push(parent.beforeEach);
if (parent.afterEach)
afterEachFns.push(parent.afterEach);
}
afterEachFns.reverse();
if (onlyLogsToPrint.length)
onlyLogsToPrint.forEach((l) => log(l));
const path = `${messages.join('/')}/`;
const full = path + title;
// Skip is always single-line
if (multiLine && !info.skip) {
log(printTree ? `${info.prefix}${title}: ☆` : `☆ ${full}:`);
}
else if (info.skip) {
log(printTree ? `${info.prefix}${title} (skip)` : `☆ ${full} (skip)`);
return true;
}
// variables influencing state / print output:
// fail = true | false
// quiet = true | false
// printTree = true | false (true when fast mode)
// stopAtError = true | false
function logTaskDone(fail = false, suffix = '') {
const symbol = fail ? '☓' : '✓';
const clr = fail ? 'red' : 'green';
const title_ = suffix ? [title, suffix].join('/') : title;
const full_ = suffix ? [full, suffix].join('/') : full;
log(printTree
? `${info.childPrefix}` + color(clr, `${title_}: ${symbol}`)
: color(clr, `${symbol} ${full_}`));
}
// Emit
function logErrorStack(suffix) {
if (isQuiet()) {
// when quiet, either stop & log trace; or log !
if (stopAtError) {
// stop, log whole path and trace
console.error();
console.error(color('red', `☓ ${full}/${suffix}`));
}
else {
// log !, continue
logQuiet(true);
}
}
else {
// when loud, log (maybe formatted) tree structure
logTaskDone(true, suffix);
}
}
// Run beforeEach hooks from parent contexts
for (const beforeFn of beforeEachFns) {
try {
await beforeFn();
}
catch (cause) {
logErrorStack('beforeEach');
// @ts-ignore
if (stopAtError)
throw cause;
else
addToErrorLog(`${full}/beforeEach`, cause);
return false;
}
}
// Run test task
try {
// possible to do let result = ... in the future to save test outputs
await info.test();
}
catch (cause) {
logErrorStack('');
// @ts-ignore
if (stopAtError)
throw cause;
else
addToErrorLog(`${full}`, cause);
return false;
}
// Run afterEach hooks from parent contexts (in reverse order)
for (const afterFn of afterEachFns) {
try {
await afterFn();
}
catch (cause) {
logErrorStack('afterEach');
// @ts-ignore
if (stopAtError)
throw cause;
else
addToErrorLog(`${full}/afterEach`, cause);
return false;
}
}
logTaskDone();
return true;
}
function stackTop() {
return stack[stack.length - 1];
}
function stackPop() {
return stack.pop();
}
function stackAdd(info) {
const c = { ...info, children: [] };
stackTop().children.push(c);
stack.push(c);
}
function stackFlatten(elm) {
const out = [];
const walk = (elm, depth = 0, isLast = false, prevPrefix = '', path = []) => {
const { prefix, childPrefix } = formatPrefix(depth, prevPrefix, isLast);
const newElm = { ...elm, prefix, childPrefix, path };
out.push(newElm);
path = path.concat([newElm]); // Save prefixes so we can print path in 'only' case
for (let i = 0; i < elm.children.length; i++)
walk(elm.children[i], depth + 1, i === elm.children.length - 1, childPrefix, path);
};
// Skip root
for (const child of elm.children) walk(child);
return out;
const out = [];
const walk = (elm, depth = 0, isLast = false, prevPrefix = '', path = []) => {
const { prefix, childPrefix } = formatPrefix(depth, prevPrefix, isLast);
const newElm = { ...elm, prefix, childPrefix, path };
out.push(newElm);
path = path.concat([newElm]); // Save prefixes so we can print path in 'only' case
const chl = elm.children;
for (let i = 0; i < chl.length; i++)
walk(chl[i], depth + 1, i === chl.length - 1, childPrefix, path);
};
// Skip root
for (const child of elm.children)
walk(child);
return out;
}
function describe(message, fn) {
stackAdd({ message });
fn(); // Run function in the context of current stack path
stackPop();
const describe = (message, fn) => {
stackAdd({ message });
fn(); // Run function in the context of current stack path
stackPop();
};
function describeSkip(message, _fn) {
stackAdd({ message, skip: true });
// fn();
stackPop();
}
function enqueue(info) {
stackAdd(info);
stackPop(); // remove from stack since there are no children
describe.skip = describeSkip;
function beforeEach(fn) {
stackTop().beforeEach = fn;
}
let only;
const should = (message, test) => enqueue({ message, test });
should.stack = stack;
should.queue = () => stackFlatten(stack[0]);
should.consumeQueue = () => {
let items = should.queue().slice();
if (only) items = items.filter((i) => i.test === only.test);
stackClean(); // Remove all elements, so next call won't process them twice
only = undefined;
return items;
};
should.only = (message, test) => enqueue((only = { message, test, only: true }));
should.skip = (message, test) => enqueue({ message, test, skip: true });
should.PRINT_TREE = true;
should.PRINT_MULTILINE = true;
should.STOP_AT_ERROR = true;
should.run = () => {
const items = should.consumeQueue();
// Return promise, so we can wait before section is complete without breaking anything
return (async () => {
for (const test of items) {
if (should.PRINT_TREE && !test.test) console.log(`${test.prefix}${test.message}`);
if (!test.test) continue;
await run(test, should.PRINT_TREE, should.PRINT_MULTILINE, should.STOP_AT_ERROR);
function afterEach(fn) {
stackTop().afterEach = fn;
}
function register(info) {
stackAdd(info);
stackPop(); // remove from stack since there are no children
}
function cloneAndReset() {
let items = stackFlatten(stack[0]).slice();
if (onlyStack)
items = items.filter((i) => i.test === onlyStack.test);
stack.splice(0, stack.length);
stack.push({ message: '', children: [] });
onlyStack = undefined;
return items;
}
// 123 tests (+quiet +fast-x8) started...
function begin(total, workers) {
const features = [isQuiet() ? '+quiet' : '', workers ? `+fast-x${workers}` : ''].filter((a) => a);
const modes = features.length ? `(${features.join(' ')}) ` : '';
// No need to log stats when tests fit on one screen
if (total > 32)
console.log(`${color('green', total.toString())} tests ${modes}started...`);
}
function finalize(total, startTime) {
console.log();
if (isQuiet())
console.log();
const totalFailed = errorLog.length;
if (totalFailed) {
console.error();
console.error(`${color('red', totalFailed)} tests failed`);
if (isQuiet()) {
errorLog.forEach((err) => console.error(err));
}
}
})();
};
else {
console.log(`${color('green', total)} tests passed in ${tdiff(startTime)}`);
}
}
async function runTests(forceSequential = false) {
if (running)
throw new Error('should.run() has already been called, wait for end');
if (!forceSequential && isCli && !!process?.env?.MSHOULD_FAST)
return runTestsInParallel();
running = true;
const tasks = cloneAndReset();
const total = tasks.filter((i) => !!i.test).length;
begin(total);
const startTime = Date.now();
for (const test of tasks) {
if (opts.PRINT_TREE && !test.test)
log(`${test.prefix}${test.message}`);
if (!test.test)
continue;
await runTest(test, opts.PRINT_TREE, opts.PRINT_MULTILINE, opts.STOP_AT_ERROR);
}
finalize(total, startTime);
running = false;
return total;
}
async function runTestsWhen(importMetaUrl) {
if (!isCli)
throw new Error('cannot be used outside of CLI');
// @ts-ignore
const url = await import('node:url');
return importMetaUrl === url.pathToFileURL(process.argv[1]).href ? runTests() : undefined;
}
// Doesn't support tree and multiline
should.runParallel = () =>
runParallel(should.consumeQueue(), (info) => run(info, false, false, should.STOP_AT_ERROR));
module.exports = { should, it: should, describe, default: should };
// TODO: support beforeEach, afterEach
async function runTestsInParallel() {
if (!isCli)
throw new Error('must run in cli');
if ('deno' in process.versions)
return runTests(true);
const tasks = cloneAndReset().filter((i) => !!i.test); // Filter describe elements
const total = tasks.length;
const startTime = Date.now();
const runTestPar = (info) => runTest(info, false, false, opts.STOP_AT_ERROR);
let cluster, err;
let totalW = Number.parseInt(process.env.MSHOULD_FAST, 10);
if (totalW === 1)
totalW = 0;
try {
// @ts-ignore
cluster = (await import('node:cluster')).default;
// @ts-ignore
if (!totalW)
totalW = (await import('node:os')).cpus().length;
}
catch (error) {
err = error;
}
if (!cluster || !totalW)
throw new Error('parallel tests are not supported: ' + err);
// the code is ran in workers
if (!cluster.isPrimary) {
process.on('error', (err) => console.log('internal error:', 'child crashed?', err));
let tasksDone = 0;
const id = cluster.worker.id;
const strId = 'W' + id;
for (let i = 0; i < tasks.length; i++) {
if (i % totalW !== id - 1)
continue;
await runTestPar(tasks[i]);
tasksDone++;
}
process.send({ name: 'parallelTests', worker: strId, tasksDone, errorLog });
process.exit();
}
// the code is ran in primary process
return await new Promise((resolve, reject) => {
begin(total, totalW);
console.log();
const workers = [];
let tasksDone = 0;
let workersDone = 0;
cluster.on('exit', (worker, code) => {
if (!code)
return;
const msg = `Worker W${worker.id} (pid: ${worker.process.pid}) crashed with code: ${code}`;
// @ts-ignore
console.error(color('red', msg));
workers.forEach((w) => w.kill()); // Shutdown other workers
reject(new Error(msg));
});
for (let i = 0; i < totalW; i++) {
const worker = cluster.fork();
workers.push(worker);
worker.on('error', (err) => reject(err));
worker.on('message', (msg) => {
if (!msg || msg.name !== 'parallelTests')
return;
workersDone++;
tasksDone += msg.tasksDone;
msg.errorLog.forEach((item) => errorLog.push(item));
if (workersDone === totalW) {
if (tasksDone === total) {
finalize(total, startTime);
resolve(tasksDone);
}
else {
reject(new Error('internal error: not all tasks have been completed'));
}
}
});
}
});
}
/**
* Registers test for future running.
* Would not auto-run, needs `it.run()` to be called at some point.
* See {@link TestFunction} for methods.
* @param message test title
* @param test function, may be async
*/
const it = (message, test) => register({ message, test, children: [] });
it.only = (message, test) => register((onlyStack = { message, test, children: [], only: true }));
it.skip = (message, test) => register({ message, test, children: [], skip: true });
it.run = runTests;
it.runWhen = runTestsWhen;
it.runParallel = runTestsInParallel;
it.opts = opts;
export { it, describe, beforeEach, afterEach, it as should };
export default it;
{
"name": "micro-should",
"version": "0.4.0",
"description": "Simplest zero-dependency testing framework, a drop-in replacement for Mocha",
"version": "0.5.0",
"description": "Micro testing framework with familiar syntax, multi-env ESM support & parallel execution",
"type": "module",
"module": "index.js",
"main": "index.js",
"files": [
"index.ts",
"index.js",

@@ -11,3 +14,6 @@ "index.d.ts"

"scripts": {
"test": "node tests/example.test.js && node tests/basic.test.js && node tests/parallel.test.js"
"build": "tsc",
"lint": "npx prettier index.ts test",
"format": "npx prettier --write index.ts test",
"test": "node test/basic.test.js; node test/example.test.js; node test/parallel.test.js"
},

@@ -31,3 +37,8 @@ "homepage": "https://github.com/paulmillr/micro-should",

"karma"
]
}
],
"devDependencies": {
"@paulmillr/jsbt": "0.2.1",
"prettier": "3.3.2",
"typescript": "5.5.2"
}
}
# micro-should
Simplest zero-dependency testing framework, a drop-in replacement for Mocha.
Micro testing framework with familiar syntax, multi-env ESM support & parallel execution.
Supports async cases. Works with any assertion library.
Used in [noble cryptography](https://paulmillr.com/noble) and [many other packages](https://github.com/paulmillr/micro-should/network/dependents).
* `should(title, case)` (or `it(title, case)`) syntax
## Usage
> npm install micro-should
> jsr add jsr:@paulmillr/micro-should
Basic methods:
* `should(title, case)` or `it(title, case)` syntax to register a test function
* `should.run()` or `it.run()` must always be executed in the end
ENV variables:
* `MSHOULD_FAST=1` enables parallel execution in node.js and Bun. Values >1 will set worker count.
* `MSHOULD_QUIET=1` enables "quiet" dot reporter
Additional methods:
* `describe(prefix, cases)` for nested execution
* `beforeEacn(fn)` to execute code before a function in `describe` block
* `afterEach` to execute code after a function in `describe` block
* `should.only(title, case)` allows to limit tests to only one case
* `should.skip(title, case)` allows to skip functions instead of commenting them out
* `describe(prefix, cases)` for nested execution
* `should.run()` must always be executed in the end
* `should.runParallel()` for CPU-intensive tasks, would ramp up threads equal to CPU count
* `describe.skip(prefix, cases)` to skip describe()-s
* `should.runWhen(import.meta.url)` helper ensures CLI tests are not `run` twice if you're using many test files
* Executes .run() when passed argument is equal to CLI-passed file name.
Consider a project with 3 test files: a.test.js, b.test.js, all.js. all.js imports a.test.js and b.test.js.
User runs node a.test.js; then node all.js;
* Writing `it.run()` everywhere would fail, because it would try to run same tests twice.
* However, `it.runWhen(import.meta.url)` would succeed, because it detects whether
current file is launched from CLI and not imported.
> npm install micro-should
![](https://raw.githubusercontent.com/paulmillr/micro-should/e60028e947f3158c46314ef105b51b2a2948c025/screenshot.png)
## Usage
### Basic
To run the example in parallel / quiet setting, save it as a.test.js:
MSHOULD_FAST=1 MSHOULD_QUIET=1 node a.test.js
```js
const { should } = require('micro-should');
const assert = require('assert'); // You can use any assertion library (e.g. Chai or Expect.js), example uses built-in nodejs
import { should } from 'micro-should';
import * as assert from 'node:assert'; // examples with node:assert
// you can use any assertion library, e.g. Chai or Expect.js

@@ -35,17 +63,12 @@ should('add two numbers together', () => {

should('produce correct promise result', async () => {
const fs = require('fs').promises;
const fs = await import('node:fs/promises');
const data = await fs.readFile('README.md', 'utf-8');
assert.ok(data.includes('Minimal testing'));
});
should.run();
```
// should.only("execute only one test", () => {
// assert.ok(true);
// });
### Nested
// should.skip("disable one test by using skip", () => {
// assert.ok(false); // would not execute
// })
// Nested
const { describe } = require('micro-should');
```js
describe('during any time of day', () => {

@@ -57,14 +80,49 @@ describe('without hesitation', () => {

should('multiply three numbers together', () => {
assert.equal(3 * 3 * 3, 27);
should.skip("disable one test by using skip", () => {
assert.ok(false); // would not execute
});
// should.only("execute only one test", () => {
// assert.ok(true);
// });
});
});
// Execute this at the end of a file.
should.run();
```
### Auto-run with cli, do not run when imported
```js
// a.test.js
import { should } from 'micro-should';
should('2 + 2', () => {
if (2 + 2 !== 4) throw new Error('invalid');
});
should.runWhen(import.meta.url);
```
```js
// b.test.js
import * from './a.test.js';
should.runWhen(import.meta.url);
```
### Options
Options which can be set via command line, as environment variables:
* `MSHOULD_FAST=1` enables parallel execution in node.js and Bun. Values >1 will set worker count.
* `MSHOULD_QUIET=1` enables "quiet" dot reporter
Options which can be set via code:
```js
import { should } from 'micro-should';
should.opts.STOP_AT_ERROR = false; // default=true
should.opts.MSHOULD_QUIET = true; // same as env var
```
## License
MIT (c) Paul Miller (https://paulmillr.com), see LICENSE file.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc