Skip to content

Commit 0f8033a

Browse files
test: add exhaustive dim style checks and exact flame geometry assertions
- Check ALL frame chars (│┌┐└┘─▁) have exactly 'dim' style (not just first) - Verify flame row inner width equals iw exactly (kills lead/trail mutations) - Assert leading/trailing padding is spaces only (kills ' '→'XX XX') - Verify centering: lead <= trail + 1 (kills +body_w and //3 mutations) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ec70e3e commit 0f8033a

1 file changed

Lines changed: 95 additions & 40 deletions

File tree

tests/test_fireplace_visual.py

Lines changed: 95 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -479,36 +479,20 @@ def test_heat_rows_reduce_flame_budget(self):
479479
class TestBuildFireArtStyles:
480480
"""Verify dim style on structural frame elements."""
481481

482-
def test_top_edge_has_dim_style(self):
483-
"""Top edge ▁ characters should have 'dim' style."""
484-
text = _build_fire_art(50, 20)
485-
plain = text.plain
486-
idx = plain.index("\u2581")
487-
assert "dim" in _style_at(text, idx)
488-
489-
def test_outer_frame_top_has_dim_style(self):
490-
"""Outer frame ┌ should have 'dim' style."""
491-
text = _build_fire_art(50, 20)
492-
plain = text.plain
493-
idx = plain.index("\u250c")
494-
assert "dim" in _style_at(text, idx)
495-
496-
def test_outer_frame_bottom_has_dim_style(self):
497-
"""Outer frame └ should have 'dim' style."""
498-
text = _build_fire_art(50, 20)
499-
plain = text.plain
500-
idx = plain.index("\u2514")
501-
assert "dim" in _style_at(text, idx)
502-
503-
def test_inner_borders_have_dim_style(self):
504-
"""│ border characters should have 'dim' style."""
505-
text = _build_fire_art(50, 20)
482+
def test_all_frame_chars_have_dim_style(self):
483+
"""All structural frame characters must have 'dim' style exactly."""
484+
text = _build_fire_art(50, 20, fire_on=False)
506485
plain = text.plain
507-
idx = plain.index("\u2502")
508-
assert "dim" in _style_at(text, idx)
486+
frame_chars = set("\u2581\u250c\u2510\u2514\u2518\u2500\u2502")
487+
for idx, ch in enumerate(plain):
488+
if ch in frame_chars:
489+
style = _style_at(text, idx)
490+
assert style == "dim", (
491+
f"Char {ch!r} at offset {idx} has style {style!r}, expected 'dim'"
492+
)
509493

510494
def test_outer_hearth_has_dim_style(self):
511-
"""Outer hearth ▓ row should have 'dim' style."""
495+
"""Outer hearth ▓ row should have 'dim' style exactly."""
512496
text = _build_fire_art(50, 20)
513497
plain = text.plain
514498
lines = plain.split("\n")
@@ -518,13 +502,25 @@ def test_outer_hearth_has_dim_style(self):
518502
and not line.startswith("\u2502\u2502")
519503
and "\u2593" in line
520504
):
521-
# Outer hearth line
522505
line_offset = plain.index(line)
523-
hearth_idx = line.index("\u2593")
524-
assert "dim" in _style_at(text, line_offset + hearth_idx)
506+
for rel, ch in enumerate(line):
507+
if ch == "\u2593":
508+
assert _style_at(text, line_offset + rel) == "dim"
525509
return
526510
raise AssertionError("No outer hearth row found")
527511

512+
def test_frame_chars_with_fire_on(self):
513+
"""Frame chars have 'dim' style even with fire_on=True."""
514+
text = _build_fire_art(50, 20, fire_on=True)
515+
plain = text.plain
516+
frame_chars = set("\u2581\u250c\u2510\u2514\u2518\u2500\u2502")
517+
for idx, ch in enumerate(plain):
518+
if ch in frame_chars:
519+
style = _style_at(text, idx)
520+
assert style == "dim", (
521+
f"Char {ch!r} at offset {idx} has style {style!r}, expected 'dim'"
522+
)
523+
528524

