import re from pathlib import Path ROOT = Path(__file__).resolve().parents[2] SITE = ROOT / "index.html" def text_of(fragment: str) -> str: """Visible text of an HTML fragment, with entities and spacing normalised. Copy assertions should fail when the words change, not when the markup around them does. Matching raw HTML has broken this suite twice: once when the mantra was split across a , and once when

[^<]*PDRC stopped at the first tag. Both times the page was fine and the test was wrong. """ txt = re.sub(r"<[^>]+>", " ", fragment) txt = txt.replace(" ", " ").replace("&", "&") txt = txt.replace("—", "—").replace("’", "'").replace("–", "–") return re.sub(r"\s+", " ", txt).strip() ACT = ROOT / "act.html" ABOUT = ROOT / "about.html" MASTER_TYP = ROOT / "report" / "spirited-energy-master.typ" NAV_LABELS = ( "The Problem", "Our Plan", "Orders", "Soil & Water", "Take Action", ) def test_site_exists_and_uses_scenario_range(): html = SITE.read_text() assert "413" in html and "788" in html assert "861" not in html # pre-correction headline must not resurface assert "895 MW" not in html assert "1.5" in html and "1.8" in html assert "4.5" in html and "6.9" in html assert "1,971" not in html # pre-correction $/kW must not resurface assert "MWth" in html and "electric" in html.lower() def test_site_is_report_shaped(): """Landing page mirrors the master filing: argument, orders, provenance.""" html = SITE.read_text() # Master filing voice and spine assert "Spirited Energy 2.0" in html assert "Recycled Heat." in html # public headline, as on the cover assert "heat that works twice" in html # argument mantra survives in §1 assert 'id="orders"' in html assert "5,111.5" in html # Non-overlapping 20-year bands, quoted as bands not point claims assert "2.7" in html and "5.4" in html assert "4.5" in html and "6.9" in html # Landing charts are live motion graphics (not frozen PNGs / not Chart.js CDN) assert "se-charts.js" in html assert 'data-chart="' in html assert "fig5_winter_load_vs_temp.png" not in html assert "fig2_capacity_scenarios.png" not in html assert "chart.js" not in html.lower() # Photos stay raster; Brandon / NEWPCC assert "brandon_station.jpg" in html assert "newpcc_plant.jpg" in html # Provenance: registry named, evidence classes legend present assert "assumptions.yaml" in html assert "report/design-tokens.css" in html # Summer stays an add-on, never winter firm assert "not winter firm" in html.lower() # Legacy dashboard is intentionally unlinked (archived, pre-correction figures) assert "index.legacy-dashboard.html" not in html def test_design_tokens_unify_plan_and_ledger_colors(): """Gas/problem orange, hybrid/solution green; thermal gold vs electric ice.""" css = (ROOT / "report" / "design-tokens.css").read_text() assert "--se-gas:" in css and "--se-hybrid:" in css assert "--se-thermal:" in css and "--se-electric:" in css assert "--se-orange:" in css # Gas / problem orange. Darkened from #c65d1a during the accessibility pass: # the old value was 4.22:1 on white, below the WCAG AA 4.5:1 floor for text. # #a34b12 is 5.88:1. Keep any future retune at or above AA. assert "#a34b12" in css assert "#14532d" in css or "#0b3d2e" in css # hybrid greens # Thermal is gold/amber family, not the same hex as gas orange thermal = re.search(r"--se-thermal:\s*([^;]+);", css) gas = re.search(r"--se-gas:\s*([^;]+);", css) assert thermal and gas assert thermal.group(1).strip() != gas.group(1).strip() def test_site_layout_centers_rail_without_figure_min_width(): """Full-viewport sections share a centered rail; figures do not force skew.""" html = SITE.read_text() assert "--se-rail" in html assert "min-width: 560px" not in html assert "min-width: 760px" not in html assert "overflow-x: clip" in html or "overflow-x:hidden" in html.replace(" ", "") def test_site_action_and_relabels(): """Take-action is the CTA; hero and stat labels match the brief.""" html = SITE.read_text() assert "Introducing Spirited Energy 2.0" in html assert "Take Action" in html assert 'id="take-action"' in html assert "./act.html" in html assert "petition.html" not in html assert "Sign the petition" not in html assert "2030 projected shortfall" in html assert "Modelled savings vs gas" in html or "Savings to ratepayers" in html # Master filing survives as the single primary download assert "spirited-energy-master-report.pdf" in html assert "Supporting whitepapers" in html def test_site_and_action_share_the_same_menu(): """Landing and act.html expose the same primary nav labels.""" site_nav = SITE.read_text().split('