@japa/runner
Version:
A simple yet powerful testing framework for Node.js
235 lines (231 loc) • 6.16 kB
JavaScript
import {
CliParser,
ConfigManager,
GlobalHooks,
Planner,
createTest,
createTestGroup
} from "../chunk-Y57JXJ7G.js";
import "../chunk-U3BSXCEH.js";
import {
Emitter,
Runner,
Suite
} from "../chunk-PCBL2VZP.js";
import "../chunk-2KG3PWR4.js";
// factories/runner.ts
import { fileURLToPath } from "url";
var RunnerFactory = class {
#emitter = new Emitter();
#config;
#cliArgs;
#file = fileURLToPath(import.meta.url);
#bail = false;
get #refiner() {
return this.#config.refiner;
}
/**
* Registers plugins
*/
async #registerPlugins(runner2) {
for (let plugin of this.#config.plugins) {
await plugin({
config: this.#config,
runner: runner2,
emitter: this.#emitter,
cliArgs: this.#cliArgs
});
}
}
/**
* Configure runner
*/
configure(config, argv) {
this.#cliArgs = new CliParser().parse(argv || []);
this.#config = new ConfigManager(config, this.#cliArgs).hydrate();
return this;
}
/**
* Define a custom emitter instance to use
*/
useEmitter(emitter) {
this.#emitter = emitter;
return this;
}
/**
* Run a test using the runner
*/
async runTest(title, callback) {
return this.runSuites((emitter, refiner, file) => {
const defaultSuite = new Suite("default", emitter, refiner);
createTest(title, emitter, refiner, {
suite: defaultSuite,
file
}).run(callback);
return [defaultSuite];
});
}
/**
* Enable/disable the bail mode
*/
bail(toggle = true) {
this.#bail = toggle;
return this;
}
/**
* Run dummy tests. You might use
*/
async runSuites(suites) {
const runner2 = new Runner(this.#emitter);
runner2.bail(this.#bail);
await this.#registerPlugins(runner2);
const { config, reporters, refinerFilters } = await new Planner(this.#config).plan();
const globalHooks = new GlobalHooks();
globalHooks.apply(config);
reporters.forEach((reporter) => {
runner2.registerReporter(reporter);
});
refinerFilters.forEach((filter) => {
config.refiner.add(filter.layer, filter.filters);
});
suites(this.#emitter, this.#refiner, this.#file).forEach((suite) => runner2.add(suite));
await globalHooks.setup(runner2);
await runner2.start();
await runner2.exec();
await runner2.end();
await globalHooks.teardown(null, runner2);
return runner2.getSummary();
}
};
// factories/create_dummy_tests.ts
import assert from "assert";
function createUnitTestsSuite(emitter, refiner, file) {
const suite = new Suite("unit", emitter, refiner);
const group = createTestGroup("Maths#add", emitter, refiner, {
suite,
file
});
createTest("A top level test inside a suite", emitter, refiner, {
suite,
file
}).run(() => {
});
createTest("add two numbers", emitter, refiner, { group, file }).run(() => {
assert.equal(2 + 2, 4);
});
createTest("add three numbers", emitter, refiner, {
group,
file
}).run(() => {
assert.equal(2 + 2 + 2, 6);
});
createTest("add group of numbers", emitter, refiner, { group, file });
createTest("use math.js lib", emitter, refiner, { group, file }).skip(
true,
"Library work pending"
);
createTest("add multiple numbers", emitter, refiner, {
file,
group
}).run(() => {
assert.equal(2 + 2 + 2 + 2, 6);
});
createTest("add floating numbers", emitter, refiner, { group, file }).run(() => {
assert.equal(2 + 2.2 + 2.1, 6);
}).fails("Have to add support for floating numbers");
createTest("regression test that is passing", emitter, refiner, { group, file }).run(() => {
assert.equal(2 + 2.2 + 2.1, 2 + 2.2 + 2.1);
}).fails("Have to add support for floating numbers");
createTest("A test with an error that is not an AssertionError", emitter, refiner, {
group,
file
}).run(() => {
throw new Error("This is an error");
});
return suite;
}
function createFunctionalTestsSuite(emitter, refiner, file) {
const suite = new Suite("functional", emitter, refiner);
const group = createTestGroup("Users/store", emitter, refiner, {
suite,
file
});
createTest("Validate user data", emitter, refiner, {
group,
file
}).run(() => {
});
createTest("Disallow duplicate emails", emitter, refiner, {
group,
file
}).run(() => {
});
createTest("Disallow duplicate emails across tenants", emitter, refiner, {
group,
file
}).run(() => {
const users = ["", ""];
assert.equal(users.length, 1);
});
createTest("Normalize email before persisting it", emitter, refiner, {
group,
file
}).skip(true, "Have to build a normalizer");
createTest("Send email verification mail", emitter, refiner, {
group,
file
});
createTest("Test that times out", emitter, refiner, {
group,
file
}).run(() => {
return new Promise((resolve) => {
setTimeout(resolve, 2100);
});
});
const usersListGroup = createTestGroup("Users/list", emitter, refiner, {
suite,
file
});
usersListGroup.setup(() => {
throw new Error("Unable to cleanup database");
});
createTest("A test that will never run because the group hooks fails", emitter, refiner, {
group: usersListGroup
});
createTest("A top level test inside functional suite", emitter, refiner, {
suite,
file
}).run(() => {
});
return suite;
}
function createDummyTests(emitter, refiner, file) {
return [
createUnitTestsSuite(emitter, refiner, file),
createFunctionalTestsSuite(emitter, refiner, file)
];
}
// factories/main.ts
var runner = () => new RunnerFactory();
var syncReporter = {
name: "sync",
handler(r, emitter) {
emitter.on("runner:end", function() {
const summary = r.getSummary();
if (summary.hasError) {
if (summary.failureTree[0].errors.length) {
throw summary.failureTree[0].errors[0].error;
}
if (summary.failureTree[0].children[0].errors.length) {
throw summary.failureTree[0].children[0].errors[0].error;
}
}
});
}
};
export {
createDummyTests,
runner,
syncReporter
};