Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions scanner/dashboard/console.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
input{font:inherit;padding:8px 10px;border:1px solid var(--border);border-radius:8px;min-width:280px}
button{font:inherit;font-weight:600;padding:8px 14px;border:0;border-radius:8px;background:var(--primary);color:var(--on-primary);cursor:pointer}
button.ghost{background:var(--surface);color:var(--primary);border:1px solid var(--border)}
button:disabled, button[aria-busy="true"], tr.scan[aria-busy="true"] { opacity: 0.7; pointer-events: none; }
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px 18px;margin-bottom:16px}
.stats{display:flex;gap:12px;flex-wrap:wrap}
.stat{flex:1;min-width:130px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px}
Expand Down Expand Up @@ -135,8 +136,8 @@ <h1>AppGuardrail Console</h1>
<td>${esc(s.created_at)}</td><td>${esc(s.repo||"—")}</td><td><code>${esc((s.commit||"—").slice(0,10))}</code></td>
<td>${s.total}</td><td>${pill(s.deploy_blocking,"var(--crit)")}</td><td>${pill(s.new_blocking,"var(--high)")}</td></tr>`).join("")||'<tr><td colspan="6" class="muted">No scans. POST to /api/v1/scans from CI.</td></tr>';
document.querySelectorAll("tr.scan").forEach(tr=>{
tr.onclick=()=>detail(tr.dataset.id,tr);
tr.addEventListener('keydown', e => { if(e.key === 'Enter' || e.key === ' ') { e.preventDefault(); detail(tr.dataset.id,tr); } });
tr.onclick=()=>{ if(tr.getAttribute("aria-busy")==="true") return; detail(tr.dataset.id,tr); };
tr.addEventListener('keydown', e => { if(e.key === 'Enter' || e.key === ' ') { e.preventDefault(); if(tr.getAttribute("aria-busy")==="true") return; detail(tr.dataset.id,tr); } });
});
}catch(e){ $("#msg").classList.remove("hidden");$("#app").classList.add("hidden");
$("#msg").innerHTML=`<span class="err">${esc(e.message)}</span>`; }
Expand Down
10 changes: 10 additions & 0 deletions tests/test_console_detail_loading_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ def test_console_exposes_loading_busy_and_error_states():
assert 'tr.removeAttribute("aria-busy");' in html


def test_console_busy_scan_row_exposes_temporary_action_unavailability():
"""A busy focusable scan row must expose and enforce its unavailable action state."""
html = _console_html()

assert 'tr.setAttribute("aria-busy","true");' in html
assert 'tr.setAttribute("aria-disabled","true");' in html
Comment thread
seonghobae marked this conversation as resolved.
assert html.count('if(tr.getAttribute("aria-disabled")==="true") return;') == 2
assert 'tr.removeAttribute("aria-disabled");' in html


def test_console_detail_scrolling_respects_reduced_motion():
"""Successful and failed detail requests must honor reduced-motion preferences."""
html = _console_html()
Expand Down
Loading