from datetime import datetime, timezone from chorus_bot import ping def test_build_and_parse_round_trip(): captured_at = datetime(2026, 7, 13, 7, 0, 0, tzinfo=timezone.utc) embed = ping.build_ping_embed( modality="bh_email", sender_id="jane@example.com", snippet="I have some books to donate...", raw_content="I have some books to donate. Full text goes here.", captured_at=captured_at, ) assert "bh_email" in embed.title or "bh_email" in str(embed.fields) assert "I have some books to donate..." in (embed.description or "") parsed = ping.parse_ping_embed(embed) assert parsed["modality"] == "bh_email" assert parsed["sender_id"] == "jane@example.com" assert parsed["raw_content"] == "I have some books to donate. Full text goes here." assert parsed["captured_at"] == captured_at def test_build_ping_embed_handles_missing_sender(): embed = ping.build_ping_embed( modality="voice", sender_id=None, snippet="call about donation", raw_content="call about donation", captured_at=datetime(2026, 7, 13, 8, 0, 0, tzinfo=timezone.utc), ) parsed = ping.parse_ping_embed(embed) assert parsed["sender_id"] is None def test_build_and_parse_empty_raw_content(): """Verify empty raw_content round-trips correctly without being converted to '(empty)'.""" captured_at = datetime(2026, 7, 13, 9, 0, 0, tzinfo=timezone.utc) embed = ping.build_ping_embed( modality="bh_email", sender_id="test@example.com", snippet="Empty message", raw_content="", captured_at=captured_at, ) parsed = ping.parse_ping_embed(embed) assert parsed["raw_content"] == "", "Empty raw_content should round-trip as empty string, not '(empty)'" def test_build_ping_embed_never_produces_empty_field_value_for_empty_raw_content(): """Regression guard for C1: Discord's API rejects embed field values with length 0 (HTTP 400). Every field value must have len() >= 1 after build_ping_embed runs, even when raw_content is ''.""" embed = ping.build_ping_embed( modality="bh_email", sender_id="test@example.com", snippet="Empty message", raw_content="", captured_at=datetime(2026, 7, 13, 9, 0, 0, tzinfo=timezone.utc), ) for field in embed.fields: assert len(field.value) >= 1, f"field {field.name!r} has an empty value" def test_build_ping_embed_never_produces_empty_field_value_for_sender_id_none(): """Regression guard for C1: manual_share.py always calls build_ping_embed with sender_id=None. Every field value must still have len() >= 1.""" embed = ping.build_ping_embed( modality="voice", sender_id=None, snippet="call about donation", raw_content="call about donation", captured_at=datetime(2026, 7, 13, 8, 0, 0, tzinfo=timezone.utc), ) for field in embed.fields: assert len(field.value) >= 1, f"field {field.name!r} has an empty value" def test_build_ping_embed_truncates_long_raw_content(): """Regression guard for C2: embed field values over 1024 chars are rejected by Discord. build_ping_embed must truncate defensively.""" long_body = "x" * 2000 embed = ping.build_ping_embed( modality="bh_email", sender_id="jane@example.com", snippet="long email", raw_content=long_body, captured_at=datetime(2026, 7, 13, 9, 0, 0, tzinfo=timezone.utc), ) raw_content_field = next(f for f in embed.fields if f.name == "raw_content") assert len(raw_content_field.value) <= 1024 assert "truncated" in raw_content_field.value