playwright-reborn 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +84 -0
- package/dist/fixture.d.ts +4 -0
- package/dist/fixture.js +53 -0
- package/dist/fixture.js.map +1 -0
- package/dist/format.d.ts +16 -0
- package/dist/format.js +113 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/model.d.ts +102 -0
- package/dist/model.js +3 -0
- package/dist/model.js.map +1 -0
- package/dist/open.d.ts +1 -0
- package/dist/open.js +19 -0
- package/dist/open.js.map +1 -0
- package/dist/options.d.ts +26 -0
- package/dist/options.js +54 -0
- package/dist/options.js.map +1 -0
- package/dist/paths.d.ts +3 -0
- package/dist/paths.js +71 -0
- package/dist/paths.js.map +1 -0
- package/dist/render.d.ts +3 -0
- package/dist/render.js +112 -0
- package/dist/render.js.map +1 -0
- package/dist/serialize.d.ts +87 -0
- package/dist/serialize.js +230 -0
- package/dist/serialize.js.map +1 -0
- package/dist/status.d.ts +7 -0
- package/dist/status.js +69 -0
- package/dist/status.js.map +1 -0
- package/dist/ui/fonts/Geist-OFL.txt +93 -0
- package/dist/ui/fonts/JetBrainsMono-OFL.txt +93 -0
- package/dist/ui/fonts/geist-latin-400-normal.woff2 +0 -0
- package/dist/ui/fonts/geist-latin-500-normal.woff2 +0 -0
- package/dist/ui/fonts/geist-latin-600-normal.woff2 +0 -0
- package/dist/ui/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/dist/ui/report.css +1147 -0
- package/dist/ui/report.js +1349 -0
- package/package.json +60 -0
package/dist/paths.d.ts
ADDED
package/dist/paths.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.relativePosix = relativePosix;
|
|
7
|
+
exports.resolveOutputFolder = resolveOutputFolder;
|
|
8
|
+
exports.prepareOutput = prepareOutput;
|
|
9
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
function relativePosix(rootDir, file) {
|
|
12
|
+
const relative = node_path_1.default.relative(rootDir, file);
|
|
13
|
+
if (!relative || relative.startsWith('..') || node_path_1.default.isAbsolute(relative)) {
|
|
14
|
+
return file.split(node_path_1.default.sep).join('/');
|
|
15
|
+
}
|
|
16
|
+
return relative.split(node_path_1.default.sep).join('/');
|
|
17
|
+
}
|
|
18
|
+
function resolveOutputFolder(rootDir, outputFolder) {
|
|
19
|
+
if (!outputFolder.trim())
|
|
20
|
+
throw new Error('Reborn outputFolder must be a non-empty path.');
|
|
21
|
+
const root = node_path_1.default.resolve(rootDir);
|
|
22
|
+
const resolved = node_path_1.default.resolve(root, outputFolder);
|
|
23
|
+
if (resolved === node_path_1.default.parse(resolved).root) {
|
|
24
|
+
throw new Error('Reborn output folder must be a dedicated directory, not a drive root.');
|
|
25
|
+
}
|
|
26
|
+
if (node_path_1.default.isAbsolute(outputFolder)) {
|
|
27
|
+
if (resolved === root) {
|
|
28
|
+
throw new Error('Reborn output folder must not be the project root.');
|
|
29
|
+
}
|
|
30
|
+
return resolved;
|
|
31
|
+
}
|
|
32
|
+
const relative = node_path_1.default.relative(root, resolved);
|
|
33
|
+
if (!relative || relative === '..' || relative.startsWith(`..${node_path_1.default.sep}`) || node_path_1.default.isAbsolute(relative)) {
|
|
34
|
+
throw new Error('Reborn output folder must be a subdirectory of the project.');
|
|
35
|
+
}
|
|
36
|
+
return resolved;
|
|
37
|
+
}
|
|
38
|
+
async function isRebornReport(dir) {
|
|
39
|
+
try {
|
|
40
|
+
const html = await promises_1.default.readFile(node_path_1.default.join(dir, 'index.html'), 'utf8');
|
|
41
|
+
return html.includes('id="reborn-data"');
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function prepareOutput(dir) {
|
|
48
|
+
let stat;
|
|
49
|
+
try {
|
|
50
|
+
stat = await promises_1.default.stat(dir);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const code = typeof error === 'object' && error && 'code' in error ? error.code : undefined;
|
|
54
|
+
if (code !== 'ENOENT')
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
if (stat && !stat.isDirectory()) {
|
|
58
|
+
throw new Error(`Reborn output folder ${dir} exists and is not a directory.`);
|
|
59
|
+
}
|
|
60
|
+
if (stat) {
|
|
61
|
+
const base = node_path_1.default.basename(dir);
|
|
62
|
+
const named = base === 'reborn-report' || base.startsWith('reborn-report-');
|
|
63
|
+
const ours = await isRebornReport(dir);
|
|
64
|
+
if (!named && !ours) {
|
|
65
|
+
throw new Error(`Refusing to replace ${dir} because it is not a Reborn report folder.`);
|
|
66
|
+
}
|
|
67
|
+
await promises_1.default.rm(dir, { recursive: true, force: true });
|
|
68
|
+
}
|
|
69
|
+
await promises_1.default.mkdir(dir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"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"}
|
package/dist/render.d.ts
ADDED
package/dist/render.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.renderHtml = renderHtml;
|
|
7
|
+
exports.writeReport = writeReport;
|
|
8
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const format_1 = require("./format");
|
|
11
|
+
const paths_1 = require("./paths");
|
|
12
|
+
function renderHtml(json) {
|
|
13
|
+
return `<!DOCTYPE html>
|
|
14
|
+
<html lang="en">
|
|
15
|
+
<head>
|
|
16
|
+
<meta charset="utf-8">
|
|
17
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
18
|
+
<meta name="robots" content="noindex">
|
|
19
|
+
<title>Report</title>
|
|
20
|
+
<link rel="stylesheet" href="assets/report.css">
|
|
21
|
+
</head>
|
|
22
|
+
<body style="margin:0;background:#080808;color:#f0f0f0">
|
|
23
|
+
<div class="light"></div>
|
|
24
|
+
<a class="skip" href="#tests">Skip to tests</a>
|
|
25
|
+
<main class="page" id="app"></main>
|
|
26
|
+
<script id="reborn-data" type="application/json">${json}</script>
|
|
27
|
+
<script src="assets/report.js"></script>
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
32
|
+
function removeAttachment(report, target) {
|
|
33
|
+
for (const test of report.tests) {
|
|
34
|
+
for (const attempt of test.attempts) {
|
|
35
|
+
attempt.attachments = attempt.attachments.filter((attachment) => attachment.path !== target);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
40
|
+
async function tooLarge(file) {
|
|
41
|
+
if (file.body && file.body.length > MAX_ATTACHMENT_BYTES)
|
|
42
|
+
return true;
|
|
43
|
+
if (!file.sourcePath)
|
|
44
|
+
return false;
|
|
45
|
+
try {
|
|
46
|
+
const stat = await promises_1.default.stat(file.sourcePath);
|
|
47
|
+
return stat.size > MAX_ATTACHMENT_BYTES;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function markOmitted(report, target) {
|
|
54
|
+
for (const test of report.tests) {
|
|
55
|
+
for (const attempt of test.attempts) {
|
|
56
|
+
for (const attachment of attempt.attachments) {
|
|
57
|
+
if (attachment.path !== target)
|
|
58
|
+
continue;
|
|
59
|
+
attachment.omitted = true;
|
|
60
|
+
attachment.path = '';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function writePending(outputDir, file) {
|
|
66
|
+
const destination = node_path_1.default.join(outputDir, ...file.target.split('/'));
|
|
67
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(destination), { recursive: true });
|
|
68
|
+
if (file.sourcePath) {
|
|
69
|
+
await promises_1.default.copyFile(file.sourcePath, destination);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (file.body) {
|
|
73
|
+
await promises_1.default.writeFile(destination, file.body);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
throw new Error('Attachment had no file and no body.');
|
|
77
|
+
}
|
|
78
|
+
async function writeReport(outputDir, report, files, uiDir) {
|
|
79
|
+
const stylesheet = node_path_1.default.join(uiDir, 'report.css');
|
|
80
|
+
const script = node_path_1.default.join(uiDir, 'report.js');
|
|
81
|
+
try {
|
|
82
|
+
await promises_1.default.access(stylesheet);
|
|
83
|
+
await promises_1.default.access(script);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
throw new Error('Reborn UI assets are missing. Build the package before running tests.');
|
|
87
|
+
}
|
|
88
|
+
await (0, paths_1.prepareOutput)(outputDir);
|
|
89
|
+
const assets = node_path_1.default.join(outputDir, 'assets');
|
|
90
|
+
await promises_1.default.mkdir(node_path_1.default.join(assets, 'attachments'), { recursive: true });
|
|
91
|
+
await promises_1.default.copyFile(stylesheet, node_path_1.default.join(assets, 'report.css'));
|
|
92
|
+
await promises_1.default.copyFile(script, node_path_1.default.join(assets, 'report.js'));
|
|
93
|
+
await promises_1.default.cp(node_path_1.default.join(uiDir, 'fonts'), node_path_1.default.join(assets, 'fonts'), { recursive: true });
|
|
94
|
+
for (const file of files) {
|
|
95
|
+
if (await tooLarge(file)) {
|
|
96
|
+
markOmitted(report, file.target);
|
|
97
|
+
report.warnings.push(`Did not copy ${file.name} because it is larger than 25MB.`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
await writePending(outputDir, file);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
report.warnings.push(`Could not save attachment ${file.name}.`);
|
|
105
|
+
removeAttachment(report, file.target);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const indexPath = node_path_1.default.join(outputDir, 'index.html');
|
|
109
|
+
await promises_1.default.writeFile(indexPath, renderHtml((0, format_1.embedJson)(report)), 'utf8');
|
|
110
|
+
return indexPath;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { TestError } from '@playwright/test/reporter';
|
|
2
|
+
import type { Accent, Attempt, PendingFile, Report, ReportError, RunStatus, ShotMode, StepDetail } from './model';
|
|
3
|
+
export type SourceSuite = {
|
|
4
|
+
title: string;
|
|
5
|
+
type: 'root' | 'project' | 'file' | 'describe';
|
|
6
|
+
parent?: SourceSuite;
|
|
7
|
+
location?: {
|
|
8
|
+
file: string;
|
|
9
|
+
line: number;
|
|
10
|
+
column: number;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export type SourceStep = {
|
|
14
|
+
title: string;
|
|
15
|
+
subtitle?: string;
|
|
16
|
+
category: string;
|
|
17
|
+
duration: number;
|
|
18
|
+
error?: TestError;
|
|
19
|
+
location?: {
|
|
20
|
+
file: string;
|
|
21
|
+
line: number;
|
|
22
|
+
column: number;
|
|
23
|
+
};
|
|
24
|
+
attachments?: SourceAttachment[];
|
|
25
|
+
steps?: SourceStep[];
|
|
26
|
+
};
|
|
27
|
+
export type SourceAttachment = {
|
|
28
|
+
name: string;
|
|
29
|
+
contentType: string;
|
|
30
|
+
path?: string;
|
|
31
|
+
body?: Buffer;
|
|
32
|
+
};
|
|
33
|
+
export type SourceResult = {
|
|
34
|
+
retry: number;
|
|
35
|
+
status: Attempt['status'];
|
|
36
|
+
duration: number;
|
|
37
|
+
startTime: Date;
|
|
38
|
+
workerIndex: number;
|
|
39
|
+
error?: TestError;
|
|
40
|
+
errors?: TestError[];
|
|
41
|
+
stdout?: Array<string | Buffer>;
|
|
42
|
+
stderr?: Array<string | Buffer>;
|
|
43
|
+
steps?: SourceStep[];
|
|
44
|
+
attachments?: SourceAttachment[];
|
|
45
|
+
};
|
|
46
|
+
export type SourceTest = {
|
|
47
|
+
id: string;
|
|
48
|
+
title: string;
|
|
49
|
+
location: {
|
|
50
|
+
file: string;
|
|
51
|
+
line: number;
|
|
52
|
+
column: number;
|
|
53
|
+
};
|
|
54
|
+
parent: SourceSuite;
|
|
55
|
+
annotations: {
|
|
56
|
+
type: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
}[];
|
|
59
|
+
tags: string[];
|
|
60
|
+
outcome(): 'skipped' | 'expected' | 'unexpected' | 'flaky';
|
|
61
|
+
results: SourceResult[];
|
|
62
|
+
};
|
|
63
|
+
export type BuildInput = {
|
|
64
|
+
tests: SourceTest[];
|
|
65
|
+
rootDir: string;
|
|
66
|
+
playwrightVersion: string;
|
|
67
|
+
projectName: string;
|
|
68
|
+
projects: string[];
|
|
69
|
+
workers: number;
|
|
70
|
+
shard: string | null;
|
|
71
|
+
status: RunStatus;
|
|
72
|
+
startTime: Date;
|
|
73
|
+
duration: number;
|
|
74
|
+
generatedAt: string;
|
|
75
|
+
errors: ReportError[];
|
|
76
|
+
screenshots?: ShotMode;
|
|
77
|
+
stepDetail?: StepDetail;
|
|
78
|
+
company?: string;
|
|
79
|
+
accent?: Accent;
|
|
80
|
+
showLogs?: boolean;
|
|
81
|
+
showFiles?: boolean;
|
|
82
|
+
overview?: 'chart' | 'timeline';
|
|
83
|
+
};
|
|
84
|
+
export declare function buildReport(input: BuildInput): {
|
|
85
|
+
report: Report;
|
|
86
|
+
files: PendingFile[];
|
|
87
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildReport = buildReport;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const format_1 = require("./format");
|
|
9
|
+
const paths_1 = require("./paths");
|
|
10
|
+
const status_1 = require("./status");
|
|
11
|
+
function walkSuites(test) {
|
|
12
|
+
const chain = [];
|
|
13
|
+
let suite = test.parent;
|
|
14
|
+
while (suite) {
|
|
15
|
+
chain.unshift(suite);
|
|
16
|
+
suite = suite.parent;
|
|
17
|
+
}
|
|
18
|
+
return chain;
|
|
19
|
+
}
|
|
20
|
+
function projectOf(test) {
|
|
21
|
+
for (const suite of walkSuites(test)) {
|
|
22
|
+
if (suite.type === 'project')
|
|
23
|
+
return suite.title;
|
|
24
|
+
}
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
27
|
+
function groupOf(test) {
|
|
28
|
+
return walkSuites(test)
|
|
29
|
+
.filter((suite) => suite.type === 'describe' && suite.title)
|
|
30
|
+
.map((suite) => suite.title);
|
|
31
|
+
}
|
|
32
|
+
function stepLocation(rootDir, step) {
|
|
33
|
+
if (!step.location)
|
|
34
|
+
return undefined;
|
|
35
|
+
const file = (0, paths_1.relativePosix)(rootDir, step.location.file);
|
|
36
|
+
if (file.includes('node_modules'))
|
|
37
|
+
return undefined;
|
|
38
|
+
return `${file}:${step.location.line}`;
|
|
39
|
+
}
|
|
40
|
+
function errorMessage(error) {
|
|
41
|
+
const main = error.message || error.value || '';
|
|
42
|
+
const cause = error.cause ? error.cause.message || error.cause.value || '' : '';
|
|
43
|
+
const combined = cause && !main.includes(cause) ? `${main}\n${cause}` : main;
|
|
44
|
+
const text = (0, format_1.capText)((0, format_1.stripAnsi)(combined), 20_000).trim();
|
|
45
|
+
return text || 'The test failed.';
|
|
46
|
+
}
|
|
47
|
+
function simplifyError(error, rootDir) {
|
|
48
|
+
const simplified = { message: errorMessage(error) };
|
|
49
|
+
if (error.stack)
|
|
50
|
+
simplified.stack = (0, format_1.capText)((0, format_1.stripAnsi)(error.stack), 20_000);
|
|
51
|
+
if (error.snippet)
|
|
52
|
+
simplified.snippet = (0, format_1.capText)((0, format_1.stripAnsi)(error.snippet), 20_000);
|
|
53
|
+
if (error.location) {
|
|
54
|
+
simplified.location = `${(0, paths_1.relativePosix)(rootDir, error.location.file)}:${error.location.line}`;
|
|
55
|
+
}
|
|
56
|
+
return simplified;
|
|
57
|
+
}
|
|
58
|
+
function mapSteps(steps, rootDir, depth, detail) {
|
|
59
|
+
if (!steps || depth > 12)
|
|
60
|
+
return [];
|
|
61
|
+
const mapped = [];
|
|
62
|
+
for (const step of steps) {
|
|
63
|
+
const kids = mapSteps(step.steps, rootDir, depth + 1, detail);
|
|
64
|
+
const hide = detail === 'user' && (step.category === 'pw:api' || step.category === 'fixture');
|
|
65
|
+
if (hide) {
|
|
66
|
+
mapped.push(...kids);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const next = {
|
|
70
|
+
title: step.title,
|
|
71
|
+
category: step.category,
|
|
72
|
+
duration: step.duration,
|
|
73
|
+
steps: kids,
|
|
74
|
+
};
|
|
75
|
+
if (step.subtitle && step.subtitle !== step.title)
|
|
76
|
+
next.subtitle = step.subtitle;
|
|
77
|
+
const location = stepLocation(rootDir, step);
|
|
78
|
+
if (location)
|
|
79
|
+
next.location = location;
|
|
80
|
+
if (step.error) {
|
|
81
|
+
const message = errorMessage(step.error);
|
|
82
|
+
if (message)
|
|
83
|
+
next.error = message;
|
|
84
|
+
}
|
|
85
|
+
mapped.push(next);
|
|
86
|
+
}
|
|
87
|
+
return mapped;
|
|
88
|
+
}
|
|
89
|
+
function collectAttachments(result) {
|
|
90
|
+
const found = [];
|
|
91
|
+
const seen = new Set();
|
|
92
|
+
const visit = (attachments) => {
|
|
93
|
+
for (const attachment of attachments || []) {
|
|
94
|
+
const key = attachment.path
|
|
95
|
+
? `path:${attachment.path}`
|
|
96
|
+
: `body:${attachment.name}:${attachment.contentType}:${attachment.body?.length || 0}:${found.length}`;
|
|
97
|
+
if (seen.has(key))
|
|
98
|
+
continue;
|
|
99
|
+
seen.add(key);
|
|
100
|
+
found.push(attachment);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
visit(result.attachments);
|
|
104
|
+
const visitSteps = (steps) => {
|
|
105
|
+
for (const step of steps || []) {
|
|
106
|
+
visit(step.attachments);
|
|
107
|
+
visitSteps(step.steps);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
visitSteps(result.steps);
|
|
111
|
+
return found;
|
|
112
|
+
}
|
|
113
|
+
function buildReport(input) {
|
|
114
|
+
const files = [];
|
|
115
|
+
let fileIndex = 0;
|
|
116
|
+
const seenIds = new Map();
|
|
117
|
+
const sorted = [...input.tests].sort((a, b) => {
|
|
118
|
+
const aStart = a.results[0]?.startTime ? a.results[0].startTime.getTime() : Number.POSITIVE_INFINITY;
|
|
119
|
+
const bStart = b.results[0]?.startTime ? b.results[0].startTime.getTime() : Number.POSITIVE_INFINITY;
|
|
120
|
+
if (aStart !== bStart)
|
|
121
|
+
return aStart - bStart;
|
|
122
|
+
return a.title.localeCompare(b.title);
|
|
123
|
+
});
|
|
124
|
+
const tests = sorted.map((test, order) => {
|
|
125
|
+
const count = seenIds.get(test.id) || 0;
|
|
126
|
+
seenIds.set(test.id, count + 1);
|
|
127
|
+
const id = count === 0 ? test.id : `${test.id}-${count}`;
|
|
128
|
+
const results = test.results || [];
|
|
129
|
+
const last = results[results.length - 1];
|
|
130
|
+
const rawStatus = last?.status || 'skipped';
|
|
131
|
+
let pwOutcome = 'skipped';
|
|
132
|
+
try {
|
|
133
|
+
pwOutcome = test.outcome();
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
pwOutcome = 'skipped';
|
|
137
|
+
}
|
|
138
|
+
const attempts = results.map((result) => {
|
|
139
|
+
const errors = (result.errors && result.errors.length > 0 ? result.errors : result.error ? [result.error] : [])
|
|
140
|
+
.map((error) => simplifyError(error, input.rootDir));
|
|
141
|
+
const attachments = collectAttachments(result).map((attachment) => {
|
|
142
|
+
const parsed = (0, format_1.parseShotName)(attachment.name || 'file');
|
|
143
|
+
const ext = (0, format_1.extensionFor)(attachment.contentType, attachment.path);
|
|
144
|
+
const targetName = (0, format_1.safeFileName)(parsed.name, fileIndex, ext);
|
|
145
|
+
fileIndex += 1;
|
|
146
|
+
const target = node_path_1.default.posix.join('assets', 'attachments', targetName);
|
|
147
|
+
files.push({
|
|
148
|
+
name: parsed.name,
|
|
149
|
+
target,
|
|
150
|
+
sourcePath: attachment.path,
|
|
151
|
+
body: attachment.body,
|
|
152
|
+
});
|
|
153
|
+
const reportAttachment = {
|
|
154
|
+
name: parsed.name,
|
|
155
|
+
contentType: attachment.contentType,
|
|
156
|
+
path: target,
|
|
157
|
+
kind: (0, format_1.attachmentKind)(parsed.name, attachment.contentType),
|
|
158
|
+
};
|
|
159
|
+
if (parsed.role)
|
|
160
|
+
reportAttachment.role = parsed.role;
|
|
161
|
+
if (parsed.stepTitle)
|
|
162
|
+
reportAttachment.stepTitle = parsed.stepTitle;
|
|
163
|
+
return reportAttachment;
|
|
164
|
+
});
|
|
165
|
+
const stdout = (0, format_1.joinChunks)(result.stdout);
|
|
166
|
+
const stderr = (0, format_1.joinChunks)(result.stderr);
|
|
167
|
+
const attempt = {
|
|
168
|
+
retry: result.retry,
|
|
169
|
+
status: result.status,
|
|
170
|
+
duration: result.duration,
|
|
171
|
+
startTime: result.startTime.toISOString(),
|
|
172
|
+
workerIndex: result.workerIndex,
|
|
173
|
+
errors,
|
|
174
|
+
steps: mapSteps(result.steps, input.rootDir, 0, input.stepDetail || 'user'),
|
|
175
|
+
attachments,
|
|
176
|
+
};
|
|
177
|
+
if (stdout)
|
|
178
|
+
attempt.stdout = stdout;
|
|
179
|
+
if (stderr)
|
|
180
|
+
attempt.stderr = stderr;
|
|
181
|
+
return attempt;
|
|
182
|
+
});
|
|
183
|
+
return {
|
|
184
|
+
id,
|
|
185
|
+
title: test.title,
|
|
186
|
+
file: (0, paths_1.relativePosix)(input.rootDir, test.location.file),
|
|
187
|
+
line: test.location.line,
|
|
188
|
+
project: projectOf(test),
|
|
189
|
+
group: groupOf(test),
|
|
190
|
+
tags: test.tags.slice(0, 20),
|
|
191
|
+
annotations: test.annotations.slice(0, 40).map((annotation) => ({
|
|
192
|
+
type: annotation.type,
|
|
193
|
+
description: annotation.description ? (0, format_1.capText)(annotation.description, 500) : undefined,
|
|
194
|
+
})),
|
|
195
|
+
expectedFailure: (0, status_1.isExpectedFailure)(pwOutcome, rawStatus),
|
|
196
|
+
status: (0, status_1.displayStatus)(pwOutcome, rawStatus),
|
|
197
|
+
duration: results.reduce((sum, result) => sum + (result.duration || 0), 0),
|
|
198
|
+
order,
|
|
199
|
+
attempts,
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
const counts = (0, status_1.countTests)(tests.map((test) => test.status));
|
|
203
|
+
const report = {
|
|
204
|
+
version: 2,
|
|
205
|
+
screenshots: input.screenshots || 'failure',
|
|
206
|
+
steps: input.stepDetail || 'user',
|
|
207
|
+
generatedAt: input.generatedAt,
|
|
208
|
+
playwrightVersion: input.playwrightVersion,
|
|
209
|
+
status: input.status,
|
|
210
|
+
word: (0, status_1.outcomeWord)(input.status),
|
|
211
|
+
company: (input.company || 'Sandata').trim() || 'Sandata',
|
|
212
|
+
accent: input.accent || 'green',
|
|
213
|
+
showLogs: input.showLogs !== false,
|
|
214
|
+
showFiles: input.showFiles !== false,
|
|
215
|
+
overview: input.overview === 'timeline' ? 'timeline' : 'chart',
|
|
216
|
+
summary: (0, status_1.summaryLine)(counts),
|
|
217
|
+
startTime: input.startTime.toISOString(),
|
|
218
|
+
duration: input.duration,
|
|
219
|
+
projectName: input.projectName,
|
|
220
|
+
projects: input.projects,
|
|
221
|
+
workers: input.workers,
|
|
222
|
+
shard: input.shard,
|
|
223
|
+
counts,
|
|
224
|
+
warnings: [],
|
|
225
|
+
errors: input.errors,
|
|
226
|
+
tests,
|
|
227
|
+
};
|
|
228
|
+
return { report, files };
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=serialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"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"}
|
package/dist/status.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Counts, DisplayStatus, RunStatus } from './model';
|
|
2
|
+
export declare function displayStatus(pwOutcome: string, status: string): DisplayStatus;
|
|
3
|
+
export declare function isExpectedFailure(pwOutcome: string, status: string): boolean;
|
|
4
|
+
export declare function emptyCounts(): Counts;
|
|
5
|
+
export declare function countTests(statuses: DisplayStatus[]): Counts;
|
|
6
|
+
export declare function outcomeWord(status: RunStatus): string;
|
|
7
|
+
export declare function summaryLine(counts: Counts): string;
|
package/dist/status.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.displayStatus = displayStatus;
|
|
4
|
+
exports.isExpectedFailure = isExpectedFailure;
|
|
5
|
+
exports.emptyCounts = emptyCounts;
|
|
6
|
+
exports.countTests = countTests;
|
|
7
|
+
exports.outcomeWord = outcomeWord;
|
|
8
|
+
exports.summaryLine = summaryLine;
|
|
9
|
+
function displayStatus(pwOutcome, status) {
|
|
10
|
+
if (pwOutcome === 'flaky')
|
|
11
|
+
return 'flaky';
|
|
12
|
+
if (pwOutcome === 'skipped' || status === 'skipped')
|
|
13
|
+
return 'skipped';
|
|
14
|
+
if (status === 'timedOut')
|
|
15
|
+
return 'timedOut';
|
|
16
|
+
if (status === 'interrupted')
|
|
17
|
+
return 'interrupted';
|
|
18
|
+
if (pwOutcome === 'unexpected')
|
|
19
|
+
return 'failed';
|
|
20
|
+
if (status === 'failed')
|
|
21
|
+
return 'passed';
|
|
22
|
+
return 'passed';
|
|
23
|
+
}
|
|
24
|
+
function isExpectedFailure(pwOutcome, status) {
|
|
25
|
+
return pwOutcome === 'expected' && status === 'failed';
|
|
26
|
+
}
|
|
27
|
+
function emptyCounts() {
|
|
28
|
+
return { total: 0, passed: 0, failed: 0, flaky: 0, skipped: 0, timedOut: 0, interrupted: 0 };
|
|
29
|
+
}
|
|
30
|
+
function countTests(statuses) {
|
|
31
|
+
const counts = emptyCounts();
|
|
32
|
+
counts.total = statuses.length;
|
|
33
|
+
for (const status of statuses)
|
|
34
|
+
counts[status] += 1;
|
|
35
|
+
return counts;
|
|
36
|
+
}
|
|
37
|
+
function outcomeWord(status) {
|
|
38
|
+
switch (status) {
|
|
39
|
+
case 'passed':
|
|
40
|
+
return 'Clear';
|
|
41
|
+
case 'failed':
|
|
42
|
+
return 'Broken';
|
|
43
|
+
case 'timedout':
|
|
44
|
+
return 'Timed out';
|
|
45
|
+
case 'interrupted':
|
|
46
|
+
return 'Stopped';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function summaryLine(counts) {
|
|
50
|
+
if (counts.total === 0)
|
|
51
|
+
return 'No tests ran.';
|
|
52
|
+
const problems = [];
|
|
53
|
+
if (counts.failed)
|
|
54
|
+
problems.push(`${counts.failed} failed`);
|
|
55
|
+
if (counts.timedOut)
|
|
56
|
+
problems.push(`${counts.timedOut} timed out`);
|
|
57
|
+
if (counts.interrupted)
|
|
58
|
+
problems.push(`${counts.interrupted} interrupted`);
|
|
59
|
+
if (counts.flaky)
|
|
60
|
+
problems.push(`${counts.flaky} flaky`);
|
|
61
|
+
if (problems.length === 0 && counts.skipped === 0) {
|
|
62
|
+
return counts.passed === 1 ? '1 passed.' : `${counts.passed} passed.`;
|
|
63
|
+
}
|
|
64
|
+
if (problems.length === 0) {
|
|
65
|
+
return `${counts.passed} passed, ${counts.skipped} skipped. ${counts.total} ran.`;
|
|
66
|
+
}
|
|
67
|
+
return `${problems.join(', ')}. ${counts.total} ran.`;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
|