"""iso(): the single date/datetime→JSON serializer the routes share (R6 S1a); to_tsquery_str().""" from datetime import date, datetime, timezone from app.utils import iso, normalize_description, to_tsquery_str def test_none_maps_to_none(): assert iso(None) is None def test_plain_date_serializes_as_iso_date(): # MediaAsset.upload_date is a `date`, not a datetime — the contract must accept it. assert iso(date(2026, 7, 26)) == "2026-07-26" def test_aware_datetime_keeps_offset(): dt = datetime(2026, 7, 26, 12, 30, 0, tzinfo=timezone.utc) assert iso(dt) == "2026-07-26T12:30:00+00:00" def test_naive_datetime_serializes_without_offset(): dt = datetime(2026, 7, 26, 12, 30, 0) assert iso(dt) == "2026-07-26T12:30:00" def test_matches_datetime_isoformat_contract(): # iso is exactly `dt.isoformat()` for a present value — guards the routes that used to # hand-roll `x.isoformat() if x else None`. dt = datetime(2020, 1, 2, 3, 4, 5, 678901, tzinfo=timezone.utc) assert iso(dt) == dt.isoformat() def test_normalize_description_none_stays_none(): assert normalize_description(None) is None def test_normalize_description_drops_blank_lines(): # A YouTube contact block padded with runs of blank lines — the waste we strip before storing. raw = "Contact us\n\n\nEmail: a@b.com\n \nInstagram: @x\n\n\n" assert normalize_description(raw) == "Contact us\nEmail: a@b.com\nInstagram: @x" def test_normalize_description_right_strips_and_trims(): assert normalize_description(" hi there \n\n bye ") == " hi there\n bye" def test_normalize_description_all_blank_collapses_to_empty(): assert normalize_description("\n \n\t\n") == "" def test_normalize_description_single_line_unchanged(): assert normalize_description("just one line") == "just one line" def test_normalize_description_folds_crlf_line_endings(): # splitlines() folds CR/CRLF to \n — a documented, benign line-ending normalization. assert normalize_description("a\r\nb\r\n\r\nc") == "a\nb\nc" def test_tsquery_prefix_matches_a_last_word_of_three_or_more(): assert to_tsquery_str("ti amo magyar") == "ti & amo & magyar:*" assert to_tsquery_str("min") == "min:*" def test_tsquery_matches_a_short_last_word_whole(): # A 1-2 letter prefix made ts_rank score most of the library (5-8 s on prod, E31 S4e). assert to_tsquery_str("m") == "m" assert to_tsquery_str("minecraft 4k") == "minecraft & 4k" assert to_tsquery_str("ti amo m") == "ti & amo & m" def test_tsquery_without_a_word_is_none(): assert to_tsquery_str("?! --") is None