amplegest / tests /test_dashboard_components.py
Viney's picture
feat: multi-provider LLM support, prominent chat, design pass, and new analytics
7880373
Raw
History Blame Contribute Delete
7.32 kB
"""Unit tests for dashboard/components.py HTML helpers."""
from __future__ import annotations
import pytest
from unittest.mock import patch, MagicMock
def test_ai_badge_default_label():
from dashboard.components import ai_badge
html = ai_badge()
assert "✦ AI Synthesis" in html
assert "#7c3aed" in html
assert "#ede9fe" in html
def test_ai_badge_custom_label():
from dashboard.components import ai_badge
html = ai_badge("AI")
assert "✦ AI" in html
assert "#7c3aed" in html
def test_interpretation_card_contains_badge_and_content():
from dashboard.components import interpretation_card
html = interpretation_card("What matters most", "<p>Some insight</p>")
assert "✦ AI Synthesis" in html
assert "#8b5cf6" in html # purple border (PURPLE token value)
# card background is now white (#ffffff), not lavender AI_BG
assert "What matters most" in html
assert "<p>Some insight</p>" in html
def test_interpretation_card_custom_badge_label():
from dashboard.components import interpretation_card
html = interpretation_card("Language shift", "<p>tone changed</p>", badge_label="AI")
assert "✦ AI" in html
assert "Language shift" in html
def _render_signal(sig) -> str:
"""Render a Signal through signal_card and return the produced HTML."""
import streamlit as st
from dashboard.components import signal_card
with patch.object(st, "markdown") as mock_md:
signal_card(sig)
return mock_md.call_args[0][0]
def test_signal_card_tension_variant():
"""Tension variant: two-sided body, exactly one ✦ AI badge in the header."""
from dashboard.signal_feed import Signal
html = _render_signal(Signal(
kind="tension",
headline="Revenue beat hides quality decline",
stance="mixed",
significance="HIGH",
extra={
"bullish_reading": "Strong top-line momentum",
"bearish_reading": "One-time item inflated result",
"bullish_evidence": {"evidence_snippet": "q1", "reliability": "HIGH", "source": "10-Q"},
"bearish_evidence": {"evidence_snippet": "q2", "reliability": "HIGH", "source": "10-Q"},
},
))
assert "✦ AI · experimental" in html
assert html.count("✦ AI") == 1 # badge is in the outer header, not per reading panel
assert "Strong top-line momentum" in html
assert "One-time item inflated result" in html
assert "Surface reading" in html
assert "Deeper reading" in html
assert "Material" in html # priority label, not raw HIGH/MED/LOW
# mixed stance β†’ amber accent, never bull green or bear red on the frame
assert "#f59e0b" in html
def test_signal_card_quality_variant():
"""Quality variant: assessment chip + rationale + AI badge (AI-assessed kind)."""
from dashboard.signal_feed import Signal
html = _render_signal(Signal(
kind="quality",
body="Management raised full-year guidance for the third consecutive quarter.",
stance="bull",
category="guidance_dynamics",
extra={"assessment": "positive"},
evidence_snippet="raised guidance",
source="10-Q", reliability="HIGH",
))
assert "Management raised full-year guidance" in html
assert "Guidance" in html # dimension label for guidance_dynamics
assert "β–²" in html
assert "Positive" in html
assert "✦ AI · experimental" in html # quality assessments are experimental AI
assert "#10b981" in html # bull stance β†’ green accent
def test_signal_card_delta_variant_redline():
"""Delta variant: computed-metric box + before/after redline, no AI badge."""
from dashboard.signal_feed import Signal
html = _render_signal(Signal(
kind="delta",
headline="export controls",
body="2β†’8 occurrences (+300%)",
stance="bear",
significance="HIGH",
category="term_frequency",
before_text="limited exposure to export restrictions",
after_text="new export restrictions may materially affect revenue",
source="10-Q",
period_range="4Q2024 β†’ 1Q2025",
))
assert "computed" in html
assert "2β†’8 occurrences" in html
assert "before" in html and "after" in html
assert "4Q2024 β†’ 1Q2025" in html
assert "✦ AI" not in html # deltas are deterministic, not AI
assert "Heuristic Β· validate" in html
def test_signal_card_risk_new_badge():
"""Risk variant: category chip + NEW badge when is_new."""
from dashboard.signal_feed import Signal
html = _render_signal(Signal(
kind="risk",
body="China exposure may affect supply chains.",
stance="bear",
significance="HIGH",
category="Geopolitical",
is_new=True,
source="10-K", reliability="HIGH", impact="HIGH",
))
assert "Geopolitical" in html
assert "NEW" in html
assert "#ef4444" in html # bear stance β†’ red accent
# ── New helper tests ──────────────────────────────────────────────────────────
def test_eyebrow_label():
from dashboard.components import eyebrow_label
html = eyebrow_label("what changed")
assert "text-transform:uppercase" in html
assert "what changed" in html
assert "letter-spacing" in html
html_colored = eyebrow_label("section", color="#ef4444")
assert "#ef4444" in html_colored
def test_importance_marker_levels():
from dashboard.components import importance_marker
high = importance_marker("HIGH")
assert "Critical" in high
assert "#0f172a" in high
assert "●" in high
# monochrome only β€” no green or red signal colors
assert "#10b981" not in high
assert "#ef4444" not in high
medium = importance_marker("MEDIUM")
assert "Important" in medium
assert "#64748b" in medium
assert "●" in medium
low = importance_marker("LOW")
assert "Context" in low
assert "#94a3b8" in low
assert "●" in low
# Unknown / empty returns empty string
assert importance_marker("") == ""
def test_meta_row_formatting():
from dashboard.components import meta_row
result = meta_row("HIGH", "10-Q", "HIGH")
assert "High confidence" in result
assert "10-Q" in result
assert "Critical" in result # from importance_marker("HIGH")
# All empty β†’ empty string
assert meta_row("", "", "") == ""
result2 = meta_row("MEDIUM", "transcript", "LOW")
assert "Med. confidence" in result2
assert "transcript" in result2
assert "Context" in result2 # from importance_marker("LOW")
def test_sort_by_impact_order():
from dashboard.components import sort_by_impact
items = [
{"impact": "HIGH", "name": "h"},
{"impact": "LOW", "name": "l"},
{"impact": "MEDIUM", "name": "m"},
{"name": "none"}, # missing "impact" key
]
original = list(items) # copy to check mutation
sorted_items = sort_by_impact(items)
assert [i.get("impact", "") for i in sorted_items] == ["HIGH", "MEDIUM", "LOW", ""]
# Original list must not be mutated
assert items == original