fix(tests): cotton integration tier exercises real compilation (#79) - #80
Conversation
…est-all by process (#79) tests/integration/cotton_app/settings.py never listed django_cotton in INSTALLED_APPS, so its AppConfig.ready() never ran and DTL treated <c-cf.*> tags as inert literal text — test_cotton_integration.py's assertions were passing against uncompiled markup. Registering it exposed a bigger problem: django-cotton's AppConfig.ready() mutates settings.TEMPLATES in place and resets Django's global template-engine cache, a permanent process-wide side effect. justfile's test-all recipe ran tests/unit and tests/integration in one pytest process, so once cotton was registered its loader/builtins leaked into every unit test's render_to_string call and broke ~400 of them. CI was never affected — ci.yml already runs each tier as its own step — but test-all needed the same separation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ur2c6d3peuerUGgRdJ6Fvs
…ion invariant /review on PR #80 found the invariant was only convention (justfile/CI recipe discipline), not enforced — a bare `pytest` (pyproject.toml's testpaths = ["tests"]) or `pytest tests/` still collects both tiers into one process and reintroduces the settings.TEMPLATES leak, producing ~400 confusing unit-test failures instead of an obvious error. Verified: `pytest -q` now fails fast with a clear pytest.UsageError instead of the silent breakage; both tiers still pass individually. Also corrected CLAUDE.md's now-stale claim that only E2E exercises real <c-vars> compilation — the integration tier does too as of this PR. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ur2c6d3peuerUGgRdJ6Fvs
/review findings4 findings surfaced, 2 verified via direct reproduction:
All gates re-verified after the fixes: |
attrs passthrough on the interactive set — Button, Select, Textarea, FormField, Icon, Badge, Box, CheckboxGroup (#70, #72, #73, #76, #77, #82) — plus the two coverage-gap fixes found along the way (#78/#81 JinjaX docs, #79/#80 cotton integration compiler). Fully additive: attrs defaults to {} everywhere, so every existing call site renders byte-identically. #70 stays open for the remaining components. Verified before tagging: 3186 passed / 13 skipped (unit), 40 passed (integration), 236 passed / 33 skipped (E2E chromium, both js modes), ruff check/format clean, djlint clean on both template trees (126 cotton + 105 jinja, 0 errors), mkdocs build --strict clean, and the release workflow's own wheel guard run locally against `uv build` — 237 shipped templates and assets, all present, twine check passed on both sdist and wheel.
Summary
tests/integration/cotton_app/settings.pynever listeddjango_cottoninINSTALLED_APPS, so itsAppConfig.ready()never ran and Django's template engine treated<c-cf.*>tags as inert literal text —test_cotton_integration.py's assertions were satisfied by uncompiled markup, not real cotton output.django_cottontoINSTALLED_APPSandCOTTON_SNAKE_CASED_NAMES = False(matching the precedent already set intests/e2e/_e2e_django_settings.py), and added a regression assertion to each of the three existing tests proving the raw<c-cf.*>tag is compiled away, not passed through.django_cottonsurfaced a bigger, previously-latent problem:django_cotton.apps.LoaderAppConfig.ready()mutatessettings.TEMPLATESin place and resets Django's global template-engine cache — a permanent, process-wide side effect the moment it's inINSTALLED_APPS.justfile'stest-allrecipe rantests/unitandtests/integrationin onepytest tests/process, so once cotton was registered its loader/builtins leaked into every unit test'srender_to_stringcall, breaking ~400 unrelated unit tests..github/workflows/ci.ymlwas never affected — it already runs each tier as its own step (separate process) — buttest-allneeded the same separation to match. Fixedtest-allto invokepytestonce per tier, and correctedtests/integration/conftest.py's docstring, which had documented a conftest "race" that doesn't actually matter once tiers never share a process.Test plan
pytest tests/integration/test_cotton_integration.py -v— all 3 tests pass against real compiled markup (confirmed the newassert b"<c-cf..." not in r.contentassertions fail without theINSTALLED_APPSfix, pass with it)pytest tests/unit -q— 2826 passed, 13 skipped, run alonepytest tests/integration -q— 25 passed, run aloneruff check src tests/ruff format --check src tests— clean🤖 Generated with Claude Code
https://claude.ai/code/session_01Ur2c6d3peuerUGgRdJ6Fvs