Repository navigation
UI testing: static check for the grid-gate class, a dev seeder, and the grid pass recorded - #372
Merged
Merged
Conversation
… the grid pass recorded Three things, all from the same morning's findings. 1. paradigm-scan grows a FIFTH check, `datatable_gate` (blocker). A view whose registered JS calls tigerDataTable() while its owning controller never sets useDataTables is the TIGER-390 class: HTTP 200, empty table, zero console errors, because the grid script's bail-out guard is doing its job. Invisible to PHPUnit (nothing renders) and to the browser probe's "no console errors" detector, so it has to be caught statically. Mutation-verified twice — removing the flag from system/SitesController and then newsletter/AdminController each produces exactly one finding naming the file and the cause; restoring it goes quiet. Scope stated in the code: the flag is looked for anywhere in the controller, not inside the specific action, so a finding means the controller never sets it at all — the case that actually shipped, and zero false positives. That check also made the scan 20x SLOWER (29s), because reading a view's registered JS meant a `find` shell-out per asset per view — and hasAjaxHandler was already doing the same. Both now share one basename->path index built once: 29s -> 1.4s, faster than before the check existed. 2. tests/ui/bin/seed-dev.php — the probe org owned no content, so EVERY grid looked exactly like the three broken ones and separating them took a SQL query a scenario cannot run. Seeds one page, one article, one menu, one inactive snippet and one subscriber, all labelled `UI Probe`, addresses on the reserved .invalid domain. Dry run unless --apply; idempotent. Its guard went through three honest failures worth recording. First version read config.json relative to __DIR__, found none when run from a copied path, and so "passed" with an empty never_target — a check that could only ever succeed. Second version matched hosts as substrings, which would refuse tiger-dev.webtigers.com for containing webtigers.com. Third discovery killed the whole approach: an install cannot tell you which site it is — on tiger-dev APPLICATION_ENV is literally "production", tiger.site.url is unset, and gethostname() returns an EC2 internal name. So the operator NAMES the target with --base and never_target refuses the forbidden ones, which is the contract the two probes already use. Five branches each verified on dev: no --base refuses, tiger.webtigers.com refuses, www.webtigers.com refuses, a missing never_target refuses, and the dev base proceeds. 3. scenarios/admin-grids.json — the grid pass recorded in the same intent-level shape as auth.json, five scenarios with `verified` lines carrying what the real run saw. UI-GRID-EMPTY-TRUTH is the one to keep: an empty grid and a broken grid are the same picture, so never record a PASS on an empty grid without establishing why it is empty. That discipline is what surfaced TIGER-391 — /media's honest 0 rows next to /cms/page's 25 is what exposed the missing org filter. Scan: 108 views, 0 findings on all five checks. Unit suite: 1200 tests, 18318 assertions, green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013vdyTeoDrGE4hKxt53TsE8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three things from the same morning's findings. Test-harness only — no shipped code changes.
1.
paradigm-scangrows a fifth check —datatable_gate(blocker)A view whose registered JS calls
tigerDataTable()while its owning controller never setsuseDataTables. That's the TIGER-390 class: HTTP 200, empty table, zero console errors, because the grid script's bail-out guard is doing its job. Invisible to PHPUnit (nothing renders) and to the browser probe's "no console errors" detector — so it has to be caught statically.Mutation-verified twice. Removing the flag from
system/SitesController, then fromnewsletter/AdminController, each produces exactly one finding naming the file and the cause; restoring it goes quiet.Scope is stated in the code: the flag is looked for anywhere in the controller, not inside the specific action. A finding therefore means the controller never sets it at all — the case that actually shipped, and zero false positives.
It also made the scan 20× slower, so that's fixed too. Reading a view's registered JS meant a
findshell-out per asset per view, andhasAjaxHandlerwas already doing the same thing. Both now share one basename→path index built once: 29s → 1.4s, faster than before the check existed.2.
tests/ui/bin/seed-dev.phpThe probe account's org owned no content, so every grid looked exactly like the three broken ones — and telling them apart took a SQL query a scenario can't run. Seeds one page, one article, one menu, one inactive snippet and one subscriber, all labelled
UI Probe, addresses on the reserved.invaliddomain. Dry run unless--apply; idempotent.Its guard failed honestly three times before it worked, which is the part worth reading:
config.jsonrelative to__DIR__, found none when run from a copied path, and so "passed" with an emptynever_target— a safety check that could only ever succeed.tiger-dev.webtigers.comfor containingwebtigers.com.APPLICATION_ENVis literallyproduction,tiger.site.urlis unset, andgethostname()returnsip-172-31-44-189.ec2.internal.So the operator names the target with
--baseandnever_targetrefuses the forbidden ones — the contract both probes already use. Five branches, each verified on dev:--base--base=https://tiger.webtigers.com--base=https://www.webtigers.comnever_target--base=https://tiger-dev.webtigers.com3.
scenarios/admin-grids.jsonThe grid pass recorded in the same intent-level shape as
auth.json— five scenarios, each with averifiedline carrying what the real run saw.UI-GRID-EMPTY-TRUTHis the one to keep: an empty grid and a broken grid are the same picture, so never record a PASS on an empty grid without establishing why it's empty. That discipline is what surfaced TIGER-391 —/media's honest 0 rows next to/cms/page's 25 is what exposed the missing org filter.Scan: 108 views, 0 findings on all five checks. Unit suite: 1200 tests, 18318 assertions, green.
🤖 Generated with Claude Code
https://claude.ai/code/session_013vdyTeoDrGE4hKxt53TsE8