From 0ea03076702f259035dc42d9fcf56b184ae69fca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 00:52:03 +0000 Subject: [PATCH 1/5] Initial plan From f0b3390671dc9b03a4715e6aea5677c5d5ed346d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 00:57:38 +0000 Subject: [PATCH 2/5] Add exception when layout is missing head/body tags for asset injection Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com> --- interceptors/CBWIRE.cfc | 16 ++++++++++++++ test-harness/handlers/Tests.cfc | 21 ++++++++++++++++++ test-harness/layouts/MissingBodyTag.cfm | 9 ++++++++ test-harness/layouts/MissingBothTags.cfm | 6 ++++++ test-harness/layouts/MissingHeadTag.cfm | 8 +++++++ test-harness/tests/specs/CBWIRESpec.cfc | 27 ++++++++++++++++++++++++ test-harness/views/tests/missingtags.cfm | 3 +++ 7 files changed, 90 insertions(+) create mode 100644 test-harness/handlers/Tests.cfc create mode 100644 test-harness/layouts/MissingBodyTag.cfm create mode 100644 test-harness/layouts/MissingBothTags.cfm create mode 100644 test-harness/layouts/MissingHeadTag.cfm create mode 100644 test-harness/views/tests/missingtags.cfm diff --git a/interceptors/CBWIRE.cfc b/interceptors/CBWIRE.cfc index 6463489e..cbd36a90 100644 --- a/interceptors/CBWIRE.cfc +++ b/interceptors/CBWIRE.cfc @@ -140,6 +140,22 @@ component { function postLayoutRender() { if ( shouldInject( arguments.event ) && !request.keyExists( "_cbwire_injected_assets" ) ) { + // Check if the layout has required tags for asset injection + if ( !findNoCase( "", arguments.data.renderedLayout ) ) { + throw( + type = "CBWIREException", + message = "Layout is missing tag required for wireStyles() injection.", + detail = "Your layout must include a tag where CBWIRE can inject CSS styles. Either add a tag to your layout or set 'autoInjectAssets' to false and manually call wireStyles() and wireScripts()." + ); + } + if ( !findNoCase( "", arguments.data.renderedLayout ) ) { + throw( + type = "CBWIREException", + message = "Layout is missing tag required for wireScripts() injection.", + detail = "Your layout must include a tag where CBWIRE can inject JavaScript. Either add a tag to your layout or set 'autoInjectAssets' to false and manually call wireStyles() and wireScripts()." + ); + } + arguments.data.renderedLayout = replaceNoCase( arguments.data.renderedLayout, "", getStyles() & chr( 10 ) & "", "one" ); arguments.data.renderedLayout = replaceNoCase( arguments.data.renderedLayout, "", getScripts() & chr( 10 ) & "", "one" ); request._cbwire_injected_assets = true; diff --git a/test-harness/handlers/Tests.cfc b/test-harness/handlers/Tests.cfc new file mode 100644 index 00000000..1033a0c4 --- /dev/null +++ b/test-harness/handlers/Tests.cfc @@ -0,0 +1,21 @@ +/** + * Handler for testing missing layout tags + */ +component { + + function testMissingHeadTag( event, rc, prc ) { + event.setLayout( "MissingHeadTag" ); + event.setView( "tests/missingtags" ); + } + + function testMissingBodyTag( event, rc, prc ) { + event.setLayout( "MissingBodyTag" ); + event.setView( "tests/missingtags" ); + } + + function testMissingBothTags( event, rc, prc ) { + event.setLayout( "MissingBothTags" ); + event.setView( "tests/missingtags" ); + } + +} diff --git a/test-harness/layouts/MissingBodyTag.cfm b/test-harness/layouts/MissingBodyTag.cfm new file mode 100644 index 00000000..21aef2e1 --- /dev/null +++ b/test-harness/layouts/MissingBodyTag.cfm @@ -0,0 +1,9 @@ + + + + + Missing Body Tag + + #view()# + + diff --git a/test-harness/layouts/MissingBothTags.cfm b/test-harness/layouts/MissingBothTags.cfm new file mode 100644 index 00000000..4b520785 --- /dev/null +++ b/test-harness/layouts/MissingBothTags.cfm @@ -0,0 +1,6 @@ + + + + #view()# + + diff --git a/test-harness/layouts/MissingHeadTag.cfm b/test-harness/layouts/MissingHeadTag.cfm new file mode 100644 index 00000000..39698769 --- /dev/null +++ b/test-harness/layouts/MissingHeadTag.cfm @@ -0,0 +1,8 @@ + + + + + #view()# + + + diff --git a/test-harness/tests/specs/CBWIRESpec.cfc b/test-harness/tests/specs/CBWIRESpec.cfc index 265eff9e..03d10c68 100644 --- a/test-harness/tests/specs/CBWIRESpec.cfc +++ b/test-harness/tests/specs/CBWIRESpec.cfc @@ -127,6 +127,33 @@ component extends="coldbox.system.testing.BaseTestCase" { expect( beforeHead ).toInclude( "" ); } ); + it( "should throw exception when layout is missing tag with autoInjectAssets enabled", function() { + var settings = getInstance( "coldbox:modulesettings:cbwire" ); + settings.autoInjectAssets = true; + expect( function() { + this.get( "tests.testMissingHeadTag" ); + } ).toThrow( type="CBWIREException", message="Layout is missing tag required for wireStyles() injection." ); + } ); + + it( "should throw exception when layout is missing tag with autoInjectAssets enabled", function() { + var settings = getInstance( "coldbox:modulesettings:cbwire" ); + settings.autoInjectAssets = true; + expect( function() { + this.get( "tests.testMissingBodyTag" ); + } ).toThrow( type="CBWIREException", message="Layout is missing tag required for wireScripts() injection." ); + } ); + + it( "should not throw exception when layout is missing tags with autoInjectAssets disabled", function() { + var settings = getInstance( "coldbox:modulesettings:cbwire" ); + settings.autoInjectAssets = false; + var event = this.get( "tests.testMissingBothTags" ); + var html = event.getRenderedContent(); + // Should render without error + expect( html ).toBeString(); + expect( html ).notToInclude( "" ); + expect( html ).notToInclude( "" ); + } ); + } ); describe("Component.cfc", function() { diff --git a/test-harness/views/tests/missingtags.cfm b/test-harness/views/tests/missingtags.cfm new file mode 100644 index 00000000..54f6aa73 --- /dev/null +++ b/test-harness/views/tests/missingtags.cfm @@ -0,0 +1,3 @@ + + #wire( "Counter" )# + From ecef09db410f825a746923f09e06ed51da9854a7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 01:00:09 +0000 Subject: [PATCH 3/5] Fix trailing whitespace in CBWIRE.cfc Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com> --- interceptors/CBWIRE.cfc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interceptors/CBWIRE.cfc b/interceptors/CBWIRE.cfc index cbd36a90..2845b0a1 100644 --- a/interceptors/CBWIRE.cfc +++ b/interceptors/CBWIRE.cfc @@ -155,7 +155,7 @@ component { detail = "Your layout must include a tag where CBWIRE can inject JavaScript. Either add a tag to your layout or set 'autoInjectAssets' to false and manually call wireStyles() and wireScripts()." ); } - + arguments.data.renderedLayout = replaceNoCase( arguments.data.renderedLayout, "", getStyles() & chr( 10 ) & "", "one" ); arguments.data.renderedLayout = replaceNoCase( arguments.data.renderedLayout, "", getScripts() & chr( 10 ) & "", "one" ); request._cbwire_injected_assets = true; From e4a2347d74c6bd1401d56f767f9f3df1d06161c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 01:23:07 +0000 Subject: [PATCH 4/5] Optimize layout tag validation by reading layout file instead of rendered content Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com> --- interceptors/CBWIRE.cfc | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/interceptors/CBWIRE.cfc b/interceptors/CBWIRE.cfc index 2845b0a1..eed7a648 100644 --- a/interceptors/CBWIRE.cfc +++ b/interceptors/CBWIRE.cfc @@ -140,15 +140,18 @@ component { function postLayoutRender() { if ( shouldInject( arguments.event ) && !request.keyExists( "_cbwire_injected_assets" ) ) { + // Get the layout file content to check for required tags + local.layoutContent = getLayoutContent( arguments.event ); + // Check if the layout has required tags for asset injection - if ( !findNoCase( "", arguments.data.renderedLayout ) ) { + if ( !findNoCase( "", local.layoutContent ) ) { throw( type = "CBWIREException", message = "Layout is missing tag required for wireStyles() injection.", detail = "Your layout must include a tag where CBWIRE can inject CSS styles. Either add a tag to your layout or set 'autoInjectAssets' to false and manually call wireStyles() and wireScripts()." ); } - if ( !findNoCase( "", arguments.data.renderedLayout ) ) { + if ( !findNoCase( "", local.layoutContent ) ) { throw( type = "CBWIREException", message = "Layout is missing tag required for wireScripts() injection.", @@ -162,6 +165,40 @@ component { } } + /** + * Gets the layout file content for validation. + * Reads the actual layout file from disk based on the current layout name. + * + * @event The request context object + * + * @return string The layout file content + */ + private function getLayoutContent( event ) { + // Get the current layout name from the private collection + local.layoutName = arguments.event.getPrivateValue( "currentLayout", "" ); + + if ( !len( local.layoutName ) ) { + return ""; + } + + // Get the layouts directory path + local.layoutsPath = expandPath( "/layouts/" ); + + // Try common file extensions + local.extensions = [ ".cfm", ".bxm" ]; + + for ( local.ext in local.extensions ) { + local.layoutFile = local.layoutsPath & local.layoutName & local.ext; + if ( fileExists( local.layoutFile ) ) { + return fileRead( local.layoutFile ); + } + } + + // If we can't find the layout file, return empty string + // This will allow the existing rendered content check to fail gracefully + return ""; + } + function preModuleLoad() eventPattern="^cbwire.*" { return true; } From 97138408dfac45f6f8a3bc7f5221482e1717cfec Mon Sep 17 00:00:00 2001 From: Grant Copley Date: Tue, 25 Nov 2025 19:43:46 -0600 Subject: [PATCH 5/5] Normalize file path verification in FileUploadSpec to handle platform differences --- test-harness/tests/specs/FileUploadSpec.cfc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test-harness/tests/specs/FileUploadSpec.cfc b/test-harness/tests/specs/FileUploadSpec.cfc index 2ba399e7..20d2107c 100644 --- a/test-harness/tests/specs/FileUploadSpec.cfc +++ b/test-harness/tests/specs/FileUploadSpec.cfc @@ -139,14 +139,15 @@ component extends="coldbox.system.testing.BaseTestCase" { var result = loadMockedFileUpload( "test-store-file", "text", "plain" ); var destinationDir = getTempDirectory() & "/cbwire-test-store-file"; var destinationPath = destinationDir & "/myfile.png"; - + // Store the file with specific filename var storedPath = result.store( destinationPath ); - + // Verify the file was moved to the destination with the new name expect( fileExists( storedPath ) ).toBeTrue(); - expect( storedPath ).toBe( getCanonicalPath( destinationPath ) ); - + // Normalize both paths to handle platform differences (e.g., /var vs /private/var on macOS) + expect( getCanonicalPath( storedPath ) ).toBe( getCanonicalPath( destinationPath ) ); + // Clean up if ( directoryExists( destinationDir ) ) { directoryDelete( destinationDir, true );