"""Smoke tests for the public-site routes. These tests focus on contract rather than styling: - every public route returns 200 with an HTML content-type - each page contains a page-specific substring (proves the template actually rendered, not just that the route exists) - the homepage renders the Phase 2 seeded welcome post title - the About page renders the Phase 2 seeded About markdown - the shared layout emits the logo image path - the About nav link carries ``aria-current="page"`` Phase 2 updates: the homepage no longer shows "No posts yet" because the seed inserts a welcome post, and the About page content now comes from the DB-backed ``pages`` row rather than the old static template. """ from __future__ import annotations import pytest from fastapi.testclient import TestClient from app.main import app @pytest.fixture(scope="module") def client() -> TestClient: """Return a module-scoped FastAPI TestClient. TestClient uses the module-level `app` built by `create_app()` at import time — i.e. the exact same app uvicorn runs in production, including migrations + seed. """ return TestClient(app) @pytest.mark.parametrize( "path,expected_substring", [ ("/", "Chicken Babies"), # Phase 2: the About page renders the seeded page title # "About the Farm" (h1 from the template + page.title). ("/about", "About the Farm"), ("/contact", "Get in touch"), ("/shop", "Coming soon"), ], ) def test_public_route_renders_html( client: TestClient, path: str, expected_substring: str, ) -> None: """Every public page returns 200 HTML containing a page-specific string. The substring is intentionally a headline the template owns so the test fails loudly if the wrong template is accidentally wired up. """ response = client.get(path) assert response.status_code == 200, ( f"{path} returned {response.status_code}: {response.text[:200]}" ) content_type = response.headers.get("content-type", "") assert content_type.startswith("text/html"), ( f"{path} returned unexpected content-type: {content_type!r}" ) assert expected_substring in response.text, ( f"{path} body missing expected substring {expected_substring!r}" ) def test_home_shows_welcome_post(client: TestClient) -> None: """The Phase 2 seed inserts a welcome post; its title appears on /. Replaces the Phase 1 "No posts yet" assertion now that the DB has a real published row on first boot. """ response = client.get("/") assert response.status_code == 200 assert "Welcome to the Farm" in response.text def test_about_renders_seeded_markdown(client: TestClient) -> None: """The About page body comes from the seeded ``pages`` row. Picks a distinctive substring from the seeded Markdown so the assertion fails if the old static template ever comes back. """ response = client.get("/about") assert response.status_code == 200 # Substring from the seeded About markdown paragraph 1. assert "small family farm" in response.text # Seeded copy explicitly does not expose a street address. # Spot-check: the word "Morrison" appears (town-level). assert "Morrison" in response.text def test_layout_includes_logo_image(client: TestClient) -> None: """Shared layout references the generated logo asset paths. We check for the stem (``/static/img/logo.``) rather than a specific extension so both the and markup are covered by a single assertion. """ response = client.get("/") assert response.status_code == 200 assert "/static/img/logo." in response.text def test_nav_marks_active_page(client: TestClient) -> None: """The About page renders ``aria-current=\"page\"`` on its nav link. Exercises the shared layout's active-nav logic end-to-end without inspecting internals. """ response = client.get("/about") assert response.status_code == 200 # The pair should appear exactly once per active link; we only need # to prove it's present at all. assert 'aria-current="page"' in response.text