@empiricalrun/playwright-utils 0.6.3 → 0.7.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @empiricalrun/playwright-utils
2
2
 
3
+ ## 0.7.1
4
+
5
+ ### Patch Changes
6
+
7
+ - f4dd084: minor fix
8
+
9
+ ## 0.7.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 6d954fd: feat: use custom playwright reporter
14
+
3
15
  ## 0.6.3
4
16
 
5
17
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,eAAO,MAAM,UAAU,EAAE,oBAuBxB,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,eAAO,MAAM,UAAU,EAAE,oBAyBxB,CAAC"}
package/dist/config.js CHANGED
@@ -3,14 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.baseConfig = void 0;
4
4
  exports.baseConfig = {
5
5
  testDir: "./tests",
6
+ outputDir: "./playwright-report/data", // to store default playwright artifacts (during and post test run)
6
7
  fullyParallel: true,
7
8
  forbidOnly: false,
8
9
  retries: "true" ? 2 : 0,
9
10
  workers: undefined,
10
11
  reporter: [
11
- ["html"],
12
- ["json", { outputFile: "test-results/summary.json" }],
12
+ ["./node_modules/@empiricalrun/playwright-utils/dist/reporter/custom.js"],
13
+ ["json", { outputFile: "playwright-report/summary.json" }],
13
14
  ["list"], // For real-time reporting on CI terminal (vs. the default "dot" reporter)
15
+ // ["html", { outputFolder: "test-results/html" }], // Original html reporter
14
16
  ],
15
17
  use: {
16
18
  trace: "on",
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /// <reference types="node" />
17
+ import type { FullConfig, Location, TestCase, TestError, TestResult, TestStep } from "@playwright/test/reporter";
18
+ export type TestResultOutput = {
19
+ chunk: string | Buffer;
20
+ type: "stdout" | "stderr";
21
+ };
22
+ export declare const kOutputSymbol: unique symbol;
23
+ type Annotation = {
24
+ title: string;
25
+ message: string;
26
+ location?: Location;
27
+ };
28
+ type ErrorDetails = {
29
+ message: string;
30
+ location?: Location;
31
+ };
32
+ export declare const isTTY: boolean, ttyWidth: number, colors: any;
33
+ export declare function formatFailure(config: FullConfig, test: TestCase, options?: {
34
+ index?: number;
35
+ includeStdio?: boolean;
36
+ includeAttachments?: boolean;
37
+ }): {
38
+ message: string;
39
+ annotations: Annotation[];
40
+ };
41
+ export declare function formatResultFailure(test: TestCase, result: TestResult, initialIndent: string, highlightCode: boolean): ErrorDetails[];
42
+ export declare function relativeFilePath(config: FullConfig, file: string): string;
43
+ export declare function stepSuffix(step: TestStep | undefined): string;
44
+ export declare function formatTestTitle(config: FullConfig, test: TestCase, step?: TestStep, omitLocation?: boolean): string;
45
+ export declare function formatError(error: TestError, highlightCode: boolean): ErrorDetails;
46
+ export declare function separator(text?: string): string;
47
+ export declare function prepareErrorStack(stack: string): {
48
+ message: string;
49
+ stackLines: string[];
50
+ location?: Location;
51
+ };
52
+ export declare function stripAnsiEscapes(str: string): string;
53
+ export declare function resolveOutputFile(reporterName: string, options: {
54
+ configDir: string;
55
+ outputDir?: string;
56
+ fileName?: string;
57
+ outputFile?: string;
58
+ default?: {
59
+ fileName: string;
60
+ outputDir: string;
61
+ };
62
+ }): {
63
+ outputFile: string;
64
+ outputDir?: string;
65
+ } | undefined;
66
+ export {};
67
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/reporter/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;;AAEH,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,UAAU,EACV,QAAQ,EACT,MAAM,2BAA2B,CAAC;AAWnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC3B,CAAC;AACF,eAAO,MAAM,aAAa,eAAmB,CAAC;AAE9C,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF,eAAO,MAAQ,KAAK,WAAE,QAAQ,UAAE,MAAM,KA6ClC,CAAC;AAEL,wBAAgB,aAAa,CAC3B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,QAAQ,EACd,OAAO,GAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACzB,GACL;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CA6FA;AAOD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,OAAO,GACrB,YAAY,EAAE,CAyBhB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzE;AAMD,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,UAMpD;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,QAAQ,EACd,IAAI,CAAC,EAAE,QAAQ,EACf,YAAY,GAAE,OAAe,GAC5B,MAAM,CASR;AAiCD,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,OAAO,GACrB,YAAY,CA+Bd;AAED,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAW,GAAG,MAAM,CAInD;AAMD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAmBA;AAOD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAcD,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;IACP,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,GACA;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CA8BxD"}
@@ -0,0 +1,350 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Microsoft Corporation.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ var __importDefault = (this && this.__importDefault) || function (mod) {
18
+ return (mod && mod.__esModule) ? mod : { "default": mod };
19
+ };
20
+ var _a;
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.resolveOutputFile = exports.stripAnsiEscapes = exports.prepareErrorStack = exports.separator = exports.formatError = exports.formatTestTitle = exports.stepSuffix = exports.relativeFilePath = exports.formatResultFailure = exports.formatFailure = exports.colors = exports.ttyWidth = exports.isTTY = exports.kOutputSymbol = void 0;
23
+ const path_1 = __importDefault(require("path"));
24
+ // @ts-ignore
25
+ const utils_1 = require("playwright-core/lib/utils");
26
+ const utilsBundle_1 = require("playwright-core/lib/utilsBundle");
27
+ const util_1 = require("./util");
28
+ exports.kOutputSymbol = Symbol("output");
29
+ _a = (() => {
30
+ let isTTY = !!process.stdout.isTTY;
31
+ let ttyWidth = process.stdout.columns || 0;
32
+ // if (
33
+ // process.env.PLAYWRIGHT_FORCE_TTY === "false" ||
34
+ // process.env.PLAYWRIGHT_FORCE_TTY === "0"
35
+ // ) {
36
+ // isTTY = false;
37
+ // ttyWidth = 0;
38
+ // } else if (
39
+ // process.env.PLAYWRIGHT_FORCE_TTY === "true" ||
40
+ // process.env.PLAYWRIGHT_FORCE_TTY === "1"
41
+ // ) {
42
+ // isTTY = true;
43
+ // ttyWidth = process.stdout.columns || 100;
44
+ // } else if (process.env.PLAYWRIGHT_FORCE_TTY) {
45
+ // isTTY = true;
46
+ // ttyWidth = +process.env.PLAYWRIGHT_FORCE_TTY;
47
+ // if (isNaN(ttyWidth)) ttyWidth = 100;
48
+ // }
49
+ let useColors = isTTY;
50
+ // if (
51
+ // process.env.DEBUG_COLORS === "0" ||
52
+ // process.env.DEBUG_COLORS === "false" ||
53
+ // process.env.FORCE_COLOR === "0" ||
54
+ // process.env.FORCE_COLOR === "false"
55
+ // )
56
+ // useColors = false;
57
+ // else if (process.env.DEBUG_COLORS || process.env.FORCE_COLOR)
58
+ // useColors = true;
59
+ const colors = useColors
60
+ ? utilsBundle_1.colors
61
+ : {
62
+ bold: (t) => t,
63
+ cyan: (t) => t,
64
+ dim: (t) => t,
65
+ gray: (t) => t,
66
+ green: (t) => t,
67
+ red: (t) => t,
68
+ yellow: (t) => t,
69
+ enabled: false,
70
+ };
71
+ return { isTTY, ttyWidth, colors };
72
+ })(), exports.isTTY = _a.isTTY, exports.ttyWidth = _a.ttyWidth, exports.colors = _a.colors;
73
+ function formatFailure(config, test, options = {}) {
74
+ const { index, includeStdio, includeAttachments = true } = options;
75
+ const lines = [];
76
+ const title = formatTestTitle(config, test);
77
+ const annotations = [];
78
+ const header = formatTestHeader(config, test, {
79
+ indent: " ",
80
+ index,
81
+ mode: "error",
82
+ });
83
+ lines.push(exports.colors.red(header));
84
+ for (const result of test.results) {
85
+ const resultLines = [];
86
+ const errors = formatResultFailure(test, result, " ", exports.colors.enabled);
87
+ if (!errors.length)
88
+ continue;
89
+ const retryLines = [];
90
+ if (result.retry) {
91
+ retryLines.push("");
92
+ retryLines.push(exports.colors.gray(separator(` Retry #${result.retry}`)));
93
+ }
94
+ resultLines.push(...retryLines);
95
+ resultLines.push(...errors.map((error) => "\n" + error.message));
96
+ if (includeAttachments) {
97
+ for (let i = 0; i < result.attachments.length; ++i) {
98
+ const attachment = result.attachments[i];
99
+ const hasPrintableContent = attachment?.contentType.startsWith("text/");
100
+ if (!attachment || (!attachment.path && !hasPrintableContent))
101
+ continue;
102
+ resultLines.push("");
103
+ resultLines.push(exports.colors.cyan(separator(` attachment #${i + 1}: ${attachment.name} (${attachment.contentType})`)));
104
+ if (attachment.path) {
105
+ const relativePath = path_1.default.relative(process.cwd(), attachment.path);
106
+ resultLines.push(exports.colors.cyan(` ${relativePath}`));
107
+ // Make this extensible
108
+ if (attachment.name === "trace") {
109
+ const packageManagerCommand = (0, utils_1.getPackageManagerExecCommand)();
110
+ resultLines.push(exports.colors.cyan(` Usage:`));
111
+ resultLines.push("");
112
+ resultLines.push(exports.colors.cyan(` ${packageManagerCommand} playwright show-trace ${quotePathIfNeeded(relativePath)}`));
113
+ resultLines.push("");
114
+ }
115
+ }
116
+ else {
117
+ if (attachment.contentType.startsWith("text/") && attachment.body) {
118
+ let text = attachment.body.toString();
119
+ if (text.length > 300)
120
+ text = text.slice(0, 300) + "...";
121
+ for (const line of text.split("\n"))
122
+ resultLines.push(exports.colors.cyan(` ${line}`));
123
+ }
124
+ }
125
+ resultLines.push(exports.colors.cyan(separator(" ")));
126
+ }
127
+ }
128
+ const output = (result[exports.kOutputSymbol] || []);
129
+ if (includeStdio && output.length) {
130
+ const outputText = output
131
+ .map(({ chunk, type }) => {
132
+ const text = chunk.toString("utf8");
133
+ if (type === "stderr")
134
+ return exports.colors.red(stripAnsiEscapes(text));
135
+ return text;
136
+ })
137
+ .join("");
138
+ resultLines.push("");
139
+ resultLines.push(exports.colors.gray(separator("--- Test output")) +
140
+ "\n\n" +
141
+ outputText +
142
+ "\n" +
143
+ separator());
144
+ }
145
+ for (const error of errors) {
146
+ annotations.push({
147
+ location: error.location,
148
+ title,
149
+ message: [header, ...retryLines, error.message].join("\n"),
150
+ });
151
+ }
152
+ lines.push(...resultLines);
153
+ }
154
+ lines.push("");
155
+ return {
156
+ message: lines.join("\n"),
157
+ annotations,
158
+ };
159
+ }
160
+ exports.formatFailure = formatFailure;
161
+ function quotePathIfNeeded(path) {
162
+ if (/\s/.test(path))
163
+ return `"${path}"`;
164
+ return path;
165
+ }
166
+ function formatResultFailure(test, result, initialIndent, highlightCode) {
167
+ const errorDetails = [];
168
+ if (result.status === "passed" && test.expectedStatus === "failed") {
169
+ errorDetails.push({
170
+ message: indent(exports.colors.red(`Expected to fail, but passed.`), initialIndent),
171
+ });
172
+ }
173
+ if (result.status === "interrupted") {
174
+ errorDetails.push({
175
+ message: indent(exports.colors.red(`Test was interrupted.`), initialIndent),
176
+ });
177
+ }
178
+ for (const error of result.errors) {
179
+ const formattedError = formatError(error, highlightCode);
180
+ errorDetails.push({
181
+ message: indent(formattedError.message, initialIndent),
182
+ location: formattedError.location,
183
+ });
184
+ }
185
+ return errorDetails;
186
+ }
187
+ exports.formatResultFailure = formatResultFailure;
188
+ function relativeFilePath(config, file) {
189
+ return path_1.default.relative(config.rootDir, file) || path_1.default.basename(file);
190
+ }
191
+ exports.relativeFilePath = relativeFilePath;
192
+ function relativeTestPath(config, test) {
193
+ return relativeFilePath(config, test.location.file);
194
+ }
195
+ function stepSuffix(step) {
196
+ const stepTitles = step ? step.titlePath() : [];
197
+ return stepTitles
198
+ .map((t) => t.split("\n")[0])
199
+ .map((t) => " › " + t)
200
+ .join("");
201
+ }
202
+ exports.stepSuffix = stepSuffix;
203
+ function formatTestTitle(config, test, step, omitLocation = false) {
204
+ // root, project, file, ...describes, test
205
+ const [, projectName, , ...titles] = test.titlePath();
206
+ let location;
207
+ if (omitLocation)
208
+ location = `${relativeTestPath(config, test)}`;
209
+ else
210
+ location = `${relativeTestPath(config, test)}:${step?.location?.line ?? test.location.line}:${step?.location?.column ?? test.location.column}`;
211
+ const projectTitle = projectName ? `[${projectName}] › ` : "";
212
+ return `${projectTitle}${location} › ${titles.join(" › ")}${stepSuffix(step)}`;
213
+ }
214
+ exports.formatTestTitle = formatTestTitle;
215
+ function formatTestHeader(config, test, options = {}) {
216
+ const title = formatTestTitle(config, test);
217
+ const header = `${options.indent || ""}${options.index ? options.index + ") " : ""}${title}`;
218
+ let fullHeader = header;
219
+ // Render the path to the deepest failing test.step.
220
+ if (options.mode === "error") {
221
+ const stepPaths = new Set();
222
+ for (const result of test.results.filter((r) => !!r.errors.length)) {
223
+ const stepPath = [];
224
+ const visit = (steps) => {
225
+ const errors = steps.filter((s) => s.error);
226
+ if (errors.length > 1)
227
+ return;
228
+ if (errors.length === 1 && errors[0]?.category === "test.step") {
229
+ stepPath.push(errors[0].title);
230
+ visit(errors[0].steps);
231
+ }
232
+ };
233
+ visit(result.steps);
234
+ stepPaths.add(["", ...stepPath].join(" › "));
235
+ }
236
+ fullHeader =
237
+ header + (stepPaths.size === 1 ? stepPaths.values().next().value : "");
238
+ }
239
+ return separator(fullHeader);
240
+ }
241
+ function formatError(error, highlightCode) {
242
+ const message = error.message || error.value || "";
243
+ const stack = error.stack;
244
+ if (!stack && !error.location)
245
+ return { message };
246
+ const tokens = [];
247
+ // Now that we filter out internals from our stack traces, we can safely render
248
+ // the helper / original exception locations.
249
+ const parsedStack = stack ? prepareErrorStack(stack) : undefined;
250
+ tokens.push(parsedStack?.message || message);
251
+ if (error.snippet) {
252
+ let snippet = error.snippet;
253
+ if (!highlightCode)
254
+ snippet = stripAnsiEscapes(snippet);
255
+ tokens.push("");
256
+ tokens.push(snippet);
257
+ }
258
+ if (parsedStack && parsedStack.stackLines.length) {
259
+ tokens.push("");
260
+ tokens.push(exports.colors.dim(parsedStack.stackLines.join("\n")));
261
+ }
262
+ let location = error.location;
263
+ if (parsedStack && !location)
264
+ location = parsedStack.location;
265
+ return {
266
+ location,
267
+ message: tokens.join("\n"),
268
+ };
269
+ }
270
+ exports.formatError = formatError;
271
+ function separator(text = "") {
272
+ if (text)
273
+ text += " ";
274
+ const columns = Math.min(100, exports.ttyWidth || 100);
275
+ return text + exports.colors.dim("─".repeat(Math.max(0, columns - text.length)));
276
+ }
277
+ exports.separator = separator;
278
+ function indent(lines, tab) {
279
+ return lines.replace(/^(?=.+$)/gm, tab);
280
+ }
281
+ function prepareErrorStack(stack) {
282
+ const lines = stack.split("\n");
283
+ let firstStackLine = lines.findIndex((line) => line.startsWith(" at "));
284
+ if (firstStackLine === -1)
285
+ firstStackLine = lines.length;
286
+ const message = lines.slice(0, firstStackLine).join("\n");
287
+ const stackLines = lines.slice(firstStackLine);
288
+ let location;
289
+ for (const line of stackLines) {
290
+ const frame = (0, utilsBundle_1.parseStackTraceLine)(line);
291
+ if (!frame || !frame.file)
292
+ continue;
293
+ if (belongsToNodeModules(frame.file))
294
+ continue;
295
+ location = {
296
+ file: frame.file,
297
+ column: frame.column || 0,
298
+ line: frame.line || 0,
299
+ };
300
+ break;
301
+ }
302
+ return { message, stackLines, location };
303
+ }
304
+ exports.prepareErrorStack = prepareErrorStack;
305
+ const ansiRegex = new RegExp(
306
+ // eslint-disable-next-line no-control-regex
307
+ "([\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~])))", "g");
308
+ function stripAnsiEscapes(str) {
309
+ return str.replace(ansiRegex, "");
310
+ }
311
+ exports.stripAnsiEscapes = stripAnsiEscapes;
312
+ function belongsToNodeModules(file) {
313
+ return file.includes(`${path_1.default.sep}node_modules${path_1.default.sep}`);
314
+ }
315
+ function resolveFromEnv(name) {
316
+ const value = process.env[name];
317
+ if (value)
318
+ return path_1.default.resolve(process.cwd(), value);
319
+ return undefined;
320
+ }
321
+ // In addition to `outputFile` the function returns `outputDir` which should
322
+ // be cleaned up if present by some reporters contract.
323
+ function resolveOutputFile(reporterName, options) {
324
+ const name = reporterName.toUpperCase();
325
+ let outputFile;
326
+ if (options.outputFile)
327
+ outputFile = path_1.default.resolve(options.configDir, options.outputFile);
328
+ if (!outputFile)
329
+ outputFile = resolveFromEnv(`PLAYWRIGHT_${name}_OUTPUT_FILE`);
330
+ // Return early to avoid deleting outputDir.
331
+ if (outputFile)
332
+ return { outputFile };
333
+ let outputDir;
334
+ if (options.outputDir)
335
+ outputDir = path_1.default.resolve(options.configDir, options.outputDir);
336
+ if (!outputDir)
337
+ outputDir = resolveFromEnv(`PLAYWRIGHT_${name}_OUTPUT_DIR`);
338
+ if (!outputDir && options.default)
339
+ outputDir = (0, util_1.resolveReporterOutputPath)(options.default.outputDir, options.configDir, undefined);
340
+ if (!outputFile) {
341
+ const reportName = options.fileName ??
342
+ process.env[`PLAYWRIGHT_${name}_OUTPUT_NAME`] ??
343
+ options.default?.fileName;
344
+ if (!reportName)
345
+ return undefined;
346
+ outputFile = path_1.default.resolve(outputDir ?? process.cwd(), reportName);
347
+ }
348
+ return { outputFile, outputDir };
349
+ }
350
+ exports.resolveOutputFile = resolveOutputFile;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import type { FullConfig, FullResult, Suite, TestCase as TestCasePublic, TestError, TestResult as TestResultPublic } from "@playwright/test/reporter";
17
+ import { HttpServer } from "playwright-core/lib/utils";
18
+ import type { ReporterV2 } from "./reporterV2";
19
+ declare const htmlReportOptions: string[];
20
+ type HtmlReportOpenOption = (typeof htmlReportOptions)[number];
21
+ type HtmlReporterOptions = {
22
+ configDir: string;
23
+ outputFolder?: string;
24
+ open?: HtmlReportOpenOption;
25
+ host?: string;
26
+ port?: number;
27
+ attachmentsBaseURL?: string;
28
+ _mode?: "test" | "list";
29
+ _isTestServer?: boolean;
30
+ };
31
+ declare class HtmlReporter implements ReporterV2 {
32
+ private config;
33
+ private suite;
34
+ private _options;
35
+ private _outputFolder;
36
+ private _attachmentsBaseURL;
37
+ private _open;
38
+ private _port;
39
+ private _host;
40
+ private _buildResult;
41
+ private _topLevelErrors;
42
+ constructor(options: HtmlReporterOptions);
43
+ printsToStdio(): boolean;
44
+ onStdOut(): void;
45
+ onStdErr(): void;
46
+ onStepBegin(): void;
47
+ onStepEnd(): void;
48
+ version(): "v2";
49
+ onTestBegin(): void;
50
+ onTestEnd(test: TestCasePublic, result: TestResultPublic): void;
51
+ onConfigure(config: FullConfig): void;
52
+ onBegin(suite: Suite): void;
53
+ _resolveOptions(): {
54
+ outputFolder: string;
55
+ open: HtmlReportOpenOption;
56
+ attachmentsBaseURL: string;
57
+ host: string | undefined;
58
+ port: number | undefined;
59
+ };
60
+ _isSubdirectory(parentDir: string, dir: string): boolean;
61
+ onError(error: TestError): void;
62
+ onEnd(result: FullResult): Promise<void>;
63
+ onExit(): Promise<void>;
64
+ }
65
+ export declare function showHTMLReport(reportFolder: string | undefined, host?: string, port?: number, testId?: string): Promise<void>;
66
+ export declare function startHtmlReportServer(folder: string): HttpServer;
67
+ export default HtmlReporter;
68
+ //# sourceMappingURL=custom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/reporter/custom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EAEV,KAAK,EACL,QAAQ,IAAI,cAAc,EAC1B,SAAS,EACT,UAAU,IAAI,gBAAgB,EAE/B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAML,UAAU,EAMX,MAAM,2BAA2B,CAAC;AAgBnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAwC/C,QAAA,MAAM,iBAAiB,UAAoC,CAAC;AAC5D,KAAK,oBAAoB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAM/D,KAAK,mBAAmB,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,cAAM,YAAa,YAAW,UAAU;IACtC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,mBAAmB,CAAU;IACrC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,YAAY,CAEN;IACd,OAAO,CAAC,eAAe,CAAmB;gBAE9B,OAAO,EAAE,mBAAmB;IAIxC,aAAa;IAIb,QAAQ;IAER,QAAQ;IAER,WAAW;IAEX,SAAS;IAET,OAAO,IAAI,IAAI;IAIf,WAAW;IAEX,SAAS,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB;IAiCxD,WAAW,CAAC,MAAM,EAAE,UAAU;IAI9B,OAAO,CAAC,KAAK,EAAE,KAAK;IAYpB,eAAe,IAAI;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,IAAI,EAAE,oBAAoB,CAAC;QAC3B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QACzB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B;IAkCD,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IASxD,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAIzB,KAAK,CAAC,MAAM,EAAE,UAAU;IA0ExB,MAAM;CA8Bb;AAkCD,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,GAAE,MAAoB,EAC1B,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,iBAqBhB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAsBhE;AAqiBD,eAAe,YAAY,CAAC"}