from app.screener.ai_news import telegram as tg def _row(ticker, score, reason="r"): return {"ticker": ticker, "score_raw": score, "reason": reason, "news_count": 5, "tokens_input": 100, "tokens_output": 20, "model": "m"} def test_build_message_includes_top_sections(): msg = tg.build_message( asof="2026-05-13", top_pos=[_row("005930", 8.5, "HBM 호재")], top_neg=[_row("373220", -6.3, "수주 지연")], tokens_input=10000, tokens_output=2000, ) assert "AI 뉴스 분석" in msg assert "호재 Top" in msg assert "악재 Top" in msg assert "005930" in msg assert "8.5" in msg assert "HBM" in msg assert "373220" in msg def test_build_message_escapes_markdownv2_specials(): msg = tg.build_message( asof="2026-05-13", top_pos=[_row("005930", 3.0, "테스트(괄호) [대괄호]")], top_neg=[], tokens_input=100, tokens_output=20, ) # MarkdownV2 특수문자 ( ) [ ] 이 escape 되어야 함 assert r"\(" in msg or r"\)" in msg assert r"\[" in msg or r"\]" in msg def test_build_message_cost_won_line(): msg = tg.build_message( asof="2026-05-13", top_pos=[], top_neg=[], tokens_input=10000, tokens_output=2000, ) # tokens_input × 0.0013 + tokens_output × 0.0065 = 13 + 13 = ₩26 assert "₩26" in msg or "₩ 26" in msg or "₩" in msg def test_build_message_empty_lists(): msg = tg.build_message( asof="2026-05-13", top_pos=[], top_neg=[], tokens_input=0, tokens_output=0, ) # 빈 리스트라도 헤더는 있어야 함 assert "호재 Top" in msg assert "악재 Top" in msg