@japa/runner 4.3.1 → 4.4.1

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/build/index.js CHANGED
@@ -1,284 +1,238 @@
1
- import {
2
- CliParser,
3
- ConfigManager,
4
- GlobalHooks,
5
- Planner,
6
- createTest,
7
- createTestGroup,
8
- debug_default,
9
- validator_default
10
- } from "./chunk-Y57JXJ7G.js";
11
- import "./chunk-U3BSXCEH.js";
12
- import {
13
- Emitter,
14
- Runner,
15
- Suite,
16
- colors
17
- } from "./chunk-PCBL2VZP.js";
18
- import "./chunk-2KG3PWR4.js";
19
-
20
- // index.ts
21
- import { fileURLToPath } from "url";
22
- import { ErrorsPrinter as ErrorsPrinter2 } from "@japa/errors-printer";
23
-
24
- // src/plugins/retry.ts
25
- import { join } from "path";
1
+ import { a as GlobalHooks, c as debug_default, i as CliParser, n as createTestGroup, o as Planner, r as ConfigManager, s as validator_default, t as createTest } from "./create_test-CuTGNCAf.js";
2
+ import { c as Suite, i as Emitter, r as printPinnedTests, s as Runner, t as colors } from "./helpers-BlHaYYTh.js";
3
+ import "./main-CB1nhl6c.js";
4
+ import { fileURLToPath } from "node:url";
5
+ import { ErrorsPrinter } from "@japa/errors-printer";
6
+ import { join } from "node:path";
7
+ import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
26
8
  import findCacheDirectory from "find-cache-directory";
27
- import { mkdir, readFile, unlink, writeFile } from "fs/promises";
28
- var CACHE_DIR = findCacheDirectory({ name: "@japa/runner" });
29
- var SUMMARY_FILE = CACHE_DIR ? join(CACHE_DIR, "summary.json") : void 0;
9
+ const CACHE_DIR = findCacheDirectory({ name: "@japa/runner" });
10
+ const SUMMARY_FILE = CACHE_DIR ? join(CACHE_DIR, "summary.json") : void 0;
30
11
  async function getFailedTests() {
31
- try {
32
- const summary = await readFile(SUMMARY_FILE, "utf-8");
33
- return JSON.parse(summary);
34
- } catch (error) {
35
- if (error.code === "ENOENT") {
36
- return {};
37
- }
38
- throw new Error("Unable to read failed tests cache file", { cause: error });
39
- }
12
+ try {
13
+ const summary = await readFile(SUMMARY_FILE, "utf-8");
14
+ return JSON.parse(summary);
15
+ } catch (error) {
16
+ if (error.code === "ENOENT") return {};
17
+ throw new Error("Unable to read failed tests cache file", { cause: error });
18
+ }
40
19
  }
41
20
  async function cacheFailedTests(tests) {
42
- await mkdir(CACHE_DIR, { recursive: true });
43
- await writeFile(SUMMARY_FILE, JSON.stringify({ tests }));
21
+ await mkdir(CACHE_DIR, { recursive: true });
22
+ await writeFile(SUMMARY_FILE, JSON.stringify({ tests }));
44
23
  }
