reporting-labs 0.6.3 → 0.6.5
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 +4 -0
- package/dist/template.html +7 -6
- package/dist/template.js +7 -6
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -604,6 +604,10 @@ Your Slack step can then read `results.json` for pass / fail counts and top fail
|
|
|
604
604
|
- **Print.** A print stylesheet is included, so "Save as PDF" works.
|
|
605
605
|
- **Themes.** Light and dark follow the OS. The toggle in the header remembers your choice.
|
|
606
606
|
|
|
607
|
+
## Java teams
|
|
608
|
+
|
|
609
|
+
The same report, from Java: `dev.reportinglabs` on Maven Central, for TestNG and JUnit 5, with zero-code add-ons for Selenium and REST Assured, a one-line add-on for Playwright for Java and a Cucumber JVM plugin (one row per scenario, Given/When/Then as steps). Source: [reporting-labs-java](https://github.com/naveenautomationlabs/reporting-labs-java). Guides: [reportinglabs.dev/get-started/java](https://reportinglabs.dev/get-started/java).
|
|
610
|
+
|
|
607
611
|
## Roadmap
|
|
608
612
|
|
|
609
613
|
- WebdriverIO, Cypress, Jest/Vitest and JUnit XML adapters
|
package/dist/template.html
CHANGED
|
@@ -226,6 +226,7 @@ a{color:var(--accent)}
|
|
|
226
226
|
.step .t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
227
227
|
.step .d{font:11px var(--mono);color:var(--ink-3)}
|
|
228
228
|
.step.bad{color:var(--fail)} .step.bad .t{font-weight:500}
|
|
229
|
+
.step.skip .t,.step.skip .kw,.step.skip .d{color:var(--ink-3);font-style:italic}
|
|
229
230
|
.step .e{font:12px var(--mono);color:var(--fail);padding:2px 0 6px 28px;white-space:pre-wrap}
|
|
230
231
|
li.collapsed>ul{display:none}
|
|
231
232
|
.att{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}
|
|
@@ -1155,7 +1156,7 @@ function errorWhere(e){
|
|
|
1155
1156
|
function errorBody(e){
|
|
1156
1157
|
const msg=e.message||'';
|
|
1157
1158
|
const box=h('div',{class:'err'}, msg, e.stack&&e.stack!==msg? h('details',{}, h('summary',{},'Stack trace'), h('div',{class:'stack'},e.stack)) : null);
|
|
1158
|
-
const ex=msg.match(
|
|
1159
|
+
const ex=msg.match(/^\s*(Expected[^:\n]{0,40}):[ \t]*(.+)$/m), rc=msg.match(/^\s*((?:Received|Actual|But was)[^:\n]{0,40}):[ \t]*(.+)$/m);
|
|
1159
1160
|
if(ex&&rc&&ex[2].trim()&&rc[2].trim()&&ex[2].length<2000&&rc[2].length<2000){
|
|
1160
1161
|
const d=tokenDiff(ex[2].trim(), rc[2].trim());
|
|
1161
1162
|
if(d){ return h('div',{}, h('div',{class:'ediff'},
|
|
@@ -1531,10 +1532,10 @@ function renderDetail(t){
|
|
|
1531
1532
|
}
|
|
1532
1533
|
function stepTree(steps, total){
|
|
1533
1534
|
return h('ul',{class:'steps'}, steps.map(s=>{
|
|
1534
|
-
const bad=!!s.error, kids=s.steps.length>0, pct=total?Math.min(100,s.duration/total*100):0;
|
|
1535
|
+
const bad=!!s.error, skip=s.status==='skipped', kids=s.steps.length>0, pct=total?Math.min(100,s.duration/total*100):0;
|
|
1535
1536
|
const li=h('li',{class:kids&&!hasError(s)?'collapsed':''});
|
|
1536
|
-
const row=h('div',{class:'step'+(bad?' bad':'')},
|
|
1537
|
-
h('span',{class:'tw'}, kids? '▸' : ''), data.bdd?null:h('span',{class:'cat'},s.category), gherkin(s.title), total? h('span',{class:'tb',title:Math.round(pct)+'% of the test'}, h('i',{class:pct>=30?'slow':'',style:'width:'+Math.max(pct,s.duration>0?1.5:0)+'%'})) : null, h('span',{class:'d'},ms(s.duration)));
|
|
1537
|
+
const row=h('div',{class:'step'+(bad?' bad':'')+(skip?' skip':'')},
|
|
1538
|
+
h('span',{class:'tw'}, kids? '▸' : ''), data.bdd?null:h('span',{class:'cat'},s.category), gherkin(s.title), total&&!skip? h('span',{class:'tb',title:Math.round(pct)+'% of the test'}, h('i',{class:pct>=30?'slow':'',style:'width:'+Math.max(pct,s.duration>0?1.5:0)+'%'})) : null, h('span',{class:'d'},skip?'not run':ms(s.duration)));
|
|
1538
1539
|
if(kids){ row.style.cursor='pointer'; row.addEventListener('click',()=>{li.classList.toggle('collapsed'); row.querySelector('.tw').textContent=li.classList.contains('collapsed')?'▸':'▾';}); if(!li.classList.contains('collapsed')) row.querySelector('.tw').textContent='▾'; }
|
|
1539
1540
|
li.append(row); if(bad) li.append(h('div',{class:'e'},s.error)); if(kids) li.append(stepTree(s.steps, total));
|
|
1540
1541
|
return li;
|
|
@@ -1591,9 +1592,9 @@ function compare(set){
|
|
|
1591
1592
|
/* ---- bug report: a ready-to-paste ticket built from the failure ---- */
|
|
1592
1593
|
function bugModel(t){
|
|
1593
1594
|
const r=t.results[t.results.length-1], e=r&&r.errors[0], x=e&&e.explain, msg=e?e.message:'';
|
|
1594
|
-
const ex=msg.match(
|
|
1595
|
+
const ex=msg.match(/^\s*(Expected[^:\n]{0,40}):[ \t]*(.+)$/m), rc=msg.match(/^\s*((?:Received|Actual|But was)[^:\n]{0,40}):[ \t]*(.+)$/m);
|
|
1595
1596
|
const si=sinceInfo(t);
|
|
1596
|
-
const steps=[]; const walk=(list,depth)=>{ for(const st of list){ if(st.category==='hook'||/^Attach "/.test(st.title)||/^Worker Cleanup/.test(st.title)) continue; const user=st.category==='test.step'; if(user||depth===0) steps.push({title:st.title.replace(/^(Given|When|Then|And|But)\s+/,m=>m), failed:!!st.error, user}); if(user&&st.steps.length&&!st.steps.some(c=>c.category==='test.step')) continue; if(st.steps.length) walk(st.steps,depth+1); } };
|
|
1597
|
+
const steps=[]; const walk=(list,depth)=>{ for(const st of list){ if(st.category==='hook'||/^Attach "/.test(st.title)||/^Worker Cleanup/.test(st.title)) continue; const user=st.category==='test.step'; if(user||depth===0) steps.push({title:st.title.replace(/^(Given|When|Then|And|But)\s+/,m=>m)+(st.status==='skipped'?' (not run)':''), failed:!!st.error, user}); if(user&&st.steps.length&&!st.steps.some(c=>c.category==='test.step')) continue; if(st.steps.length) walk(st.steps,depth+1); } };
|
|
1597
1598
|
if(r) walk(r.steps,0);
|
|
1598
1599
|
const userSteps=steps.filter(s=>s.user); const repro=(userSteps.length?userSteps:steps).filter(s=>!/^Expect "/.test(s.title)||s.failed);
|
|
1599
1600
|
const env=[]; if(data.options.project&&data.options.project.name) env.push(['Application', data.options.project.name+(data.options.project.version?' v'+data.options.project.version:'')]);
|
package/dist/template.js
CHANGED
|
@@ -297,6 +297,7 @@ a{color:var(--accent)}
|
|
|
297
297
|
.step .t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
298
298
|
.step .d{font:11px var(--mono);color:var(--ink-3)}
|
|
299
299
|
.step.bad{color:var(--fail)} .step.bad .t{font-weight:500}
|
|
300
|
+
.step.skip .t,.step.skip .kw,.step.skip .d{color:var(--ink-3);font-style:italic}
|
|
300
301
|
.step .e{font:12px var(--mono);color:var(--fail);padding:2px 0 6px 28px;white-space:pre-wrap}
|
|
301
302
|
li.collapsed>ul{display:none}
|
|
302
303
|
.att{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}
|
|
@@ -1221,7 +1222,7 @@ function errorWhere(e){
|
|
|
1221
1222
|
function errorBody(e){
|
|
1222
1223
|
const msg=e.message||'';
|
|
1223
1224
|
const box=h('div',{class:'err'}, msg, e.stack&&e.stack!==msg? h('details',{}, h('summary',{},'Stack trace'), h('div',{class:'stack'},e.stack)) : null);
|
|
1224
|
-
const ex=msg.match(
|
|
1225
|
+
const ex=msg.match(/^\s*(Expected[^:\n]{0,40}):[ \t]*(.+)$/m), rc=msg.match(/^\s*((?:Received|Actual|But was)[^:\n]{0,40}):[ \t]*(.+)$/m);
|
|
1225
1226
|
if(ex&&rc&&ex[2].trim()&&rc[2].trim()&&ex[2].length<2000&&rc[2].length<2000){
|
|
1226
1227
|
const d=tokenDiff(ex[2].trim(), rc[2].trim());
|
|
1227
1228
|
if(d){ return h('div',{}, h('div',{class:'ediff'},
|
|
@@ -1597,10 +1598,10 @@ function renderDetail(t){
|
|
|
1597
1598
|
}
|
|
1598
1599
|
function stepTree(steps, total){
|
|
1599
1600
|
return h('ul',{class:'steps'}, steps.map(s=>{
|
|
1600
|
-
const bad=!!s.error, kids=s.steps.length>0, pct=total?Math.min(100,s.duration/total*100):0;
|
|
1601
|
+
const bad=!!s.error, skip=s.status==='skipped', kids=s.steps.length>0, pct=total?Math.min(100,s.duration/total*100):0;
|
|
1601
1602
|
const li=h('li',{class:kids&&!hasError(s)?'collapsed':''});
|
|
1602
|
-
const row=h('div',{class:'step'+(bad?' bad':'')},
|
|
1603
|
-
h('span',{class:'tw'}, kids? '▸' : ''), data.bdd?null:h('span',{class:'cat'},s.category), gherkin(s.title), total? h('span',{class:'tb',title:Math.round(pct)+'% of the test'}, h('i',{class:pct>=30?'slow':'',style:'width:'+Math.max(pct,s.duration>0?1.5:0)+'%'})) : null, h('span',{class:'d'},ms(s.duration)));
|
|
1603
|
+
const row=h('div',{class:'step'+(bad?' bad':'')+(skip?' skip':'')},
|
|
1604
|
+
h('span',{class:'tw'}, kids? '▸' : ''), data.bdd?null:h('span',{class:'cat'},s.category), gherkin(s.title), total&&!skip? h('span',{class:'tb',title:Math.round(pct)+'% of the test'}, h('i',{class:pct>=30?'slow':'',style:'width:'+Math.max(pct,s.duration>0?1.5:0)+'%'})) : null, h('span',{class:'d'},skip?'not run':ms(s.duration)));
|
|
1604
1605
|
if(kids){ row.style.cursor='pointer'; row.addEventListener('click',()=>{li.classList.toggle('collapsed'); row.querySelector('.tw').textContent=li.classList.contains('collapsed')?'▸':'▾';}); if(!li.classList.contains('collapsed')) row.querySelector('.tw').textContent='▾'; }
|
|
1605
1606
|
li.append(row); if(bad) li.append(h('div',{class:'e'},s.error)); if(kids) li.append(stepTree(s.steps, total));
|
|
1606
1607
|
return li;
|
|
@@ -1657,9 +1658,9 @@ function compare(set){
|
|
|
1657
1658
|
/* ---- bug report: a ready-to-paste ticket built from the failure ---- */
|
|
1658
1659
|
function bugModel(t){
|
|
1659
1660
|
const r=t.results[t.results.length-1], e=r&&r.errors[0], x=e&&e.explain, msg=e?e.message:'';
|
|
1660
|
-
const ex=msg.match(
|
|
1661
|
+
const ex=msg.match(/^\s*(Expected[^:\n]{0,40}):[ \t]*(.+)$/m), rc=msg.match(/^\s*((?:Received|Actual|But was)[^:\n]{0,40}):[ \t]*(.+)$/m);
|
|
1661
1662
|
const si=sinceInfo(t);
|
|
1662
|
-
const steps=[]; const walk=(list,depth)=>{ for(const st of list){ if(st.category==='hook'||/^Attach "/.test(st.title)||/^Worker Cleanup/.test(st.title)) continue; const user=st.category==='test.step'; if(user||depth===0) steps.push({title:st.title.replace(/^(Given|When|Then|And|But)\s+/,m=>m), failed:!!st.error, user}); if(user&&st.steps.length&&!st.steps.some(c=>c.category==='test.step')) continue; if(st.steps.length) walk(st.steps,depth+1); } };
|
|
1663
|
+
const steps=[]; const walk=(list,depth)=>{ for(const st of list){ if(st.category==='hook'||/^Attach "/.test(st.title)||/^Worker Cleanup/.test(st.title)) continue; const user=st.category==='test.step'; if(user||depth===0) steps.push({title:st.title.replace(/^(Given|When|Then|And|But)\s+/,m=>m)+(st.status==='skipped'?' (not run)':''), failed:!!st.error, user}); if(user&&st.steps.length&&!st.steps.some(c=>c.category==='test.step')) continue; if(st.steps.length) walk(st.steps,depth+1); } };
|
|
1663
1664
|
if(r) walk(r.steps,0);
|
|
1664
1665
|
const userSteps=steps.filter(s=>s.user); const repro=(userSteps.length?userSteps:steps).filter(s=>!/^Expect "/.test(s.title)||s.failed);
|
|
1665
1666
|
const env=[]; if(data.options.project&&data.options.project.name) env.push(['Application', data.options.project.name+(data.options.project.version?' v'+data.options.project.version:'')]);
|
package/dist/types.d.ts
CHANGED
|
@@ -196,6 +196,8 @@ export interface StepData {
|
|
|
196
196
|
category: string;
|
|
197
197
|
duration: number;
|
|
198
198
|
error?: string;
|
|
199
|
+
/** 'skipped' when the runner never executed it (a Cucumber step after a failed one) */
|
|
200
|
+
status?: 'skipped';
|
|
199
201
|
steps: StepData[];
|
|
200
202
|
}
|
|
201
203
|
export interface AttachmentData {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reporting-labs",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
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",
|