diff --git a/src/components/renderer/file-upload.vue b/src/components/renderer/file-upload.vue
index 78211762a..0863436b1 100644
--- a/src/components/renderer/file-upload.vue
+++ b/src/components/renderer/file-upload.vue
@@ -94,8 +94,6 @@ export default {
(loop, removed) => this.listenRemovedLoop(loop, removed));
this.removeDefaultClasses();
-
- this.checkIfInRecordList();
this.setPrefix();
if (this.$refs['uploader']) {
@@ -288,15 +286,6 @@ export default {
this.prefix = parent.loopContext + '.';
}
},
- setFileUploadNameForChildren(children, prefix) {
- children.forEach(child => {
- if (_.get(child, '$options.name') === 'FileUpload') {
- child.prefix = prefix;
- } else if (_.get(child, '$children', []).length > 0) {
- this.setFileUploadNameForChildren(child.$children, prefix);
- }
- });
- },
addFile(file) {
if (this.disabled) {
file.ignored = true;
@@ -420,14 +409,6 @@ export default {
: null;
}
},
- checkIfInRecordList() {
- const parent = this.parentRecordList(this);
- if (parent !== null) {
- const recordList = parent;
- const prefix = recordList.name + '.';
- this.setFileUploadNameForChildren(recordList.$children, prefix);
- }
- },
},
};
diff --git a/src/components/renderer/form-record-list.vue b/src/components/renderer/form-record-list.vue
index c9179eace..c78679fda 100644
--- a/src/components/renderer/form-record-list.vue
+++ b/src/components/renderer/form-record-list.vue
@@ -86,6 +86,7 @@
debug-context="Record List Add"
:key="Array.isArray(value) ? value.length : 0"
:_parent="validationData"
+ @update="updateRowDataNamePrefix"
/>
diff --git a/tests/e2e/fixtures/record_list_fileupload_loops.json b/tests/e2e/fixtures/record_list_fileupload_loops.json
new file mode 100644
index 000000000..b8efef92a
--- /dev/null
+++ b/tests/e2e/fixtures/record_list_fileupload_loops.json
@@ -0,0 +1,1003 @@
+{
+ "type": "screen_package",
+ "version": "2",
+ "screens": [
+ {
+ "id": 2,
+ "screen_category_id": "1",
+ "title": "26955-1",
+ "description": "test",
+ "type": "FORM",
+ "config": [
+ {
+ "name": "record_list_page",
+ "items": [
+ {
+ "label": "Record List",
+ "config": {
+ "form": "1",
+ "icon": "fas fa-th-list",
+ "name": "form_record_list_1",
+ "label": "New Record List",
+ "fields": {
+ "jsonData": "[]",
+ "editIndex": null,
+ "dataSource": "provideData",
+ "optionsList": [],
+ "removeIndex": null,
+ "showJsonEditor": false,
+ "showOptionCard": false,
+ "showRemoveWarning": false
+ },
+ "editable": true
+ },
+ "component": "FormRecordList",
+ "inspector": [
+ {
+ "type": "FormInput",
+ "field": "name",
+ "config": {
+ "name": "Variable Name",
+ "label": "Variable Name",
+ "helper": "A variable name is a symbolic name to reference information.",
+ "validation": "regex:\/^([a-zA-Z]([a-zA-Z0-9_]?)+\\.?)+(? Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####",
+ "validation": null
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customCssSelector",
+ "config": {
+ "label": "CSS Selector Name",
+ "helper": "Use this in your custom css rules",
+ "validation": "regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]"
+ }
+ }
+ ],
+ "editor-control": "FormText",
+ "editor-component": "FormText"
+ },
+ {
+ "label": "Submit Button",
+ "config": {
+ "icon": "fas fa-share-square",
+ "name": null,
+ "event": "submit",
+ "label": "New Submit",
+ "variant": "primary",
+ "fieldValue": null,
+ "defaultSubmit": true
+ },
+ "component": "FormButton",
+ "inspector": [
+ {
+ "type": "FormInput",
+ "field": "label",
+ "config": {
+ "label": "Label",
+ "helper": "The label describes the button's text"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "name",
+ "config": {
+ "name": "Variable Name",
+ "label": "Variable Name",
+ "helper": "A variable name is a symbolic name to reference information."
+ }
+ },
+ {
+ "type": "FormMultiselect",
+ "field": "event",
+ "config": {
+ "label": "Type",
+ "helper": "Choose whether the button should submit the form",
+ "options": [
+ {
+ "value": "submit",
+ "content": "Submit Button"
+ },
+ {
+ "value": "script",
+ "content": "Regular Button"
+ }
+ ]
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "fieldValue",
+ "config": {
+ "label": "Value",
+ "helper": "The value being submitted"
+ }
+ },
+ {
+ "type": "FormMultiselect",
+ "field": "variant",
+ "config": {
+ "label": "Button Variant Style",
+ "helper": "The variant determines the appearance of the button",
+ "options": [
+ {
+ "value": "primary",
+ "content": "Primary"
+ },
+ {
+ "value": "secondary",
+ "content": "Secondary"
+ },
+ {
+ "value": "success",
+ "content": "Success"
+ },
+ {
+ "value": "danger",
+ "content": "Danger"
+ },
+ {
+ "value": "warning",
+ "content": "Warning"
+ },
+ {
+ "value": "info",
+ "content": "Info"
+ },
+ {
+ "value": "light",
+ "content": "Light"
+ },
+ {
+ "value": "dark",
+ "content": "Dark"
+ },
+ {
+ "value": "link",
+ "content": "Link"
+ }
+ ]
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "conditionalHide",
+ "config": {
+ "label": "Visibility Rule",
+ "helper": "This control is hidden until this expression is true"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customFormatter",
+ "config": {
+ "label": "Custom Format String",
+ "helper": "Use the Mask Pattern format
Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####",
+ "validation": null
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customCssSelector",
+ "config": {
+ "label": "CSS Selector Name",
+ "helper": "Use this in your custom css rules",
+ "validation": "regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]"
+ }
+ }
+ ],
+ "editor-control": "FormSubmit",
+ "editor-component": "FormButton"
+ }
+ ]
+ },
+ {
+ "name": "input_page",
+ "items": [
+ {
+ "items": [
+ {
+ "label": "Line Input",
+ "config": {
+ "icon": "far fa-square",
+ "name": "form_input_4",
+ "type": "text",
+ "label": "New Input",
+ "helper": null,
+ "readonly": false,
+ "dataFormat": "string",
+ "validation": [],
+ "placeholder": null
+ },
+ "component": "FormInput",
+ "inspector": [
+ {
+ "type": "FormInput",
+ "field": "name",
+ "config": {
+ "name": "Variable Name",
+ "label": "Variable Name",
+ "helper": "A variable name is a symbolic name to reference information.",
+ "validation": "regex:\/^(?:[A-Za-z])(?:[0-9A-Z_a-z])*(?:\\.[0-9A-Z_a-z]+)*$\/|required|not_in:null,break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,class,const,enum,export,extends,import,super"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "label",
+ "config": {
+ "label": "Label",
+ "helper": "The label describes the field's name"
+ }
+ },
+ {
+ "type": "FormMultiselect",
+ "field": "dataFormat",
+ "config": {
+ "name": "Data Type",
+ "label": "Data Type",
+ "helper": "The data type specifies what kind of data is stored in the variable.",
+ "options": [
+ {
+ "value": "string",
+ "content": "Text"
+ },
+ {
+ "value": "int",
+ "content": "Integer"
+ },
+ {
+ "value": "currency",
+ "content": "Currency"
+ },
+ {
+ "value": "percentage",
+ "content": "Percentage"
+ },
+ {
+ "value": "float",
+ "content": "Decimal"
+ },
+ {
+ "value": "datetime",
+ "content": "Datetime"
+ },
+ {
+ "value": "date",
+ "content": "Date"
+ },
+ {
+ "value": "password",
+ "content": "Password"
+ }
+ ],
+ "validation": "required"
+ }
+ },
+ {
+ "type": {
+ "_Ctor": [],
+ "extends": {
+ "_Ctor": [],
+ "props": {
+ "name": {
+ "type": null
+ },
+ "error": {
+ "type": null
+ },
+ "label": {
+ "type": null
+ },
+ "value": {
+ "type": null
+ },
+ "helper": {
+ "type": null
+ },
+ "options": {
+ "type": null
+ },
+ "selectedControl": {
+ "type": null
+ }
+ },
+ "mixins": [
+ {
+ "props": {
+ "validation": {
+ "type": null
+ },
+ "validationData": {
+ "type": null
+ },
+ "validationField": {
+ "type": null
+ },
+ "validationMessages": {
+ "type": null
+ }
+ },
+ "watch": {
+ "validationData": {
+ "deep": true,
+ "user": true
+ }
+ },
+ "methods": [],
+ "computed": []
+ }
+ ],
+ "methods": [],
+ "computed": [],
+ "_compiled": true,
+ "components": {
+ "Multiselect": {
+ "name": "vue-multiselect",
+ "_Ctor": [],
+ "props": {
+ "name": {
+ "default": null
+ },
+ "limit": {
+ "default": 99999
+ },
+ "loading": {
+ "default": false
+ },
+ "disabled": {
+ "default": false
+ },
+ "tabindex": {
+ "default": 0
+ },
+ "limitText": [],
+ "maxHeight": {
+ "default": 300
+ },
+ "showLabels": {
+ "default": true
+ },
+ "selectLabel": {
+ "default": "Press enter to select"
+ },
+ "deselectLabel": {
+ "default": "Press enter to remove"
+ },
+ "openDirection": {
+ "default": null
+ },
+ "selectedLabel": {
+ "default": "Selected"
+ },
+ "showNoOptions": {
+ "default": true
+ },
+ "showNoResults": {
+ "default": true
+ },
+ "selectGroupLabel": {
+ "default": "Press enter to select group"
+ },
+ "deselectGroupLabel": {
+ "default": "Press enter to deselect group"
+ }
+ },
+ "mixins": [
+ {
+ "props": {
+ "id": {
+ "default": null
+ },
+ "max": {
+ "type": [
+ null,
+ null
+ ],
+ "default": false
+ },
+ "label": [],
+ "value": {
+ "type": null
+ },
+ "options": {
+ "required": true
+ },
+ "trackBy": [],
+ "multiple": {
+ "default": false
+ },
+ "taggable": {
+ "default": false
+ },
+ "blockKeys": [],
+ "allowEmpty": {
+ "default": true
+ },
+ "groupLabel": [],
+ "resetAfter": {
+ "default": false
+ },
+ "searchable": {
+ "default": true
+ },
+ "customLabel": [],
+ "groupSelect": {
+ "default": false
+ },
+ "groupValues": [],
+ "placeholder": {
+ "default": "Select option"
+ },
+ "tagPosition": {
+ "default": "top"
+ },
+ "hideSelected": {
+ "default": false
+ },
+ "optionsLimit": {
+ "default": 1000
+ },
+ "clearOnSelect": {
+ "default": true
+ },
+ "closeOnSelect": {
+ "default": true
+ },
+ "internalSearch": {
+ "default": true
+ },
+ "preselectFirst": {
+ "default": false
+ },
+ "preserveSearch": {
+ "default": false
+ },
+ "tagPlaceholder": {
+ "default": "Press enter to create a tag"
+ }
+ },
+ "watch": [],
+ "methods": [],
+ "computed": []
+ },
+ {
+ "props": {
+ "showPointer": {
+ "default": true
+ },
+ "optionHeight": {
+ "default": 40
+ }
+ },
+ "watch": [],
+ "methods": [],
+ "computed": []
+ }
+ ],
+ "computed": [],
+ "_compiled": true,
+ "beforeCreate": [
+ null
+ ],
+ "staticRenderFns": []
+ }
+ },
+ "inheritAttrs": false,
+ "staticRenderFns": []
+ },
+ "computed": [],
+ "_compiled": true,
+ "staticRenderFns": []
+ },
+ "field": "dataMask",
+ "config": {
+ "name": "Data Format",
+ "label": "Data Format",
+ "helper": "The data format for the selected type."
+ }
+ },
+ {
+ "type": "ValidationSelect",
+ "field": "validation",
+ "config": {
+ "label": "Validation Rules",
+ "helper": "The validation rules needed for this field"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "placeholder",
+ "config": {
+ "label": "Placeholder Text",
+ "helper": "The placeholder is what is shown in the field when no value is provided yet"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "helper",
+ "config": {
+ "label": "Helper Text",
+ "helper": "Help text is meant to provide additional guidance on the field's value"
+ }
+ },
+ {
+ "type": "FormCheckbox",
+ "field": "readonly",
+ "config": {
+ "label": "Read Only",
+ "helper": null
+ }
+ },
+ {
+ "type": "ColorSelect",
+ "field": "color",
+ "config": {
+ "label": "Text Color",
+ "helper": "Set the element's text color",
+ "options": [
+ {
+ "value": "text-primary",
+ "content": "primary"
+ },
+ {
+ "value": "text-secondary",
+ "content": "secondary"
+ },
+ {
+ "value": "text-success",
+ "content": "success"
+ },
+ {
+ "value": "text-danger",
+ "content": "danger"
+ },
+ {
+ "value": "text-warning",
+ "content": "warning"
+ },
+ {
+ "value": "text-info",
+ "content": "info"
+ },
+ {
+ "value": "text-light",
+ "content": "light"
+ },
+ {
+ "value": "text-dark",
+ "content": "dark"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ColorSelect",
+ "field": "bgcolor",
+ "config": {
+ "label": "Background Color",
+ "helper": "Set the element's background color",
+ "options": [
+ {
+ "value": "alert alert-primary",
+ "content": "primary"
+ },
+ {
+ "value": "alert alert-secondary",
+ "content": "secondary"
+ },
+ {
+ "value": "alert alert-success",
+ "content": "success"
+ },
+ {
+ "value": "alert alert-danger",
+ "content": "danger"
+ },
+ {
+ "value": "alert alert-warning",
+ "content": "warning"
+ },
+ {
+ "value": "alert alert-info",
+ "content": "info"
+ },
+ {
+ "value": "alert alert-light",
+ "content": "light"
+ },
+ {
+ "value": "alert alert-dark",
+ "content": "dark"
+ }
+ ]
+ }
+ },
+ {
+ "type": {
+ "_Ctor": [],
+ "props": {
+ "value": {
+ "type": null
+ },
+ "helper": {
+ "type": null
+ }
+ },
+ "watch": {
+ "value": {
+ "user": true,
+ "immediate": true
+ }
+ },
+ "methods": [],
+ "_scopeId": "data-v-7c18055b",
+ "computed": {
+ "effectiveValue": []
+ },
+ "_compiled": true,
+ "components": {
+ "MonacoEditor": {
+ "name": "monaco-editor",
+ "_Ctor": [],
+ "props": {
+ "amdRequire": []
+ },
+ "extends": {
+ "name": "MonacoEditor",
+ "model": {
+ "event": "change"
+ },
+ "props": {
+ "theme": {
+ "default": "vs"
+ },
+ "value": {
+ "required": true
+ },
+ "options": [],
+ "language": [],
+ "original": [],
+ "amdRequire": [],
+ "diffEditor": {
+ "default": false
+ }
+ },
+ "watch": {
+ "options": {
+ "deep": true,
+ "user": true
+ }
+ },
+ "methods": []
+ },
+ "methods": []
+ }
+ },
+ "staticRenderFns": []
+ },
+ "field": "defaultValue",
+ "config": {
+ "label": "Default Value",
+ "helper": "The default value is pre populated using the existing request data. This feature will allow you to modify the value displayed on screen load if needed."
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "conditionalHide",
+ "config": {
+ "label": "Visibility Rule",
+ "helper": "This control is hidden until this expression is true"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customFormatter",
+ "config": {
+ "label": "Custom Format String",
+ "helper": "Use the Mask Pattern format
Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####",
+ "validation": null
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customCssSelector",
+ "config": {
+ "label": "CSS Selector Name",
+ "helper": "Use this in your custom css rules",
+ "validation": "regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]"
+ }
+ }
+ ],
+ "editor-control": "FormInput",
+ "editor-component": "FormInput"
+ },
+ {
+ "label": "File Upload",
+ "config": {
+ "icon": "fas fa-file-upload",
+ "name": "file_upload_2",
+ "label": "New File Upload"
+ },
+ "component": "FileUpload",
+ "inspector": [
+ {
+ "type": "FormInput",
+ "field": "name",
+ "config": {
+ "name": "Variable Name",
+ "label": "Variable Name",
+ "helper": "A variable name is a symbolic name to reference information.",
+ "validation": "regex:\/^(?:[A-Za-z])(?:[0-9A-Z_a-z])*(?:\\.[0-9A-Z_a-z]+)*$\/|required|not_in:null,break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,class,const,enum,export,extends,import,super"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "label",
+ "config": {
+ "label": "Label",
+ "helper": "The label describes the field's name"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "accept",
+ "config": {
+ "label": "File Accepted",
+ "helper": "application\/msword, image\/gif, image\/jpeg, application\/pdf, application\/vnd.ms-powerpoint, application\/vnd.ms-excel, text\/plain"
+ }
+ },
+ {
+ "type": "RequiredCheckbox",
+ "field": "validation",
+ "config": {
+ "label": "Required",
+ "helper": "Prevent form from being submitted unless a file is uploaded"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "conditionalHide",
+ "config": {
+ "label": "Visibility Rule",
+ "helper": "This control is hidden until this expression is true"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customFormatter",
+ "config": {
+ "label": "Custom Format String",
+ "helper": "Use the Mask Pattern format
Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####",
+ "validation": null
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customCssSelector",
+ "config": {
+ "label": "CSS Selector Name",
+ "helper": "Use this in your custom css rules",
+ "validation": "regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]"
+ }
+ }
+ ],
+ "editor-control": "FileUpload",
+ "editor-component": "FileUpload"
+ }
+ ],
+ "label": "Loop",
+ "config": {
+ "icon": "fas fa-redo",
+ "name": "loop_1",
+ "label": null,
+ "settings": {
+ "add": true,
+ "type": "new",
+ "times": "1",
+ "varname": "loop_1"
+ },
+ "conditionalHide": null
+ },
+ "component": "FormLoop",
+ "container": true,
+ "inspector": [
+ {
+ "type": "LoopInspector",
+ "field": "settings",
+ "config": {
+ "label": null,
+ "helper": null
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "conditionalHide",
+ "config": {
+ "label": "Visibility Rule",
+ "helper": "This control is hidden until this expression is true"
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customFormatter",
+ "config": {
+ "label": "Custom Format String",
+ "helper": "Use the Mask Pattern format
Date ##\/##\/####
SSN ###-##-####
Phone (###) ###-####",
+ "validation": null
+ }
+ },
+ {
+ "type": "FormInput",
+ "field": "customCssSelector",
+ "config": {
+ "label": "CSS Selector Name",
+ "helper": "Use this in your custom css rules",
+ "validation": "regex: [-?[_a-zA-Z]+[_-a-zA-Z0-9]*]"
+ }
+ }
+ ],
+ "editor-control": "Loop",
+ "editor-component": "Loop"
+ }
+ ]
+ }
+ ],
+ "computed": [],
+ "custom_css": null,
+ "created_at": "2021-12-28T13:16:33-06:00",
+ "updated_at": "2022-03-16T12:02:22-06:00",
+ "status": "ACTIVE",
+ "key": null,
+ "watchers": [],
+ "categories": [
+ {
+ "id": 1,
+ "name": "Uncategorized",
+ "status": "ACTIVE",
+ "is_system": 0,
+ "created_at": "2022-03-15T12:12:34-06:00",
+ "updated_at": "2022-03-15T12:12:34-06:00",
+ "pivot": {
+ "assignable_id": 2,
+ "category_id": 1,
+ "category_type": "ProcessMaker\\Models\\ScreenCategory"
+ }
+ }
+ ]
+ }
+ ],
+ "screen_categories": [],
+ "scripts": []
+}
\ No newline at end of file
diff --git a/tests/e2e/specs/RecordList.spec.js b/tests/e2e/specs/RecordList.spec.js
index 58cc6fba5..3666b832a 100644
--- a/tests/e2e/specs/RecordList.spec.js
+++ b/tests/e2e/specs/RecordList.spec.js
@@ -144,4 +144,82 @@ describe('Record list', () => {
});
});
});
+
+ it('FileUpload in record lists within loops', () => {
+ cy.loadFromJson('record_list_fileupload_loops.json', 0);
+ cy.get('[data-cy=mode-preview]').click();
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=add-row]').click();
+
+ // Upload the first file.
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-add] [name=form_input_4]').eq(0).clear().type('First');
+ cy.route('POST', '/api/1.0/requests/1/files', JSON.stringify({
+ message: 'The file was uploaded.',
+ fileUploadId: 1,
+ }));
+ cy.uploadFile('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-add] [data-cy="screen-field-file_upload_2"] input[type=file]', 'avatar.jpeg', 'image/jpg');
+
+ // Upload a second file.
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-add] [data-cy=loop-loop_1-add]').click();
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-add] [name=form_input_4]').eq(1).clear().type('Second');
+ cy.route('POST', '/api/1.0/requests/1/files', JSON.stringify({
+ message: 'The file was uploaded.',
+ fileUploadId: 2,
+ }));
+ cy.uploadFile('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-add] [data-cy="screen-field-file_upload_2"] input[type=file]', 'avatar.jpeg', 'image/jpg', 1);
+ cy.wait(1000);
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-add] [data-cy="screen-field-file_upload_2"]').eq(0).should('contain.text', 'avatar.jpeg');
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-add] [data-cy="screen-field-file_upload_2"]').eq(1).should('contain.text', 'avatar.jpeg');
+
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-add] button:contains(Ok)').click();
+
+ // Edit record and check the uploaded files are displayed.
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=edit-row]').click();
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] [data-cy="screen-field-file_upload_2"]').eq(0).should('contain.text', 'avatar.jpeg');
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] [data-cy="screen-field-file_upload_2"]').eq(1).should('contain.text', 'avatar.jpeg');
+
+ // Add a third file in edit modal.
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] [data-cy=loop-loop_1-add]').click();
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] [name=form_input_4]').eq(2).clear().type('Third');
+ cy.route('POST', '/api/1.0/requests/1/files', JSON.stringify({
+ message: 'The file was uploaded.',
+ fileUploadId: 3,
+ }));
+ cy.uploadFile('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] [data-cy="screen-field-file_upload_2"] input[type=file]', 'avatar.jpeg', 'image/jpg', 2);
+ cy.wait(1000);
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] [data-cy="screen-field-file_upload_2"]').eq(2).should('contain.text', 'avatar.jpeg');
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] button:contains(Save)').click();
+
+ // Delete third file in edit modal.
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=edit-row]').click();
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] [data-cy=loop-loop_1-remove]').click();
+ cy.on('window:confirm', () => true);
+ cy.wait(500);
+ cy.get('[data-cy=preview-content] [data-cy=screen-field-form_record_list_1] [data-cy=modal-edit] button:contains(Save)').click();
+
+ // Verify the data structure.
+ cy.get('#screen-builder-container').then((div) => {
+ const data = div[0].__vue__.previewData;
+ const record_row_id = data.form_record_list_1[0].row_id;
+ expect(data).to.eql({
+ 'form_record_list_1': [
+ {
+ 'loop_1': [
+ {
+ 'form_input_4': 'First',
+ 'file_upload_2': 1,
+ },
+ {
+ 'form_input_4': 'Second',
+ 'file_upload_2': 2,
+ },
+ ],
+ 'row_id': record_row_id,
+ },
+ ],
+ 'loop_1': [
+ {},
+ ],
+ });
+ });
+ });
});
diff --git a/tests/e2e/support/commands.js b/tests/e2e/support/commands.js
index 0f426488b..a11642f3a 100644
--- a/tests/e2e/support/commands.js
+++ b/tests/e2e/support/commands.js
@@ -59,8 +59,8 @@ function getFixtureBlob(fileUrl, type) {
* @param {String} fileUrl - The file url to upload
* @param {String} type - content type of the uploaded file
*/
-Cypress.Commands.add('uploadFile', (selector, fileUrl, type = '') => {
- return cy.get(selector).then(subject => {
+Cypress.Commands.add('uploadFile', (selector, fileUrl, type = '', index = 0) => {
+ return cy.get(selector).eq(index).then(subject => {
return getFixtureBlob(fileUrl, type).then(blob => {
return cy.window().then(win => {
const el = subject[0];