donobu 5.43.2 → 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.
- package/dist/esm/reporter/render.js +128 -25
- package/dist/reporter/render.js +128 -25
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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-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
|
-
<
|
|
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('')}
|
|
@@ -1769,6 +1778,17 @@ body::before{content:'';position:fixed;top:-750px;left:50%;transform:translateX(
|
|
|
1769
1778
|
.stat-pill.active{background:var(--accent);border-color:var(--accent);color:#fff}
|
|
1770
1779
|
.stat-pill.active .pill-count{background:rgba(255,255,255,.25);color:#fff}
|
|
1771
1780
|
.pill-count{font-size:11px;font-weight:700;background:var(--overlay-light-active);color:var(--text-dim);padding:1px 7px;border-radius:calc(var(--radius) - 2px);min-width:20px;text-align:center;transition:all .2s}
|
|
1781
|
+
/* Substring search across test filename + spec title. Lives in the same row
|
|
1782
|
+
* as the stat pills and tag/diagnosis filter. */
|
|
1783
|
+
.filter-search-wrap{position:relative;display:inline-flex;align-items:center;flex-shrink:0}
|
|
1784
|
+
.filter-search-icon{position:absolute;left:8px;width:14px;height:14px;color:var(--text-muted);fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;pointer-events:none}
|
|
1785
|
+
.filter-search{background:var(--surface);border:1px solid var(--border);color:var(--text);font:inherit;font-size:12px;height:28px;padding:0 10px 0 28px;border-radius:var(--radius);width:200px;outline:none;transition:border-color .15s,background .15s}
|
|
1786
|
+
.filter-search::placeholder{color:var(--text-dim)}
|
|
1787
|
+
.filter-search:hover{border-color:var(--text-dim)}
|
|
1788
|
+
.filter-search:focus{border-color:var(--accent);background:var(--surface-raised)}
|
|
1789
|
+
/* Hide the WebKit search clear "x" — Clear Filters wipes it via the same UI. */
|
|
1790
|
+
.filter-search::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
|
|
1791
|
+
|
|
1772
1792
|
.clear-filter{background:var(--surface);border:1px solid var(--border);color:var(--text-muted);padding:6px 14px;border-radius:var(--radius);cursor:pointer;font-size:12px;font-weight:500;font-family:inherit;display:none;align-items:center;gap:5px;flex-shrink:0;transition:all .2s}
|
|
1773
1793
|
.clear-filter:hover{background:var(--surface-raised);border-color:var(--text-dim);color:var(--text)}
|
|
1774
1794
|
.clear-filter.visible{display:flex}
|
|
@@ -1806,9 +1826,15 @@ body::before{content:'';position:fixed;top:-750px;left:50%;transform:translateX(
|
|
|
1806
1826
|
.chevron-spacer{width:18px;flex-shrink:0}
|
|
1807
1827
|
.test-card.expanded .chevron{transform:rotate(90deg)}
|
|
1808
1828
|
.status-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
|
|
1809
|
-
.test-file{color:var(--text);font-weight:600}
|
|
1810
1829
|
.test-name-group{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
|
|
1811
|
-
.test-
|
|
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}
|
|
1812
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}
|
|
1813
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}
|
|
1814
1840
|
.copy-flow-id:hover{background:var(--overlay-light-active);color:var(--text)}
|
|
@@ -2131,6 +2157,10 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2131
2157
|
<div class="test-bar">${testBarHtml}</div>
|
|
2132
2158
|
<div class="summary-stats">
|
|
2133
2159
|
<div class="stat-pills">${statPillsHtml}</div>
|
|
2160
|
+
<label class="filter-search-wrap" title="Search test titles">
|
|
2161
|
+
<svg class="filter-search-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
|
|
2162
|
+
<input type="search" class="filter-search" data-filter-search placeholder="Search tests…" autocomplete="off" spellcheck="false" />
|
|
2163
|
+
</label>
|
|
2134
2164
|
<div class="tag-filter-controls" data-tag-filter-controls hidden>
|
|
2135
2165
|
<div class="tag-filter-trigger-wrap">
|
|
2136
2166
|
<button class="add-tag-filter" data-add-tag-filter title="Filter by tag or diagnosis"><span class="add-tag-plus">+</span> Filter</button>
|
|
@@ -2165,15 +2195,43 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2165
2195
|
var activeStatus=null;
|
|
2166
2196
|
var activeTags=new Set();
|
|
2167
2197
|
var activeReasons=new Set();
|
|
2198
|
+
var activeSearch=''; // lowercase substring match against data-search
|
|
2168
2199
|
var allTags=[];
|
|
2169
2200
|
var allReasons=[]; // ordered list of REASON keys present in the report
|
|
2170
2201
|
var REASON_LABELS=${JSON.stringify(REASON_LABELS)};
|
|
2171
2202
|
|
|
2172
2203
|
function cardTags(card){var raw=card.getAttribute('data-tags');if(!raw)return [];try{var v=JSON.parse(raw);return Array.isArray(v)?v:[]}catch(_){return []}}
|
|
2173
|
-
|
|
2204
|
+
|
|
2205
|
+
// Faceted-search counts. Each filter option's badge shows "how many tests
|
|
2206
|
+
// would this option contribute given the rest of the filters." The semantics
|
|
2207
|
+
// per dimension match how clicking interacts:
|
|
2208
|
+
// - Status pills (single-select replace): ignore current activeStatus.
|
|
2209
|
+
// - Tag menu items (multi-select AND): use ALL current filters.
|
|
2210
|
+
// - Reason menu items (multi-select OR): ignore current activeReasons.
|
|
2211
|
+
// Search is free-form and not counted.
|
|
2212
|
+
function cardsMatching(ignoreStatus,ignoreTags,ignoreReasons){
|
|
2213
|
+
var out=[];
|
|
2214
|
+
document.querySelectorAll('.test-card').forEach(function(card){
|
|
2215
|
+
var statusOk=ignoreStatus||activeStatus===null||card.getAttribute('data-status')===activeStatus;
|
|
2216
|
+
var tagsOk=true;
|
|
2217
|
+
if(!ignoreTags&&activeTags.size>0){
|
|
2218
|
+
var t=cardTags(card);
|
|
2219
|
+
activeTags.forEach(function(w){if(t.indexOf(w)===-1)tagsOk=false});
|
|
2220
|
+
}
|
|
2221
|
+
var reasonOk=ignoreReasons||activeReasons.size===0||activeReasons.has(card.getAttribute('data-reason')||'');
|
|
2222
|
+
var searchOk=activeSearch.length===0||(card.getAttribute('data-search')||'').indexOf(activeSearch)!==-1;
|
|
2223
|
+
if(statusOk&&tagsOk&&reasonOk&&searchOk)out.push(card);
|
|
2224
|
+
});
|
|
2225
|
+
return out;
|
|
2226
|
+
}
|
|
2227
|
+
function tagCount(t){
|
|
2228
|
+
var pool=cardsMatching(false,false,false);
|
|
2229
|
+
var n=0;for(var i=0;i<pool.length;i++){if(cardTags(pool[i]).indexOf(t)!==-1)n++}
|
|
2230
|
+
return n;
|
|
2231
|
+
}
|
|
2174
2232
|
|
|
2175
2233
|
function applyFilters(){
|
|
2176
|
-
var anyActive=activeStatus!==null||activeTags.size>0||activeReasons.size>0;
|
|
2234
|
+
var anyActive=activeStatus!==null||activeTags.size>0||activeReasons.size>0||activeSearch.length>0;
|
|
2177
2235
|
document.querySelector('.clear-filter').classList.toggle('visible',anyActive);
|
|
2178
2236
|
var visibleTests=0;
|
|
2179
2237
|
var visibleFiles=Object.create(null);
|
|
@@ -2189,7 +2247,12 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2189
2247
|
var r=card.getAttribute('data-reason')||'';
|
|
2190
2248
|
reasonOk=activeReasons.has(r);
|
|
2191
2249
|
}
|
|
2192
|
-
var
|
|
2250
|
+
var searchOk=true;
|
|
2251
|
+
if(activeSearch.length>0){
|
|
2252
|
+
var hay=card.getAttribute('data-search')||'';
|
|
2253
|
+
searchOk=hay.indexOf(activeSearch)!==-1;
|
|
2254
|
+
}
|
|
2255
|
+
var hide=!(statusOk&&tagsOk&&reasonOk&&searchOk);
|
|
2193
2256
|
card.classList.toggle('hidden-by-filter',hide);
|
|
2194
2257
|
if(!hide){
|
|
2195
2258
|
visibleTests++;
|
|
@@ -2203,6 +2266,11 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2203
2266
|
var card=document.getElementById(block.getAttribute('data-target'));
|
|
2204
2267
|
block.classList.toggle('hidden-by-filter',!!(card&&card.classList.contains('hidden-by-filter')));
|
|
2205
2268
|
});
|
|
2269
|
+
// Faceted-search live counts: status pills, and the tag/diagnosis menu
|
|
2270
|
+
// (refreshed if currently open) all reflect "given the other filters,
|
|
2271
|
+
// how many tests would this option contribute".
|
|
2272
|
+
updateStatPillCounts();
|
|
2273
|
+
if(tagMenuOpen())openTagMenu(); // re-render menu items with fresh counts
|
|
2206
2274
|
// "X tests across Y files" subtitle reflects the current filter result.
|
|
2207
2275
|
// When no filter is active the form matches the original (no "of Y").
|
|
2208
2276
|
var sub=document.querySelector('[data-summary-sub]');
|
|
@@ -2227,6 +2295,7 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2227
2295
|
if(activeStatus)p.set('status',activeStatus);
|
|
2228
2296
|
activeTags.forEach(function(t){p.append('tag',t)});
|
|
2229
2297
|
activeReasons.forEach(function(r){p.append('reason',r)});
|
|
2298
|
+
if(activeSearch)p.set('q',activeSearch);
|
|
2230
2299
|
var qs=p.toString();
|
|
2231
2300
|
var next=location.pathname+(qs?'?'+qs:'')+(location.hash||'');
|
|
2232
2301
|
if(next!==location.pathname+location.search+location.hash){
|
|
@@ -2277,25 +2346,42 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2277
2346
|
function addReason(r){if(!r||activeReasons.has(r))return;activeReasons.add(r);renderActiveChips();applyFilters()}
|
|
2278
2347
|
function removeReason(r){if(!activeReasons.delete(r))return;renderActiveChips();applyFilters()}
|
|
2279
2348
|
|
|
2280
|
-
function reasonCount(r){
|
|
2349
|
+
function reasonCount(r){
|
|
2350
|
+
var pool=cardsMatching(false,false,true);
|
|
2351
|
+
var n=0;for(var i=0;i<pool.length;i++){if(pool[i].getAttribute('data-reason')===r)n++}
|
|
2352
|
+
return n;
|
|
2353
|
+
}
|
|
2354
|
+
function updateStatPillCounts(){
|
|
2355
|
+
var pool=cardsMatching(true,false,false);
|
|
2356
|
+
var counts=Object.create(null);
|
|
2357
|
+
for(var i=0;i<pool.length;i++){var s=pool[i].getAttribute('data-status');counts[s]=(counts[s]||0)+1}
|
|
2358
|
+
document.querySelectorAll('.stat-pill[data-filter]').forEach(function(pill){
|
|
2359
|
+
var key=pill.getAttribute('data-filter');
|
|
2360
|
+
var span=pill.querySelector('.pill-count');
|
|
2361
|
+
if(span)span.textContent=counts[key]||0;
|
|
2362
|
+
});
|
|
2363
|
+
}
|
|
2281
2364
|
|
|
2282
2365
|
function openTagMenu(){
|
|
2283
2366
|
var menu=document.querySelector('[data-tag-menu]');
|
|
2284
2367
|
if(!menu)return;
|
|
2285
2368
|
var trigger=document.querySelector('[data-add-tag-filter]');
|
|
2286
2369
|
menu.innerHTML='';
|
|
2287
|
-
|
|
2288
|
-
|
|
2370
|
+
// For each available tag/reason, compute its preview count under the
|
|
2371
|
+
// current other filters. Options with count 0 are hidden — they'd lead
|
|
2372
|
+
// to an empty view, so they're not useful to offer.
|
|
2373
|
+
var tagsWithCounts=allTags.filter(function(t){return !activeTags.has(t)}).map(function(t){return {key:t,count:tagCount(t)}}).filter(function(x){return x.count>0});
|
|
2374
|
+
var reasonsWithCounts=allReasons.filter(function(r){return !activeReasons.has(r)}).map(function(r){return {key:r,count:reasonCount(r)}}).filter(function(x){return x.count>0});
|
|
2289
2375
|
var added=false;
|
|
2290
2376
|
if(allTags.length>0){
|
|
2291
2377
|
var hT=document.createElement('div');hT.className='tag-menu-section';hT.textContent='Tags';menu.appendChild(hT);
|
|
2292
|
-
if(
|
|
2293
|
-
var emptyT=document.createElement('div');emptyT.className='tag-menu-empty';emptyT.textContent='All tags selected';menu.appendChild(emptyT);
|
|
2378
|
+
if(tagsWithCounts.length===0){
|
|
2379
|
+
var emptyT=document.createElement('div');emptyT.className='tag-menu-empty';emptyT.textContent=allTags.length===activeTags.size?'All tags selected':'No matching tags';menu.appendChild(emptyT);
|
|
2294
2380
|
}else{
|
|
2295
|
-
|
|
2296
|
-
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-tag-menu-item',
|
|
2297
|
-
var label=document.createElement('span');label.textContent=
|
|
2298
|
-
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=
|
|
2381
|
+
tagsWithCounts.forEach(function(x){
|
|
2382
|
+
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-tag-menu-item',x.key);
|
|
2383
|
+
var label=document.createElement('span');label.textContent=x.key;
|
|
2384
|
+
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=x.count;
|
|
2299
2385
|
item.appendChild(label);item.appendChild(count);
|
|
2300
2386
|
menu.appendChild(item);
|
|
2301
2387
|
});
|
|
@@ -2304,14 +2390,14 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2304
2390
|
}
|
|
2305
2391
|
if(allReasons.length>0){
|
|
2306
2392
|
var hR=document.createElement('div');hR.className='tag-menu-section';hR.textContent='Diagnoses';menu.appendChild(hR);
|
|
2307
|
-
if(
|
|
2308
|
-
var emptyR=document.createElement('div');emptyR.className='tag-menu-empty';emptyR.textContent='All diagnoses selected';menu.appendChild(emptyR);
|
|
2393
|
+
if(reasonsWithCounts.length===0){
|
|
2394
|
+
var emptyR=document.createElement('div');emptyR.className='tag-menu-empty';emptyR.textContent=allReasons.length===activeReasons.size?'All diagnoses selected':'No matching diagnoses';menu.appendChild(emptyR);
|
|
2309
2395
|
}else{
|
|
2310
|
-
|
|
2311
|
-
var meta=REASON_LABELS[
|
|
2312
|
-
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-reason-menu-item',
|
|
2396
|
+
reasonsWithCounts.forEach(function(x){
|
|
2397
|
+
var meta=REASON_LABELS[x.key]||REASON_LABELS['UNKNOWN'];
|
|
2398
|
+
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-reason-menu-item',x.key);
|
|
2313
2399
|
var label=document.createElement('span');label.textContent=meta.label;label.style.color=meta.color;
|
|
2314
|
-
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=
|
|
2400
|
+
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=x.count;
|
|
2315
2401
|
item.appendChild(label);item.appendChild(count);
|
|
2316
2402
|
menu.appendChild(item);
|
|
2317
2403
|
});
|
|
@@ -2335,7 +2421,10 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2335
2421
|
activeStatus=null;
|
|
2336
2422
|
activeTags.clear();
|
|
2337
2423
|
activeReasons.clear();
|
|
2424
|
+
activeSearch='';
|
|
2338
2425
|
document.querySelectorAll('.stat-pill').forEach(function(p){p.classList.remove('active')});
|
|
2426
|
+
var searchInput=document.querySelector('[data-filter-search]');
|
|
2427
|
+
if(searchInput)searchInput.value='';
|
|
2339
2428
|
renderActiveChips();
|
|
2340
2429
|
closeTagMenu();
|
|
2341
2430
|
applyFilters();
|
|
@@ -2365,7 +2454,9 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2365
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)}
|
|
2366
2455
|
return;
|
|
2367
2456
|
}
|
|
2368
|
-
// 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}
|
|
2369
2460
|
var flowBtn=e.target.closest('.copy-flow-id');
|
|
2370
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}
|
|
2371
2462
|
var jsonBtn=e.target.closest('.copy-json');
|
|
@@ -2463,8 +2554,20 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2463
2554
|
p.getAll('tag').forEach(function(t){if(tagSet[t])activeTags.add(t)});
|
|
2464
2555
|
var reasonSet={};allReasons.forEach(function(r){reasonSet[r]=true});
|
|
2465
2556
|
p.getAll('reason').forEach(function(r){if(reasonSet[r])activeReasons.add(r)});
|
|
2557
|
+
var q=p.get('q');
|
|
2558
|
+
var searchInput=document.querySelector('[data-filter-search]');
|
|
2559
|
+
if(q){
|
|
2560
|
+
activeSearch=q.toLowerCase();
|
|
2561
|
+
if(searchInput)searchInput.value=q;
|
|
2562
|
+
}
|
|
2563
|
+
if(searchInput){
|
|
2564
|
+
searchInput.addEventListener('input',function(){
|
|
2565
|
+
activeSearch=searchInput.value.trim().toLowerCase();
|
|
2566
|
+
applyFilters();
|
|
2567
|
+
});
|
|
2568
|
+
}
|
|
2466
2569
|
if(activeTags.size>0||activeReasons.size>0)renderActiveChips();
|
|
2467
|
-
if(activeStatus!==null||activeTags.size>0||activeReasons.size>0)applyFilters();
|
|
2570
|
+
if(activeStatus!==null||activeTags.size>0||activeReasons.size>0||activeSearch.length>0)applyFilters();
|
|
2468
2571
|
})();
|
|
2469
2572
|
|
|
2470
2573
|
// Open #?testId=<id> deep links to the matching test card. Used by the
|
package/dist/reporter/render.js
CHANGED
|
@@ -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
|
-
|
|
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-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
|
-
<
|
|
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('')}
|
|
@@ -1769,6 +1778,17 @@ body::before{content:'';position:fixed;top:-750px;left:50%;transform:translateX(
|
|
|
1769
1778
|
.stat-pill.active{background:var(--accent);border-color:var(--accent);color:#fff}
|
|
1770
1779
|
.stat-pill.active .pill-count{background:rgba(255,255,255,.25);color:#fff}
|
|
1771
1780
|
.pill-count{font-size:11px;font-weight:700;background:var(--overlay-light-active);color:var(--text-dim);padding:1px 7px;border-radius:calc(var(--radius) - 2px);min-width:20px;text-align:center;transition:all .2s}
|
|
1781
|
+
/* Substring search across test filename + spec title. Lives in the same row
|
|
1782
|
+
* as the stat pills and tag/diagnosis filter. */
|
|
1783
|
+
.filter-search-wrap{position:relative;display:inline-flex;align-items:center;flex-shrink:0}
|
|
1784
|
+
.filter-search-icon{position:absolute;left:8px;width:14px;height:14px;color:var(--text-muted);fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;pointer-events:none}
|
|
1785
|
+
.filter-search{background:var(--surface);border:1px solid var(--border);color:var(--text);font:inherit;font-size:12px;height:28px;padding:0 10px 0 28px;border-radius:var(--radius);width:200px;outline:none;transition:border-color .15s,background .15s}
|
|
1786
|
+
.filter-search::placeholder{color:var(--text-dim)}
|
|
1787
|
+
.filter-search:hover{border-color:var(--text-dim)}
|
|
1788
|
+
.filter-search:focus{border-color:var(--accent);background:var(--surface-raised)}
|
|
1789
|
+
/* Hide the WebKit search clear "x" — Clear Filters wipes it via the same UI. */
|
|
1790
|
+
.filter-search::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
|
|
1791
|
+
|
|
1772
1792
|
.clear-filter{background:var(--surface);border:1px solid var(--border);color:var(--text-muted);padding:6px 14px;border-radius:var(--radius);cursor:pointer;font-size:12px;font-weight:500;font-family:inherit;display:none;align-items:center;gap:5px;flex-shrink:0;transition:all .2s}
|
|
1773
1793
|
.clear-filter:hover{background:var(--surface-raised);border-color:var(--text-dim);color:var(--text)}
|
|
1774
1794
|
.clear-filter.visible{display:flex}
|
|
@@ -1806,9 +1826,15 @@ body::before{content:'';position:fixed;top:-750px;left:50%;transform:translateX(
|
|
|
1806
1826
|
.chevron-spacer{width:18px;flex-shrink:0}
|
|
1807
1827
|
.test-card.expanded .chevron{transform:rotate(90deg)}
|
|
1808
1828
|
.status-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
|
|
1809
|
-
.test-file{color:var(--text);font-weight:600}
|
|
1810
1829
|
.test-name-group{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
|
|
1811
|
-
.test-
|
|
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}
|
|
1812
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}
|
|
1813
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}
|
|
1814
1840
|
.copy-flow-id:hover{background:var(--overlay-light-active);color:var(--text)}
|
|
@@ -2131,6 +2157,10 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2131
2157
|
<div class="test-bar">${testBarHtml}</div>
|
|
2132
2158
|
<div class="summary-stats">
|
|
2133
2159
|
<div class="stat-pills">${statPillsHtml}</div>
|
|
2160
|
+
<label class="filter-search-wrap" title="Search test titles">
|
|
2161
|
+
<svg class="filter-search-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
|
|
2162
|
+
<input type="search" class="filter-search" data-filter-search placeholder="Search tests…" autocomplete="off" spellcheck="false" />
|
|
2163
|
+
</label>
|
|
2134
2164
|
<div class="tag-filter-controls" data-tag-filter-controls hidden>
|
|
2135
2165
|
<div class="tag-filter-trigger-wrap">
|
|
2136
2166
|
<button class="add-tag-filter" data-add-tag-filter title="Filter by tag or diagnosis"><span class="add-tag-plus">+</span> Filter</button>
|
|
@@ -2165,15 +2195,43 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2165
2195
|
var activeStatus=null;
|
|
2166
2196
|
var activeTags=new Set();
|
|
2167
2197
|
var activeReasons=new Set();
|
|
2198
|
+
var activeSearch=''; // lowercase substring match against data-search
|
|
2168
2199
|
var allTags=[];
|
|
2169
2200
|
var allReasons=[]; // ordered list of REASON keys present in the report
|
|
2170
2201
|
var REASON_LABELS=${JSON.stringify(REASON_LABELS)};
|
|
2171
2202
|
|
|
2172
2203
|
function cardTags(card){var raw=card.getAttribute('data-tags');if(!raw)return [];try{var v=JSON.parse(raw);return Array.isArray(v)?v:[]}catch(_){return []}}
|
|
2173
|
-
|
|
2204
|
+
|
|
2205
|
+
// Faceted-search counts. Each filter option's badge shows "how many tests
|
|
2206
|
+
// would this option contribute given the rest of the filters." The semantics
|
|
2207
|
+
// per dimension match how clicking interacts:
|
|
2208
|
+
// - Status pills (single-select replace): ignore current activeStatus.
|
|
2209
|
+
// - Tag menu items (multi-select AND): use ALL current filters.
|
|
2210
|
+
// - Reason menu items (multi-select OR): ignore current activeReasons.
|
|
2211
|
+
// Search is free-form and not counted.
|
|
2212
|
+
function cardsMatching(ignoreStatus,ignoreTags,ignoreReasons){
|
|
2213
|
+
var out=[];
|
|
2214
|
+
document.querySelectorAll('.test-card').forEach(function(card){
|
|
2215
|
+
var statusOk=ignoreStatus||activeStatus===null||card.getAttribute('data-status')===activeStatus;
|
|
2216
|
+
var tagsOk=true;
|
|
2217
|
+
if(!ignoreTags&&activeTags.size>0){
|
|
2218
|
+
var t=cardTags(card);
|
|
2219
|
+
activeTags.forEach(function(w){if(t.indexOf(w)===-1)tagsOk=false});
|
|
2220
|
+
}
|
|
2221
|
+
var reasonOk=ignoreReasons||activeReasons.size===0||activeReasons.has(card.getAttribute('data-reason')||'');
|
|
2222
|
+
var searchOk=activeSearch.length===0||(card.getAttribute('data-search')||'').indexOf(activeSearch)!==-1;
|
|
2223
|
+
if(statusOk&&tagsOk&&reasonOk&&searchOk)out.push(card);
|
|
2224
|
+
});
|
|
2225
|
+
return out;
|
|
2226
|
+
}
|
|
2227
|
+
function tagCount(t){
|
|
2228
|
+
var pool=cardsMatching(false,false,false);
|
|
2229
|
+
var n=0;for(var i=0;i<pool.length;i++){if(cardTags(pool[i]).indexOf(t)!==-1)n++}
|
|
2230
|
+
return n;
|
|
2231
|
+
}
|
|
2174
2232
|
|
|
2175
2233
|
function applyFilters(){
|
|
2176
|
-
var anyActive=activeStatus!==null||activeTags.size>0||activeReasons.size>0;
|
|
2234
|
+
var anyActive=activeStatus!==null||activeTags.size>0||activeReasons.size>0||activeSearch.length>0;
|
|
2177
2235
|
document.querySelector('.clear-filter').classList.toggle('visible',anyActive);
|
|
2178
2236
|
var visibleTests=0;
|
|
2179
2237
|
var visibleFiles=Object.create(null);
|
|
@@ -2189,7 +2247,12 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2189
2247
|
var r=card.getAttribute('data-reason')||'';
|
|
2190
2248
|
reasonOk=activeReasons.has(r);
|
|
2191
2249
|
}
|
|
2192
|
-
var
|
|
2250
|
+
var searchOk=true;
|
|
2251
|
+
if(activeSearch.length>0){
|
|
2252
|
+
var hay=card.getAttribute('data-search')||'';
|
|
2253
|
+
searchOk=hay.indexOf(activeSearch)!==-1;
|
|
2254
|
+
}
|
|
2255
|
+
var hide=!(statusOk&&tagsOk&&reasonOk&&searchOk);
|
|
2193
2256
|
card.classList.toggle('hidden-by-filter',hide);
|
|
2194
2257
|
if(!hide){
|
|
2195
2258
|
visibleTests++;
|
|
@@ -2203,6 +2266,11 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2203
2266
|
var card=document.getElementById(block.getAttribute('data-target'));
|
|
2204
2267
|
block.classList.toggle('hidden-by-filter',!!(card&&card.classList.contains('hidden-by-filter')));
|
|
2205
2268
|
});
|
|
2269
|
+
// Faceted-search live counts: status pills, and the tag/diagnosis menu
|
|
2270
|
+
// (refreshed if currently open) all reflect "given the other filters,
|
|
2271
|
+
// how many tests would this option contribute".
|
|
2272
|
+
updateStatPillCounts();
|
|
2273
|
+
if(tagMenuOpen())openTagMenu(); // re-render menu items with fresh counts
|
|
2206
2274
|
// "X tests across Y files" subtitle reflects the current filter result.
|
|
2207
2275
|
// When no filter is active the form matches the original (no "of Y").
|
|
2208
2276
|
var sub=document.querySelector('[data-summary-sub]');
|
|
@@ -2227,6 +2295,7 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2227
2295
|
if(activeStatus)p.set('status',activeStatus);
|
|
2228
2296
|
activeTags.forEach(function(t){p.append('tag',t)});
|
|
2229
2297
|
activeReasons.forEach(function(r){p.append('reason',r)});
|
|
2298
|
+
if(activeSearch)p.set('q',activeSearch);
|
|
2230
2299
|
var qs=p.toString();
|
|
2231
2300
|
var next=location.pathname+(qs?'?'+qs:'')+(location.hash||'');
|
|
2232
2301
|
if(next!==location.pathname+location.search+location.hash){
|
|
@@ -2277,25 +2346,42 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2277
2346
|
function addReason(r){if(!r||activeReasons.has(r))return;activeReasons.add(r);renderActiveChips();applyFilters()}
|
|
2278
2347
|
function removeReason(r){if(!activeReasons.delete(r))return;renderActiveChips();applyFilters()}
|
|
2279
2348
|
|
|
2280
|
-
function reasonCount(r){
|
|
2349
|
+
function reasonCount(r){
|
|
2350
|
+
var pool=cardsMatching(false,false,true);
|
|
2351
|
+
var n=0;for(var i=0;i<pool.length;i++){if(pool[i].getAttribute('data-reason')===r)n++}
|
|
2352
|
+
return n;
|
|
2353
|
+
}
|
|
2354
|
+
function updateStatPillCounts(){
|
|
2355
|
+
var pool=cardsMatching(true,false,false);
|
|
2356
|
+
var counts=Object.create(null);
|
|
2357
|
+
for(var i=0;i<pool.length;i++){var s=pool[i].getAttribute('data-status');counts[s]=(counts[s]||0)+1}
|
|
2358
|
+
document.querySelectorAll('.stat-pill[data-filter]').forEach(function(pill){
|
|
2359
|
+
var key=pill.getAttribute('data-filter');
|
|
2360
|
+
var span=pill.querySelector('.pill-count');
|
|
2361
|
+
if(span)span.textContent=counts[key]||0;
|
|
2362
|
+
});
|
|
2363
|
+
}
|
|
2281
2364
|
|
|
2282
2365
|
function openTagMenu(){
|
|
2283
2366
|
var menu=document.querySelector('[data-tag-menu]');
|
|
2284
2367
|
if(!menu)return;
|
|
2285
2368
|
var trigger=document.querySelector('[data-add-tag-filter]');
|
|
2286
2369
|
menu.innerHTML='';
|
|
2287
|
-
|
|
2288
|
-
|
|
2370
|
+
// For each available tag/reason, compute its preview count under the
|
|
2371
|
+
// current other filters. Options with count 0 are hidden — they'd lead
|
|
2372
|
+
// to an empty view, so they're not useful to offer.
|
|
2373
|
+
var tagsWithCounts=allTags.filter(function(t){return !activeTags.has(t)}).map(function(t){return {key:t,count:tagCount(t)}}).filter(function(x){return x.count>0});
|
|
2374
|
+
var reasonsWithCounts=allReasons.filter(function(r){return !activeReasons.has(r)}).map(function(r){return {key:r,count:reasonCount(r)}}).filter(function(x){return x.count>0});
|
|
2289
2375
|
var added=false;
|
|
2290
2376
|
if(allTags.length>0){
|
|
2291
2377
|
var hT=document.createElement('div');hT.className='tag-menu-section';hT.textContent='Tags';menu.appendChild(hT);
|
|
2292
|
-
if(
|
|
2293
|
-
var emptyT=document.createElement('div');emptyT.className='tag-menu-empty';emptyT.textContent='All tags selected';menu.appendChild(emptyT);
|
|
2378
|
+
if(tagsWithCounts.length===0){
|
|
2379
|
+
var emptyT=document.createElement('div');emptyT.className='tag-menu-empty';emptyT.textContent=allTags.length===activeTags.size?'All tags selected':'No matching tags';menu.appendChild(emptyT);
|
|
2294
2380
|
}else{
|
|
2295
|
-
|
|
2296
|
-
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-tag-menu-item',
|
|
2297
|
-
var label=document.createElement('span');label.textContent=
|
|
2298
|
-
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=
|
|
2381
|
+
tagsWithCounts.forEach(function(x){
|
|
2382
|
+
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-tag-menu-item',x.key);
|
|
2383
|
+
var label=document.createElement('span');label.textContent=x.key;
|
|
2384
|
+
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=x.count;
|
|
2299
2385
|
item.appendChild(label);item.appendChild(count);
|
|
2300
2386
|
menu.appendChild(item);
|
|
2301
2387
|
});
|
|
@@ -2304,14 +2390,14 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2304
2390
|
}
|
|
2305
2391
|
if(allReasons.length>0){
|
|
2306
2392
|
var hR=document.createElement('div');hR.className='tag-menu-section';hR.textContent='Diagnoses';menu.appendChild(hR);
|
|
2307
|
-
if(
|
|
2308
|
-
var emptyR=document.createElement('div');emptyR.className='tag-menu-empty';emptyR.textContent='All diagnoses selected';menu.appendChild(emptyR);
|
|
2393
|
+
if(reasonsWithCounts.length===0){
|
|
2394
|
+
var emptyR=document.createElement('div');emptyR.className='tag-menu-empty';emptyR.textContent=allReasons.length===activeReasons.size?'All diagnoses selected':'No matching diagnoses';menu.appendChild(emptyR);
|
|
2309
2395
|
}else{
|
|
2310
|
-
|
|
2311
|
-
var meta=REASON_LABELS[
|
|
2312
|
-
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-reason-menu-item',
|
|
2396
|
+
reasonsWithCounts.forEach(function(x){
|
|
2397
|
+
var meta=REASON_LABELS[x.key]||REASON_LABELS['UNKNOWN'];
|
|
2398
|
+
var item=document.createElement('button');item.className='tag-menu-item';item.setAttribute('data-reason-menu-item',x.key);
|
|
2313
2399
|
var label=document.createElement('span');label.textContent=meta.label;label.style.color=meta.color;
|
|
2314
|
-
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=
|
|
2400
|
+
var count=document.createElement('span');count.className='tag-menu-count';count.textContent=x.count;
|
|
2315
2401
|
item.appendChild(label);item.appendChild(count);
|
|
2316
2402
|
menu.appendChild(item);
|
|
2317
2403
|
});
|
|
@@ -2335,7 +2421,10 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2335
2421
|
activeStatus=null;
|
|
2336
2422
|
activeTags.clear();
|
|
2337
2423
|
activeReasons.clear();
|
|
2424
|
+
activeSearch='';
|
|
2338
2425
|
document.querySelectorAll('.stat-pill').forEach(function(p){p.classList.remove('active')});
|
|
2426
|
+
var searchInput=document.querySelector('[data-filter-search]');
|
|
2427
|
+
if(searchInput)searchInput.value='';
|
|
2339
2428
|
renderActiveChips();
|
|
2340
2429
|
closeTagMenu();
|
|
2341
2430
|
applyFilters();
|
|
@@ -2365,7 +2454,9 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2365
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)}
|
|
2366
2455
|
return;
|
|
2367
2456
|
}
|
|
2368
|
-
// 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}
|
|
2369
2460
|
var flowBtn=e.target.closest('.copy-flow-id');
|
|
2370
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}
|
|
2371
2462
|
var jsonBtn=e.target.closest('.copy-json');
|
|
@@ -2463,8 +2554,20 @@ details.ai-invocation[open]>summary .native-step-chevron{transform:rotate(90deg)
|
|
|
2463
2554
|
p.getAll('tag').forEach(function(t){if(tagSet[t])activeTags.add(t)});
|
|
2464
2555
|
var reasonSet={};allReasons.forEach(function(r){reasonSet[r]=true});
|
|
2465
2556
|
p.getAll('reason').forEach(function(r){if(reasonSet[r])activeReasons.add(r)});
|
|
2557
|
+
var q=p.get('q');
|
|
2558
|
+
var searchInput=document.querySelector('[data-filter-search]');
|
|
2559
|
+
if(q){
|
|
2560
|
+
activeSearch=q.toLowerCase();
|
|
2561
|
+
if(searchInput)searchInput.value=q;
|
|
2562
|
+
}
|
|
2563
|
+
if(searchInput){
|
|
2564
|
+
searchInput.addEventListener('input',function(){
|
|
2565
|
+
activeSearch=searchInput.value.trim().toLowerCase();
|
|
2566
|
+
applyFilters();
|
|
2567
|
+
});
|
|
2568
|
+
}
|
|
2466
2569
|
if(activeTags.size>0||activeReasons.size>0)renderActiveChips();
|
|
2467
|
-
if(activeStatus!==null||activeTags.size>0||activeReasons.size>0)applyFilters();
|
|
2570
|
+
if(activeStatus!==null||activeTags.size>0||activeReasons.size>0||activeSearch.length>0)applyFilters();
|
|
2468
2571
|
})();
|
|
2469
2572
|
|
|
2470
2573
|
// Open #?testId=<id> deep links to the matching test card. Used by the
|