|
f7eb47b…
|
lmata
|
1 |
"use strict"; |
|
f7eb47b…
|
lmata
|
2 |
var __create = Object.create; |
|
f7eb47b…
|
lmata
|
3 |
var __defProp = Object.defineProperty; |
|
f7eb47b…
|
lmata
|
4 |
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; |
|
f7eb47b…
|
lmata
|
5 |
var __getOwnPropNames = Object.getOwnPropertyNames; |
|
f7eb47b…
|
lmata
|
6 |
var __getProtoOf = Object.getPrototypeOf; |
|
f7eb47b…
|
lmata
|
7 |
var __hasOwnProp = Object.prototype.hasOwnProperty; |
|
f7eb47b…
|
lmata
|
8 |
var __export = (target, all) => { |
|
f7eb47b…
|
lmata
|
9 |
for (var name in all) |
|
f7eb47b…
|
lmata
|
10 |
__defProp(target, name, { get: all[name], enumerable: true }); |
|
f7eb47b…
|
lmata
|
11 |
}; |
|
f7eb47b…
|
lmata
|
12 |
var __copyProps = (to, from, except, desc) => { |
|
f7eb47b…
|
lmata
|
13 |
if (from && typeof from === "object" || typeof from === "function") { |
|
f7eb47b…
|
lmata
|
14 |
for (let key of __getOwnPropNames(from)) |
|
f7eb47b…
|
lmata
|
15 |
if (!__hasOwnProp.call(to, key) && key !== except) |
|
f7eb47b…
|
lmata
|
16 |
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); |
|
f7eb47b…
|
lmata
|
17 |
} |
|
f7eb47b…
|
lmata
|
18 |
return to; |
|
f7eb47b…
|
lmata
|
19 |
}; |
|
f7eb47b…
|
lmata
|
20 |
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( |
|
f7eb47b…
|
lmata
|
21 |
// If the importer is in node compatibility mode or this is not an ESM |
|
f7eb47b…
|
lmata
|
22 |
// file that has been converted to a CommonJS file using a Babel- |
|
f7eb47b…
|
lmata
|
23 |
// compatible transform (i.e. "__esModule" has not been set), then set |
|
f7eb47b…
|
lmata
|
24 |
// "default" to the CommonJS "module.exports" for node compatibility. |
|
f7eb47b…
|
lmata
|
25 |
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, |
|
f7eb47b…
|
lmata
|
26 |
mod |
|
f7eb47b…
|
lmata
|
27 |
)); |
|
f7eb47b…
|
lmata
|
28 |
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); |
|
f7eb47b…
|
lmata
|
29 |
var merge_exports = {}; |
|
f7eb47b…
|
lmata
|
30 |
__export(merge_exports, { |
|
f7eb47b…
|
lmata
|
31 |
createMergedReport: () => createMergedReport |
|
f7eb47b…
|
lmata
|
32 |
}); |
|
f7eb47b…
|
lmata
|
33 |
module.exports = __toCommonJS(merge_exports); |
|
f7eb47b…
|
lmata
|
34 |
var import_fs = __toESM(require("fs")); |
|
f7eb47b…
|
lmata
|
35 |
var import_path = __toESM(require("path")); |
|
f7eb47b…
|
lmata
|
36 |
var import_utils = require("playwright-core/lib/utils"); |
|
f7eb47b…
|
lmata
|
37 |
var import_blob = require("./blob"); |
|
f7eb47b…
|
lmata
|
38 |
var import_multiplexer = require("./multiplexer"); |
|
f7eb47b…
|
lmata
|
39 |
var import_stringInternPool = require("../isomorphic/stringInternPool"); |
|
f7eb47b…
|
lmata
|
40 |
var import_teleReceiver = require("../isomorphic/teleReceiver"); |
|
f7eb47b…
|
lmata
|
41 |
var import_reporters = require("../runner/reporters"); |
|
f7eb47b…
|
lmata
|
42 |
var import_util = require("../util"); |
|
f7eb47b…
|
lmata
|
43 |
async function createMergedReport(config, dir, reporterDescriptions, rootDirOverride) { |
|
f7eb47b…
|
lmata
|
44 |
const reporters = await (0, import_reporters.createReporters)(config, "merge", reporterDescriptions); |
|
f7eb47b…
|
lmata
|
45 |
const multiplexer = new import_multiplexer.Multiplexer(reporters); |
|
f7eb47b…
|
lmata
|
46 |
const stringPool = new import_stringInternPool.StringInternPool(); |
|
f7eb47b…
|
lmata
|
47 |
let printStatus = () => { |
|
f7eb47b…
|
lmata
|
48 |
}; |
|
f7eb47b…
|
lmata
|
49 |
if (!multiplexer.printsToStdio()) { |
|
f7eb47b…
|
lmata
|
50 |
printStatus = printStatusToStdout; |
|
f7eb47b…
|
lmata
|
51 |
printStatus(`merging reports from ${dir}`); |
|
f7eb47b…
|
lmata
|
52 |
} |
|
f7eb47b…
|
lmata
|
53 |
const shardFiles = await sortedShardFiles(dir); |
|
f7eb47b…
|
lmata
|
54 |
if (shardFiles.length === 0) |
|
f7eb47b…
|
lmata
|
55 |
throw new Error(`No report files found in ${dir}`); |
|
f7eb47b…
|
lmata
|
56 |
const eventData = await mergeEvents(dir, shardFiles, stringPool, printStatus, rootDirOverride); |
|
f7eb47b…
|
lmata
|
57 |
const pathSeparator = rootDirOverride ? import_path.default.sep : eventData.pathSeparatorFromMetadata ?? import_path.default.sep; |
|
f7eb47b…
|
lmata
|
58 |
const pathPackage = pathSeparator === "/" ? import_path.default.posix : import_path.default.win32; |
|
f7eb47b…
|
lmata
|
59 |
const receiver = new import_teleReceiver.TeleReporterReceiver(multiplexer, { |
|
f7eb47b…
|
lmata
|
60 |
mergeProjects: false, |
|
f7eb47b…
|
lmata
|
61 |
mergeTestCases: false, |
|
f7eb47b…
|
lmata
|
62 |
// When merging on a different OS, an absolute path like `C:\foo\bar` from win may look like |
|
f7eb47b…
|
lmata
|
63 |
// a relative path on posix, and vice versa. |
|
f7eb47b…
|
lmata
|
64 |
// Therefore, we cannot use `path.resolve()` here - it will resolve relative-looking paths |
|
f7eb47b…
|
lmata
|
65 |
// against `process.cwd()`, while we just want to normalize ".." and "." segments. |
|
f7eb47b…
|
lmata
|
66 |
resolvePath: (rootDir, relativePath) => stringPool.internString(pathPackage.normalize(pathPackage.join(rootDir, relativePath))), |
|
f7eb47b…
|
lmata
|
67 |
configOverrides: config.config |
|
f7eb47b…
|
lmata
|
68 |
}); |
|
f7eb47b…
|
lmata
|
69 |
printStatus(`processing test events`); |
|
f7eb47b…
|
lmata
|
70 |
const dispatchEvents = async (events) => { |
|
f7eb47b…
|
lmata
|
71 |
for (const event of events) { |
|
f7eb47b…
|
lmata
|
72 |
if (event.method === "onEnd") |
|
f7eb47b…
|
lmata
|
73 |
printStatus(`building final report`); |
|
f7eb47b…
|
lmata
|
74 |
await receiver.dispatch(event); |
|
f7eb47b…
|
lmata
|
75 |
if (event.method === "onEnd") |
|
f7eb47b…
|
lmata
|
76 |
printStatus(`finished building report`); |
|
f7eb47b…
|
lmata
|
77 |
} |
|
f7eb47b…
|
lmata
|
78 |
}; |
|
f7eb47b…
|
lmata
|
79 |
await dispatchEvents(eventData.prologue); |
|
f7eb47b…
|
lmata
|
80 |
for (const { reportFile, eventPatchers, metadata, tags, startTime, duration } of eventData.reports) { |
|
f7eb47b…
|
lmata
|
81 |
const reportJsonl = await import_fs.default.promises.readFile(reportFile); |
|
f7eb47b…
|
lmata
|
82 |
const events = parseTestEvents(reportJsonl); |
|
f7eb47b…
|
lmata
|
83 |
new import_stringInternPool.JsonStringInternalizer(stringPool).traverse(events); |
|
f7eb47b…
|
lmata
|
84 |
eventPatchers.patchers.push(new AttachmentPathPatcher(dir)); |
|
f7eb47b…
|
lmata
|
85 |
if (metadata.name) |
|
f7eb47b…
|
lmata
|
86 |
eventPatchers.patchers.push(new GlobalErrorPatcher(metadata.name)); |
|
f7eb47b…
|
lmata
|
87 |
if (tags.length) |
|
f7eb47b…
|
lmata
|
88 |
eventPatchers.patchers.push(new GlobalErrorPatcher(tags.join(" "))); |
|
f7eb47b…
|
lmata
|
89 |
eventPatchers.patchEvents(events); |
|
f7eb47b…
|
lmata
|
90 |
await dispatchEvents(events); |
|
f7eb47b…
|
lmata
|
91 |
multiplexer.onMachineEnd({ |
|
f7eb47b…
|
lmata
|
92 |
startTime: new Date(startTime), |
|
f7eb47b…
|
lmata
|
93 |
duration, |
|
f7eb47b…
|
lmata
|
94 |
tag: tags, |
|
f7eb47b…
|
lmata
|
95 |
shardIndex: metadata.shard?.current |
|
f7eb47b…
|
lmata
|
96 |
}); |
|
f7eb47b…
|
lmata
|
97 |
} |
|
f7eb47b…
|
lmata
|
98 |
await dispatchEvents(eventData.epilogue); |
|
f7eb47b…
|
lmata
|
99 |
} |
|
f7eb47b…
|
lmata
|
100 |
const commonEventNames = ["onBlobReportMetadata", "onConfigure", "onProject", "onBegin", "onEnd"]; |
|
f7eb47b…
|
lmata
|
101 |
const commonEvents = new Set(commonEventNames); |
|
f7eb47b…
|
lmata
|
102 |
const commonEventRegex = new RegExp(`${commonEventNames.join("|")}`); |
|
f7eb47b…
|
lmata
|
103 |
function parseCommonEvents(reportJsonl) { |
|
f7eb47b…
|
lmata
|
104 |
return splitBufferLines(reportJsonl).map((line) => line.toString("utf8")).filter((line) => commonEventRegex.test(line)).map((line) => JSON.parse(line)).filter((event) => commonEvents.has(event.method)); |
|
f7eb47b…
|
lmata
|
105 |
} |
|
f7eb47b…
|
lmata
|
106 |
function parseTestEvents(reportJsonl) { |
|
f7eb47b…
|
lmata
|
107 |
return splitBufferLines(reportJsonl).map((line) => line.toString("utf8")).filter((line) => line.length).map((line) => JSON.parse(line)).filter((event) => !commonEvents.has(event.method)); |
|
f7eb47b…
|
lmata
|
108 |
} |
|
f7eb47b…
|
lmata
|
109 |
function splitBufferLines(buffer) { |
|
f7eb47b…
|
lmata
|
110 |
const lines = []; |
|
f7eb47b…
|
lmata
|
111 |
let start = 0; |
|
f7eb47b…
|
lmata
|
112 |
while (start < buffer.length) { |
|
f7eb47b…
|
lmata
|
113 |
const end = buffer.indexOf(10, start); |
|
f7eb47b…
|
lmata
|
114 |
if (end === -1) { |
|
f7eb47b…
|
lmata
|
115 |
lines.push(buffer.slice(start)); |
|
f7eb47b…
|
lmata
|
116 |
break; |
|
f7eb47b…
|
lmata
|
117 |
} |
|
f7eb47b…
|
lmata
|
118 |
lines.push(buffer.slice(start, end)); |
|
f7eb47b…
|
lmata
|
119 |
start = end + 1; |
|
f7eb47b…
|
lmata
|
120 |
} |
|
f7eb47b…
|
lmata
|
121 |
return lines; |
|
f7eb47b…
|
lmata
|
122 |
} |
|
f7eb47b…
|
lmata
|
123 |
async function extractAndParseReports(dir, shardFiles, internalizer, printStatus) { |
|
f7eb47b…
|
lmata
|
124 |
const shardEvents = []; |
|
f7eb47b…
|
lmata
|
125 |
await import_fs.default.promises.mkdir(import_path.default.join(dir, "resources"), { recursive: true }); |
|
f7eb47b…
|
lmata
|
126 |
const reportNames = new UniqueFileNameGenerator(); |
|
f7eb47b…
|
lmata
|
127 |
for (const file of shardFiles) { |
|
f7eb47b…
|
lmata
|
128 |
const absolutePath = import_path.default.join(dir, file); |
|
f7eb47b…
|
lmata
|
129 |
printStatus(`extracting: ${(0, import_util.relativeFilePath)(absolutePath)}`); |
|
f7eb47b…
|
lmata
|
130 |
const zipFile = new import_utils.ZipFile(absolutePath); |
|
f7eb47b…
|
lmata
|
131 |
const entryNames = await zipFile.entries(); |
|
f7eb47b…
|
lmata
|
132 |
for (const entryName of entryNames.sort()) { |
|
f7eb47b…
|
lmata
|
133 |
let fileName = import_path.default.join(dir, entryName); |
|
f7eb47b…
|
lmata
|
134 |
const content = await zipFile.read(entryName); |
|
f7eb47b…
|
lmata
|
135 |
if (entryName.endsWith(".jsonl")) { |
|
f7eb47b…
|
lmata
|
136 |
fileName = reportNames.makeUnique(fileName); |
|
f7eb47b…
|
lmata
|
137 |
let parsedEvents = parseCommonEvents(content); |
|
f7eb47b…
|
lmata
|
138 |
internalizer.traverse(parsedEvents); |
|
f7eb47b…
|
lmata
|
139 |
const metadata = findMetadata(parsedEvents, file); |
|
f7eb47b…
|
lmata
|
140 |
parsedEvents = modernizer.modernize(metadata.version, parsedEvents); |
|
f7eb47b…
|
lmata
|
141 |
shardEvents.push({ |
|
f7eb47b…
|
lmata
|
142 |
file, |
|
f7eb47b…
|
lmata
|
143 |
localPath: fileName, |
|
f7eb47b…
|
lmata
|
144 |
metadata, |
|
f7eb47b…
|
lmata
|
145 |
parsedEvents |
|
f7eb47b…
|
lmata
|
146 |
}); |
|
f7eb47b…
|
lmata
|
147 |
} |
|
f7eb47b…
|
lmata
|
148 |
await import_fs.default.promises.writeFile(fileName, content); |
|
f7eb47b…
|
lmata
|
149 |
} |
|
f7eb47b…
|
lmata
|
150 |
zipFile.close(); |
|
f7eb47b…
|
lmata
|
151 |
} |
|
f7eb47b…
|
lmata
|
152 |
return shardEvents; |
|
f7eb47b…
|
lmata
|
153 |
} |
|
f7eb47b…
|
lmata
|
154 |
function findMetadata(events, file) { |
|
f7eb47b…
|
lmata
|
155 |
if (events[0]?.method !== "onBlobReportMetadata") |
|
f7eb47b…
|
lmata
|
156 |
throw new Error(`No metadata event found in ${file}`); |
|
f7eb47b…
|
lmata
|
157 |
const metadata = events[0].params; |
|
f7eb47b…
|
lmata
|
158 |
if (metadata.version > import_blob.currentBlobReportVersion) |
|
f7eb47b…
|
lmata
|
159 |
throw new Error(`Blob report ${file} was created with a newer version of Playwright.`); |
|
f7eb47b…
|
lmata
|
160 |
return metadata; |
|
f7eb47b…
|
lmata
|
161 |
} |
|
f7eb47b…
|
lmata
|
162 |
async function mergeEvents(dir, shardReportFiles, stringPool, printStatus, rootDirOverride) { |
|
f7eb47b…
|
lmata
|
163 |
const internalizer = new import_stringInternPool.JsonStringInternalizer(stringPool); |
|
f7eb47b…
|
lmata
|
164 |
const configureEvents = []; |
|
f7eb47b…
|
lmata
|
165 |
const projectEvents = []; |
|
f7eb47b…
|
lmata
|
166 |
const endEvents = []; |
|
f7eb47b…
|
lmata
|
167 |
const blobs = await extractAndParseReports(dir, shardReportFiles, internalizer, printStatus); |
|
f7eb47b…
|
lmata
|
168 |
blobs.sort((a, b) => { |
|
f7eb47b…
|
lmata
|
169 |
const nameA = a.metadata.name ?? ""; |
|
f7eb47b…
|
lmata
|
170 |
const nameB = b.metadata.name ?? ""; |
|
f7eb47b…
|
lmata
|
171 |
if (nameA !== nameB) |
|
f7eb47b…
|
lmata
|
172 |
return nameA.localeCompare(nameB); |
|
f7eb47b…
|
lmata
|
173 |
const shardA = a.metadata.shard?.current ?? 0; |
|
f7eb47b…
|
lmata
|
174 |
const shardB = b.metadata.shard?.current ?? 0; |
|
f7eb47b…
|
lmata
|
175 |
if (shardA !== shardB) |
|
f7eb47b…
|
lmata
|
176 |
return shardA - shardB; |
|
f7eb47b…
|
lmata
|
177 |
return a.file.localeCompare(b.file); |
|
f7eb47b…
|
lmata
|
178 |
}); |
|
f7eb47b…
|
lmata
|
179 |
printStatus(`merging events`); |
|
f7eb47b…
|
lmata
|
180 |
const reports = []; |
|
f7eb47b…
|
lmata
|
181 |
const globalTestIdSet = /* @__PURE__ */ new Set(); |
|
f7eb47b…
|
lmata
|
182 |
for (let i = 0; i < blobs.length; ++i) { |
|
f7eb47b…
|
lmata
|
183 |
const { parsedEvents, metadata, localPath } = blobs[i]; |
|
f7eb47b…
|
lmata
|
184 |
const eventPatchers = new JsonEventPatchers(); |
|
f7eb47b…
|
lmata
|
185 |
eventPatchers.patchers.push(new IdsPatcher( |
|
f7eb47b…
|
lmata
|
186 |
stringPool, |
|
f7eb47b…
|
lmata
|
187 |
metadata.name, |
|
f7eb47b…
|
lmata
|
188 |
String(i), |
|
f7eb47b…
|
lmata
|
189 |
globalTestIdSet |
|
f7eb47b…
|
lmata
|
190 |
)); |
|
f7eb47b…
|
lmata
|
191 |
if (rootDirOverride) |
|
f7eb47b…
|
lmata
|
192 |
eventPatchers.patchers.push(new PathSeparatorPatcher(metadata.pathSeparator)); |
|
f7eb47b…
|
lmata
|
193 |
eventPatchers.patchEvents(parsedEvents); |
|
f7eb47b…
|
lmata
|
194 |
let tags = []; |
|
f7eb47b…
|
lmata
|
195 |
let startTime = 0; |
|
f7eb47b…
|
lmata
|
196 |
let duration = 0; |
|
f7eb47b…
|
lmata
|
197 |
for (const event of parsedEvents) { |
|
f7eb47b…
|
lmata
|
198 |
if (event.method === "onConfigure") { |
|
f7eb47b…
|
lmata
|
199 |
configureEvents.push(event); |
|
f7eb47b…
|
lmata
|
200 |
tags = event.params.config.tags || []; |
|
f7eb47b…
|
lmata
|
201 |
} else if (event.method === "onProject") { |
|
f7eb47b…
|
lmata
|
202 |
projectEvents.push(event); |
|
f7eb47b…
|
lmata
|
203 |
} else if (event.method === "onEnd") { |
|
f7eb47b…
|
lmata
|
204 |
endEvents.push({ event, metadata, tags }); |
|
f7eb47b…
|
lmata
|
205 |
startTime = event.params.result.startTime; |
|
f7eb47b…
|
lmata
|
206 |
duration = event.params.result.duration; |
|
f7eb47b…
|
lmata
|
207 |
} |
|
f7eb47b…
|
lmata
|
208 |
} |
|
f7eb47b…
|
lmata
|
209 |
reports.push({ |
|
f7eb47b…
|
lmata
|
210 |
eventPatchers, |
|
f7eb47b…
|
lmata
|
211 |
reportFile: localPath, |
|
f7eb47b…
|
lmata
|
212 |
metadata, |
|
f7eb47b…
|
lmata
|
213 |
tags, |
|
f7eb47b…
|
lmata
|
214 |
startTime, |
|
f7eb47b…
|
lmata
|
215 |
duration |
|
f7eb47b…
|
lmata
|
216 |
}); |
|
f7eb47b…
|
lmata
|
217 |
} |
|
f7eb47b…
|
lmata
|
218 |
return { |
|
f7eb47b…
|
lmata
|
219 |
prologue: [ |
|
f7eb47b…
|
lmata
|
220 |
mergeConfigureEvents(configureEvents, rootDirOverride), |
|
f7eb47b…
|
lmata
|
221 |
...projectEvents, |
|
f7eb47b…
|
lmata
|
222 |
{ method: "onBegin", params: void 0 } |
|
f7eb47b…
|
lmata
|
223 |
], |
|
f7eb47b…
|
lmata
|
224 |
reports, |
|
f7eb47b…
|
lmata
|
225 |
epilogue: [ |
|
f7eb47b…
|
lmata
|
226 |
mergeEndEvents(endEvents), |
|
f7eb47b…
|
lmata
|
227 |
{ method: "onExit", params: void 0 } |
|
f7eb47b…
|
lmata
|
228 |
], |
|
f7eb47b…
|
lmata
|
229 |
pathSeparatorFromMetadata: blobs[0]?.metadata.pathSeparator |
|
f7eb47b…
|
lmata
|
230 |
}; |
|
f7eb47b…
|
lmata
|
231 |
} |
|
f7eb47b…
|
lmata
|
232 |
function mergeConfigureEvents(configureEvents, rootDirOverride) { |
|
f7eb47b…
|
lmata
|
233 |
if (!configureEvents.length) |
|
f7eb47b…
|
lmata
|
234 |
throw new Error("No configure events found"); |
|
f7eb47b…
|
lmata
|
235 |
let config = { |
|
f7eb47b…
|
lmata
|
236 |
configFile: void 0, |
|
f7eb47b…
|
lmata
|
237 |
globalTimeout: 0, |
|
f7eb47b…
|
lmata
|
238 |
maxFailures: 0, |
|
f7eb47b…
|
lmata
|
239 |
metadata: {}, |
|
f7eb47b…
|
lmata
|
240 |
rootDir: "", |
|
f7eb47b…
|
lmata
|
241 |
version: "", |
|
f7eb47b…
|
lmata
|
242 |
workers: 0, |
|
f7eb47b…
|
lmata
|
243 |
globalSetup: null, |
|
f7eb47b…
|
lmata
|
244 |
globalTeardown: null |
|
f7eb47b…
|
lmata
|
245 |
}; |
|
f7eb47b…
|
lmata
|
246 |
for (const event of configureEvents) |
|
f7eb47b…
|
lmata
|
247 |
config = mergeConfigs(config, event.params.config); |
|
f7eb47b…
|
lmata
|
248 |
if (rootDirOverride) { |
|
f7eb47b…
|
lmata
|
249 |
config.rootDir = rootDirOverride; |
|
f7eb47b…
|
lmata
|
250 |
} else { |
|
f7eb47b…
|
lmata
|
251 |
const rootDirs = new Set(configureEvents.map((e) => e.params.config.rootDir)); |
|
f7eb47b…
|
lmata
|
252 |
if (rootDirs.size > 1) { |
|
f7eb47b…
|
lmata
|
253 |
throw new Error([ |
|
f7eb47b…
|
lmata
|
254 |
`Blob reports being merged were recorded with different test directories, and`, |
|
f7eb47b…
|
lmata
|
255 |
`merging cannot proceed. This may happen if you are merging reports from`, |
|
f7eb47b…
|
lmata
|
256 |
`machines with different environments, like different operating systems or`, |
|
f7eb47b…
|
lmata
|
257 |
`if the tests ran with different playwright configs.`, |
|
f7eb47b…
|
lmata
|
258 |
``, |
|
f7eb47b…
|
lmata
|
259 |
`You can force merge by specifying a merge config file with "-c" option. If`, |
|
f7eb47b…
|
lmata
|
260 |
`you'd like all test paths to be correct, make sure 'testDir' in the merge config`, |
|
f7eb47b…
|
lmata
|
261 |
`file points to the actual tests location.`, |
|
f7eb47b…
|
lmata
|
262 |
``, |
|
f7eb47b…
|
lmata
|
263 |
`Found directories:`, |
|
f7eb47b…
|
lmata
|
264 |
...rootDirs |
|
f7eb47b…
|
lmata
|
265 |
].join("\n")); |
|
f7eb47b…
|
lmata
|
266 |
} |
|
f7eb47b…
|
lmata
|
267 |
} |
|
f7eb47b…
|
lmata
|
268 |
return { |
|
f7eb47b…
|
lmata
|
269 |
method: "onConfigure", |
|
f7eb47b…
|
lmata
|
270 |
params: { |
|
f7eb47b…
|
lmata
|
271 |
config |
|
f7eb47b…
|
lmata
|
272 |
} |
|
f7eb47b…
|
lmata
|
273 |
}; |
|
f7eb47b…
|
lmata
|
274 |
} |
|
f7eb47b…
|
lmata
|
275 |
function mergeConfigs(to, from) { |
|
f7eb47b…
|
lmata
|
276 |
return { |
|
f7eb47b…
|
lmata
|
277 |
...to, |
|
f7eb47b…
|
lmata
|
278 |
...from, |
|
f7eb47b…
|
lmata
|
279 |
metadata: { |
|
f7eb47b…
|
lmata
|
280 |
...to.metadata, |
|
f7eb47b…
|
lmata
|
281 |
...from.metadata, |
|
f7eb47b…
|
lmata
|
282 |
actualWorkers: (to.metadata.actualWorkers || 0) + (from.metadata.actualWorkers || 0) |
|
f7eb47b…
|
lmata
|
283 |
}, |
|
f7eb47b…
|
lmata
|
284 |
workers: to.workers + from.workers |
|
f7eb47b…
|
lmata
|
285 |
}; |
|
f7eb47b…
|
lmata
|
286 |
} |
|
f7eb47b…
|
lmata
|
287 |
function mergeEndEvents(endEvents) { |
|
f7eb47b…
|
lmata
|
288 |
let startTime = endEvents.length ? 1e13 : Date.now(); |
|
f7eb47b…
|
lmata
|
289 |
let status = "passed"; |
|
f7eb47b…
|
lmata
|
290 |
let endTime = 0; |
|
f7eb47b…
|
lmata
|
291 |
for (const { event } of endEvents) { |
|
f7eb47b…
|
lmata
|
292 |
const shardResult = event.params.result; |
|
f7eb47b…
|
lmata
|
293 |
if (shardResult.status === "failed") |
|
f7eb47b…
|
lmata
|
294 |
status = "failed"; |
|
f7eb47b…
|
lmata
|
295 |
else if (shardResult.status === "timedout" && status !== "failed") |
|
f7eb47b…
|
lmata
|
296 |
status = "timedout"; |
|
f7eb47b…
|
lmata
|
297 |
else if (shardResult.status === "interrupted" && status !== "failed" && status !== "timedout") |
|
f7eb47b…
|
lmata
|
298 |
status = "interrupted"; |
|
f7eb47b…
|
lmata
|
299 |
startTime = Math.min(startTime, shardResult.startTime); |
|
f7eb47b…
|
lmata
|
300 |
endTime = Math.max(endTime, shardResult.startTime + shardResult.duration); |
|
f7eb47b…
|
lmata
|
301 |
} |
|
f7eb47b…
|
lmata
|
302 |
const result = { |
|
f7eb47b…
|
lmata
|
303 |
status, |
|
f7eb47b…
|
lmata
|
304 |
startTime, |
|
f7eb47b…
|
lmata
|
305 |
duration: endTime - startTime |
|
f7eb47b…
|
lmata
|
306 |
}; |
|
f7eb47b…
|
lmata
|
307 |
return { |
|
f7eb47b…
|
lmata
|
308 |
method: "onEnd", |
|
f7eb47b…
|
lmata
|
309 |
params: { |
|
f7eb47b…
|
lmata
|
310 |
result |
|
f7eb47b…
|
lmata
|
311 |
} |
|
f7eb47b…
|
lmata
|
312 |
}; |
|
f7eb47b…
|
lmata
|
313 |
} |
|
f7eb47b…
|
lmata
|
314 |
async function sortedShardFiles(dir) { |
|
f7eb47b…
|
lmata
|
315 |
const files = await import_fs.default.promises.readdir(dir); |
|
f7eb47b…
|
lmata
|
316 |
return files.filter((file) => file.endsWith(".zip")).sort(); |
|
f7eb47b…
|
lmata
|
317 |
} |
|
f7eb47b…
|
lmata
|
318 |
function printStatusToStdout(message) { |
|
f7eb47b…
|
lmata
|
319 |
process.stdout.write(`${message} |
|
f7eb47b…
|
lmata
|
320 |
`); |
|
f7eb47b…
|
lmata
|
321 |
} |
|
f7eb47b…
|
lmata
|
322 |
class UniqueFileNameGenerator { |
|
f7eb47b…
|
lmata
|
323 |
constructor() { |
|
f7eb47b…
|
lmata
|
324 |
this._usedNames = /* @__PURE__ */ new Set(); |
|
f7eb47b…
|
lmata
|
325 |
} |
|
f7eb47b…
|
lmata
|
326 |
makeUnique(name) { |
|
f7eb47b…
|
lmata
|
327 |
if (!this._usedNames.has(name)) { |
|
f7eb47b…
|
lmata
|
328 |
this._usedNames.add(name); |
|
f7eb47b…
|
lmata
|
329 |
return name; |
|
f7eb47b…
|
lmata
|
330 |
} |
|
f7eb47b…
|
lmata
|
331 |
const extension = import_path.default.extname(name); |
|
f7eb47b…
|
lmata
|
332 |
name = name.substring(0, name.length - extension.length); |
|
f7eb47b…
|
lmata
|
333 |
let index = 0; |
|
f7eb47b…
|
lmata
|
334 |
while (true) { |
|
f7eb47b…
|
lmata
|
335 |
const candidate = `${name}-${++index}${extension}`; |
|
f7eb47b…
|
lmata
|
336 |
if (!this._usedNames.has(candidate)) { |
|
f7eb47b…
|
lmata
|
337 |
this._usedNames.add(candidate); |
|
f7eb47b…
|
lmata
|
338 |
return candidate; |
|
f7eb47b…
|
lmata
|
339 |
} |
|
f7eb47b…
|
lmata
|
340 |
} |
|
f7eb47b…
|
lmata
|
341 |
} |
|
f7eb47b…
|
lmata
|
342 |
} |
|
f7eb47b…
|
lmata
|
343 |
class IdsPatcher { |
|
f7eb47b…
|
lmata
|
344 |
constructor(stringPool, botName, salt, globalTestIdSet) { |
|
f7eb47b…
|
lmata
|
345 |
this._stringPool = stringPool; |
|
f7eb47b…
|
lmata
|
346 |
this._botName = botName; |
|
f7eb47b…
|
lmata
|
347 |
this._salt = salt; |
|
f7eb47b…
|
lmata
|
348 |
this._testIdsMap = /* @__PURE__ */ new Map(); |
|
f7eb47b…
|
lmata
|
349 |
this._globalTestIdSet = globalTestIdSet; |
|
f7eb47b…
|
lmata
|
350 |
} |
|
f7eb47b…
|
lmata
|
351 |
patchEvent(event) { |
|
f7eb47b…
|
lmata
|
352 |
const { method, params } = event; |
|
f7eb47b…
|
lmata
|
353 |
switch (method) { |
|
f7eb47b…
|
lmata
|
354 |
case "onProject": |
|
f7eb47b…
|
lmata
|
355 |
this._onProject(params.project); |
|
f7eb47b…
|
lmata
|
356 |
return; |
|
f7eb47b…
|
lmata
|
357 |
case "onAttach": |
|
f7eb47b…
|
lmata
|
358 |
case "onTestBegin": |
|
f7eb47b…
|
lmata
|
359 |
case "onStepBegin": |
|
f7eb47b…
|
lmata
|
360 |
case "onStepEnd": |
|
f7eb47b…
|
lmata
|
361 |
case "onStdIO": |
|
f7eb47b…
|
lmata
|
362 |
params.testId = params.testId ? this._mapTestId(params.testId) : void 0; |
|
f7eb47b…
|
lmata
|
363 |
return; |
|
f7eb47b…
|
lmata
|
364 |
case "onTestEnd": |
|
f7eb47b…
|
lmata
|
365 |
params.test.testId = this._mapTestId(params.test.testId); |
|
f7eb47b…
|
lmata
|
366 |
return; |
|
f7eb47b…
|
lmata
|
367 |
} |
|
f7eb47b…
|
lmata
|
368 |
} |
|
f7eb47b…
|
lmata
|
369 |
_onProject(project) { |
|
f7eb47b…
|
lmata
|
370 |
project.metadata ??= {}; |
|
f7eb47b…
|
lmata
|
371 |
project.suites.forEach((suite) => this._updateTestIds(suite)); |
|
f7eb47b…
|
lmata
|
372 |
} |
|
f7eb47b…
|
lmata
|
373 |
_updateTestIds(suite) { |
|
f7eb47b…
|
lmata
|
374 |
suite.entries.forEach((entry) => { |
|
f7eb47b…
|
lmata
|
375 |
if ("testId" in entry) |
|
f7eb47b…
|
lmata
|
376 |
this._updateTestId(entry); |
|
f7eb47b…
|
lmata
|
377 |
else |
|
f7eb47b…
|
lmata
|
378 |
this._updateTestIds(entry); |
|
f7eb47b…
|
lmata
|
379 |
}); |
|
f7eb47b…
|
lmata
|
380 |
} |
|
f7eb47b…
|
lmata
|
381 |
_updateTestId(test) { |
|
f7eb47b…
|
lmata
|
382 |
test.testId = this._mapTestId(test.testId); |
|
f7eb47b…
|
lmata
|
383 |
if (this._botName) { |
|
f7eb47b…
|
lmata
|
384 |
test.tags = test.tags || []; |
|
f7eb47b…
|
lmata
|
385 |
test.tags.unshift("@" + this._botName); |
|
f7eb47b…
|
lmata
|
386 |
} |
|
f7eb47b…
|
lmata
|
387 |
} |
|
f7eb47b…
|
lmata
|
388 |
_mapTestId(testId) { |
|
f7eb47b…
|
lmata
|
389 |
const t1 = this._stringPool.internString(testId); |
|
f7eb47b…
|
lmata
|
390 |
if (this._testIdsMap.has(t1)) |
|
f7eb47b…
|
lmata
|
391 |
return this._testIdsMap.get(t1); |
|
f7eb47b…
|
lmata
|
392 |
if (this._globalTestIdSet.has(t1)) { |
|
f7eb47b…
|
lmata
|
393 |
const t2 = this._stringPool.internString(testId + this._salt); |
|
f7eb47b…
|
lmata
|
394 |
this._globalTestIdSet.add(t2); |
|
f7eb47b…
|
lmata
|
395 |
this._testIdsMap.set(t1, t2); |
|
f7eb47b…
|
lmata
|
396 |
return t2; |
|
f7eb47b…
|
lmata
|
397 |
} |
|
f7eb47b…
|
lmata
|
398 |
this._globalTestIdSet.add(t1); |
|
f7eb47b…
|
lmata
|
399 |
this._testIdsMap.set(t1, t1); |
|
f7eb47b…
|
lmata
|
400 |
return t1; |
|
f7eb47b…
|
lmata
|
401 |
} |
|
f7eb47b…
|
lmata
|
402 |
} |
|
f7eb47b…
|
lmata
|
403 |
class AttachmentPathPatcher { |
|
f7eb47b…
|
lmata
|
404 |
constructor(_resourceDir) { |
|
f7eb47b…
|
lmata
|
405 |
this._resourceDir = _resourceDir; |
|
f7eb47b…
|
lmata
|
406 |
} |
|
f7eb47b…
|
lmata
|
407 |
patchEvent(event) { |
|
f7eb47b…
|
lmata
|
408 |
if (event.method === "onAttach") |
|
f7eb47b…
|
lmata
|
409 |
this._patchAttachments(event.params.attachments); |
|
f7eb47b…
|
lmata
|
410 |
else if (event.method === "onTestEnd") |
|
f7eb47b…
|
lmata
|
411 |
this._patchAttachments(event.params.result.attachments ?? []); |
|
f7eb47b…
|
lmata
|
412 |
} |
|
f7eb47b…
|
lmata
|
413 |
_patchAttachments(attachments) { |
|
f7eb47b…
|
lmata
|
414 |
for (const attachment of attachments) { |
|
f7eb47b…
|
lmata
|
415 |
if (!attachment.path) |
|
f7eb47b…
|
lmata
|
416 |
continue; |
|
f7eb47b…
|
lmata
|
417 |
attachment.path = import_path.default.join(this._resourceDir, attachment.path); |
|
f7eb47b…
|
lmata
|
418 |
} |
|
f7eb47b…
|
lmata
|
419 |
} |
|
f7eb47b…
|
lmata
|
420 |
} |
|
f7eb47b…
|
lmata
|
421 |
class PathSeparatorPatcher { |
|
f7eb47b…
|
lmata
|
422 |
constructor(from) { |
|
f7eb47b…
|
lmata
|
423 |
this._from = from ?? (import_path.default.sep === "/" ? "\\" : "/"); |
|
f7eb47b…
|
lmata
|
424 |
this._to = import_path.default.sep; |
|
f7eb47b…
|
lmata
|
425 |
} |
|
f7eb47b…
|
lmata
|
426 |
patchEvent(jsonEvent) { |
|
f7eb47b…
|
lmata
|
427 |
if (this._from === this._to) |
|
f7eb47b…
|
lmata
|
428 |
return; |
|
f7eb47b…
|
lmata
|
429 |
if (jsonEvent.method === "onProject") { |
|
f7eb47b…
|
lmata
|
430 |
this._updateProject(jsonEvent.params.project); |
|
f7eb47b…
|
lmata
|
431 |
return; |
|
f7eb47b…
|
lmata
|
432 |
} |
|
f7eb47b…
|
lmata
|
433 |
if (jsonEvent.method === "onTestEnd") { |
|
f7eb47b…
|
lmata
|
434 |
const test = jsonEvent.params.test; |
|
f7eb47b…
|
lmata
|
435 |
test.annotations?.forEach((annotation) => this._updateAnnotationLocation(annotation)); |
|
f7eb47b…
|
lmata
|
436 |
const testResult = jsonEvent.params.result; |
|
f7eb47b…
|
lmata
|
437 |
testResult.annotations?.forEach((annotation) => this._updateAnnotationLocation(annotation)); |
|
f7eb47b…
|
lmata
|
438 |
testResult.errors.forEach((error) => this._updateErrorLocations(error)); |
|
f7eb47b…
|
lmata
|
439 |
(testResult.attachments ?? []).forEach((attachment) => { |
|
f7eb47b…
|
lmata
|
440 |
if (attachment.path) |
|
f7eb47b…
|
lmata
|
441 |
attachment.path = this._updatePath(attachment.path); |
|
f7eb47b…
|
lmata
|
442 |
}); |
|
f7eb47b…
|
lmata
|
443 |
return; |
|
f7eb47b…
|
lmata
|
444 |
} |
|
f7eb47b…
|
lmata
|
445 |
if (jsonEvent.method === "onStepBegin") { |
|
f7eb47b…
|
lmata
|
446 |
const step = jsonEvent.params.step; |
|
f7eb47b…
|
lmata
|
447 |
this._updateLocation(step.location); |
|
f7eb47b…
|
lmata
|
448 |
return; |
|
f7eb47b…
|
lmata
|
449 |
} |
|
f7eb47b…
|
lmata
|
450 |
if (jsonEvent.method === "onStepEnd") { |
|
f7eb47b…
|
lmata
|
451 |
const step = jsonEvent.params.step; |
|
f7eb47b…
|
lmata
|
452 |
this._updateErrorLocations(step.error); |
|
f7eb47b…
|
lmata
|
453 |
step.annotations?.forEach((annotation) => this._updateAnnotationLocation(annotation)); |
|
f7eb47b…
|
lmata
|
454 |
return; |
|
f7eb47b…
|
lmata
|
455 |
} |
|
f7eb47b…
|
lmata
|
456 |
if (jsonEvent.method === "onAttach") { |
|
f7eb47b…
|
lmata
|
457 |
const attach = jsonEvent.params; |
|
f7eb47b…
|
lmata
|
458 |
attach.attachments.forEach((attachment) => { |
|
f7eb47b…
|
lmata
|
459 |
if (attachment.path) |
|
f7eb47b…
|
lmata
|
460 |
attachment.path = this._updatePath(attachment.path); |
|
f7eb47b…
|
lmata
|
461 |
}); |
|
f7eb47b…
|
lmata
|
462 |
return; |
|
f7eb47b…
|
lmata
|
463 |
} |
|
f7eb47b…
|
lmata
|
464 |
} |
|
f7eb47b…
|
lmata
|
465 |
_updateProject(project) { |
|
f7eb47b…
|
lmata
|
466 |
project.outputDir = this._updatePath(project.outputDir); |
|
f7eb47b…
|
lmata
|
467 |
project.testDir = this._updatePath(project.testDir); |
|
f7eb47b…
|
lmata
|
468 |
project.snapshotDir = this._updatePath(project.snapshotDir); |
|
f7eb47b…
|
lmata
|
469 |
project.suites.forEach((suite) => this._updateSuite(suite, true)); |
|
f7eb47b…
|
lmata
|
470 |
} |
|
f7eb47b…
|
lmata
|
471 |
_updateSuite(suite, isFileSuite = false) { |
|
f7eb47b…
|
lmata
|
472 |
this._updateLocation(suite.location); |
|
f7eb47b…
|
lmata
|
473 |
if (isFileSuite) |
|
f7eb47b…
|
lmata
|
474 |
suite.title = this._updatePath(suite.title); |
|
f7eb47b…
|
lmata
|
475 |
for (const entry of suite.entries) { |
|
f7eb47b…
|
lmata
|
476 |
if ("testId" in entry) { |
|
f7eb47b…
|
lmata
|
477 |
this._updateLocation(entry.location); |
|
f7eb47b…
|
lmata
|
478 |
entry.annotations?.forEach((annotation) => this._updateAnnotationLocation(annotation)); |
|
f7eb47b…
|
lmata
|
479 |
} else { |
|
f7eb47b…
|
lmata
|
480 |
this._updateSuite(entry); |
|
f7eb47b…
|
lmata
|
481 |
} |
|
f7eb47b…
|
lmata
|
482 |
} |
|
f7eb47b…
|
lmata
|
483 |
} |
|
f7eb47b…
|
lmata
|
484 |
_updateErrorLocations(error) { |
|
f7eb47b…
|
lmata
|
485 |
while (error) { |
|
f7eb47b…
|
lmata
|
486 |
this._updateLocation(error.location); |
|
f7eb47b…
|
lmata
|
487 |
error = error.cause; |
|
f7eb47b…
|
lmata
|
488 |
} |
|
f7eb47b…
|
lmata
|
489 |
} |
|
f7eb47b…
|
lmata
|
490 |
_updateAnnotationLocation(annotation) { |
|
f7eb47b…
|
lmata
|
491 |
this._updateLocation(annotation.location); |
|
f7eb47b…
|
lmata
|
492 |
} |
|
f7eb47b…
|
lmata
|
493 |
_updateLocation(location) { |
|
f7eb47b…
|
lmata
|
494 |
if (location) |
|
f7eb47b…
|
lmata
|
495 |
location.file = this._updatePath(location.file); |
|
f7eb47b…
|
lmata
|
496 |
} |
|
f7eb47b…
|
lmata
|
497 |
_updatePath(text) { |
|
f7eb47b…
|
lmata
|
498 |
return text.split(this._from).join(this._to); |
|
f7eb47b…
|
lmata
|
499 |
} |
|
f7eb47b…
|
lmata
|
500 |
} |
|
f7eb47b…
|
lmata
|
501 |
class GlobalErrorPatcher { |
|
f7eb47b…
|
lmata
|
502 |
constructor(botName) { |
|
f7eb47b…
|
lmata
|
503 |
this._prefix = `(${botName}) `; |
|
f7eb47b…
|
lmata
|
504 |
} |
|
f7eb47b…
|
lmata
|
505 |
patchEvent(event) { |
|
f7eb47b…
|
lmata
|
506 |
if (event.method !== "onError") |
|
f7eb47b…
|
lmata
|
507 |
return; |
|
f7eb47b…
|
lmata
|
508 |
const error = event.params.error; |
|
f7eb47b…
|
lmata
|
509 |
if (error.message !== void 0) |
|
f7eb47b…
|
lmata
|
510 |
error.message = this._prefix + error.message; |
|
f7eb47b…
|
lmata
|
511 |
if (error.stack !== void 0) |
|
f7eb47b…
|
lmata
|
512 |
error.stack = this._prefix + error.stack; |
|
f7eb47b…
|
lmata
|
513 |
} |
|
f7eb47b…
|
lmata
|
514 |
} |
|
f7eb47b…
|
lmata
|
515 |
class JsonEventPatchers { |
|
f7eb47b…
|
lmata
|
516 |
constructor() { |
|
f7eb47b…
|
lmata
|
517 |
this.patchers = []; |
|
f7eb47b…
|
lmata
|
518 |
} |
|
f7eb47b…
|
lmata
|
519 |
patchEvents(events) { |
|
f7eb47b…
|
lmata
|
520 |
for (const event of events) { |
|
f7eb47b…
|
lmata
|
521 |
for (const patcher of this.patchers) |
|
f7eb47b…
|
lmata
|
522 |
patcher.patchEvent(event); |
|
f7eb47b…
|
lmata
|
523 |
} |
|
f7eb47b…
|
lmata
|
524 |
} |
|
f7eb47b…
|
lmata
|
525 |
} |
|
f7eb47b…
|
lmata
|
526 |
class BlobModernizer { |
|
f7eb47b…
|
lmata
|
527 |
modernize(fromVersion, events) { |
|
f7eb47b…
|
lmata
|
528 |
const result = []; |
|
f7eb47b…
|
lmata
|
529 |
for (const event of events) |
|
f7eb47b…
|
lmata
|
530 |
result.push(...this._modernize(fromVersion, event)); |
|
f7eb47b…
|
lmata
|
531 |
return result; |
|
f7eb47b…
|
lmata
|
532 |
} |
|
f7eb47b…
|
lmata
|
533 |
_modernize(fromVersion, event) { |
|
f7eb47b…
|
lmata
|
534 |
let events = [event]; |
|
f7eb47b…
|
lmata
|
535 |
for (let version = fromVersion; version < import_blob.currentBlobReportVersion; ++version) |
|
f7eb47b…
|
lmata
|
536 |
events = this[`_modernize_${version}_to_${version + 1}`].call(this, events); |
|
f7eb47b…
|
lmata
|
537 |
return events; |
|
f7eb47b…
|
lmata
|
538 |
} |
|
f7eb47b…
|
lmata
|
539 |
_modernize_1_to_2(events) { |
|
f7eb47b…
|
lmata
|
540 |
return events.map((event) => { |
|
f7eb47b…
|
lmata
|
541 |
if (event.method === "onProject") { |
|
f7eb47b…
|
lmata
|
542 |
const modernizeSuite = (suite) => { |
|
f7eb47b…
|
lmata
|
543 |
const newSuites = suite.suites.map(modernizeSuite); |
|
f7eb47b…
|
lmata
|
544 |
const { suites, tests, ...remainder } = suite; |
|
f7eb47b…
|
lmata
|
545 |
return { entries: [...newSuites, ...tests], ...remainder }; |
|
f7eb47b…
|
lmata
|
546 |
}; |
|
f7eb47b…
|
lmata
|
547 |
const project = event.params.project; |
|
f7eb47b…
|
lmata
|
548 |
project.suites = project.suites.map(modernizeSuite); |
|
f7eb47b…
|
lmata
|
549 |
} |
|
f7eb47b…
|
lmata
|
550 |
return event; |
|
f7eb47b…
|
lmata
|
551 |
}); |
|
f7eb47b…
|
lmata
|
552 |
} |
|
f7eb47b…
|
lmata
|
553 |
} |
|
f7eb47b…
|
lmata
|
554 |
const modernizer = new BlobModernizer(); |
|
f7eb47b…
|
lmata
|
555 |
// Annotate the CommonJS export names for ESM import in node: |
|
f7eb47b…
|
lmata
|
556 |
0 && (module.exports = { |
|
f7eb47b…
|
lmata
|
557 |
createMergedReport |
|
f7eb47b…
|
lmata
|
558 |
}); |