@japa/runner 3.1.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/build/{chunk-OBDV3O36.js → chunk-OGQDXVXY.js} +1 -1
- package/build/{chunk-LRVNUQHW.js → chunk-PLH254PF.js} +24 -42
- package/build/chunk-PLH254PF.js.map +1 -0
- package/build/{chunk-PKOB3ULJ.js → chunk-VDZGMJWM.js} +45 -19
- package/build/chunk-VDZGMJWM.js.map +1 -0
- package/build/{chunk-CYPN7IGE.js → chunk-ZBQV333W.js} +17 -8
- package/build/chunk-ZBQV333W.js.map +1 -0
- package/build/factories/{create_diverse_tests.d.ts → create_dummy_tests.d.ts} +1 -1
- package/build/factories/main.d.ts +1 -1
- package/build/factories/main.js +28 -8
- package/build/factories/main.js.map +1 -1
- package/build/factories/runner.d.ts +4 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +29 -13
- package/build/index.js.map +1 -1
- package/build/modules/core/main.d.ts +10 -3
- package/build/modules/core/main.js +2 -2
- package/build/modules/core/reporters/base.d.ts +1 -1
- package/build/modules/core/types.d.ts +0 -1
- package/build/src/config_manager.d.ts +1 -1
- package/build/src/debug.d.ts +0 -1
- package/build/src/exceptions_manager.d.ts +1 -1
- package/build/src/files_manager.d.ts +0 -1
- package/build/src/helpers.d.ts +1 -0
- package/build/src/planner.d.ts +0 -1
- package/build/src/reporters/main.js +3 -3
- package/build/src/types.d.ts +2 -1
- package/build/src/types.js +1 -1
- package/build/src/types.js.map +1 -1
- package/package.json +75 -72
- package/build/chunk-CYPN7IGE.js.map +0 -1
- package/build/chunk-LRVNUQHW.js.map +0 -1
- package/build/chunk-PKOB3ULJ.js.map +0 -1
- /package/build/{chunk-OBDV3O36.js.map → chunk-OGQDXVXY.js.map} +0 -0
package/build/factories/main.js
CHANGED
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
Planner,
|
|
6
6
|
createTest,
|
|
7
7
|
createTestGroup
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
8
|
+
} from "../chunk-ZBQV333W.js";
|
|
9
|
+
import "../chunk-PLH254PF.js";
|
|
10
10
|
import {
|
|
11
11
|
Emitter,
|
|
12
12
|
Runner,
|
|
13
13
|
Suite
|
|
14
|
-
} from "../chunk-
|
|
15
|
-
import "../chunk-
|
|
14
|
+
} from "../chunk-VDZGMJWM.js";
|
|
15
|
+
import "../chunk-OGQDXVXY.js";
|
|
16
16
|
|
|
17
17
|
// factories/runner.ts
|
|
18
18
|
import { fileURLToPath } from "node:url";
|
|
@@ -21,6 +21,7 @@ var RunnerFactory = class {
|
|
|
21
21
|
#config;
|
|
22
22
|
#cliArgs;
|
|
23
23
|
#file = fileURLToPath(import.meta.url);
|
|
24
|
+
#bail = false;
|
|
24
25
|
get #refiner() {
|
|
25
26
|
return this.#config.refiner;
|
|
26
27
|
}
|
|
@@ -65,11 +66,19 @@ var RunnerFactory = class {
|
|
|
65
66
|
return [defaultSuite];
|
|
66
67
|
});
|
|
67
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Enable/disable the bail mode
|
|
71
|
+
*/
|
|
72
|
+
bail(toggle = true) {
|
|
73
|
+
this.#bail = toggle;
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
68
76
|
/**
|
|
69
77
|
* Run dummy tests. You might use
|
|
70
78
|
*/
|
|
71
79
|
async runSuites(suites) {
|
|
72
80
|
const runner2 = new Runner(this.#emitter);
|
|
81
|
+
runner2.bail(this.#bail);
|
|
73
82
|
await this.#registerPlugins(runner2);
|
|
74
83
|
const { config, reporters, refinerFilters } = await new Planner(this.#config).plan();
|
|
75
84
|
const globalHooks = new GlobalHooks();
|
|
@@ -90,7 +99,7 @@ var RunnerFactory = class {
|
|
|
90
99
|
}
|
|
91
100
|
};
|
|
92
101
|
|
|
93
|
-
// factories/
|
|
102
|
+
// factories/create_dummy_tests.ts
|
|
94
103
|
import assert from "node:assert";
|
|
95
104
|
function createUnitTestsSuite(emitter, refiner, file) {
|
|
96
105
|
const suite = new Suite("unit", emitter, refiner);
|
|
@@ -126,6 +135,9 @@ function createUnitTestsSuite(emitter, refiner, file) {
|
|
|
126
135
|
createTest("add floating numbers", emitter, refiner, { group, file }).run(() => {
|
|
127
136
|
assert.equal(2 + 2.2 + 2.1, 6);
|
|
128
137
|
}).fails("Have to add support for floating numbers");
|
|
138
|
+
createTest("regression test that is passing", emitter, refiner, { group, file }).run(() => {
|
|
139
|
+
assert.equal(2 + 2.2 + 2.1, 2 + 2.2 + 2.1);
|
|
140
|
+
}).fails("Have to add support for floating numbers");
|
|
129
141
|
createTest("A test with an error that is not an AssertionError", emitter, refiner, {
|
|
130
142
|
group,
|
|
131
143
|
file
|
|
@@ -165,6 +177,14 @@ function createFunctionalTestsSuite(emitter, refiner, file) {
|
|
|
165
177
|
group,
|
|
166
178
|
file
|
|
167
179
|
});
|
|
180
|
+
createTest("Test that times out", emitter, refiner, {
|
|
181
|
+
group,
|
|
182
|
+
file
|
|
183
|
+
}).run(() => {
|
|
184
|
+
return new Promise((resolve) => {
|
|
185
|
+
setTimeout(resolve, 2100);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
168
188
|
const usersListGroup = createTestGroup("Users/list", emitter, refiner, {
|
|
169
189
|
suite,
|
|
170
190
|
file
|
|
@@ -172,7 +192,7 @@ function createFunctionalTestsSuite(emitter, refiner, file) {
|
|
|
172
192
|
usersListGroup.setup(() => {
|
|
173
193
|
throw new Error("Unable to cleanup database");
|
|
174
194
|
});
|
|
175
|
-
createTest("A test that will never because the group hooks fails", emitter, refiner, {
|
|
195
|
+
createTest("A test that will never run because the group hooks fails", emitter, refiner, {
|
|
176
196
|
group: usersListGroup
|
|
177
197
|
});
|
|
178
198
|
createTest("A top level test inside functional suite", emitter, refiner, {
|
|
@@ -182,7 +202,7 @@ function createFunctionalTestsSuite(emitter, refiner, file) {
|
|
|
182
202
|
});
|
|
183
203
|
return suite;
|
|
184
204
|
}
|
|
185
|
-
function
|
|
205
|
+
function createDummyTests(emitter, refiner, file) {
|
|
186
206
|
return [
|
|
187
207
|
createUnitTestsSuite(emitter, refiner, file),
|
|
188
208
|
createFunctionalTestsSuite(emitter, refiner, file)
|
|
@@ -208,7 +228,7 @@ var syncReporter = {
|
|
|
208
228
|
}
|
|
209
229
|
};
|
|
210
230
|
export {
|
|
211
|
-
|
|
231
|
+
createDummyTests,
|
|
212
232
|
runner,
|
|
213
233
|
syncReporter
|
|
214
234
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../factories/runner.ts","../../factories/create_diverse_tests.ts","../../factories/main.ts"],"sourcesContent":["/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { fileURLToPath } from 'node:url'\n\nimport { Planner } from '../src/planner.js'\nimport { GlobalHooks } from '../src/hooks.js'\nimport { CliParser } from '../src/cli_parser.js'\nimport { createTest } from '../src/create_test.js'\nimport { ConfigManager } from '../src/config_manager.js'\nimport { Suite, Runner, Emitter, TestContext, Refiner } from '../modules/core/main.js'\nimport type {\n Config,\n CLIArgs,\n TestExecutor,\n RunnerSummary,\n NormalizedConfig,\n} from '../src/types.js'\n\n/**\n * Runner factory exposes the API to run dummy suites, groups and tests.\n * You might want to use the factory for testing reporters and\n * plugins usage\n */\nexport class RunnerFactory {\n #emitter = new Emitter()\n #config?: NormalizedConfig\n #cliArgs?: CLIArgs\n #file = fileURLToPath(import.meta.url)\n\n get #refiner() {\n return this.#config!.refiner\n }\n\n /**\n * Registers plugins\n */\n async #registerPlugins(runner: Runner) {\n for (let plugin of this.#config!.plugins) {\n await plugin({\n config: this.#config!,\n runner,\n emitter: this.#emitter,\n cliArgs: this.#cliArgs!,\n })\n }\n }\n\n /**\n * Configure runner\n */\n configure(config: Config, argv?: string[]) {\n this.#cliArgs = new CliParser().parse(argv || [])\n this.#config = new ConfigManager(config, this.#cliArgs).hydrate()\n return this\n }\n\n /**\n * Define a custom emitter instance to use\n */\n useEmitter(emitter: Emitter) {\n this.#emitter = emitter\n return this\n }\n\n /**\n * Run a test using the runner\n */\n async runTest(\n title: string,\n callback: TestExecutor<TestContext, undefined>\n ): Promise<RunnerSummary> {\n return this.runSuites((emitter, refiner, file) => {\n const defaultSuite = new Suite('default', emitter, refiner)\n\n createTest(title, emitter, refiner, {\n suite: defaultSuite,\n file: file,\n }).run(callback)\n\n return [defaultSuite]\n })\n }\n\n /**\n * Run dummy tests. You might use\n */\n async runSuites(\n suites: (emitter: Emitter, refiner: Refiner, file?: string) => Suite[]\n ): Promise<RunnerSummary> {\n const runner = new Runner(this.#emitter)\n await this.#registerPlugins(runner)\n\n const { config, reporters, refinerFilters } = await new Planner(this.#config!).plan()\n const globalHooks = new GlobalHooks()\n globalHooks.apply(config)\n\n reporters.forEach((reporter) => {\n runner.registerReporter(reporter)\n })\n\n refinerFilters.forEach((filter) => {\n config.refiner.add(filter.layer, filter.filters)\n })\n\n suites(this.#emitter, this.#refiner, this.#file).forEach((suite) => runner.add(suite))\n\n await globalHooks.setup(runner)\n await runner.start()\n await runner.exec()\n await runner.end()\n await globalHooks.teardown(null, runner)\n\n return runner.getSummary()\n }\n}\n","import assert from 'node:assert'\nimport { Suite, Emitter, Refiner } from '../modules/core/main.js'\nimport { createTest, createTestGroup } from '../src/create_test.js'\n\n/**\n * Creates a unit tests suite with bunch of dummy tests\n * reproducing different tests behavior\n */\nfunction createUnitTestsSuite(emitter: Emitter, refiner: Refiner, file?: string) {\n const suite = new Suite('unit', emitter, refiner)\n const group = createTestGroup('Maths#add', emitter, refiner, {\n suite,\n file,\n })\n\n createTest('A top level test inside a suite', emitter, refiner, {\n suite,\n file,\n }).run(() => {})\n\n createTest('add two numbers', emitter, refiner, { group, file }).run(() => {\n assert.equal(2 + 2, 4)\n })\n createTest('add three numbers', emitter, refiner, {\n group,\n file,\n }).run(() => {\n assert.equal(2 + 2 + 2, 6)\n })\n\n createTest('add group of numbers', emitter, refiner, { group, file })\n createTest('use math.js lib', emitter, refiner, { group, file }).skip(\n true,\n 'Library work pending'\n )\n createTest('add multiple numbers', emitter, refiner, {\n file,\n group,\n }).run(() => {\n assert.equal(2 + 2 + 2 + 2, 6)\n })\n createTest('add floating numbers', emitter, refiner, { group, file })\n .run(() => {\n assert.equal(2 + 2.2 + 2.1, 6)\n })\n .fails('Have to add support for floating numbers')\n createTest('A test with an error that is not an AssertionError', emitter, refiner, {\n group,\n file,\n }).run(() => {\n throw new Error('This is an error')\n })\n\n return suite\n}\n\n/**\n * Creates a unit functional suite with bunch of dummy tests\n * reproducing different tests behavior\n */\nfunction createFunctionalTestsSuite(emitter: Emitter, refiner: Refiner, file?: string) {\n const suite = new Suite('functional', emitter, refiner)\n\n const group = createTestGroup('Users/store', emitter, refiner, {\n suite,\n file: file,\n })\n createTest('Validate user data', emitter, refiner, {\n group,\n file: file,\n }).run(() => {})\n createTest('Disallow duplicate emails', emitter, refiner, {\n group,\n file: file,\n }).run(() => {})\n createTest('Disallow duplicate emails across tenants', emitter, refiner, {\n group,\n file: file,\n }).run(() => {\n const users = ['', '']\n assert.equal(users.length, 1)\n })\n createTest('Normalize email before persisting it', emitter, refiner, {\n group,\n file: file,\n }).skip(true, 'Have to build a normalizer')\n createTest('Send email verification mail', emitter, refiner, {\n group,\n file: file,\n })\n\n const usersListGroup = createTestGroup('Users/list', emitter, refiner, {\n suite,\n file: file,\n })\n usersListGroup.setup(() => {\n throw new Error('Unable to cleanup database')\n })\n createTest('A test that will never because the group hooks fails', emitter, refiner, {\n group: usersListGroup,\n })\n\n createTest('A top level test inside functional suite', emitter, refiner, {\n suite,\n file: file,\n }).run(() => {})\n\n return suite\n}\n\n/**\n * Returns an array of suites with dummy tests reproducting\n * different test behavior\n */\nexport function createDiverseTests(emitter: Emitter, refiner: Refiner, file?: string): Suite[] {\n return [\n createUnitTestsSuite(emitter, refiner, file),\n createFunctionalTestsSuite(emitter, refiner, file),\n ]\n}\n","/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { ReporterContract } from '../src/types.js'\nimport { RunnerFactory } from './runner.js'\n\n/**\n * Create an instance of the runner factory\n */\nexport const runner = () => new RunnerFactory()\nexport { createDiverseTests } from './create_diverse_tests.js'\nexport const syncReporter: ReporterContract = {\n name: 'sync',\n handler(r, emitter) {\n emitter.on('runner:end', function () {\n const summary = r.getSummary()\n if (summary.hasError) {\n if (summary.failureTree[0].errors.length) {\n throw summary.failureTree[0].errors[0].error\n }\n if (summary.failureTree[0].children[0].errors.length) {\n throw summary.failureTree[0].children[0].errors[0].error\n }\n }\n })\n },\n}\n"],"mappings":"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","names":["runner"]}
|
|
1
|
+
{"version":3,"sources":["../../factories/runner.ts","../../factories/create_dummy_tests.ts","../../factories/main.ts"],"sourcesContent":["/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { fileURLToPath } from 'node:url'\n\nimport { Planner } from '../src/planner.js'\nimport { GlobalHooks } from '../src/hooks.js'\nimport { CliParser } from '../src/cli_parser.js'\nimport { createTest } from '../src/create_test.js'\nimport { ConfigManager } from '../src/config_manager.js'\nimport { Suite, Runner, Emitter, TestContext, Refiner } from '../modules/core/main.js'\nimport type {\n Config,\n CLIArgs,\n TestExecutor,\n RunnerSummary,\n NormalizedConfig,\n} from '../src/types.js'\n\n/**\n * Runner factory exposes the API to run dummy suites, groups and tests.\n * You might want to use the factory for testing reporters and\n * plugins usage\n */\nexport class RunnerFactory {\n #emitter = new Emitter()\n #config?: NormalizedConfig\n #cliArgs?: CLIArgs\n #file = fileURLToPath(import.meta.url)\n #bail: boolean = false\n\n get #refiner() {\n return this.#config!.refiner\n }\n\n /**\n * Registers plugins\n */\n async #registerPlugins(runner: Runner) {\n for (let plugin of this.#config!.plugins) {\n await plugin({\n config: this.#config!,\n runner,\n emitter: this.#emitter,\n cliArgs: this.#cliArgs!,\n })\n }\n }\n\n /**\n * Configure runner\n */\n configure(config: Config, argv?: string[]) {\n this.#cliArgs = new CliParser().parse(argv || [])\n this.#config = new ConfigManager(config, this.#cliArgs).hydrate()\n return this\n }\n\n /**\n * Define a custom emitter instance to use\n */\n useEmitter(emitter: Emitter) {\n this.#emitter = emitter\n return this\n }\n\n /**\n * Run a test using the runner\n */\n async runTest(\n title: string,\n callback: TestExecutor<TestContext, undefined>\n ): Promise<RunnerSummary> {\n return this.runSuites((emitter, refiner, file) => {\n const defaultSuite = new Suite('default', emitter, refiner)\n\n createTest(title, emitter, refiner, {\n suite: defaultSuite,\n file: file,\n }).run(callback)\n\n return [defaultSuite]\n })\n }\n\n /**\n * Enable/disable the bail mode\n */\n bail(toggle: boolean = true) {\n this.#bail = toggle\n return this\n }\n\n /**\n * Run dummy tests. You might use\n */\n async runSuites(\n suites: (emitter: Emitter, refiner: Refiner, file?: string) => Suite[]\n ): Promise<RunnerSummary> {\n const runner = new Runner(this.#emitter)\n runner.bail(this.#bail)\n\n await this.#registerPlugins(runner)\n\n const { config, reporters, refinerFilters } = await new Planner(this.#config!).plan()\n const globalHooks = new GlobalHooks()\n globalHooks.apply(config)\n\n reporters.forEach((reporter) => {\n runner.registerReporter(reporter)\n })\n\n refinerFilters.forEach((filter) => {\n config.refiner.add(filter.layer, filter.filters)\n })\n\n suites(this.#emitter, this.#refiner, this.#file).forEach((suite) => runner.add(suite))\n\n await globalHooks.setup(runner)\n await runner.start()\n await runner.exec()\n await runner.end()\n await globalHooks.teardown(null, runner)\n\n return runner.getSummary()\n }\n}\n","import assert from 'node:assert'\nimport { Suite, Emitter, Refiner } from '../modules/core/main.js'\nimport { createTest, createTestGroup } from '../src/create_test.js'\n\n/**\n * Creates a unit tests suite with bunch of dummy tests\n * reproducing different tests behavior\n */\nfunction createUnitTestsSuite(emitter: Emitter, refiner: Refiner, file?: string) {\n const suite = new Suite('unit', emitter, refiner)\n const group = createTestGroup('Maths#add', emitter, refiner, {\n suite,\n file,\n })\n\n createTest('A top level test inside a suite', emitter, refiner, {\n suite,\n file,\n }).run(() => {})\n\n createTest('add two numbers', emitter, refiner, { group, file }).run(() => {\n assert.equal(2 + 2, 4)\n })\n createTest('add three numbers', emitter, refiner, {\n group,\n file,\n }).run(() => {\n assert.equal(2 + 2 + 2, 6)\n })\n\n createTest('add group of numbers', emitter, refiner, { group, file })\n createTest('use math.js lib', emitter, refiner, { group, file }).skip(\n true,\n 'Library work pending'\n )\n createTest('add multiple numbers', emitter, refiner, {\n file,\n group,\n }).run(() => {\n assert.equal(2 + 2 + 2 + 2, 6)\n })\n createTest('add floating numbers', emitter, refiner, { group, file })\n .run(() => {\n assert.equal(2 + 2.2 + 2.1, 6)\n })\n .fails('Have to add support for floating numbers')\n\n createTest('regression test that is passing', emitter, refiner, { group, file })\n .run(() => {\n assert.equal(2 + 2.2 + 2.1, 2 + 2.2 + 2.1)\n })\n .fails('Have to add support for floating numbers')\n\n createTest('A test with an error that is not an AssertionError', emitter, refiner, {\n group,\n file,\n }).run(() => {\n throw new Error('This is an error')\n })\n\n return suite\n}\n\n/**\n * Creates a unit functional suite with bunch of dummy tests\n * reproducing different tests behavior\n */\nfunction createFunctionalTestsSuite(emitter: Emitter, refiner: Refiner, file?: string) {\n const suite = new Suite('functional', emitter, refiner)\n\n const group = createTestGroup('Users/store', emitter, refiner, {\n suite,\n file: file,\n })\n createTest('Validate user data', emitter, refiner, {\n group,\n file: file,\n }).run(() => {})\n createTest('Disallow duplicate emails', emitter, refiner, {\n group,\n file: file,\n }).run(() => {})\n createTest('Disallow duplicate emails across tenants', emitter, refiner, {\n group,\n file: file,\n }).run(() => {\n const users = ['', '']\n assert.equal(users.length, 1)\n })\n createTest('Normalize email before persisting it', emitter, refiner, {\n group,\n file: file,\n }).skip(true, 'Have to build a normalizer')\n createTest('Send email verification mail', emitter, refiner, {\n group,\n file: file,\n })\n\n createTest('Test that times out', emitter, refiner, {\n group,\n file: file,\n }).run(() => {\n return new Promise((resolve) => {\n setTimeout(resolve, 2100)\n })\n })\n\n const usersListGroup = createTestGroup('Users/list', emitter, refiner, {\n suite,\n file: file,\n })\n usersListGroup.setup(() => {\n throw new Error('Unable to cleanup database')\n })\n createTest('A test that will never run because the group hooks fails', emitter, refiner, {\n group: usersListGroup,\n })\n\n createTest('A top level test inside functional suite', emitter, refiner, {\n suite,\n file: file,\n }).run(() => {})\n\n return suite\n}\n\n/**\n * Returns an array of suites with dummy tests reproducting\n * different test behavior\n */\nexport function createDummyTests(emitter: Emitter, refiner: Refiner, file?: string): Suite[] {\n return [\n createUnitTestsSuite(emitter, refiner, file),\n createFunctionalTestsSuite(emitter, refiner, file),\n ]\n}\n","/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { ReporterContract } from '../src/types.js'\nimport { RunnerFactory } from './runner.js'\n\n/**\n * Create an instance of the runner factory\n */\nexport const runner = () => new RunnerFactory()\nexport { createDummyTests } from './create_dummy_tests.js'\nexport const syncReporter: ReporterContract = {\n name: 'sync',\n handler(r, emitter) {\n emitter.on('runner:end', function () {\n const summary = r.getSummary()\n if (summary.hasError) {\n if (summary.failureTree[0].errors.length) {\n throw summary.failureTree[0].errors[0].error\n }\n if (summary.failureTree[0].children[0].errors.length) {\n throw summary.failureTree[0].children[0].errors[0].error\n }\n }\n })\n },\n}\n"],"mappings":"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","names":["runner"]}
|
|
@@ -19,6 +19,10 @@ export declare class RunnerFactory {
|
|
|
19
19
|
* Run a test using the runner
|
|
20
20
|
*/
|
|
21
21
|
runTest(title: string, callback: TestExecutor<TestContext, undefined>): Promise<RunnerSummary>;
|
|
22
|
+
/**
|
|
23
|
+
* Enable/disable the bail mode
|
|
24
|
+
*/
|
|
25
|
+
bail(toggle?: boolean): this;
|
|
22
26
|
/**
|
|
23
27
|
* Run dummy tests. You might use
|
|
24
28
|
*/
|
package/build/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TestExecutor } from '@japa/core/types';
|
|
2
2
|
import type { Config } from './src/types.js';
|
|
3
3
|
import { Group, Test, TestContext } from './modules/core/main.js';
|
|
4
|
+
type OmitFirstArg<F> = F extends [_: any, ...args: infer R] ? R : never;
|
|
4
5
|
/**
|
|
5
6
|
* Create a Japa test. Defining a test without the callback
|
|
6
7
|
* will create a todo test.
|
|
@@ -8,6 +9,7 @@ import { Group, Test, TestContext } from './modules/core/main.js';
|
|
|
8
9
|
export declare function test(title: string, callback?: TestExecutor<TestContext, undefined>): Test<undefined>;
|
|
9
10
|
export declare namespace test {
|
|
10
11
|
var group: (title: string, callback: (group: Group) => void) => void;
|
|
12
|
+
var macro: <T extends (test: Test, ...args: any[]) => any>(callback: T) => (...args: OmitFirstArg<Parameters<T>>) => ReturnType<T>;
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
13
15
|
* Get the test of currently running test
|
|
@@ -31,3 +33,4 @@ export declare function configure(options: Config): void;
|
|
|
31
33
|
* files behind the scenes
|
|
32
34
|
*/
|
|
33
35
|
export declare function run(): Promise<void>;
|
|
36
|
+
export {};
|
package/build/index.js
CHANGED
|
@@ -7,16 +7,15 @@ import {
|
|
|
7
7
|
createTestGroup,
|
|
8
8
|
debug_default,
|
|
9
9
|
validator_default
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import
|
|
12
|
-
colors
|
|
13
|
-
} from "./chunk-LRVNUQHW.js";
|
|
10
|
+
} from "./chunk-ZBQV333W.js";
|
|
11
|
+
import "./chunk-PLH254PF.js";
|
|
14
12
|
import {
|
|
15
13
|
Emitter,
|
|
16
14
|
Runner,
|
|
17
|
-
Suite
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
Suite,
|
|
16
|
+
colors
|
|
17
|
+
} from "./chunk-VDZGMJWM.js";
|
|
18
|
+
import "./chunk-OGQDXVXY.js";
|
|
20
19
|
|
|
21
20
|
// index.ts
|
|
22
21
|
import { fileURLToPath } from "node:url";
|
|
@@ -105,11 +104,11 @@ var ExceptionsManager = class {
|
|
|
105
104
|
}
|
|
106
105
|
});
|
|
107
106
|
}
|
|
108
|
-
async
|
|
109
|
-
if (this.#state === "
|
|
107
|
+
async report() {
|
|
108
|
+
if (this.#state === "reporting") {
|
|
110
109
|
return;
|
|
111
110
|
}
|
|
112
|
-
this.#state = "
|
|
111
|
+
this.#state = "reporting";
|
|
113
112
|
if (this.#exceptionsBuffer.length) {
|
|
114
113
|
let exceptionsCount = this.#exceptionsBuffer.length;
|
|
115
114
|
let exceptionsIndex = this.#exceptionsBuffer.length;
|
|
@@ -151,7 +150,7 @@ function test(title, callback) {
|
|
|
151
150
|
};
|
|
152
151
|
});
|
|
153
152
|
if (callback) {
|
|
154
|
-
testInstance.run(callback);
|
|
153
|
+
testInstance.run(callback, new Error());
|
|
155
154
|
}
|
|
156
155
|
return testInstance;
|
|
157
156
|
}
|
|
@@ -163,9 +162,20 @@ test.group = function(title, callback) {
|
|
|
163
162
|
runnerConfig.refiner,
|
|
164
163
|
executionPlanState
|
|
165
164
|
);
|
|
165
|
+
if (cliArgs.bail && cliArgs.bailLayer === "group") {
|
|
166
|
+
executionPlanState.group.bail(true);
|
|
167
|
+
}
|
|
166
168
|
callback(executionPlanState.group);
|
|
167
169
|
executionPlanState.group = void 0;
|
|
168
170
|
};
|
|
171
|
+
test.macro = function(callback) {
|
|
172
|
+
return (...args) => {
|
|
173
|
+
if (!activeTest) {
|
|
174
|
+
throw new Error("Cannot invoke macro outside of the test callback");
|
|
175
|
+
}
|
|
176
|
+
return callback(activeTest, ...args);
|
|
177
|
+
};
|
|
178
|
+
};
|
|
169
179
|
function getActiveTest() {
|
|
170
180
|
return activeTest;
|
|
171
181
|
}
|
|
@@ -183,6 +193,9 @@ async function run() {
|
|
|
183
193
|
validator_default.ensureIsConfigured(runnerConfig);
|
|
184
194
|
executionPlanState.phase = "planning";
|
|
185
195
|
const runner = new Runner(emitter);
|
|
196
|
+
if (cliArgs.bail && cliArgs.bailLayer === "") {
|
|
197
|
+
runner.bail(true);
|
|
198
|
+
}
|
|
186
199
|
const globalHooks = new GlobalHooks();
|
|
187
200
|
const exceptionsManager = new ExceptionsManager();
|
|
188
201
|
try {
|
|
@@ -212,6 +225,9 @@ async function run() {
|
|
|
212
225
|
if (typeof suite.configure === "function") {
|
|
213
226
|
suite.configure(executionPlanState.suite);
|
|
214
227
|
}
|
|
228
|
+
if (cliArgs.bail && cliArgs.bailLayer === "suite") {
|
|
229
|
+
executionPlanState.suite.bail(true);
|
|
230
|
+
}
|
|
215
231
|
runner.add(executionPlanState.suite);
|
|
216
232
|
for (let fileURL of suite.filesURLs) {
|
|
217
233
|
executionPlanState.file = fileURLToPath(fileURL);
|
|
@@ -226,7 +242,7 @@ async function run() {
|
|
|
226
242
|
await runner.exec();
|
|
227
243
|
await globalHooks.teardown(null, runner);
|
|
228
244
|
await runner.end();
|
|
229
|
-
await exceptionsManager.
|
|
245
|
+
await exceptionsManager.report();
|
|
230
246
|
const summary = runner.getSummary();
|
|
231
247
|
if (summary.hasError || exceptionsManager.hasErrors) {
|
|
232
248
|
process.exitCode = 1;
|
|
@@ -238,7 +254,7 @@ async function run() {
|
|
|
238
254
|
await globalHooks.teardown(error, runner);
|
|
239
255
|
const printer = new ErrorsPrinter2();
|
|
240
256
|
await printer.printError(error);
|
|
241
|
-
await exceptionsManager.
|
|
257
|
+
await exceptionsManager.report();
|
|
242
258
|
process.exitCode = 1;
|
|
243
259
|
if (runnerConfig.forceExit) {
|
|
244
260
|
process.exit();
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../src/plugins/retry.ts","../src/exceptions_manager.ts"],"sourcesContent":["/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { fileURLToPath } from 'node:url'\nimport { ErrorsPrinter } from '@japa/errors-printer'\nimport type { TestExecutor } from '@japa/core/types'\n\nimport debug from './src/debug.js'\nimport validator from './src/validator.js'\nimport { Planner } from './src/planner.js'\nimport { GlobalHooks } from './src/hooks.js'\nimport { CliParser } from './src/cli_parser.js'\nimport { retryPlugin } from './src/plugins/retry.js'\nimport { ConfigManager } from './src/config_manager.js'\nimport { ExceptionsManager } from './src/exceptions_manager.js'\nimport { createTest, createTestGroup } from './src/create_test.js'\nimport type { CLIArgs, Config, NormalizedConfig } from './src/types.js'\nimport { Emitter, Group, Runner, Suite, Test, TestContext } from './modules/core/main.js'\n\n/**\n * Global emitter instance used by the test\n */\nconst emitter = new Emitter()\n\n/**\n * The current active test\n */\nlet activeTest: Test<any> | undefined\n\n/**\n * Parsed commandline arguments\n */\nlet cliArgs: CLIArgs = {}\n\n/**\n * Hydrated config\n */\nlet runnerConfig: NormalizedConfig | undefined\n\n/**\n * The state refers to the phase where we configure suites and import\n * test files. We stick this metadata to the test instance one can\n * later reference within the test.\n */\nconst executionPlanState: {\n phase: 'idle' | 'planning' | 'executing'\n file?: string\n suite?: Suite\n group?: Group\n timeout?: number\n retries?: number\n} = {\n phase: 'idle',\n}\n\n/**\n * Create a Japa test. Defining a test without the callback\n * will create a todo test.\n */\nexport function test(title: string, callback?: TestExecutor<TestContext, undefined>) {\n validator.ensureIsInPlanningPhase(executionPlanState.phase)\n\n const testInstance = createTest(title, emitter, runnerConfig!.refiner, executionPlanState)\n testInstance.setup((t) => {\n activeTest = t\n return () => {\n activeTest = undefined\n }\n })\n\n if (callback) {\n testInstance.run(callback)\n }\n\n return testInstance\n}\n\n/**\n * Create a Japa test group\n */\ntest.group = function (title: string, callback: (group: Group) => void) {\n validator.ensureIsInPlanningPhase(executionPlanState.phase)\n\n executionPlanState.group = createTestGroup(\n title,\n emitter,\n runnerConfig!.refiner,\n executionPlanState\n )\n callback(executionPlanState.group)\n executionPlanState.group = undefined\n}\n\n/**\n * Get the test of currently running test\n */\nexport function getActiveTest() {\n return activeTest\n}\n\n/**\n * Make Japa process command line arguments. Later the parsed output\n * will be used by Japa to compute the configuration\n */\nexport function processCLIArgs(argv: string[]) {\n cliArgs = new CliParser().parse(argv)\n}\n\n/**\n * Configure the tests runner with inline configuration. You must\n * call configure method before the run method.\n *\n * Do note: The CLI flags will overwrite the options provided\n * to the configure method.\n */\nexport function configure(options: Config) {\n runnerConfig = new ConfigManager(options, cliArgs).hydrate()\n}\n\n/**\n * Execute Japa tests. Calling this function will import the test\n * files behind the scenes\n */\nexport async function run() {\n /**\n * Display help when help flag is used\n */\n if (cliArgs.help) {\n console.log(new CliParser().getHelp())\n return\n }\n\n validator.ensureIsConfigured(runnerConfig)\n\n executionPlanState.phase = 'planning'\n const runner = new Runner(emitter)\n const globalHooks = new GlobalHooks()\n const exceptionsManager = new ExceptionsManager()\n\n try {\n /**\n * Executing the retry plugin as the first thing\n */\n await retryPlugin({ config: runnerConfig!, runner, emitter, cliArgs })\n\n /**\n * Step 1: Executing plugins before creating a plan, so that it can mutate\n * the config\n */\n for (let plugin of runnerConfig!.plugins) {\n debug('executing \"%s\" plugin', plugin.name || 'anonymous')\n await plugin({ runner, emitter, cliArgs, config: runnerConfig! })\n }\n\n /**\n * Step 2: Creating an execution plan. The output is the result of\n * applying all the filters and validations.\n */\n const { config, reporters, suites, refinerFilters } = await new Planner(runnerConfig!).plan()\n\n /**\n * Step 3: Registering reporters and filters with the runner\n */\n reporters.forEach((reporter) => {\n debug('registering \"%s\" reporter', reporter.name)\n runner.registerReporter(reporter)\n })\n refinerFilters.forEach((filter) => {\n debug('apply %s filters \"%O\" ', filter.layer, filter.filters)\n config.refiner.add(filter.layer, filter.filters)\n })\n config.refiner.matchAllTags(cliArgs.matchAll ?? false)\n runner.onSuite(config.configureSuite)\n\n /**\n * Step 4: Running the setup hooks\n */\n debug('executing global hooks')\n globalHooks.apply(config)\n await globalHooks.setup(runner)\n\n /**\n * Step 5: Register suites and import test files\n */\n for (let suite of suites) {\n /**\n * Creating and configuring the suite\n */\n executionPlanState.suite = new Suite(suite.name, emitter, config.refiner)\n executionPlanState.retries = suite.retries\n executionPlanState.timeout = suite.timeout\n if (typeof suite.configure === 'function') {\n suite.configure(executionPlanState.suite)\n }\n runner.add(executionPlanState.suite)\n\n /**\n * Importing suite files\n */\n for (let fileURL of suite.filesURLs) {\n executionPlanState.file = fileURLToPath(fileURL)\n debug('importing test file %s', executionPlanState.file)\n await config.importer(fileURL)\n }\n\n /**\n * Resetting global state\n */\n executionPlanState.suite = undefined\n }\n\n /**\n * Onto execution phase\n */\n executionPlanState.phase = 'executing'\n\n /**\n * Monitor for unhandled erorrs and rejections\n */\n exceptionsManager.monitor()\n\n await runner.start()\n await runner.exec()\n\n await globalHooks.teardown(null, runner)\n await runner.end()\n\n /**\n * Print unhandled errors\n */\n await exceptionsManager.flow()\n\n const summary = runner.getSummary()\n if (summary.hasError || exceptionsManager.hasErrors) {\n process.exitCode = 1\n }\n if (config.forceExit) {\n process.exit()\n }\n } catch (error) {\n await globalHooks.teardown(error, runner)\n const printer = new ErrorsPrinter()\n await printer.printError(error)\n\n /**\n * Print unhandled errors in case the code inside\n * the try block never got triggered\n */\n await exceptionsManager.flow()\n\n process.exitCode = 1\n if (runnerConfig!.forceExit) {\n process.exit()\n }\n }\n}\n","/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { join } from 'node:path'\nimport findCacheDirectory from 'find-cache-dir'\nimport { mkdir, readFile, unlink, writeFile } from 'node:fs/promises'\n\nimport { colors } from '../helpers.js'\nimport type { PluginFn } from '../types.js'\n\n/**\n * Paths to the cache directory and the summary file\n */\nconst CACHE_DIR = findCacheDirectory({ name: '@japa/runner' })\nconst SUMMARY_FILE = CACHE_DIR ? join(CACHE_DIR, 'summary.json') : undefined\n\n/**\n * Returns an object with the title of the tests failed during\n * the last run.\n */\nexport async function getFailedTests(): Promise<{ tests?: string[] }> {\n try {\n const summary = await readFile(SUMMARY_FILE!, 'utf-8')\n return JSON.parse(summary)\n } catch (error) {\n if (error.code === 'ENOENT') {\n return {}\n }\n throw new Error('Unable to read failed tests cache file', { cause: error })\n }\n}\n\n/**\n * Writes failing tests to the cache directory\n */\nexport async function cacheFailedTests(tests: string[]) {\n await mkdir(CACHE_DIR!, { recursive: true })\n await writeFile(SUMMARY_FILE!, JSON.stringify({ tests: tests }))\n}\n\n/**\n * Clears the cache dir\n */\nexport async function clearCache() {\n await unlink(SUMMARY_FILE!)\n}\n\n/**\n * Exposes the API to run failing tests using the \"failed\" CLI flag.\n */\nexport const retryPlugin: PluginFn = async function retry({ config, cliArgs }) {\n if (!SUMMARY_FILE) {\n return\n }\n\n config.teardown.push(async (runner) => {\n const summary = runner.getSummary()\n await cacheFailedTests(summary.failedTestsTitles)\n })\n\n if (cliArgs.failed) {\n try {\n const { tests } = await getFailedTests()\n if (!tests || !tests.length) {\n console.log(colors.bgYellow().black(' No failing tests found. Running all the tests '))\n return\n }\n config.filters.tests = tests\n } catch (error) {\n console.log(colors.bgRed().black(' Unable to read failed tests. Running all the tests '))\n console.log(colors.red(error))\n }\n }\n}\n","/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { ErrorsPrinter } from '@japa/errors-printer'\n\n/**\n * Handles uncaught exceptions and prints them to the\n * console\n */\nexport class ExceptionsManager {\n #exceptionsBuffer: any[] = []\n #rejectionsBuffer: any[] = []\n #state: 'watching' | 'flowing' = 'watching'\n #errorsPrinter = new ErrorsPrinter({ stackLinesCount: 2, framesMaxLimit: 4 })\n\n hasErrors: boolean = false\n\n /**\n * Monitors unhandled exceptions and rejections. The exceptions\n * are stacked in a buffer, so that we do not clutter the\n * tests output and once the tests are over, we will\n * print them to the console.\n *\n * In case the tests are completed, we will print errors as they\n * happen.\n */\n monitor() {\n process.on('uncaughtException', async (error) => {\n this.hasErrors = true\n if (this.#state === 'watching') {\n this.#exceptionsBuffer.push(error)\n } else {\n this.#errorsPrinter.printSectionBorder('[Unhandled Error]')\n await this.#errorsPrinter.printError(error)\n process.exitCode = 1\n }\n })\n\n process.on('unhandledRejection', async (error) => {\n this.hasErrors = true\n if (this.#state === 'watching') {\n this.#rejectionsBuffer.push(error)\n } else {\n this.#errorsPrinter.printSectionBorder('[Unhandled Rejection]')\n await this.#errorsPrinter.printError(error)\n process.exitCode = 1\n }\n })\n }\n\n async flow() {\n if (this.#state === 'flowing') {\n return\n }\n\n this.#state = 'flowing'\n\n /**\n * Print exceptions\n */\n if (this.#exceptionsBuffer.length) {\n let exceptionsCount = this.#exceptionsBuffer.length\n let exceptionsIndex = this.#exceptionsBuffer.length\n this.#errorsPrinter.printSectionHeader('Unhandled Errors')\n for (let exception of this.#exceptionsBuffer) {\n await this.#errorsPrinter.printError(exception)\n this.#errorsPrinter.printSectionBorder(`[${++exceptionsIndex}/${exceptionsCount}]`)\n }\n this.#exceptionsBuffer = []\n }\n\n /**\n * Print rejections\n */\n if (this.#rejectionsBuffer.length) {\n let rejectionsCount = this.#exceptionsBuffer.length\n let rejectionsIndex = this.#exceptionsBuffer.length\n this.#errorsPrinter.printSectionBorder('Unhandled Rejections')\n for (let rejection of this.#rejectionsBuffer) {\n await this.#errorsPrinter.printError(rejection)\n this.#errorsPrinter.printSectionBorder(`[${++rejectionsIndex}/${rejectionsCount}]`)\n }\n this.#rejectionsBuffer = []\n }\n }\n}\n"],"mappings":"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","names":["ErrorsPrinter","cliArgs","ErrorsPrinter"]}
|
|
1
|
+
{"version":3,"sources":["../index.ts","../src/plugins/retry.ts","../src/exceptions_manager.ts"],"sourcesContent":["/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { fileURLToPath } from 'node:url'\nimport { ErrorsPrinter } from '@japa/errors-printer'\nimport type { TestExecutor } from '@japa/core/types'\n\nimport debug from './src/debug.js'\nimport validator from './src/validator.js'\nimport { Planner } from './src/planner.js'\nimport { GlobalHooks } from './src/hooks.js'\nimport { CliParser } from './src/cli_parser.js'\nimport { retryPlugin } from './src/plugins/retry.js'\nimport { ConfigManager } from './src/config_manager.js'\nimport { ExceptionsManager } from './src/exceptions_manager.js'\nimport { createTest, createTestGroup } from './src/create_test.js'\nimport type { CLIArgs, Config, NormalizedConfig } from './src/types.js'\nimport { Emitter, Group, Runner, Suite, Test, TestContext } from './modules/core/main.js'\n\ntype OmitFirstArg<F> = F extends [_: any, ...args: infer R] ? R : never\n\n/**\n * Global emitter instance used by the test\n */\nconst emitter = new Emitter()\n\n/**\n * The current active test\n */\nlet activeTest: Test<any> | undefined\n\n/**\n * Parsed commandline arguments\n */\nlet cliArgs: CLIArgs = {}\n\n/**\n * Hydrated config\n */\nlet runnerConfig: NormalizedConfig | undefined\n\n/**\n * The state refers to the phase where we configure suites and import\n * test files. We stick this metadata to the test instance one can\n * later reference within the test.\n */\nconst executionPlanState: {\n phase: 'idle' | 'planning' | 'executing'\n file?: string\n suite?: Suite\n group?: Group\n timeout?: number\n retries?: number\n} = {\n phase: 'idle',\n}\n\n/**\n * Create a Japa test. Defining a test without the callback\n * will create a todo test.\n */\nexport function test(title: string, callback?: TestExecutor<TestContext, undefined>) {\n validator.ensureIsInPlanningPhase(executionPlanState.phase)\n\n const testInstance = createTest(title, emitter, runnerConfig!.refiner, executionPlanState)\n testInstance.setup((t) => {\n activeTest = t\n return () => {\n activeTest = undefined\n }\n })\n\n if (callback) {\n testInstance.run(callback, new Error())\n }\n\n return testInstance\n}\n\n/**\n * Create a Japa test group\n */\ntest.group = function (title: string, callback: (group: Group) => void) {\n validator.ensureIsInPlanningPhase(executionPlanState.phase)\n\n executionPlanState.group = createTestGroup(\n title,\n emitter,\n runnerConfig!.refiner,\n executionPlanState\n )\n\n /**\n * Enable bail on the group an when bailLayer is set to \"group\"\n */\n if (cliArgs.bail && cliArgs.bailLayer === 'group') {\n executionPlanState.group.bail(true)\n }\n\n callback(executionPlanState.group)\n executionPlanState.group = undefined\n}\n\n/**\n * Create a test bound macro. Within the macro, you can access the\n * currently executed test to read its context values or define\n * cleanup hooks\n */\ntest.macro = function <T extends (test: Test, ...args: any[]) => any>(\n callback: T\n): (...args: OmitFirstArg<Parameters<T>>) => ReturnType<T> {\n return (...args) => {\n if (!activeTest) {\n throw new Error('Cannot invoke macro outside of the test callback')\n }\n return callback(activeTest, ...args)\n }\n}\n\n/**\n * Get the test of currently running test\n */\nexport function getActiveTest() {\n return activeTest\n}\n\n/**\n * Make Japa process command line arguments. Later the parsed output\n * will be used by Japa to compute the configuration\n */\nexport function processCLIArgs(argv: string[]) {\n cliArgs = new CliParser().parse(argv)\n}\n\n/**\n * Configure the tests runner with inline configuration. You must\n * call configure method before the run method.\n *\n * Do note: The CLI flags will overwrite the options provided\n * to the configure method.\n */\nexport function configure(options: Config) {\n runnerConfig = new ConfigManager(options, cliArgs).hydrate()\n}\n\n/**\n * Execute Japa tests. Calling this function will import the test\n * files behind the scenes\n */\nexport async function run() {\n /**\n * Display help when help flag is used\n */\n if (cliArgs.help) {\n console.log(new CliParser().getHelp())\n return\n }\n\n validator.ensureIsConfigured(runnerConfig)\n\n executionPlanState.phase = 'planning'\n const runner = new Runner(emitter)\n\n /**\n * Enable bail on the runner and all the layers after the\n * runner when no specific bailLayer is specified\n */\n if (cliArgs.bail && cliArgs.bailLayer === '') {\n runner.bail(true)\n }\n\n const globalHooks = new GlobalHooks()\n const exceptionsManager = new ExceptionsManager()\n\n try {\n /**\n * Executing the retry plugin as the first thing\n */\n await retryPlugin({ config: runnerConfig!, runner, emitter, cliArgs })\n\n /**\n * Step 1: Executing plugins before creating a plan, so that it can mutate\n * the config\n */\n for (let plugin of runnerConfig!.plugins) {\n debug('executing \"%s\" plugin', plugin.name || 'anonymous')\n await plugin({ runner, emitter, cliArgs, config: runnerConfig! })\n }\n\n /**\n * Step 2: Creating an execution plan. The output is the result of\n * applying all the filters and validations.\n */\n const { config, reporters, suites, refinerFilters } = await new Planner(runnerConfig!).plan()\n\n /**\n * Step 3: Registering reporters and filters with the runner\n */\n reporters.forEach((reporter) => {\n debug('registering \"%s\" reporter', reporter.name)\n runner.registerReporter(reporter)\n })\n refinerFilters.forEach((filter) => {\n debug('apply %s filters \"%O\" ', filter.layer, filter.filters)\n config.refiner.add(filter.layer, filter.filters)\n })\n config.refiner.matchAllTags(cliArgs.matchAll ?? false)\n runner.onSuite(config.configureSuite)\n\n /**\n * Step 4: Running the setup hooks\n */\n debug('executing global hooks')\n globalHooks.apply(config)\n await globalHooks.setup(runner)\n\n /**\n * Step 5: Register suites and import test files\n */\n for (let suite of suites) {\n /**\n * Creating and configuring the suite\n */\n executionPlanState.suite = new Suite(suite.name, emitter, config.refiner)\n executionPlanState.retries = suite.retries\n executionPlanState.timeout = suite.timeout\n if (typeof suite.configure === 'function') {\n suite.configure(executionPlanState.suite)\n }\n\n /**\n * Enable bail on the suite and all the layers after the\n * suite when bailLayer is set to \"suite\"\n */\n if (cliArgs.bail && cliArgs.bailLayer === 'suite') {\n executionPlanState.suite.bail(true)\n }\n runner.add(executionPlanState.suite)\n\n /**\n * Importing suite files\n */\n for (let fileURL of suite.filesURLs) {\n executionPlanState.file = fileURLToPath(fileURL)\n debug('importing test file %s', executionPlanState.file)\n await config.importer(fileURL)\n }\n\n /**\n * Resetting global state\n */\n executionPlanState.suite = undefined\n }\n\n /**\n * Onto execution phase\n */\n executionPlanState.phase = 'executing'\n\n /**\n * Monitor for unhandled erorrs and rejections\n */\n exceptionsManager.monitor()\n\n await runner.start()\n await runner.exec()\n\n await globalHooks.teardown(null, runner)\n await runner.end()\n\n /**\n * Print unhandled errors\n */\n await exceptionsManager.report()\n\n const summary = runner.getSummary()\n if (summary.hasError || exceptionsManager.hasErrors) {\n process.exitCode = 1\n }\n if (config.forceExit) {\n process.exit()\n }\n } catch (error) {\n await globalHooks.teardown(error, runner)\n const printer = new ErrorsPrinter()\n await printer.printError(error)\n\n /**\n * Print unhandled errors in case the code inside\n * the try block never got triggered\n */\n await exceptionsManager.report()\n\n process.exitCode = 1\n if (runnerConfig!.forceExit) {\n process.exit()\n }\n }\n}\n","/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { join } from 'node:path'\nimport findCacheDirectory from 'find-cache-dir'\nimport { mkdir, readFile, unlink, writeFile } from 'node:fs/promises'\n\nimport { colors } from '../helpers.js'\nimport type { PluginFn } from '../types.js'\n\n/**\n * Paths to the cache directory and the summary file\n */\nconst CACHE_DIR = findCacheDirectory({ name: '@japa/runner' })\nconst SUMMARY_FILE = CACHE_DIR ? join(CACHE_DIR, 'summary.json') : undefined\n\n/**\n * Returns an object with the title of the tests failed during\n * the last run.\n */\nexport async function getFailedTests(): Promise<{ tests?: string[] }> {\n try {\n const summary = await readFile(SUMMARY_FILE!, 'utf-8')\n return JSON.parse(summary)\n } catch (error) {\n if (error.code === 'ENOENT') {\n return {}\n }\n throw new Error('Unable to read failed tests cache file', { cause: error })\n }\n}\n\n/**\n * Writes failing tests to the cache directory\n */\nexport async function cacheFailedTests(tests: string[]) {\n await mkdir(CACHE_DIR!, { recursive: true })\n await writeFile(SUMMARY_FILE!, JSON.stringify({ tests: tests }))\n}\n\n/**\n * Clears the cache dir\n */\nexport async function clearCache() {\n await unlink(SUMMARY_FILE!)\n}\n\n/**\n * Exposes the API to run failing tests using the \"failed\" CLI flag.\n */\nexport const retryPlugin: PluginFn = async function retry({ config, cliArgs }) {\n if (!SUMMARY_FILE) {\n return\n }\n\n config.teardown.push(async (runner) => {\n const summary = runner.getSummary()\n await cacheFailedTests(summary.failedTestsTitles)\n })\n\n if (cliArgs.failed) {\n try {\n const { tests } = await getFailedTests()\n if (!tests || !tests.length) {\n console.log(colors.bgYellow().black(' No failing tests found. Running all the tests '))\n return\n }\n config.filters.tests = tests\n } catch (error) {\n console.log(colors.bgRed().black(' Unable to read failed tests. Running all the tests '))\n console.log(colors.red(error))\n }\n }\n}\n","/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { ErrorsPrinter } from '@japa/errors-printer'\n\n/**\n * Handles uncaught exceptions and prints them to the\n * console\n */\nexport class ExceptionsManager {\n #exceptionsBuffer: any[] = []\n #rejectionsBuffer: any[] = []\n #state: 'watching' | 'reporting' = 'watching'\n #errorsPrinter = new ErrorsPrinter({ stackLinesCount: 2, framesMaxLimit: 4 })\n\n hasErrors: boolean = false\n\n /**\n * Monitors unhandled exceptions and rejections. The exceptions\n * are stacked in a buffer, so that we do not clutter the\n * tests output and once the tests are over, we will\n * print them to the console.\n *\n * In case the tests are completed, we will print errors as they\n * happen.\n */\n monitor() {\n process.on('uncaughtException', async (error) => {\n this.hasErrors = true\n if (this.#state === 'watching') {\n this.#exceptionsBuffer.push(error)\n } else {\n this.#errorsPrinter.printSectionBorder('[Unhandled Error]')\n await this.#errorsPrinter.printError(error)\n process.exitCode = 1\n }\n })\n\n process.on('unhandledRejection', async (error) => {\n this.hasErrors = true\n if (this.#state === 'watching') {\n this.#rejectionsBuffer.push(error)\n } else {\n this.#errorsPrinter.printSectionBorder('[Unhandled Rejection]')\n await this.#errorsPrinter.printError(error)\n process.exitCode = 1\n }\n })\n }\n\n async report() {\n if (this.#state === 'reporting') {\n return\n }\n\n this.#state = 'reporting'\n\n /**\n * Print exceptions\n */\n if (this.#exceptionsBuffer.length) {\n let exceptionsCount = this.#exceptionsBuffer.length\n let exceptionsIndex = this.#exceptionsBuffer.length\n this.#errorsPrinter.printSectionHeader('Unhandled Errors')\n for (let exception of this.#exceptionsBuffer) {\n await this.#errorsPrinter.printError(exception)\n this.#errorsPrinter.printSectionBorder(`[${++exceptionsIndex}/${exceptionsCount}]`)\n }\n this.#exceptionsBuffer = []\n }\n\n /**\n * Print rejections\n */\n if (this.#rejectionsBuffer.length) {\n let rejectionsCount = this.#exceptionsBuffer.length\n let rejectionsIndex = this.#exceptionsBuffer.length\n this.#errorsPrinter.printSectionBorder('Unhandled Rejections')\n for (let rejection of this.#rejectionsBuffer) {\n await this.#errorsPrinter.printError(rejection)\n this.#errorsPrinter.printSectionBorder(`[${++rejectionsIndex}/${rejectionsCount}]`)\n }\n this.#rejectionsBuffer = []\n }\n }\n}\n"],"mappings":"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","names":["ErrorsPrinter","cliArgs","ErrorsPrinter"]}
|
|
@@ -3,9 +3,17 @@ import { BaseReporter } from './reporters/base.js';
|
|
|
3
3
|
import type { DataSetNode, TestHooksCleanupHandler } from './types.js';
|
|
4
4
|
declare module '@japa/core' {
|
|
5
5
|
interface Test<Context extends Record<any, any>, TestData extends DataSetNode = undefined> {
|
|
6
|
+
/**
|
|
7
|
+
* Assert the test throws an exception with a certain error message
|
|
8
|
+
* and optionally is an instance of a given Error class.
|
|
9
|
+
*/
|
|
6
10
|
throws(message: string | RegExp, errorConstructor?: any): this;
|
|
7
11
|
}
|
|
8
12
|
interface TestContext {
|
|
13
|
+
/**
|
|
14
|
+
* Register a cleanup function that runs after the test finishes
|
|
15
|
+
* successfully or with an error.
|
|
16
|
+
*/
|
|
9
17
|
cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void;
|
|
10
18
|
}
|
|
11
19
|
}
|
|
@@ -36,9 +44,8 @@ export declare class Test<TestData extends DataSetNode = undefined> extends Base
|
|
|
36
44
|
*/
|
|
37
45
|
static executingCallbacks: never[];
|
|
38
46
|
/**
|
|
39
|
-
* Assert the test
|
|
40
|
-
*
|
|
41
|
-
* Error class.
|
|
47
|
+
* Assert the test throws an exception with a certain error message
|
|
48
|
+
* and optionally is an instance of a given Error class.
|
|
42
49
|
*/
|
|
43
50
|
throws(message: string | RegExp, errorConstructor?: any): this;
|
|
44
51
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { TestEndNode, SuiteEndNode, GroupEndNode, TestStartNode, RunnerSummary, RunnerEndNode, GroupStartNode, SuiteStartNode, RunnerStartNode, BaseReporterOptions } from '../types.js';
|
|
2
1
|
import { Emitter, Runner } from '../main.js';
|
|
2
|
+
import type { TestEndNode, SuiteEndNode, GroupEndNode, TestStartNode, RunnerSummary, RunnerEndNode, GroupStartNode, SuiteStartNode, RunnerStartNode, BaseReporterOptions } from '../types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Base reporter to build custom reporters on top of
|
|
5
5
|
*/
|
|
@@ -2,7 +2,7 @@ import type { CLIArgs, Config, NormalizedConfig } from './types.js';
|
|
|
2
2
|
export declare const NOOP: () => void;
|
|
3
3
|
/**
|
|
4
4
|
* Config manager is used to hydrate the configuration by merging
|
|
5
|
-
* the defaults
|
|
5
|
+
* the defaults with the user defined config and the command line
|
|
6
6
|
* flags.
|
|
7
7
|
*
|
|
8
8
|
* The command line flags have the upmost priority
|
package/build/src/debug.d.ts
CHANGED
package/build/src/helpers.d.ts
CHANGED
package/build/src/planner.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
dot,
|
|
3
3
|
ndjson,
|
|
4
4
|
spec
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
7
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-PLH254PF.js";
|
|
6
|
+
import "../../chunk-VDZGMJWM.js";
|
|
7
|
+
import "../../chunk-OGQDXVXY.js";
|
|
8
8
|
export {
|
|
9
9
|
dot,
|
|
10
10
|
ndjson,
|
package/build/src/types.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
1
|
import type { HookHandler } from '@poppinss/hooks/types';
|
|
3
2
|
import type { Emitter, Refiner, Runner, Suite } from '../modules/core/main.js';
|
|
4
3
|
import type { FilteringOptions, NamedReporterContract } from '../modules/core/types.js';
|
|
@@ -36,6 +35,8 @@ export type CLIArgs = {
|
|
|
36
35
|
failed?: boolean;
|
|
37
36
|
help?: boolean;
|
|
38
37
|
matchAll?: boolean;
|
|
38
|
+
bail?: boolean;
|
|
39
|
+
bailLayer?: string;
|
|
39
40
|
} & Record<string, string | string[] | boolean>;
|
|
40
41
|
/**
|
|
41
42
|
* Set of filters you can apply to run only specific tests
|
package/build/src/types.js
CHANGED
package/build/src/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/types.ts","../../modules/core/types.ts"],"sourcesContent":["/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport type { HookHandler } from '@poppinss/hooks/types'\n\nimport type { Emitter, Refiner, Runner, Suite } from '../modules/core/main.js'\nimport type { FilteringOptions, NamedReporterContract } from '../modules/core/types.js'\n\nexport * from '../modules/core/types.js'\n\n/**\n * Global setup hook\n */\nexport type SetupHookState = [[runner: Runner], [error: Error | null, runner: Runner]]\nexport type SetupHookHandler = HookHandler<SetupHookState[0], SetupHookState[1]>\n\n/**\n * Global teardown hook\n */\nexport type TeardownHookState = [[runner: Runner], [error: Error | null, runner: Runner]]\nexport type TeardownHookHandler = HookHandler<TeardownHookState[0], TeardownHookState[1]>\n\n/**\n * Global set of available hooks\n */\nexport type HooksEvents = {\n setup: SetupHookState\n teardown: TeardownHookState\n}\n\n/**\n * Parsed command-line arguments\n */\nexport type CLIArgs = {\n _?: string[]\n tags?: string | string[]\n files?: string | string[]\n tests?: string | string[]\n groups?: string | string[]\n timeout?: string\n retries?: string\n reporters?: string | string[]\n forceExit?: boolean\n failed?: boolean\n help?: boolean\n matchAll?: boolean\n} & Record<string, string | string[] | boolean>\n\n/**\n * Set of filters you can apply to run only specific tests\n */\nexport type Filters = FilteringOptions & {\n files?: string[]\n suites?: string[]\n}\n\n/**\n * Plugin function receives an instance of the runner,\n * emitter, config and the hooks\n */\nexport type PluginFn = (japa: {\n config: NormalizedConfig\n cliArgs: CLIArgs\n runner: Runner\n emitter: Emitter\n}) => void | Promise<void>\n\n/**\n * Base configuration options\n */\nexport type BaseConfig = {\n /**\n * Current working directory. It is required to search for\n * the test files\n */\n cwd?: string\n\n /**\n * The timeout to apply on all the tests, unless overwritten explicitly\n */\n timeout?: number\n\n /**\n * The retries to apply on all the tests, unless overwritten explicitly\n */\n retries?: number\n\n /**\n * Test filters to apply\n */\n filters?: Filters\n\n /**\n * A hook to configure suites. The callback will be called for each\n * suite before it gets executed.\n */\n configureSuite?: (suite: Suite) => void\n\n /**\n * A collection of registered reporters. Reporters are not activated by\n * default. Either you have to activate them using the commandline,\n * or using the `activated` property.\n */\n reporters?: {\n activated: string[]\n list?: NamedReporterContract[]\n }\n\n /**\n * A collection of registered plugins\n */\n plugins?: PluginFn[]\n\n /**\n * A custom implementation to import test files.\n */\n importer?: (filePath: URL) => void | Promise<void>\n\n /**\n * Overwrite tests refiner. Check documentation for refiner\n * usage\n */\n refiner?: Refiner\n\n /**\n * Enable/disable force exiting.\n */\n forceExit?: boolean\n\n /**\n * Global hooks to execute before importing\n * the test files\n */\n setup?: SetupHookHandler[]\n\n /**\n * Global hooks to execute on teardown\n */\n teardown?: TeardownHookHandler[]\n\n /**\n * An array of directories to exclude when searching\n * for test files.\n *\n * For example, if you search for test files inside the entire\n * project, you might want to exclude \"node_modules\"\n */\n exclude?: string[]\n}\n\n/**\n * A collection of test files defined as a glob or a callback\n * function that returns an array of URLs\n */\nexport type TestFiles = string | string[] | (() => URL[] | Promise<URL[]>)\n\n/**\n * A test suite to register tests under a named suite\n */\nexport type TestSuite = {\n /**\n * A unique name for the suite\n */\n name: string\n\n /**\n * Collection of files associated with the suite. Files should be\n * defined as a glob or a callback function that returns an array of URLs\n */\n files: TestFiles\n\n /**\n * A callback functon to configure the suite. The callback is invoked only\n * when the runner is going to run the tests for the given suite.\n */\n configure?: (suite: Suite) => void\n\n /**\n * The timeout to apply on all the tests in this suite, unless overwritten explicitly\n */\n timeout?: number\n\n /**\n * The retries to apply on all the tests in this suite, unless overwritten explicitly\n */\n retries?: number\n}\n\n/**\n * BaseConfig after normalized by the config manager\n */\nexport type NormalizedBaseConfig = Required<Omit<BaseConfig, 'reporters'>> & {\n reporters: {\n activated: string[]\n list: NamedReporterContract[]\n }\n}\n\n/**\n * Configuration options\n */\nexport type Config = BaseConfig &\n (\n | {\n files: TestFiles\n }\n | {\n suites: TestSuite[]\n }\n )\n\n/**\n * Config after normalized by the config manager\n */\nexport type NormalizedConfig = NormalizedBaseConfig &\n (\n | {\n files: TestFiles\n }\n | {\n suites: Required<TestSuite>[]\n }\n )\n","/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nexport * from '@japa/core/types'\n\nexport type BaseReporterOptions = {\n
|
|
1
|
+
{"version":3,"sources":["../../src/types.ts","../../modules/core/types.ts"],"sourcesContent":["/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport type { HookHandler } from '@poppinss/hooks/types'\n\nimport type { Emitter, Refiner, Runner, Suite } from '../modules/core/main.js'\nimport type { FilteringOptions, NamedReporterContract } from '../modules/core/types.js'\n\nexport * from '../modules/core/types.js'\n\n/**\n * Global setup hook\n */\nexport type SetupHookState = [[runner: Runner], [error: Error | null, runner: Runner]]\nexport type SetupHookHandler = HookHandler<SetupHookState[0], SetupHookState[1]>\n\n/**\n * Global teardown hook\n */\nexport type TeardownHookState = [[runner: Runner], [error: Error | null, runner: Runner]]\nexport type TeardownHookHandler = HookHandler<TeardownHookState[0], TeardownHookState[1]>\n\n/**\n * Global set of available hooks\n */\nexport type HooksEvents = {\n setup: SetupHookState\n teardown: TeardownHookState\n}\n\n/**\n * Parsed command-line arguments\n */\nexport type CLIArgs = {\n _?: string[]\n tags?: string | string[]\n files?: string | string[]\n tests?: string | string[]\n groups?: string | string[]\n timeout?: string\n retries?: string\n reporters?: string | string[]\n forceExit?: boolean\n failed?: boolean\n help?: boolean\n matchAll?: boolean\n bail?: boolean\n bailLayer?: string\n} & Record<string, string | string[] | boolean>\n\n/**\n * Set of filters you can apply to run only specific tests\n */\nexport type Filters = FilteringOptions & {\n files?: string[]\n suites?: string[]\n}\n\n/**\n * Plugin function receives an instance of the runner,\n * emitter, config and the hooks\n */\nexport type PluginFn = (japa: {\n config: NormalizedConfig\n cliArgs: CLIArgs\n runner: Runner\n emitter: Emitter\n}) => void | Promise<void>\n\n/**\n * Base configuration options\n */\nexport type BaseConfig = {\n /**\n * Current working directory. It is required to search for\n * the test files\n */\n cwd?: string\n\n /**\n * The timeout to apply on all the tests, unless overwritten explicitly\n */\n timeout?: number\n\n /**\n * The retries to apply on all the tests, unless overwritten explicitly\n */\n retries?: number\n\n /**\n * Test filters to apply\n */\n filters?: Filters\n\n /**\n * A hook to configure suites. The callback will be called for each\n * suite before it gets executed.\n */\n configureSuite?: (suite: Suite) => void\n\n /**\n * A collection of registered reporters. Reporters are not activated by\n * default. Either you have to activate them using the commandline,\n * or using the `activated` property.\n */\n reporters?: {\n activated: string[]\n list?: NamedReporterContract[]\n }\n\n /**\n * A collection of registered plugins\n */\n plugins?: PluginFn[]\n\n /**\n * A custom implementation to import test files.\n */\n importer?: (filePath: URL) => void | Promise<void>\n\n /**\n * Overwrite tests refiner. Check documentation for refiner\n * usage\n */\n refiner?: Refiner\n\n /**\n * Enable/disable force exiting.\n */\n forceExit?: boolean\n\n /**\n * Global hooks to execute before importing\n * the test files\n */\n setup?: SetupHookHandler[]\n\n /**\n * Global hooks to execute on teardown\n */\n teardown?: TeardownHookHandler[]\n\n /**\n * An array of directories to exclude when searching\n * for test files.\n *\n * For example, if you search for test files inside the entire\n * project, you might want to exclude \"node_modules\"\n */\n exclude?: string[]\n}\n\n/**\n * A collection of test files defined as a glob or a callback\n * function that returns an array of URLs\n */\nexport type TestFiles = string | string[] | (() => URL[] | Promise<URL[]>)\n\n/**\n * A test suite to register tests under a named suite\n */\nexport type TestSuite = {\n /**\n * A unique name for the suite\n */\n name: string\n\n /**\n * Collection of files associated with the suite. Files should be\n * defined as a glob or a callback function that returns an array of URLs\n */\n files: TestFiles\n\n /**\n * A callback functon to configure the suite. The callback is invoked only\n * when the runner is going to run the tests for the given suite.\n */\n configure?: (suite: Suite) => void\n\n /**\n * The timeout to apply on all the tests in this suite, unless overwritten explicitly\n */\n timeout?: number\n\n /**\n * The retries to apply on all the tests in this suite, unless overwritten explicitly\n */\n retries?: number\n}\n\n/**\n * BaseConfig after normalized by the config manager\n */\nexport type NormalizedBaseConfig = Required<Omit<BaseConfig, 'reporters'>> & {\n reporters: {\n activated: string[]\n list: NamedReporterContract[]\n }\n}\n\n/**\n * Configuration options\n */\nexport type Config = BaseConfig &\n (\n | {\n files: TestFiles\n }\n | {\n suites: TestSuite[]\n }\n )\n\n/**\n * Config after normalized by the config manager\n */\nexport type NormalizedConfig = NormalizedBaseConfig &\n (\n | {\n files: TestFiles\n }\n | {\n suites: Required<TestSuite>[]\n }\n )\n","/*\n * @japa/runner\n *\n * (c) Japa\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nexport * from '@japa/core/types'\n\nexport type BaseReporterOptions = {\n framesMaxLimit?: number\n}\n"],"mappings":";;;;;AAAA,IAAAA,iBAAA;;;ACAA;AASA;AAAA,4BAAc;;;ADKd,WAAAC,gBAAc;","names":["types_exports","types_exports"]}
|