test(view): regression spec for inline-SVG icon convention in migrator view#2565
Conversation
…r view Adds vendor/wheels/tests/specs/migrator/MigratorViewIconsSpec.cfc that asserts (1) the migrator view's Database Error placeholder uses an inline SVG icon, and (2) the file contains no Semantic UI icon-font tags. Documents the inline-SVG convention used throughout vendor/wheels/public/views/migrator.cfm and guards against drift. The original bug (broken icon glyph on Database Error placeholder, #2427) was fixed by: - #2562 - replaced the offending icon-font tag with an inline SVG matching the sibling "No migration files found" placeholder. - #2563 - inlined the Semantic UI icon font globally so font-based glyphs render across all framework dev pages. This test is convention enforcement - it catches reintroduction of icon-font tags in this file even though the font now loads. Closes #2427. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d8e1ba0 to
1301ea6
Compare
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: This PR adds a single regression spec (vendor/wheels/tests/specs/migrator/MigratorViewIconsSpec.cfc) that enforces the inline-SVG icon convention in the migrator dashboard view. The change is test-only, correct, cross-engine safe, and follows BDD conventions. Approving with two minor nits.
Correctness
The test logic holds up under scrutiny:
Find("Database Error", source)correctly returns the byte position of the anchor text (line 300 ofmigrator.cfm). Theexpect(anchor).toBeGT(0, ...)guard catches a missing anchor with a helpful message.- The window arithmetic (
windowStart = Max(anchor - 1500, 1),windowLen = anchor - windowStart) captures exactly 1500 characters immediately before the anchor — sufficient to contain the preceding<svg>block, which is confirmed to be ~380 chars in the current file. The comment explaining the 700-char estimate refers to path data length; 1500 is a safe upper bound. reFindNoCasereturns0when no match is found.expect(fontIconHit).toBe(0)is the correct idiom for that return value.reMatchNoCasereturns an array of all matches;expect(ArrayLen(hits)).toBe(0)is correct for "no matches".toBeGT,toInclude, andtoBeall accept amessagesecond argument as defined invendor/wheels/wheelstest/system/Expectation.cfclines 624, 560, and 168 respectively — usage is valid.
Conventions
The Chr(60) & "i[\s>][^>]*\bicon\b" pattern correctly avoids embedding a literal < in a CFML string expression, following the guidance in .ai/wheels/testing/ and consistent with the # scanner trap documented in CLAUDE.md. The spec extends wheels.WheelsTest (not the legacy wheels.Test) and uses BDD describe/it/expect syntax throughout — correct.
Nit — duplicate FileRead call (lines 23 and 59):
// it block 1 (line 23)
var source = FileRead(ExpandPath("/wheels/public/views/migrator.cfm"));
// it block 2 (line 59)
var source = FileRead(ExpandPath("/wheels/public/views/migrator.cfm"));Both it blocks read the same file independently. A beforeAll (or a describe-level local.source read once at the top of run()) would eliminate the duplicate disk hit. This is cosmetic — the file is ~50 KB and reads in milliseconds — but worth a one-line fix.
Cross-engine
All functions used (FileRead, ExpandPath, Find, Mid, Max, reFindNoCase, reMatchNoCase, Chr, ArrayLen, ArrayToList) are standard CFML and work on Lucee 6/7, Adobe CF 2023/2025, and BoxLang. Arrow-function closures (() => {}) are supported by every engine in the CI matrix. No struct.map() on CFC objects, no application scope members, no client scope usage. The Left(str, 0) Lucee 7 gotcha (CLAUDE.md "Known cross-engine gotchas") does not apply here — Mid() is used, and the degenerate windowLen = 0 case (which would require "Database Error" to appear at byte position 1 in the file) cannot occur in practice.
Tests
This PR is entirely test code and is self-verifying. Both happy-path assertions (<svg present, zero icon-font tags) pass against the current migrator.cfm on develop as confirmed by the PR description's Python pre-check. ExpandPath("/wheels/public/views/migrator.cfm") follows the same /wheels/ virtual-path convention used in migratorSpec.cfc line 386 — path resolution is correct.
Docs
Nit — PR labels: The PR carries docs and enhancement labels, but the type-of-change checklist correctly marks [x] Test-only (regression coverage). The labels do not reflect the test-only nature and may mislead triage — worth updating.
Commits
Single commit: test(view): regression spec for inline-SVG icon convention in migrator view
- Type
test: valid - Scope
view: valid (the spec testsmigrator.cfm, a view template) - Subject 60 chars, not ALL-CAPS: valid
- Describes the why ("regression spec for ... convention"), not just the what: valid
No commitlint violations.
Security
No user input, no SQL, no XSS surface. FileRead reads a known framework-owned path resolved via ExpandPath — no path traversal risk.
Summary
Adds a regression test (
vendor/wheels/tests/specs/migrator/MigratorViewIconsSpec.cfc) that locks in the inline-SVG icon convention for the migrator dashboard.The original bug (broken icon glyph on the Database Error placeholder, #2427 / #2425) has already been fixed on
developvia two earlier PRs:_header.cfm/_header_simple.cfm), so font-based glyphs now render across every framework dev page (/wheels/guides,/wheels/info,/wheels/migrator, etc.).This PR was originally opened against the unfixed state and conflicted with
developafter #2562 / #2563 landed. Rebased to drop the duplicate view change + duplicate CHANGELOG entry and keep just the new regression spec — convention enforcement formigrator.cfmgoing forward.Related Issue
Closes #2427 (duplicate of #2425; substantive fix is on
develop).Type of Change
What this test asserts
vendor/wheels/public/views/migrator.cfmuses an inline<svg>(not an icon-font tag).<i ...icon...>opener tags.Both checks build their regex literals via
Chr(60) & ...to avoid the Lucee tag-scanner trap documented in .ai/wheels/testing/.Feature Completeness Checklist
vendor/wheels/tests/specs/migrator/MigratorViewIconsSpec.cfcis the entire change.vendor/wheels/public/views/migrator.cfmon develop: both checks pass (anchor found at byte ~16700,<svgpresent in the 1500-char window before it, zero icon-font hits in the 50KB file). CI will run the CFML spec end-to-end.Test Plan
The test reads
migrator.cfmdirectly viaFileRead(ExpandPath("/wheels/public/views/migrator.cfm"))— no database, no HTTP, no fixtures required. It will pass on every engine × DB combo so long asmigrator.cfmkeeps its inline-SVG convention.🤖 Generated with Claude Code