@japa/runner 3.0.4 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/chunk-52OY4QRJ.js +284 -0
- package/build/chunk-52OY4QRJ.js.map +1 -0
- package/build/chunk-IKX2FPUC.js +505 -0
- package/build/chunk-IKX2FPUC.js.map +1 -0
- package/build/chunk-OBDV3O36.js +18 -0
- package/build/chunk-OBDV3O36.js.map +1 -0
- package/build/chunk-PKOB3ULJ.js +270 -0
- package/build/chunk-PKOB3ULJ.js.map +1 -0
- package/build/factories/main.js +214 -29
- package/build/factories/main.js.map +1 -0
- package/build/index.js +243 -202
- package/build/index.js.map +1 -0
- package/build/modules/core/main.d.ts +0 -1
- package/build/modules/core/main.js +22 -121
- package/build/modules/core/main.js.map +1 -0
- package/build/src/files_manager.d.ts +1 -1
- package/build/src/reporters/main.js +12 -37
- package/build/src/reporters/main.js.map +1 -0
- package/build/src/types.d.ts +8 -0
- package/build/src/types.js +15 -9
- package/build/src/types.js.map +1 -0
- package/package.json +42 -26
- package/build/factories/create_diverse_tests.js +0 -106
- package/build/factories/runner.js +0 -93
- package/build/modules/core/reporters/base.js +0 -183
- package/build/modules/core/types.js +0 -9
- package/build/src/cli_parser.js +0 -75
- package/build/src/config_manager.js +0 -168
- package/build/src/create_test.js +0 -53
- package/build/src/debug.js +0 -10
- package/build/src/exceptions_manager.js +0 -85
- package/build/src/files_manager.js +0 -57
- package/build/src/helpers.js +0 -34
- package/build/src/hooks.js +0 -46
- package/build/src/planner.js +0 -98
- package/build/src/plugins/retry.js +0 -72
- package/build/src/reporters/dot.js +0 -41
- package/build/src/reporters/ndjson.js +0 -86
- package/build/src/reporters/spec.js +0 -152
- package/build/src/validator.js +0 -85
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// modules/core/main.ts
|
|
2
|
+
import {
|
|
3
|
+
Emitter,
|
|
4
|
+
Refiner,
|
|
5
|
+
Test as BaseTest,
|
|
6
|
+
Suite as BaseSuite,
|
|
7
|
+
Group as BaseGroup,
|
|
8
|
+
Runner as BaseRunner,
|
|
9
|
+
TestContext as BaseTestContext
|
|
10
|
+
} from "@japa/core";
|
|
11
|
+
import { inspect } from "node:util";
|
|
12
|
+
import { AssertionError } from "node:assert";
|
|
13
|
+
|
|
14
|
+
// modules/core/reporters/base.ts
|
|
15
|
+
import ms from "ms";
|
|
16
|
+
import colors from "@poppinss/colors";
|
|
17
|
+
import { ErrorsPrinter } from "@japa/errors-printer";
|
|
18
|
+
var ansi = colors.ansi();
|
|
19
|
+
var BaseReporter = class {
|
|
20
|
+
#options;
|
|
21
|
+
runner;
|
|
22
|
+
/**
|
|
23
|
+
* Path to the file for which the tests are getting executed
|
|
24
|
+
*/
|
|
25
|
+
currentFileName;
|
|
26
|
+
/**
|
|
27
|
+
* Suite for which the tests are getting executed
|
|
28
|
+
*/
|
|
29
|
+
currentSuiteName;
|
|
30
|
+
/**
|
|
31
|
+
* Group for which the tests are getting executed
|
|
32
|
+
*/
|
|
33
|
+
currentGroupName;
|
|
34
|
+
constructor(options = {}) {
|
|
35
|
+
this.#options = Object.assign({ stackLinesCount: 2 }, options);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Pretty prints the aggregates
|
|
39
|
+
*/
|
|
40
|
+
#printAggregates(summary) {
|
|
41
|
+
const tests = [];
|
|
42
|
+
if (summary.aggregates.passed) {
|
|
43
|
+
tests.push(ansi.green(`${summary.aggregates.passed} passed`));
|
|
44
|
+
}
|
|
45
|
+
if (summary.aggregates.failed) {
|
|
46
|
+
tests.push(ansi.red(`${summary.aggregates.failed} failed`));
|
|
47
|
+
}
|
|
48
|
+
if (summary.aggregates.todo) {
|
|
49
|
+
tests.push(ansi.cyan(`${summary.aggregates.todo} todo`));
|
|
50
|
+
}
|
|
51
|
+
if (summary.aggregates.skipped) {
|
|
52
|
+
tests.push(ansi.yellow(`${summary.aggregates.skipped} skipped`));
|
|
53
|
+
}
|
|
54
|
+
if (summary.aggregates.regression) {
|
|
55
|
+
tests.push(ansi.magenta(`${summary.aggregates.regression} regression`));
|
|
56
|
+
}
|
|
57
|
+
this.runner.summaryBuilder.use(() => {
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
key: ansi.dim("Tests"),
|
|
61
|
+
value: `${tests.join(", ")} ${ansi.dim(`(${summary.aggregates.total})`)}`
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: ansi.dim("Time"),
|
|
65
|
+
value: ansi.dim(ms(summary.duration))
|
|
66
|
+
}
|
|
67
|
+
];
|
|
68
|
+
});
|
|
69
|
+
console.log(this.runner.summaryBuilder.build().join("\n"));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Aggregates errors tree to a flat array
|
|
73
|
+
*/
|
|
74
|
+
#aggregateErrors(summary) {
|
|
75
|
+
const errorsList = [];
|
|
76
|
+
summary.failureTree.forEach((suite) => {
|
|
77
|
+
suite.errors.forEach((error) => errorsList.push({ title: suite.name, ...error }));
|
|
78
|
+
suite.children.forEach((testOrGroup) => {
|
|
79
|
+
if (testOrGroup.type === "test") {
|
|
80
|
+
testOrGroup.errors.forEach((error) => {
|
|
81
|
+
errorsList.push({ title: `${suite.name} / ${testOrGroup.title}`, ...error });
|
|
82
|
+
});
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
testOrGroup.errors.forEach((error) => {
|
|
86
|
+
errorsList.push({ title: testOrGroup.name, ...error });
|
|
87
|
+
});
|
|
88
|
+
testOrGroup.children.forEach((test) => {
|
|
89
|
+
test.errors.forEach((error) => {
|
|
90
|
+
errorsList.push({ title: `${testOrGroup.name} / ${test.title}`, ...error });
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
return errorsList;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Pretty print errors
|
|
99
|
+
*/
|
|
100
|
+
async #printErrors(summary) {
|
|
101
|
+
if (!summary.failureTree.length) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const errorPrinter = new ErrorsPrinter({
|
|
105
|
+
stackLinesCount: this.#options.stackLinesCount,
|
|
106
|
+
framesMaxLimit: this.#options.framesMaxLimit
|
|
107
|
+
});
|
|
108
|
+
errorPrinter.printSectionHeader("ERRORS");
|
|
109
|
+
await errorPrinter.printErrors(this.#aggregateErrors(summary));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Handlers to capture events
|
|
113
|
+
*/
|
|
114
|
+
onTestStart(_) {
|
|
115
|
+
}
|
|
116
|
+
onTestEnd(_) {
|
|
117
|
+
}
|
|
118
|
+
onGroupStart(_) {
|
|
119
|
+
}
|
|
120
|
+
onGroupEnd(_) {
|
|
121
|
+
}
|
|
122
|
+
onSuiteStart(_) {
|
|
123
|
+
}
|
|
124
|
+
onSuiteEnd(_) {
|
|
125
|
+
}
|
|
126
|
+
async start(_) {
|
|
127
|
+
}
|
|
128
|
+
async end(_) {
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Print tests summary
|
|
132
|
+
*/
|
|
133
|
+
async printSummary(summary) {
|
|
134
|
+
await this.#printErrors(summary);
|
|
135
|
+
console.log("");
|
|
136
|
+
if (summary.aggregates.total === 0 && !summary.hasError) {
|
|
137
|
+
console.log(ansi.bgYellow().black(" NO TESTS EXECUTED "));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (summary.hasError) {
|
|
141
|
+
console.log(ansi.bgRed().black(" FAILED "));
|
|
142
|
+
} else {
|
|
143
|
+
console.log(ansi.bgGreen().black(" PASSED "));
|
|
144
|
+
}
|
|
145
|
+
console.log("");
|
|
146
|
+
this.#printAggregates(summary);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Invoked by the tests runner when tests are about to start
|
|
150
|
+
*/
|
|
151
|
+
boot(runner, emitter) {
|
|
152
|
+
this.runner = runner;
|
|
153
|
+
emitter.on("test:start", (payload) => {
|
|
154
|
+
this.currentFileName = payload.meta.fileName;
|
|
155
|
+
this.onTestStart(payload);
|
|
156
|
+
});
|
|
157
|
+
emitter.on("test:end", (payload) => {
|
|
158
|
+
this.onTestEnd(payload);
|
|
159
|
+
});
|
|
160
|
+
emitter.on("group:start", (payload) => {
|
|
161
|
+
this.currentGroupName = payload.title;
|
|
162
|
+
this.currentFileName = payload.meta.fileName;
|
|
163
|
+
this.onGroupStart(payload);
|
|
164
|
+
});
|
|
165
|
+
emitter.on("group:end", (payload) => {
|
|
166
|
+
this.currentGroupName = void 0;
|
|
167
|
+
this.onGroupEnd(payload);
|
|
168
|
+
});
|
|
169
|
+
emitter.on("suite:start", (payload) => {
|
|
170
|
+
this.currentSuiteName = payload.name;
|
|
171
|
+
this.onSuiteStart(payload);
|
|
172
|
+
});
|
|
173
|
+
emitter.on("suite:end", (payload) => {
|
|
174
|
+
this.currentSuiteName = void 0;
|
|
175
|
+
this.onSuiteEnd(payload);
|
|
176
|
+
});
|
|
177
|
+
emitter.on("runner:start", async (payload) => {
|
|
178
|
+
await this.start(payload);
|
|
179
|
+
});
|
|
180
|
+
emitter.on("runner:end", async (payload) => {
|
|
181
|
+
await this.end(payload);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// modules/core/main.ts
|
|
187
|
+
var TestContext = class extends BaseTestContext {
|
|
188
|
+
constructor(test) {
|
|
189
|
+
super();
|
|
190
|
+
this.test = test;
|
|
191
|
+
this.cleanup = (cleanupCallback) => {
|
|
192
|
+
test.cleanup(cleanupCallback);
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
var Test = class extends BaseTest {
|
|
197
|
+
/**
|
|
198
|
+
* @inheritdoc
|
|
199
|
+
*/
|
|
200
|
+
static executedCallbacks = [];
|
|
201
|
+
/**
|
|
202
|
+
* @inheritdoc
|
|
203
|
+
*/
|
|
204
|
+
static executingCallbacks = [];
|
|
205
|
+
/**
|
|
206
|
+
* Assert the test callback throws an exception when a certain
|
|
207
|
+
* error message and optionally is an instance of a given
|
|
208
|
+
* Error class.
|
|
209
|
+
*/
|
|
210
|
+
throws(message, errorConstructor) {
|
|
211
|
+
const errorInPoint = new AssertionError({});
|
|
212
|
+
const existingExecutor = this.options.executor;
|
|
213
|
+
if (!existingExecutor) {
|
|
214
|
+
throw new Error('Cannot use "test.throws" method without a test callback');
|
|
215
|
+
}
|
|
216
|
+
this.options.executor = async (...args) => {
|
|
217
|
+
let raisedException;
|
|
218
|
+
try {
|
|
219
|
+
await existingExecutor(...args);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
raisedException = error;
|
|
222
|
+
}
|
|
223
|
+
if (!raisedException) {
|
|
224
|
+
errorInPoint.message = "Expected test to throw an exception";
|
|
225
|
+
throw errorInPoint;
|
|
226
|
+
}
|
|
227
|
+
if (errorConstructor && !(raisedException instanceof errorConstructor)) {
|
|
228
|
+
errorInPoint.message = `Expected test to throw "${inspect(errorConstructor)}"`;
|
|
229
|
+
throw errorInPoint;
|
|
230
|
+
}
|
|
231
|
+
const exceptionMessage = raisedException.message;
|
|
232
|
+
if (!exceptionMessage || typeof exceptionMessage !== "string") {
|
|
233
|
+
errorInPoint.message = "Expected test to throw an exception with message property";
|
|
234
|
+
throw errorInPoint;
|
|
235
|
+
}
|
|
236
|
+
if (typeof message === "string") {
|
|
237
|
+
if (exceptionMessage !== message) {
|
|
238
|
+
errorInPoint.message = `Expected test to throw "${message}". Instead received "${raisedException.message}"`;
|
|
239
|
+
errorInPoint.actual = raisedException.message;
|
|
240
|
+
errorInPoint.expected = message;
|
|
241
|
+
throw errorInPoint;
|
|
242
|
+
}
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (!message.test(exceptionMessage)) {
|
|
246
|
+
errorInPoint.message = `Expected test error to match "${message}" regular expression`;
|
|
247
|
+
throw errorInPoint;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
return this;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
var Group = class extends BaseGroup {
|
|
254
|
+
};
|
|
255
|
+
var Suite = class extends BaseSuite {
|
|
256
|
+
};
|
|
257
|
+
var Runner = class extends BaseRunner {
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export {
|
|
261
|
+
BaseReporter,
|
|
262
|
+
Emitter,
|
|
263
|
+
Refiner,
|
|
264
|
+
TestContext,
|
|
265
|
+
Test,
|
|
266
|
+
Group,
|
|
267
|
+
Suite,
|
|
268
|
+
Runner
|
|
269
|
+
};
|
|
270
|
+
//# sourceMappingURL=chunk-PKOB3ULJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../modules/core/main.ts","../modules/core/reporters/base.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 {\n Emitter,\n Refiner,\n Test as BaseTest,\n Suite as BaseSuite,\n Group as BaseGroup,\n Runner as BaseRunner,\n TestContext as BaseTestContext,\n} from '@japa/core'\nimport { inspect } from 'node:util'\nimport { AssertionError } from 'node:assert'\nimport { BaseReporter } from './reporters/base.js'\nimport type { DataSetNode, TestHooksCleanupHandler } from './types.js'\n\ndeclare module '@japa/core' {\n interface Test<Context extends Record<any, any>, TestData extends DataSetNode = undefined> {\n throws(message: string | RegExp, errorConstructor?: any): this\n }\n interface TestContext {\n cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void\n }\n}\n\nexport { Emitter, Refiner, BaseReporter }\n\n/**\n * Test context carries context data for a given test.\n */\nexport class TestContext extends BaseTestContext {\n /**\n * Register a cleanup function that runs after the test finishes\n * successfully or with an error.\n */\n declare cleanup: (cleanupCallback: TestHooksCleanupHandler<TestContext>) => void\n\n constructor(public test: Test) {\n super()\n this.cleanup = (cleanupCallback: TestHooksCleanupHandler<TestContext>) => {\n test.cleanup(cleanupCallback)\n }\n }\n}\n\n/**\n * Test class represents an individual test and exposes API to tweak\n * its runtime behavior.\n */\nexport class Test<TestData extends DataSetNode = undefined> extends BaseTest<\n TestContext,\n TestData\n> {\n /**\n * @inheritdoc\n */\n static executedCallbacks = []\n\n /**\n * @inheritdoc\n */\n static executingCallbacks = []\n\n /**\n * Assert the test callback throws an exception when a certain\n * error message and optionally is an instance of a given\n * Error class.\n */\n throws(message: string | RegExp, errorConstructor?: any) {\n const errorInPoint = new AssertionError({})\n const existingExecutor = this.options.executor\n if (!existingExecutor) {\n throw new Error('Cannot use \"test.throws\" method without a test callback')\n }\n\n /**\n * Overwriting existing callback\n */\n this.options.executor = async (...args: [any, any, any]) => {\n let raisedException: any\n try {\n await existingExecutor(...args)\n } catch (error) {\n raisedException = error\n }\n\n /**\n * Notify no exception has been raised\n */\n if (!raisedException) {\n errorInPoint.message = 'Expected test to throw an exception'\n throw errorInPoint\n }\n\n /**\n * Constructor mis-match\n */\n if (errorConstructor && !(raisedException instanceof errorConstructor)) {\n errorInPoint.message = `Expected test to throw \"${inspect(errorConstructor)}\"`\n throw errorInPoint\n }\n\n /**\n * Error does not have a message property\n */\n const exceptionMessage: unknown = raisedException.message\n if (!exceptionMessage || typeof exceptionMessage !== 'string') {\n errorInPoint.message = 'Expected test to throw an exception with message property'\n throw errorInPoint\n }\n\n /**\n * Message does not match\n */\n if (typeof message === 'string') {\n if (exceptionMessage !== message) {\n errorInPoint.message = `Expected test to throw \"${message}\". Instead received \"${raisedException.message}\"`\n errorInPoint.actual = raisedException.message\n errorInPoint.expected = message\n throw errorInPoint\n }\n return\n }\n\n if (!message.test(exceptionMessage)) {\n errorInPoint.message = `Expected test error to match \"${message}\" regular expression`\n throw errorInPoint\n }\n }\n\n return this\n }\n}\n\n/**\n * TestGroup is used to bulk configure a collection of tests and\n * define lifecycle hooks for them\n */\nexport class Group extends BaseGroup<TestContext> {}\n\n/**\n * A suite is a collection of tests created around a given\n * testing type. For example: A suite for unit tests, a\n * suite for functional tests and so on.\n */\nexport class Suite extends BaseSuite<TestContext> {}\n\n/**\n * Runner class is used to execute the tests\n */\nexport class Runner extends BaseRunner<TestContext> {}\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 ms from 'ms'\nimport colors from '@poppinss/colors'\nimport { ErrorsPrinter } from '@japa/errors-printer'\n\nimport type {\n TestEndNode,\n SuiteEndNode,\n GroupEndNode,\n TestStartNode,\n RunnerSummary,\n RunnerEndNode,\n GroupStartNode,\n SuiteStartNode,\n RunnerStartNode,\n BaseReporterOptions,\n} from '../types.js'\nimport { Emitter, Runner } from '../main.js'\n\nconst ansi = colors.ansi()\n\n/**\n * Base reporter to build custom reporters on top of\n */\nexport abstract class BaseReporter {\n #options: BaseReporterOptions\n runner?: Runner\n\n /**\n * Path to the file for which the tests are getting executed\n */\n currentFileName?: string\n\n /**\n * Suite for which the tests are getting executed\n */\n currentSuiteName?: string\n\n /**\n * Group for which the tests are getting executed\n */\n currentGroupName?: string\n\n constructor(options: BaseReporterOptions = {}) {\n this.#options = Object.assign({ stackLinesCount: 2 }, options)\n }\n\n /**\n * Pretty prints the aggregates\n */\n #printAggregates(summary: RunnerSummary) {\n const tests: string[] = []\n\n /**\n * Set value for tests row\n */\n if (summary.aggregates.passed) {\n tests.push(ansi.green(`${summary.aggregates.passed} passed`))\n }\n if (summary.aggregates.failed) {\n tests.push(ansi.red(`${summary.aggregates.failed} failed`))\n }\n if (summary.aggregates.todo) {\n tests.push(ansi.cyan(`${summary.aggregates.todo} todo`))\n }\n if (summary.aggregates.skipped) {\n tests.push(ansi.yellow(`${summary.aggregates.skipped} skipped`))\n }\n if (summary.aggregates.regression) {\n tests.push(ansi.magenta(`${summary.aggregates.regression} regression`))\n }\n\n this.runner!.summaryBuilder.use(() => {\n return [\n {\n key: ansi.dim('Tests'),\n value: `${tests.join(', ')} ${ansi.dim(`(${summary.aggregates.total})`)}`,\n },\n {\n key: ansi.dim('Time'),\n value: ansi.dim(ms(summary.duration)),\n },\n ]\n })\n\n console.log(this.runner!.summaryBuilder.build().join('\\n'))\n }\n\n /**\n * Aggregates errors tree to a flat array\n */\n #aggregateErrors(summary: RunnerSummary) {\n const errorsList: { phase: string; title: string; error: Error }[] = []\n\n summary.failureTree.forEach((suite) => {\n suite.errors.forEach((error) => errorsList.push({ title: suite.name, ...error }))\n\n suite.children.forEach((testOrGroup) => {\n /**\n * Suite child is a test\n */\n if (testOrGroup.type === 'test') {\n testOrGroup.errors.forEach((error) => {\n errorsList.push({ title: `${suite.name} / ${testOrGroup.title}`, ...error })\n })\n return\n }\n\n /**\n * Suite child is a group\n */\n testOrGroup.errors.forEach((error) => {\n errorsList.push({ title: testOrGroup.name, ...error })\n })\n testOrGroup.children.forEach((test) => {\n test.errors.forEach((error) => {\n errorsList.push({ title: `${testOrGroup.name} / ${test.title}`, ...error })\n })\n })\n })\n })\n\n return errorsList\n }\n\n /**\n * Pretty print errors\n */\n async #printErrors(summary: RunnerSummary) {\n if (!summary.failureTree.length) {\n return\n }\n\n const errorPrinter = new ErrorsPrinter({\n stackLinesCount: this.#options.stackLinesCount,\n framesMaxLimit: this.#options.framesMaxLimit,\n })\n\n errorPrinter.printSectionHeader('ERRORS')\n await errorPrinter.printErrors(this.#aggregateErrors(summary))\n }\n\n /**\n * Handlers to capture events\n */\n protected onTestStart(_: TestStartNode): void {}\n protected onTestEnd(_: TestEndNode) {}\n\n protected onGroupStart(_: GroupStartNode) {}\n protected onGroupEnd(_: GroupEndNode) {}\n\n protected onSuiteStart(_: SuiteStartNode) {}\n protected onSuiteEnd(_: SuiteEndNode) {}\n\n protected async start(_: RunnerStartNode) {}\n protected async end(_: RunnerEndNode) {}\n\n /**\n * Print tests summary\n */\n protected async printSummary(summary: RunnerSummary) {\n await this.#printErrors(summary)\n\n console.log('')\n if (summary.aggregates.total === 0 && !summary.hasError) {\n console.log(ansi.bgYellow().black(' NO TESTS EXECUTED '))\n return\n }\n\n if (summary.hasError) {\n console.log(ansi.bgRed().black(' FAILED '))\n } else {\n console.log(ansi.bgGreen().black(' PASSED '))\n }\n console.log('')\n this.#printAggregates(summary)\n }\n\n /**\n * Invoked by the tests runner when tests are about to start\n */\n boot(runner: Runner, emitter: Emitter) {\n this.runner = runner\n\n emitter.on('test:start', (payload) => {\n this.currentFileName = payload.meta.fileName\n this.onTestStart(payload)\n })\n\n emitter.on('test:end', (payload) => {\n this.onTestEnd(payload)\n })\n\n emitter.on('group:start', (payload) => {\n this.currentGroupName = payload.title\n this.currentFileName = payload.meta.fileName\n this.onGroupStart(payload)\n })\n\n emitter.on('group:end', (payload) => {\n this.currentGroupName = undefined\n this.onGroupEnd(payload)\n })\n\n emitter.on('suite:start', (payload) => {\n this.currentSuiteName = payload.name\n this.onSuiteStart(payload)\n })\n\n emitter.on('suite:end', (payload) => {\n this.currentSuiteName = undefined\n this.onSuiteEnd(payload)\n })\n\n emitter.on('runner:start', async (payload) => {\n await this.start(payload)\n })\n\n emitter.on('runner:end', async (payload) => {\n await this.end(payload)\n })\n }\n}\n"],"mappings":"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","names":[]}
|
package/build/factories/main.js
CHANGED
|
@@ -1,30 +1,215 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
import {
|
|
2
|
+
CliParser,
|
|
3
|
+
ConfigManager,
|
|
4
|
+
GlobalHooks,
|
|
5
|
+
Planner,
|
|
6
|
+
createTest,
|
|
7
|
+
createTestGroup
|
|
8
|
+
} from "../chunk-IKX2FPUC.js";
|
|
9
|
+
import "../chunk-52OY4QRJ.js";
|
|
10
|
+
import {
|
|
11
|
+
Emitter,
|
|
12
|
+
Runner,
|
|
13
|
+
Suite
|
|
14
|
+
} from "../chunk-PKOB3ULJ.js";
|
|
15
|
+
import "../chunk-OBDV3O36.js";
|
|
16
|
+
|
|
17
|
+
// factories/runner.ts
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
var RunnerFactory = class {
|
|
20
|
+
#emitter = new Emitter();
|
|
21
|
+
#config;
|
|
22
|
+
#cliArgs;
|
|
23
|
+
#file = fileURLToPath(import.meta.url);
|
|
24
|
+
get #refiner() {
|
|
25
|
+
return this.#config.refiner;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Registers plugins
|
|
29
|
+
*/
|
|
30
|
+
async #registerPlugins(runner2) {
|
|
31
|
+
for (let plugin of this.#config.plugins) {
|
|
32
|
+
await plugin({
|
|
33
|
+
config: this.#config,
|
|
34
|
+
runner: runner2,
|
|
35
|
+
emitter: this.#emitter,
|
|
36
|
+
cliArgs: this.#cliArgs
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Configure runner
|
|
42
|
+
*/
|
|
43
|
+
configure(config, argv) {
|
|
44
|
+
this.#cliArgs = new CliParser().parse(argv || []);
|
|
45
|
+
this.#config = new ConfigManager(config, this.#cliArgs).hydrate();
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Define a custom emitter instance to use
|
|
50
|
+
*/
|
|
51
|
+
useEmitter(emitter) {
|
|
52
|
+
this.#emitter = emitter;
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run a test using the runner
|
|
57
|
+
*/
|
|
58
|
+
async runTest(title, callback) {
|
|
59
|
+
return this.runSuites((emitter, refiner, file) => {
|
|
60
|
+
const defaultSuite = new Suite("default", emitter, refiner);
|
|
61
|
+
createTest(title, emitter, refiner, {
|
|
62
|
+
suite: defaultSuite,
|
|
63
|
+
file
|
|
64
|
+
}).run(callback);
|
|
65
|
+
return [defaultSuite];
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Run dummy tests. You might use
|
|
70
|
+
*/
|
|
71
|
+
async runSuites(suites) {
|
|
72
|
+
const runner2 = new Runner(this.#emitter);
|
|
73
|
+
await this.#registerPlugins(runner2);
|
|
74
|
+
const { config, reporters, refinerFilters } = await new Planner(this.#config).plan();
|
|
75
|
+
const globalHooks = new GlobalHooks();
|
|
76
|
+
globalHooks.apply(config);
|
|
77
|
+
reporters.forEach((reporter) => {
|
|
78
|
+
runner2.registerReporter(reporter);
|
|
79
|
+
});
|
|
80
|
+
refinerFilters.forEach((filter) => {
|
|
81
|
+
config.refiner.add(filter.layer, filter.filters);
|
|
82
|
+
});
|
|
83
|
+
suites(this.#emitter, this.#refiner, this.#file).forEach((suite) => runner2.add(suite));
|
|
84
|
+
await globalHooks.setup(runner2);
|
|
85
|
+
await runner2.start();
|
|
86
|
+
await runner2.exec();
|
|
87
|
+
await runner2.end();
|
|
88
|
+
await globalHooks.teardown(null, runner2);
|
|
89
|
+
return runner2.getSummary();
|
|
90
|
+
}
|
|
30
91
|
};
|
|
92
|
+
|
|
93
|
+
// factories/create_diverse_tests.ts
|
|
94
|
+
import assert from "node:assert";
|
|
95
|
+
function createUnitTestsSuite(emitter, refiner, file) {
|
|
96
|
+
const suite = new Suite("unit", emitter, refiner);
|
|
97
|
+
const group = createTestGroup("Maths#add", emitter, refiner, {
|
|
98
|
+
suite,
|
|
99
|
+
file
|
|
100
|
+
});
|
|
101
|
+
createTest("A top level test inside a suite", emitter, refiner, {
|
|
102
|
+
suite,
|
|
103
|
+
file
|
|
104
|
+
}).run(() => {
|
|
105
|
+
});
|
|
106
|
+
createTest("add two numbers", emitter, refiner, { group, file }).run(() => {
|
|
107
|
+
assert.equal(2 + 2, 4);
|
|
108
|
+
});
|
|
109
|
+
createTest("add three numbers", emitter, refiner, {
|
|
110
|
+
group,
|
|
111
|
+
file
|
|
112
|
+
}).run(() => {
|
|
113
|
+
assert.equal(2 + 2 + 2, 6);
|
|
114
|
+
});
|
|
115
|
+
createTest("add group of numbers", emitter, refiner, { group, file });
|
|
116
|
+
createTest("use math.js lib", emitter, refiner, { group, file }).skip(
|
|
117
|
+
true,
|
|
118
|
+
"Library work pending"
|
|
119
|
+
);
|
|
120
|
+
createTest("add multiple numbers", emitter, refiner, {
|
|
121
|
+
file,
|
|
122
|
+
group
|
|
123
|
+
}).run(() => {
|
|
124
|
+
assert.equal(2 + 2 + 2 + 2, 6);
|
|
125
|
+
});
|
|
126
|
+
createTest("add floating numbers", emitter, refiner, { group, file }).run(() => {
|
|
127
|
+
assert.equal(2 + 2.2 + 2.1, 6);
|
|
128
|
+
}).fails("Have to add support for floating numbers");
|
|
129
|
+
createTest("A test with an error that is not an AssertionError", emitter, refiner, {
|
|
130
|
+
group,
|
|
131
|
+
file
|
|
132
|
+
}).run(() => {
|
|
133
|
+
throw new Error("This is an error");
|
|
134
|
+
});
|
|
135
|
+
return suite;
|
|
136
|
+
}
|
|
137
|
+
function createFunctionalTestsSuite(emitter, refiner, file) {
|
|
138
|
+
const suite = new Suite("functional", emitter, refiner);
|
|
139
|
+
const group = createTestGroup("Users/store", emitter, refiner, {
|
|
140
|
+
suite,
|
|
141
|
+
file
|
|
142
|
+
});
|
|
143
|
+
createTest("Validate user data", emitter, refiner, {
|
|
144
|
+
group,
|
|
145
|
+
file
|
|
146
|
+
}).run(() => {
|
|
147
|
+
});
|
|
148
|
+
createTest("Disallow duplicate emails", emitter, refiner, {
|
|
149
|
+
group,
|
|
150
|
+
file
|
|
151
|
+
}).run(() => {
|
|
152
|
+
});
|
|
153
|
+
createTest("Disallow duplicate emails across tenants", emitter, refiner, {
|
|
154
|
+
group,
|
|
155
|
+
file
|
|
156
|
+
}).run(() => {
|
|
157
|
+
const users = ["", ""];
|
|
158
|
+
assert.equal(users.length, 1);
|
|
159
|
+
});
|
|
160
|
+
createTest("Normalize email before persisting it", emitter, refiner, {
|
|
161
|
+
group,
|
|
162
|
+
file
|
|
163
|
+
}).skip(true, "Have to build a normalizer");
|
|
164
|
+
createTest("Send email verification mail", emitter, refiner, {
|
|
165
|
+
group,
|
|
166
|
+
file
|
|
167
|
+
});
|
|
168
|
+
const usersListGroup = createTestGroup("Users/list", emitter, refiner, {
|
|
169
|
+
suite,
|
|
170
|
+
file
|
|
171
|
+
});
|
|
172
|
+
usersListGroup.setup(() => {
|
|
173
|
+
throw new Error("Unable to cleanup database");
|
|
174
|
+
});
|
|
175
|
+
createTest("A test that will never because the group hooks fails", emitter, refiner, {
|
|
176
|
+
group: usersListGroup
|
|
177
|
+
});
|
|
178
|
+
createTest("A top level test inside functional suite", emitter, refiner, {
|
|
179
|
+
suite,
|
|
180
|
+
file
|
|
181
|
+
}).run(() => {
|
|
182
|
+
});
|
|
183
|
+
return suite;
|
|
184
|
+
}
|
|
185
|
+
function createDiverseTests(emitter, refiner, file) {
|
|
186
|
+
return [
|
|
187
|
+
createUnitTestsSuite(emitter, refiner, file),
|
|
188
|
+
createFunctionalTestsSuite(emitter, refiner, file)
|
|
189
|
+
];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// factories/main.ts
|
|
193
|
+
var runner = () => new RunnerFactory();
|
|
194
|
+
var syncReporter = {
|
|
195
|
+
name: "sync",
|
|
196
|
+
handler(r, emitter) {
|
|
197
|
+
emitter.on("runner:end", function() {
|
|
198
|
+
const summary = r.getSummary();
|
|
199
|
+
if (summary.hasError) {
|
|
200
|
+
if (summary.failureTree[0].errors.length) {
|
|
201
|
+
throw summary.failureTree[0].errors[0].error;
|
|
202
|
+
}
|
|
203
|
+
if (summary.failureTree[0].children[0].errors.length) {
|
|
204
|
+
throw summary.failureTree[0].children[0].errors[0].error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
export {
|
|
211
|
+
createDiverseTests,
|
|
212
|
+
runner,
|
|
213
|
+
syncReporter
|
|
214
|
+
};
|
|
215
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +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"]}
|