Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 8 additions & 1 deletion heart/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -1413,8 +1413,15 @@ def _copy_btn(payload: str, label: str = "copy", face: str = "πŸ“‹") -> str:
``face`` is what the button shows: the bare πŸ“‹ for a chip beside a row, a
short worded face (⌨ command chain) where the board offers more than one
payload and the reader has to choose between them.

A worded face takes the theme's `text` modifier. The base `button.copy` is
a fixed 2.6rem SQUARE β€” right for a bare glyph, and a trap for words: the
label wrapped inside 42px into a one-word-per-line column and spilled out
of its own box. Whitespace in the face is the test, because that is what
makes a face a phrase rather than a glyph.
"""
return (f"<button class='copy' type='button' "
cls = "copy text" if len(face.split()) > 1 else "copy"
return (f"<button class='{cls}' type='button' "
f"title='{_html.escape(label, quote=True)}' "
f"data-cmd=\"{_html.escape(payload, quote=True)}\">{_html.escape(face)}</button>")

Expand Down
24 changes: 24 additions & 0 deletions tests/test_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,30 @@ def test_surfaces_render_the_remedies_and_the_plan():
assert all("command" in b for b in d["blockers"])


def test_a_worded_copy_face_is_a_chip_and_a_glyph_stays_a_square():
"""The theme sizes `button.copy` as a fixed 2.6rem SQUARE. A face carrying
words needs the `text` modifier or the label wraps inside 42px into a
one-word-per-line column and spills out of the box β€” which is what the
plan line did until it was caught on a laptop.

Asserted per button rather than by position: the invariant is "this face
has words, so this button is a chip", which stays true however the board
reorders its tiers.
"""
v = _stale_verdict(GAPS, ["install_unknown", "test_unknown"])
html = dashboard.render(make_snapshot(), v, fmt="html", now=FRESH_NOW)

buttons = re.findall(r"<button class='(copy[^']*)'[^>]*>([^<]*)</button>", html)
assert buttons, "no copy buttons on the board at all"
for cls, face in buttons:
is_chip = "text" in cls.split()
assert is_chip == (len(face.split()) > 1), (cls, face)

faces = [f for _, f in buttons]
assert "\U0001f4cb clear them all" in faces # a worded chip is on show
assert "\U0001f4cb" in faces # and a bare glyph beside it


def test_the_plan_stays_off_a_board_showing_another_tier():
# The board shows one tier at a time; a plan for gaps the reader cannot see
# is noise (the json surface still carries it as data).
Expand Down
Loading