diff --git a/tests/AGENTS.md b/tests/AGENTS.md index ba88180a..0d28760a 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -40,6 +40,14 @@ Lessons that cost iterations getting the patch-coverage and mutation tail gates - **Help text and docstrings are pinned by the syrupy snapshots, not unit asserts** — a mutated help string is killed by the regenerated `.ambr`, so `--snapshot-update` and commit rather than adding redundant `--help` substring asserts. +- **Render width is pinned suite-wide (`COLUMNS=80`), so a `--help` substring assert is + deterministic** — the autouse `fixed_render_size` fixture (`conftest.py`) sets `COLUMNS`/`LINES` + for *every* test, because the no-clip help table ellipsizes a long flag name + (`--end-of-turn-c…`) once its column overflows. Without the pin a `--with-api-key`-style + substring assert passes at a wide local terminal and fails at CI's narrower width — that gap + cost a PR three CI rounds. Don't fight it: a local green is now a CI green for output tests. + A test that genuinely needs a different width passes it on the call + (`runner.invoke(app, argv, env={"COLUMNS": "300"})`), which overrides the default. - **Typer's `CliRunner` merges stderr into `result.output`, and not in call order**, so don't assume `splitlines()[-1]` is the command payload. In `--json` mode the env-mismatch warning is its own `{"warning": …}` line, so filter parsed lines by a key the payload carries diff --git a/tests/conftest.py b/tests/conftest.py index 39a33c8c..f115411b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -87,12 +87,23 @@ def pin_timezone(monkeypatch): time.tzset() -@pytest.fixture +@pytest.fixture(autouse=True) def fixed_render_size(monkeypatch): - # Pin the render width/height so the CLI-surface goldens (the - # test_snapshots_* modules) are byte-identical across machines and CI. - # Named (not autouse): only the snapshot modules opt in via - # `pytestmark = pytest.mark.usefixtures("fixed_render_size")`. + # Pin the render width/height for the *whole* suite so anything that renders + # CLI/help output is byte-identical across machines and CI. Rich/Click derive + # the help width from COLUMNS (falling back to the inherited terminal size), + # and the no-clip table ellipsizes long flag names ("--end-of-turn-c…") once + # the column overflows — so a `--help` substring assertion that passes at a + # contributor's wide local terminal can silently fail at CI's narrower width. + # That exact gap (a hidden `--with-api-key` flag asserted present, clipped away + # in CI) burned three CI rounds on one PR; autouse closes it so a local green + # means a CI green. + # + # Autouse, not opt-in: every test gets the pinned size. A test that needs a + # different width passes it explicitly to the invocation (the canonical pattern + # in test_help_rendering.py: `runner.invoke(app, argv, env={"COLUMNS": "80"})`), + # which CliRunner merges over this default. The snapshot modules still carry an + # explicit `usefixtures("fixed_render_size")` marker to document the dependency. monkeypatch.setenv("COLUMNS", "80") monkeypatch.setenv("LINES", "40")