@japa/runner 4.4.1 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -61
- package/build/chunk-2KG3PWR4.js +17 -0
- package/build/chunk-L7YZLDZD.js +340 -0
- package/build/chunk-RFKFNXTE.js +347 -0
- package/build/chunk-WNJXMFYL.js +520 -0
- package/build/factories/create_dummy_tests.d.ts +1 -1
- package/build/factories/main.d.ts +1 -1
- package/build/factories/main.js +232 -182
- package/build/factories/runner.d.ts +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.js +278 -214
- package/build/modules/core/main.js +21 -2
- package/build/modules/core/reporters/base.d.ts +1 -1
- package/build/src/create_test.d.ts +1 -1
- package/build/src/debug.d.ts +1 -1
- package/build/src/helpers.d.ts +2 -2
- package/build/src/hooks.d.ts +1 -1
- package/build/src/plugins/main.js +28 -20
- package/build/src/reporters/main.js +14 -3
- package/build/src/reporters/spec.d.ts +1 -1
- package/build/src/types.js +14 -7
- package/build/src/validator.d.ts +1 -1
- package/package.json +32 -29
- package/build/create_test-CuTGNCAf.js +0 -353
- package/build/helpers-BlHaYYTh.js +0 -241
- package/build/main-CB1nhl6c.js +0 -336
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseReporter,
|
|
3
|
+
colors,
|
|
4
|
+
icons
|
|
5
|
+
} from "./chunk-L7YZLDZD.js";
|
|
6
|
+
|
|
7
|
+
// src/reporters/dot.ts
|
|
8
|
+
var DotReporter = class extends BaseReporter {
|
|
9
|
+
/**
|
|
10
|
+
* When a test ended
|
|
11
|
+
*/
|
|
12
|
+
onTestEnd(payload) {
|
|
13
|
+
let output = "";
|
|
14
|
+
if (payload.isTodo) {
|
|
15
|
+
output = colors.cyan(icons.info);
|
|
16
|
+
} else if (payload.hasError) {
|
|
17
|
+
output = colors.red(icons.cross);
|
|
18
|
+
} else if (payload.isSkipped) {
|
|
19
|
+
output = colors.yellow(icons.bullet);
|
|
20
|
+
} else if (payload.isFailing) {
|
|
21
|
+
output = colors.magenta(icons.squareSmallFilled);
|
|
22
|
+
} else {
|
|
23
|
+
output = colors.green(icons.tick);
|
|
24
|
+
}
|
|
25
|
+
process.stdout.write(`${output}`);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* When test runner ended
|
|
29
|
+
*/
|
|
30
|
+
async end() {
|
|
31
|
+
console.log("");
|
|
32
|
+
await this.printSummary(this.runner.getSummary());
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// src/reporters/spec.ts
|
|
37
|
+
import ms from "ms";
|
|
38
|
+
import { relative } from "path";
|
|
39
|
+
var SpecReporter = class extends BaseReporter {
|
|
40
|
+
/**
|
|
41
|
+
* Tracking if the first event we get is for a test without any parent group
|
|
42
|
+
* We need this to decide the display style for tests without groups.
|
|
43
|
+
*/
|
|
44
|
+
#isFirstLoneTest = true;
|
|
45
|
+
/**
|
|
46
|
+
* Returns the icon for the test
|
|
47
|
+
*/
|
|
48
|
+
#getTestIcon(payload) {
|
|
49
|
+
if (payload.isTodo) {
|
|
50
|
+
return colors.cyan(icons.info);
|
|
51
|
+
}
|
|
52
|
+
if (payload.hasError) {
|
|
53
|
+
return colors.red(icons.cross);
|
|
54
|
+
}
|
|
55
|
+
if (payload.isSkipped) {
|
|
56
|
+
return colors.yellow(icons.bullet);
|
|
57
|
+
}
|
|
58
|
+
if (payload.isFailing) {
|
|
59
|
+
return colors.magenta(icons.squareSmallFilled);
|
|
60
|
+
}
|
|
61
|
+
return colors.green(icons.tick);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns the test message
|
|
65
|
+
*/
|
|
66
|
+
#getTestMessage(payload) {
|
|
67
|
+
const message = payload.title.expanded;
|
|
68
|
+
if (payload.isTodo) {
|
|
69
|
+
return colors.blue(message);
|
|
70
|
+
}
|
|
71
|
+
if (payload.hasError) {
|
|
72
|
+
return colors.red(message);
|
|
73
|
+
}
|
|
74
|
+
if (payload.isSkipped) {
|
|
75
|
+
return colors.yellow(message);
|
|
76
|
+
}
|
|
77
|
+
if (payload.isFailing) {
|
|
78
|
+
return colors.magenta(message);
|
|
79
|
+
}
|
|
80
|
+
return colors.grey(message);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Returns the subtext message for the test
|
|
84
|
+
*/
|
|
85
|
+
#getSubText(payload) {
|
|
86
|
+
if (payload.isSkipped && payload.skipReason) {
|
|
87
|
+
return colors.dim(`${icons.branch} ${colors.italic(payload.skipReason)}`);
|
|
88
|
+
}
|
|
89
|
+
if (!payload.isFailing) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (payload.hasError) {
|
|
93
|
+
const message = payload.errors.find((error) => error.phase === "test")?.error.message ?? `Test marked with ".fails()" must finish with an error`;
|
|
94
|
+
return colors.dim(`${icons.branch} ${colors.italic(message)}`);
|
|
95
|
+
}
|
|
96
|
+
if (payload.failReason) {
|
|
97
|
+
return colors.dim(`${icons.branch} ${colors.italic(payload.failReason)}`);
|
|
98
|
+
}
|
|
99
|
+
const testErrorMessage = payload.errors.find((error) => error.phase === "test");
|
|
100
|
+
if (testErrorMessage && testErrorMessage.error) {
|
|
101
|
+
return colors.dim(`${icons.branch} ${colors.italic(testErrorMessage.error.message)}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Returns the filename relative from the current working dir
|
|
106
|
+
*/
|
|
107
|
+
#getRelativeFilename(fileName) {
|
|
108
|
+
return relative(process.cwd(), fileName);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Prints the test details
|
|
112
|
+
*/
|
|
113
|
+
#printTest(payload) {
|
|
114
|
+
const icon = this.#getTestIcon(payload);
|
|
115
|
+
const message = this.#getTestMessage(payload);
|
|
116
|
+
const prefix = payload.isPinned ? colors.yellow("[PINNED] ") : "";
|
|
117
|
+
const indentation = this.currentFileName || this.currentGroupName ? " " : "";
|
|
118
|
+
const duration = colors.dim(`(${ms(Number(payload.duration.toFixed(2)))})`);
|
|
119
|
+
const retries = payload.retryAttempt && payload.retryAttempt > 1 ? colors.dim(`(x${payload.retryAttempt}) `) : "";
|
|
120
|
+
let subText = this.#getSubText(payload);
|
|
121
|
+
subText = subText ? `
|
|
122
|
+
${indentation} ${subText}` : "";
|
|
123
|
+
console.log(`${indentation}${icon} ${prefix}${retries}${message} ${duration}${subText}`);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Prints the group name
|
|
127
|
+
*/
|
|
128
|
+
#printGroup(payload) {
|
|
129
|
+
const title = this.currentSuiteName !== "default" ? `${this.currentSuiteName} / ${payload.title}` : payload.title;
|
|
130
|
+
const suffix = this.currentFileName ? colors.dim(` (${this.#getRelativeFilename(this.currentFileName)})`) : "";
|
|
131
|
+
console.log(`
|
|
132
|
+
${title}${suffix}`);
|
|
133
|
+
}
|
|
134
|
+
onTestStart() {
|
|
135
|
+
if (this.currentFileName && this.#isFirstLoneTest) {
|
|
136
|
+
console.log(`
|
|
137
|
+
${colors.dim(this.#getRelativeFilename(this.currentFileName))}`);
|
|
138
|
+
}
|
|
139
|
+
this.#isFirstLoneTest = false;
|
|
140
|
+
}
|
|
141
|
+
onTestEnd(payload) {
|
|
142
|
+
this.#printTest(payload);
|
|
143
|
+
}
|
|
144
|
+
onGroupStart(payload) {
|
|
145
|
+
this.#isFirstLoneTest = false;
|
|
146
|
+
this.#printGroup(payload);
|
|
147
|
+
}
|
|
148
|
+
onGroupEnd() {
|
|
149
|
+
this.#isFirstLoneTest = true;
|
|
150
|
+
}
|
|
151
|
+
async end() {
|
|
152
|
+
const summary = this.runner.getSummary();
|
|
153
|
+
await this.printSummary(summary);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// src/reporters/ndjson.ts
|
|
158
|
+
import { relative as relative2 } from "path";
|
|
159
|
+
import { serializeError } from "serialize-error";
|
|
160
|
+
var NdJSONReporter = class extends BaseReporter {
|
|
161
|
+
/**
|
|
162
|
+
* Returns the filename relative from the current working dir
|
|
163
|
+
*/
|
|
164
|
+
#getRelativeFilename(fileName) {
|
|
165
|
+
return relative2(process.cwd(), fileName);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Serialize errors to JSON
|
|
169
|
+
*/
|
|
170
|
+
#serializeErrors(errors) {
|
|
171
|
+
return errors.map((error) => ({
|
|
172
|
+
phase: error.phase,
|
|
173
|
+
error: serializeError(error.error)
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
onTestEnd(payload) {
|
|
177
|
+
console.log(
|
|
178
|
+
JSON.stringify({
|
|
179
|
+
event: "test:end",
|
|
180
|
+
filePath: this.currentFileName,
|
|
181
|
+
relativePath: this.currentFileName ? this.#getRelativeFilename(this.currentFileName) : void 0,
|
|
182
|
+
title: payload.title,
|
|
183
|
+
duration: payload.duration,
|
|
184
|
+
failReason: payload.failReason,
|
|
185
|
+
isFailing: payload.isFailing,
|
|
186
|
+
skipReason: payload.skipReason,
|
|
187
|
+
isSkipped: payload.isSkipped,
|
|
188
|
+
isTodo: payload.isTodo,
|
|
189
|
+
isPinned: payload.isPinned,
|
|
190
|
+
retryAttempt: payload.retryAttempt,
|
|
191
|
+
retries: payload.retries,
|
|
192
|
+
errors: this.#serializeErrors(payload.errors)
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
onGroupStart(payload) {
|
|
197
|
+
console.log(
|
|
198
|
+
JSON.stringify({
|
|
199
|
+
event: "group:start",
|
|
200
|
+
title: payload.title
|
|
201
|
+
})
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
onGroupEnd(payload) {
|
|
205
|
+
JSON.stringify({
|
|
206
|
+
event: "group:end",
|
|
207
|
+
title: payload.title,
|
|
208
|
+
errors: this.#serializeErrors(payload.errors)
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
onSuiteStart(payload) {
|
|
212
|
+
console.log(
|
|
213
|
+
JSON.stringify({
|
|
214
|
+
event: "suite:start",
|
|
215
|
+
...payload
|
|
216
|
+
})
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
onSuiteEnd(payload) {
|
|
220
|
+
console.log(
|
|
221
|
+
JSON.stringify({
|
|
222
|
+
event: "suite:end",
|
|
223
|
+
name: payload.name,
|
|
224
|
+
hasError: payload.hasError,
|
|
225
|
+
errors: this.#serializeErrors(payload.errors)
|
|
226
|
+
})
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
async end() {
|
|
230
|
+
const summary = this.runner.getSummary();
|
|
231
|
+
console.log(
|
|
232
|
+
JSON.stringify({
|
|
233
|
+
aggregates: summary.aggregates,
|
|
234
|
+
duration: summary.duration,
|
|
235
|
+
failedTestsTitles: summary.failedTestsTitles,
|
|
236
|
+
hasError: summary.hasError
|
|
237
|
+
})
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// src/reporters/github.ts
|
|
243
|
+
import slash from "slash";
|
|
244
|
+
import { relative as relative3 } from "path";
|
|
245
|
+
import { stripVTControlCharacters } from "util";
|
|
246
|
+
import { ErrorsPrinter } from "@japa/errors-printer";
|
|
247
|
+
var GithubReporter = class extends BaseReporter {
|
|
248
|
+
/**
|
|
249
|
+
* Performs string escape on annotation message as per
|
|
250
|
+
* https://github.com/actions/toolkit/blob/f1d9b4b985e6f0f728b4b766db73498403fd5ca3/packages/core/src/command.ts#L80-L85
|
|
251
|
+
*/
|
|
252
|
+
escapeMessage(value) {
|
|
253
|
+
return value.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Performs string escape on annotation properties as per
|
|
257
|
+
* https://github.com/actions/toolkit/blob/f1d9b4b985e6f0f728b4b766db73498403fd5ca3/packages/core/src/command.ts#L80-L85
|
|
258
|
+
*/
|
|
259
|
+
escapeProperty(value) {
|
|
260
|
+
return value.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A").replace(/:/g, "%3A").replace(/,/g, "%2C");
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Formats the message as per the Github annotations spec.
|
|
264
|
+
* https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message
|
|
265
|
+
*/
|
|
266
|
+
formatMessage({
|
|
267
|
+
command,
|
|
268
|
+
properties,
|
|
269
|
+
message
|
|
270
|
+
}) {
|
|
271
|
+
let result = `::${command}`;
|
|
272
|
+
Object.entries(properties).forEach(([k, v], i) => {
|
|
273
|
+
result += i === 0 ? " " : ",";
|
|
274
|
+
result += `${k}=${this.escapeProperty(v)}`;
|
|
275
|
+
});
|
|
276
|
+
result += `::${this.escapeMessage(message)}`;
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Prints Github annotation for a given error
|
|
281
|
+
*/
|
|
282
|
+
async getErrorAnnotation(printer, error) {
|
|
283
|
+
const parsedError = await printer.parseError(error.error);
|
|
284
|
+
if (!("frames" in parsedError)) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const mainFrame = parsedError.frames.find((frame) => frame.type === "app");
|
|
288
|
+
if (!mainFrame) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
return this.formatMessage({
|
|
292
|
+
command: "error",
|
|
293
|
+
properties: {
|
|
294
|
+
file: slash(relative3(process.cwd(), mainFrame.fileName)),
|
|
295
|
+
title: error.title,
|
|
296
|
+
line: String(mainFrame.lineNumber),
|
|
297
|
+
column: String(mainFrame.columnNumber)
|
|
298
|
+
},
|
|
299
|
+
message: stripVTControlCharacters(parsedError.message)
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
async end() {
|
|
303
|
+
const summary = this.runner.getSummary();
|
|
304
|
+
const errorsList = this.aggregateErrors(summary);
|
|
305
|
+
const errorPrinter = new ErrorsPrinter(this.options);
|
|
306
|
+
for (let error of errorsList) {
|
|
307
|
+
const formatted = await this.getErrorAnnotation(errorPrinter, error);
|
|
308
|
+
if (formatted) {
|
|
309
|
+
console.log(`
|
|
310
|
+
${formatted}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// src/reporters/main.ts
|
|
317
|
+
var spec = (options) => {
|
|
318
|
+
return {
|
|
319
|
+
name: "spec",
|
|
320
|
+
handler: (...args) => new SpecReporter(options).boot(...args)
|
|
321
|
+
};
|
|
322
|
+
};
|
|
323
|
+
var dot = (options) => {
|
|
324
|
+
return {
|
|
325
|
+
name: "dot",
|
|
326
|
+
handler: (...args) => new DotReporter(options).boot(...args)
|
|
327
|
+
};
|
|
328
|
+
};
|
|
329
|
+
var ndjson = (options) => {
|
|
330
|
+
return {
|
|
331
|
+
name: "ndjson",
|
|
332
|
+
handler: (...args) => new NdJSONReporter(options).boot(...args)
|
|
333
|
+
};
|
|
334
|
+
};
|
|
335
|
+
var github = (options) => {
|
|
336
|
+
return {
|
|
337
|
+
name: "github",
|
|
338
|
+
handler: (...args) => new GithubReporter(options).boot(...args)
|
|
339
|
+
};
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
export {
|
|
343
|
+
spec,
|
|
344
|
+
dot,
|
|
345
|
+
ndjson,
|
|
346
|
+
github
|
|
347
|
+
};
|