@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.
Files changed (35) hide show
  1. package/README.md +8 -4
  2. package/build/{chunk-OBDV3O36.js → chunk-OGQDXVXY.js} +1 -1
  3. package/build/{chunk-LRVNUQHW.js → chunk-PLH254PF.js} +24 -42
  4. package/build/chunk-PLH254PF.js.map +1 -0
  5. package/build/{chunk-PKOB3ULJ.js → chunk-VDZGMJWM.js} +45 -19
  6. package/build/chunk-VDZGMJWM.js.map +1 -0
  7. package/build/{chunk-CYPN7IGE.js → chunk-ZBQV333W.js} +17 -8
  8. package/build/chunk-ZBQV333W.js.map +1 -0
  9. package/build/factories/{create_diverse_tests.d.ts → create_dummy_tests.d.ts} +1 -1
  10. package/build/factories/main.d.ts +1 -1
  11. package/build/factories/main.js +28 -8
  12. package/build/factories/main.js.map +1 -1
  13. package/build/factories/runner.d.ts +4 -0
  14. package/build/index.d.ts +3 -0
  15. package/build/index.js +29 -13
  16. package/build/index.js.map +1 -1
  17. package/build/modules/core/main.d.ts +10 -3
  18. package/build/modules/core/main.js +2 -2
  19. package/build/modules/core/reporters/base.d.ts +1 -1
  20. package/build/modules/core/types.d.ts +0 -1
  21. package/build/src/config_manager.d.ts +1 -1
  22. package/build/src/debug.d.ts +0 -1
  23. package/build/src/exceptions_manager.d.ts +1 -1
  24. package/build/src/files_manager.d.ts +0 -1
  25. package/build/src/helpers.d.ts +1 -0
  26. package/build/src/planner.d.ts +0 -1
  27. package/build/src/reporters/main.js +3 -3
  28. package/build/src/types.d.ts +2 -1
  29. package/build/src/types.js +1 -1
  30. package/build/src/types.js.map +1 -1
  31. package/package.json +75 -72
  32. package/build/chunk-CYPN7IGE.js.map +0 -1
  33. package/build/chunk-LRVNUQHW.js.map +0 -1
  34. package/build/chunk-PKOB3ULJ.js.map +0 -1
  35. /package/build/{chunk-OBDV3O36.js.map → chunk-OGQDXVXY.js.map} +0 -0
@@ -5,14 +5,14 @@ import {
5
5
  Planner,
6
6
  createTest,
7
7
  createTestGroup
8
- } from "../chunk-CYPN7IGE.js";
9
- import "../chunk-LRVNUQHW.js";
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-PKOB3ULJ.js";
15
- import "../chunk-OBDV3O36.js";
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/create_diverse_tests.ts
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 createDiverseTests(emitter, refiner, file) {
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
- createDiverseTests,
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-CYPN7IGE.js";
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
- } from "./chunk-PKOB3ULJ.js";
19
- import "./chunk-OBDV3O36.js";
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 flow() {
109
- if (this.#state === "flowing") {
107
+ async report() {
108
+ if (this.#state === "reporting") {
110
109
  return;
111
110
  }
112
- this.#state = "flowing";
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.flow();
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.flow();
257
+ await exceptionsManager.report();
242
258
  process.exitCode = 1;
243
259
  if (runnerConfig.forceExit) {
244
260
  process.exit();
@@ -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 callback throws an exception when a certain
40
- * error message and optionally is an instance of a given
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
  }
@@ -7,8 +7,8 @@ import {
7
7
  Suite,
8
8
  Test,
9
9
  TestContext
10
- } from "../../chunk-PKOB3ULJ.js";
11
- import "../../chunk-OBDV3O36.js";
10
+ } from "../../chunk-VDZGMJWM.js";
11
+ import "../../chunk-OGQDXVXY.js";
12
12
  export {
13
13
  BaseReporter,
14
14
  Emitter,
@@ -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
  */
@@ -1,5 +1,4 @@
1
1
  export * from '@japa/core/types';
2
2
  export type BaseReporterOptions = {
3
- stackLinesCount?: number;
4
3
  framesMaxLimit?: number;
5
4
  };
@@ -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, user defined config and the command line
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
@@ -1,3 +1,2 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  declare const _default: import("util").DebugLogger;
3
2
  export default _default;
@@ -15,5 +15,5 @@ export declare class ExceptionsManager {
15
15
  * happen.
16
16
  */
17
17
  monitor(): void;
18
- flow(): Promise<void>;
18
+ report(): Promise<void>;
19
19
  }
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import type { TestFiles } from './types.js';
3
2
  /**
4
3
  * Files manager exposes the API to collect, filter and import test
@@ -11,5 +11,6 @@ export declare const icons: {
11
11
  pointer: string;
12
12
  info: string;
13
13
  warning: string;
14
+ branch: string;
14
15
  squareSmallFilled: string;
15
16
  };
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import type { NamedReporterContract, NormalizedConfig, TestSuite } from './types.js';
3
2
  /**
4
3
  * The tests planner is used to plan the tests by doing all
@@ -2,9 +2,9 @@ import {
2
2
  dot,
3
3
  ndjson,
4
4
  spec
5
- } from "../../chunk-LRVNUQHW.js";
6
- import "../../chunk-PKOB3ULJ.js";
7
- import "../../chunk-OBDV3O36.js";
5
+ } from "../../chunk-PLH254PF.js";
6
+ import "../../chunk-VDZGMJWM.js";
7
+ import "../../chunk-OGQDXVXY.js";
8
8
  export {
9
9
  dot,
10
10
  ndjson,
@@ -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
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  __reExport
3
- } from "../chunk-OBDV3O36.js";
3
+ } from "../chunk-OGQDXVXY.js";
4
4
 
5
5
  // src/types.ts
6
6
  var types_exports2 = {};
@@ -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 stackLinesCount?: number\n framesMaxLimit?: number\n}\n"],"mappings":";;;;;AAAA,IAAAA,iBAAA;;;ACAA;AASA;AAAA,4BAAc;;;ADKd,WAAAC,gBAAc;","names":["types_exports","types_exports"]}
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"]}