import os import threading from http.server import HTTPServer from http.server import SimpleHTTPRequestHandler from pathlib import Path from typing import TYPE_CHECKING import pytest from feeds.models import Entry from feeds.models import Feed from feeds.services import fetch_and_archive_feed if TYPE_CHECKING: from pathlib import Path @pytest.mark.django_db def test_entry_id_string_guid_dict(tmp_path: Path) -> None: """Test that entry_id is always a string, even if guid is a dict.""" # Prepare a fake RSS feed with guid as dict (attributes) feed_content = """ Test Feed http://example.com/ Test feed description Item 1 http://example.com/item1 http://example.com/item1 """ feed_path: Path = tmp_path / "test_feed.xml" feed_path.write_text(feed_content, encoding="utf-8") os.chdir(tmp_path) server = HTTPServer(("localhost", 0), SimpleHTTPRequestHandler) port: int = server.server_address[1] thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start() url: str = f"http://localhost:{port}/test_feed.xml" feed: Feed = Feed.objects.create(url=url, domain="localhost") fetch_and_archive_feed(feed) entry: Entry | None = Entry.objects.filter(feed=feed).first() assert entry is not None assert isinstance(entry.entry_id, str) assert entry.entry_id == "http://example.com/item1" server.shutdown() @pytest.mark.django_db def test_entry_id_string_guid_string(tmp_path: Path) -> None: """Test that entry_id is a string when guid is a plain string.""" feed_content = """ Test Feed http://example.com/ Test feed description Item 2 http://example.com/item2 http://example.com/item2 """ feed_path: Path = tmp_path / "test_feed.xml" feed_path.write_text(feed_content, encoding="utf-8") os.chdir(tmp_path) server = HTTPServer(("localhost", 0), SimpleHTTPRequestHandler) port: int = server.server_address[1] thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start() url: str = f"http://localhost:{port}/test_feed.xml" feed: Feed = Feed.objects.create(url=url, domain="localhost") fetch_and_archive_feed(feed) entry: Entry | None = Entry.objects.filter(feed=feed).first() assert entry is not None assert isinstance(entry.entry_id, str) assert entry.entry_id == "http://example.com/item2" server.shutdown() @pytest.mark.django_db def test_entry_id_fallback_to_link(tmp_path: Path) -> None: """Test that entry_id falls back to link if guid/id missing.""" feed_content = """ Test Feed http://example.com/ Test feed description Item 3 http://example.com/item3 """ feed_path: Path = tmp_path / "test_feed.xml" feed_path.write_text(feed_content, encoding="utf-8") os.chdir(tmp_path) server = HTTPServer(("localhost", 0), SimpleHTTPRequestHandler) port: int = server.server_address[1] thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start() url: str = f"http://localhost:{port}/test_feed.xml" feed: Feed = Feed.objects.create(url=url, domain="localhost") fetch_and_archive_feed(feed) entry: Entry | None = Entry.objects.filter(feed=feed).first() assert entry is not None assert isinstance(entry.entry_id, str) assert entry.entry_id == "http://example.com/item3" server.shutdown()