fix(wheelstest): capture spec-load errors against the bundle and emit positive error count#2831
Conversation
Wheels Bot — Docs updatedAdded a doc commit to this PR:
|
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: This fix is clean and correct. BDDRunner.cfc is patched in exactly the right two places — startBundleStats moved before target.run() so there is always a bundle record to attach errors to, and the surrounding try/catch widened to cover both the suite-descriptor phase and the execution phase so neither orphan-it() nor a throwing beforeAll() can escape as an anonymous BundleRunnerMajorException. The -1 sentinel is replaced with +1. Two purpose-built fixtures and a BDD spec verify both shapes. No cross-engine, security, or convention issues found. Verdict: approve (self-authored PR; GitHub disallows the approval API, so this is recorded as a comment review instead).
Tests
vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc, line 39
expect(results.getTotalError()).toBeGT(0);
...
expect(bs[1].totalError).toBeGT(0);The first test case (OrphanItFixture) correctly uses toBe(1) for exact precision. The BeforeAllErrorFixture case uses toBeGT(0), which is weaker — the fix guarantees exactly 1 error per bundle failure just as the first case does. Suggest tightening to toBe(1) to lock the invariant:
expect(results.getTotalError()).toBe(1);
...
expect(bs[1].totalError).toBe(1);Not a blocker, but the first spec sets a clear precedent for exact counts.
Correctness
The refactor correctly preserves existing behaviour for the non-error path (the canRunBundle guard, beforeAll/afterAll annotation method loops, onSuiteStart/onSuiteEnd callbacks, and endStats are all unchanged and still run on the happy path). The isNull(thisSuite) guard in the catch block is safe: for (var thisSuite in testSuites) declares thisSuite in function scope before the loop body executes, so it is null when the catch fires before the loop is entered, and isNull(null) returns true, passing {} to announceToModules as the "no active suite" signal.
Commits
Single commit fix(wheelstest): capture spec-load errors against the bundle and emit positive error count — type fix, scope wheelstest, subject 68 characters, body explains the why. DCO Signed-off-by: claude[bot] present.
Docs
CHANGELOG.md [Unreleased] → Fixed entry is accurate and placed correctly beneath the existing ### Changed block. AI/framework-doc follow-ups are explicitly deferred to bot-update-docs.yml, which is the established pattern.
There was a problem hiding this comment.
Wheels Bot -- Reviewer A
TL;DR: The docs follow-up commit d12e401 adds exactly one bullet to the Common failure modes section of the running-tests-locally guide, accurately describing the new error output shape introduced by the fix. It is clean, well-placed, and commit-lint clean. The one minor nit from the previous review round -- tightening toBeGT(0) to toBe(1) in the BeforeAllErrorFixture case -- remains unaddressed but is not a blocker. No correctness, cross-engine, or security concerns. Verdict: comment (minor nit only).
Tests: vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc lines 39 and 43 -- The first case OrphanItFixture uses exact assertion toBe(1). The second case BeforeAllErrorFixture uses the weaker toBeGT(0). Since the catch block unconditionally sets bundleStats.totalError = 1 and increments by 1, the result is always exactly 1. Suggest tightening both to toBe(1) to match the first case.
Docs: web/sites/guides/src/content/docs/v4-0-0/testing/running-tests-locally.mdx line 205 -- The added bullet is factually correct, names both failure shapes, points users to globalException, and directs them to the bundle path. Placement inside Common failure modes is exactly right.
Commits: fix(wheelstest) subject 68 chars DCO present; docs(web/guides) subject 52 chars DCO present. Both conform to commitlint.config.js.
wheels-bot:review-a:2831:d12e401632a54b77451f63b2f7b0d986aa2fa822
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: The docs follow-up commit (d12e401) adds exactly one bullet to the "Common failure modes" section of the running-tests-locally guide, accurately describing the new error output shape introduced by the fix. It is clean, well-placed, and commit-lint clean. The one minor nit from the previous review round — tightening toBeGT(0) to toBe(1) in the BeforeAllErrorFixture case — remains unaddressed but is not a blocker. No correctness, cross-engine, or security concerns. Verdict: comment (minor nit only).
Tests
vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc, lines 39 and 43
The first case (OrphanItFixture) uses the exact assertion toBe(1), which locks the invariant precisely. The second case (BeforeAllErrorFixture) uses the weaker toBeGT(0). Since the catch block unconditionally sets bundleStats.totalError = 1 and calls incrementStat(type="error", count=1), the result is always exactly 1. Suggest tightening both assertions to toBe(1) to match the first case and catch any future regression that produces a different positive count.
Docs
web/sites/guides/src/content/docs/v4-0-0/testing/running-tests-locally.mdx, line 205
The added bullet is factually correct: it names both failure shapes (orphan it() call, throwing beforeAll()), points users to globalException, and directs them to the bundle path shown in the summary. Placement inside the "Common failure modes" list is exactly right.
Commits
Two commits in the PR:
fix(wheelstest): capture spec-load errors against the bundle and emit positive error count— typefix, scopewheelstest, subject 68 chars, DCOSigned-off-bypresent.docs(web/guides): note BDD runner load-time errors in common failure modes— typedocs, scopeweb/guides, subject 52 chars, DCOSigned-off-bypresent.
Both conform to commitlint.config.js. No issues.
Wheels Bot — Reviewer B (round 1)A's review is clean and grounded. The single nit is real, A's line reference has a minor off-by-one, and both A and I land on the same verdict: the PR is correct but has two weak assertions worth tightening before merge. SycophancyNone detected. Every positive statement in A's review is paired with a specific reference to the code or the diff. False positivesNone detected. A's claim — that the outer catch unconditionally sets Missed issuesOne minor inaccuracy in A's line citation: A says "lines 39 and 43" for the two No other missed issues. Cross-engine exposure is negligible (standard Verdict alignmentA's ConvergenceAligned. The joint recommendation: tighten lines 39 and 42 of |
|
|
Wheels Bot -- Reviewer B (round 1)A's review of the docs follow-up commit is clean and technically sound. The nit about SycophancyNone detected. A cited specific line references and explained the reasoning behind each finding rather than deferring to the author. False positivesNone detected.
Missed issuesNone on this round's diff. One concern A addressed in the first-round review and correctly resolved: the Verdict alignmentA's ConvergenceAligned. A has correctly identified the only actionable item ( |
Wheels Bot — Address Review (round 1)Applied the consensus finding from Reviewer A and Reviewer B's convergence (round 1 of the convergence loop):
Verification: re-ran the The new commit will trigger a fresh Reviewer A run on the updated SHA. Convergence loop continues until reviewers align on |
Address Reviewer A/B consensus from PR #2831 round 1: both reviewers agreed the BeforeAllErrorFixture case in vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc should match the OrphanItFixture case's exact-count style. The catch block in BDDRunner.cfc unconditionally records totalError = 1 per failed bundle, so toBeGT(0) was weaker than the invariant the fix guarantees. - vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc lines 39 and 42: toBeGT(0) -> toBe(1) for results.getTotalError() and bs[1].totalError in the BeforeAllErrorFixture case. Verified: wheelstest layer 143 pass / 0 fail / 0 error against the running CI server (sqlite). Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: The sole nit from the two previous review rounds — tightening toBeGT(0) to toBe(1) in the BeforeAllErrorFixture case — is now addressed in commit 15810f495. Both spec cases in BDDRunnerErrorReportingSpec.cfc now use identical exact-count assertions, which correctly locks the invariant guaranteed by the bundleStats.totalError = 1 assignment in the catch block. The PR is clean across all three commits; no correctness, cross-engine, convention, or security issues remain. Verdict: approve (GitHub blocks self-approval on bot-authored PRs, so this is recorded as a comment review instead).
Tests
vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc, lines 39 and 42
Previous round: toBeGT(0) — weak, passes for any positive value.
This commit: toBe(1) — exact, matches what the catch block guarantees.
Both cases now read:
expect(results.getTotalError()).toBe(1);
// ...
expect(bs[1].totalError).toBe(1);This is consistent with the OrphanItFixture case (lines 23 and 26) and correctly reflects the bundleStats.totalError = 1 hard-assignment in BDDRunner.cfc's catch block.
Commits
Three commits across the PR:
fix(wheelstest): capture spec-load errors against the bundle and emit positive error count— typefix, scopewheelstest, 68 chars, DCO signed. Substantive fix.docs(web/guides): note BDD runner load-time errors in common failure modes— typedocs, scopeweb/guides, 52 chars, DCO signed. Accurate follow-up.fix(wheelstest): tighten BeforeAllErrorFixture assertions to toBe(1)— typefix, scopewheelstest, 49 chars, DCO signed. Addresses review nit.
All three conform to commitlint.config.js. Commit bodies explain the why.
Wheels Bot — Reviewer B (round 1)A's review of the updated SHA is clean and accurate. The sole outstanding nit from prior rounds was correctly verified as addressed, line citations are now correct, and all three commits pass conformance checks. Aligned on approve. SycophancyNone detected. A identified exactly what changed (the tightened assertions at lines 39 and 42), verified against the actual diff, and explained the reasoning in terms of the False positivesNone detected.
Missed issuesNone detected. Cross-engine exposure remains negligible: the fix is a try/catch restructuring and struct assignment with no closures, Verdict alignmentA's ConvergenceAligned. All three commits are correct: the core BDDRunner fix, the docs follow-up, and the assertion tightening. No further changes needed. Joint recommendation: approve. |
…ntinel (#2853) * fix(test): repair CLI suite failures masked by the BDDRunner error sentinel The CLI suite (cli/lucli/tests/specs) carried 13 pre-existing failures that BDDRunner's legacy -1 bundle-error sentinel had been arithmetically cancelling: a negative error total netted real failures to <= 0, so CI read the suite as green. (PR #2831 flips that sentinel to +1, which surfaces them.) This repairs the suite directly so it is honestly green. - Add a lightweight modules.BaseModule test double (cli/lucli/tests/_modules) plus a /modules mapping so the *CommandSpec bundles can instantiate cli.lucli.Module under TestBox -- resurrecting Db/Info/Migrate/Test as real behavioral coverage. Longest-prefix keeps /modules/wheels authoritative. - Fix the stale AdminSpec assertion (.namespace("admin"), not the legacy .scope(path="admin") the service no longer emits). - xdescribe/xit (with documented reasons) the specs that need the LuCLI runtime / CodeGen fixtures / CLI wrapper (Deploy/Destroy/Generate/Packages) and the unbuilt-feature specs (Doctor #2260, Scaffold RMB), pending a command-by-command CLI test audit. - Harden tools/ci/run-tests.sh: clamp a negative error count and fail explicitly on one, so this masking class can't recur. Refs #2829 Signed-off-by: Peter Amiri <peter@alurium.com> * fix(test): address Reviewer A/B consensus findings (round 1) - Collapse 20-line docblock in cli/lucli/tests/_modules/BaseModule.cfc to one line (CLAUDE.md "one short line max" rule). - Drop `private` from BaseModule.cfc out()/err() so they match the inherited surface real LuCLI's modules.BaseModule exposes to Module.cfc subclass calls. - Collapse 6-line comment in public/Application.cfc above /modules mapping to one line. - Collapse 4-line comment in cli/lucli/tests/Application.cfc above /modules mapping to one line. PR label flipped from `docs` to `bug` separately via gh. Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> * fix(test): skip server-dependent migrate/test command specs (no server in CI) CI surfaced what a local dev server had masked: MigrateCommandSpec (migrate + seed) and TestCommandSpec's "wheels test" cases invoke commands that detect a *running* Wheels server (via lucee.json/.env ports). The stateless CI harness has none on the expected port, so all 23 errored with "No running Wheels server detected" -- they only "passed" locally because a dev server happened to satisfy detection. xdescribe both MigrateCommandSpec describes and TestCommandSpec's "wheels test" describe (its $normalizeTestFilter / $resolveAppTestDataSource unit describes are server-independent and keep running). Db/Info command specs remain real resurrected coverage (server-independent; green in CI). Refs #2829 Signed-off-by: Peter Amiri <peter@alurium.com> --------- Signed-off-by: Peter Amiri <peter@alurium.com> Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
… positive error count Spec files whose run() called it() outside a describe() block, or whose beforeAll() threw during load, were silently dropped (the run bubbled up as an anonymous BundleRunnerMajorException) or surfaced as the legacy "-1 error(s)" sentinel in the summary, with no file context. BDDRunner now starts bundle stats before invoking the target and wraps both the suite-descriptor pass (target.run / getTestSuites) and the bundle execution (beforeAll, suite iteration, afterAll) in a single catch that records the throw against bundleStats.globalException and increments the error count by one. Tooling that walks bundleStats.path / globalException already surfaces the filename and exception detail. Fixes the silent-failure reports in issue #2829 for both shapes — a malformed orphan-it() spec and a load-time exception from a setup hook. Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
…modes Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Address Reviewer A/B consensus from PR #2831 round 1: both reviewers agreed the BeforeAllErrorFixture case in vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc should match the OrphanItFixture case's exact-count style. The catch block in BDDRunner.cfc unconditionally records totalError = 1 per failed bundle, so toBeGT(0) was weaker than the invariant the fix guarantees. - vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc lines 39 and 42: toBeGT(0) -> toBe(1) for results.getTotalError() and bs[1].totalError in the BeforeAllErrorFixture case. Verified: wheelstest layer 143 pass / 0 fail / 0 error against the running CI server (sqlite). Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
15810f4 to
c22c2cf
Compare
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: Post-rebase re-review of the same three commits that were approved at SHA 15810f495. The PR was rebased onto a newer develop HEAD, producing the new SHA c22c2cfa7; the content of all three commits is identical to what was reviewed in round 4. The BDDRunner fix is correct, the spec assertions use exact counts in both cases, commits are commitlint-clean, and docs are updated. Verdict: approve (GitHub blocks self-approval on bot-authored PRs, so this is recorded as a comment instead).
Correctness
vendor/wheels/wheelstest/system/runners/BDDRunner.cfc, lines 55–174
Moving startBundleStats before arguments.target.run() and widening the try/catch to cover both the suite-descriptor pass and the bundle-execution pass is the right fix for both failure shapes. The happy path is preserved: canRunBundle, beforeAll/afterAll, and endStats all run in the same order as before.
The isNull(thisSuite) guard in the catch block (line 171) is safe across all supported engines. CFML hoists var declarations from for loops into function scope, so thisSuite is declared (and null) even when the catch fires before the loop is entered — which is the case when target.run() throws on the OrphanItFixture path.
The catch block writes bundleStats.globalException = e and bundleStats.totalError = 1 as struct field assignments (not local.X assignments), which is the safe pattern that survives BoxLang's catch-scope isolation (Cross-Engine Invariant #11).
Tests
vendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfc, lines 23, 26, 39, 42
The nit from round 1 — tightening toBeGT(0) to toBe(1) on the BeforeAllErrorFixture assertions — is resolved. Both cases now read:
expect(results.getTotalError()).toBe(1);
expect(bs[1].totalError).toBe(1);This locks the invariant guaranteed by the bundleStats.totalError = 1 hard-assignment in the catch block. The shared-struct pattern (var state = {threw: false, results: ""}) used in the OrphanIt case correctly routes around the closure-scope issue (Anti-Pattern #10).
Commits
Three commits, all conforming to commitlint.config.js:
fix(wheelstest): capture spec-load errors against the bundle and emit positive error count— 68 chars, DCO signed, explains the why in the body.docs(web/guides): note BDD runner load-time errors in common failure modes— 52 chars, DCO signed.fix(wheelstest): tighten BeforeAllErrorFixture assertions to toBe(1)— 49 chars, DCO signed.
Docs
CHANGELOG.md carries a [Unreleased] → Fixed entry. web/sites/guides/src/content/docs/v4-0-0/testing/running-tests-locally.mdx adds a bullet under "Common failure modes" that names both error shapes and points users to globalException. Both are accurate and well-placed.
Wheels Bot — Reviewer B (round 1)A's re-review of the rebased SHA is accurate and well-grounded. One minor false positive on commit character-count methodology — not consequential, all three commits pass the limit — and no missed issues on the diff. Aligned on approve. SycophancyNone detected. A correctly identified this as a rebase re-review (same three commits, new SHA), cited specific line numbers, and explained the reasoning behind each finding rather than deferring to prior approval. False positivesOne methodology issue: A cites commit header lengths as "68", "52", and "49" chars respectively, but those figures appear to count only the subject portion and not the full
All three are under the 100-char ceiling, so A's conclusion (conforming) is correct. The cited numbers are wrong but the call stands. Everything else A claimed was verified against the diff:
Missed issuesNone detected. The remaining Verdict alignmentA's ConvergenceAligned. The three commits are correct: the BDDRunner catch widening, the docs follow-up, and the assertion tightening. The char-count methodology issue is not consequential — all headers pass linting. Joint recommendation: approve. |
…n-browser-login-as-set Resolve CHANGELOG.md [Unreleased] Added conflict by keeping both the RustCFML engine-recognition entry (#2837) and the browserLoginAsHandler fixture-override entry (#2830). Brings in #2831/#2853, which repair the CLI test suite masking (the prior 605/5/-8 result). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Peter Amiri <peter@alurium.com>
Summary
The WheelsTest BDD runner silently dropped spec files whose
run()invokedit()outside adescribe()block (the throw bubbled out as an anonymousBundleRunnerMajorExceptionwith no file context), and reported a-1sentinel error count when a spec'sbeforeAll()threw during load. Both shapes are easy to land accidentally during TDD iteration and cost minutes of "why isn't my new test running?" debugging.vendor/wheels/wheelstest/system/runners/BDDRunner.cfcnow starts the bundle stats record before invoking the target and wraps both the suite-descriptor pass (target.run/getTestSuites) and the bundle execution (beforeAll, suite iteration,afterAll) in one catch. The catch records the throw againstbundleStats.globalExceptionand increments the error count by a positive one, so the summary reads "1 error(s)" with the offending bundle path and the underlying exception attached. The existingdisplayTestResultswalker already surfaces the path + message once a positive count is recorded.Related Issue
Closes #2829
Type of Change
Feature Completeness Checklist
Signed-off-by:(usegit commit -s); see CONTRIBUTING.mdvendor/wheels/tests/specs/wheelstest/BDDRunnerErrorReportingSpec.cfcreproduces both shapes via two fixture bundles (OrphanItFixture,BeforeAllErrorFixture) and assertstotalError == 1plusbundleStats[1].globalExceptionpopulated; failing-then-passingbot-update-docs.ymlfollow-upbot-update-docs.ymlfollow-upbot-update-docs.ymlfollow-up[Unreleased] -> Fixedwheels.tests.specs.wheelstest143 pass / 0 fail / 0 error (HTTP 200) after the patch; broader spot checks:wheels.tests.specs.security182 pass / 0 fail,wheels.tests.specs.dispatch96 pass / 0 fail,wheels.tests.specs.model843 pass / 11 skip / 0 fail (no regressions)Test Plan
The TDD failing-then-passing capture is the primary verification.
Before the patch, against
wheels.tests.specs.wheelstest.BDDRunnerErrorReportingSpec:Expected [true] to be false—state.threw == truebecause the orphan-it()fixture surfaced asBundleRunnerMajorExceptionrather than landing in the bundle's catchThe actual [-1] is not greater than [0]—results.getTotalError()was the-1sentinelAfter the patch (HTTP 200, both specs green) and a re-run of
security,dispatch, andmodelshows no regressions in the unrelated test layers.