reporting-labs 0.4.2 → 0.5.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/README.md +16 -1
- package/bin/config-template.txt +5 -0
- package/dist/reporter.d.ts +4 -0
- package/dist/reporter.js +39 -1
- package/dist/template.js +4 -1
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,13 +46,25 @@ Your other reporters (list, html, blob...) keep working as before.
|
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
48
|
npx playwright test
|
|
49
|
-
open reporting-labs/index.html
|
|
50
49
|
```
|
|
51
50
|
|
|
51
|
+
The report opens in your browser when something failed (`open: 'always'` to open every time, `'never'` to stay quiet). It is at `reporting-labs/index.html`.
|
|
52
|
+
|
|
52
53
|
Done. Everything below is optional.
|
|
53
54
|
|
|
54
55
|
> **In a hurry?** Skip the config file and pass options inline: `reporter: [['reporting-labs', { title: 'My app' }]]`.
|
|
55
56
|
|
|
57
|
+
## See everything the report can do
|
|
58
|
+
|
|
59
|
+
Every card and tab is switched on. What you see depends on what your tests give it:
|
|
60
|
+
|
|
61
|
+
1. **Add `meta()` to your tests** and the report ranks failures by priority, groups them by owner and feature, and links to your stories. See [the helpers](#add-details-to-your-tests-3-small-helpers).
|
|
62
|
+
2. **Run the suite twice** and the Trend chart, "new vs known" failures, flaky dots and "Got slower" appear. History is kept in `reporting-labs.history.json`.
|
|
63
|
+
3. **Turn on Playwright's `screenshot`, `video` and `trace`** in `playwright.config.ts` and they show up on every failed test.
|
|
64
|
+
4. **Have more than one Playwright project** (say chromium and webkit) and you get a feature × project heatmap.
|
|
65
|
+
|
|
66
|
+
The report tells you about these itself: a card that has nothing to show yet explains what to do.
|
|
67
|
+
|
|
56
68
|
## Add details to your tests (3 small helpers)
|
|
57
69
|
|
|
58
70
|
The report already shows steps, screenshots, videos, traces and errors on its own. Three small helpers add the rest. Import them from `reporting-labs` and call them inside a test.
|
|
@@ -73,6 +85,7 @@ One line per test. With this the report can rank failures by priority, group the
|
|
|
73
85
|
- Known keys: `priority`, `severity`, `owner`, `feature`, `epic`, `story`, `issue`, `component`, `team`. Any other key you pass is shown too.
|
|
74
86
|
- Your Playwright tags like `@sanity` or `@regression` stay as they are and still show on the test.
|
|
75
87
|
- To make story and epic keys clickable, set `links` in the config: `links: { story: 'https://yourteam.atlassian.net/browse/{id}' }`.
|
|
88
|
+
- Forgot one? After every run the console lists the tests that have no `meta()`, with file and line. Turn it off with `warnMissingMeta: false`.
|
|
76
89
|
- `priority`, `severity`, `feature` and `owner` each get a tab in the Breakdown chart and a filter on the Tests page. Want the same for your own key, say `meta({ team: 'web' })`? Add it to `dimensions` in the config: `dimensions: ['priority', 'severity', 'feature', 'owner', 'team']`.
|
|
77
90
|
|
|
78
91
|
### `log()`: a line in the report
|
|
@@ -287,6 +300,8 @@ Every option is optional. `npx reporting-labs init` writes them all, with commen
|
|
|
287
300
|
| `embedVideos` | `false` | Videos inside the HTML too (bigger file, no folder issues) |
|
|
288
301
|
| `embedFonts` | `true` | Bundle the fonts (~140 KB) so it looks the same offline |
|
|
289
302
|
| `announce` | `true` | Print the report path after the run |
|
|
303
|
+
| `open` | `'on-failure'` | Open the report in the browser after the run: `'on-failure'`, `'always'` or `'never'`. Never opens in CI |
|
|
304
|
+
| `warnMissingMeta` | `true` | After the run, list the tests that have no `meta()` in the console, so nobody on the team forgets |
|
|
290
305
|
|
|
291
306
|
If your reporter list differs between CI and local, add the same line to both:
|
|
292
307
|
|
package/bin/config-template.txt
CHANGED
|
@@ -3,6 +3,9 @@ import type { ReportingLabsOptions } from 'reporting-labs';
|
|
|
3
3
|
|
|
4
4
|
// reportingLabs configuration.
|
|
5
5
|
// Every option is optional. Lines that start with // show the default; uncomment and change what you need.
|
|
6
|
+
// All cards and tabs are on by default. What the report shows depends on your tests: add meta() for
|
|
7
|
+
// priorities and owners, run the suite twice for trends and flaky detection, and keep Playwright's
|
|
8
|
+
// screenshot / video / trace settings on. A card with nothing to show yet tells you what to do.
|
|
6
9
|
// Docs: https://github.com/naveenautomationlabs/reporting-labs#options
|
|
7
10
|
|
|
8
11
|
const config: ReportingLabsOptions = {
|
|
@@ -32,6 +35,8 @@ const config: ReportingLabsOptions = {
|
|
|
32
35
|
// embedLimit: 2 * 1024 * 1024, // attachments bigger than this (bytes) are copied as files
|
|
33
36
|
// embedVideos: false, // true = videos inside the HTML too (bigger file, no folder issues)
|
|
34
37
|
// announce: true, // print the report path after the run
|
|
38
|
+
// open: 'on-failure', // open the report in the browser: 'on-failure' | 'always' | 'never'; never in CI
|
|
39
|
+
// warnMissingMeta: true, // after the run, list tests that have no meta() in the console
|
|
35
40
|
|
|
36
41
|
// ── Test details ─────────────────────────────────────────────────────────────
|
|
37
42
|
// Values come from meta({ priority, severity, owner, feature, epic, story, ... }) in your tests.
|
package/dist/reporter.d.ts
CHANGED
|
@@ -20,6 +20,10 @@ export default class ReportingLabsReporter implements Reporter {
|
|
|
20
20
|
private pushOutput;
|
|
21
21
|
onBegin(config: FullConfig, suite: Suite): void;
|
|
22
22
|
onEnd(result: FullResult): Promise<void>;
|
|
23
|
+
/** One short list of tests that carry no meta() at all, so the whole team keeps the report useful. */
|
|
24
|
+
private printMissingMeta;
|
|
25
|
+
/** Open the report in the default browser, like Playwright's HTML reporter. Never in CI. */
|
|
26
|
+
private maybeOpen;
|
|
23
27
|
/** Videos and traces are finalized asynchronously by the runner; wait until every file-backed attachment stops growing. */
|
|
24
28
|
private settleAttachmentFiles;
|
|
25
29
|
/** Runtime facts for the Environment card: Playwright, Node, OS, browsers, CI job, git commit. */
|
package/dist/reporter.js
CHANGED
|
@@ -204,8 +204,46 @@ class ReportingLabsReporter {
|
|
|
204
204
|
fs.writeFileSync(file, (0, template_1.renderHtml)(data), 'utf8');
|
|
205
205
|
if (this.options.announce !== false) {
|
|
206
206
|
const rel = path.relative(process.cwd(), file);
|
|
207
|
-
console.log(`\n reporting-labs: report written to ${rel}
|
|
207
|
+
console.log(`\n reporting-labs: report written to ${rel}`);
|
|
208
|
+
this.printMissingMeta(tests);
|
|
209
|
+
console.log('');
|
|
208
210
|
}
|
|
211
|
+
this.maybeOpen(file, result);
|
|
212
|
+
}
|
|
213
|
+
/** One short list of tests that carry no meta() at all, so the whole team keeps the report useful. */
|
|
214
|
+
printMissingMeta(tests) {
|
|
215
|
+
if (this.options.warnMissingMeta === false)
|
|
216
|
+
return;
|
|
217
|
+
const seen = new Set();
|
|
218
|
+
const missing = tests.filter(t => Object.keys(t.meta).length === 0 && !seen.has(t.file + ':' + t.line) && seen.add(t.file + ':' + t.line));
|
|
219
|
+
if (!missing.length)
|
|
220
|
+
return;
|
|
221
|
+
const total = new Set(tests.map(t => t.file + ':' + t.line)).size;
|
|
222
|
+
console.log(` reporting-labs: ${missing.length} of ${total} tests have no meta()`);
|
|
223
|
+
const show = missing.slice(0, 15);
|
|
224
|
+
const w = Math.max(...show.map(t => (t.file + ':' + t.line).length));
|
|
225
|
+
for (const t of show)
|
|
226
|
+
console.log(` ${(t.file + ':' + t.line).padEnd(w)} ${t.title}`);
|
|
227
|
+
if (missing.length > show.length)
|
|
228
|
+
console.log(` … and ${missing.length - show.length} more`);
|
|
229
|
+
console.log(" Add meta({ priority: 'P1', owner: 'name', feature: 'area' }) at the top of the test. Set warnMissingMeta: false to hide this.");
|
|
230
|
+
}
|
|
231
|
+
/** Open the report in the default browser, like Playwright's HTML reporter. Never in CI. */
|
|
232
|
+
maybeOpen(file, result) {
|
|
233
|
+
const mode = this.options.open ?? 'on-failure';
|
|
234
|
+
if (mode === 'never' || process.env.CI)
|
|
235
|
+
return;
|
|
236
|
+
if (mode === 'on-failure' && result.status === 'passed')
|
|
237
|
+
return;
|
|
238
|
+
try {
|
|
239
|
+
const cmd = process.platform === 'darwin' ? ['open', [file]]
|
|
240
|
+
: process.platform === 'win32' ? ['cmd', ['/c', 'start', '', file]]
|
|
241
|
+
: ['xdg-open', [file]];
|
|
242
|
+
const child = (0, child_process_1.spawn)(cmd[0], [...cmd[1]], { detached: true, stdio: 'ignore' });
|
|
243
|
+
child.on('error', () => { });
|
|
244
|
+
child.unref();
|
|
245
|
+
}
|
|
246
|
+
catch { /* ignore */ }
|
|
209
247
|
}
|
|
210
248
|
// ---- helpers -------------------------------------------------------------
|
|
211
249
|
/** Videos and traces are finalized asynchronously by the runner; wait until every file-backed attachment stops growing. */
|
package/dist/template.js
CHANGED
|
@@ -268,6 +268,7 @@ a{color:var(--accent)}
|
|
|
268
268
|
.item .tt .n{font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
269
269
|
.item .d{font:11px var(--mono);color:var(--ink-3);margin-top:3px}
|
|
270
270
|
.empty{padding:40px 20px;text-align:center;color:var(--ink-3)}
|
|
271
|
+
.nudge{font-size:var(--fs-s);color:var(--ink-2);background:var(--surface-2);border:1px dashed var(--line);border-radius:var(--radius);padding:10px 12px;margin-bottom:10px;line-height:1.5} .nudge code{font-family:var(--mono);font-size:12px} .nudge b{color:var(--ink)}
|
|
271
272
|
|
|
272
273
|
/* ---------- detail ---------- */
|
|
273
274
|
.detail{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:22px;min-width:0}
|
|
@@ -872,6 +873,7 @@ function summary(){
|
|
|
872
873
|
if(W.skipped!==false) { const sc=skippedCard(); if(sc) g.push(sc); }
|
|
873
874
|
if(W.environment!==false) { const ec=envCard(); if(ec) g.push(ec); }
|
|
874
875
|
if(data.history.length>1) g.push(h('div',{class:'card w12'}, h('h2',{},'Trend', h('span',{class:'hint'},'last '+data.history.length+' runs')), trend()));
|
|
876
|
+
else if(data.history.length===1) g.push(h('div',{class:'card w12'}, h('h2',{},'Trend', h('span',{class:'hint'},'from the second run')), h('div',{class:'nudge'}, h('b',{},'First run recorded.'),' Run the suite once more and this card shows the pass-rate trend, and every failure gets "new this run" or "failing since #…", last-10-runs dots, a Flakiest tests card and a Got slower tab. History lives in ',h('code',{},data.historyFile||'reporting-labs.history.json'),', commit it or cache it in CI.')));
|
|
875
877
|
const ge=data.globalErrors||[], go=data.globalOutput||[];
|
|
876
878
|
if(ge.length||go.some(x=>x.stream==='err')) g.unshift(h('div',{class:'card w12 fail-rail'}, h('h2',{}, ge.length? ge.length+' error'+(ge.length>1?'s':'')+' outside tests' : 'Output outside tests', h('span',{class:'hint'},'spec files that failed to load, global setup, worker crashes')),
|
|
877
879
|
...ge.map(errorView), go.length? h('details',{class:'errfull'}, h('summary',{},'Console output outside tests ('+go.length+' chunks)'), h('pre',{class:'txt'}, go.map(x=>(x.stream==='err'?'[stderr] ':'')+x.text).join(''))) : null));
|
|
@@ -1137,10 +1139,11 @@ function breakdown(){
|
|
|
1137
1139
|
if(data.options.widgets.tags&&data.tests.some(t=>t.tags.length)) tabs.push(['tags','Tags',tagsChart]);
|
|
1138
1140
|
if(data.projects.length>1&&DIMS.length) tabs.push(['heat','Heatmap',heatmap]);
|
|
1139
1141
|
if(!tabs.length) return h('div',{class:'empty'},'Add meta({ priority, severity, owner, feature }) to your tests to see breakdowns here.');
|
|
1142
|
+
const nudge=!DIMS.length? h('div',{class:'nudge'}, h('b',{},'Tip:'),' add ',h('code',{},"meta({ priority: 'P1', severity: 'major', owner: 'priya', feature: 'checkout' })"),' at the top of a test and this card gains Priority, Severity, Feature and Owner tabs, the failures get ranked, and owners get their own rollup.') : null;
|
|
1140
1143
|
let cur=tabs[0][0]; const bar=h('div',{class:'bk-tabs'}), body=h('div',{});
|
|
1141
1144
|
const render=()=>{ body.innerHTML=''; body.append(tabs.find(t=>t[0]===cur)[2]()); bar.querySelectorAll('button').forEach(b=>b.setAttribute('aria-selected',b.dataset.k===cur)); };
|
|
1142
1145
|
for(const [k,l] of tabs) bar.append(h('button',{'data-k':k,onclick:()=>{cur=k;render();}},l));
|
|
1143
|
-
render(); return h('div',{}, bar, body);
|
|
1146
|
+
render(); return h('div',{}, nudge, bar, body);
|
|
1144
1147
|
}
|
|
1145
1148
|
function errorSignature(msg){
|
|
1146
1149
|
return (msg||'').split('\n')[0].replace(/\d+(\.\d+)?(ms|s)\b/g,'N').replace(/\b\d{2,}\b/g,'N').replace(/["'][^"']{0,60}["']/g,'"…"').replace(/\s+/g,' ').trim().slice(0,160);
|
package/dist/types.d.ts
CHANGED
|
@@ -58,6 +58,10 @@ export interface ReportingLabsOptions {
|
|
|
58
58
|
embedFonts?: boolean;
|
|
59
59
|
/** Print report path to the console after the run. Default: true */
|
|
60
60
|
announce?: boolean;
|
|
61
|
+
/** After the run, list the tests that have no meta() in the console. Default: true */
|
|
62
|
+
warnMissingMeta?: boolean;
|
|
63
|
+
/** Open the report in the browser after the run: 'on-failure' (default), 'always' or 'never'. Never opens in CI. */
|
|
64
|
+
open?: 'on-failure' | 'always' | 'never';
|
|
61
65
|
/** Company / project block in the header. */
|
|
62
66
|
project?: {
|
|
63
67
|
name?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reporting-labs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "reportingLabs – beautiful, customizable single-file HTML test reports. One line of config. Playwright adapter included, more runners on the way.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"test-report",
|