Files
chicken_babies_site/tests/test_page_service.py
Phillip Tarrant 0306f71763 feat: phase 2 content model + cache — SQLite schema, markdown, TTL
Stand up the full SQLite content layer: all 7 tables from the authoritative
schema with WAL + foreign-keys enforced per-connection, entity dataclasses
plus row mappers, hand-rolled versioned migrations tracked in
schema_migrations, and an idempotent Python seed (system user + welcome
post + About page).

Add a Markdown->HTML service using markdown-it-py with a strict bleach
allowlist (tables intentionally omitted on both sides). Add a typed
in-process TTLCache[K,V] and wire it into real DB-backed PostService and
PageService, both exposing invalidate_all() for Phase 4 admin writes.

Rewire / and /about to read from the DB; homepage renders the seeded
welcome post, About renders page.title + sanitized body_html_cached.
Update the Phase 1 route tests accordingly.

Mark Phase 2 complete in docs/ROADMAP.md.
2026-04-21 15:40:35 -05:00

54 lines
1.8 KiB
Python

"""Tests for :class:`app.services.pages.PageService`.
Uses the session-scoped seeded ``db_engine`` fixture.
"""
from __future__ import annotations
from sqlalchemy import Engine
from app.models.entities import Page
from app.services.pages import PageService
def test_get_by_slug_returns_seeded_about_page(db_engine: Engine) -> None:
"""The seeded About page loads as a :class:`Page` dataclass."""
service = PageService(db_engine)
page = service.get_by_slug("about")
assert page is not None
assert isinstance(page, Page)
assert page.slug == "about"
assert page.title == "About the Farm"
# The sanitized HTML must contain a <p> since the seed Markdown
# has multiple paragraphs; this also proves the Markdown pipeline
# ran at seed time.
assert "<p>" in page.body_html_cached
assert page.published is True
def test_get_by_slug_returns_none_for_unknown_slug(db_engine: Engine) -> None:
"""Unknown slugs return ``None`` rather than raising."""
service = PageService(db_engine)
assert service.get_by_slug("does-not-exist") is None
def test_get_by_slug_is_cached(db_engine: Engine) -> None:
"""The TTL cache wraps page lookups keyed by slug."""
service = PageService(db_engine)
first = service.get_by_slug("about")
second = service.get_by_slug("about")
assert first is second
def test_invalidate_all_forces_reload(db_engine: Engine) -> None:
"""After :meth:`invalidate_all` the next call re-hits the DB."""
service = PageService(db_engine)
first = service.get_by_slug("about")
service.invalidate_all()
second = service.get_by_slug("about")
assert first is not second
# Same slug, same row — content equal, identity different.
assert first is not None and second is not None
assert first.slug == second.slug == "about"