@testpulse.run/playwright-console-reporter 0.2.3
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/README.md +67 -0
- package/dist/index.cjs +242 -0
- package/dist/index.d.cts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +221 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://testpulse.run">
|
|
3
|
+
<img src="https://testpulse.run/images/logo-testpulse.svg" alt="TestPulse.run" height="48">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://testpulse.run">testpulse.run</a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
# @testpulse.run/playwright-console-reporter
|
|
12
|
+
|
|
13
|
+
Console reporter for Playwright built on the TestPulse reporter event pipeline.
|
|
14
|
+
|
|
15
|
+
Use this package when you want a compact terminal reporter that prints test progress, stdout/stderr, failures, retries, and the final run summary.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install -D @testpulse.run/playwright-console-reporter @playwright/test
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Playwright Configuration
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { defineConfig } from "@playwright/test";
|
|
27
|
+
|
|
28
|
+
export default defineConfig({
|
|
29
|
+
reporter: [["@testpulse.run/playwright-console-reporter"]]
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
You can combine it with other reporters:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
export default defineConfig({
|
|
37
|
+
reporter: [
|
|
38
|
+
["@testpulse.run/playwright-console-reporter"],
|
|
39
|
+
["html"]
|
|
40
|
+
]
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Options
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
export default defineConfig({
|
|
48
|
+
reporter: [
|
|
49
|
+
[
|
|
50
|
+
"@testpulse.run/playwright-console-reporter",
|
|
51
|
+
{
|
|
52
|
+
color: "auto",
|
|
53
|
+
verbose: false
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
]
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- `color`: `true`, `false`, or `"auto"`; defaults to automatic TTY detection.
|
|
61
|
+
- `verbose`: prints test start lines in addition to completion lines.
|
|
62
|
+
|
|
63
|
+
## Related Packages
|
|
64
|
+
|
|
65
|
+
- `@testpulse.run/reporter`: sends Playwright events to TestPulse.
|
|
66
|
+
- `@testpulse.run/playwright-jsonl-reporter`: writes Playwright events as JSONL.
|
|
67
|
+
- `@testpulse.run/playwright-core`: lower-level reporter event adapter.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ConsoleReporter: () => ConsoleReporter,
|
|
24
|
+
default: () => index_default
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
var import_playwright_core = require("@testpulse.run/playwright-core");
|
|
28
|
+
var import_playwright_events = require("@testpulse.run/playwright-events");
|
|
29
|
+
|
|
30
|
+
// src/format.ts
|
|
31
|
+
function createColorizer(enabled) {
|
|
32
|
+
const color = (code, value) => enabled ? `\x1B[${code}m${value}\x1B[0m` : value;
|
|
33
|
+
return {
|
|
34
|
+
green: (value) => color(32, value),
|
|
35
|
+
red: (value) => color(31, value),
|
|
36
|
+
yellow: (value) => color(33, value),
|
|
37
|
+
gray: (value) => color(90, value)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function formatTestTitle(test) {
|
|
41
|
+
const location = test.location ? `${test.location.file}:${test.location.line}:${test.location.column}` : "";
|
|
42
|
+
const path = test.titlePath.length > 0 ? test.titlePath : [test.title];
|
|
43
|
+
const title = path.filter(Boolean).join(" \u203A ");
|
|
44
|
+
return location ? `${location} \u203A ${title}` : title;
|
|
45
|
+
}
|
|
46
|
+
function formatDuration(durationMs) {
|
|
47
|
+
if (durationMs < 1e3) {
|
|
48
|
+
return `${Math.round(durationMs)}ms`;
|
|
49
|
+
}
|
|
50
|
+
return `${(durationMs / 1e3).toFixed(1)}s`;
|
|
51
|
+
}
|
|
52
|
+
function statusSymbol(status) {
|
|
53
|
+
switch (status) {
|
|
54
|
+
case "passed":
|
|
55
|
+
return "ok";
|
|
56
|
+
case "skipped":
|
|
57
|
+
return "-";
|
|
58
|
+
case "timedOut":
|
|
59
|
+
return "timeout";
|
|
60
|
+
case "interrupted":
|
|
61
|
+
return "interrupted";
|
|
62
|
+
case "failed":
|
|
63
|
+
default:
|
|
64
|
+
return "x";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function colorStatus(status, value, colors) {
|
|
68
|
+
switch (status) {
|
|
69
|
+
case "passed":
|
|
70
|
+
return colors.green(value);
|
|
71
|
+
case "skipped":
|
|
72
|
+
return colors.yellow(value);
|
|
73
|
+
case "failed":
|
|
74
|
+
case "timedOut":
|
|
75
|
+
case "interrupted":
|
|
76
|
+
return colors.red(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/index.ts
|
|
81
|
+
var ConsoleReporter = class {
|
|
82
|
+
core;
|
|
83
|
+
events;
|
|
84
|
+
output;
|
|
85
|
+
errorOutput;
|
|
86
|
+
colors;
|
|
87
|
+
verbose;
|
|
88
|
+
totalTests = 0;
|
|
89
|
+
nextTestOrdinal = 1;
|
|
90
|
+
testOrdinals = /* @__PURE__ */ new Map();
|
|
91
|
+
outcomes = {
|
|
92
|
+
passed: 0,
|
|
93
|
+
failed: 0,
|
|
94
|
+
flaky: 0,
|
|
95
|
+
skipped: 0,
|
|
96
|
+
interrupted: 0,
|
|
97
|
+
timedOut: 0
|
|
98
|
+
};
|
|
99
|
+
suite;
|
|
100
|
+
config;
|
|
101
|
+
constructor(options = {}) {
|
|
102
|
+
this.output = options.output ?? process.stdout;
|
|
103
|
+
this.errorOutput = options.errorOutput ?? process.stderr;
|
|
104
|
+
this.verbose = options.verbose ?? false;
|
|
105
|
+
const shouldColor = options.color === true || options.color !== false && Boolean(this.output.isTTY);
|
|
106
|
+
this.colors = createColorizer(shouldColor);
|
|
107
|
+
const consolePlugin = {
|
|
108
|
+
name: "@testpulse.run/playwright-console-reporter",
|
|
109
|
+
RunStarted: (event) => this.onRunStarted(event),
|
|
110
|
+
TestStarted: (event) => this.onTestStarted(event),
|
|
111
|
+
StdOutReceived: (event) => this.onStdOutReceived(event),
|
|
112
|
+
StdErrReceived: (event) => this.onStdErrReceived(event),
|
|
113
|
+
RunFinished: (event) => this.onRunFinished(event)
|
|
114
|
+
};
|
|
115
|
+
const derivedPlugin = {
|
|
116
|
+
name: "@testpulse.run/playwright-console-reporter",
|
|
117
|
+
TestAttemptFinished: (event) => this.onTestAttemptFinished(event),
|
|
118
|
+
TestOutcomeResolved: (event) => this.onTestOutcomeResolved(event)
|
|
119
|
+
};
|
|
120
|
+
this.events = new import_playwright_events.PlaywrightEvents({ plugins: [derivedPlugin] });
|
|
121
|
+
this.core = new import_playwright_core.TestPulseReporterCore({ plugins: [this.events.asCorePlugin(), consolePlugin] });
|
|
122
|
+
this.events.setErrorSink(this.core);
|
|
123
|
+
}
|
|
124
|
+
printsToStdio() {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
onBegin(config, suite) {
|
|
128
|
+
this.config = config;
|
|
129
|
+
this.suite = suite;
|
|
130
|
+
this.core.onBegin(config, suite);
|
|
131
|
+
}
|
|
132
|
+
onEnd(result) {
|
|
133
|
+
return this.core.onEnd(result);
|
|
134
|
+
}
|
|
135
|
+
onError(...args) {
|
|
136
|
+
this.core.onError(...args);
|
|
137
|
+
}
|
|
138
|
+
onTestBegin(...args) {
|
|
139
|
+
this.core.onTestBegin(...args);
|
|
140
|
+
}
|
|
141
|
+
onTestEnd(...args) {
|
|
142
|
+
this.core.onTestEnd(...args);
|
|
143
|
+
}
|
|
144
|
+
onStepBegin(...args) {
|
|
145
|
+
this.core.onStepBegin(...args);
|
|
146
|
+
}
|
|
147
|
+
onStepEnd(...args) {
|
|
148
|
+
this.core.onStepEnd(...args);
|
|
149
|
+
}
|
|
150
|
+
onStdOut(...args) {
|
|
151
|
+
this.core.onStdOut(...args);
|
|
152
|
+
}
|
|
153
|
+
onStdErr(...args) {
|
|
154
|
+
this.core.onStdErr(...args);
|
|
155
|
+
}
|
|
156
|
+
onRunStarted(event) {
|
|
157
|
+
this.totalTests = event.totalTests;
|
|
158
|
+
this.nextTestOrdinal = 1;
|
|
159
|
+
this.testOrdinals.clear();
|
|
160
|
+
this.outcomes = {
|
|
161
|
+
passed: 0,
|
|
162
|
+
failed: 0,
|
|
163
|
+
flaky: 0,
|
|
164
|
+
skipped: 0,
|
|
165
|
+
interrupted: 0,
|
|
166
|
+
timedOut: 0
|
|
167
|
+
};
|
|
168
|
+
const workers = this.config?.workers ?? 1;
|
|
169
|
+
this.writeLine(`Running ${event.totalTests} test${event.totalTests === 1 ? "" : "s"} using ${workers} worker${workers === 1 ? "" : "s"}`);
|
|
170
|
+
}
|
|
171
|
+
onTestStarted(event) {
|
|
172
|
+
if (!this.verbose) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this.writeLine(`[${this.getTestOrdinal(event.test.testId ?? event.titlePath.join(" \u203A "))}/${this.totalTests}] ${formatTestTitle(event.test)}`);
|
|
176
|
+
}
|
|
177
|
+
onTestAttemptFinished(event) {
|
|
178
|
+
const testOrdinal = this.getTestOrdinal(event.testId);
|
|
179
|
+
const marker = colorStatus(event.status, statusSymbol(event.status), this.colors);
|
|
180
|
+
const duration = this.colors.gray(formatDuration(event.attempt.durationMs));
|
|
181
|
+
const retry = event.retry > 0 ? this.colors.gray(` retry #${event.retry}`) : "";
|
|
182
|
+
this.writeLine(`${marker} ${testOrdinal} ${formatTestTitle(event.test)} (${duration})`);
|
|
183
|
+
if (retry) {
|
|
184
|
+
this.writeLine(` ${retry}`);
|
|
185
|
+
}
|
|
186
|
+
if (event.attempt.errors[0]) {
|
|
187
|
+
this.writeLine(` ${event.attempt.errors[0].message ?? String(event.attempt.errors[0])}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
onTestOutcomeResolved(event) {
|
|
191
|
+
this.outcomes[event.outcome] += 1;
|
|
192
|
+
}
|
|
193
|
+
onStdOutReceived(event) {
|
|
194
|
+
this.output.write(event.text);
|
|
195
|
+
}
|
|
196
|
+
onStdErrReceived(event) {
|
|
197
|
+
this.errorOutput.write(event.text);
|
|
198
|
+
}
|
|
199
|
+
onRunFinished(event) {
|
|
200
|
+
const parts = [];
|
|
201
|
+
if (this.outcomes.failed > 0) {
|
|
202
|
+
parts.push(this.colors.red(`${this.outcomes.failed} failed`));
|
|
203
|
+
}
|
|
204
|
+
if (this.outcomes.timedOut > 0) {
|
|
205
|
+
parts.push(this.colors.red(`${this.outcomes.timedOut} timed out`));
|
|
206
|
+
}
|
|
207
|
+
if (this.outcomes.interrupted > 0) {
|
|
208
|
+
parts.push(this.colors.red(`${this.outcomes.interrupted} interrupted`));
|
|
209
|
+
}
|
|
210
|
+
if (this.outcomes.flaky > 0) {
|
|
211
|
+
parts.push(this.colors.yellow(`${this.outcomes.flaky} flaky`));
|
|
212
|
+
}
|
|
213
|
+
if (this.outcomes.passed > 0) {
|
|
214
|
+
parts.push(this.colors.green(`${this.outcomes.passed} passed`));
|
|
215
|
+
}
|
|
216
|
+
if (this.outcomes.skipped > 0) {
|
|
217
|
+
parts.push(this.colors.yellow(`${this.outcomes.skipped} skipped`));
|
|
218
|
+
}
|
|
219
|
+
const summary = parts.length > 0 ? parts.join(", ") : event.result.status;
|
|
220
|
+
this.writeLine(`
|
|
221
|
+
${summary}`);
|
|
222
|
+
}
|
|
223
|
+
writeLine(value) {
|
|
224
|
+
this.output.write(`${value}
|
|
225
|
+
`);
|
|
226
|
+
}
|
|
227
|
+
getTestOrdinal(testId) {
|
|
228
|
+
const existing = this.testOrdinals.get(testId);
|
|
229
|
+
if (existing) {
|
|
230
|
+
return existing;
|
|
231
|
+
}
|
|
232
|
+
const ordinal = this.nextTestOrdinal;
|
|
233
|
+
this.nextTestOrdinal += 1;
|
|
234
|
+
this.testOrdinals.set(testId, ordinal);
|
|
235
|
+
return ordinal;
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
var index_default = ConsoleReporter;
|
|
239
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
240
|
+
0 && (module.exports = {
|
|
241
|
+
ConsoleReporter
|
|
242
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Reporter, FullConfig, Suite, FullResult } from '@playwright/test/reporter';
|
|
2
|
+
import { TestPulseReporterCore } from '@testpulse.run/playwright-core';
|
|
3
|
+
|
|
4
|
+
interface ConsoleReporterOptions {
|
|
5
|
+
output?: NodeJS.WritableStream;
|
|
6
|
+
errorOutput?: NodeJS.WritableStream;
|
|
7
|
+
color?: boolean | "auto";
|
|
8
|
+
verbose?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare class ConsoleReporter implements Reporter {
|
|
11
|
+
private readonly core;
|
|
12
|
+
private readonly events;
|
|
13
|
+
private readonly output;
|
|
14
|
+
private readonly errorOutput;
|
|
15
|
+
private readonly colors;
|
|
16
|
+
private readonly verbose;
|
|
17
|
+
private totalTests;
|
|
18
|
+
private nextTestOrdinal;
|
|
19
|
+
private readonly testOrdinals;
|
|
20
|
+
private outcomes;
|
|
21
|
+
private suite?;
|
|
22
|
+
private config?;
|
|
23
|
+
constructor(options?: ConsoleReporterOptions);
|
|
24
|
+
printsToStdio(): boolean;
|
|
25
|
+
onBegin(config: FullConfig, suite: Suite): void;
|
|
26
|
+
onEnd(result: FullResult): ReturnType<TestPulseReporterCore["onEnd"]>;
|
|
27
|
+
onError(...args: Parameters<TestPulseReporterCore["onError"]>): void;
|
|
28
|
+
onTestBegin(...args: Parameters<TestPulseReporterCore["onTestBegin"]>): void;
|
|
29
|
+
onTestEnd(...args: Parameters<TestPulseReporterCore["onTestEnd"]>): void;
|
|
30
|
+
onStepBegin(...args: Parameters<TestPulseReporterCore["onStepBegin"]>): void;
|
|
31
|
+
onStepEnd(...args: Parameters<TestPulseReporterCore["onStepEnd"]>): void;
|
|
32
|
+
onStdOut(...args: Parameters<TestPulseReporterCore["onStdOut"]>): void;
|
|
33
|
+
onStdErr(...args: Parameters<TestPulseReporterCore["onStdErr"]>): void;
|
|
34
|
+
private onRunStarted;
|
|
35
|
+
private onTestStarted;
|
|
36
|
+
private onTestAttemptFinished;
|
|
37
|
+
private onTestOutcomeResolved;
|
|
38
|
+
private onStdOutReceived;
|
|
39
|
+
private onStdErrReceived;
|
|
40
|
+
private onRunFinished;
|
|
41
|
+
private writeLine;
|
|
42
|
+
private getTestOrdinal;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { ConsoleReporter, type ConsoleReporterOptions, ConsoleReporter as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Reporter, FullConfig, Suite, FullResult } from '@playwright/test/reporter';
|
|
2
|
+
import { TestPulseReporterCore } from '@testpulse.run/playwright-core';
|
|
3
|
+
|
|
4
|
+
interface ConsoleReporterOptions {
|
|
5
|
+
output?: NodeJS.WritableStream;
|
|
6
|
+
errorOutput?: NodeJS.WritableStream;
|
|
7
|
+
color?: boolean | "auto";
|
|
8
|
+
verbose?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare class ConsoleReporter implements Reporter {
|
|
11
|
+
private readonly core;
|
|
12
|
+
private readonly events;
|
|
13
|
+
private readonly output;
|
|
14
|
+
private readonly errorOutput;
|
|
15
|
+
private readonly colors;
|
|
16
|
+
private readonly verbose;
|
|
17
|
+
private totalTests;
|
|
18
|
+
private nextTestOrdinal;
|
|
19
|
+
private readonly testOrdinals;
|
|
20
|
+
private outcomes;
|
|
21
|
+
private suite?;
|
|
22
|
+
private config?;
|
|
23
|
+
constructor(options?: ConsoleReporterOptions);
|
|
24
|
+
printsToStdio(): boolean;
|
|
25
|
+
onBegin(config: FullConfig, suite: Suite): void;
|
|
26
|
+
onEnd(result: FullResult): ReturnType<TestPulseReporterCore["onEnd"]>;
|
|
27
|
+
onError(...args: Parameters<TestPulseReporterCore["onError"]>): void;
|
|
28
|
+
onTestBegin(...args: Parameters<TestPulseReporterCore["onTestBegin"]>): void;
|
|
29
|
+
onTestEnd(...args: Parameters<TestPulseReporterCore["onTestEnd"]>): void;
|
|
30
|
+
onStepBegin(...args: Parameters<TestPulseReporterCore["onStepBegin"]>): void;
|
|
31
|
+
onStepEnd(...args: Parameters<TestPulseReporterCore["onStepEnd"]>): void;
|
|
32
|
+
onStdOut(...args: Parameters<TestPulseReporterCore["onStdOut"]>): void;
|
|
33
|
+
onStdErr(...args: Parameters<TestPulseReporterCore["onStdErr"]>): void;
|
|
34
|
+
private onRunStarted;
|
|
35
|
+
private onTestStarted;
|
|
36
|
+
private onTestAttemptFinished;
|
|
37
|
+
private onTestOutcomeResolved;
|
|
38
|
+
private onStdOutReceived;
|
|
39
|
+
private onStdErrReceived;
|
|
40
|
+
private onRunFinished;
|
|
41
|
+
private writeLine;
|
|
42
|
+
private getTestOrdinal;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { ConsoleReporter, type ConsoleReporterOptions, ConsoleReporter as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
TestPulseReporterCore
|
|
4
|
+
} from "@testpulse.run/playwright-core";
|
|
5
|
+
import {
|
|
6
|
+
PlaywrightEvents
|
|
7
|
+
} from "@testpulse.run/playwright-events";
|
|
8
|
+
|
|
9
|
+
// src/format.ts
|
|
10
|
+
function createColorizer(enabled) {
|
|
11
|
+
const color = (code, value) => enabled ? `\x1B[${code}m${value}\x1B[0m` : value;
|
|
12
|
+
return {
|
|
13
|
+
green: (value) => color(32, value),
|
|
14
|
+
red: (value) => color(31, value),
|
|
15
|
+
yellow: (value) => color(33, value),
|
|
16
|
+
gray: (value) => color(90, value)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function formatTestTitle(test) {
|
|
20
|
+
const location = test.location ? `${test.location.file}:${test.location.line}:${test.location.column}` : "";
|
|
21
|
+
const path = test.titlePath.length > 0 ? test.titlePath : [test.title];
|
|
22
|
+
const title = path.filter(Boolean).join(" \u203A ");
|
|
23
|
+
return location ? `${location} \u203A ${title}` : title;
|
|
24
|
+
}
|
|
25
|
+
function formatDuration(durationMs) {
|
|
26
|
+
if (durationMs < 1e3) {
|
|
27
|
+
return `${Math.round(durationMs)}ms`;
|
|
28
|
+
}
|
|
29
|
+
return `${(durationMs / 1e3).toFixed(1)}s`;
|
|
30
|
+
}
|
|
31
|
+
function statusSymbol(status) {
|
|
32
|
+
switch (status) {
|
|
33
|
+
case "passed":
|
|
34
|
+
return "ok";
|
|
35
|
+
case "skipped":
|
|
36
|
+
return "-";
|
|
37
|
+
case "timedOut":
|
|
38
|
+
return "timeout";
|
|
39
|
+
case "interrupted":
|
|
40
|
+
return "interrupted";
|
|
41
|
+
case "failed":
|
|
42
|
+
default:
|
|
43
|
+
return "x";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function colorStatus(status, value, colors) {
|
|
47
|
+
switch (status) {
|
|
48
|
+
case "passed":
|
|
49
|
+
return colors.green(value);
|
|
50
|
+
case "skipped":
|
|
51
|
+
return colors.yellow(value);
|
|
52
|
+
case "failed":
|
|
53
|
+
case "timedOut":
|
|
54
|
+
case "interrupted":
|
|
55
|
+
return colors.red(value);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/index.ts
|
|
60
|
+
var ConsoleReporter = class {
|
|
61
|
+
core;
|
|
62
|
+
events;
|
|
63
|
+
output;
|
|
64
|
+
errorOutput;
|
|
65
|
+
colors;
|
|
66
|
+
verbose;
|
|
67
|
+
totalTests = 0;
|
|
68
|
+
nextTestOrdinal = 1;
|
|
69
|
+
testOrdinals = /* @__PURE__ */ new Map();
|
|
70
|
+
outcomes = {
|
|
71
|
+
passed: 0,
|
|
72
|
+
failed: 0,
|
|
73
|
+
flaky: 0,
|
|
74
|
+
skipped: 0,
|
|
75
|
+
interrupted: 0,
|
|
76
|
+
timedOut: 0
|
|
77
|
+
};
|
|
78
|
+
suite;
|
|
79
|
+
config;
|
|
80
|
+
constructor(options = {}) {
|
|
81
|
+
this.output = options.output ?? process.stdout;
|
|
82
|
+
this.errorOutput = options.errorOutput ?? process.stderr;
|
|
83
|
+
this.verbose = options.verbose ?? false;
|
|
84
|
+
const shouldColor = options.color === true || options.color !== false && Boolean(this.output.isTTY);
|
|
85
|
+
this.colors = createColorizer(shouldColor);
|
|
86
|
+
const consolePlugin = {
|
|
87
|
+
name: "@testpulse.run/playwright-console-reporter",
|
|
88
|
+
RunStarted: (event) => this.onRunStarted(event),
|
|
89
|
+
TestStarted: (event) => this.onTestStarted(event),
|
|
90
|
+
StdOutReceived: (event) => this.onStdOutReceived(event),
|
|
91
|
+
StdErrReceived: (event) => this.onStdErrReceived(event),
|
|
92
|
+
RunFinished: (event) => this.onRunFinished(event)
|
|
93
|
+
};
|
|
94
|
+
const derivedPlugin = {
|
|
95
|
+
name: "@testpulse.run/playwright-console-reporter",
|
|
96
|
+
TestAttemptFinished: (event) => this.onTestAttemptFinished(event),
|
|
97
|
+
TestOutcomeResolved: (event) => this.onTestOutcomeResolved(event)
|
|
98
|
+
};
|
|
99
|
+
this.events = new PlaywrightEvents({ plugins: [derivedPlugin] });
|
|
100
|
+
this.core = new TestPulseReporterCore({ plugins: [this.events.asCorePlugin(), consolePlugin] });
|
|
101
|
+
this.events.setErrorSink(this.core);
|
|
102
|
+
}
|
|
103
|
+
printsToStdio() {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
onBegin(config, suite) {
|
|
107
|
+
this.config = config;
|
|
108
|
+
this.suite = suite;
|
|
109
|
+
this.core.onBegin(config, suite);
|
|
110
|
+
}
|
|
111
|
+
onEnd(result) {
|
|
112
|
+
return this.core.onEnd(result);
|
|
113
|
+
}
|
|
114
|
+
onError(...args) {
|
|
115
|
+
this.core.onError(...args);
|
|
116
|
+
}
|
|
117
|
+
onTestBegin(...args) {
|
|
118
|
+
this.core.onTestBegin(...args);
|
|
119
|
+
}
|
|
120
|
+
onTestEnd(...args) {
|
|
121
|
+
this.core.onTestEnd(...args);
|
|
122
|
+
}
|
|
123
|
+
onStepBegin(...args) {
|
|
124
|
+
this.core.onStepBegin(...args);
|
|
125
|
+
}
|
|
126
|
+
onStepEnd(...args) {
|
|
127
|
+
this.core.onStepEnd(...args);
|
|
128
|
+
}
|
|
129
|
+
onStdOut(...args) {
|
|
130
|
+
this.core.onStdOut(...args);
|
|
131
|
+
}
|
|
132
|
+
onStdErr(...args) {
|
|
133
|
+
this.core.onStdErr(...args);
|
|
134
|
+
}
|
|
135
|
+
onRunStarted(event) {
|
|
136
|
+
this.totalTests = event.totalTests;
|
|
137
|
+
this.nextTestOrdinal = 1;
|
|
138
|
+
this.testOrdinals.clear();
|
|
139
|
+
this.outcomes = {
|
|
140
|
+
passed: 0,
|
|
141
|
+
failed: 0,
|
|
142
|
+
flaky: 0,
|
|
143
|
+
skipped: 0,
|
|
144
|
+
interrupted: 0,
|
|
145
|
+
timedOut: 0
|
|
146
|
+
};
|
|
147
|
+
const workers = this.config?.workers ?? 1;
|
|
148
|
+
this.writeLine(`Running ${event.totalTests} test${event.totalTests === 1 ? "" : "s"} using ${workers} worker${workers === 1 ? "" : "s"}`);
|
|
149
|
+
}
|
|
150
|
+
onTestStarted(event) {
|
|
151
|
+
if (!this.verbose) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
this.writeLine(`[${this.getTestOrdinal(event.test.testId ?? event.titlePath.join(" \u203A "))}/${this.totalTests}] ${formatTestTitle(event.test)}`);
|
|
155
|
+
}
|
|
156
|
+
onTestAttemptFinished(event) {
|
|
157
|
+
const testOrdinal = this.getTestOrdinal(event.testId);
|
|
158
|
+
const marker = colorStatus(event.status, statusSymbol(event.status), this.colors);
|
|
159
|
+
const duration = this.colors.gray(formatDuration(event.attempt.durationMs));
|
|
160
|
+
const retry = event.retry > 0 ? this.colors.gray(` retry #${event.retry}`) : "";
|
|
161
|
+
this.writeLine(`${marker} ${testOrdinal} ${formatTestTitle(event.test)} (${duration})`);
|
|
162
|
+
if (retry) {
|
|
163
|
+
this.writeLine(` ${retry}`);
|
|
164
|
+
}
|
|
165
|
+
if (event.attempt.errors[0]) {
|
|
166
|
+
this.writeLine(` ${event.attempt.errors[0].message ?? String(event.attempt.errors[0])}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
onTestOutcomeResolved(event) {
|
|
170
|
+
this.outcomes[event.outcome] += 1;
|
|
171
|
+
}
|
|
172
|
+
onStdOutReceived(event) {
|
|
173
|
+
this.output.write(event.text);
|
|
174
|
+
}
|
|
175
|
+
onStdErrReceived(event) {
|
|
176
|
+
this.errorOutput.write(event.text);
|
|
177
|
+
}
|
|
178
|
+
onRunFinished(event) {
|
|
179
|
+
const parts = [];
|
|
180
|
+
if (this.outcomes.failed > 0) {
|
|
181
|
+
parts.push(this.colors.red(`${this.outcomes.failed} failed`));
|
|
182
|
+
}
|
|
183
|
+
if (this.outcomes.timedOut > 0) {
|
|
184
|
+
parts.push(this.colors.red(`${this.outcomes.timedOut} timed out`));
|
|
185
|
+
}
|
|
186
|
+
if (this.outcomes.interrupted > 0) {
|
|
187
|
+
parts.push(this.colors.red(`${this.outcomes.interrupted} interrupted`));
|
|
188
|
+
}
|
|
189
|
+
if (this.outcomes.flaky > 0) {
|
|
190
|
+
parts.push(this.colors.yellow(`${this.outcomes.flaky} flaky`));
|
|
191
|
+
}
|
|
192
|
+
if (this.outcomes.passed > 0) {
|
|
193
|
+
parts.push(this.colors.green(`${this.outcomes.passed} passed`));
|
|
194
|
+
}
|
|
195
|
+
if (this.outcomes.skipped > 0) {
|
|
196
|
+
parts.push(this.colors.yellow(`${this.outcomes.skipped} skipped`));
|
|
197
|
+
}
|
|
198
|
+
const summary = parts.length > 0 ? parts.join(", ") : event.result.status;
|
|
199
|
+
this.writeLine(`
|
|
200
|
+
${summary}`);
|
|
201
|
+
}
|
|
202
|
+
writeLine(value) {
|
|
203
|
+
this.output.write(`${value}
|
|
204
|
+
`);
|
|
205
|
+
}
|
|
206
|
+
getTestOrdinal(testId) {
|
|
207
|
+
const existing = this.testOrdinals.get(testId);
|
|
208
|
+
if (existing) {
|
|
209
|
+
return existing;
|
|
210
|
+
}
|
|
211
|
+
const ordinal = this.nextTestOrdinal;
|
|
212
|
+
this.nextTestOrdinal += 1;
|
|
213
|
+
this.testOrdinals.set(testId, ordinal);
|
|
214
|
+
return ordinal;
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
var index_default = ConsoleReporter;
|
|
218
|
+
export {
|
|
219
|
+
ConsoleReporter,
|
|
220
|
+
index_default as default
|
|
221
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@testpulse.run/playwright-console-reporter",
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"description": "Console reporter for Playwright built on TestPulse reporter core.",
|
|
5
|
+
"homepage": "https://testpulse.run",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"testpulse",
|
|
8
|
+
"playwright",
|
|
9
|
+
"playwright-reporter",
|
|
10
|
+
"console-reporter",
|
|
11
|
+
"test-reporter",
|
|
12
|
+
"test-automation",
|
|
13
|
+
"testing",
|
|
14
|
+
"typescript"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/index.cjs",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"require": "./dist/index.cjs"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
35
|
+
"test": "vitest run"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@testpulse.run/playwright-core": "0.2.3",
|
|
39
|
+
"@testpulse.run/playwright-events": "0.2.3"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@playwright/test": ">=1.40.0"
|
|
43
|
+
}
|
|
44
|
+
}
|