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 # score는 MarkdownV2 escape 거쳐 "8\.5" 형태 ('.' 가 reserved) 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