test(demo): cover the demo app + sales-surface coherence

Adds a demo test suite on top of the data-value pins:

- tests/gui/test_app_demo.py (new, AppTest): every accounting persona
  renders with its dataset, the default/unknown-persona fallback resolves
  to bookkeeper, clicking Run produces the AFTER value (rows reduced to the
  validated count) with the watermarked download + Gumroad CTA, and
  switching persona via the quick-switch dropdown clears the stale result.
- tests/test_demo_pipelines.py (extended): cross-surface coherence —
  each persona key served by app_demo has a matching landing page whose
  iframe (?p=) and CTA (from=) point at it and that the hub links to;
  no retired Shopify/RevOps language remains in landing HTML; and the
  demo download still appends exactly one watermark row.

Full suite: 2584 passed, 91 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-22 19:06:50 +00:00
parent e7ec79b9b5
commit 9943e6e537
2 changed files with 161 additions and 0 deletions

View File

@@ -69,3 +69,48 @@ def test_app_demo_references_each_demo_file():
assert pipeline_file in src, f"{pipeline_file} not referenced in app_demo.py"
assert (_DEMO / data_file).exists(), f"missing {data_file}"
assert (_DEMO / pipeline_file).exists(), f"missing {pipeline_file}"
# The accounting persona keys served by the demo app — each must line up with
# a landing page that embeds the matching demo. (key, data-file stem)
_PERSONA_KEYS = [
("bookkeeper", "bank_reconciliation"),
("ap-1099", "vendor_1099"),
("ar-aging", "ar_open_invoices"),
]
_LANDING = _REPO / "landing"
@pytest.mark.parametrize("key,stem", _PERSONA_KEYS)
def test_landing_page_embeds_the_matching_demo(key, stem):
"""Each landing page exists and its iframe + CTA point at this persona —
so the sales surface (landing -> demo app -> dataset) stays coherent."""
app_src = (_REPO / "src" / "gui" / "app_demo.py").read_text(encoding="utf-8")
assert f'"{key}"' in app_src, f"persona key {key!r} not served by app_demo.py"
page = _LANDING / key / "index.html"
assert page.exists(), f"missing landing page for {key}"
html = page.read_text(encoding="utf-8")
assert f"?p={key}" in html, f"{key} landing iframe doesn't load ?p={key}"
assert f"from={key}" in html, f"{key} landing CTA isn't tagged from={key}"
# The hub links to this persona's page.
hub = (_LANDING / "index.html").read_text(encoding="utf-8")
assert f'href="{key}/"' in hub, f"hub doesn't link to {key}/"
def test_landing_surface_has_no_stale_persona_refs():
"""No retired Shopify / RevOps persona language remains in landing HTML."""
for html_file in _LANDING.rglob("*.html"):
text = html_file.read_text(encoding="utf-8").lower()
for stale in ("shopify", "revops", "klaviyo", "hubspot"):
assert stale not in text, f"{stale!r} still in {html_file.relative_to(_REPO)}"
def test_demo_app_builds_a_single_watermark_row():
"""The demo download appends exactly one trailing watermark row
(DEMO-PLAN §6: the AFTER preview must read as production-quality)."""
src = (_REPO / "src" / "gui" / "app_demo.py").read_text(encoding="utf-8")
assert "DataTools demo — buy at" in src
# One trailing row concatenated onto the result frame.
assert "watermark_row" in src and "pd.concat([result.final_df, watermark_row]" in src