"""Offline regressions for feed metadata, date ranking and challenge filtering.""" import sys from datetime import datetime, timezone from pathlib import Path from types import SimpleNamespace import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from omni import feeds, rank from omni.dates import parse_published from omni.model import Item from omni.sources import S @pytest.mark.parametrize("value", [ "2026-10-20T12:00:00Z", "2026-10-20T15:00:00+03:00", "Tue, 20 Oct 2026 12:00:00 GMT", "2026-10-20T12:00:00", "1792497600", "1792497600000", 1792497600, ]) def test_publication_formats_have_equal_freshness(value, monkeypatch): stamp = datetime(2026, 10, 20, 12, tzinfo=timezone.utc).timestamp() parsed = parse_published(value) assert parsed is not None assert parsed.timestamp() == stamp monkeypatch.setattr(rank.time, "time", lambda: stamp + 86400) assert rank._fresh(value) == pytest.approx(1 - 1 / 30) def test_date_only_and_invalid_dates(monkeypatch): stamp = datetime(2026, 10, 20, tzinfo=timezone.utc).timestamp() monkeypatch.setattr(rank.time, "time", lambda: stamp) assert rank._fresh("2026-10-20") == 1 for value in (None, "", "not a date", "99999999999999999999999999", "NaN"): assert parse_published(value) is None assert rank._fresh(value) == 0.3 assert rank._fresh("2020-01-01") == 0 assert parse_published("2026") is None assert parse_published("20261020") == datetime(2026, 10, 20, tzinfo=timezone.utc) def test_atom_alternate_links_author_and_date(monkeypatch): src = S("atom_test", "models", "rss", "https://example.invalid/feed.atom") xml = ''' Runtime release 2.0 Release team 2026-10-20T15:00:00+03:00 Faster inference and improved caching. ''' monkeypatch.setattr(feeds.net, "get", lambda *a, **kw: SimpleNamespace(status=200, text=xml)) rows = feeds.fetch(src) assert len(rows) == 1 assert rows[0].url == "https://example.invalid/releases/2.0" assert rows[0].author == "Release team" assert rows[0].published == "2026-10-20T12:00:00+00:00" def test_rss_namespaced_creator_and_no_author(monkeypatch): src = S("rss_test", "security", "rss", "https://example.invalid/feed") xml = ''' Security advisoryhttps://example.invalid/advisory Security teamTue, 20 Oct 2026 12:00:00 GMT New patch availablehttps://example.invalid/patch ''' monkeypatch.setattr(feeds.net, "get", lambda *a, **kw: SimpleNamespace(status=200, text=xml)) rows = feeds.fetch(src) assert len(rows) == 2 assert rows[0].author == "Security team" assert rows[0].published == "2026-10-20T12:00:00+00:00" assert rows[1].author == "" def test_fetch_drops_invalid_pages_but_keeps_short_real_posts(monkeypatch): src = S("test", "security", "rss", "https://example.invalid/feed", "test_adapter") def item(path, title, text=""): return Item("test", "entry", url=path, title=title, text=text) good = item("https://example.invalid/release", "v1.2") real = item("https://example.invalid/article", "Access denied", "Real analysis of authorization failure. " * 20) rows = [ item("", "A missing URL"), item("javascript:alert(1)", "A dangerous URL"), item("https://example.invalid/blank", ""), item("https://example.invalid/challenge", "Just a moment...", "Checking your browser"), item("https://example.invalid/denied", "Attention Required! | Cloudflare", "captcha"), item("https://example.invalid/long-challenge", "Just a moment...", "Checking your browser before accessing this site. " * 20), {"title": "Malformed adapter result"}, None, "not an Item", good, item(good.url, "Duplicate record"), real, ] monkeypatch.setitem(feeds.ADAPTERS, "test_adapter", lambda source, n: rows) assert feeds.fetch(src) == [good, real] def test_fetch_bad_record_does_not_discard_valid_siblings(monkeypatch): src = S("test", "security", "rss", "https://example.invalid/feed", "test_adapter") good = Item("test", "entry", url="https://example.invalid/release", title="Real release") bad = Item("test", "entry", url="https://example.invalid/bad", title="Malformed") bad.text = None monkeypatch.setitem(feeds.ADAPTERS, "test_adapter", lambda source, n: [bad, good]) assert feeds.fetch(src) == [good]