@epicat/toon-reporter 0.0.4 → 0.0.6
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 +125 -11
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +59 -0
- package/dist/playwright.d.mts +25 -0
- package/dist/playwright.mjs +111 -0
- package/package.json +17 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# toon-reporter
|
|
2
2
|
|
|
3
|
-
A minimal Vitest reporter optimized for LLM consumption. Outputs test results in a compact, token-efficient format.
|
|
3
|
+
A minimal Vitest and Playwright reporter optimized for LLM consumption. Outputs test results in a compact, token-efficient format.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -10,13 +10,15 @@ npm install @epicat/toon-reporter
|
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
|
-
###
|
|
13
|
+
### Vitest
|
|
14
|
+
|
|
15
|
+
#### CLI
|
|
14
16
|
|
|
15
17
|
```bash
|
|
16
18
|
npx vitest run --reporter=@epicat/toon-reporter
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
#### Config
|
|
20
22
|
|
|
21
23
|
```ts
|
|
22
24
|
// vitest.config.ts
|
|
@@ -29,6 +31,34 @@ export default defineConfig({
|
|
|
29
31
|
})
|
|
30
32
|
```
|
|
31
33
|
|
|
34
|
+
### Playwright
|
|
35
|
+
|
|
36
|
+
#### Config
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
// playwright.config.ts
|
|
40
|
+
import { defineConfig } from '@playwright/test'
|
|
41
|
+
|
|
42
|
+
export default defineConfig({
|
|
43
|
+
reporter: [['@epicat/toon-reporter/playwright']],
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### With options
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// playwright.config.ts
|
|
51
|
+
import { defineConfig } from '@playwright/test'
|
|
52
|
+
|
|
53
|
+
export default defineConfig({
|
|
54
|
+
reporter: [
|
|
55
|
+
['@epicat/toon-reporter/playwright', {
|
|
56
|
+
outputFile: 'test-results.toon'
|
|
57
|
+
}]
|
|
58
|
+
],
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
32
62
|
## Output Format
|
|
33
63
|
|
|
34
64
|
### All tests passing
|
|
@@ -37,7 +67,7 @@ export default defineConfig({
|
|
|
37
67
|
passing: 42
|
|
38
68
|
```
|
|
39
69
|
|
|
40
|
-
### With failures
|
|
70
|
+
### With failures (Vitest)
|
|
41
71
|
|
|
42
72
|
```
|
|
43
73
|
passing: 40
|
|
@@ -49,7 +79,15 @@ failing[2]:
|
|
|
49
79
|
error: TypeError: Cannot read property 'id' of undefined
|
|
50
80
|
```
|
|
51
81
|
|
|
52
|
-
### With
|
|
82
|
+
### With failures (Playwright)
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
passing: 1
|
|
86
|
+
failing[1]{at,expected,got}:
|
|
87
|
+
"login.spec.ts:7:42",Welcome,Hello World
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### With parameterized test failures (Vitest)
|
|
53
91
|
|
|
54
92
|
Uses TOON tabular format for uniform parameter arrays:
|
|
55
93
|
|
|
@@ -69,16 +107,60 @@ Uses TOON tabular format for uniform arrays:
|
|
|
69
107
|
```
|
|
70
108
|
passing: 38
|
|
71
109
|
todo[1]{at,name}:
|
|
72
|
-
src/api.test.ts,implement error handling
|
|
110
|
+
"src/api.test.ts:15:3",implement error handling
|
|
73
111
|
skipped[2]{at,name}:
|
|
74
|
-
src/utils.test.ts,handles edge case
|
|
112
|
+
"src/utils.test.ts:8:3",handles edge case
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### With flaky tests (Playwright)
|
|
116
|
+
|
|
117
|
+
Tests that fail initially but pass on retry are reported as flaky:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
passing: 5
|
|
121
|
+
flaky[1]{at,name,retries}:
|
|
122
|
+
"checkout.spec.ts:12:3",should complete payment,2
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### With coverage (Vitest only)
|
|
126
|
+
|
|
127
|
+
Coverage is automatically included when running with `--coverage`. No extra configuration needed:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npx vitest run --coverage --reporter=@epicat/toon-reporter
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Output includes total percentages and uncovered lines per file:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
passing: 8
|
|
137
|
+
coverage:
|
|
138
|
+
"total%":
|
|
139
|
+
lines: 60.99
|
|
140
|
+
stmts: 58.82
|
|
141
|
+
branch: 44.34
|
|
142
|
+
funcs: 57.57
|
|
143
|
+
files[1]{file,uncoveredLines}:
|
|
144
|
+
src/toon-reporter.ts,"12-14,19-23,32,99"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- **Total percentages**: Help teams track coverage thresholds
|
|
148
|
+
- **Per-file uncovered lines**: Give LLMs actionable info to improve coverage
|
|
149
|
+
- **100% covered files are hidden** by default to reduce noise
|
|
150
|
+
|
|
151
|
+
With `verbose: true`, all files appear with per-file percentages:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
files[2]{file,uncoveredLines,"lines%","stmts%","branch%","funcs%"}:
|
|
155
|
+
src/toon-reporter.ts,"12-14,19-23,32,99",56.89,55.63,43.63,61.53
|
|
156
|
+
test/test-utils.ts,"",100,100,100,100
|
|
75
157
|
```
|
|
76
158
|
|
|
77
159
|
## Colors
|
|
78
160
|
|
|
79
161
|
- **Green**: `passing` count
|
|
80
162
|
- **Red**: `failing` header
|
|
81
|
-
- **Yellow**: file paths
|
|
163
|
+
- **Yellow**: `flaky` header, file paths
|
|
82
164
|
- **Gray**: `skipped` tests
|
|
83
165
|
- **Cyan**: `todo` tests
|
|
84
166
|
|
|
@@ -119,11 +201,21 @@ COLOR=1 npx vitest run --reporter=@epicat/toon-reporter
|
|
|
119
201
|
Write report to a file instead of stdout.
|
|
120
202
|
|
|
121
203
|
```ts
|
|
122
|
-
reporters: [['toon-reporter', { outputFile: 'test-results.txt' }]]
|
|
204
|
+
reporters: [['@epicat/toon-reporter', { outputFile: 'test-results.txt' }]]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### `verbose`
|
|
208
|
+
|
|
209
|
+
Include per-file coverage percentages (lines, stmts, branch, funcs) alongside uncovered lines.
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
reporters: [new ToonReporter({ verbose: true })]
|
|
123
213
|
```
|
|
124
214
|
|
|
125
215
|
## Skipped/Todo Line Numbers
|
|
126
216
|
|
|
217
|
+
### Vitest
|
|
218
|
+
|
|
127
219
|
To get line:column information for skipped and todo tests, enable `includeTaskLocation` in your vitest config:
|
|
128
220
|
|
|
129
221
|
```ts
|
|
@@ -131,7 +223,7 @@ To get line:column information for skipped and todo tests, enable `includeTaskLo
|
|
|
131
223
|
export default defineConfig({
|
|
132
224
|
test: {
|
|
133
225
|
includeTaskLocation: true,
|
|
134
|
-
reporters: ['toon-reporter'],
|
|
226
|
+
reporters: ['@epicat/toon-reporter'],
|
|
135
227
|
},
|
|
136
228
|
})
|
|
137
229
|
```
|
|
@@ -139,18 +231,40 @@ export default defineConfig({
|
|
|
139
231
|
Or via CLI:
|
|
140
232
|
|
|
141
233
|
```bash
|
|
142
|
-
npx vitest run --reporter
|
|
234
|
+
npx vitest run --reporter=@epicat/toon-reporter --includeTaskLocation
|
|
143
235
|
```
|
|
144
236
|
|
|
145
237
|
Without this option, skipped/todo tests will only show the file path (not line:column). This is a Vitest limitation - test locations are only collected when this config is enabled before test collection.
|
|
146
238
|
|
|
239
|
+
### Playwright
|
|
240
|
+
|
|
241
|
+
Playwright always includes test locations. Tests marked with `test.fixme()` are reported as `todo`, while `test.skip()` tests are reported as `skipped`.
|
|
242
|
+
|
|
243
|
+
## Playwright-Specific Features
|
|
244
|
+
|
|
245
|
+
### Flaky Test Detection
|
|
246
|
+
|
|
247
|
+
When `retries` is configured in your Playwright config, tests that fail initially but pass on retry are reported as flaky:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
// playwright.config.ts
|
|
251
|
+
export default defineConfig({
|
|
252
|
+
retries: 2,
|
|
253
|
+
reporter: [['@epicat/toon-reporter/playwright']],
|
|
254
|
+
})
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Output: `flaky[1]{at,name,retries}: "test.spec.ts:5:3",should work,1`
|
|
258
|
+
|
|
147
259
|
## Why?
|
|
148
260
|
|
|
149
261
|
Traditional test reporters output verbose information optimized for human readability. When feeding test results to an LLM for automated fixing, this verbosity wastes tokens. This reporter outputs only what's needed:
|
|
150
262
|
|
|
151
263
|
- Pass count
|
|
152
264
|
- Failure locations with expected/got values
|
|
265
|
+
- Flaky test detection with retry counts (Playwright)
|
|
153
266
|
- Skipped/todo test names for context
|
|
267
|
+
- Coverage totals and uncovered lines (Vitest with `--coverage`)
|
|
154
268
|
|
|
155
269
|
## Token Efficiency
|
|
156
270
|
|
package/dist/index.d.mts
CHANGED
|
@@ -5,6 +5,8 @@ import { Reporter, TestRunEndReason, Vitest } from "vitest/node";
|
|
|
5
5
|
interface ToonReporterOptions {
|
|
6
6
|
outputFile?: string;
|
|
7
7
|
color?: boolean;
|
|
8
|
+
/** Include per-file coverage percentages (lines, stmts, branch, funcs) */
|
|
9
|
+
verbose?: boolean;
|
|
8
10
|
/** @internal Used for testing to capture output */
|
|
9
11
|
_captureOutput?: (output: string) => void;
|
|
10
12
|
}
|
|
@@ -13,8 +15,12 @@ declare class ToonReporter implements Reporter {
|
|
|
13
15
|
ctx: Vitest;
|
|
14
16
|
options: ToonReporterOptions;
|
|
15
17
|
private useColor;
|
|
18
|
+
private coverageMap;
|
|
16
19
|
constructor(options?: ToonReporterOptions);
|
|
17
20
|
onInit(ctx: Vitest): void;
|
|
21
|
+
onCoverage(coverage: unknown): void;
|
|
22
|
+
private getCoverageSummary;
|
|
23
|
+
private formatLineRanges;
|
|
18
24
|
private formatLocation;
|
|
19
25
|
private parseErrorLocation;
|
|
20
26
|
private parseExpectedGot;
|
package/dist/index.mjs
CHANGED
|
@@ -54,6 +54,63 @@ var ToonReporter = class {
|
|
|
54
54
|
onInit(ctx) {
|
|
55
55
|
this.ctx = ctx;
|
|
56
56
|
this.start = Date.now();
|
|
57
|
+
this.coverageMap = void 0;
|
|
58
|
+
const coverage = ctx.config.coverage;
|
|
59
|
+
if (coverage?.reporter) coverage.reporter = [];
|
|
60
|
+
}
|
|
61
|
+
onCoverage(coverage) {
|
|
62
|
+
this.coverageMap = coverage;
|
|
63
|
+
}
|
|
64
|
+
getCoverageSummary() {
|
|
65
|
+
if (!this.coverageMap) return void 0;
|
|
66
|
+
const map = this.coverageMap;
|
|
67
|
+
if (typeof map.getCoverageSummary !== "function") return void 0;
|
|
68
|
+
const summary = map.getCoverageSummary().toJSON();
|
|
69
|
+
const rootDir = this.ctx.config.root;
|
|
70
|
+
const result = { "total%": {
|
|
71
|
+
lines: summary.lines?.pct ?? 0,
|
|
72
|
+
stmts: summary.statements?.pct ?? 0,
|
|
73
|
+
branch: summary.branches?.pct ?? 0,
|
|
74
|
+
funcs: summary.functions?.pct ?? 0
|
|
75
|
+
} };
|
|
76
|
+
if (map.files && map.fileCoverageFor) {
|
|
77
|
+
const entries = [];
|
|
78
|
+
const verbose = this.options.verbose;
|
|
79
|
+
for (const file of map.files()) {
|
|
80
|
+
const fc = map.fileCoverageFor(file);
|
|
81
|
+
const uncoveredLines = fc.getUncoveredLines();
|
|
82
|
+
const hasGaps = uncoveredLines.length > 0;
|
|
83
|
+
if (!verbose && !hasGaps) continue;
|
|
84
|
+
const entry = {
|
|
85
|
+
file: relative(rootDir, file),
|
|
86
|
+
uncoveredLines: this.formatLineRanges(uncoveredLines)
|
|
87
|
+
};
|
|
88
|
+
if (verbose) {
|
|
89
|
+
const fileSummary = fc.toSummary().toJSON();
|
|
90
|
+
entry["lines%"] = fileSummary.lines?.pct ?? 0;
|
|
91
|
+
entry["stmts%"] = fileSummary.statements?.pct ?? 0;
|
|
92
|
+
entry["branch%"] = fileSummary.branches?.pct ?? 0;
|
|
93
|
+
entry["funcs%"] = fileSummary.functions?.pct ?? 0;
|
|
94
|
+
}
|
|
95
|
+
entries.push(entry);
|
|
96
|
+
}
|
|
97
|
+
if (entries.length > 0) result.files = entries;
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
formatLineRanges(lines) {
|
|
102
|
+
if (lines.length === 0) return "";
|
|
103
|
+
const sorted = lines.map(Number).sort((a, b) => a - b);
|
|
104
|
+
const ranges = [];
|
|
105
|
+
let start = sorted[0];
|
|
106
|
+
let end = start;
|
|
107
|
+
for (let i = 1; i <= sorted.length; i++) if (sorted[i] === end + 1) end = sorted[i];
|
|
108
|
+
else {
|
|
109
|
+
ranges.push(start === end ? String(start) : `${start}-${end}`);
|
|
110
|
+
start = sorted[i];
|
|
111
|
+
end = start;
|
|
112
|
+
}
|
|
113
|
+
return ranges.join(",");
|
|
57
114
|
}
|
|
58
115
|
formatLocation(relPath, line, column) {
|
|
59
116
|
return line ? `${relPath}:${line}:${column || 0}` : relPath;
|
|
@@ -135,6 +192,8 @@ var ToonReporter = class {
|
|
|
135
192
|
if (failures.length > 0) report.failing = failures;
|
|
136
193
|
if (todoTests.length > 0) report.todo = todoTests.map(mapToSkipped);
|
|
137
194
|
if (skippedTests.length > 0) report.skipped = skippedTests.map(mapToSkipped);
|
|
195
|
+
const coverage = this.getCoverageSummary();
|
|
196
|
+
if (coverage) report.coverage = coverage;
|
|
138
197
|
await this.writeReport(encode(report));
|
|
139
198
|
}
|
|
140
199
|
colorize(report) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { FullConfig, FullResult, Reporter, Suite } from "@playwright/test/reporter";
|
|
2
|
+
|
|
3
|
+
//#region src/toon-playwright-reporter.d.ts
|
|
4
|
+
interface ToonPlaywrightReporterOptions {
|
|
5
|
+
outputFile?: string;
|
|
6
|
+
/** @internal Used for testing to capture output */
|
|
7
|
+
_captureOutput?: (output: string) => void;
|
|
8
|
+
}
|
|
9
|
+
declare class ToonPlaywrightReporter implements Reporter {
|
|
10
|
+
private config;
|
|
11
|
+
private suite;
|
|
12
|
+
private options;
|
|
13
|
+
constructor(options?: ToonPlaywrightReporterOptions);
|
|
14
|
+
onBegin(config: FullConfig, suite: Suite): void;
|
|
15
|
+
private get rootDir();
|
|
16
|
+
private formatLocation;
|
|
17
|
+
private stripAnsi;
|
|
18
|
+
private stripOuterQuotes;
|
|
19
|
+
private parseExpectedGot;
|
|
20
|
+
onEnd(result: FullResult): Promise<void>;
|
|
21
|
+
writeReport(report: string): Promise<void>;
|
|
22
|
+
printsToStdio(): boolean;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { ToonPlaywrightReporter, ToonPlaywrightReporter as default, type ToonPlaywrightReporterOptions };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { existsSync, promises } from "node:fs";
|
|
2
|
+
import { dirname, relative, resolve } from "pathe";
|
|
3
|
+
import { encode } from "@toon-format/toon";
|
|
4
|
+
|
|
5
|
+
//#region src/toon-playwright-reporter.ts
|
|
6
|
+
var ToonPlaywrightReporter = class {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
onBegin(config, suite) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.suite = suite;
|
|
13
|
+
}
|
|
14
|
+
get rootDir() {
|
|
15
|
+
return this.config.rootDir;
|
|
16
|
+
}
|
|
17
|
+
formatLocation(filePath, line, column) {
|
|
18
|
+
const relPath = relative(this.rootDir, filePath);
|
|
19
|
+
return line ? `${relPath}:${line}:${column || 0}` : relPath;
|
|
20
|
+
}
|
|
21
|
+
stripAnsi(str) {
|
|
22
|
+
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
23
|
+
}
|
|
24
|
+
stripOuterQuotes(str) {
|
|
25
|
+
if (str.startsWith("\"") && str.endsWith("\"") || str.startsWith("'") && str.endsWith("'")) return str.slice(1, -1);
|
|
26
|
+
return str;
|
|
27
|
+
}
|
|
28
|
+
parseExpectedGot(error) {
|
|
29
|
+
const message = this.stripAnsi(error?.message || "");
|
|
30
|
+
const expectedMatch = message.match(/Expected:\s*(.+?)(?:\n|$)/i);
|
|
31
|
+
const receivedMatch = message.match(/Received:\s*(.+?)(?:\n|$)/i);
|
|
32
|
+
if (expectedMatch && receivedMatch) return {
|
|
33
|
+
expected: this.stripOuterQuotes(expectedMatch[1].trim()),
|
|
34
|
+
got: this.stripOuterQuotes(receivedMatch[1].trim())
|
|
35
|
+
};
|
|
36
|
+
const toBeMatch = message.match(/expect\((.+?)\)\.toBe\((.+?)\)/i);
|
|
37
|
+
if (toBeMatch) return {
|
|
38
|
+
expected: this.stripOuterQuotes(toBeMatch[2].trim()),
|
|
39
|
+
got: this.stripOuterQuotes(toBeMatch[1].trim())
|
|
40
|
+
};
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
async onEnd(result) {
|
|
44
|
+
const allTests = this.suite.allTests();
|
|
45
|
+
const passedTests = [];
|
|
46
|
+
const failedTests = [];
|
|
47
|
+
const skippedTests = [];
|
|
48
|
+
const todoTests = [];
|
|
49
|
+
const flakyTests = [];
|
|
50
|
+
for (const test of allTests) {
|
|
51
|
+
const lastResult = test.results[test.results.length - 1];
|
|
52
|
+
if (!lastResult) continue;
|
|
53
|
+
const status = lastResult.status;
|
|
54
|
+
const isFixme = test.annotations.some((a) => a.type === "fixme");
|
|
55
|
+
if (status === "passed" && test.results.length > 1 && test.results.some((r) => r.status === "failed")) flakyTests.push(test);
|
|
56
|
+
else if (status === "passed") passedTests.push(test);
|
|
57
|
+
else if (status === "failed" || status === "timedOut" || status === "interrupted") failedTests.push(test);
|
|
58
|
+
else if (status === "skipped") if (isFixme) todoTests.push(test);
|
|
59
|
+
else skippedTests.push(test);
|
|
60
|
+
}
|
|
61
|
+
const failures = [];
|
|
62
|
+
for (const test of failedTests) {
|
|
63
|
+
const error = test.results[test.results.length - 1]?.errors?.[0];
|
|
64
|
+
const loc = error?.location || test.location;
|
|
65
|
+
const failure = { at: this.formatLocation(loc.file, loc.line, loc.column) };
|
|
66
|
+
if (error) {
|
|
67
|
+
const { expected, got } = this.parseExpectedGot(error);
|
|
68
|
+
if (expected !== void 0 && got !== void 0) {
|
|
69
|
+
failure.expected = expected;
|
|
70
|
+
failure.got = got;
|
|
71
|
+
} else failure.error = error.message;
|
|
72
|
+
}
|
|
73
|
+
failures.push(failure);
|
|
74
|
+
}
|
|
75
|
+
const mapToSkipped = (test) => ({
|
|
76
|
+
at: this.formatLocation(test.location.file, test.location.line, test.location.column),
|
|
77
|
+
name: test.title
|
|
78
|
+
});
|
|
79
|
+
const mapToFlaky = (test) => ({
|
|
80
|
+
at: this.formatLocation(test.location.file, test.location.line, test.location.column),
|
|
81
|
+
name: test.title,
|
|
82
|
+
retries: test.results.length - 1
|
|
83
|
+
});
|
|
84
|
+
const report = { passing: passedTests.length };
|
|
85
|
+
if (flakyTests.length > 0) report.flaky = flakyTests.map(mapToFlaky);
|
|
86
|
+
if (failures.length > 0) report.failing = failures;
|
|
87
|
+
if (todoTests.length > 0) report.todo = todoTests.map(mapToSkipped);
|
|
88
|
+
if (skippedTests.length > 0) report.skipped = skippedTests.map(mapToSkipped);
|
|
89
|
+
await this.writeReport(encode(report));
|
|
90
|
+
}
|
|
91
|
+
async writeReport(report) {
|
|
92
|
+
if (this.options._captureOutput) {
|
|
93
|
+
this.options._captureOutput(report);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const outputFile = this.options.outputFile;
|
|
97
|
+
if (outputFile) {
|
|
98
|
+
const reportFile = resolve(this.rootDir, outputFile);
|
|
99
|
+
const outputDirectory = dirname(reportFile);
|
|
100
|
+
if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
|
|
101
|
+
await promises.writeFile(reportFile, report, "utf-8");
|
|
102
|
+
console.log(`TOON report written to ${reportFile}`);
|
|
103
|
+
} else console.log(report);
|
|
104
|
+
}
|
|
105
|
+
printsToStdio() {
|
|
106
|
+
return !this.options.outputFile;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
//#endregion
|
|
111
|
+
export { ToonPlaywrightReporter, ToonPlaywrightReporter as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epicat/toon-reporter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "A minimal Vitest reporter optimized for LLM consumption",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,20 +16,35 @@
|
|
|
16
16
|
"types": "./dist/index.d.mts",
|
|
17
17
|
"exports": {
|
|
18
18
|
".": "./dist/index.mjs",
|
|
19
|
+
"./playwright": "./dist/playwright.mjs",
|
|
19
20
|
"./package.json": "./package.json"
|
|
20
21
|
},
|
|
21
22
|
"peerDependencies": {
|
|
23
|
+
"@playwright/test": ">=1.40.0",
|
|
22
24
|
"vitest": ">=2.0.0"
|
|
23
25
|
},
|
|
26
|
+
"peerDependenciesMeta": {
|
|
27
|
+
"@playwright/test": {
|
|
28
|
+
"optional": true
|
|
29
|
+
},
|
|
30
|
+
"vitest": {
|
|
31
|
+
"optional": true
|
|
32
|
+
}
|
|
33
|
+
},
|
|
24
34
|
"dependencies": {
|
|
25
35
|
"@toon-format/toon": "^2.0.1",
|
|
26
36
|
"pathe": "^2.0.3"
|
|
27
37
|
},
|
|
28
38
|
"devDependencies": {
|
|
29
39
|
"@changesets/cli": "^2.29.8",
|
|
40
|
+
"@playwright/test": "^1.57.0",
|
|
30
41
|
"@types/node": "^24.10.1",
|
|
42
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
31
43
|
"@vitest/runner": "4.0.15",
|
|
32
44
|
"@vitest/utils": "4.0.15",
|
|
45
|
+
"gpt-tokenizer": "^3.4.0",
|
|
46
|
+
"istanbul-lib-coverage": "^3.2.2",
|
|
47
|
+
"serve": "^14.2.5",
|
|
33
48
|
"tsdown": "^0.16.4",
|
|
34
49
|
"typescript": "^5.9.3",
|
|
35
50
|
"vitest": "4.0.15"
|
|
@@ -38,6 +53,7 @@
|
|
|
38
53
|
"build": "tsdown",
|
|
39
54
|
"dev": "tsdown --watch",
|
|
40
55
|
"test": "vitest run",
|
|
56
|
+
"test:coverage": "vitest run --coverage",
|
|
41
57
|
"test:watch": "vitest"
|
|
42
58
|
}
|
|
43
59
|
}
|