From 8143fa24f7c8dd043ce86eec3836dab6a480099c Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 30 Aug 2026 04:58:43 +0000 Subject: [PATCH] TESTBOX-456: Simplify BoxLang CLI url scope guard to a param Replace the two-condition if-guard (!IS_CLI || isDefined("url")) with a plain `param name="url" default={};` at the top of runRaw()/dryRun(). param is a no-op wherever the scope already exists (every engine, every non-CLI request) and only defaults it in the one case that was ever broken - BoxLang CLI, where the scope isn't registered at all. Verified against real BoxLang v1.17.0+58: dryRun()/runRaw() both complete without throwing in CLI mode (isDefined('url') == false). --- system/TestBox.cfc | 56 ++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/system/TestBox.cfc b/system/TestBox.cfc index 58195ad..db0066c 100644 --- a/system/TestBox.cfc +++ b/system/TestBox.cfc @@ -408,21 +408,20 @@ component accessors="true" { // The `url` scope only exists in a real HTTP request - it isn't registered at all when // TestBox runs via the BoxLang CLI, so even a `structKeyExists( url, ... )` guard throws // (resolving the bare `url` identifier is what fails, not the key lookup within it). - // `isDefined()` is the safe way to probe for scope existence without that risk, so - // don't just skip on IS_CLI - only skip when the scope truly isn't there. - if ( !variables.IS_CLI || isDefined( "url" ) ) { - if ( structKeyExists( url, "testBundles" ) && !isNull( url.testBundles ) ) { - testBundles.append( listToArray( urlDecode( url.testBundles ) ), true ); - } - if ( structKeyExists( url, "testSuites" ) && !isNull( url.testSuites ) ) { - arguments.testSuites.append( listToArray( urlDecode( url.testSuites ) ), true ); - } - if ( structKeyExists( url, "testSpecs" ) && !isNull( url.testSpecs ) ) { - arguments.testSpecs.append( listToArray( urlDecode( url.testSpecs ) ), true ); - } - if ( structKeyExists( url, "testMethod" ) && !isNull( url.testMethod ) ) { - arguments.testSpecs.append( listToArray( urlDecode( url.testMethod ) ), true ); - } + // Param it to an empty struct so it's always safe to touch below - a no-op everywhere + // the scope already exists (every engine, every non-CLI request). + param name="url" default={}; + if ( structKeyExists( url, "testBundles" ) && !isNull( url.testBundles ) ) { + testBundles.append( listToArray( urlDecode( url.testBundles ) ), true ); + } + if ( structKeyExists( url, "testSuites" ) && !isNull( url.testSuites ) ) { + arguments.testSuites.append( listToArray( urlDecode( url.testSuites ) ), true ); + } + if ( structKeyExists( url, "testSpecs" ) && !isNull( url.testSpecs ) ) { + arguments.testSpecs.append( listToArray( urlDecode( url.testSpecs ) ), true ); + } + if ( structKeyExists( url, "testMethod" ) && !isNull( url.testMethod ) ) { + arguments.testSpecs.append( listToArray( urlDecode( url.testMethod ) ), true ); } // Using a directory runner? @@ -531,20 +530,19 @@ component accessors="true" { isSimpleValue( arguments.testSpecs ) ? listToArray( arguments.testSpecs ) : arguments.testSpecs ); - // The `url` scope only exists in a real HTTP request - see the identical guard in runRaw(). - if ( !variables.IS_CLI || isDefined( "url" ) ) { - if ( structKeyExists( url, "testBundles" ) && !isNull( url.testBundles ) ) { - arguments.testBundles.append( listToArray( urlDecode( url.testBundles ) ), true ); - } - if ( structKeyExists( url, "testSuites" ) && !isNull( url.testSuites ) ) { - arguments.testSuites.append( listToArray( urlDecode( url.testSuites ) ), true ); - } - if ( structKeyExists( url, "testSpecs" ) && !isNull( url.testSpecs ) ) { - arguments.testSpecs.append( listToArray( urlDecode( url.testSpecs ) ), true ); - } - if ( structKeyExists( url, "testMethod" ) && !isNull( url.testMethod ) ) { - arguments.testSpecs.append( listToArray( urlDecode( url.testMethod ) ), true ); - } + // The `url` scope only exists in a real HTTP request - see the identical param in runRaw(). + param name="url" default={}; + if ( structKeyExists( url, "testBundles" ) && !isNull( url.testBundles ) ) { + arguments.testBundles.append( listToArray( urlDecode( url.testBundles ) ), true ); + } + if ( structKeyExists( url, "testSuites" ) && !isNull( url.testSuites ) ) { + arguments.testSuites.append( listToArray( urlDecode( url.testSuites ) ), true ); + } + if ( structKeyExists( url, "testSpecs" ) && !isNull( url.testSpecs ) ) { + arguments.testSpecs.append( listToArray( urlDecode( url.testSpecs ) ), true ); + } + if ( structKeyExists( url, "testMethod" ) && !isNull( url.testMethod ) ) { + arguments.testSpecs.append( listToArray( urlDecode( url.testMethod ) ), true ); } var filterState = new testbox.system.TestResult(