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.
@@ -0,0 +1,3 @@
1
+ export declare function relativePosix(rootDir: string, file: string): string;
2
+ export declare function resolveOutputFolder(rootDir: string, outputFolder: string): string;
3
+ export declare function prepareOutput(dir: string): Promise<void>;
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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"}
@@ -0,0 +1,3 @@
1
+ import type { PendingFile, Report } from './model';
2
+ export declare function renderHtml(json: string): string;
3
+ export declare function writeReport(outputDir: string, report: Report, files: PendingFile[], uiDir: string): Promise<string>;
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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"}
@@ -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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"}