"""Tests for the message-type normalization parser (Task 1.6). The parser must be total — it never raises on weird input — because every incoming WeChat record runs through it during a scrape, and one malformed type code must not abort the whole pull. Unknown codes pass through as ``"unknown"`` so the message is still ingested (and recoverable via ``raw_json``); only the ``-2`` date-divider code maps to ``"divider"``, which the scraper uses as its drop signal. """ from __future__ import annotations import pytest from app.scraper.parsers import normalize_wechat_type @pytest.mark.parametrize( "raw,expected", [ # Phase-0 confirmed codes (see docs/superpowers/specs/phase0-findings.md §2). (1, "text"), (-2, "divider"), # date separator — NOT a real message (scraper drops it) (2, "image"), # image / sticker (webp) — file/fileTh are direct URLs (3, "image_legacy"), # old image format — file is an opaque ID (needs another endpoint) (4, "video"), # mp4 — file is a direct URL (10, "system"), # system / link / card / invite — non-media, skip download # Still-unconfirmed codes — pass through as "unknown", never dropped. # (6, 9, 13, 15, 21, 22 — voice/file/transfer/redpacket/quote/etc; raw_json retains the code.) (6, "unknown"), (9, "unknown"), (34, "unknown"), # voice (legacy WeChat code, not yet seen in yunke) (49, "unknown"), # file / link / transfer (10000, "unknown"), # Stringified ints (the upstream API may send either form). ("1", "text"), ("-2", "divider"), ("2", "image"), ("3", "image_legacy"), ("4", "video"), ("10", "system"), ("34", "unknown"), ], ) def test_normalize_wechat_type_maps_known_and_unknown(raw, expected): assert normalize_wechat_type(raw) == expected def test_normalize_wechat_type_never_raises(): """Whatever we throw at it, it returns a string — never raises.""" for raw in (None, "", "junk", "1.5", [], {}, object(), float("nan")): out = normalize_wechat_type(raw) assert isinstance(out, str) assert out == "unknown"