from __future__ import annotations import asyncio from pathlib import Path from repub.model import save_setting from repub.web import create_app def test_dev_mode_serves_published_feeds(monkeypatch, tmp_path: Path) -> None: db_path = tmp_path / "dev-mode.db" feeds_dir = tmp_path / "out" / "feeds" monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path)) async def run() -> None: app = create_app(dev_mode=True) app.config["REPUB_FEEDS_DIR"] = feeds_dir feed_path = feeds_dir / "demo-source" / "feed.rss" feed_path.parent.mkdir(parents=True) feed_path.write_text("\n", encoding="utf-8") client = app.test_client() response = await client.get("/feeds/demo-source/feed.rss") assert response.status_code == 200 assert response.mimetype == "application/rss+xml" assert await response.get_data(as_text=True) == "\n" asyncio.run(run()) def test_dev_mode_serves_feed_enclosure_assets(monkeypatch, tmp_path: Path) -> None: db_path = tmp_path / "dev-mode-assets.db" feeds_dir = tmp_path / "out" / "feeds" monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path)) async def run() -> None: app = create_app(dev_mode=True) app.config["REPUB_FEEDS_DIR"] = feeds_dir enclosure_path = feeds_dir / "demo-source" / "audio" / "episode.mp3" enclosure_path.parent.mkdir(parents=True) enclosure_path.write_bytes(b"mp3-data") client = app.test_client() response = await client.get("/feeds/demo-source/audio/episode.mp3") assert response.status_code == 200 assert await response.get_data() == b"mp3-data" asyncio.run(run()) def test_default_mode_serves_published_rss_feeds(monkeypatch, tmp_path: Path) -> None: db_path = tmp_path / "default-mode.db" feeds_dir = tmp_path / "out" / "feeds" monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path)) async def run() -> None: app = create_app() app.config["REPUB_FEEDS_DIR"] = feeds_dir feed_path = feeds_dir / "demo-source" / "feed.rss" feed_path.parent.mkdir(parents=True) feed_path.write_text("\n", encoding="utf-8") client = app.test_client() response = await client.get("/feeds/demo-source/feed.rss") assert response.status_code == 200 assert response.mimetype == "application/rss+xml" assert await response.get_data(as_text=True) == "\n" asyncio.run(run()) def test_default_mode_does_not_serve_feed_enclosure_assets( monkeypatch, tmp_path: Path ) -> None: db_path = tmp_path / "default-mode-assets.db" feeds_dir = tmp_path / "out" / "feeds" monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path)) async def run() -> None: app = create_app() app.config["REPUB_FEEDS_DIR"] = feeds_dir enclosure_path = feeds_dir / "demo-source" / "audio" / "episode.mp3" enclosure_path.parent.mkdir(parents=True) enclosure_path.write_bytes(b"mp3-data") client = app.test_client() response = await client.get("/feeds/demo-source/audio/episode.mp3") assert response.status_code == 404 asyncio.run(run()) def test_published_rss_rewrites_feed_url_to_https_host_header( monkeypatch, tmp_path: Path ) -> None: db_path = tmp_path / "rewrite-feed-url.db" feeds_dir = tmp_path / "out" / "feeds" monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path)) async def run() -> None: app = create_app() app.config["REPUB_FEEDS_DIR"] = feeds_dir save_setting("feed_url", "https://ocb.bypasscensorship.org") feed_path = feeds_dir / "mn-america-latina" / "feed.rss" feed_path.parent.mkdir(parents=True) feed_path.write_text( ( "" "https://ocb.bypasscensorship.org/feeds/" "mn-america-latina/images/full/example.jpg" "https://example.com/article" "\n" ), encoding="utf-8", ) client = app.test_client() response = await client.get( "/feeds/mn-america-latina/feed.rss", headers={"Host": "altmirror.example:8443"}, ) assert response.status_code == 200 assert response.mimetype == "application/rss+xml" assert await response.get_data(as_text=True) == ( "" "https://altmirror.example:8443/feeds/" "mn-america-latina/images/full/example.jpg" "https://example.com/article" "\n" ) assert response.headers["Access-Control-Allow-Origin"] == "*" assert response.headers["Access-Control-Allow-Methods"] == "GET, HEAD, OPTIONS" assert response.headers["Access-Control-Allow-Headers"] == "*" assert response.cache_control.public is True assert response.cache_control.max_age == 300 assert response.headers["ETag"] != "" asyncio.run(run()) def test_published_rss_supports_conditional_requests( monkeypatch, tmp_path: Path ) -> None: db_path = tmp_path / "conditional-rss.db" feeds_dir = tmp_path / "out" / "feeds" monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path)) async def run() -> None: app = create_app() app.config["REPUB_FEEDS_DIR"] = feeds_dir feed_path = feeds_dir / "demo-source" / "feed.rss" feed_path.parent.mkdir(parents=True) feed_path.write_text( "Demo\n", encoding="utf-8" ) client = app.test_client() first_response = await client.get("/feeds/demo-source/feed.rss") etag = first_response.headers["ETag"] second_response = await client.get( "/feeds/demo-source/feed.rss", headers={"If-None-Match": etag}, ) assert second_response.status_code == 304 assert await second_response.get_data(as_text=True) == "" assert second_response.headers["ETag"] == etag asyncio.run(run())