diff --git a/heart/dashboard.py b/heart/dashboard.py index de3f2e9..ebe220b 100644 --- a/heart/dashboard.py +++ b/heart/dashboard.py @@ -2397,7 +2397,13 @@ def _render_html(board: Board) -> str: refreshed_at=board.refreshed_at, refresh_url=(f"https://github.com/{gh_owner}/{repo_name}/actions/workflows/heart-health.yml" if gh_owner else None)) - return f""" + observed_states = {section.state for section in board.sections} + observed_status = ("red" if FAIL in observed_states else + "yellow" if WARN in observed_states else + "stale" if board.stale else + "unknown" if UNOBS in observed_states or not observed_states else + "green" if OK in observed_states else "unknown") + return t_.section_layout(f""" PyAutoHeart Dashboard — {word} @@ -2428,7 +2434,8 @@ def _render_html(board: Board) -> str: {_boards_nav_html()} -""" +""", {"observed-checks": {"status": observed_status, + "label": "Observed: " + observed_status, "count": len(board.sections)}}) def to_dict(board: Board) -> dict[str, Any]: diff --git a/tests/test_dashboard_disclosures.py b/tests/test_dashboard_disclosures.py index 1143311..e58a364 100644 --- a/tests/test_dashboard_disclosures.py +++ b/tests/test_dashboard_disclosures.py @@ -173,3 +173,26 @@ def test_repair_rows_copy_exact_prompts_without_toggling_prompt_disclosures(): assert next(details.find('pre')).text() == plan['prompt'] assert button.text() == '' and list(button.find('svg')) assert any(p.attrs.get('aria-live') == 'polite' for p in section.find('p')) + + +def test_observed_summary_uses_check_states_not_release_verdict(): + cases = [ + ([dashboard.OK], False, 'green'), + ([dashboard.OK, dashboard.WARN], False, 'yellow'), + ([dashboard.WARN, dashboard.FAIL, dashboard.UNOBS], True, 'red'), + ([dashboard.OK], True, 'stale'), + ([dashboard.OK, dashboard.UNOBS], False, 'unknown'), + ([], False, 'unknown'), + ] + for states, stale, expected in cases: + board = dashboard.build_board(make_snapshot(), make_verdict(), now=FRESH_NOW) + board.stale = stale + board.sections = [dashboard.Section(str(i), 'Check', state, 'Summary') + for i, state in enumerate(states)] + root = Page(dashboard._render_html(board)).root + section = next(root.find('details', 'board-section')) + summary = next(section.find('summary')) + assert 'Observed checks' in summary.text() + assert 'Observed: ' + expected in summary.text() + assert next(summary.find(cls='section-status-' + expected)) + assert 'open' not in section.attrs