Spaces:
Sleeping
test: cover render_summary and The Brief's zone dispatcher
Browse filesrender_summary is the branch's flagship renderer -- drift_summary's
renderer, the sole caller of render_tone_strip, and the only place the
spec's two anti-duplication rules become observable -- and had no
executable test at all.
Two tests in the established spy mould: six eligible deltas in must
produce exactly three cards plus the pointer at the full view, and a
tone-only brief must produce the trajectory sparkline alongside the
rl_summary_none empty state (Ruling A-8's path, previously pinned only
at the order level).
Also pins render()'s dispatcher: inverting `if key in zone_3: continue`
would ship commodity blocks above the fold and differentiated ones
inside a collapsed expander -- the precise inversion this sub-project
exists to fix -- with a green suite. All three tests were confirmed to
fail against a deliberately mutated implementation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- tests/test_brief_order.py +126 -0
|
@@ -317,3 +317,129 @@ def test_ask_cta_closes_the_sourced_facts_zone():
|
|
| 317 |
from dashboard.verdict import ZONE_2
|
| 318 |
|
| 319 |
assert ZONE_2[-1] == "ask_cta"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 317 |
from dashboard.verdict import ZONE_2
|
| 318 |
|
| 319 |
assert ZONE_2[-1] == "ask_cta"
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
# ββ render_summary: the flagship renderer βββββββββββββββββββββββββββββββββββ
|
| 323 |
+
#
|
| 324 |
+
# The Brief's promoted drift panel. It is the renderer for drift_summary, the
|
| 325 |
+
# SOLE caller of render_tone_strip, and the only place the spec's two
|
| 326 |
+
# anti-duplication rules ("at most three cards", "always point at the full
|
| 327 |
+
# view") become observable.
|
| 328 |
+
|
| 329 |
+
_TONE_METRIC = (
|
| 330 |
+
"hedge-word rate 27β13β15β55 per 10k words over FY2025βQ32026 "
|
| 331 |
+
"(rising 3 quarters) β more cautious"
|
| 332 |
+
)
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
def _tone_delta(term: str = "hedging language") -> dict:
|
| 336 |
+
delta = _delta("tone_trend", term, "HIGH")
|
| 337 |
+
delta["computed_metric"] = _TONE_METRIC
|
| 338 |
+
delta["source"] = "transcript"
|
| 339 |
+
return delta
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
def test_render_summary_shows_at_most_three_cards_and_points_at_the_full_view(
|
| 343 |
+
monkeypatch,
|
| 344 |
+
):
|
| 345 |
+
"""Both anti-duplication rules at the render level: The Brief promotes
|
| 346 |
+
only the top three wording changes, and always tells the reader where the
|
| 347 |
+
other three live. Nothing else covers either rule at any level."""
|
| 348 |
+
import dashboard.redline_view as mod
|
| 349 |
+
from dashboard.i18n import t
|
| 350 |
+
|
| 351 |
+
captured: list[str] = []
|
| 352 |
+
monkeypatch.setattr(
|
| 353 |
+
mod.st, "markdown", lambda html, **kw: captured.append(str(html))
|
| 354 |
+
)
|
| 355 |
+
|
| 356 |
+
brief = {"quarter_deltas": [
|
| 357 |
+
_delta("risk_added", f"drift {i}") for i in range(6)
|
| 358 |
+
]}
|
| 359 |
+
mod.render_summary(brief, limit=3)
|
| 360 |
+
|
| 361 |
+
joined = "".join(captured)
|
| 362 |
+
|
| 363 |
+
assert joined.count('class="primer-card"') == 3
|
| 364 |
+
assert "drift 0" in joined and "drift 1" in joined and "drift 2" in joined
|
| 365 |
+
assert "drift 3" not in joined
|
| 366 |
+
assert "drift 4" not in joined
|
| 367 |
+
assert "drift 5" not in joined
|
| 368 |
+
assert t("rl_summary_more").format(section=t("nav_signals")) in joined
|
| 369 |
+
|
| 370 |
+
|
| 371 |
+
def test_render_summary_shows_the_tone_strip_and_the_empty_state_for_a_tone_only_brief(
|
| 372 |
+
monkeypatch,
|
| 373 |
+
):
|
| 374 |
+
"""Ruling A-8's path at the render level, not just the order level:
|
| 375 |
+
tone_trend is excluded from top_deltas, so a tone-only brief must still
|
| 376 |
+
produce the trajectory sparkline AND say plainly that no wording changed
|
| 377 |
+
-- rather than an empty panel or a silent no-op."""
|
| 378 |
+
import dashboard.redline_view as mod
|
| 379 |
+
import dashboard.tone_strip as tone_mod
|
| 380 |
+
from dashboard.i18n import t
|
| 381 |
+
|
| 382 |
+
captured: list[str] = []
|
| 383 |
+
monkeypatch.setattr(
|
| 384 |
+
mod.st, "markdown", lambda html, **kw: captured.append(str(html))
|
| 385 |
+
)
|
| 386 |
+
monkeypatch.setattr(
|
| 387 |
+
tone_mod.st, "markdown", lambda html, **kw: captured.append(str(html))
|
| 388 |
+
)
|
| 389 |
+
|
| 390 |
+
mod.render_summary({"quarter_deltas": [_tone_delta()]}, limit=3)
|
| 391 |
+
|
| 392 |
+
joined = "".join(captured)
|
| 393 |
+
|
| 394 |
+
assert "<svg" in joined
|
| 395 |
+
assert "hedging language" in joined
|
| 396 |
+
assert t("rl_summary_none") in joined
|
| 397 |
+
assert 'class="primer-card"' not in joined
|
| 398 |
+
|
| 399 |
+
|
| 400 |
+
# ββ render(): the zone dispatcher βββββββββββββββββββββββββββββββββββββββββββ
|
| 401 |
+
|
| 402 |
+
def test_render_keeps_zone_3_inside_the_expander_and_everything_else_above_it(
|
| 403 |
+
monkeypatch,
|
| 404 |
+
):
|
| 405 |
+
"""The one behaviour of render()'s dispatcher. Inverting
|
| 406 |
+
`if key in zone_3: continue` would ship the commodity reference blocks
|
| 407 |
+
above the fold and the differentiated ones inside a collapsed expander --
|
| 408 |
+
the precise inversion this sub-project exists to fix -- with a green
|
| 409 |
+
suite."""
|
| 410 |
+
from contextlib import contextmanager
|
| 411 |
+
|
| 412 |
+
import dashboard.verdict as mod
|
| 413 |
+
|
| 414 |
+
seen: list[str] = []
|
| 415 |
+
|
| 416 |
+
@contextmanager
|
| 417 |
+
def _expander(*args, **kwargs):
|
| 418 |
+
seen.append("<expander>")
|
| 419 |
+
yield None
|
| 420 |
+
|
| 421 |
+
monkeypatch.setattr(mod.st, "markdown", lambda *a, **kw: None)
|
| 422 |
+
monkeypatch.setattr(mod.st, "expander", _expander)
|
| 423 |
+
monkeypatch.setattr(
|
| 424 |
+
mod, "_block_renderers",
|
| 425 |
+
lambda brief, ticker: {
|
| 426 |
+
key: (lambda k=key: seen.append(k))
|
| 427 |
+
for key in (*mod.ZONE_1, *mod.ZONE_2, *mod.ZONE_3)
|
| 428 |
+
},
|
| 429 |
+
)
|
| 430 |
+
|
| 431 |
+
brief = _full_brief()
|
| 432 |
+
mod.render(brief)
|
| 433 |
+
|
| 434 |
+
order = mod.brief_block_order(brief)
|
| 435 |
+
boundary = seen.index("<expander>")
|
| 436 |
+
above = seen[:boundary]
|
| 437 |
+
inside = seen[boundary + 1:]
|
| 438 |
+
|
| 439 |
+
assert inside, "the expander rendered nothing"
|
| 440 |
+
assert set(inside) == set(mod.ZONE_3)
|
| 441 |
+
assert set(above) == set(order) - set(mod.ZONE_3)
|
| 442 |
+
assert not set(above) & set(mod.ZONE_3)
|
| 443 |
+
# Order is preserved within each side, not merely partitioned.
|
| 444 |
+
assert above == [k for k in order if k not in set(mod.ZONE_3)]
|
| 445 |
+
assert inside == [k for k in order if k in set(mod.ZONE_3)]
|