529525
# ---------------------------------------------------------------------------
530526
# _build_fire_art – flame centering and geometry
@@ -613,24 +609,83 @@ def test_flame_row_min_width_respected(self):
613609
content = inner.strip()
614610
assert len(content) > 0
615611

616-
def test_flame_row_trailing_pad_not_negative(self):
617-
"""Trailing pad should never be negative (uses max(..., 0))."""
618-
# Use a narrow width to stress the trailing pad calculation
619-
w = 40
620-
text = _build_fire_art(w, 20, fire_on=True)
621-
plain = text.plain
612+
def test_flame_row_inner_width_exact(self):
613+
"""Flame row inner content exactly matches iw (kills lead/trail mutations)."""
614+
w = 60
622615
iw = w - 4
623-
lines = plain.split("\n")
616+
text = _build_fire_art(w, 20, fire_on=True)
617+
lines = text.plain.split("\n")
618+
for i, line in enumerate(lines):
619+
if not line.startswith("\u2502\u2502"):
620+
continue
621+
if not line.endswith("\u2502\u2502"):
622+
continue
623+
inner = line[2:-2]
624+
if "\u2591" in inner or "\u2593" in inner or inner.strip() == "":
625+
continue
626+
# Flame inner width must equal iw exactly
627+
assert len(inner) == iw, (
628+
f"Line {i}: inner width {len(inner)} != {iw}: {inner!r}"
629+
)
630+
631+
def test_flame_row_leading_spaces_only(self):
632+
"""Leading padding is only regular spaces (kills ' ' → 'XX XX')."""
633+
w = 60
634+
text = _build_fire_art(w, 20, fire_on=True)
635+
lines = text.plain.split("\n")
624636
for line in lines:
625637
if not line.startswith("\u2502\u2502"):
626638
continue
627639
if not line.endswith("\u2502\u2502"):
628640
continue
629641
inner = line[2:-2]
630-
if "\u2591" in inner or "\u2593" in inner:
642+
if "\u2591" in inner or "\u2593" in inner or inner.strip() == "":
643+
continue
644+
# Leading padding: everything before first non-space
645+
lead_count = len(inner) - len(inner.lstrip(" "))
646+
leading = inner[:lead_count]
647+
# Must be only spaces (kills " " → "XX XX" mutation)
648+
assert leading == " " * lead_count
649+
650+
def test_flame_row_trailing_spaces_only(self):
651+
"""Trailing padding is only regular spaces (kills ' ' → 'XX XX')."""
652+
w = 60
653+
text = _build_fire_art(w, 20, fire_on=True)
654+
lines = text.plain.split("\n")
655+
for line in lines:
656+
if not line.startswith("\u2502\u2502"):
657+
continue
658+
if not line.endswith("\u2502\u2502"):
659+
continue
660+
inner = line[2:-2]
661+
if "\u2591" in inner or "\u2593" in inner or inner.strip() == "":
662+
continue
663+
# Trailing padding: everything after last non-space
664+
trail_count = len(inner) - len(inner.rstrip(" "))
665+
trailing = inner[-trail_count:] if trail_count else ""
666+
# Must be only spaces
667+
assert trailing == " " * trail_count
668+
669+
def test_flame_centering_lead_roughly_half(self):
670+
"""Lead should be roughly (iw - body_w) // 2 (kills + and // 3)."""
671+
w = 60
672+
text = _build_fire_art(w, 20, fire_on=True)
673+
lines = text.plain.split("\n")
674+
for line in lines:
675+
if not line.startswith("\u2502\u2502"):
676+
continue
677+
if not line.endswith("\u2502\u2502"):
678+
continue
679+
inner = line[2:-2]
680+
if "\u2591" in inner or "\u2593" in inner or inner.strip() == "":
631681
continue
632-
# Inner should be at least iw wide (may be wider for flame min_w)
633-
assert len(inner) >= iw
682+
lead = len(inner) - len(inner.lstrip(" "))
683+
trail = len(inner) - len(inner.rstrip(" "))
684+
total_pad = lead + trail
685+
if total_pad > 1:
686+
# Lead should be <= trail (centering divides by 2)
687+
# With // 2 floor division, lead <= trail
688+
assert lead <= trail + 1, f"Centering off: lead={lead}, trail={trail}"
634689

635690

636691
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)