"""generator unit tests (test-after, Standard strategy). Covers: config/content ingestion, markdown→article fidelity (NFR7), layout + pagination (page breaks/running headers), self-contained zero-network emit (NFR4), empty-state (US10), no-fabricated-photos (FR7.4), graceful no-AI-draft (BR4.1), funnies embedding (US3). """ from __future__ import annotations import json import tempfile from pathlib import Path from newspaper.generator import ( load_config, load_content, run_generate, build_layout, emit_empty_state, emit_newspaper, ) from newspaper.generator.model import Article, Issue, MastheadConfig def _sample_project(tmp: Path, content: dict | None = None, article: str | None = None) -> None: cfg = tmp / "config.json" cfg.write_text(json.dumps(content or { "title": "The Wedding Times", "couple_names": "Sam & Alex", "date_line": "14 Sep", "issue_number": "1", "volume": "1", })) (tmp / "content").mkdir(exist_ok=True) if article is not None: (tmp / "content" / "lead.md").write_text(article) def test_config_loads_masthead(): with tempfile.TemporaryDirectory() as d: tmp = Path(d) _sample_project(tmp) m = load_config(tmp / "config.json") assert m.title == "The Wedding Times" assert m.couple_names == "Sam & Alex" def test_parse_article_fidelity(): md = "---\nheadline: The Big Day\nbyline: Sam & Alex\n---\nVows said & dancing began." with tempfile.TemporaryDirectory() as d: tmp = Path(d) _sample_project(tmp, article=md) arts = load_content(tmp / "content") assert len(arts) == 1 a = arts[0] assert "&" in a.body and "&" in a.headline # no mangled escaping def test_empty_content_emits_guided_empty_state(): with tempfile.TemporaryDirectory() as d: tmp = Path(d) _sample_project(tmp) out = run_generate(tmp) assert out.name == "newspaper.html" text = out.read_text() assert "Welcome" in text # friendly empty-state, not blank def test_layout_flows_pages_with_running_headers(): arts = [Article(f"a{i}", "article", f"Head {i}", "Body" * 20, "", "News") for i in range(9)] pages = build_layout(arts) assert len(pages) >= 1 assert all(p.running_header for p in pages) def test_emitted_newspaper_is_self_contained(): with tempfile.TemporaryDirectory() as d: tmp = Path(d) mh = MastheadConfig("T", "C", "d", "1", "1") issue = Issue("i", mh, [Article("a1", "article", "H", "B", "", "News")], build_layout([Article("a1", "article", "H", "B", "", "News")])) out = tmp / "newspaper.html" emit_newspaper(issue, out) text = out.read_text() assert "http://" not in text and "https://" not in text # NFR4 no remote def test_no_photos_no_fabricated_images(): with tempfile.TemporaryDirectory() as d: tmp = Path(d) _sample_project(tmp, article="Just text, no photos.") out = run_generate(tmp) assert "