From 2cb3a9479323c18e1fd6293c1bf909a3798c4462 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 9 Oct 2025 21:47:31 +0000
Subject: [PATCH 1/6] Initial plan
From 474b0c5ce0c5881c260e0f8e5deeb53a8b8b0880 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 9 Oct 2025 21:53:45 +0000
Subject: [PATCH 2/6] Add _uploadErrored method and onUploadError lifecycle
hook with tests
Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com>
---
models/Component.cfc | 16 ++++++++++++
test-harness/tests/specs/CBWIRESpec.cfc | 25 +++++++++++++++++++
test-harness/wires/OnUploadError.cfc | 13 ++++++++++
test-harness/wires/OnUploadError.cfm | 6 +++++
.../wires/test/should_call_onuploaderror.cfm | 20 +++++++++++++++
5 files changed, 80 insertions(+)
create mode 100644 test-harness/wires/OnUploadError.cfc
create mode 100644 test-harness/wires/OnUploadError.cfm
create mode 100644 test-harness/wires/test/should_call_onuploaderror.cfm
diff --git a/models/Component.cfc b/models/Component.cfc
index 127a63f..93c7936 100644
--- a/models/Component.cfc
+++ b/models/Component.cfc
@@ -924,6 +924,22 @@ component output="true" accessors="true" {
);
}
+ /**
+ * Method that is invoked when a file upload errors.
+ *
+ * @prop string | The property for the file input.
+ * @errors any | The errors that occurred during upload.
+ * @self boolean | Whether to dispatch to self.
+ *
+ * @return void
+ */
+ function _uploadErrored( prop, errors, self ) {
+ // Check if the component has an onUploadError method and invoke it
+ if ( structKeyExists( this, "onUploadError" ) ) {
+ invoke( this, "onUploadError", { name: arguments.prop } );
+ }
+ }
+
/**
* Fires when missing methods are called.
* Handles computed properties.
diff --git a/test-harness/tests/specs/CBWIRESpec.cfc b/test-harness/tests/specs/CBWIRESpec.cfc
index 37a4ae4..5d441ba 100644
--- a/test-harness/tests/specs/CBWIRESpec.cfc
+++ b/test-harness/tests/specs/CBWIRESpec.cfc
@@ -1060,6 +1060,31 @@ component extends="coldbox.system.testing.BaseTestCase" {
expect( response.components[1].effects.html ).toInclude( "Hydrated Property: true" );
} );
+ it( "should call onUploadError() if it exists when _uploadErrored is called", function() {
+ var payload = incomingRequest(
+ memo = {
+ "name": "test.should_call_onuploaderror",
+ "id": "Z1Ruz1tGMPXSfw7osBW2",
+ "children": []
+ },
+ data = {
+ "uploadErrored": false,
+ "erroredPropertyName": ""
+ },
+ calls = [
+ {
+ "path": "",
+ "method": "_uploadErrored",
+ "params": [ "photo", null, false ]
+ }
+ ],
+ updates = {}
+ );
+ var response = cbwireController.handleRequest( payload, event );
+ expect( response.components[1].effects.html ).toInclude( "Upload Errored: true" );
+ expect( response.components[1].effects.html ).toInclude( "Errored Property Name: photo" );
+ } );
+
it( "should be able to return javascript to return", () => {
var payload = incomingRequest(
memo = {
diff --git a/test-harness/wires/OnUploadError.cfc b/test-harness/wires/OnUploadError.cfc
new file mode 100644
index 0000000..63bdaf2
--- /dev/null
+++ b/test-harness/wires/OnUploadError.cfc
@@ -0,0 +1,13 @@
+component extends="cbwire.models.Component" {
+
+ data = {
+ "uploadErrored": false,
+ "erroredPropertyName": ""
+ };
+
+ function onUploadError( name ) {
+ data.uploadErrored = true;
+ data.erroredPropertyName = arguments.name;
+ }
+
+}
diff --git a/test-harness/wires/OnUploadError.cfm b/test-harness/wires/OnUploadError.cfm
new file mode 100644
index 0000000..a436b3a
--- /dev/null
+++ b/test-harness/wires/OnUploadError.cfm
@@ -0,0 +1,6 @@
+
+
+
Upload Errored: #uploadErrored#
+
Errored Property Name: #erroredPropertyName#
+
+
diff --git a/test-harness/wires/test/should_call_onuploaderror.cfm b/test-harness/wires/test/should_call_onuploaderror.cfm
new file mode 100644
index 0000000..8488617
--- /dev/null
+++ b/test-harness/wires/test/should_call_onuploaderror.cfm
@@ -0,0 +1,20 @@
+
+ // @startWire
+ data = {
+ "uploadErrored": false,
+ "erroredPropertyName": ""
+ };
+
+ function onUploadError( name ) {
+ data.uploadErrored = true;
+ data.erroredPropertyName = arguments.name;
+ }
+ // @endWire
+
+
+
+
+
Upload Errored: #uploadErrored#
+
Errored Property Name: #erroredPropertyName#
+
+
From 2c583402caa876c71fa3e8d57cae5425b2d83e08 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 9 Oct 2025 21:57:23 +0000
Subject: [PATCH 3/6] Pass all parameters (errors, multiple) to onUploadError
lifecycle method
Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com>
---
models/Component.cfc | 6 +++++-
test-harness/tests/specs/CBWIRESpec.cfc | 6 +++++-
test-harness/wires/OnUploadError.cfc | 8 ++++++--
test-harness/wires/OnUploadError.cfm | 2 ++
test-harness/wires/test/should_call_onuploaderror.cfm | 10 ++++++++--
5 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/models/Component.cfc b/models/Component.cfc
index 93c7936..1cb105d 100644
--- a/models/Component.cfc
+++ b/models/Component.cfc
@@ -936,7 +936,11 @@ component output="true" accessors="true" {
function _uploadErrored( prop, errors, self ) {
// Check if the component has an onUploadError method and invoke it
if ( structKeyExists( this, "onUploadError" ) ) {
- invoke( this, "onUploadError", { name: arguments.prop } );
+ invoke( this, "onUploadError", {
+ name: arguments.prop,
+ errors: arguments.errors,
+ multiple: arguments.self
+ } );
}
}
diff --git a/test-harness/tests/specs/CBWIRESpec.cfc b/test-harness/tests/specs/CBWIRESpec.cfc
index 5d441ba..158e5fb 100644
--- a/test-harness/tests/specs/CBWIRESpec.cfc
+++ b/test-harness/tests/specs/CBWIRESpec.cfc
@@ -1069,7 +1069,9 @@ component extends="coldbox.system.testing.BaseTestCase" {
},
data = {
"uploadErrored": false,
- "erroredPropertyName": ""
+ "erroredPropertyName": "",
+ "errorInfo": "",
+ "isMultiple": false
},
calls = [
{
@@ -1083,6 +1085,8 @@ component extends="coldbox.system.testing.BaseTestCase" {
var response = cbwireController.handleRequest( payload, event );
expect( response.components[1].effects.html ).toInclude( "Upload Errored: true" );
expect( response.components[1].effects.html ).toInclude( "Errored Property Name: photo" );
+ expect( response.components[1].effects.html ).toInclude( "Error Info: null" );
+ expect( response.components[1].effects.html ).toInclude( "Is Multiple: false" );
} );
it( "should be able to return javascript to return", () => {
diff --git a/test-harness/wires/OnUploadError.cfc b/test-harness/wires/OnUploadError.cfc
index 63bdaf2..2e4139a 100644
--- a/test-harness/wires/OnUploadError.cfc
+++ b/test-harness/wires/OnUploadError.cfc
@@ -2,12 +2,16 @@ component extends="cbwire.models.Component" {
data = {
"uploadErrored": false,
- "erroredPropertyName": ""
+ "erroredPropertyName": "",
+ "errorInfo": "",
+ "isMultiple": false
};
- function onUploadError( name ) {
+ function onUploadError( name, errors, multiple ) {
data.uploadErrored = true;
data.erroredPropertyName = arguments.name;
+ data.errorInfo = isNull( arguments.errors ) ? "null" : "has errors";
+ data.isMultiple = arguments.multiple;
}
}
diff --git a/test-harness/wires/OnUploadError.cfm b/test-harness/wires/OnUploadError.cfm
index a436b3a..b78dbf4 100644
--- a/test-harness/wires/OnUploadError.cfm
+++ b/test-harness/wires/OnUploadError.cfm
@@ -2,5 +2,7 @@
Upload Errored: #uploadErrored#
Errored Property Name: #erroredPropertyName#
+
Error Info: #errorInfo#
+
Is Multiple: #isMultiple#
diff --git a/test-harness/wires/test/should_call_onuploaderror.cfm b/test-harness/wires/test/should_call_onuploaderror.cfm
index 8488617..aacaae4 100644
--- a/test-harness/wires/test/should_call_onuploaderror.cfm
+++ b/test-harness/wires/test/should_call_onuploaderror.cfm
@@ -2,12 +2,16 @@
// @startWire
data = {
"uploadErrored": false,
- "erroredPropertyName": ""
+ "erroredPropertyName": "",
+ "errorInfo": "",
+ "isMultiple": false
};
- function onUploadError( name ) {
+ function onUploadError( name, errors, multiple ) {
data.uploadErrored = true;
data.erroredPropertyName = arguments.name;
+ data.errorInfo = isNull( arguments.errors ) ? "null" : "has errors";
+ data.isMultiple = arguments.multiple;
}
// @endWire
@@ -16,5 +20,7 @@
Upload Errored: #uploadErrored#
Errored Property Name: #erroredPropertyName#
+
Error Info: #errorInfo#
+
Is Multiple: #isMultiple#
From 82cc3c4706f13e035e4c0e1631d1260fc9abb703 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 9 Oct 2025 21:59:03 +0000
Subject: [PATCH 4/6] Fix parameter name: rename 'self' to 'multiple' for
clarity
Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com>
---
models/Component.cfc | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/models/Component.cfc b/models/Component.cfc
index 1cb105d..0c9d9b8 100644
--- a/models/Component.cfc
+++ b/models/Component.cfc
@@ -929,17 +929,17 @@ component output="true" accessors="true" {
*
* @prop string | The property for the file input.
* @errors any | The errors that occurred during upload.
- * @self boolean | Whether to dispatch to self.
+ * @multiple boolean | Whether multiple files are being uploaded.
*
* @return void
*/
- function _uploadErrored( prop, errors, self ) {
+ function _uploadErrored( prop, errors, multiple ) {
// Check if the component has an onUploadError method and invoke it
if ( structKeyExists( this, "onUploadError" ) ) {
invoke( this, "onUploadError", {
name: arguments.prop,
errors: arguments.errors,
- multiple: arguments.self
+ multiple: arguments.multiple
} );
}
}
From 80c0aab7978efb4cca082efb1eb394d0071e0efc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 10 Oct 2025 14:54:14 +0000
Subject: [PATCH 5/6] Rename 'name' parameter to 'property' in onUploadError
lifecycle method
Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com>
---
models/Component.cfc | 2 +-
test-harness/wires/OnUploadError.cfc | 4 ++--
test-harness/wires/test/should_call_onuploaderror.cfm | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/models/Component.cfc b/models/Component.cfc
index 0c9d9b8..2b20797 100644
--- a/models/Component.cfc
+++ b/models/Component.cfc
@@ -937,7 +937,7 @@ component output="true" accessors="true" {
// Check if the component has an onUploadError method and invoke it
if ( structKeyExists( this, "onUploadError" ) ) {
invoke( this, "onUploadError", {
- name: arguments.prop,
+ property: arguments.prop,
errors: arguments.errors,
multiple: arguments.multiple
} );
diff --git a/test-harness/wires/OnUploadError.cfc b/test-harness/wires/OnUploadError.cfc
index 2e4139a..e5df5b5 100644
--- a/test-harness/wires/OnUploadError.cfc
+++ b/test-harness/wires/OnUploadError.cfc
@@ -7,9 +7,9 @@ component extends="cbwire.models.Component" {
"isMultiple": false
};
- function onUploadError( name, errors, multiple ) {
+ function onUploadError( property, errors, multiple ) {
data.uploadErrored = true;
- data.erroredPropertyName = arguments.name;
+ data.erroredPropertyName = arguments.property;
data.errorInfo = isNull( arguments.errors ) ? "null" : "has errors";
data.isMultiple = arguments.multiple;
}
diff --git a/test-harness/wires/test/should_call_onuploaderror.cfm b/test-harness/wires/test/should_call_onuploaderror.cfm
index aacaae4..247f311 100644
--- a/test-harness/wires/test/should_call_onuploaderror.cfm
+++ b/test-harness/wires/test/should_call_onuploaderror.cfm
@@ -7,9 +7,9 @@
"isMultiple": false
};
- function onUploadError( name, errors, multiple ) {
+ function onUploadError( property, errors, multiple ) {
data.uploadErrored = true;
- data.erroredPropertyName = arguments.name;
+ data.erroredPropertyName = arguments.property;
data.errorInfo = isNull( arguments.errors ) ? "null" : "has errors";
data.isMultiple = arguments.multiple;
}
From d2ace047d2e23ad33fa4121bcdbd4ee7042ae96b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 10 Oct 2025 15:01:03 +0000
Subject: [PATCH 6/6] Dispatch upload:errored event to trigger JavaScript error
handler
Co-authored-by: grantcopley <1197835+grantcopley@users.noreply.github.com>
---
models/Component.cfc | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/models/Component.cfc b/models/Component.cfc
index 2b20797..84e0267 100644
--- a/models/Component.cfc
+++ b/models/Component.cfc
@@ -934,6 +934,13 @@ component output="true" accessors="true" {
* @return void
*/
function _uploadErrored( prop, errors, multiple ) {
+ // Dispatch the upload errored event
+ dispatchSelf(
+ event="upload:errored",
+ params=[
+ "name"=arguments.prop
+ ]
+ );
// Check if the component has an onUploadError method and invoke it
if ( structKeyExists( this, "onUploadError" ) ) {
invoke( this, "onUploadError", {