ScuttleBot

1
"use strict";
2
var __create = Object.create;
3
var __defProp = Object.defineProperty;
4
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
var __getOwnPropNames = Object.getOwnPropertyNames;
6
var __getProtoOf = Object.getPrototypeOf;
7
var __hasOwnProp = Object.prototype.hasOwnProperty;
8
var __export = (target, all) => {
9
for (var name in all)
10
__defProp(target, name, { get: all[name], enumerable: true });
11
};
12
var __copyProps = (to, from, except, desc) => {
13
if (from && typeof from === "object" || typeof from === "function") {
14
for (let key of __getOwnPropNames(from))
15
if (!__hasOwnProp.call(to, key) && key !== except)
16
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
}
18
return to;
19
};
20
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
// If the importer is in node compatibility mode or this is not an ESM
22
// file that has been converted to a CommonJS file using a Babel-
23
// compatible transform (i.e. "__esModule" has not been set), then set
24
// "default" to the CommonJS "module.exports" for node compatibility.
25
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
mod
27
));
28
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
var json_exports = {};
30
__export(json_exports, {
31
default: () => json_default,
32
serializePatterns: () => serializePatterns
33
});
34
module.exports = __toCommonJS(json_exports);
35
var import_fs = __toESM(require("fs"));
36
var import_path = __toESM(require("path"));
37
var import_utils = require("playwright-core/lib/utils");
38
var import_base = require("./base");
39
var import_config = require("../common/config");
40
class JSONReporter {
41
constructor(options) {
42
this._errors = [];
43
this._resolvedOutputFile = (0, import_base.resolveOutputFile)("JSON", options)?.outputFile;
44
}
45
version() {
46
return "v2";
47
}
48
printsToStdio() {
49
return !this._resolvedOutputFile;
50
}
51
onConfigure(config) {
52
this.config = config;
53
}
54
onBegin(suite) {
55
this.suite = suite;
56
}
57
onError(error) {
58
this._errors.push(error);
59
}
60
async onEnd(result) {
61
await outputReport(this._serializeReport(result), this._resolvedOutputFile);
62
}
63
_serializeReport(result) {
64
const report = {
65
config: {
66
...removePrivateFields(this.config),
67
rootDir: (0, import_utils.toPosixPath)(this.config.rootDir),
68
projects: this.config.projects.map((project) => {
69
return {
70
outputDir: (0, import_utils.toPosixPath)(project.outputDir),
71
repeatEach: project.repeatEach,
72
retries: project.retries,
73
metadata: project.metadata,
74
id: (0, import_config.getProjectId)(project),
75
name: project.name,
76
testDir: (0, import_utils.toPosixPath)(project.testDir),
77
testIgnore: serializePatterns(project.testIgnore),
78
testMatch: serializePatterns(project.testMatch),
79
timeout: project.timeout
80
};
81
})
82
},
83
suites: this._mergeSuites(this.suite.suites),
84
errors: this._errors,
85
stats: {
86
startTime: result.startTime.toISOString(),
87
duration: result.duration,
88
expected: 0,
89
skipped: 0,
90
unexpected: 0,
91
flaky: 0
92
}
93
};
94
for (const test of this.suite.allTests())
95
++report.stats[test.outcome()];
96
return report;
97
}
98
_mergeSuites(suites) {
99
const fileSuites = new import_utils.MultiMap();
100
for (const projectSuite of suites) {
101
const projectId = (0, import_config.getProjectId)(projectSuite.project());
102
const projectName = projectSuite.project().name;
103
for (const fileSuite of projectSuite.suites) {
104
const file = fileSuite.location.file;
105
const serialized = this._serializeSuite(projectId, projectName, fileSuite);
106
if (serialized)
107
fileSuites.set(file, serialized);
108
}
109
}
110
const results = [];
111
for (const [, suites2] of fileSuites) {
112
const result = {
113
title: suites2[0].title,
114
file: suites2[0].file,
115
column: 0,
116
line: 0,
117
specs: []
118
};
119
for (const suite of suites2)
120
this._mergeTestsFromSuite(result, suite);
121
results.push(result);
122
}
123
return results;
124
}
125
_relativeLocation(location) {
126
if (!location)
127
return { file: "", line: 0, column: 0 };
128
return {
129
file: (0, import_utils.toPosixPath)(import_path.default.relative(this.config.rootDir, location.file)),
130
line: location.line,
131
column: location.column
132
};
133
}
134
_locationMatches(s1, s2) {
135
return s1.file === s2.file && s1.line === s2.line && s1.column === s2.column;
136
}
137
_mergeTestsFromSuite(to, from) {
138
for (const fromSuite of from.suites || []) {
139
const toSuite = (to.suites || []).find((s) => s.title === fromSuite.title && this._locationMatches(s, fromSuite));
140
if (toSuite) {
141
this._mergeTestsFromSuite(toSuite, fromSuite);
142
} else {
143
if (!to.suites)
144
to.suites = [];
145
to.suites.push(fromSuite);
146
}
147
}
148
for (const spec of from.specs || []) {
149
const toSpec = to.specs.find((s) => s.title === spec.title && s.file === (0, import_utils.toPosixPath)(import_path.default.relative(this.config.rootDir, spec.file)) && s.line === spec.line && s.column === spec.column);
150
if (toSpec)
151
toSpec.tests.push(...spec.tests);
152
else
153
to.specs.push(spec);
154
}
155
}
156
_serializeSuite(projectId, projectName, suite) {
157
if (!suite.allTests().length)
158
return null;
159
const suites = suite.suites.map((suite2) => this._serializeSuite(projectId, projectName, suite2)).filter((s) => s);
160
return {
161
title: suite.title,
162
...this._relativeLocation(suite.location),
163
specs: suite.tests.map((test) => this._serializeTestSpec(projectId, projectName, test)),
164
suites: suites.length ? suites : void 0
165
};
166
}
167
_serializeTestSpec(projectId, projectName, test) {
168
return {
169
title: test.title,
170
ok: test.ok(),
171
tags: test.tags.map((tag) => tag.substring(1)),
172
// Strip '@'.
173
tests: [this._serializeTest(projectId, projectName, test)],
174
id: test.id,
175
...this._relativeLocation(test.location)
176
};
177
}
178
_serializeTest(projectId, projectName, test) {
179
return {
180
timeout: test.timeout,
181
annotations: test.annotations,
182
expectedStatus: test.expectedStatus,
183
projectId,
184
projectName,
185
results: test.results.map((r) => this._serializeTestResult(r, test)),
186
status: test.outcome()
187
};
188
}
189
_serializeTestResult(result, test) {
190
const steps = result.steps.filter((s) => s.category === "test.step");
191
const jsonResult = {
192
workerIndex: result.workerIndex,
193
parallelIndex: result.parallelIndex,
194
status: result.status,
195
duration: result.duration,
196
error: result.error,
197
errors: result.errors.map((e) => this._serializeError(e)),
198
stdout: result.stdout.map((s) => stdioEntry(s)),
199
stderr: result.stderr.map((s) => stdioEntry(s)),
200
retry: result.retry,
201
steps: steps.length ? steps.map((s) => this._serializeTestStep(s)) : void 0,
202
startTime: result.startTime.toISOString(),
203
annotations: result.annotations,
204
attachments: result.attachments.map((a) => ({
205
name: a.name,
206
contentType: a.contentType,
207
path: a.path,
208
body: a.body?.toString("base64")
209
}))
210
};
211
if (result.error?.stack)
212
jsonResult.errorLocation = (0, import_base.prepareErrorStack)(result.error.stack).location;
213
return jsonResult;
214
}
215
_serializeError(error) {
216
return (0, import_base.formatError)(import_base.nonTerminalScreen, error);
217
}
218
_serializeTestStep(step) {
219
const steps = step.steps.filter((s) => s.category === "test.step");
220
return {
221
title: step.title,
222
duration: step.duration,
223
error: step.error,
224
steps: steps.length ? steps.map((s) => this._serializeTestStep(s)) : void 0
225
};
226
}
227
}
228
async function outputReport(report, resolvedOutputFile) {
229
const reportString = JSON.stringify(report, void 0, 2);
230
if (resolvedOutputFile) {
231
await import_fs.default.promises.mkdir(import_path.default.dirname(resolvedOutputFile), { recursive: true });
232
await import_fs.default.promises.writeFile(resolvedOutputFile, reportString);
233
} else {
234
console.log(reportString);
235
}
236
}
237
function stdioEntry(s) {
238
if (typeof s === "string")
239
return { text: s };
240
return { buffer: s.toString("base64") };
241
}
242
function removePrivateFields(config) {
243
return Object.fromEntries(Object.entries(config).filter(([name, value]) => !name.startsWith("_")));
244
}
245
function serializePatterns(patterns) {
246
if (!Array.isArray(patterns))
247
patterns = [patterns];
248
return patterns.map((s) => s.toString());
249
}
250
var json_default = JSONReporter;
251
// Annotate the CommonJS export names for ESM import in node:
252
0 && (module.exports = {
253
serializePatterns
254
});
255

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button