from __future__ import annotations import json import unittest from pathlib import Path from types import SimpleNamespace import sys from unittest.mock import patch ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(ROOT / "scripts")) import build import translate_site from scisiteforge.content import SiteContent, cards_from_config, load_citegeist_cards, load_didactopus_cards, load_doclift_cards, load_groundrecall_cards from scisiteforge.notebook import load_notebooks, render_notebooks from scisiteforge.themes import get_theme, materialize_theme from scisiteforge.translations import GenieHiveTranslator, TranslationConfig class SciSiteForgeTests(unittest.TestCase): def test_theme_materialization_copies_theme_assets(self) -> None: from tempfile import TemporaryDirectory with TemporaryDirectory() as tmp: tmp_path = Path(tmp) theme = get_theme("talkorigins-modern") payload = materialize_theme(theme, tmp_path) self.assertTrue((tmp_path / "theme" / "style.css").exists()) self.assertTrue((tmp_path / "theme" / "main.js").exists()) self.assertTrue((tmp_path / "theme" / "assets" / "toa.ico").exists()) self.assertTrue((tmp_path / "theme" / "assets" / "toa_logo_001_edit_001.png").exists()) self.assertEqual(payload["theme_name"], "talkorigins-modern") def test_content_loaders_parse_local_repo_artifacts(self) -> None: from tempfile import TemporaryDirectory with TemporaryDirectory() as tmp: tmp_path = Path(tmp) doclift_root = tmp_path / "doclift" doclift_root.mkdir() (doclift_root / "manifest.json").write_text( json.dumps( { "documents": [ { "document_id": "doc-1", "title": "Legacy Document", "document_kind": "article", "markdown_path": "documents/doc-1/document.md", "source_path": "source/doc-1.html", } ] } ), encoding="utf-8", ) (doclift_root / "documents" / "doc-1").mkdir(parents=True) (doclift_root / "documents" / "doc-1" / "document.md").write_text("First paragraph.\n\nSecond.", encoding="utf-8") groundrecall_root = tmp_path / "groundrecall" groundrecall_root.mkdir() (groundrecall_root / "groundrecall_query_bundle.json").write_text( json.dumps( { "concept": {"concept_id": "concept::topic", "title": "GroundRecall Topic"}, "summary": "Grounded summary.", "claims": [{"claim_id": "clm-1", "claim_text": "Claim one", "claim_kind": "summary"}], } ), encoding="utf-8", ) didactopus_root = tmp_path / "didactopus" didactopus_root.mkdir() (didactopus_root / "pack.yaml").write_text("name: test-pack\ndisplay_name: Test Pack\n", encoding="utf-8") (didactopus_root / "concepts.yaml").write_text( "concepts:\n - id: prior\n title: Prior\n description: Previous knowledge.\n prerequisites: []\n", encoding="utf-8", ) citegeist_root = tmp_path / "citegeist" citegeist_root.mkdir() (citegeist_root / "refs.bib").write_text( """@article{smith2024,\n title = {A Study},\n author = {Smith, Jane and Roe, John},\n year = {2024}\n}\n""", encoding="utf-8", ) doclift_cards = load_doclift_cards(doclift_root) groundrecall_cards = load_groundrecall_cards(groundrecall_root) didactopus_cards = load_didactopus_cards(didactopus_root) citegeist_cards = load_citegeist_cards(citegeist_root) self.assertEqual(doclift_cards[0].title, "Legacy Document") self.assertEqual(doclift_cards[0].body, "First paragraph.") self.assertEqual(groundrecall_cards[0].title, "GroundRecall Topic") self.assertEqual(groundrecall_cards[1].title, "Claim one") self.assertEqual(didactopus_cards[0].title, "Prior") self.assertEqual(citegeist_cards[0].title, "A Study") def test_inline_config_cards_can_seed_example_content(self) -> None: cards = cards_from_config( [ { "title": "Foundation Search", "body": "Corpus-aware search entry point.", "href": "/search/", "meta": "workbench", "link_label": "Search", } ], default_kind="feature", ) self.assertEqual(cards[0].title, "Foundation Search") self.assertEqual(cards[0].kind, "feature") self.assertEqual(cards[0].href, "/search/") self.assertEqual(cards[0].meta, "workbench") self.assertEqual(cards[0].link_label, "Search") def test_build_site_renders_selected_theme_and_content(self) -> None: from tempfile import TemporaryDirectory with TemporaryDirectory() as tmp: tmp_path = Path(tmp) content_root = tmp_path / "content" content_root.mkdir() doclift_root = content_root / "doclift" doclift_root.mkdir() (doclift_root / "manifest.json").write_text( json.dumps({"documents": [{"document_id": "doc-1", "title": "Legacy Document", "markdown_path": "documents/doc-1/document.md"}]}), encoding="utf-8", ) (doclift_root / "documents" / "doc-1").mkdir(parents=True) (doclift_root / "documents" / "doc-1" / "document.md").write_text("Doclift content.", encoding="utf-8") didactopus_root = content_root / "didactopus" didactopus_root.mkdir() (didactopus_root / "pack.yaml").write_text("name: test-pack\ndisplay_name: Test Pack\n", encoding="utf-8") (didactopus_root / "concepts.yaml").write_text( "concepts:\n - id: prior\n title: Prior\n description: Previous knowledge.\n prerequisites: []\n", encoding="utf-8", ) groundrecall_root = content_root / "groundrecall" groundrecall_root.mkdir() (groundrecall_root / "groundrecall_query_bundle.json").write_text( json.dumps({"concept": {"concept_id": "concept::topic", "title": "GroundRecall Topic"}, "summary": "Grounded summary."}), encoding="utf-8", ) citegeist_root = content_root / "citegeist" citegeist_root.mkdir() (citegeist_root / "refs.bib").write_text( """@article{smith2024,\n title = {A Study},\n author = {Smith, Jane and Roe, John},\n year = {2024}\n}\n""", encoding="utf-8", ) config = { "lang": "en", "title": "TalkOrigins Preview", "site_title": "TalkOrigins Archive", "license": "CC BY-SA 4.0", "github_url": "https://example.invalid", "contact_email": "admin@example.invalid", "theme": "talkorigins-modern", "languages": [{"code": "en", "name": "English"}], "navigation": [{"label": "Home", "href": "/"}], "hero": { "kicker": "Archive Preview", "title": "Modernized, reviewable, and still archive-first.", "lede": "Proof-of-concept output from SciSiteForge.", "actions": [{"label": "Open", "href": "#overview", "primary": True}], }, "content_sources": { "doclift_bundle": str(doclift_root), "groundrecall_bundle": str(groundrecall_root), "didactopus_pack": str(didactopus_root), "bibliography": str(citegeist_root), }, } config_path = tmp_path / "site.json" config_path.write_text(json.dumps(config), encoding="utf-8") out_dir = tmp_path / "out" result = build.build_site(config_path, out_dir) html = (out_dir / "index.html").read_text(encoding="utf-8") self.assertEqual(result["theme"], "talkorigins-modern") self.assertIn("TalkOrigins Preview", html) self.assertIn("Legacy Document", html) self.assertIn("GroundRecall Topic", html) self.assertIn("Prior", html) self.assertIn("A Study", html) self.assertTrue((out_dir / "theme" / "assets" / "toa.ico").exists()) def test_build_site_filters_languages_by_coverage_and_shows_planned_list(self) -> None: from tempfile import TemporaryDirectory with TemporaryDirectory() as tmp: tmp_path = Path(tmp) config = { "lang": "en", "title": "TalkOrigins Preview", "site_title": "TalkOrigins Archive", "license": "CC BY-SA 4.0", "github_url": "https://example.invalid", "contact_email": "admin@example.invalid", "theme": "talkorigins-modern", "languages": [ {"code": "en", "name": "English", "coverage": True}, {"code": "es", "name": "Español", "coverage": False}, {"code": "fr", "name": "Français", "coverage": False}, ], "language_policy": { "planned_languages": [ {"code": "es", "name": "Español"}, {"code": "fr", "name": "Français"}, ] }, "navigation": [{"label": "Home", "href": "/"}], "hero": { "kicker": "Archive Preview", "title": "Modernized, reviewable, and still archive-first.", "lede": "Proof-of-concept output from SciSiteForge.", "actions": [{"label": "Open", "href": "#overview", "primary": True}], }, "content_sources": {}, } config_path = tmp_path / "site.json" config_path.write_text(json.dumps(config), encoding="utf-8") out_dir = tmp_path / "out" build.build_site(config_path, out_dir) html = (out_dir / "index.html").read_text(encoding="utf-8") self.assertNotIn('