"""The status and layout macros in _macros.html (#5094), rendered through the app's own Jinja environment so its globals (status_info, required) are the real ones.""" import enum import pytest from steward.core.formatting import STATES, status_info async def _render(app, source: str, **ctx) -> str: async with app.app_context(): tpl = app.jinja_env.from_string('{% from "_macros.html" import status_badge, status_dot, ' 'stat_tile, empty_state, page_header, icon_button %}' + source) out = await tpl.render_async(**ctx) if app.jinja_env.is_async else tpl.render(**ctx) return " ".join(out.split()) def test_every_state_a_page_shows_has_a_tone_and_a_label(): named = ["up", "down", "stale", "firing", "pending", "acknowledged", "no_data", "ok", "warn", "crit"] assert set(named) <= set(STATES) assert {tone for tone, _ in STATES.values()} == {"ok", "warn", "crit", "info", "dim"} assert status_info("down")[0] == status_info("firing")[0] == "crit" class _State(enum.Enum): firing = "firing" @pytest.mark.parametrize("state, tone, label", [ ("firing", "crit", "Firing"), (_State.firing, "crit", "Firing"), ("UP", "ok", "Up"), ("no_data", "warn", "No data"), ("acknowledged", "info", "Acknowledged"), (None, "dim", "Unknown"), ("half_open", "dim", "Half open"), # unmapped: dim, its own name ]) def test_status_info(state, tone, label): assert status_info(state) == (tone, label) async def test_status_badge(app): assert await _render(app, "{{ status_badge('firing') }}") == 'Firing' out = await _render(app, "{{ status_badge(s, 'Muted', title=t) }}", s=_State.firing, t='a "b"') assert out == 'Muted' async def test_a_status_dot_always_carries_its_label(app): out = await _render(app, "{{ status_dot('down') }}") assert 'class="dot dot-crit" aria-hidden="true"' in out and 'Down' in out out = await _render(app, "{{ status_dot('up', show_label=true) }}") assert 'Up' in out and "sr-only" not in out async def test_stat_tile(app): out = await _render(app, "{{ stat_tile('Firing', 3, state='crit', href='/alerts/?a=1&b=2') }}") assert out.startswith('') assert '3' in out and out.endswith("") out = await _render(app, "{{ stat_tile('', 12, hint='2 stale') }}") assert out.startswith('
') and "<Hosts>" in out and "2 stale" in out async def test_empty_state(app): out = await _render(app, "{{ empty_state('No rules yet.', 'New rule', '/alerts/rules/new') }}") assert "

No rules yet.

" in out and 'href="/alerts/rules/new">New rule' in out assert "New{% endcall %}") assert '

Alerts

' in out and '

All rules

' in out assert '' in out assert "page-actions" not in await _render(app, "{{ page_header('Alerts') }}") async def test_icon_button_names_itself_and_refuses_to_render_without_a_label(app): out = await _render(app, "{{ icon_button('×', 'Delete rule web01', type='submit', cls='btn-danger', confirm='Delete?') }}") assert 'type="submit"' in out and 'aria-label="Delete rule web01"' in out and 'data-confirm="Delete?"' in out out = await _render(app, "{{ icon_button('✎', 'Edit', href='/x') }}") assert out.startswith('