|
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 html_exports = {}; |
|
f7eb47b…
|
lmata
|
30 |
__export(html_exports, { |
|
f7eb47b…
|
lmata
|
31 |
default: () => html_default, |
|
f7eb47b…
|
lmata
|
32 |
showHTMLReport: () => showHTMLReport, |
|
f7eb47b…
|
lmata
|
33 |
startHtmlReportServer: () => startHtmlReportServer |
|
f7eb47b…
|
lmata
|
34 |
}); |
|
f7eb47b…
|
lmata
|
35 |
module.exports = __toCommonJS(html_exports); |
|
f7eb47b…
|
lmata
|
36 |
var import_fs = __toESM(require("fs")); |
|
f7eb47b…
|
lmata
|
37 |
var import_path = __toESM(require("path")); |
|
f7eb47b…
|
lmata
|
38 |
var import_stream = require("stream"); |
|
f7eb47b…
|
lmata
|
39 |
var import_utils = require("playwright-core/lib/utils"); |
|
f7eb47b…
|
lmata
|
40 |
var import_utils2 = require("playwright-core/lib/utils"); |
|
f7eb47b…
|
lmata
|
41 |
var import_utilsBundle = require("playwright-core/lib/utilsBundle"); |
|
f7eb47b…
|
lmata
|
42 |
var import_utilsBundle2 = require("playwright-core/lib/utilsBundle"); |
|
f7eb47b…
|
lmata
|
43 |
var import_zipBundle = require("playwright-core/lib/zipBundle"); |
|
f7eb47b…
|
lmata
|
44 |
var import_base = require("./base"); |
|
f7eb47b…
|
lmata
|
45 |
var import_babelBundle = require("../transform/babelBundle"); |
|
f7eb47b…
|
lmata
|
46 |
var import_util = require("../util"); |
|
f7eb47b…
|
lmata
|
47 |
const htmlReportOptions = ["always", "never", "on-failure"]; |
|
f7eb47b…
|
lmata
|
48 |
const isHtmlReportOption = (type) => { |
|
f7eb47b…
|
lmata
|
49 |
return htmlReportOptions.includes(type); |
|
f7eb47b…
|
lmata
|
50 |
}; |
|
f7eb47b…
|
lmata
|
51 |
class HtmlReporter { |
|
f7eb47b…
|
lmata
|
52 |
constructor(options) { |
|
f7eb47b…
|
lmata
|
53 |
this._topLevelErrors = []; |
|
f7eb47b…
|
lmata
|
54 |
this._machines = []; |
|
f7eb47b…
|
lmata
|
55 |
this._options = options; |
|
f7eb47b…
|
lmata
|
56 |
} |
|
f7eb47b…
|
lmata
|
57 |
version() { |
|
f7eb47b…
|
lmata
|
58 |
return "v2"; |
|
f7eb47b…
|
lmata
|
59 |
} |
|
f7eb47b…
|
lmata
|
60 |
printsToStdio() { |
|
f7eb47b…
|
lmata
|
61 |
return false; |
|
f7eb47b…
|
lmata
|
62 |
} |
|
f7eb47b…
|
lmata
|
63 |
onConfigure(config) { |
|
f7eb47b…
|
lmata
|
64 |
this.config = config; |
|
f7eb47b…
|
lmata
|
65 |
} |
|
f7eb47b…
|
lmata
|
66 |
onBegin(suite) { |
|
f7eb47b…
|
lmata
|
67 |
const { outputFolder, open: open2, attachmentsBaseURL, host, port } = this._resolveOptions(); |
|
f7eb47b…
|
lmata
|
68 |
this._outputFolder = outputFolder; |
|
f7eb47b…
|
lmata
|
69 |
this._open = open2; |
|
f7eb47b…
|
lmata
|
70 |
this._host = host; |
|
f7eb47b…
|
lmata
|
71 |
this._port = port; |
|
f7eb47b…
|
lmata
|
72 |
this._attachmentsBaseURL = attachmentsBaseURL; |
|
f7eb47b…
|
lmata
|
73 |
const reportedWarnings = /* @__PURE__ */ new Set(); |
|
f7eb47b…
|
lmata
|
74 |
for (const project of this.config.projects) { |
|
f7eb47b…
|
lmata
|
75 |
if (this._isSubdirectory(outputFolder, project.outputDir) || this._isSubdirectory(project.outputDir, outputFolder)) { |
|
f7eb47b…
|
lmata
|
76 |
const key = outputFolder + "|" + project.outputDir; |
|
f7eb47b…
|
lmata
|
77 |
if (reportedWarnings.has(key)) |
|
f7eb47b…
|
lmata
|
78 |
continue; |
|
f7eb47b…
|
lmata
|
79 |
reportedWarnings.add(key); |
|
f7eb47b…
|
lmata
|
80 |
writeLine(import_utils2.colors.red(`Configuration Error: HTML reporter output folder clashes with the tests output folder:`)); |
|
f7eb47b…
|
lmata
|
81 |
writeLine(` |
|
f7eb47b…
|
lmata
|
82 |
html reporter folder: ${import_utils2.colors.bold(outputFolder)} |
|
f7eb47b…
|
lmata
|
83 |
test results folder: ${import_utils2.colors.bold(project.outputDir)}`); |
|
f7eb47b…
|
lmata
|
84 |
writeLine(""); |
|
f7eb47b…
|
lmata
|
85 |
writeLine(`HTML reporter will clear its output directory prior to being generated, which will lead to the artifact loss. |
|
f7eb47b…
|
lmata
|
86 |
`); |
|
f7eb47b…
|
lmata
|
87 |
} |
|
f7eb47b…
|
lmata
|
88 |
} |
|
f7eb47b…
|
lmata
|
89 |
this.suite = suite; |
|
f7eb47b…
|
lmata
|
90 |
} |
|
f7eb47b…
|
lmata
|
91 |
_resolveOptions() { |
|
f7eb47b…
|
lmata
|
92 |
const outputFolder = reportFolderFromEnv() ?? (0, import_util.resolveReporterOutputPath)("playwright-report", this._options.configDir, this._options.outputFolder); |
|
f7eb47b…
|
lmata
|
93 |
return { |
|
f7eb47b…
|
lmata
|
94 |
outputFolder, |
|
f7eb47b…
|
lmata
|
95 |
open: getHtmlReportOptionProcessEnv() || this._options.open || "on-failure", |
|
f7eb47b…
|
lmata
|
96 |
attachmentsBaseURL: process.env.PLAYWRIGHT_HTML_ATTACHMENTS_BASE_URL || this._options.attachmentsBaseURL || "data/", |
|
f7eb47b…
|
lmata
|
97 |
host: process.env.PLAYWRIGHT_HTML_HOST || this._options.host, |
|
f7eb47b…
|
lmata
|
98 |
port: process.env.PLAYWRIGHT_HTML_PORT ? +process.env.PLAYWRIGHT_HTML_PORT : this._options.port |
|
f7eb47b…
|
lmata
|
99 |
}; |
|
f7eb47b…
|
lmata
|
100 |
} |
|
f7eb47b…
|
lmata
|
101 |
_isSubdirectory(parentDir, dir) { |
|
f7eb47b…
|
lmata
|
102 |
const relativePath = import_path.default.relative(parentDir, dir); |
|
f7eb47b…
|
lmata
|
103 |
return !!relativePath && !relativePath.startsWith("..") && !import_path.default.isAbsolute(relativePath); |
|
f7eb47b…
|
lmata
|
104 |
} |
|
f7eb47b…
|
lmata
|
105 |
onError(error) { |
|
f7eb47b…
|
lmata
|
106 |
this._topLevelErrors.push(error); |
|
f7eb47b…
|
lmata
|
107 |
} |
|
f7eb47b…
|
lmata
|
108 |
onMachineEnd(result) { |
|
f7eb47b…
|
lmata
|
109 |
this._machines.push(result); |
|
f7eb47b…
|
lmata
|
110 |
} |
|
f7eb47b…
|
lmata
|
111 |
async onEnd(result) { |
|
f7eb47b…
|
lmata
|
112 |
const projectSuites = this.suite.suites; |
|
f7eb47b…
|
lmata
|
113 |
await (0, import_utils.removeFolders)([this._outputFolder]); |
|
f7eb47b…
|
lmata
|
114 |
let noSnippets; |
|
f7eb47b…
|
lmata
|
115 |
if (process.env.PLAYWRIGHT_HTML_NO_SNIPPETS === "false" || process.env.PLAYWRIGHT_HTML_NO_SNIPPETS === "0") |
|
f7eb47b…
|
lmata
|
116 |
noSnippets = false; |
|
f7eb47b…
|
lmata
|
117 |
else if (process.env.PLAYWRIGHT_HTML_NO_SNIPPETS) |
|
f7eb47b…
|
lmata
|
118 |
noSnippets = true; |
|
f7eb47b…
|
lmata
|
119 |
noSnippets = noSnippets || this._options.noSnippets; |
|
f7eb47b…
|
lmata
|
120 |
let noCopyPrompt; |
|
f7eb47b…
|
lmata
|
121 |
if (process.env.PLAYWRIGHT_HTML_NO_COPY_PROMPT === "false" || process.env.PLAYWRIGHT_HTML_NO_COPY_PROMPT === "0") |
|
f7eb47b…
|
lmata
|
122 |
noCopyPrompt = false; |
|
f7eb47b…
|
lmata
|
123 |
else if (process.env.PLAYWRIGHT_HTML_NO_COPY_PROMPT) |
|
f7eb47b…
|
lmata
|
124 |
noCopyPrompt = true; |
|
f7eb47b…
|
lmata
|
125 |
noCopyPrompt = noCopyPrompt || this._options.noCopyPrompt; |
|
f7eb47b…
|
lmata
|
126 |
const builder = new HtmlBuilder(this.config, this._outputFolder, this._attachmentsBaseURL, { |
|
f7eb47b…
|
lmata
|
127 |
title: process.env.PLAYWRIGHT_HTML_TITLE || this._options.title, |
|
f7eb47b…
|
lmata
|
128 |
noSnippets, |
|
f7eb47b…
|
lmata
|
129 |
noCopyPrompt |
|
f7eb47b…
|
lmata
|
130 |
}); |
|
f7eb47b…
|
lmata
|
131 |
this._buildResult = await builder.build(this.config.metadata, projectSuites, result, this._topLevelErrors, this._machines); |
|
f7eb47b…
|
lmata
|
132 |
} |
|
f7eb47b…
|
lmata
|
133 |
async onExit() { |
|
f7eb47b…
|
lmata
|
134 |
if (process.env.CI || !this._buildResult) |
|
f7eb47b…
|
lmata
|
135 |
return; |
|
f7eb47b…
|
lmata
|
136 |
const { ok, singleTestId } = this._buildResult; |
|
f7eb47b…
|
lmata
|
137 |
const shouldOpen = !!process.stdin.isTTY && (this._open === "always" || !ok && this._open === "on-failure"); |
|
f7eb47b…
|
lmata
|
138 |
if (shouldOpen) { |
|
f7eb47b…
|
lmata
|
139 |
await showHTMLReport(this._outputFolder, this._host, this._port, singleTestId); |
|
f7eb47b…
|
lmata
|
140 |
} else if (this._options._mode === "test" && !!process.stdin.isTTY) { |
|
f7eb47b…
|
lmata
|
141 |
const packageManagerCommand = (0, import_utils.getPackageManagerExecCommand)(); |
|
f7eb47b…
|
lmata
|
142 |
const relativeReportPath = this._outputFolder === standaloneDefaultFolder() ? "" : " " + import_path.default.relative(process.cwd(), this._outputFolder); |
|
f7eb47b…
|
lmata
|
143 |
const hostArg = this._host ? ` --host ${this._host}` : ""; |
|
f7eb47b…
|
lmata
|
144 |
const portArg = this._port ? ` --port ${this._port}` : ""; |
|
f7eb47b…
|
lmata
|
145 |
writeLine(""); |
|
f7eb47b…
|
lmata
|
146 |
writeLine("To open last HTML report run:"); |
|
f7eb47b…
|
lmata
|
147 |
writeLine(import_utils2.colors.cyan(` |
|
f7eb47b…
|
lmata
|
148 |
${packageManagerCommand} playwright show-report${relativeReportPath}${hostArg}${portArg} |
|
f7eb47b…
|
lmata
|
149 |
`)); |
|
f7eb47b…
|
lmata
|
150 |
} |
|
f7eb47b…
|
lmata
|
151 |
} |
|
f7eb47b…
|
lmata
|
152 |
} |
|
f7eb47b…
|
lmata
|
153 |
function reportFolderFromEnv() { |
|
f7eb47b…
|
lmata
|
154 |
const envValue = process.env.PLAYWRIGHT_HTML_OUTPUT_DIR || process.env.PLAYWRIGHT_HTML_REPORT; |
|
f7eb47b…
|
lmata
|
155 |
return envValue ? import_path.default.resolve(envValue) : void 0; |
|
f7eb47b…
|
lmata
|
156 |
} |
|
f7eb47b…
|
lmata
|
157 |
function getHtmlReportOptionProcessEnv() { |
|
f7eb47b…
|
lmata
|
158 |
const htmlOpenEnv = process.env.PLAYWRIGHT_HTML_OPEN || process.env.PW_TEST_HTML_REPORT_OPEN; |
|
f7eb47b…
|
lmata
|
159 |
if (!htmlOpenEnv) |
|
f7eb47b…
|
lmata
|
160 |
return void 0; |
|
f7eb47b…
|
lmata
|
161 |
if (!isHtmlReportOption(htmlOpenEnv)) { |
|
f7eb47b…
|
lmata
|
162 |
writeLine(import_utils2.colors.red(`Configuration Error: HTML reporter Invalid value for PLAYWRIGHT_HTML_OPEN: ${htmlOpenEnv}. Valid values are: ${htmlReportOptions.join(", ")}`)); |
|
f7eb47b…
|
lmata
|
163 |
return void 0; |
|
f7eb47b…
|
lmata
|
164 |
} |
|
f7eb47b…
|
lmata
|
165 |
return htmlOpenEnv; |
|
f7eb47b…
|
lmata
|
166 |
} |
|
f7eb47b…
|
lmata
|
167 |
function standaloneDefaultFolder() { |
|
f7eb47b…
|
lmata
|
168 |
return reportFolderFromEnv() ?? (0, import_util.resolveReporterOutputPath)("playwright-report", process.cwd(), void 0); |
|
f7eb47b…
|
lmata
|
169 |
} |
|
f7eb47b…
|
lmata
|
170 |
async function showHTMLReport(reportFolder, host = "localhost", port, testId) { |
|
f7eb47b…
|
lmata
|
171 |
const folder = reportFolder ?? standaloneDefaultFolder(); |
|
f7eb47b…
|
lmata
|
172 |
try { |
|
f7eb47b…
|
lmata
|
173 |
(0, import_utils.assert)(import_fs.default.statSync(folder).isDirectory()); |
|
f7eb47b…
|
lmata
|
174 |
} catch (e) { |
|
f7eb47b…
|
lmata
|
175 |
writeLine(import_utils2.colors.red(`No report found at "${folder}"`)); |
|
f7eb47b…
|
lmata
|
176 |
(0, import_utils.gracefullyProcessExitDoNotHang)(1); |
|
f7eb47b…
|
lmata
|
177 |
return; |
|
f7eb47b…
|
lmata
|
178 |
} |
|
f7eb47b…
|
lmata
|
179 |
const server = startHtmlReportServer(folder); |
|
f7eb47b…
|
lmata
|
180 |
await server.start({ port, host, preferredPort: port ? void 0 : 9323 }); |
|
f7eb47b…
|
lmata
|
181 |
let url = server.urlPrefix("human-readable"); |
|
f7eb47b…
|
lmata
|
182 |
writeLine(""); |
|
f7eb47b…
|
lmata
|
183 |
writeLine(import_utils2.colors.cyan(` Serving HTML report at ${url}. Press Ctrl+C to quit.`)); |
|
f7eb47b…
|
lmata
|
184 |
if (testId) |
|
f7eb47b…
|
lmata
|
185 |
url += `#?testId=${testId}`; |
|
f7eb47b…
|
lmata
|
186 |
url = url.replace("0.0.0.0", "localhost"); |
|
f7eb47b…
|
lmata
|
187 |
await (0, import_utilsBundle.open)(url, { wait: true }).catch(() => { |
|
f7eb47b…
|
lmata
|
188 |
}); |
|
f7eb47b…
|
lmata
|
189 |
await new Promise(() => { |
|
f7eb47b…
|
lmata
|
190 |
}); |
|
f7eb47b…
|
lmata
|
191 |
} |
|
f7eb47b…
|
lmata
|
192 |
function startHtmlReportServer(folder) { |
|
f7eb47b…
|
lmata
|
193 |
const server = new import_utils.HttpServer(); |
|
f7eb47b…
|
lmata
|
194 |
server.routePrefix("/", (request, response) => { |
|
f7eb47b…
|
lmata
|
195 |
let relativePath = new URL("http://localhost" + request.url).pathname; |
|
f7eb47b…
|
lmata
|
196 |
if (relativePath.startsWith("/trace/file")) { |
|
f7eb47b…
|
lmata
|
197 |
const url = new URL("http://localhost" + request.url); |
|
f7eb47b…
|
lmata
|
198 |
try { |
|
f7eb47b…
|
lmata
|
199 |
return server.serveFile(request, response, url.searchParams.get("path")); |
|
f7eb47b…
|
lmata
|
200 |
} catch (e) { |
|
f7eb47b…
|
lmata
|
201 |
return false; |
|
f7eb47b…
|
lmata
|
202 |
} |
|
f7eb47b…
|
lmata
|
203 |
} |
|
f7eb47b…
|
lmata
|
204 |
if (relativePath === "/") |
|
f7eb47b…
|
lmata
|
205 |
relativePath = "/index.html"; |
|
f7eb47b…
|
lmata
|
206 |
const absolutePath = import_path.default.join(folder, ...relativePath.split("/")); |
|
f7eb47b…
|
lmata
|
207 |
return server.serveFile(request, response, absolutePath); |
|
f7eb47b…
|
lmata
|
208 |
}); |
|
f7eb47b…
|
lmata
|
209 |
return server; |
|
f7eb47b…
|
lmata
|
210 |
} |
|
f7eb47b…
|
lmata
|
211 |
class HtmlBuilder { |
|
f7eb47b…
|
lmata
|
212 |
constructor(config, outputDir, attachmentsBaseURL, options) { |
|
f7eb47b…
|
lmata
|
213 |
this._stepsInFile = new import_utils.MultiMap(); |
|
f7eb47b…
|
lmata
|
214 |
this._hasTraces = false; |
|
f7eb47b…
|
lmata
|
215 |
this._config = config; |
|
f7eb47b…
|
lmata
|
216 |
this._reportFolder = outputDir; |
|
f7eb47b…
|
lmata
|
217 |
this._options = options; |
|
f7eb47b…
|
lmata
|
218 |
import_fs.default.mkdirSync(this._reportFolder, { recursive: true }); |
|
f7eb47b…
|
lmata
|
219 |
this._dataZipFile = new import_zipBundle.yazl.ZipFile(); |
|
f7eb47b…
|
lmata
|
220 |
this._attachmentsBaseURL = attachmentsBaseURL; |
|
f7eb47b…
|
lmata
|
221 |
} |
|
f7eb47b…
|
lmata
|
222 |
async build(metadata, projectSuites, result, topLevelErrors, machines) { |
|
f7eb47b…
|
lmata
|
223 |
const data = /* @__PURE__ */ new Map(); |
|
f7eb47b…
|
lmata
|
224 |
for (const projectSuite of projectSuites) { |
|
f7eb47b…
|
lmata
|
225 |
const projectName = projectSuite.project().name; |
|
f7eb47b…
|
lmata
|
226 |
for (const fileSuite of projectSuite.suites) { |
|
f7eb47b…
|
lmata
|
227 |
const fileName = this._relativeLocation(fileSuite.location).file; |
|
f7eb47b…
|
lmata
|
228 |
this._createEntryForSuite(data, projectName, fileSuite, fileName, true); |
|
f7eb47b…
|
lmata
|
229 |
} |
|
f7eb47b…
|
lmata
|
230 |
} |
|
f7eb47b…
|
lmata
|
231 |
if (!this._options.noSnippets) |
|
f7eb47b…
|
lmata
|
232 |
createSnippets(this._stepsInFile); |
|
f7eb47b…
|
lmata
|
233 |
let ok = true; |
|
f7eb47b…
|
lmata
|
234 |
for (const [fileId, { testFile, testFileSummary }] of data) { |
|
f7eb47b…
|
lmata
|
235 |
const stats = testFileSummary.stats; |
|
f7eb47b…
|
lmata
|
236 |
for (const test of testFileSummary.tests) { |
|
f7eb47b…
|
lmata
|
237 |
if (test.outcome === "expected") |
|
f7eb47b…
|
lmata
|
238 |
++stats.expected; |
|
f7eb47b…
|
lmata
|
239 |
if (test.outcome === "skipped") |
|
f7eb47b…
|
lmata
|
240 |
++stats.skipped; |
|
f7eb47b…
|
lmata
|
241 |
if (test.outcome === "unexpected") |
|
f7eb47b…
|
lmata
|
242 |
++stats.unexpected; |
|
f7eb47b…
|
lmata
|
243 |
if (test.outcome === "flaky") |
|
f7eb47b…
|
lmata
|
244 |
++stats.flaky; |
|
f7eb47b…
|
lmata
|
245 |
++stats.total; |
|
f7eb47b…
|
lmata
|
246 |
} |
|
f7eb47b…
|
lmata
|
247 |
stats.ok = stats.unexpected + stats.flaky === 0; |
|
f7eb47b…
|
lmata
|
248 |
if (!stats.ok) |
|
f7eb47b…
|
lmata
|
249 |
ok = false; |
|
f7eb47b…
|
lmata
|
250 |
const testCaseSummaryComparator = (t1, t2) => { |
|
f7eb47b…
|
lmata
|
251 |
const w1 = (t1.outcome === "unexpected" ? 1e3 : 0) + (t1.outcome === "flaky" ? 1 : 0); |
|
f7eb47b…
|
lmata
|
252 |
const w2 = (t2.outcome === "unexpected" ? 1e3 : 0) + (t2.outcome === "flaky" ? 1 : 0); |
|
f7eb47b…
|
lmata
|
253 |
return w2 - w1; |
|
f7eb47b…
|
lmata
|
254 |
}; |
|
f7eb47b…
|
lmata
|
255 |
testFileSummary.tests.sort(testCaseSummaryComparator); |
|
f7eb47b…
|
lmata
|
256 |
this._addDataFile(fileId + ".json", testFile); |
|
f7eb47b…
|
lmata
|
257 |
} |
|
f7eb47b…
|
lmata
|
258 |
const htmlReport = { |
|
f7eb47b…
|
lmata
|
259 |
metadata, |
|
f7eb47b…
|
lmata
|
260 |
startTime: result.startTime.getTime(), |
|
f7eb47b…
|
lmata
|
261 |
duration: result.duration, |
|
f7eb47b…
|
lmata
|
262 |
files: [...data.values()].map((e) => e.testFileSummary), |
|
f7eb47b…
|
lmata
|
263 |
projectNames: projectSuites.map((r) => r.project().name), |
|
f7eb47b…
|
lmata
|
264 |
stats: { ...[...data.values()].reduce((a, e) => addStats(a, e.testFileSummary.stats), emptyStats()) }, |
|
f7eb47b…
|
lmata
|
265 |
errors: topLevelErrors.map((error) => (0, import_base.formatError)(import_base.internalScreen, error).message), |
|
f7eb47b…
|
lmata
|
266 |
options: this._options, |
|
f7eb47b…
|
lmata
|
267 |
machines: machines.map((s) => ({ |
|
f7eb47b…
|
lmata
|
268 |
duration: s.duration, |
|
f7eb47b…
|
lmata
|
269 |
startTime: s.startTime.getTime(), |
|
f7eb47b…
|
lmata
|
270 |
tag: s.tag, |
|
f7eb47b…
|
lmata
|
271 |
shardIndex: s.shardIndex |
|
f7eb47b…
|
lmata
|
272 |
})) |
|
f7eb47b…
|
lmata
|
273 |
}; |
|
f7eb47b…
|
lmata
|
274 |
htmlReport.files.sort((f1, f2) => { |
|
f7eb47b…
|
lmata
|
275 |
const w1 = f1.stats.unexpected * 1e3 + f1.stats.flaky; |
|
f7eb47b…
|
lmata
|
276 |
const w2 = f2.stats.unexpected * 1e3 + f2.stats.flaky; |
|
f7eb47b…
|
lmata
|
277 |
return w2 - w1; |
|
f7eb47b…
|
lmata
|
278 |
}); |
|
f7eb47b…
|
lmata
|
279 |
this._addDataFile("report.json", htmlReport); |
|
f7eb47b…
|
lmata
|
280 |
let singleTestId; |
|
f7eb47b…
|
lmata
|
281 |
if (htmlReport.stats.total === 1) { |
|
f7eb47b…
|
lmata
|
282 |
const testFile = data.values().next().value.testFile; |
|
f7eb47b…
|
lmata
|
283 |
singleTestId = testFile.tests[0].testId; |
|
f7eb47b…
|
lmata
|
284 |
} |
|
f7eb47b…
|
lmata
|
285 |
const appFolder = import_path.default.join(require.resolve("playwright-core"), "..", "lib", "vite", "htmlReport"); |
|
f7eb47b…
|
lmata
|
286 |
await (0, import_utils.copyFileAndMakeWritable)(import_path.default.join(appFolder, "index.html"), import_path.default.join(this._reportFolder, "index.html")); |
|
f7eb47b…
|
lmata
|
287 |
if (this._hasTraces) { |
|
f7eb47b…
|
lmata
|
288 |
const traceViewerFolder = import_path.default.join(require.resolve("playwright-core"), "..", "lib", "vite", "traceViewer"); |
|
f7eb47b…
|
lmata
|
289 |
const traceViewerTargetFolder = import_path.default.join(this._reportFolder, "trace"); |
|
f7eb47b…
|
lmata
|
290 |
const traceViewerAssetsTargetFolder = import_path.default.join(traceViewerTargetFolder, "assets"); |
|
f7eb47b…
|
lmata
|
291 |
import_fs.default.mkdirSync(traceViewerAssetsTargetFolder, { recursive: true }); |
|
f7eb47b…
|
lmata
|
292 |
for (const file of import_fs.default.readdirSync(traceViewerFolder)) { |
|
f7eb47b…
|
lmata
|
293 |
if (file.endsWith(".map") || file.includes("watch") || file.includes("assets")) |
|
f7eb47b…
|
lmata
|
294 |
continue; |
|
f7eb47b…
|
lmata
|
295 |
await (0, import_utils.copyFileAndMakeWritable)(import_path.default.join(traceViewerFolder, file), import_path.default.join(traceViewerTargetFolder, file)); |
|
f7eb47b…
|
lmata
|
296 |
} |
|
f7eb47b…
|
lmata
|
297 |
for (const file of import_fs.default.readdirSync(import_path.default.join(traceViewerFolder, "assets"))) { |
|
f7eb47b…
|
lmata
|
298 |
if (file.endsWith(".map") || file.includes("xtermModule")) |
|
f7eb47b…
|
lmata
|
299 |
continue; |
|
f7eb47b…
|
lmata
|
300 |
await (0, import_utils.copyFileAndMakeWritable)(import_path.default.join(traceViewerFolder, "assets", file), import_path.default.join(traceViewerAssetsTargetFolder, file)); |
|
f7eb47b…
|
lmata
|
301 |
} |
|
f7eb47b…
|
lmata
|
302 |
} |
|
f7eb47b…
|
lmata
|
303 |
await this._writeReportData(import_path.default.join(this._reportFolder, "index.html")); |
|
f7eb47b…
|
lmata
|
304 |
return { ok, singleTestId }; |
|
f7eb47b…
|
lmata
|
305 |
} |
|
f7eb47b…
|
lmata
|
306 |
async _writeReportData(filePath) { |
|
f7eb47b…
|
lmata
|
307 |
import_fs.default.appendFileSync(filePath, '<script id="playwrightReportBase64" type="application/zip">data:application/zip;base64,'); |
|
f7eb47b…
|
lmata
|
308 |
await new Promise((f) => { |
|
f7eb47b…
|
lmata
|
309 |
this._dataZipFile.end(void 0, () => { |
|
f7eb47b…
|
lmata
|
310 |
this._dataZipFile.outputStream.pipe(new Base64Encoder()).pipe(import_fs.default.createWriteStream(filePath, { flags: "a" })).on("close", f); |
|
f7eb47b…
|
lmata
|
311 |
}); |
|
f7eb47b…
|
lmata
|
312 |
}); |
|
f7eb47b…
|
lmata
|
313 |
import_fs.default.appendFileSync(filePath, "</script>"); |
|
f7eb47b…
|
lmata
|
314 |
} |
|
f7eb47b…
|
lmata
|
315 |
_addDataFile(fileName, data) { |
|
f7eb47b…
|
lmata
|
316 |
this._dataZipFile.addBuffer(Buffer.from(JSON.stringify(data)), fileName); |
|
f7eb47b…
|
lmata
|
317 |
} |
|
f7eb47b…
|
lmata
|
318 |
_createEntryForSuite(data, projectName, suite, fileName, deep) { |
|
f7eb47b…
|
lmata
|
319 |
const fileId = (0, import_utils.calculateSha1)(fileName).slice(0, 20); |
|
f7eb47b…
|
lmata
|
320 |
let fileEntry = data.get(fileId); |
|
f7eb47b…
|
lmata
|
321 |
if (!fileEntry) { |
|
f7eb47b…
|
lmata
|
322 |
fileEntry = { |
|
f7eb47b…
|
lmata
|
323 |
testFile: { fileId, fileName, tests: [] }, |
|
f7eb47b…
|
lmata
|
324 |
testFileSummary: { fileId, fileName, tests: [], stats: emptyStats() } |
|
f7eb47b…
|
lmata
|
325 |
}; |
|
f7eb47b…
|
lmata
|
326 |
data.set(fileId, fileEntry); |
|
f7eb47b…
|
lmata
|
327 |
} |
|
f7eb47b…
|
lmata
|
328 |
const { testFile, testFileSummary } = fileEntry; |
|
f7eb47b…
|
lmata
|
329 |
const testEntries = []; |
|
f7eb47b…
|
lmata
|
330 |
this._processSuite(suite, projectName, [], deep, testEntries); |
|
f7eb47b…
|
lmata
|
331 |
for (const test of testEntries) { |
|
f7eb47b…
|
lmata
|
332 |
testFile.tests.push(test.testCase); |
|
f7eb47b…
|
lmata
|
333 |
testFileSummary.tests.push(test.testCaseSummary); |
|
f7eb47b…
|
lmata
|
334 |
} |
|
f7eb47b…
|
lmata
|
335 |
} |
|
f7eb47b…
|
lmata
|
336 |
_processSuite(suite, projectName, path2, deep, outTests) { |
|
f7eb47b…
|
lmata
|
337 |
const newPath = [...path2, suite.title]; |
|
f7eb47b…
|
lmata
|
338 |
suite.entries().forEach((e) => { |
|
f7eb47b…
|
lmata
|
339 |
if (e.type === "test") |
|
f7eb47b…
|
lmata
|
340 |
outTests.push(this._createTestEntry(e, projectName, newPath)); |
|
f7eb47b…
|
lmata
|
341 |
else if (deep) |
|
f7eb47b…
|
lmata
|
342 |
this._processSuite(e, projectName, newPath, deep, outTests); |
|
f7eb47b…
|
lmata
|
343 |
}); |
|
f7eb47b…
|
lmata
|
344 |
} |
|
f7eb47b…
|
lmata
|
345 |
_createTestEntry(test, projectName, path2) { |
|
f7eb47b…
|
lmata
|
346 |
const duration = test.results.reduce((a, r) => a + r.duration, 0); |
|
f7eb47b…
|
lmata
|
347 |
const location = this._relativeLocation(test.location); |
|
f7eb47b…
|
lmata
|
348 |
path2 = path2.slice(1).filter((path3) => path3.length > 0); |
|
f7eb47b…
|
lmata
|
349 |
const results = test.results.map((r) => this._createTestResult(test, r)); |
|
f7eb47b…
|
lmata
|
350 |
return { |
|
f7eb47b…
|
lmata
|
351 |
testCase: { |
|
f7eb47b…
|
lmata
|
352 |
testId: test.id, |
|
f7eb47b…
|
lmata
|
353 |
title: test.title, |
|
f7eb47b…
|
lmata
|
354 |
projectName, |
|
f7eb47b…
|
lmata
|
355 |
location, |
|
f7eb47b…
|
lmata
|
356 |
duration, |
|
f7eb47b…
|
lmata
|
357 |
annotations: this._serializeAnnotations(test.annotations), |
|
f7eb47b…
|
lmata
|
358 |
tags: test.tags, |
|
f7eb47b…
|
lmata
|
359 |
outcome: test.outcome(), |
|
f7eb47b…
|
lmata
|
360 |
path: path2, |
|
f7eb47b…
|
lmata
|
361 |
results, |
|
f7eb47b…
|
lmata
|
362 |
ok: test.outcome() === "expected" || test.outcome() === "flaky" |
|
f7eb47b…
|
lmata
|
363 |
}, |
|
f7eb47b…
|
lmata
|
364 |
testCaseSummary: { |
|
f7eb47b…
|
lmata
|
365 |
testId: test.id, |
|
f7eb47b…
|
lmata
|
366 |
title: test.title, |
|
f7eb47b…
|
lmata
|
367 |
projectName, |
|
f7eb47b…
|
lmata
|
368 |
location, |
|
f7eb47b…
|
lmata
|
369 |
duration, |
|
f7eb47b…
|
lmata
|
370 |
annotations: this._serializeAnnotations(test.annotations), |
|
f7eb47b…
|
lmata
|
371 |
tags: test.tags, |
|
f7eb47b…
|
lmata
|
372 |
outcome: test.outcome(), |
|
f7eb47b…
|
lmata
|
373 |
path: path2, |
|
f7eb47b…
|
lmata
|
374 |
ok: test.outcome() === "expected" || test.outcome() === "flaky", |
|
f7eb47b…
|
lmata
|
375 |
results: results.map((result) => { |
|
f7eb47b…
|
lmata
|
376 |
return { attachments: result.attachments.map((a) => ({ name: a.name, contentType: a.contentType, path: a.path })) }; |
|
f7eb47b…
|
lmata
|
377 |
}) |
|
f7eb47b…
|
lmata
|
378 |
} |
|
f7eb47b…
|
lmata
|
379 |
}; |
|
f7eb47b…
|
lmata
|
380 |
} |
|
f7eb47b…
|
lmata
|
381 |
_serializeAttachments(attachments) { |
|
f7eb47b…
|
lmata
|
382 |
let lastAttachment; |
|
f7eb47b…
|
lmata
|
383 |
return attachments.map((a) => { |
|
f7eb47b…
|
lmata
|
384 |
if (a.name === "trace") |
|
f7eb47b…
|
lmata
|
385 |
this._hasTraces = true; |
|
f7eb47b…
|
lmata
|
386 |
if ((a.name === "stdout" || a.name === "stderr") && a.contentType === "text/plain") { |
|
f7eb47b…
|
lmata
|
387 |
if (lastAttachment && lastAttachment.name === a.name && lastAttachment.contentType === a.contentType) { |
|
f7eb47b…
|
lmata
|
388 |
lastAttachment.body += (0, import_util.stripAnsiEscapes)(a.body); |
|
f7eb47b…
|
lmata
|
389 |
return null; |
|
f7eb47b…
|
lmata
|
390 |
} |
|
f7eb47b…
|
lmata
|
391 |
a.body = (0, import_util.stripAnsiEscapes)(a.body); |
|
f7eb47b…
|
lmata
|
392 |
lastAttachment = a; |
|
f7eb47b…
|
lmata
|
393 |
return a; |
|
f7eb47b…
|
lmata
|
394 |
} |
|
f7eb47b…
|
lmata
|
395 |
if (a.path) { |
|
f7eb47b…
|
lmata
|
396 |
let fileName = a.path; |
|
f7eb47b…
|
lmata
|
397 |
try { |
|
f7eb47b…
|
lmata
|
398 |
const buffer = import_fs.default.readFileSync(a.path); |
|
f7eb47b…
|
lmata
|
399 |
const sha1 = (0, import_utils.calculateSha1)(buffer) + import_path.default.extname(a.path); |
|
f7eb47b…
|
lmata
|
400 |
fileName = this._attachmentsBaseURL + sha1; |
|
f7eb47b…
|
lmata
|
401 |
import_fs.default.mkdirSync(import_path.default.join(this._reportFolder, "data"), { recursive: true }); |
|
f7eb47b…
|
lmata
|
402 |
import_fs.default.writeFileSync(import_path.default.join(this._reportFolder, "data", sha1), buffer); |
|
f7eb47b…
|
lmata
|
403 |
} catch (e) { |
|
f7eb47b…
|
lmata
|
404 |
} |
|
f7eb47b…
|
lmata
|
405 |
return { |
|
f7eb47b…
|
lmata
|
406 |
name: a.name, |
|
f7eb47b…
|
lmata
|
407 |
contentType: a.contentType, |
|
f7eb47b…
|
lmata
|
408 |
path: fileName, |
|
f7eb47b…
|
lmata
|
409 |
body: a.body |
|
f7eb47b…
|
lmata
|
410 |
}; |
|
f7eb47b…
|
lmata
|
411 |
} |
|
f7eb47b…
|
lmata
|
412 |
if (a.body instanceof Buffer) { |
|
f7eb47b…
|
lmata
|
413 |
if (isTextContentType(a.contentType)) { |
|
f7eb47b…
|
lmata
|
414 |
const charset = a.contentType.match(/charset=(.*)/)?.[1]; |
|
f7eb47b…
|
lmata
|
415 |
try { |
|
f7eb47b…
|
lmata
|
416 |
const body = a.body.toString(charset || "utf-8"); |
|
f7eb47b…
|
lmata
|
417 |
return { |
|
f7eb47b…
|
lmata
|
418 |
name: a.name, |
|
f7eb47b…
|
lmata
|
419 |
contentType: a.contentType, |
|
f7eb47b…
|
lmata
|
420 |
body |
|
f7eb47b…
|
lmata
|
421 |
}; |
|
f7eb47b…
|
lmata
|
422 |
} catch (e) { |
|
f7eb47b…
|
lmata
|
423 |
} |
|
f7eb47b…
|
lmata
|
424 |
} |
|
f7eb47b…
|
lmata
|
425 |
import_fs.default.mkdirSync(import_path.default.join(this._reportFolder, "data"), { recursive: true }); |
|
f7eb47b…
|
lmata
|
426 |
const extension = (0, import_utils.sanitizeForFilePath)(import_path.default.extname(a.name).replace(/^\./, "")) || import_utilsBundle2.mime.getExtension(a.contentType) || "dat"; |
|
f7eb47b…
|
lmata
|
427 |
const sha1 = (0, import_utils.calculateSha1)(a.body) + "." + extension; |
|
f7eb47b…
|
lmata
|
428 |
import_fs.default.writeFileSync(import_path.default.join(this._reportFolder, "data", sha1), a.body); |
|
f7eb47b…
|
lmata
|
429 |
return { |
|
f7eb47b…
|
lmata
|
430 |
name: a.name, |
|
f7eb47b…
|
lmata
|
431 |
contentType: a.contentType, |
|
f7eb47b…
|
lmata
|
432 |
path: this._attachmentsBaseURL + sha1 |
|
f7eb47b…
|
lmata
|
433 |
}; |
|
f7eb47b…
|
lmata
|
434 |
} |
|
f7eb47b…
|
lmata
|
435 |
return { |
|
f7eb47b…
|
lmata
|
436 |
name: a.name, |
|
f7eb47b…
|
lmata
|
437 |
contentType: a.contentType, |
|
f7eb47b…
|
lmata
|
438 |
body: a.body |
|
f7eb47b…
|
lmata
|
439 |
}; |
|
f7eb47b…
|
lmata
|
440 |
}).filter(Boolean); |
|
f7eb47b…
|
lmata
|
441 |
} |
|
f7eb47b…
|
lmata
|
442 |
_serializeAnnotations(annotations) { |
|
f7eb47b…
|
lmata
|
443 |
return annotations.map((a) => ({ |
|
f7eb47b…
|
lmata
|
444 |
type: a.type, |
|
f7eb47b…
|
lmata
|
445 |
description: a.description === void 0 ? void 0 : String(a.description), |
|
f7eb47b…
|
lmata
|
446 |
location: a.location ? { |
|
f7eb47b…
|
lmata
|
447 |
file: a.location.file, |
|
f7eb47b…
|
lmata
|
448 |
line: a.location.line, |
|
f7eb47b…
|
lmata
|
449 |
column: a.location.column |
|
f7eb47b…
|
lmata
|
450 |
} : void 0 |
|
f7eb47b…
|
lmata
|
451 |
})); |
|
f7eb47b…
|
lmata
|
452 |
} |
|
f7eb47b…
|
lmata
|
453 |
_createTestResult(test, result) { |
|
f7eb47b…
|
lmata
|
454 |
return { |
|
f7eb47b…
|
lmata
|
455 |
duration: result.duration, |
|
f7eb47b…
|
lmata
|
456 |
startTime: result.startTime.toISOString(), |
|
f7eb47b…
|
lmata
|
457 |
retry: result.retry, |
|
f7eb47b…
|
lmata
|
458 |
steps: dedupeSteps(result.steps).map((s) => this._createTestStep(s, result)), |
|
f7eb47b…
|
lmata
|
459 |
errors: (0, import_base.formatResultFailure)(import_base.internalScreen, test, result, "").map((error) => { |
|
f7eb47b…
|
lmata
|
460 |
return { |
|
f7eb47b…
|
lmata
|
461 |
message: error.message, |
|
f7eb47b…
|
lmata
|
462 |
codeframe: error.location ? createErrorCodeframe(error.message, error.location) : void 0 |
|
f7eb47b…
|
lmata
|
463 |
}; |
|
f7eb47b…
|
lmata
|
464 |
}), |
|
f7eb47b…
|
lmata
|
465 |
status: result.status, |
|
f7eb47b…
|
lmata
|
466 |
annotations: this._serializeAnnotations(result.annotations), |
|
f7eb47b…
|
lmata
|
467 |
attachments: this._serializeAttachments([ |
|
f7eb47b…
|
lmata
|
468 |
...result.attachments, |
|
f7eb47b…
|
lmata
|
469 |
...result.stdout.map((m) => stdioAttachment(m, "stdout")), |
|
f7eb47b…
|
lmata
|
470 |
...result.stderr.map((m) => stdioAttachment(m, "stderr")) |
|
f7eb47b…
|
lmata
|
471 |
]) |
|
f7eb47b…
|
lmata
|
472 |
}; |
|
f7eb47b…
|
lmata
|
473 |
} |
|
f7eb47b…
|
lmata
|
474 |
_createTestStep(dedupedStep, result) { |
|
f7eb47b…
|
lmata
|
475 |
const { step, duration, count } = dedupedStep; |
|
f7eb47b…
|
lmata
|
476 |
const skipped = dedupedStep.step.annotations?.find((a) => a.type === "skip"); |
|
f7eb47b…
|
lmata
|
477 |
let title = step.title; |
|
f7eb47b…
|
lmata
|
478 |
if (skipped) |
|
f7eb47b…
|
lmata
|
479 |
title = `${title} (skipped${skipped.description ? ": " + skipped.description : ""})`; |
|
f7eb47b…
|
lmata
|
480 |
const testStep = { |
|
f7eb47b…
|
lmata
|
481 |
title, |
|
f7eb47b…
|
lmata
|
482 |
startTime: step.startTime.toISOString(), |
|
f7eb47b…
|
lmata
|
483 |
duration, |
|
f7eb47b…
|
lmata
|
484 |
steps: dedupeSteps(step.steps).map((s) => this._createTestStep(s, result)), |
|
f7eb47b…
|
lmata
|
485 |
attachments: step.attachments.map((s) => { |
|
f7eb47b…
|
lmata
|
486 |
const index = result.attachments.indexOf(s); |
|
f7eb47b…
|
lmata
|
487 |
if (index === -1) |
|
f7eb47b…
|
lmata
|
488 |
throw new Error("Unexpected, attachment not found"); |
|
f7eb47b…
|
lmata
|
489 |
return index; |
|
f7eb47b…
|
lmata
|
490 |
}), |
|
f7eb47b…
|
lmata
|
491 |
location: this._relativeLocation(step.location), |
|
f7eb47b…
|
lmata
|
492 |
error: step.error?.message, |
|
f7eb47b…
|
lmata
|
493 |
count, |
|
f7eb47b…
|
lmata
|
494 |
skipped: !!skipped |
|
f7eb47b…
|
lmata
|
495 |
}; |
|
f7eb47b…
|
lmata
|
496 |
if (step.location) |
|
f7eb47b…
|
lmata
|
497 |
this._stepsInFile.set(step.location.file, testStep); |
|
f7eb47b…
|
lmata
|
498 |
return testStep; |
|
f7eb47b…
|
lmata
|
499 |
} |
|
f7eb47b…
|
lmata
|
500 |
_relativeLocation(location) { |
|
f7eb47b…
|
lmata
|
501 |
if (!location) |
|
f7eb47b…
|
lmata
|
502 |
return void 0; |
|
f7eb47b…
|
lmata
|
503 |
const file = (0, import_utils.toPosixPath)(import_path.default.relative(this._config.rootDir, location.file)); |
|
f7eb47b…
|
lmata
|
504 |
return { |
|
f7eb47b…
|
lmata
|
505 |
file, |
|
f7eb47b…
|
lmata
|
506 |
line: location.line, |
|
f7eb47b…
|
lmata
|
507 |
column: location.column |
|
f7eb47b…
|
lmata
|
508 |
}; |
|
f7eb47b…
|
lmata
|
509 |
} |
|
f7eb47b…
|
lmata
|
510 |
} |
|
f7eb47b…
|
lmata
|
511 |
const emptyStats = () => { |
|
f7eb47b…
|
lmata
|
512 |
return { |
|
f7eb47b…
|
lmata
|
513 |
total: 0, |
|
f7eb47b…
|
lmata
|
514 |
expected: 0, |
|
f7eb47b…
|
lmata
|
515 |
unexpected: 0, |
|
f7eb47b…
|
lmata
|
516 |
flaky: 0, |
|
f7eb47b…
|
lmata
|
517 |
skipped: 0, |
|
f7eb47b…
|
lmata
|
518 |
ok: true |
|
f7eb47b…
|
lmata
|
519 |
}; |
|
f7eb47b…
|
lmata
|
520 |
}; |
|
f7eb47b…
|
lmata
|
521 |
const addStats = (stats, delta) => { |
|
f7eb47b…
|
lmata
|
522 |
stats.total += delta.total; |
|
f7eb47b…
|
lmata
|
523 |
stats.skipped += delta.skipped; |
|
f7eb47b…
|
lmata
|
524 |
stats.expected += delta.expected; |
|
f7eb47b…
|
lmata
|
525 |
stats.unexpected += delta.unexpected; |
|
f7eb47b…
|
lmata
|
526 |
stats.flaky += delta.flaky; |
|
f7eb47b…
|
lmata
|
527 |
stats.ok = stats.ok && delta.ok; |
|
f7eb47b…
|
lmata
|
528 |
return stats; |
|
f7eb47b…
|
lmata
|
529 |
}; |
|
f7eb47b…
|
lmata
|
530 |
class Base64Encoder extends import_stream.Transform { |
|
f7eb47b…
|
lmata
|
531 |
_transform(chunk, encoding, callback) { |
|
f7eb47b…
|
lmata
|
532 |
if (this._remainder) { |
|
f7eb47b…
|
lmata
|
533 |
chunk = Buffer.concat([this._remainder, chunk]); |
|
f7eb47b…
|
lmata
|
534 |
this._remainder = void 0; |
|
f7eb47b…
|
lmata
|
535 |
} |
|
f7eb47b…
|
lmata
|
536 |
const remaining = chunk.length % 3; |
|
f7eb47b…
|
lmata
|
537 |
if (remaining) { |
|
f7eb47b…
|
lmata
|
538 |
this._remainder = chunk.slice(chunk.length - remaining); |
|
f7eb47b…
|
lmata
|
539 |
chunk = chunk.slice(0, chunk.length - remaining); |
|
f7eb47b…
|
lmata
|
540 |
} |
|
f7eb47b…
|
lmata
|
541 |
chunk = chunk.toString("base64"); |
|
f7eb47b…
|
lmata
|
542 |
this.push(Buffer.from(chunk)); |
|
f7eb47b…
|
lmata
|
543 |
callback(); |
|
f7eb47b…
|
lmata
|
544 |
} |
|
f7eb47b…
|
lmata
|
545 |
_flush(callback) { |
|
f7eb47b…
|
lmata
|
546 |
if (this._remainder) |
|
f7eb47b…
|
lmata
|
547 |
this.push(Buffer.from(this._remainder.toString("base64"))); |
|
f7eb47b…
|
lmata
|
548 |
callback(); |
|
f7eb47b…
|
lmata
|
549 |
} |
|
f7eb47b…
|
lmata
|
550 |
} |
|
f7eb47b…
|
lmata
|
551 |
function isTextContentType(contentType) { |
|
f7eb47b…
|
lmata
|
552 |
return contentType.startsWith("text/") || contentType.startsWith("application/json"); |
|
f7eb47b…
|
lmata
|
553 |
} |
|
f7eb47b…
|
lmata
|
554 |
function stdioAttachment(chunk, type) { |
|
f7eb47b…
|
lmata
|
555 |
return { |
|
f7eb47b…
|
lmata
|
556 |
name: type, |
|
f7eb47b…
|
lmata
|
557 |
contentType: "text/plain", |
|
f7eb47b…
|
lmata
|
558 |
body: typeof chunk === "string" ? chunk : chunk.toString("utf-8") |
|
f7eb47b…
|
lmata
|
559 |
}; |
|
f7eb47b…
|
lmata
|
560 |
} |
|
f7eb47b…
|
lmata
|
561 |
function dedupeSteps(steps) { |
|
f7eb47b…
|
lmata
|
562 |
const result = []; |
|
f7eb47b…
|
lmata
|
563 |
let lastResult = void 0; |
|
f7eb47b…
|
lmata
|
564 |
for (const step of steps) { |
|
f7eb47b…
|
lmata
|
565 |
const canDedupe = !step.error && step.duration >= 0 && step.location?.file && !step.steps.length; |
|
f7eb47b…
|
lmata
|
566 |
const lastStep = lastResult?.step; |
|
f7eb47b…
|
lmata
|
567 |
if (canDedupe && lastResult && lastStep && step.category === lastStep.category && step.title === lastStep.title && step.location?.file === lastStep.location?.file && step.location?.line === lastStep.location?.line && step.location?.column === lastStep.location?.column) { |
|
f7eb47b…
|
lmata
|
568 |
++lastResult.count; |
|
f7eb47b…
|
lmata
|
569 |
lastResult.duration += step.duration; |
|
f7eb47b…
|
lmata
|
570 |
continue; |
|
f7eb47b…
|
lmata
|
571 |
} |
|
f7eb47b…
|
lmata
|
572 |
lastResult = { step, count: 1, duration: step.duration }; |
|
f7eb47b…
|
lmata
|
573 |
result.push(lastResult); |
|
f7eb47b…
|
lmata
|
574 |
if (!canDedupe) |
|
f7eb47b…
|
lmata
|
575 |
lastResult = void 0; |
|
f7eb47b…
|
lmata
|
576 |
} |
|
f7eb47b…
|
lmata
|
577 |
return result; |
|
f7eb47b…
|
lmata
|
578 |
} |
|
f7eb47b…
|
lmata
|
579 |
function createSnippets(stepsInFile) { |
|
f7eb47b…
|
lmata
|
580 |
for (const file of stepsInFile.keys()) { |
|
f7eb47b…
|
lmata
|
581 |
let source; |
|
f7eb47b…
|
lmata
|
582 |
try { |
|
f7eb47b…
|
lmata
|
583 |
source = import_fs.default.readFileSync(file, "utf-8") + "\n//"; |
|
f7eb47b…
|
lmata
|
584 |
} catch (e) { |
|
f7eb47b…
|
lmata
|
585 |
continue; |
|
f7eb47b…
|
lmata
|
586 |
} |
|
f7eb47b…
|
lmata
|
587 |
const lines = source.split("\n").length; |
|
f7eb47b…
|
lmata
|
588 |
const highlighted = (0, import_babelBundle.codeFrameColumns)(source, { start: { line: lines, column: 1 } }, { highlightCode: true, linesAbove: lines, linesBelow: 0 }); |
|
f7eb47b…
|
lmata
|
589 |
const highlightedLines = highlighted.split("\n"); |
|
f7eb47b…
|
lmata
|
590 |
const lineWithArrow = highlightedLines[highlightedLines.length - 1]; |
|
f7eb47b…
|
lmata
|
591 |
for (const step of stepsInFile.get(file)) { |
|
f7eb47b…
|
lmata
|
592 |
if (step.location.line < 2 || step.location.line >= lines) |
|
f7eb47b…
|
lmata
|
593 |
continue; |
|
f7eb47b…
|
lmata
|
594 |
const snippetLines = highlightedLines.slice(step.location.line - 2, step.location.line + 1); |
|
f7eb47b…
|
lmata
|
595 |
const index = lineWithArrow.indexOf("^"); |
|
f7eb47b…
|
lmata
|
596 |
const shiftedArrow = lineWithArrow.slice(0, index) + " ".repeat(step.location.column - 1) + lineWithArrow.slice(index); |
|
f7eb47b…
|
lmata
|
597 |
snippetLines.splice(2, 0, shiftedArrow); |
|
f7eb47b…
|
lmata
|
598 |
step.snippet = snippetLines.join("\n"); |
|
f7eb47b…
|
lmata
|
599 |
} |
|
f7eb47b…
|
lmata
|
600 |
} |
|
f7eb47b…
|
lmata
|
601 |
} |
|
f7eb47b…
|
lmata
|
602 |
function createErrorCodeframe(message, location) { |
|
f7eb47b…
|
lmata
|
603 |
let source; |
|
f7eb47b…
|
lmata
|
604 |
try { |
|
f7eb47b…
|
lmata
|
605 |
source = import_fs.default.readFileSync(location.file, "utf-8") + "\n//"; |
|
f7eb47b…
|
lmata
|
606 |
} catch (e) { |
|
f7eb47b…
|
lmata
|
607 |
return; |
|
f7eb47b…
|
lmata
|
608 |
} |
|
f7eb47b…
|
lmata
|
609 |
return (0, import_babelBundle.codeFrameColumns)( |
|
f7eb47b…
|
lmata
|
610 |
source, |
|
f7eb47b…
|
lmata
|
611 |
{ |
|
f7eb47b…
|
lmata
|
612 |
start: { |
|
f7eb47b…
|
lmata
|
613 |
line: location.line, |
|
f7eb47b…
|
lmata
|
614 |
column: location.column |
|
f7eb47b…
|
lmata
|
615 |
} |
|
f7eb47b…
|
lmata
|
616 |
}, |
|
f7eb47b…
|
lmata
|
617 |
{ |
|
f7eb47b…
|
lmata
|
618 |
highlightCode: false, |
|
f7eb47b…
|
lmata
|
619 |
linesAbove: 100, |
|
f7eb47b…
|
lmata
|
620 |
linesBelow: 100, |
|
f7eb47b…
|
lmata
|
621 |
message: (0, import_util.stripAnsiEscapes)(message).split("\n")[0] || void 0 |
|
f7eb47b…
|
lmata
|
622 |
} |
|
f7eb47b…
|
lmata
|
623 |
); |
|
f7eb47b…
|
lmata
|
624 |
} |
|
f7eb47b…
|
lmata
|
625 |
function writeLine(line) { |
|
f7eb47b…
|
lmata
|
626 |
process.stdout.write(line + "\n"); |
|
f7eb47b…
|
lmata
|
627 |
} |
|
f7eb47b…
|
lmata
|
628 |
var html_default = HtmlReporter; |
|
f7eb47b…
|
lmata
|
629 |
// Annotate the CommonJS export names for ESM import in node: |
|
f7eb47b…
|
lmata
|
630 |
0 && (module.exports = { |
|
f7eb47b…
|
lmata
|
631 |
showHTMLReport, |
|
f7eb47b…
|
lmata
|
632 |
startHtmlReportServer |
|
f7eb47b…
|
lmata
|
633 |
}); |