@japa/runner 3.0.0-8 → 3.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 (52) hide show
  1. package/build/factories/create_diverse_tests.d.ts +6 -0
  2. package/build/factories/create_diverse_tests.js +106 -0
  3. package/build/factories/main.d.ts +5 -42
  4. package/build/factories/main.js +24 -208
  5. package/build/factories/runner.d.ts +26 -0
  6. package/build/factories/runner.js +93 -0
  7. package/build/index.d.ts +9 -14
  8. package/build/index.js +202 -237
  9. package/build/modules/core/main.d.ts +63 -3
  10. package/build/modules/core/main.js +121 -21
  11. package/build/modules/core/reporters/base.d.ts +41 -0
  12. package/build/modules/core/reporters/base.js +183 -0
  13. package/build/modules/core/types.d.ts +5 -0
  14. package/build/modules/core/types.js +9 -0
  15. package/build/src/cli_parser.d.ts +14 -0
  16. package/build/src/cli_parser.js +75 -0
  17. package/build/src/config_manager.d.ts +18 -0
  18. package/build/src/config_manager.js +168 -0
  19. package/build/src/create_test.d.ts +21 -0
  20. package/build/src/create_test.js +53 -0
  21. package/build/src/debug.d.ts +3 -0
  22. package/build/src/debug.js +10 -0
  23. package/build/src/exceptions_manager.d.ts +19 -0
  24. package/build/src/exceptions_manager.js +85 -0
  25. package/build/src/files_manager.d.ts +18 -0
  26. package/build/src/files_manager.js +57 -0
  27. package/build/src/helpers.d.ts +15 -0
  28. package/build/src/helpers.js +34 -0
  29. package/build/src/hooks.d.ts +20 -0
  30. package/build/src/hooks.js +46 -0
  31. package/build/src/planner.d.ts +25 -0
  32. package/build/src/planner.js +98 -0
  33. package/build/src/plugins/retry.d.ts +20 -0
  34. package/build/src/plugins/retry.js +66 -0
  35. package/build/src/reporters/dot.d.ts +15 -0
  36. package/build/src/reporters/dot.js +41 -0
  37. package/build/src/reporters/main.d.ts +4 -9
  38. package/build/src/reporters/main.js +37 -11
  39. package/build/src/reporters/ndjson.d.ts +15 -0
  40. package/build/src/reporters/ndjson.js +86 -0
  41. package/build/src/reporters/spec.d.ts +13 -0
  42. package/build/src/reporters/spec.js +152 -0
  43. package/build/src/types.d.ts +20 -24
  44. package/build/src/types.js +9 -14
  45. package/build/src/validator.d.ts +30 -0
  46. package/build/src/validator.js +85 -0
  47. package/package.json +17 -28
  48. package/build/chunk-7THDHQFT.js +0 -283
  49. package/build/chunk-HN4AVHWN.js +0 -17
  50. package/build/chunk-MCOW34SG.js +0 -269
  51. package/build/chunk-W5IABAQU.js +0 -502
  52. package/build/main-63126780.d.ts +0 -109
