donobu 5.45.0 → 5.46.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.
@@ -1597,7 +1597,9 @@ function renderHtml(report, triage, outputDir) {
1597
1597
  const testId = testIds[ti];
1598
1598
  const hasMultipleResults = test.results.length > 1;
1599
1599
  const lastResult = test.results.at(-1);
1600
- const displayFileName = test.file.split('/').pop() ?? test.file;
1600
+ // Path is already relative to rootDir (see buildReport.ts), so it's safe
1601
+ // to display directly — no absolute paths leak through.
1602
+ const displayFilePath = test.file;
1601
1603
  let detailsHtml = '';
1602
1604
  // 0. Skip reason — surface the description and call site from
1603
1605
  // test.skip()/test.fixme() so a skipped test explains itself.
@@ -1678,12 +1680,19 @@ function renderHtml(report, triage, outputDir) {
1678
1680
  ? `<div class="flow-id-detail"><span class="detail-label">Flow ID</span><span class="flow-id-value">${esc(test.flowId)}<button class="copy-flow-id" data-flow-id="${esc(test.flowId)}" title="Copy flow ID"><svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button></span></div>`
1679
1681
  : '';
1680
1682
  testSectionsHtml += `
1681
- <div class="test-card ${sc.label.toLowerCase().replace(/ /g, '')} ${expandableClass}" id="${testId}" data-status="${test.status}" data-file="${esc(test.file)}" data-search="${esc((displayFileName + ' ' + test.specTitle).toLowerCase())}" data-tags="${esc(JSON.stringify(test.tags))}"${test.plan ? ` data-reason="${esc(test.plan.plan.failureReason)}"` : ''} ${hasDetails ? `data-detail="${testId}"` : ''}>
1683
+ <div class="test-card ${sc.label.toLowerCase().replace(/ /g, '')} ${expandableClass}" id="${testId}" data-status="${test.status}" data-file="${esc(test.file)}" data-search="${esc((displayFilePath + ' ' + test.specTitle).toLowerCase())}" data-tags="${esc(JSON.stringify(test.tags))}"${test.plan ? ` data-reason="${esc(test.plan.plan.failureReason)}"` : ''} ${hasDetails ? `data-detail="${testId}"` : ''}>
1682
1684
  <div class="test-summary">
1683
1685
  ${chevron}
1684
1686
  <span class="status-dot" style="background:${sc.color}" title="${sc.label}"></span>
1685
1687
  <div class="test-name-group">
1686
- <span class="test-name"><span class="test-file">${esc(displayFileName)}</span> (${esc(test.specTitle)})</span>
1688
+ <div class="test-file-line">
1689
+ <span class="test-file">${esc(displayFilePath)}</span>
1690
+ <button class="copy-text" data-copy-text="${esc(displayFilePath)}" title="Copy file name"><svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button>
1691
+ </div>
1692
+ <div class="test-title-line">
1693
+ <span class="test-title">${esc(test.specTitle)}</span>
1694
+ <button class="copy-text" data-copy-text="${esc(test.specTitle)}" title="Copy test name"><svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button>
1695
+ </div>
1687
1696
  </div>
1688
1697
  ${test.plan ? `<span class="inline-reason" style="color:${reasonCfg(test.plan.plan.failureReason).color}" title="${esc(test.plan.plan.failureReason)}">${esc(reasonCfg(test.plan.plan.failureReason).label)}</span>` : ''}
1689
1698
  ${test.tags.map((t) => `<span class="test-tag">${esc(t)}</span>`).join('')}
@@ -1817,9 +1826,15 @@ body::before{content:'';position:fixed;top:-750px;left:50%;transform:translateX(
1817
1826
  .chevron-spacer{width:18px;flex-shrink:0}
1818
1827
  .test-card.expanded .chevron{transform:rotate(90deg)}
1819
1828
  .status-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
1820
- .test-file{color:var(--text);font-weight:600}
1821
1829
  .test-name-group{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
1822
- .test-name{font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1830
+ .test-file-line,.test-title-line{display:flex;align-items:center;gap:6px;min-width:0}
1831
+ .test-file{color:var(--text-muted);font-family:var(--mono);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1832
+ .test-title{color:var(--text);font-weight:500;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1833
+ .copy-text{background:transparent;border:none;border-radius:4px;cursor:pointer;padding:2px;display:flex;align-items:center;justify-content:center;color:var(--text-dim);opacity:0;transition:opacity .15s,background .15s,color .15s;flex-shrink:0}
1834
+ .test-summary:hover .copy-text,.copy-text:focus-visible{opacity:1}
1835
+ .copy-text:hover{background:var(--overlay-light-active);color:var(--text)}
1836
+ .copy-text svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
1837
+ .copy-text .check-icon{color:#22c55e;opacity:1}
1823
1838
  .flow-id{font-size:11px;color:var(--text-dim);opacity:.6;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:flex;align-items:center;gap:4px}
1824
1839
  .copy-flow-id{background:var(--overlay-light-hover);border:none;border-radius:4px;cursor:pointer;padding:3px;display:flex;align-items:center;justify-content:center;color:var(--text-dim);transition:background .15s,color .15s;flex-shrink:0}
1825
1840
  .copy-flow-id:hover{background:var(--overlay-light-active);color:var(--text)}
@@ -2439,7 +2454,9 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
2439
2454
  if(el){navigator.clipboard.writeText(el.textContent);var s=copyBtn.innerHTML;copyBtn.innerHTML='<svg class="check-icon" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>';setTimeout(function(){copyBtn.innerHTML=s},2000)}
2440
2455
  return;
2441
2456
  }
2442
- // Copy buttons (flow ID + JSON)
2457
+ // Copy buttons (flow ID + JSON + inline text via data-copy-text)
2458
+ var copyTextBtn=e.target.closest('.copy-text[data-copy-text]');
2459
+ if(copyTextBtn){e.stopPropagation();e.preventDefault();navigator.clipboard.writeText(copyTextBtn.getAttribute('data-copy-text'));var copyTextSvg=copyTextBtn.innerHTML;copyTextBtn.innerHTML='<svg class="check-icon" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>';setTimeout(function(){copyTextBtn.innerHTML=copyTextSvg},2000);return}
2443
2460
  var flowBtn=e.target.closest('.copy-flow-id');
2444
2461
  if(flowBtn){e.stopPropagation();navigator.clipboard.writeText(flowBtn.getAttribute('data-flow-id'));var copySvg=flowBtn.innerHTML;flowBtn.innerHTML='<svg class="check-icon" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>';setTimeout(function(){flowBtn.innerHTML=copySvg},2000);return}
2445
2462
  var jsonBtn=e.target.closest('.copy-json');
@@ -1597,7 +1597,9 @@ function renderHtml(report, triage, outputDir) {
1597
1597
  const testId = testIds[ti];
1598
1598
  const hasMultipleResults = test.results.length > 1;
1599
1599
  const lastResult = test.results.at(-1);
1600
- const displayFileName = test.file.split('/').pop() ?? test.file;
1600
+ // Path is already relative to rootDir (see buildReport.ts), so it's safe
1601
+ // to display directly — no absolute paths leak through.
1602
+ const displayFilePath = test.file;
1601
1603
  let detailsHtml = '';
1602
1604
  // 0. Skip reason — surface the description and call site from
1603
1605
  // test.skip()/test.fixme() so a skipped test explains itself.
@@ -1678,12 +1680,19 @@ function renderHtml(report, triage, outputDir) {
1678
1680
  ? `<div class="flow-id-detail"><span class="detail-label">Flow ID</span><span class="flow-id-value">${esc(test.flowId)}<button class="copy-flow-id" data-flow-id="${esc(test.flowId)}" title="Copy flow ID"><svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button></span></div>`
1679
1681
  : '';
1680
1682
  testSectionsHtml += `
1681
- <div class="test-card ${sc.label.toLowerCase().replace(/ /g, '')} ${expandableClass}" id="${testId}" data-status="${test.status}" data-file="${esc(test.file)}" data-search="${esc((displayFileName + ' ' + test.specTitle).toLowerCase())}" data-tags="${esc(JSON.stringify(test.tags))}"${test.plan ? ` data-reason="${esc(test.plan.plan.failureReason)}"` : ''} ${hasDetails ? `data-detail="${testId}"` : ''}>
1683
+ <div class="test-card ${sc.label.toLowerCase().replace(/ /g, '')} ${expandableClass}" id="${testId}" data-status="${test.status}" data-file="${esc(test.file)}" data-search="${esc((displayFilePath + ' ' + test.specTitle).toLowerCase())}" data-tags="${esc(JSON.stringify(test.tags))}"${test.plan ? ` data-reason="${esc(test.plan.plan.failureReason)}"` : ''} ${hasDetails ? `data-detail="${testId}"` : ''}>
1682
1684
  <div class="test-summary">
1683
1685
  ${chevron}
1684
1686
  <span class="status-dot" style="background:${sc.color}" title="${sc.label}"></span>
1685
1687
  <div class="test-name-group">
1686
- <span class="test-name"><span class="test-file">${esc(displayFileName)}</span> (${esc(test.specTitle)})</span>
1688
+ <div class="test-file-line">
1689
+ <span class="test-file">${esc(displayFilePath)}</span>
1690
+ <button class="copy-text" data-copy-text="${esc(displayFilePath)}" title="Copy file name"><svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button>
1691
+ </div>
1692
+ <div class="test-title-line">
1693
+ <span class="test-title">${esc(test.specTitle)}</span>
1694
+ <button class="copy-text" data-copy-text="${esc(test.specTitle)}" title="Copy test name"><svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg></button>
1695
+ </div>
1687
1696
  </div>
1688
1697
  ${test.plan ? `<span class="inline-reason" style="color:${reasonCfg(test.plan.plan.failureReason).color}" title="${esc(test.plan.plan.failureReason)}">${esc(reasonCfg(test.plan.plan.failureReason).label)}</span>` : ''}
1689
1698
  ${test.tags.map((t) => `<span class="test-tag">${esc(t)}</span>`).join('')}
@@ -1817,9 +1826,15 @@ body::before{content:'';position:fixed;top:-750px;left:50%;transform:translateX(
1817
1826
  .chevron-spacer{width:18px;flex-shrink:0}
1818
1827
  .test-card.expanded .chevron{transform:rotate(90deg)}
1819
1828
  .status-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
1820
- .test-file{color:var(--text);font-weight:600}
1821
1829
  .test-name-group{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
1822
- .test-name{font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1830
+ .test-file-line,.test-title-line{display:flex;align-items:center;gap:6px;min-width:0}
1831
+ .test-file{color:var(--text-muted);font-family:var(--mono);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1832
+ .test-title{color:var(--text);font-weight:500;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1833
+ .copy-text{background:transparent;border:none;border-radius:4px;cursor:pointer;padding:2px;display:flex;align-items:center;justify-content:center;color:var(--text-dim);opacity:0;transition:opacity .15s,background .15s,color .15s;flex-shrink:0}
1834
+ .test-summary:hover .copy-text,.copy-text:focus-visible{opacity:1}
1835
+ .copy-text:hover{background:var(--overlay-light-active);color:var(--text)}
1836
+ .copy-text svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
1837
+ .copy-text .check-icon{color:#22c55e;opacity:1}
1823
1838
  .flow-id{font-size:11px;color:var(--text-dim);opacity:.6;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:flex;align-items:center;gap:4px}
1824
1839
  .copy-flow-id{background:var(--overlay-light-hover);border:none;border-radius:4px;cursor:pointer;padding:3px;display:flex;align-items:center;justify-content:center;color:var(--text-dim);transition:background .15s,color .15s;flex-shrink:0}
1825
1840
  .copy-flow-id:hover{background:var(--overlay-light-active);color:var(--text)}
@@ -2439,7 +2454,9 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
2439
2454
  if(el){navigator.clipboard.writeText(el.textContent);var s=copyBtn.innerHTML;copyBtn.innerHTML='<svg class="check-icon" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>';setTimeout(function(){copyBtn.innerHTML=s},2000)}
2440
2455
  return;
2441
2456
  }
2442
- // Copy buttons (flow ID + JSON)
2457
+ // Copy buttons (flow ID + JSON + inline text via data-copy-text)
2458
+ var copyTextBtn=e.target.closest('.copy-text[data-copy-text]');
2459
+ if(copyTextBtn){e.stopPropagation();e.preventDefault();navigator.clipboard.writeText(copyTextBtn.getAttribute('data-copy-text'));var copyTextSvg=copyTextBtn.innerHTML;copyTextBtn.innerHTML='<svg class="check-icon" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>';setTimeout(function(){copyTextBtn.innerHTML=copyTextSvg},2000);return}
2443
2460
  var flowBtn=e.target.closest('.copy-flow-id');
2444
2461
  if(flowBtn){e.stopPropagation();navigator.clipboard.writeText(flowBtn.getAttribute('data-flow-id'));var copySvg=flowBtn.innerHTML;flowBtn.innerHTML='<svg class="check-icon" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>';setTimeout(function(){flowBtn.innerHTML=copySvg},2000);return}
2445
2462
  var jsonBtn=e.target.closest('.copy-json');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "donobu",
3
- "version": "5.45.0",
3
+ "version": "5.46.0",
4
4
  "description": "Create browser automations with an LLM agent and replay them as Playwright scripts.",
5
5
  "main": "dist/main.js",
6
6
  "module": "dist/esm/main.js",