# mgf-uitest-web

Browser-level UI testing for the Magogi web consoles — the missing tier.

Every Magogi web console (**ProofWarden** / `mgf-test-web`, the federation
dashboard / `mgf-fed-web`, the cloud console / `mgf-cloud-web`) is a FastAPI +
Jinja server-rendered app that, until now, was tested only through an in-process
`TestClient`. A `TestClient` renders no CSS, runs no JavaScript, and never opens a
browser — so it cannot see the things an operator actually notices. This package
closes that gap: it drives each console in a **real Chromium via Playwright** and
asserts the pillars a `TestClient` can't.

## §1. The pillars

1. **Layout integrity** — reads the browser's real geometry to catch content that
   spills past its box (text outside a border, an element pushed beyond the
   viewport). Deterministic; **no image baseline** to bless.
2. **Functional** — drive the real golden paths and assert outcomes.
3. **Accessibility** — axe-core, no serious/critical violations.
4. **Runtime health** — zero console errors, zero failed requests.
5. **Responsive** — the above across a width × theme matrix *(Chunk 1+)*.
6. **Visual gallery** — screenshots (page × width × theme) for human eyeballing.

## §2. How it drives a console

The harness treats each console as a **black box over HTTP**: it launches the
console's own `mgf-*-web` CLI (from the console's own virtualenv) as a subprocess
on an ephemeral port, waits until it serves, and points Chromium at it. The
harness therefore never imports FastAPI/Jinja or any console's stack — its only
dependency is the browser-driving tier (Playwright + axe).

## §3. Family

The web half of the `mgf-uitest` family. A future `mgf-uitest-qt` sibling will
carry the same pillar vocabulary to the PySide desktop apps; genuinely shared
pieces (baseline/report plumbing) get extracted into `mgf-uitest-core` **only once
that second consumer exists** — not on speculation.

## §4. Status

Pre-alpha, prove-first. Built and proven locally against two consoles
(`mgf-fed-web`, `mgf-test-web`) before it is registered in the federation or wired
as a blocking CI gate — that promotion is a deliberate, founder-fired step. See the
decision package under the MGF Court workspace.

## §5. Setup

The harness uses Playwright's **pinned** Chromium — never a system-browser fallback,
because a different browser can resolve CSS `@import` / relative URLs differently and
produce findings that don't reproduce. One-time:

```
uv venv
uv pip install -e ".[dev]"
python -m playwright install chromium
```

## §6. Running the suite

```
PYTHONPATH=src python -m pytest tests/
```

Each console provides a `console_launch` fixture declaring how to start itself; the
harness launches it as a black-box server and drives it in a real browser.
Screenshots land in `tests/_artifacts/gallery/` (page × width × theme).

**The console specs live in the consoles, not here.** Each console owns its own UI
gate — `mgf-fed-web` and `mgf-test-web` carry their specs and their `console_launch`
under their own `tests/e2e/`, so a change to a console's chrome is caught by that
console's CI, and this harness stays console-free (it needs no sibling checkout to
test itself). Worked examples: [`mgf-fed-web`](https://codeberg.org/magogi-admin/mgf-fed-web)
and [`mgf-test-web`](https://codeberg.org/magogi-admin/mgf-test-web), `tests/e2e/conftest.py`
in each. Consoles pick the gate up by depending on this package — `mgf-fed`'s
renderer then splices a dedicated `ui-gate` step into their pipeline.

This repo's own suite is partitioned by tier: `tests/unit/` + `tests/smoke/` (no
browser) and `tests/integration/` (a real Chromium against a **stdlib static
server** — so the `Console` contract is proven with no console repo present). CI
runs tiers 0–2 and covers 95% of the package.

## §7. Standards conformance

`mgf-uitest-web` declares **L2 — Standard** (CFM-02): conform to every MUST rule,
evidenced by a per-rule audit. The audit is
[`docs/inprogress/MGF_STANDARDS_CONFORMANCE.md`](docs/inprogress/MGF_STANDARDS_CONFORMANCE.md)
— all **265** MUSTs of the corpus accounted for: 118 ✅ · 143 N/A · 3 declined-with-rationale
· **1 in flight** (AP-02 per-name usage examples). The open item is named there with its
closing action — a level claim is only worth what its ledger shows.

The public contract is [`PUBLIC_API.md`](PUBLIC_API.md) (every name, its stability
tier); the boundary is [`SCOPE.md`](SCOPE.md).
