84 lines
3.0 KiB
Python
84 lines
3.0 KiB
Python
import json
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
from src.fetcher import fetch_and_cache_articles
|
|
from src.models import Article, Image
|
|
from tests.conftest import SAMPLE_RSS_XML
|
|
|
|
|
|
def _mock_feed_response(xml_content):
|
|
mock = MagicMock()
|
|
mock.content = xml_content.encode("utf-8")
|
|
mock.text = xml_content
|
|
mock.status_code = 200
|
|
mock.raise_for_status = MagicMock()
|
|
return mock
|
|
|
|
|
|
def test_fetch_creates_articles(app, db):
|
|
with app.app_context():
|
|
with patch("src.fetcher.requests.get") as mock_get:
|
|
mock_get.return_value = _mock_feed_response(SAMPLE_RSS_XML)
|
|
with patch("src.fetcher.process_image") as mock_img:
|
|
mock_img.return_value = ("/fake/path.jpg", 800, 450)
|
|
result = fetch_and_cache_articles()
|
|
|
|
assert result["new"] == 2
|
|
assert result["skipped"] == 0
|
|
articles = Article.query.order_by(Article.pub_date).all()
|
|
assert len(articles) == 2
|
|
assert articles[0].title == "Test Article One"
|
|
assert articles[1].title == "Test Article Two"
|
|
|
|
|
|
def test_fetch_deduplicates(app, db):
|
|
with app.app_context():
|
|
with patch("src.fetcher.requests.get") as mock_get:
|
|
mock_get.return_value = _mock_feed_response(SAMPLE_RSS_XML)
|
|
with patch("src.fetcher.process_image") as mock_img:
|
|
mock_img.return_value = ("/fake/path.jpg", 800, 450)
|
|
fetch_and_cache_articles()
|
|
result = fetch_and_cache_articles()
|
|
|
|
assert result["new"] == 0
|
|
assert result["skipped"] == 2
|
|
assert Article.query.count() == 2
|
|
|
|
|
|
def test_fetch_downloads_images(app, db):
|
|
with app.app_context():
|
|
with patch("src.fetcher.requests.get") as mock_get:
|
|
mock_get.return_value = _mock_feed_response(SAMPLE_RSS_XML)
|
|
with patch("src.fetcher.process_image") as mock_img:
|
|
mock_img.return_value = ("/fake/path.jpg", 800, 450)
|
|
fetch_and_cache_articles()
|
|
|
|
images = Image.query.all()
|
|
assert len(images) == 1
|
|
assert images[0].original_url == "https://example.com/image1.jpg"
|
|
|
|
|
|
def test_fetch_rewrites_image_src(app, db):
|
|
with app.app_context():
|
|
with patch("src.fetcher.requests.get") as mock_get:
|
|
mock_get.return_value = _mock_feed_response(SAMPLE_RSS_XML)
|
|
with patch("src.fetcher.process_image") as mock_img:
|
|
mock_img.return_value = ("/fake/path.jpg", 800, 450)
|
|
fetch_and_cache_articles()
|
|
|
|
article = Article.query.filter_by(
|
|
guid="https://example.com/?p=1001"
|
|
).first()
|
|
assert "https://example.com/image1.jpg" not in article.content_html
|
|
assert "/fake/path.jpg" in article.content_html
|
|
|
|
|
|
def test_fetch_handles_feed_error(app, db):
|
|
with app.app_context():
|
|
with patch("src.fetcher.requests.get") as mock_get:
|
|
mock_get.side_effect = Exception("Network error")
|
|
result = fetch_and_cache_articles()
|
|
|
|
assert result["error"] is not None
|
|
assert Article.query.count() == 0
|