45
- var retryPlugin = async function retry({ config, cliArgs: cliArgs2 }) {
46
- if (!SUMMARY_FILE) {
47
- return;
48
- }
49
- config.teardown.push(async (runner) => {
50
- const summary = runner.getSummary();
51
- await cacheFailedTests(summary.failedTestsTitles);
52
- });
53
- if (cliArgs2.failed) {
54
- try {
55
- const { tests } = await getFailedTests();
56
- if (!tests || !tests.length) {
57
- console.log(colors.bgYellow().black(" No failing tests found. Running all the tests "));
58
- return;
59
- }
60
- config.filters.tests = tests;
61
- } catch (error) {
62
- console.log(colors.bgRed().black(" Unable to read failed tests. Running all the tests "));
63
- console.log(colors.red(error));
64
- }
65
- }
24
+ const retryPlugin = async function retry({ config, cliArgs: cliArgs$1 }) {
25
+ if (!SUMMARY_FILE) return;
26
+ config.teardown.push(async (runner) => {
27
+ await cacheFailedTests(runner.getSummary().failedTestsTitles);
28
+ });
29
+ if (cliArgs$1.failed) try {
30
+ const { tests } = await getFailedTests();
31
+ if (!tests || !tests.length) {
32
+ console.log(colors.bgYellow().black(" No failing tests found. Running all the tests "));
33
+ return;
34
+ }
35
+ config.filters.tests = tests;
36
+ } catch (error) {
37
+ console.log(colors.bgRed().black(" Unable to read failed tests. Running all the tests "));
38
+ console.log(colors.red(error));
39
+ }
66
40
  };
67
-
68
- // src/exceptions_manager.ts
69
- import { ErrorsPrinter } from "@japa/errors-printer";
70
41
  var ExceptionsManager = class {
71
- #exceptionsBuffer = [];
72
- #rejectionsBuffer = [];
73
- #state = "watching";
74
- #errorsPrinter = new ErrorsPrinter({ stackLinesCount: 2, framesMaxLimit: 4 });
75
- hasErrors = false;
76
- /**
77
- * Monitors unhandled exceptions and rejections. The exceptions
78
- * are stacked in a buffer, so that we do not clutter the
79
- * tests output and once the tests are over, we will
80
- * print them to the console.
81
- *
82
- * In case the tests are completed, we will print errors as they
83
- * happen.
84
- */
85
- monitor() {
86
- process.on("uncaughtException", async (error) => {
87
- debug_default("received uncaught exception %O", error);
88
- this.hasErrors = true;
89
- if (this.#state === "watching") {
90
- this.#exceptionsBuffer.push(error);
91
- } else {
92
- this.#errorsPrinter.printSectionBorder("[Unhandled Error]");
93
- await this.#errorsPrinter.printError(error);
94
- process.exitCode = 1;
95
- }
96
- });
97
- process.on("unhandledRejection", async (error) => {
98
- debug_default("received unhandled rejection %O", error);
99
- this.hasErrors = true;
100
- if (this.#state === "watching") {
101
- this.#rejectionsBuffer.push(error);
102
- } else {
103
- this.#errorsPrinter.printSectionBorder("[Unhandled Rejection]");
104
- await this.#errorsPrinter.printError(error);
105
- process.exitCode = 1;
106
- }
107
- });
108
- }
109
- async report() {
110
- if (this.#state === "reporting") {
111
- return;
112
- }
113
- this.#state = "reporting";
114
- if (this.#exceptionsBuffer.length) {
115
- let exceptionsCount = this.#exceptionsBuffer.length;
116
- let exceptionsIndex = this.#exceptionsBuffer.length;
117
- this.#errorsPrinter.printSectionHeader("Unhandled Errors");
118
- for (let exception of this.#exceptionsBuffer) {
119
- await this.#errorsPrinter.printError(exception);
120
- this.#errorsPrinter.printSectionBorder(`[${++exceptionsIndex}/${exceptionsCount}]`);
121
- }
122
- this.#exceptionsBuffer = [];
123
- }
124
- if (this.#rejectionsBuffer.length) {
125
- let rejectionsCount = this.#exceptionsBuffer.length;
126
- let rejectionsIndex = this.#exceptionsBuffer.length;
127
- this.#errorsPrinter.printSectionBorder("Unhandled Rejections");
128
- for (let rejection of this.#rejectionsBuffer) {
129
- await this.#errorsPrinter.printError(rejection);
130
- this.#errorsPrinter.printSectionBorder(`[${++rejectionsIndex}/${rejectionsCount}]`);
131
- }
132
- this.#rejectionsBuffer = [];
133
- }
134
- }
135
- };
136
-
137
- // index.ts
138
- var emitter = new Emitter();
139
- var activeTest;
140
- var cliArgs = {};
141
- var runnerConfig;
142
- var executionPlanState = {
143
- phase: "idle"
42
+ #exceptionsBuffer = [];
43
+ #rejectionsBuffer = [];
44
+ #state = "watching";
45
+ #errorsPrinter = new ErrorsPrinter({
46
+ stackLinesCount: 2,
47
+ framesMaxLimit: 4
48
+ });
49
+ hasErrors = false;
50
+ monitor() {
51
+ process.on("uncaughtException", async (error) => {
52
+ debug_default("received uncaught exception %O", error);
53
+ this.hasErrors = true;
54
+ if (this.#state === "watching") this.#exceptionsBuffer.push(error);
55
+ else {
56
+ this.#errorsPrinter.printSectionBorder("[Unhandled Error]");
57
+ await this.#errorsPrinter.printError(error);
58
+ process.exitCode = 1;
59
+ }
60
+ });
61
+ process.on("unhandledRejection", async (error) => {
62
+ debug_default("received unhandled rejection %O", error);
63
+ this.hasErrors = true;
64
+ if (this.#state === "watching") this.#rejectionsBuffer.push(error);
65
+ else {
66
+ this.#errorsPrinter.printSectionBorder("[Unhandled Rejection]");
67
+ await this.#errorsPrinter.printError(error);
68
+ process.exitCode = 1;
69
+ }
70
+ });
71
+ }
72
+ async report() {
73
+ if (this.#state === "reporting") return;
74
+ this.#state = "reporting";
75
+ if (this.#exceptionsBuffer.length) {
76
+ let exceptionsCount = this.#exceptionsBuffer.length;
77
+ let exceptionsIndex = this.#exceptionsBuffer.length;
78
+ this.#errorsPrinter.printSectionHeader("Unhandled Errors");
79
+ for (let exception of this.#exceptionsBuffer) {
80
+ await this.#errorsPrinter.printError(exception);
81
+ this.#errorsPrinter.printSectionBorder(`[${++exceptionsIndex}/${exceptionsCount}]`);
82
+ }
83
+ this.#exceptionsBuffer = [];
84
+ }
85
+ if (this.#rejectionsBuffer.length) {
86
+ let rejectionsCount = this.#exceptionsBuffer.length;
87
+ let rejectionsIndex = this.#exceptionsBuffer.length;
88
+ this.#errorsPrinter.printSectionBorder("Unhandled Rejections");
89
+ for (let rejection of this.#rejectionsBuffer) {
90
+ await this.#errorsPrinter.printError(rejection);
91
+ this.#errorsPrinter.printSectionBorder(`[${++rejectionsIndex}/${rejectionsCount}]`);
92
+ }
93
+ this.#rejectionsBuffer = [];
94
+ }
95
+ }
144
96
  };
97
+ const emitter = new Emitter();
98
+ let activeTest;
99
+ let cliArgs = {};
100
+ let runnerConfig;
101
+ const executionPlanState = { phase: "idle" };
145
102
  function test(title, callback) {
146
- validator_default.ensureIsInPlanningPhase(executionPlanState.phase);
147
- const testInstance = createTest(title, emitter, runnerConfig.refiner, executionPlanState);
148
- testInstance.setup((t) => {
149
- activeTest = t;
150
- return () => {
151
- activeTest = void 0;
152
- };
153
- });
154
- if (callback) {
155
- testInstance.run(callback, new Error());
156
- }
157
- return testInstance;
103
+ validator_default.ensureIsInPlanningPhase(executionPlanState.phase);
104
+ const debuggingError = /* @__PURE__ */ new Error();
105
+ const testInstance = createTest(title, emitter, runnerConfig.refiner, debuggingError, executionPlanState);
106
+ testInstance.setup((t) => {
107
+ activeTest = t;
108
+ return () => {
109
+ activeTest = void 0;
110
+ };
111
+ });
112
+ if (callback) testInstance.run(callback, debuggingError);
113
+ return testInstance;
158
114
  }
159
115
  test.group = function(title, callback) {
160
- validator_default.ensureIsInPlanningPhase(executionPlanState.phase);
161
- const group = createTestGroup(title, emitter, runnerConfig.refiner, executionPlanState);
162
- executionPlanState.group = group;
163
- if (cliArgs.bail && cliArgs.bailLayer === "group") {
164
- executionPlanState.group.bail(true);
165
- }
166
- callback(executionPlanState.group);
167
- executionPlanState.group = void 0;
168
- return group;
116
+ validator_default.ensureIsInPlanningPhase(executionPlanState.phase);
117
+ const group = createTestGroup(title, emitter, runnerConfig.refiner, executionPlanState);
118
+ executionPlanState.group = group;
119
+ if (cliArgs.bail && cliArgs.bailLayer === "group") executionPlanState.group.bail(true);
120
+ callback(executionPlanState.group);
121
+ executionPlanState.group = void 0;
122
+ return group;
169
123
  };
170
124
  test.macro = function(callback) {
171
- return (...args) => {
172
- if (!activeTest) {
173
- throw new Error("Cannot invoke macro outside of the test callback");
174
- }
175
- return callback(activeTest, ...args);
176
- };
125
+ return (...args) => {
126
+ if (!activeTest) throw new Error("Cannot invoke macro outside of the test callback");
127
+ return callback(activeTest, ...args);
128
+ };
177
129
  };
178
130
  function getActiveTest() {
179
- return activeTest;
131
+ return activeTest;
180
132
  }
181
133
  function getActiveTestOrFail() {
182
- if (!activeTest) throw new Error("Cannot access active test outside of a test callback");
183
- return activeTest;
134
+ if (!activeTest) throw new Error("Cannot access active test outside of a test callback");
135
+ return activeTest;
184
136
  }
185
137
  function processCLIArgs(argv) {
186
- cliArgs = new CliParser().parse(argv);
138
+ cliArgs = new CliParser().parse(argv);
187
139
  }
188
140
  function configure(options) {
189
- runnerConfig = new ConfigManager(options, cliArgs).hydrate();
141
+ runnerConfig = new ConfigManager(options, cliArgs).hydrate();
190
142
  }
191
143
  async function run() {
192
- if (cliArgs.help) {
193
- console.log(new CliParser().getHelp());
194
- return;
195
- }
196
- validator_default.ensureIsConfigured(runnerConfig);
197
- executionPlanState.phase = "planning";
198
- const runner = new Runner(emitter);
199
- if (cliArgs.bail && cliArgs.bailLayer === "") {
200
- runner.bail(true);
201
- }
202
- const globalHooks = new GlobalHooks();
203
- const exceptionsManager = new ExceptionsManager();
204
- try {
205
- await retryPlugin({ config: runnerConfig, runner, emitter, cliArgs });
206
- for (let plugin of runnerConfig.plugins) {
207
- debug_default('executing "%s" plugin', plugin.name || "anonymous");
208
- await plugin({ runner, emitter, cliArgs, config: runnerConfig });
209
- }
210
- const { config, reporters, suites, refinerFilters } = await new Planner(runnerConfig).plan();
211
- reporters.forEach((reporter) => {
212
- debug_default('registering "%s" reporter', reporter.name);
213
- runner.registerReporter(reporter);
214
- });
215
- refinerFilters.forEach((filter) => {
216
- debug_default('apply %s filters "%O" ', filter.layer, filter.filters);
217
- config.refiner.add(filter.layer, filter.filters);
218
- });
219
- config.refiner.matchAllTags(cliArgs.matchAll ?? false);
220
- runner.onSuite(config.configureSuite);
221
- debug_default("executing global hooks");
222
- globalHooks.apply(config);
223
- await globalHooks.setup(runner);
224
- for (let suite of suites) {
225
- debug_default("initiating suite %s", suite.name);
226
- executionPlanState.suite = new Suite(suite.name, emitter, config.refiner);
227
- executionPlanState.retries = suite.retries;
228
- executionPlanState.timeout = suite.timeout;
229
- if (typeof suite.configure === "function") {
230
- suite.configure(executionPlanState.suite);
231
- }
232
- if (cliArgs.bail && cliArgs.bailLayer === "suite") {
233
- debug_default("enabling bail mode for the suite %s", suite.name);
234
- executionPlanState.suite.bail(true);
235
- }
236
- runner.add(executionPlanState.suite);
237
- for (let fileURL of suite.filesURLs) {
238
- executionPlanState.file = fileURLToPath(fileURL);
239
- debug_default("importing test file %s", executionPlanState.file);
240
- await config.importer(fileURL);
241
- }
242
- executionPlanState.suite = void 0;
243
- }
244
- executionPlanState.phase = "executing";
245
- exceptionsManager.monitor();
246
- await runner.start();
247
- await runner.exec();
248
- await globalHooks.teardown(null, runner);
249
- await runner.end();
250
- await exceptionsManager.report();
251
- const summary = runner.getSummary();
252
- if (summary.hasError || exceptionsManager.hasErrors) {
253
- debug_default(
254
- "updating exit code to 1. summary.hasError %s, process.hasError",
255
- summary.hasError,
256
- exceptionsManager.hasErrors
257
- );
258
- process.exitCode = 1;
259
- }
260
- if (config.forceExit) {
261
- debug_default("force exiting process");
262
- process.exit();
263
- }
264
- } catch (error) {
265
- debug_default("error running tests %O", error);
266
- await globalHooks.teardown(error, runner);
267
- const printer = new ErrorsPrinter2();
268
- await printer.printError(error);
269
- await exceptionsManager.report();
270
- process.exitCode = 1;
271
- if (runnerConfig.forceExit) {
272
- debug_default("force exiting process");
273
- process.exit();
274
- }
275
- }
144
+ if (cliArgs.help) {
145
+ console.log(new CliParser().getHelp());
146
+ return;
147
+ }
148
+ validator_default.ensureIsConfigured(runnerConfig);
149
+ executionPlanState.phase = "planning";
150
+ const runner = new Runner(emitter);
151
+ if (cliArgs.bail && cliArgs.bailLayer === "") runner.bail(true);
152
+ const globalHooks = new GlobalHooks();
153
+ const exceptionsManager = new ExceptionsManager();
154
+ try {
155
+ await retryPlugin({
156
+ config: runnerConfig,
157
+ runner,
158
+ emitter,
159
+ cliArgs
160
+ });
161
+ for (let plugin of runnerConfig.plugins) {
162
+ debug_default("executing \"%s\" plugin", plugin.name || "anonymous");
163
+ await plugin({
164
+ runner,
165
+ emitter,
166
+ cliArgs,
167
+ config: runnerConfig
168
+ });
169
+ }
170
+ const { config, reporters, suites, refinerFilters } = await new Planner(runnerConfig).plan();
171
+ reporters.forEach((reporter) => {
172
+ debug_default("registering \"%s\" reporter", reporter.name);
173
+ runner.registerReporter(reporter);
174
+ });
175
+ refinerFilters.forEach((filter) => {
176
+ debug_default("apply %s filters \"%O\" ", filter.layer, filter.filters);
177
+ config.refiner.add(filter.layer, filter.filters);
178
+ });
179
+ config.refiner.matchAllTags(cliArgs.matchAll ?? false);
180
+ runner.onSuite(config.configureSuite);
181
+ debug_default("executing global hooks");
182
+ globalHooks.apply(config);
183
+ if (!cliArgs.listPinned) await globalHooks.setup(runner);
184
+ for (let suite of suites) {
185
+ debug_default("initiating suite %s", suite.name);
186
+ executionPlanState.suite = new Suite(suite.name, emitter, config.refiner);
187
+ executionPlanState.retries = suite.retries;
188
+ executionPlanState.timeout = suite.timeout;
189
+ if (typeof suite.configure === "function") suite.configure(executionPlanState.suite);
190
+ if (cliArgs.bail && cliArgs.bailLayer === "suite") {
191
+ debug_default("enabling bail mode for the suite %s", suite.name);
192
+ executionPlanState.suite.bail(true);
193
+ }
194
+ runner.add(executionPlanState.suite);
195
+ for (let fileURL of suite.filesURLs) {
196
+ executionPlanState.file = fileURLToPath(fileURL);
197
+ debug_default("importing test file %s", executionPlanState.file);
198
+ await config.importer(fileURL);
199
+ }
200
+ executionPlanState.suite = void 0;
201
+ }
202
+ if (cliArgs.listPinned) {
203
+ printPinnedTests(runner);
204
+ if (config.forceExit) {
205
+ debug_default("force exiting process");
206
+ process.exit();
207
+ }
208
+ return;
209
+ }
210
+ executionPlanState.phase = "executing";
211
+ exceptionsManager.monitor();
212
+ await runner.start();
213
+ await runner.exec();
214
+ await globalHooks.teardown(null, runner);
215
+ await runner.end();
216
+ await exceptionsManager.report();
217
+ const summary = runner.getSummary();
218
+ if (summary.hasError || exceptionsManager.hasErrors) {
219
+ debug_default("updating exit code to 1. summary.hasError %s, process.hasError", summary.hasError, exceptionsManager.hasErrors);
220
+ process.exitCode = 1;
221
+ }
222
+ if (config.forceExit) {
223
+ debug_default("force exiting process");
224
+ process.exit();
225
+ }
226
+ } catch (error) {
227
+ debug_default("error running tests %O", error);
228
+ await globalHooks.teardown(error, runner);
229
+ await new ErrorsPrinter().printError(error);
230
+ await exceptionsManager.report();
231
+ process.exitCode = 1;
232
+ if (runnerConfig.forceExit) {
233
+ debug_default("force exiting process");
234
+ process.exit();
235
+ }
236
+ }
276
237
  }
277
- export {
278
- configure,
279
- getActiveTest,
280
- getActiveTestOrFail,
281
- processCLIArgs,
282
- run,
283
- test
284
- };
238
+ export { configure, getActiveTest, getActiveTestOrFail, processCLIArgs, run, test };