toofast
Version:
The Node.js performance testing tool with unit-test-like API.
86 lines (85 loc) • 3.43 kB
JavaScript
import fs from 'fs';
import path from 'path';
import glob from 'fast-glob';
import * as d from 'doubter';
import globToRegExp from 'glob-to-regexp';
import { parseArgs } from 'argcat';
const CONFIG_FILES = ['.toofastrc', 'toofast.json', 'toofast.config.json'];
const INCLUDE_GLOBS = ['**/*.perf.{js,mjs,ts,mts}'];
/**
* Shape of CLI arguments.
*/
const processArgsShape = d
.object({
// A config file path
config: d.string().coerce().optional(),
// An array of test suite file globs
include: d.array(d.string()).optional(),
// An array of setup file globs
setup: d.array(d.string()).optional(),
// An array of test name globs to enable
'': d.array(d.string()),
// CLI arguments override test options from config file
measureTimeout: d.number().int().positive().coerce().optional(),
targetRme: d.number().gt(0).lt(1).coerce().optional(),
warmupIterationCount: d.number().int().positive().coerce().optional(),
batchIterationCount: d.number().int().positive().coerce().optional(),
batchTimeout: d.number().int().positive().coerce().optional(),
batchIntermissionTimeout: d.number().int().positive().coerce().optional(),
})
// Don't allow unknown arguments
.exact();
/**
* Shape of global test options.
*/
const testOptionsShape = d
.object({
measureTimeout: d.number().int().positive(),
targetRme: d.number().gt(0).lt(1),
warmupIterationCount: d.number().int().positive(),
batchIterationCount: d.number().int().positive(),
batchTimeout: d.number().int().positive(),
batchIntermissionTimeout: d.number().int().positive(),
})
.partial()
.strip();
/**
* Shape of a config read from a file.
*/
const configShape = d
.object({
testOptions: testOptionsShape,
// An array of test suite file globs
include: d.array(d.string()),
// An array of setup file globs
setup: d.array(d.string()),
})
.partial();
/**
* Parses CLI arguments and loads config from a file if needed.
*/
export function resolveConfig(argv = process.argv, cwd = process.cwd()) {
var _a, _b, _c, _d;
const args = processArgsShape.parse(parseArgs(argv.slice(2)));
const configFile = args.config || CONFIG_FILES.find(file => fs.existsSync(path.resolve(cwd, file)));
const config = configFile === undefined
? {}
: configShape.parse(JSON.parse(fs.readFileSync(path.resolve(cwd, configFile), 'utf8')));
const baseDir = configFile === undefined ? cwd : path.dirname(path.resolve(cwd, configFile));
const setupFiles = ((_a = args.setup) === null || _a === void 0 ? void 0 : _a.flatMap(src => resolveFiles(src, cwd))) ||
((_b = config.setup) === null || _b === void 0 ? void 0 : _b.flatMap(src => resolveFiles(src, baseDir))) ||
[];
const testFiles = ((_c = args.include) === null || _c === void 0 ? void 0 : _c.flatMap(src => resolveFiles(src, cwd))) ||
((_d = config.include) === null || _d === void 0 ? void 0 : _d.flatMap(src => resolveFiles(src, baseDir))) ||
INCLUDE_GLOBS.flatMap(src => resolveFiles(src, cwd));
return {
baseDir,
setupFiles,
testFiles,
testRegExps: args[''].map(src => globToRegExp(src, { flags: 'i' })),
testOptions: Object.assign(Object.assign({}, config.testOptions), testOptionsShape.parse(args)),
};
}
function resolveFiles(src, cwd) {
return glob.sync(src, { absolute: true, cwd });
}