"""Tests for Flask web routes using the test client. Uses the real data/drafts.db so templates can render with actual data. """ from __future__ import annotations import sys import os import pytest # Ensure src is on path sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src")) from webui.app import create_app @pytest.fixture def client(): """Create a Flask test client in dev mode (admin enabled).""" # Reset auth module state so create_app can re-initialize import webui.auth as auth_mod auth_mod._initialized = False auth_mod._dev_mode = False app = create_app(dev=True) app.config["TESTING"] = True with app.test_client() as c: yield c @pytest.fixture def prod_client(): """Create a Flask test client in production mode (admin disabled).""" import webui.auth as auth_mod auth_mod._initialized = False auth_mod._dev_mode = False app = create_app(dev=False) app.config["TESTING"] = True with app.test_client() as c: yield c # ── Public pages ────────────────────────────────────────────────────── def test_overview_page(client): resp = client.get("/") assert resp.status_code == 200 def test_drafts_page(client): resp = client.get("/drafts") assert resp.status_code == 200 def test_authors_page(client): resp = client.get("/authors") assert resp.status_code == 200 def test_timeline_page(client): resp = client.get("/timeline") assert resp.status_code == 200 def test_search_page_empty(client): resp = client.get("/search") assert resp.status_code == 200 def test_search_page_with_query(client): resp = client.get("/search?q=agent") assert resp.status_code == 200 def test_about_page(client): resp = client.get("/about") assert resp.status_code == 200 def test_ratings_page(client): resp = client.get("/ratings") assert resp.status_code == 200 def test_citations_page(client): resp = client.get("/citations") assert resp.status_code == 200 def test_ideas_page(client): resp = client.get("/ideas") assert resp.status_code == 200 def test_idea_clusters_page(client): resp = client.get("/idea-clusters") assert resp.status_code == 200 def test_architecture_page(client): resp = client.get("/architecture") assert resp.status_code == 200 def test_impressum_page(client): resp = client.get("/impressum") assert resp.status_code == 200 def test_datenschutz_page(client): resp = client.get("/datenschutz") assert resp.status_code == 200 # ── 404 handling ────────────────────────────────────────────────────── def test_404_for_nonexistent_page(client): resp = client.get("/this-page-does-not-exist") assert resp.status_code == 404 def test_404_for_nonexistent_draft(client): resp = client.get("/drafts/draft-nonexistent-foobar-xyz") assert resp.status_code == 404 # ── Admin pages (dev mode) ─────────────────────────────────────────── def test_gaps_page_dev(client): resp = client.get("/gaps") assert resp.status_code == 200 def test_monitor_page_dev(client): resp = client.get("/monitor") assert resp.status_code == 200 def test_proposals_page_dev(client): resp = client.get("/proposals") assert resp.status_code == 200 # ── Admin pages (production = 404) ─────────────────────────────────── def test_gaps_page_prod_hidden(prod_client): resp = prod_client.get("/gaps") assert resp.status_code == 404 def test_monitor_page_prod_hidden(prod_client): resp = prod_client.get("/monitor") assert resp.status_code == 404 def test_proposals_page_prod_hidden(prod_client): resp = prod_client.get("/proposals") assert resp.status_code == 404 # ── API endpoints ───────────────────────────────────────────────────── def test_api_stats(client): resp = client.get("/api/stats") assert resp.status_code == 200 data = resp.get_json() assert isinstance(data, dict) assert "total_drafts" in data or "drafts" in data or len(data) > 0 def test_api_drafts(client): resp = client.get("/api/drafts") assert resp.status_code == 200 data = resp.get_json() assert isinstance(data, dict) def test_api_ratings(client): resp = client.get("/api/ratings") assert resp.status_code == 200 data = resp.get_json() assert isinstance(data, dict) def test_api_timeline(client): resp = client.get("/api/timeline") assert resp.status_code == 200 data = resp.get_json() assert isinstance(data, (dict, list)) def test_api_categories(client): resp = client.get("/api/categories") assert resp.status_code == 200 data = resp.get_json() assert isinstance(data, dict) def test_api_ideas(client): resp = client.get("/api/ideas") assert resp.status_code == 200 data = resp.get_json() assert isinstance(data, dict) def test_api_search_empty(client): resp = client.get("/api/search") assert resp.status_code == 200 data = resp.get_json() assert "drafts" in data def test_api_search_with_query(client): resp = client.get("/api/search?q=agent") assert resp.status_code == 200 data = resp.get_json() assert isinstance(data, dict) def test_api_draft_detail_not_found(client): resp = client.get("/api/drafts/nonexistent-draft-xyz") assert resp.status_code == 404 data = resp.get_json() assert "error" in data def test_api_architecture(client): resp = client.get("/api/architecture") assert resp.status_code == 200 data = resp.get_json() assert isinstance(data, dict) def test_api_idea_clusters(client): resp = client.get("/api/idea-clusters") assert resp.status_code == 200 def test_api_citations(client): resp = client.get("/api/citations") assert resp.status_code == 200 def test_api_author_network(client): resp = client.get("/api/authors/network") assert resp.status_code == 200 # ── CSV export format ───────────────────────────────────────────────── def test_api_drafts_csv(client): resp = client.get("/api/drafts?format=csv") assert resp.status_code == 200 assert "text/csv" in resp.content_type def test_api_categories_csv(client): resp = client.get("/api/categories?format=csv") assert resp.status_code == 200 assert "text/csv" in resp.content_type