Revert "feat(lvl5): P1 — 5-rung ladder (L5=abra recipe lint) + de-capped level semantics"
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This reverts commit e219a7891d.
This commit is contained in:
@ -1,11 +1,8 @@
|
||||
"""Unit tests for the pure card/badge renderers (harness.card) — phase lvl5 semantics.
|
||||
"""Unit tests for the pure card/badge renderers (harness.card), Phase 3 U2 (R3/R6).
|
||||
|
||||
Covers the deterministic HTML + SVG string builders (the PNG step needs Playwright + is exercised
|
||||
live). The cardinal check: the card REPORTS the data verbatim — level/marks come straight from the
|
||||
dict, never recomputed — the badge is NUMBER + COLOUR ONLY, and the per-rung table rows (incl.
|
||||
intentional-skip / unverified) are the sole carrier of "why isn't the level higher". Old schema-1
|
||||
artifacts (4-rung ladder, cap fields present) must render without error and without relabeling.
|
||||
Run cold: cc-ci-run -m pytest tests/unit/test_card.py -q
|
||||
Covers the deterministic HTML + SVG string builders (the PNG step needs Playwright + is exercised in
|
||||
the U2 live demo). The cardinal check: the card REPORTS the data verbatim — level/marks come straight
|
||||
from the dict, never recomputed. Run cold: cc-ci-run -m pytest tests/unit/test_card.py -q
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@ -17,19 +14,12 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner")
|
||||
from harness import card as C # noqa: E402
|
||||
|
||||
|
||||
def _data(level=5, **kw):
|
||||
d = {
|
||||
"schema": 2,
|
||||
def _data(level=3, cap="L4 functional (recipe-specific tests) N/A"):
|
||||
return {
|
||||
"recipe": "uptime-kuma",
|
||||
"version": "1.23.0",
|
||||
"level": level,
|
||||
"rungs": {
|
||||
"install": "pass",
|
||||
"upgrade": "pass",
|
||||
"backup_restore": "pass",
|
||||
"functional": "pass",
|
||||
"lint": "pass",
|
||||
},
|
||||
"level_cap_reason": cap,
|
||||
"flags": {"clean_teardown": True, "no_secret_leak": True},
|
||||
"screenshot": "screenshot.png",
|
||||
"stages": [
|
||||
@ -46,54 +36,46 @@ def _data(level=5, **kw):
|
||||
{"name": "test_broken", "status": "fail", "ms": 5},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "lint",
|
||||
"status": "pass",
|
||||
"tests": [{"name": "abra recipe lint", "status": "pass", "ms": 0}],
|
||||
},
|
||||
],
|
||||
}
|
||||
d.update(kw)
|
||||
return d
|
||||
|
||||
|
||||
def test_level_color_ramp():
|
||||
# 0 (red) … 5 (bright green — full 5-rung climb); unknown → grey.
|
||||
assert C.level_color(0) != C.level_color(5)
|
||||
assert C.level_color(5) == "#3fb950"
|
||||
assert C.level_color(99) == "#8b949e"
|
||||
assert C.level_color(0) != C.level_color(6)
|
||||
assert C.level_color(6) == "#3fb950"
|
||||
assert C.level_color(99) == "#8b949e" # unknown → grey
|
||||
|
||||
|
||||
def test_badge_svg_is_number_and_color_only():
|
||||
def test_badge_svg_wellformed():
|
||||
svg = C.level_badge_svg(4)
|
||||
assert svg.startswith("<svg") and svg.endswith("</svg>")
|
||||
assert "level 4" in svg
|
||||
assert C.level_color(4) in svg
|
||||
# operator-specified (phase lvl5): NOTHING but the level on the badge — no annotation
|
||||
# segment of any kind, whatever the rung situation.
|
||||
assert "expected" not in svg and "gap?" not in svg and "skip" not in svg
|
||||
# plain cap (no intent) → two-box badge, no third segment
|
||||
assert "expected" not in svg and "gap?" not in svg
|
||||
|
||||
|
||||
def test_badge_svg_level5():
|
||||
svg = C.level_badge_svg(5)
|
||||
assert "level 5" in svg and "#3fb950" in svg
|
||||
def test_badge_svg_differentiates_intentional_vs_unintentional_skip():
|
||||
# an intentional (declared) skip capped the climb → muted "expected" third segment
|
||||
exp = C.level_badge_svg(2, "L3 backup/restore N/A", "intentional")
|
||||
assert "level 2" in exp and "expected" in exp and C.EXPECT_COLOR in exp
|
||||
assert "gap?" not in exp
|
||||
# an unintentional skip (not declared) → amber "gap?" third segment
|
||||
gap = C.level_badge_svg(2, "L3 backup/restore N/A", "unintentional")
|
||||
assert "level 2" in gap and "gap?" in gap and C.GAP_COLOR in gap
|
||||
assert "expected" not in gap
|
||||
|
||||
|
||||
def test_skip_rows_intentional_and_unverified():
|
||||
def test_skip_rows_intentional_and_unintentional():
|
||||
html_out = C._skip_rows(
|
||||
{"intentional": {"backup_restore": "no persistent data"}, "unintentional": ["functional"]}
|
||||
)
|
||||
# intentional skip: labelled row (muted green) + the reason on its own line
|
||||
assert "intentional skip" in html_out and C.SKIP_GREEN in html_out
|
||||
assert "backup/restore" in html_out and "no persistent data" in html_out
|
||||
# unverified rung: amber row + the blocks-the-level explanation
|
||||
assert "unverified" in html_out and C.GAP_COLOR in html_out
|
||||
assert "functional" in html_out and "cannot rise above" in html_out
|
||||
|
||||
|
||||
def test_skip_rows_lint_label_known():
|
||||
html_out = C._skip_rows({"intentional": {}, "unintentional": ["lint"]})
|
||||
assert ">lint<" in html_out.replace("</b>", "<") # rung label renders, not a KeyError
|
||||
# unintentional skip: amber row + prompt to declare/add coverage
|
||||
assert "unintentional skip" in html_out and C.GAP_COLOR in html_out
|
||||
assert "functional" in html_out and "EXPECTED_NA" in html_out
|
||||
|
||||
|
||||
def test_skip_rows_empty_when_no_skips():
|
||||
@ -101,68 +83,22 @@ def test_skip_rows_empty_when_no_skips():
|
||||
|
||||
|
||||
def test_card_html_reports_level_verbatim():
|
||||
html = C.render_card_html(_data(level=2))
|
||||
html = C.render_card_html(_data(level=2, cap="L3 backup/restore (data integrity) N/A"))
|
||||
assert "uptime-kuma" in html
|
||||
assert "1.23.0" in html
|
||||
# the level shown is exactly what was passed (no recompute)
|
||||
assert ">2<" in html
|
||||
assert "level 2 of 5" in html
|
||||
assert "L3 backup/restore" in html
|
||||
assert C.level_color(2) in html
|
||||
|
||||
|
||||
def test_card_html_no_cap_language():
|
||||
html = C.render_card_html(_data())
|
||||
assert "capped" not in html and "cap_reason" not in html
|
||||
assert "level 5 of 5" in html
|
||||
|
||||
|
||||
def test_card_html_old_schema1_artifact_renders():
|
||||
# history compatibility: a pre-lvl5 results.json (4-rung ladder, cap fields, "na" statuses)
|
||||
# renders without KeyError and shows ITS OWN ladder height (no retroactive relabeling).
|
||||
old = {
|
||||
"schema": 1,
|
||||
"recipe": "legacy",
|
||||
"version": "0.9",
|
||||
"level": 4,
|
||||
"level_cap_reason": "",
|
||||
"level_cap_rung": None,
|
||||
"rungs": {
|
||||
"install": "pass",
|
||||
"upgrade": "pass",
|
||||
"backup_restore": "pass",
|
||||
"functional": "pass",
|
||||
},
|
||||
"skips": {"intentional": {}, "unintentional": []},
|
||||
"flags": {"clean_teardown": True, "no_secret_leak": True},
|
||||
"screenshot": None,
|
||||
"stages": [],
|
||||
}
|
||||
html = C.render_card_html(old)
|
||||
assert "legacy" in html
|
||||
assert "level 4 of 4" in html # the old top, not 5
|
||||
assert "capped" not in html
|
||||
|
||||
|
||||
def test_card_html_shows_stage_and_test_marks_incl_lint():
|
||||
def test_card_html_shows_stage_and_test_marks():
|
||||
html = C.render_card_html(_data())
|
||||
assert "install" in html and "custom" in html
|
||||
assert "abra recipe lint" in html
|
||||
assert "test_serving" in html and "test_broken" in html
|
||||
assert C.STATUS_MARK["pass"] in html and C.STATUS_MARK["fail"] in html
|
||||
|
||||
|
||||
def test_card_html_unver_stage_mark_renders():
|
||||
d = _data()
|
||||
d["stages"][2] = {
|
||||
"name": "lint",
|
||||
"status": "unver",
|
||||
"tests": [{"name": "abra recipe lint", "status": "unver", "ms": 0, "message": "timed out"}],
|
||||
}
|
||||
html = C.render_card_html(d)
|
||||
assert C.STATUS_MARK["unver"] in html
|
||||
assert C.STATUS_COLOR["unver"] in html
|
||||
|
||||
|
||||
def test_card_html_flags_rendered():
|
||||
html = C.render_card_html(_data())
|
||||
assert "clean teardown" in html and "no secret leak" in html
|
||||
|
||||
Reference in New Issue
Block a user