From 853823da896da85ada81513b544ea1cbe48fed7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 06:24:06 +0000 Subject: [PATCH 1/4] Initial plan From 8a7e7c925456d05455ddb54e89a05154b70dc5b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 06:30:22 +0000 Subject: [PATCH 2/4] Add enhanced error reporting for single-file components Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com> --- models/Component.cfc | 133 +++++++++++++++++++++++++- models/EmptySingleFileComponent.bx | 11 +++ models/EmptySingleFileComponent.cfc | 11 +++ models/SingleFileComponentBuilder.cfc | 24 ++++- 4 files changed, 176 insertions(+), 3 deletions(-) diff --git a/models/Component.cfc b/models/Component.cfc index 606bf24..b2a859c 100644 --- a/models/Component.cfc +++ b/models/Component.cfc @@ -702,6 +702,14 @@ component output="true" accessors="true" { params=arguments.params ); } catch ( any e ) { + // Enhance exception for single-file components + if ( _isSingleFileComponent() ) { + throw( + type = "CBWIREException", + message = "Failure when calling onMount(). " & _buildEnhancedErrorMessage( e ), + detail = e.detail ?: "" + ); + } throw( type="CBWIREException", message="Failure when calling onMount(). #e.message#" ); } } @@ -1102,6 +1110,14 @@ component output="true" accessors="true" { } catch ( ValidationException e ) { // silently fail so the component can continue to render } catch( any e ) { + // Enhance exception for single-file components + if ( _isSingleFileComponent() ) { + throw( + type = e.type ?: "CBWIREException", + message = _buildEnhancedErrorMessage( e ), + detail = e.detail ?: "" + ); + } rethrow; } } ); @@ -1706,8 +1722,20 @@ component output="true" accessors="true" { // should render based on if onSecure exists and allows rendering. render only if true. var renderedContent = ""; if( _onSecureShouldRender() ){ - local.trimmedHTML = isNull( arguments.rendering ) ? trim( onRender() ) : trim( arguments.rendering ); - renderedContent = variables._renderService.render( this, local.trimmedHTML ); + try { + local.trimmedHTML = isNull( arguments.rendering ) ? trim( onRender() ) : trim( arguments.rendering ); + renderedContent = variables._renderService.render( this, local.trimmedHTML ); + } catch ( any e ) { + // Enhance exception for single-file components + if ( _isSingleFileComponent() ) { + throw( + type = e.type ?: "CBWIREException", + message = _buildEnhancedErrorMessage( e ), + detail = e.detail ?: "" + ); + } + rethrow; + } }else{ // fireInterceptor event for blocked render @@ -1731,6 +1759,107 @@ component output="true" accessors="true" { return variables._compileTimeKey; } + /** + * Returns true if this component was generated from a single-file component. + * + * @return boolean + */ + function _isSingleFileComponent() { + return variables.keyExists( "_singleFileSourcePath" ) && len( variables._singleFileSourcePath ); + } + + /** + * Returns the original source file path for single-file components. + * Returns empty string for regular components. + * + * @return string + */ + function _getSingleFileSourcePath() { + return variables.keyExists( "_singleFileSourcePath" ) ? variables._singleFileSourcePath : ""; + } + + /** + * Returns the line offset for mapping generated code back to the original source file. + * This is the line number where @startWire begins in the original file. + * + * @return numeric + */ + function _getSingleFileLineOffset() { + return variables.keyExists( "_singleFileLineOffset" ) ? variables._singleFileLineOffset : 0; + } + + /** + * Enhances an exception with single-file component source information. + * This helps developers understand where errors originated in their original source file. + * + * @exception struct | The caught exception to enhance + * + * @return struct | Enhanced exception information with source file context + */ + function _enhanceExceptionForSingleFile( required any exception ) { + var enhanced = { + "originalException": arguments.exception, + "isSingleFileComponent": _isSingleFileComponent(), + "message": arguments.exception.message ?: "", + "detail": arguments.exception.detail ?: "", + "type": arguments.exception.type ?: "Application" + }; + + if ( enhanced.isSingleFileComponent ) { + enhanced[ "singleFileSourcePath" ] = _getSingleFileSourcePath(); + enhanced[ "singleFileLineOffset" ] = _getSingleFileLineOffset(); + enhanced[ "enhancedMessage" ] = _buildEnhancedErrorMessage( arguments.exception ); + } + + return enhanced; + } + + /** + * Builds an enhanced error message that includes single-file component source information. + * + * @exception struct | The caught exception + * + * @return string | The enhanced error message + */ + function _buildEnhancedErrorMessage( required any exception ) { + var sourcePath = _getSingleFileSourcePath(); + var lineOffset = _getSingleFileLineOffset(); + var originalMessage = arguments.exception.message ?: "Unknown error"; + + var enhancedMessage = originalMessage; + enhancedMessage &= chr(10) & chr(10) & "=== CBWIRE Single-File Component Debug Info ===" & chr(10); + enhancedMessage &= "Original source file: " & sourcePath & chr(10); + + if ( lineOffset > 0 ) { + enhancedMessage &= "Wire code starts at line: " & lineOffset & " in the original file" & chr(10); + enhancedMessage &= "To find the actual error line in your source file, add " & lineOffset & " to any line numbers shown in the generated component stack trace." & chr(10); + } + + // Try to extract line number from the exception if available + if ( structKeyExists( arguments.exception, "tagContext" ) && isArray( arguments.exception.tagContext ) && arguments.exception.tagContext.len() ) { + // Look for the tmp file reference in the stack trace + for ( var ctx in arguments.exception.tagContext ) { + if ( structKeyExists( ctx, "template" ) && ctx.template contains "cbwire" && ctx.template contains "tmp" ) { + var generatedLine = structKeyExists( ctx, "line" ) ? ctx.line : 0; + if ( generatedLine > 0 && lineOffset > 0 ) { + // The generated component has some header lines, so we need to account for that + // The header in EmptySingleFileComponent.cfc has approximately 14 lines before CFC_CONTENTS + var headerLines = 14; + var estimatedSourceLine = generatedLine - headerLines + lineOffset; + if ( estimatedSourceLine > 0 ) { + enhancedMessage &= "Estimated source line: ~" & estimatedSourceLine & chr(10); + } + } + break; + } + } + } + + enhancedMessage &= "================================================"; + + return enhancedMessage; + } + /** * Fires an interceptor event. * Standardizes data passed to interceptors fired from base wire Component.cfc diff --git a/models/EmptySingleFileComponent.bx b/models/EmptySingleFileComponent.bx index 676d96a..199c539 100644 --- a/models/EmptySingleFileComponent.bx +++ b/models/EmptySingleFileComponent.bx @@ -1,5 +1,16 @@ class extends="{{ EXTENDS_PATH }}" { + /** + * Path to the original single-file component source for error reporting. + */ + variables._singleFileSourcePath = "{{ SOURCE_PATH }}"; + + /** + * Line offset for mapping generated code back to original source. + * This is the line number in the original file where @startWire begins. + */ + variables._singleFileLineOffset = {{ LINE_OFFSET }}; + {{ CFC_CONTENTS }} function onRender() { diff --git a/models/EmptySingleFileComponent.cfc b/models/EmptySingleFileComponent.cfc index a6877a6..ac3e592 100644 --- a/models/EmptySingleFileComponent.cfc +++ b/models/EmptySingleFileComponent.cfc @@ -1,5 +1,16 @@ component extends="{{ EXTENDS_PATH }}" { + /** + * Path to the original single-file component source for error reporting. + */ + variables._singleFileSourcePath = "{{ SOURCE_PATH }}"; + + /** + * Line offset for mapping generated code back to original source. + * This is the line number in the original file where @startWire begins. + */ + variables._singleFileLineOffset = {{ LINE_OFFSET }}; + {{ CFC_CONTENTS }} function onRender() { diff --git a/models/SingleFileComponentBuilder.cfc b/models/SingleFileComponentBuilder.cfc index 799ada3..e7ad815 100644 --- a/models/SingleFileComponentBuilder.cfc +++ b/models/SingleFileComponentBuilder.cfc @@ -50,6 +50,8 @@ component accessors="true" singleton { local.startedWire = false; local.endedWire = false; + local.lineNumber = 0; + local.startWireLineNumber = 0; local.isBoxLang = arguments.cfmPath.listToArray(".").last() == "bxm" ? true : false; local.insideScriptTag = false; @@ -57,6 +59,7 @@ component accessors="true" singleton { local.REEndScriptTag = local.isBoxLang ? "<\s*/\s*bx:script\s*>" : "<\s*/\s*cfscript\s*>"; for ( local.line in local.fileContents.listToArray( chr( 10 ) ) ) { + local.lineNumber++; if ( REFindNoCase( local.REStartScriptTag, local.line ) > 0 ) { local.insideScriptTag = true; @@ -80,6 +83,7 @@ component accessors="true" singleton { if ( local.insideScriptTag && local.line contains "@startWire" ) { local.startedWire = true; + local.startWireLineNumber = local.lineNumber; continue; } if ( local.insideScriptTag && local.line contains "@endWire" ) { @@ -97,7 +101,8 @@ component accessors="true" singleton { return { "singleFileContents" : local.singleFileContents, "remainingContents" : local.remainingContents, - "extendsPath" : local.extendsPath + "extendsPath" : local.extendsPath, + "startWireLineNumber" : local.startWireLineNumber }; } @@ -173,6 +178,23 @@ component accessors="true" singleton { "one" ); + // Add source path for error reporting (escape backslashes for Windows paths) + local.escapedSourcePath = replace( arguments.sourcePath, "\", "\\", "all" ); + local.emptySingleFileComponent = replaceNoCase( + local.emptySingleFileComponent, + "{{ SOURCE_PATH }}", + local.escapedSourcePath, + "one" + ); + + // Add line offset for error reporting + local.emptySingleFileComponent = replaceNoCase( + local.emptySingleFileComponent, + "{{ LINE_OFFSET }}", + local.parsedContents.startWireLineNumber, + "one" + ); + local.uuid = createUUID(); fileWrite( local.tmpClassPath, local.emptySingleFileComponent ); From fdc775f3437768f44478fa0503a8a5d80be7d313 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 06:31:35 +0000 Subject: [PATCH 3/4] Add unit tests for single-file component error reporting Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com> --- .../tests/specs/unit/ComponentSpec.cfc | 94 ++++++++++++++++ .../unit/SingleFileComponentBuilderSpec.cfc | 100 ++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 test-harness/tests/specs/unit/SingleFileComponentBuilderSpec.cfc diff --git a/test-harness/tests/specs/unit/ComponentSpec.cfc b/test-harness/tests/specs/unit/ComponentSpec.cfc index 4073c2c..6739e1c 100644 --- a/test-harness/tests/specs/unit/ComponentSpec.cfc +++ b/test-harness/tests/specs/unit/ComponentSpec.cfc @@ -78,6 +78,100 @@ component extends="coldbox.system.testing.BaseTestCase" { }); + describe( "Single-file component error reporting", function() { + + it( "_isSingleFileComponent returns false for regular components", function() { + // Regular components don't have _singleFileSourcePath set + var result = variables.wireComponent._isSingleFileComponent(); + expect( result ).toBeFalse(); + }); + + it( "_getSingleFileSourcePath returns empty string for regular components", function() { + var result = variables.wireComponent._getSingleFileSourcePath(); + expect( result ).toBe( "" ); + }); + + it( "_getSingleFileLineOffset returns 0 for regular components", function() { + var result = variables.wireComponent._getSingleFileLineOffset(); + expect( result ).toBe( 0 ); + }); + + it( "_isSingleFileComponent returns true when _singleFileSourcePath is set", function() { + // Simulate a single-file component by setting the variables + variables.wireComponent.$property( propertyName="_singleFileSourcePath", mock="/path/to/TestComponent.cfm" ); + var result = variables.wireComponent._isSingleFileComponent(); + expect( result ).toBeTrue(); + }); + + it( "_getSingleFileSourcePath returns the path when set", function() { + var testPath = "/path/to/TestComponent.cfm"; + variables.wireComponent.$property( propertyName="_singleFileSourcePath", mock=testPath ); + var result = variables.wireComponent._getSingleFileSourcePath(); + expect( result ).toBe( testPath ); + }); + + it( "_getSingleFileLineOffset returns the offset when set", function() { + variables.wireComponent.$property( propertyName="_singleFileLineOffset", mock=15 ); + var result = variables.wireComponent._getSingleFileLineOffset(); + expect( result ).toBe( 15 ); + }); + + it( "_buildEnhancedErrorMessage includes source file path", function() { + variables.wireComponent.$property( propertyName="_singleFileSourcePath", mock="/path/to/TestComponent.cfm" ); + variables.wireComponent.$property( propertyName="_singleFileLineOffset", mock=10 ); + + var mockException = { + "message": "Test error message", + "detail": "Test detail", + "type": "TestException" + }; + + var result = variables.wireComponent._buildEnhancedErrorMessage( mockException ); + + expect( result ).toInclude( "Test error message" ); + expect( result ).toInclude( "/path/to/TestComponent.cfm" ); + expect( result ).toInclude( "CBWIRE Single-File Component Debug Info" ); + expect( result ).toInclude( "Wire code starts at line: 10" ); + }); + + it( "_enhanceExceptionForSingleFile returns enhanced struct for single-file components", function() { + variables.wireComponent.$property( propertyName="_singleFileSourcePath", mock="/path/to/TestComponent.cfm" ); + variables.wireComponent.$property( propertyName="_singleFileLineOffset", mock=10 ); + + var mockException = { + "message": "Test error message", + "detail": "Test detail", + "type": "TestException" + }; + + var result = variables.wireComponent._enhanceExceptionForSingleFile( mockException ); + + expect( result ).toHaveKey( "isSingleFileComponent" ); + expect( result.isSingleFileComponent ).toBeTrue(); + expect( result ).toHaveKey( "singleFileSourcePath" ); + expect( result.singleFileSourcePath ).toBe( "/path/to/TestComponent.cfm" ); + expect( result ).toHaveKey( "singleFileLineOffset" ); + expect( result.singleFileLineOffset ).toBe( 10 ); + expect( result ).toHaveKey( "enhancedMessage" ); + }); + + it( "_enhanceExceptionForSingleFile returns basic struct for regular components", function() { + var mockException = { + "message": "Test error message", + "detail": "Test detail", + "type": "TestException" + }; + + var result = variables.wireComponent._enhanceExceptionForSingleFile( mockException ); + + expect( result ).toHaveKey( "isSingleFileComponent" ); + expect( result.isSingleFileComponent ).toBeFalse(); + expect( result ).notToHaveKey( "singleFileSourcePath" ); + expect( result ).notToHaveKey( "enhancedMessage" ); + }); + + }); + }); } diff --git a/test-harness/tests/specs/unit/SingleFileComponentBuilderSpec.cfc b/test-harness/tests/specs/unit/SingleFileComponentBuilderSpec.cfc new file mode 100644 index 0000000..c70d45f --- /dev/null +++ b/test-harness/tests/specs/unit/SingleFileComponentBuilderSpec.cfc @@ -0,0 +1,100 @@ +component extends="coldbox.system.testing.BaseTestCase" { + + function beforeAll() { + // Create the service instance + variables.builder = new cbwire.models.SingleFileComponentBuilder(); + } + + function run() { + describe( "SingleFileComponentBuilder", function() { + + describe( "parseContents()", function() { + + it( "should track the line number where @startWire begins", function() { + // Create a temp file with known content + var testContent = "" & chr( 10 ) & + "// some comment" & chr( 10 ) & + "// @startWire" & chr( 10 ) & + " data = { 'name': 'test' };" & chr( 10 ) & + "// @endWire" & chr( 10 ) & + "" & chr( 10 ) & + "
test
"; + + var tempFile = getTempDirectory() & "testWire_" & createUUID() & ".cfm"; + fileWrite( tempFile, testContent ); + + try { + var result = variables.builder.parseContents( tempFile ); + + // @startWire is on line 3 + expect( result.startWireLineNumber ).toBe( 3 ); + expect( result ).toHaveKey( "singleFileContents" ); + expect( result ).toHaveKey( "remainingContents" ); + expect( result ).toHaveKey( "extendsPath" ); + } finally { + // Clean up temp file + if ( fileExists( tempFile ) ) { + fileDelete( tempFile ); + } + } + }); + + it( "should return 0 for startWireLineNumber when @startWire is not found", function() { + // Create a temp file without @startWire + var testContent = "" & chr( 10 ) & + "// some comment" & chr( 10 ) & + "" & chr( 10 ) & + "
test
"; + + var tempFile = getTempDirectory() & "testWireNoAnnotation_" & createUUID() & ".cfm"; + fileWrite( tempFile, testContent ); + + try { + var result = variables.builder.parseContents( tempFile ); + + expect( result.startWireLineNumber ).toBe( 0 ); + } finally { + // Clean up temp file + if ( fileExists( tempFile ) ) { + fileDelete( tempFile ); + } + } + }); + + it( "should correctly parse the wire contents between @startWire and @endWire", function() { + // Create a temp file with known content + var testContent = "" & chr( 10 ) & + "// @startWire" & chr( 10 ) & + " data = { 'counter': 0 };" & chr( 10 ) & + " function increment() { data.counter++; }" & chr( 10 ) & + "// @endWire" & chr( 10 ) & + "" & chr( 10 ) & + "
test
"; + + var tempFile = getTempDirectory() & "testWireContents_" & createUUID() & ".cfm"; + fileWrite( tempFile, testContent ); + + try { + var result = variables.builder.parseContents( tempFile ); + + // Wire contents should include the data and function definitions + expect( result.singleFileContents ).toInclude( "data = { 'counter': 0 }" ); + expect( result.singleFileContents ).toInclude( "function increment()" ); + + // Remaining contents should include the template part + expect( result.remainingContents ).toInclude( "" ); + expect( result.remainingContents ).toInclude( "
test
" ); + } finally { + // Clean up temp file + if ( fileExists( tempFile ) ) { + fileDelete( tempFile ); + } + } + }); + + }); + + }); + } + +} From f17a160c418a96f55491813cd78a7b61941e9e40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 06:33:45 +0000 Subject: [PATCH 4/4] Address code review feedback: fix docblocks, improve line number estimation Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com> --- models/Component.cfc | 24 +++-- .../unit/SingleFileComponentBuilderSpec.cfc | 101 +++++++++--------- 2 files changed, 64 insertions(+), 61 deletions(-) diff --git a/models/Component.cfc b/models/Component.cfc index b2a859c..2aeae85 100644 --- a/models/Component.cfc +++ b/models/Component.cfc @@ -1792,9 +1792,9 @@ component output="true" accessors="true" { * Enhances an exception with single-file component source information. * This helps developers understand where errors originated in their original source file. * - * @exception struct | The caught exception to enhance + * @exception any The caught exception to enhance * - * @return struct | Enhanced exception information with source file context + * @return struct Enhanced exception information with source file context */ function _enhanceExceptionForSingleFile( required any exception ) { var enhanced = { @@ -1817,9 +1817,9 @@ component output="true" accessors="true" { /** * Builds an enhanced error message that includes single-file component source information. * - * @exception struct | The caught exception + * @exception any The caught exception * - * @return string | The enhanced error message + * @return string The enhanced error message */ function _buildEnhancedErrorMessage( required any exception ) { var sourcePath = _getSingleFileSourcePath(); @@ -1842,11 +1842,17 @@ component output="true" accessors="true" { if ( structKeyExists( ctx, "template" ) && ctx.template contains "cbwire" && ctx.template contains "tmp" ) { var generatedLine = structKeyExists( ctx, "line" ) ? ctx.line : 0; if ( generatedLine > 0 && lineOffset > 0 ) { - // The generated component has some header lines, so we need to account for that - // The header in EmptySingleFileComponent.cfc has approximately 14 lines before CFC_CONTENTS - var headerLines = 14; - var estimatedSourceLine = generatedLine - headerLines + lineOffset; - if ( estimatedSourceLine > 0 ) { + /* + * The generated component file (EmptySingleFileComponent.cfc/.bx) has header lines + * before the {{ CFC_CONTENTS }} placeholder where user code is inserted. + * This includes: component declaration, variable definitions for source path and + * line offset, comments, and blank lines. Currently this is approximately 14 lines. + * See models/EmptySingleFileComponent.cfc for the template structure. + */ + var generatedTemplateHeaderLines = 14; + var estimatedSourceLine = generatedLine - generatedTemplateHeaderLines + lineOffset; + // Only show the estimated line if it's a positive, reasonable value + if ( estimatedSourceLine > 0 && estimatedSourceLine <= 10000 ) { enhancedMessage &= "Estimated source line: ~" & estimatedSourceLine & chr(10); } } diff --git a/test-harness/tests/specs/unit/SingleFileComponentBuilderSpec.cfc b/test-harness/tests/specs/unit/SingleFileComponentBuilderSpec.cfc index c70d45f..3bf65fd 100644 --- a/test-harness/tests/specs/unit/SingleFileComponentBuilderSpec.cfc +++ b/test-harness/tests/specs/unit/SingleFileComponentBuilderSpec.cfc @@ -3,6 +3,33 @@ component extends="coldbox.system.testing.BaseTestCase" { function beforeAll() { // Create the service instance variables.builder = new cbwire.models.SingleFileComponentBuilder(); + // Track temp files for cleanup + variables.tempFiles = []; + } + + function afterAll() { + // Clean up any remaining temp files + for ( var tempFile in variables.tempFiles ) { + if ( fileExists( tempFile ) ) { + fileDelete( tempFile ); + } + } + } + + /** + * Helper method to create a temp file with the given content. + * The file is automatically tracked for cleanup. + * + * @content string The content to write to the file + * @extension string The file extension (default: .cfm) + * + * @return string The path to the created temp file + */ + private function createTempFile( required string content, string extension = ".cfm" ) { + var tempFile = getTempDirectory() & "testWire_" & createUUID() & arguments.extension; + fileWrite( tempFile, arguments.content ); + variables.tempFiles.append( tempFile ); + return tempFile; } function run() { @@ -11,7 +38,6 @@ component extends="coldbox.system.testing.BaseTestCase" { describe( "parseContents()", function() { it( "should track the line number where @startWire begins", function() { - // Create a temp file with known content var testContent = "" & chr( 10 ) & "// some comment" & chr( 10 ) & "// @startWire" & chr( 10 ) & @@ -20,49 +46,29 @@ component extends="coldbox.system.testing.BaseTestCase" { "" & chr( 10 ) & "
test
"; - var tempFile = getTempDirectory() & "testWire_" & createUUID() & ".cfm"; - fileWrite( tempFile, testContent ); - - try { - var result = variables.builder.parseContents( tempFile ); - - // @startWire is on line 3 - expect( result.startWireLineNumber ).toBe( 3 ); - expect( result ).toHaveKey( "singleFileContents" ); - expect( result ).toHaveKey( "remainingContents" ); - expect( result ).toHaveKey( "extendsPath" ); - } finally { - // Clean up temp file - if ( fileExists( tempFile ) ) { - fileDelete( tempFile ); - } - } + var tempFile = createTempFile( testContent ); + var result = variables.builder.parseContents( tempFile ); + + // @startWire is on line 3 + expect( result.startWireLineNumber ).toBe( 3 ); + expect( result ).toHaveKey( "singleFileContents" ); + expect( result ).toHaveKey( "remainingContents" ); + expect( result ).toHaveKey( "extendsPath" ); }); it( "should return 0 for startWireLineNumber when @startWire is not found", function() { - // Create a temp file without @startWire var testContent = "" & chr( 10 ) & "// some comment" & chr( 10 ) & "" & chr( 10 ) & "
test
"; - var tempFile = getTempDirectory() & "testWireNoAnnotation_" & createUUID() & ".cfm"; - fileWrite( tempFile, testContent ); - - try { - var result = variables.builder.parseContents( tempFile ); - - expect( result.startWireLineNumber ).toBe( 0 ); - } finally { - // Clean up temp file - if ( fileExists( tempFile ) ) { - fileDelete( tempFile ); - } - } + var tempFile = createTempFile( testContent ); + var result = variables.builder.parseContents( tempFile ); + + expect( result.startWireLineNumber ).toBe( 0 ); }); it( "should correctly parse the wire contents between @startWire and @endWire", function() { - // Create a temp file with known content var testContent = "" & chr( 10 ) & "// @startWire" & chr( 10 ) & " data = { 'counter': 0 };" & chr( 10 ) & @@ -71,25 +77,16 @@ component extends="coldbox.system.testing.BaseTestCase" { "" & chr( 10 ) & "
test
"; - var tempFile = getTempDirectory() & "testWireContents_" & createUUID() & ".cfm"; - fileWrite( tempFile, testContent ); - - try { - var result = variables.builder.parseContents( tempFile ); - - // Wire contents should include the data and function definitions - expect( result.singleFileContents ).toInclude( "data = { 'counter': 0 }" ); - expect( result.singleFileContents ).toInclude( "function increment()" ); - - // Remaining contents should include the template part - expect( result.remainingContents ).toInclude( "" ); - expect( result.remainingContents ).toInclude( "
test
" ); - } finally { - // Clean up temp file - if ( fileExists( tempFile ) ) { - fileDelete( tempFile ); - } - } + var tempFile = createTempFile( testContent ); + var result = variables.builder.parseContents( tempFile ); + + // Wire contents should include the data and function definitions + expect( result.singleFileContents ).toInclude( "data = { 'counter': 0 }" ); + expect( result.singleFileContents ).toInclude( "function increment()" ); + + // Remaining contents should include the template part + expect( result.remainingContents ).toInclude( "" ); + expect( result.remainingContents ).toInclude( "
test
" ); }); });