diff --git a/src/main/resources/report/partials/tests.html b/src/main/resources/report/partials/tests.html index f34b747..6377659 100644 --- a/src/main/resources/report/partials/tests.html +++ b/src/main/resources/report/partials/tests.html @@ -11,6 +11,10 @@ + + + +
🔍 diff --git a/src/main/resources/report/report.css b/src/main/resources/report/report.css index a53fccb..6de8919 100644 --- a/src/main/resources/report/report.css +++ b/src/main/resources/report/report.css @@ -233,6 +233,7 @@ .filter-bar { display: flex; align-items: center; gap: 10px; padding: 14px 24px; border-bottom: 1px solid var(--border); flex-wrap: wrap; } .filter-btn { border: 1px solid var(--border); background: var(--surface); color: var(--text-secondary); border-radius: 16px; padding: 4px 14px; font-size: 13px; cursor: pointer; transition: all .15s; } .filter-btn:hover, .filter-btn.active { background: var(--primary); color: #fff; border-color: var(--primary); } + .expand-controls { display: inline-flex; gap: 8px; margin-left: 8px; } .search-wrap { margin-left: auto; display: flex; align-items: center; border: 1px solid var(--border); border-radius: 20px; padding: 4px 14px; background: var(--surface2); } .search-wrap input { border: none; background: transparent; outline: none; font-size: 13px; color: var(--text); width: 200px; } .search-wrap input::placeholder { color: var(--text-secondary); } @@ -474,6 +475,7 @@ .sidebar, .filter-bar, .filter-btn, + .expand-controls, .search-wrap, .dark-toggle, .copy-failure-btn, diff --git a/src/main/resources/report/report.js b/src/main/resources/report/report.js index 41eb396..5e08d00 100644 --- a/src/main/resources/report/report.js +++ b/src/main/resources/report/report.js @@ -102,6 +102,27 @@ function toggleDetail(idx) { if (icon) icon.classList.toggle('open', !isOpen); } +// ── Expand all / collapse all (tests matching the active filter and search) ── +function setAllDetails(open) { + const q = document.getElementById('searchInput').value.toLowerCase(); + if (open) { + document.querySelectorAll('#testTable tbody tr.group-header').forEach(hdr => { + if (hdr.style.display === 'none') return; + const icon = document.getElementById('gicon-' + hdr.getAttribute('data-group')); + if (icon) icon.classList.remove('closed'); + }); + } + document.querySelectorAll('#testTable tbody tr.group-member.expandable').forEach(row => { + if (!rowMatches(row, q) || !groupIsOpen(row.getAttribute('data-group'))) return; + const detail = row.nextElementSibling; + if (!detail || !detail.classList.contains('detail-row')) return; + row.style.display = ''; + detail.style.display = open ? '' : 'none'; + const icon = row.querySelector('.expand-icon'); + if (icon) icon.classList.toggle('open', open); + }); +} + // ── Tag filtering ── let activeTagFilter = ''; function filterByTag(tagName, event) { @@ -152,27 +173,36 @@ function setFilter(status, btn) { } catch (e) {} applySearch(); } +function rowMatches(row, q) { + const rowStatus = row.getAttribute('data-status') || ''; + const rowTest = row.getAttribute('data-test') || ''; + const groupId = row.getAttribute('data-group') || ''; + const rowTags = (row.getAttribute('data-tags') || '').split(',').map(t => t.trim().toLowerCase()).filter(Boolean); + const hasRetry = row.querySelector('.retry-badge') !== null; + const matchFilter = activeFilter === 'ALL' + || activeFilter === rowStatus + || (activeFilter === 'FLAKY' && hasRetry); + const matchTag = !activeTagFilter || rowTags.includes(activeTagFilter); + const matchSearch = !q + || rowTest.includes(q) + || groupId.toLowerCase().includes(q) + || rowTags.some(t => t.includes(q)); + return matchFilter && matchTag && matchSearch; +} +function groupIsOpen(groupId) { + const icon = document.getElementById('gicon-' + groupId); + return !icon || !icon.classList.contains('closed'); +} function applySearch() { const q = document.getElementById('searchInput').value.toLowerCase(); const members = document.querySelectorAll('#testTable tbody tr.group-member:not(.detail-row)'); const visibleGroups = new Set(); members.forEach(row => { - const rowStatus = row.getAttribute('data-status') || ''; - const rowTest = row.getAttribute('data-test') || ''; - const groupId = row.getAttribute('data-group') || ''; - const rowTags = (row.getAttribute('data-tags') || '').split(',').map(t => t.trim().toLowerCase()).filter(Boolean); - const hasRetry = row.querySelector('.retry-badge') !== null; - const matchFilter = activeFilter === 'ALL' - || activeFilter === rowStatus - || (activeFilter === 'FLAKY' && hasRetry); - const matchTag = !activeTagFilter || rowTags.includes(activeTagFilter); - const matchSearch = !q - || rowTest.includes(q) - || groupId.toLowerCase().includes(q) - || rowTags.some(t => t.includes(q)); - const show = matchFilter && matchTag && matchSearch; + const groupId = row.getAttribute('data-group') || ''; + const match = rowMatches(row, q); + const show = match && groupIsOpen(groupId); row.style.display = show ? '' : 'none'; - if (show) visibleGroups.add(groupId); + if (match) visibleGroups.add(groupId); const next = row.nextElementSibling; if (next && next.classList.contains('detail-row') && !show) next.style.display = 'none'; });