package/build/index.js CHANGED
@@ -1,249 +1,214 @@
1
- import {
2
- CliParser,
3
- ConfigManager,
4
- GlobalHooks,
5
- Planner,
6
- createTest,
7
- createTestGroup,
8
- debug_default,
9
- validator_default
10
- } from "./chunk-W5IABAQU.js";
11
- import {
12
- colors
13
- } from "./chunk-7THDHQFT.js";
14
- import {
15
- Emitter,
16
- Runner,
17
- Suite
18
- } from "./chunk-MCOW34SG.js";
19
- import "./chunk-HN4AVHWN.js";
20
-
21
- // index.ts
22
- import { fileURLToPath } from "node:url";
23
- import { ErrorsPrinter as ErrorsPrinter2 } from "@japa/errors-printer";
24
-
25
- // src/plugins/retry.ts
26
- import { join } from "node:path";
27
- import findCacheDirectory from "find-cache-dir";
28
- import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
29
- var CACHE_DIR = findCacheDirectory({ name: "@japa/runner" });
30
- var SUMMARY_FILE = CACHE_DIR ? join(CACHE_DIR, "summary.json") : void 0;
31
- async function getFailedTests() {
32
- try {
33
- const summary = await readFile(SUMMARY_FILE, "utf-8");
34
- return JSON.parse(summary);
35
- } catch (error) {
36
- if (error.code === "ENOENT") {
37
- return {};
38
- }
39
- throw new Error("Unable to read failed tests cache file", { cause: error });
40
- }
41
- }
42
- async function cacheFailedTests(tests) {
43
- await mkdir(CACHE_DIR, { recursive: true });
44
- await writeFile(SUMMARY_FILE, JSON.stringify({ tests }));
45
- }
46
- var retryPlugin = async function retry({ config, cliArgs: cliArgs2 }) {
47
- if (!SUMMARY_FILE) {
48
- return;
49
- }
50
- config.teardown.push(async (runner) => {
51
- const summary = runner.getSummary();
52
- await cacheFailedTests(summary.failedTestsTitles);
53
- });
54
- if (cliArgs2.failed) {
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
- }
1
+ /*
2
+ * @japa/runner
3
+ *
4
+ * (c) Japa
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import { fileURLToPath } from 'node:url';
10
+ import { ErrorsPrinter } from '@japa/errors-printer';
11
+ import debug from './src/debug.js';
12
+ import validator from './src/validator.js';
13
+ import { Planner } from './src/planner.js';
14
+ import { GlobalHooks } from './src/hooks.js';
15
+ import { CliParser } from './src/cli_parser.js';
16
+ import { retryPlugin } from './src/plugins/retry.js';
17
+ import { ConfigManager } from './src/config_manager.js';
18
+ import { ExceptionsManager } from './src/exceptions_manager.js';
19
+ import { createTest, createTestGroup } from './src/create_test.js';
20
+ import { Emitter, Runner, Suite } from './modules/core/main.js';
21
+ /**
22
+ * Global emitter instance used by the test
23
+ */
24
+ const emitter = new Emitter();
25
+ /**
26
+ * The current active test
27
+ */
28
+ let activeTest;
29
+ /**
30
+ * Parsed commandline arguments
31
+ */
32
+ let cliArgs = {};
33
+ /**
34
+ * Hydrated config
35
+ */
36
+ let runnerConfig;
37
+ /**
38
+ * The state refers to the phase where we configure suites and import
39
+ * test files. We stick this metadata to the test instance one can
40
+ * later reference within the test.
41
+ */
42
+ const executionPlanState = {
43
+ phase: 'idle',
62
44
  };
63
-
64
- // src/exceptions_manager.ts
65
- import { ErrorsPrinter } from "@japa/errors-printer";
66
- var ExceptionsManager = class {
67
- #exceptionsBuffer = [];
68
- #rejectionsBuffer = [];
69
- #state = "watching";
70
- #errorsPrinter = new ErrorsPrinter({ stackLinesCount: 2, framesMaxLimit: 4 });
71
- hasErrors = false;
72
- /**
73
- * Monitors unhandled exceptions and rejections. The exceptions
74
- * are stacked in a buffer, so that we do not clutter the
75
- * tests output and once the tests are over, we will
76
- * print them to the console.
77
- *
78
- * In case the tests are completed, we will print errors as they
79
- * happen.
80
- */
81
- monitor() {
82
- process.on("uncaughtException", async (error) => {
83
- this.hasErrors = true;
84
- if (this.#state === "watching") {
85
- this.#exceptionsBuffer.push(error);
86
- } else {
87
- this.#errorsPrinter.printSectionBorder("[Unhandled Error]");
88
- await this.#errorsPrinter.printError(error);
89
- process.exitCode = 1;
90
- }
45
+ /**
46
+ * Create a Japa test. Defining a test without the callback
47
+ * will create a todo test.
48
+ */
49
+ export function test(title, callback) {
50
+ validator.ensureIsInPlanningPhase(executionPlanState.phase);
51
+ const testInstance = createTest(title, emitter, runnerConfig.refiner, executionPlanState);
52
+ testInstance.setup((t) => {
53
+ activeTest = t;
54
+ return () => {
55
+ activeTest = undefined;
56
+ };
91
57
  });
92
- process.on("unhandledRejection", async (error) => {
93
- this.hasErrors = true;
94
- if (this.#state === "watching") {
95
- this.#rejectionsBuffer.push(error);
96
- } else {
97
- this.#errorsPrinter.printSectionBorder("[Unhandled Rejection]");
98
- await this.#errorsPrinter.printError(error);
99
- process.exitCode = 1;
100
- }
101
- });
102
- }
103
- async flow() {
104
- if (this.#state === "flowing") {
105
- return;
106
- }
107
- this.#state = "flowing";
108
- if (this.#exceptionsBuffer.length) {
109
- let exceptionsCount = this.#exceptionsBuffer.length;
110
- let exceptionsIndex = this.#exceptionsBuffer.length;
111
- this.#errorsPrinter.printSectionHeader("Unhandled Errors");
112
- for (let exception of this.#exceptionsBuffer) {
113
- await this.#errorsPrinter.printError(exception);
114
- this.#errorsPrinter.printSectionBorder(`[${++exceptionsIndex}/${exceptionsCount}]`);
115
- }
116
- this.#exceptionsBuffer = [];
117
- }
118
- if (this.#rejectionsBuffer.length) {
119
- let rejectionsCount = this.#exceptionsBuffer.length;
120
- let rejectionsIndex = this.#exceptionsBuffer.length;
121
- this.#errorsPrinter.printSectionBorder("Unhandled Rejections");
122
- for (let rejection of this.#rejectionsBuffer) {
123
- await this.#errorsPrinter.printError(rejection);
124
- this.#errorsPrinter.printSectionBorder(`[${++rejectionsIndex}/${rejectionsCount}]`);
125
- }
126
- this.#rejectionsBuffer = [];
58
+ if (callback) {
59
+ testInstance.run(callback);
127
60
  }
128
- }
129
- };
130
-
131
- // index.ts
132
- var emitter = new Emitter();
133
- var activeTest;
134
- var cliArgs = {};
135
- var runnerConfig;
136
- var executionPlanState = {
137
- phase: "idle"
138
- };
139
- function test(title, callback) {
140
- validator_default.ensureIsInPlanningPhase(executionPlanState.phase);
141
- const testInstance = createTest(title, emitter, runnerConfig.refiner, executionPlanState);
142
- testInstance.setup((t) => {
143
- activeTest = t;
144
- return () => {
145
- activeTest = void 0;
146
- };
147
- });
148
- if (callback) {
149
- testInstance.run(callback);
150
- }
151
- return testInstance;
61
+ return testInstance;
152
62
  }
153
- test.group = function(title, callback) {
154
- validator_default.ensureIsInPlanningPhase(executionPlanState.phase);
155
- executionPlanState.group = createTestGroup(
156
- title,
157
- emitter,
158
- runnerConfig.refiner,
159
- executionPlanState
160
- );
161
- callback(executionPlanState.group);
162
- executionPlanState.group = void 0;
63
+ /**
64
+ * Create a Japa test group
65
+ */
66
+ test.group = function (title, callback) {
67
+ validator.ensureIsInPlanningPhase(executionPlanState.phase);
68
+ executionPlanState.group = createTestGroup(title, emitter, runnerConfig.refiner, executionPlanState);
69
+ callback(executionPlanState.group);
70
+ executionPlanState.group = undefined;
163
71
  };
164
- function getActiveTest() {
165
- return activeTest;
72
+ /**
73
+ * Get the test of currently running test
74
+ */
75
+ export function getActiveTest() {
76
+ return activeTest;
166
77
  }
167
- function processCLIArgs(argv) {
168
- cliArgs = new CliParser().parse(argv);
78
+ /**
79
+ * Make Japa process command line arguments. Later the parsed output
80
+ * will be used by Japa to compute the configuration
81
+ */
82
+ export function processCLIArgs(argv) {
83
+ cliArgs = new CliParser().parse(argv);
169
84
  }
170
- function configure(options) {
171
- runnerConfig = new ConfigManager(options, cliArgs).hydrate();
85
+ /**
86
+ * Configure the tests runner with inline configuration. You must
87
+ * call configure method before the run method.
88
+ *
89
+ * Do note: The CLI flags will overwrite the options provided
90
+ * to the configure method.
91
+ */
92
+ export function configure(options) {
93
+ runnerConfig = new ConfigManager(options, cliArgs).hydrate();
172
94
  }
173
- async function run() {
174
- if (cliArgs.help) {
175
- console.log(new CliParser().getHelp());
176
- return;
177
- }
178
- validator_default.ensureIsConfigured(runnerConfig);
179
- executionPlanState.phase = "planning";
180
- const runner = new Runner(emitter);
181
- const globalHooks = new GlobalHooks();
182
- const exceptionsManager = new ExceptionsManager();
183
- try {
184
- await retryPlugin({ config: runnerConfig, runner, emitter, cliArgs });
185
- for (let plugin of runnerConfig.plugins) {
186
- debug_default('executing "%s" plugin', plugin.name || "anonymous");
187
- await plugin({ runner, emitter, cliArgs, config: runnerConfig });
188
- }
189
- const { config, reporters, suites, refinerFilters } = await new Planner(runnerConfig).plan();
190
- reporters.forEach((reporter) => {
191
- debug_default('registering "%s" reporter', reporter.name);
192
- runner.registerReporter(reporter);
193
- });
194
- refinerFilters.forEach((filter) => {
195
- debug_default('apply %s filters "%O" ', filter.layer, filter.filters);
196
- config.refiner.add(filter.layer, filter.filters);
197
- });
198
- config.refiner.matchAllTags(cliArgs.matchAll ?? false);
199
- runner.onSuite(config.configureSuite);
200
- debug_default("executing global hooks");
201
- globalHooks.apply(config);
202
- await globalHooks.setup(runner);
203
- for (let suite of suites) {
204
- executionPlanState.suite = new Suite(suite.name, emitter, config.refiner);
205
- executionPlanState.retries = suite.retries;
206
- executionPlanState.timeout = suite.timeout;
207
- if (typeof suite.configure === "function") {
208
- suite.configure(executionPlanState.suite);
209
- }
210
- runner.add(executionPlanState.suite);
211
- for (let fileURL of suite.filesURLs) {
212
- executionPlanState.file = fileURLToPath(fileURL);
213
- debug_default("importing test file %s", executionPlanState.file);
214
- await config.importer(fileURL);
215
- }
216
- executionPlanState.suite = void 0;
217
- }
218
- executionPlanState.phase = "executing";
219
- exceptionsManager.monitor();
220
- await runner.start();
221
- await runner.exec();
222
- await globalHooks.teardown(null, runner);
223
- await runner.end();
224
- await exceptionsManager.flow();
225
- const summary = runner.getSummary();
226
- if (summary.hasError || exceptionsManager.hasErrors) {
227
- process.exitCode = 1;
95
+ /**
96
+ * Execute Japa tests. Calling this function will import the test
97
+ * files behind the scenes
98
+ */
99
+ export async function run() {
100
+ /**
101
+ * Display help when help flag is used
102
+ */
103
+ if (cliArgs.help) {
104
+ console.log(new CliParser().getHelp());
105
+ return;
228
106
  }
229
- if (config.forceExit) {
230
- process.exit();
107
+ validator.ensureIsConfigured(runnerConfig);
108
+ executionPlanState.phase = 'planning';
109
+ const runner = new Runner(emitter);
110
+ const globalHooks = new GlobalHooks();
111
+ const exceptionsManager = new ExceptionsManager();
112
+ try {
113
+ /**
114
+ * Executing the retry plugin as the first thing
115
+ */
116
+ await retryPlugin({ config: runnerConfig, runner, emitter, cliArgs });
117
+ /**
118
+ * Step 1: Executing plugins before creating a plan, so that it can mutate
119
+ * the config
120
+ */
121
+ for (let plugin of runnerConfig.plugins) {
122
+ debug('executing "%s" plugin', plugin.name || 'anonymous');
123
+ await plugin({ runner, emitter, cliArgs, config: runnerConfig });
124
+ }
125
+ /**
126
+ * Step 2: Creating an execution plan. The output is the result of
127
+ * applying all the filters and validations.
128
+ */
129
+ const { config, reporters, suites, refinerFilters } = await new Planner(runnerConfig).plan();
130
+ /**
131
+ * Step 3: Registering reporters and filters with the runner
132
+ */
133
+ reporters.forEach((reporter) => {
134
+ debug('registering "%s" reporter', reporter.name);
135
+ runner.registerReporter(reporter);
136
+ });
137
+ refinerFilters.forEach((filter) => {
138
+ debug('apply %s filters "%O" ', filter.layer, filter.filters);
139
+ config.refiner.add(filter.layer, filter.filters);
140
+ });
141
+ config.refiner.matchAllTags(cliArgs.matchAll ?? false);
142
+ runner.onSuite(config.configureSuite);
143
+ /**
144
+ * Step 4: Running the setup hooks
145
+ */
146
+ debug('executing global hooks');
147
+ globalHooks.apply(config);
148
+ await globalHooks.setup(runner);
149
+ /**
150
+ * Step 5: Register suites and import test files
151
+ */
152
+ for (let suite of suites) {
153
+ /**
154
+ * Creating and configuring the suite
155
+ */
156
+ executionPlanState.suite = new Suite(suite.name, emitter, config.refiner);
157
+ executionPlanState.retries = suite.retries;
158
+ executionPlanState.timeout = suite.timeout;
159
+ if (typeof suite.configure === 'function') {
160
+ suite.configure(executionPlanState.suite);
161
+ }
162
+ runner.add(executionPlanState.suite);
163
+ /**
164
+ * Importing suite files
165
+ */
166
+ for (let fileURL of suite.filesURLs) {
167
+ executionPlanState.file = fileURLToPath(fileURL);
168
+ debug('importing test file %s', executionPlanState.file);
169
+ await config.importer(fileURL);
170
+ }
171
+ /**
172
+ * Resetting global state
173
+ */
174
+ executionPlanState.suite = undefined;
175
+ }
176
+ /**
177
+ * Onto execution phase
178
+ */
179
+ executionPlanState.phase = 'executing';
180
+ /**
181
+ * Monitor for unhandled erorrs and rejections
182
+ */
183
+ exceptionsManager.monitor();
184
+ await runner.start();
185
+ await runner.exec();
186
+ await globalHooks.teardown(null, runner);
187
+ await runner.end();
188
+ /**
189
+ * Print unhandled errors
190
+ */
191
+ await exceptionsManager.flow();
192
+ const summary = runner.getSummary();
193
+ if (summary.hasError || exceptionsManager.hasErrors) {
194
+ process.exitCode = 1;
195
+ }
196
+ if (config.forceExit) {
197
+ process.exit();
198
+ }
231
199
  }
232
- } catch (error) {
233
- await globalHooks.teardown(error, runner);
234
- const printer = new ErrorsPrinter2();
235
- await printer.printError(error);
236
- await exceptionsManager.flow();
237
- process.exitCode = 1;
238
- if (runnerConfig.forceExit) {
239
- process.exit();
200
+ catch (error) {
201
+ await globalHooks.teardown(error, runner);
202
+ const printer = new ErrorsPrinter();
203
+ await printer.printError(error);
204
+ /**
205
+ * Print unhandled errors in case the code inside
206
+ * the try block never got triggered
207
+ */
208
+ await exceptionsManager.flow();
209
+ process.exitCode = 1;
210
+ if (runnerConfig.forceExit) {
211
+ process.exit();
212
+ }
240
213
  }
241
- }
242
214
  }
243
- export {
244
- configure,
245
- getActiveTest,
246
- processCLIArgs,
247
- run,
248
- test
249
- };
@@ -1,3 +1,63 @@
1
- export { Emitter, Refiner } from '@japa/core';
2
- export { b as BaseReporter, G as Group, R as Runner, S as Suite, a as Test, T as TestContext } from '../../main-63126780.js';
3
- import '@japa/core/types';
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { Emitter, Refiner, Test as BaseTest, Suite as BaseSuite, Group as BaseGroup, Runner as BaseRunner, TestContext as BaseTestContext } from '@japa/core';
3
+ import { BaseReporter } from './reporters/base.js';
4
+ import type { DataSetNode, TestHooksCleanupHandler } from './types.js';
5
+ declare module '@japa/core' {
6
+ interface Test<Context extends Record<any, any>, TestData extends DataSetNode = undefined> {
7
+ throws(message: string | RegExp, errorConstructor?: any): this;
8
+ }
9
+ interface TestContext {
10
+ cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void;
11
+ }
12
+ }
13
+ export { Emitter, Refiner, BaseReporter };
14
+ /**
15
+ * Test context carries context data for a given test.
16
+ */
17
+ export declare class TestContext extends BaseTestContext {
18
+ test: Test;
19
+ /**
20
+ * Register a cleanup function that runs after the test finishes
21
+ * successfully or with an error.
22
+ */
23
+ cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void;
24
+ constructor(test: Test);
25
+ }
26
+ /**
27
+ * Test class represents an individual test and exposes API to tweak
28
+ * its runtime behavior.
29
+ */
30
+ export declare class Test<TestData extends DataSetNode = undefined> extends BaseTest<TestContext, TestData> {
31
+ /**
32
+ * @inheritdoc
33
+ */
34
+ static executedCallbacks: never[];
35
+ /**
36
+ * @inheritdoc
37
+ */
38
+ static executingCallbacks: never[];
39
+ /**
40
+ * Assert the test callback throws an exception when a certain
41
+ * error message and optionally is an instance of a given
42
+ * Error class.
43
+ */
44
+ throws(message: string | RegExp, errorConstructor?: any): this;
45
+ }
46
+ /**
47
+ * TestGroup is used to bulk configure a collection of tests and
48
+ * define lifecycle hooks for them
49
+ */
50
+ export declare class Group extends BaseGroup<TestContext> {
51
+ }
52
+ /**
53
+ * A suite is a collection of tests created around a given
54
+ * testing type. For example: A suite for unit tests, a
55
+ * suite for functional tests and so on.
56
+ */
57
+ export declare class Suite extends BaseSuite<TestContext> {
58
+ }
59
+ /**
60
+ * Runner class is used to execute the tests
61
+ */
62
+ export declare class Runner extends BaseRunner<TestContext> {
63
+ }
@@ -1,21 +1,121 @@
1
- import {
2
- BaseReporter,
3
- Emitter,
4
- Group,
5
- Refiner,
6
- Runner,
7
- Suite,
8
- Test,
9
- TestContext
10
- } from "../../chunk-MCOW34SG.js";
11
- import "../../chunk-HN4AVHWN.js";
12
- export {
13
- BaseReporter,
14
- Emitter,
15
- Group,
16
- Refiner,
17
- Runner,
18
- Suite,
19
- Test,
20
- TestContext
21
- };
1
+ /*
2
+ * @japa/runner
3
+ *
4
+ * (c) Japa
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import { Emitter, Refiner, Test as BaseTest, Suite as BaseSuite, Group as BaseGroup, Runner as BaseRunner, TestContext as BaseTestContext, } from '@japa/core';
10
+ import { inspect } from 'node:util';
11
+ import { AssertionError } from 'node:assert';
12
+ import { BaseReporter } from './reporters/base.js';
13
+ export { Emitter, Refiner, BaseReporter };
14
+ /**
15
+ * Test context carries context data for a given test.
16
+ */
17
+ export class TestContext extends BaseTestContext {
18
+ test;
19
+ constructor(test) {
20
+ super();
21
+ this.test = test;
22
+ this.cleanup = (cleanupCallback) => {
23
+ test.cleanup(cleanupCallback);
24
+ };
25
+ }
26
+ }
27
+ /**
28
+ * Test class represents an individual test and exposes API to tweak
29
+ * its runtime behavior.
30
+ */
31
+ export class Test extends BaseTest {
32
+ /**
33
+ * @inheritdoc
34
+ */
35
+ static executedCallbacks = [];
36
+ /**
37
+ * @inheritdoc
38
+ */
39
+ static executingCallbacks = [];
40
+ /**
41
+ * Assert the test callback throws an exception when a certain
42
+ * error message and optionally is an instance of a given
43
+ * Error class.
44
+ */
45
+ throws(message, errorConstructor) {
46
+ const errorInPoint = new AssertionError({});
47
+ const existingExecutor = this.options.executor;
48
+ if (!existingExecutor) {
49
+ throw new Error('Cannot use "test.throws" method without a test callback');
50
+ }
51
+ /**
52
+ * Overwriting existing callback
53
+ */
54
+ this.options.executor = async (...args) => {
55
+ let raisedException;
56
+ try {
57
+ await existingExecutor(...args);
58
+ }
59
+ catch (error) {
60
+ raisedException = error;
61
+ }
62
+ /**
63
+ * Notify no exception has been raised
64
+ */
65
+ if (!raisedException) {
66
+ errorInPoint.message = 'Expected test to throw an exception';
67
+ throw errorInPoint;
68
+ }
69
+ /**
70
+ * Constructor mis-match
71
+ */
72
+ if (errorConstructor && !(raisedException instanceof errorConstructor)) {
73
+ errorInPoint.message = `Expected test to throw "${inspect(errorConstructor)}"`;
74
+ throw errorInPoint;
75
+ }
76
+ /**
77
+ * Error does not have a message property
78
+ */
79
+ const exceptionMessage = raisedException.message;
80
+ if (!exceptionMessage || typeof exceptionMessage !== 'string') {
81
+ errorInPoint.message = 'Expected test to throw an exception with message property';
82
+ throw errorInPoint;
83
+ }
84
+ /**
85
+ * Message does not match
86
+ */
87
+ if (typeof message === 'string') {
88
+ if (exceptionMessage !== message) {
89
+ errorInPoint.message = `Expected test to throw "${message}". Instead received "${raisedException.message}"`;
90
+ errorInPoint.actual = raisedException.message;
91
+ errorInPoint.expected = message;
92
+ throw errorInPoint;
93
+ }
94
+ return;
95
+ }
96
+ if (!message.test(exceptionMessage)) {
97
+ errorInPoint.message = `Expected test error to match "${message}" regular expression`;
98
+ throw errorInPoint;
99
+ }
100
+ };
101
+ return this;
102
+ }
103
+ }
104
+ /**
105
+ * TestGroup is used to bulk configure a collection of tests and
106
+ * define lifecycle hooks for them
107
+ */
108
+ export class Group extends BaseGroup {
109
+ }
110
+ /**
111
+ * A suite is a collection of tests created around a given
112
+ * testing type. For example: A suite for unit tests, a
113
+ * suite for functional tests and so on.
114
+ */
115
+ export class Suite extends BaseSuite {
116
+ }
117
+ /**
118
+ * Runner class is used to execute the tests
119
+ */
120
+ export class Runner extends BaseRunner {
121
+ }