diff --git a/src/App.vue b/src/App.vue index eef62ff20..78fb2fcc2 100644 --- a/src/App.vue +++ b/src/App.vue @@ -50,6 +50,7 @@ + + + + + + + + + diff --git a/src/components/ScreenToolbar.vue b/src/components/ScreenToolbar.vue index daf8a1eb9..ebb524552 100644 --- a/src/components/ScreenToolbar.vue +++ b/src/components/ScreenToolbar.vue @@ -4,7 +4,7 @@ @@ -14,7 +14,7 @@ @@ -34,6 +34,7 @@ type="button" class="screen-toolbar-button" variant="link" + :disabled="disabled" :title="$t('Calculated Properties')" data-cy="topbar-calcs" @click="$emit('open-calc')" @@ -45,6 +46,7 @@ type="button" class="screen-toolbar-button" variant="link" + :disabled="disabled" :title="$t('Custom CSS')" data-cy="topbar-css" @click="$emit('open-customCss')" @@ -56,6 +58,7 @@ type="button" class="screen-toolbar-button" variant="link" + :disabled="disabled" :title="$t('Watchers')" data-cy="topbar-watchers" @click="$emit('open-watchers')" @@ -67,6 +70,7 @@ type="button" class="screen-toolbar-button" variant="outlined-secondary" + :disabled="disabled" :popper-opts="{ placement: 'bottom-end' }" data-cy="topbar-options" > @@ -86,6 +90,15 @@ diff --git a/src/form-builder-controls.js b/src/form-builder-controls.js index ae236b80a..0ae341a31 100755 --- a/src/form-builder-controls.js +++ b/src/form-builder-controls.js @@ -56,7 +56,7 @@ export default [ rendererBinding: 'FormHtmlEditor', control: { popoverContent: "Use a Rich Text Editor to add HTML-formatted", - order: 1.0, + order: 2.0, group: 'Content Fields', label: 'Rich Text', component: 'FormHtmlViewer', @@ -98,7 +98,7 @@ export default [ rendererBinding: 'FormMaskedInput', control: { popoverContent: "Collect a string of text and format it as one of several data types", - order: 1.0, + order: 2.0, group: 'Input Fields', label: 'Line Input', component: 'FormInput', @@ -129,6 +129,7 @@ export default [ ], }, }, + { editorComponent: FormTextArea, editorBinding: 'FormTextArea', @@ -136,7 +137,7 @@ export default [ rendererBinding: 'FormTextArea', control: { popoverContent: "Collect a multi-line string of text, to allow for extensive, richly formatted responses", - order: 4.0, + order: 5.0, group: 'Input Fields', label: 'Textarea', component: 'FormTextArea', @@ -194,7 +195,7 @@ export default [ rendererBinding: 'FormSelectList', control: { popoverContent: "Collect options from a list, as radio butttons or dropdowns", - order: 2.0, + order: 3.0, group: 'Input Fields', label: 'Select List', component: 'FormSelectList', @@ -249,7 +250,7 @@ export default [ rendererBinding: 'FormCheckbox', control: { popoverContent: "Add a checkbox or toggle for true/false responses", - order: 6.0, + order: 7.0, group: 'Input Fields', label: 'Checkbox', component: 'FormCheckbox', @@ -291,7 +292,7 @@ export default [ rendererBinding: 'FormDatePicker', control: { popoverContent: "Collect a date or date/time", - order: 5.0, + order: 6.0, group: 'Input Fields', label: 'Date Picker', component: 'FormDatePicker', @@ -345,7 +346,7 @@ export default [ rendererBinding: 'FormButton', control: { popoverContent: "Add special buttons that link between subpages within this Form", - order: 1.0, + order: 2.0, group: 'Navigation', label: 'Page Navigation', component: 'FormButton', @@ -380,7 +381,7 @@ export default [ rendererBinding: 'FormMultiColumn', control: { popoverContent: "Organize and group your content in columns", - order: 2.0, + order: 3.0, group: 'Content Fields', label: 'Multicolumn / Table', component: 'FormMultiColumn', @@ -425,7 +426,7 @@ export default [ rendererBinding: 'FormLoop', control: { popoverContent: "Add a repeatable section of content", - order: 5.0, + order: 6.0, group: 'Content Fields', label: 'Loop', component: 'FormLoop', @@ -461,7 +462,7 @@ export default [ rendererBinding: 'FormRecordList', control: { popoverContent: "Format content in a table structure and allow for adding rows", - order: 4.0, + order: 5.0, group: 'Content Fields', label: 'Record List', component: 'FormRecordList', @@ -568,7 +569,7 @@ export default [ rendererBinding: 'FormImage', control: { popoverContent: "Upload an image to your screen", - order: 3.0, + order: 4.0, group: 'Content Fields', label: 'Image', component: 'FormImage', @@ -635,7 +636,7 @@ export default [ rendererBinding: 'FormAvatar', control: { popoverContent: "User avatar", - order: 3.0, + order: 4.0, group: 'Dashboards', label: 'User Avatar', component: 'FormAvatar', @@ -679,7 +680,7 @@ export default [ rendererBinding: 'FormButton', control: { popoverContent: "Add an action to submit your form or update a field", - order: 3.0, + order: 4.0, group: 'Input Fields', label: 'Submit Button', component: 'FormButton', @@ -740,7 +741,7 @@ export default [ rendererBinding: 'FormNestedScreen', control: { popoverContent: "Add and reuse another Form within this Form", - order: 6.0, + order: 7.0, group: 'Content Fields', label: 'Nested Screen', component: 'FormNestedScreen', @@ -775,7 +776,7 @@ export default [ control: { group: "Files", popoverContent: "Collect files uploaded into the Form", - order: 1.0, + order: 2.0, label: 'File Upload', component: 'FileUpload', 'editor-component': 'FileUpload', @@ -827,7 +828,7 @@ export default [ builderBinding: 'FileDownload', control: { popoverContent: "Offer a File download", - order: 2.0, + order: 3.0, group: "Files", label: 'File Download', component: 'FileDownload', @@ -863,7 +864,7 @@ export default [ builderBinding: 'BFormComponent', control: { popoverContent: "Add one of several Bootstrap Vue components", - order: 1.0, + order: 2.0, group: 'Advanced', label: 'Bootstrap Component', component: 'BFormComponent', @@ -917,7 +918,7 @@ export default [ builderBinding: 'BWrapperComponent', control: { popoverContent: "Wrap an existing subpage within this Form into a Bootstrap Vue component", - order: 2.0, + order: 3.0, group: 'Advanced', label: 'Bootstrap Wrapper', component: 'BWrapperComponent', @@ -1016,7 +1017,7 @@ export default [ rendererBinding: "FormAnalyticsChart", control: { popoverContent: "Add a chart from the Analytics Reports", - order: 6.0, + order: 7.0, group: 'Dashboards', label: "Analytics Chart", component: "FormAnalyticsChart", @@ -1047,7 +1048,7 @@ export default [ control: { popoverContent: "Add a URL where this link should redirect", group: 'Content Fields', - order: 6.0, + order: 7.0, label: "Link URL", component: "LinkButton", "editor-component": "LinkButton", @@ -1079,6 +1080,19 @@ export default [ ] } }, + { + control: { + popoverContent: "Drag and paste copied elements to your desired location.", + order: 1.0, + group: 'Clipboard', + label: 'Drag & Paste', + component: "Clipboard", + config: { + icon: 'fa fa-clipboard', + }, + inspector: [], + }, + }, { editorComponent: FormCollectionRecordControl, editorBinding: 'FormCollectionRecordControl', diff --git a/src/main.js b/src/main.js index e2658e501..1153cec71 100644 --- a/src/main.js +++ b/src/main.js @@ -15,6 +15,7 @@ import { LRUCache } from "lru-cache"; import VueFormElements from "@processmaker/vue-form-elements"; import undoRedoModule from "@/store/modules/undoRedoModule"; import globalErrorsModule from "@/store/modules/globalErrorsModule"; +import clipboardModule from "@/store/modules/clipboardModule"; import ScreenBuilder from "@/components"; import TestComponents from "../tests/components"; @@ -52,7 +53,8 @@ Vue.component("PmqlInput", { const store = new Vuex.Store({ modules: { globalErrorsModule, - undoRedoModule + undoRedoModule, + clipboardModule } }); diff --git a/src/mixins/Clipboard.js b/src/mixins/Clipboard.js new file mode 100644 index 000000000..ef9478e19 --- /dev/null +++ b/src/mixins/Clipboard.js @@ -0,0 +1,153 @@ +import { v4 as uuidv4 } from 'uuid'; +import _ from "lodash"; + +const clipboardComponentName = "Clipboard"; + +export default { + data() { + return { + showClipboard: false, + }; + }, + methods: { + /** + * Adds a deep-cloned item to the clipboard, ensuring the original item is unmodified. + * + * @param {Object} item - The item to add to the clipboard. + * @returns {void} + */ + addToClipboard(item) { + const duplicate = _.cloneDeep(item); // Create a deep copy of the item + this.$store.dispatch("clipboardModule/addToClipboard", duplicate); // Dispatch action to add item to the Vuex store + this.$root.$emit('update-clipboard'); + }, + + /** + * Removes the specified item from the clipboard. + * + * @param {Object} item - The item to remove from the clipboard. + * @returns {void} + */ + removeFromClipboard(item) { + this.$store.dispatch("clipboardModule/removeFromClipboard", item); // Dispatch action to remove item from the Vuex store + this.$root.$emit('update-clipboard'); + }, + + /** + * Checks if the specified item is currently in the clipboard. + * + * @param {Object} item - The item to check. + * @returns {Boolean} - Returns true if the item is in the clipboard, otherwise false. + */ + isInClipboard(item) { + return this.$store.getters["clipboardModule/isInClipboard"](item); // Use Vuex getter to check if item exists in the clipboard + }, + + /** + * Generate a unique UUID for the specified item. + */ + generateUUID() { + return uuidv4(); // Generate a unique identifier using UUID v4 + }, + + /** + * Add a UUID to each element in the screen configuration. + * + * @param array screenConfig + */ + addUuidToElements(screenConfig) { + const replaceInPage = (page) => { + page.items.forEach((item, index) => { + if (!item.uuid) { + item.uuid = this.generateUUID(); + } + if (item.items) { + replaceInPage(item); + } + }); + } + + screenConfig.forEach((item) => replaceInPage(item)); + }, + + /** + * Setup or update UUID for the item and its children. + * + * @param {*} item Control item in the screen configuration + */ + updateUuids(item) { + item.uuid = this.generateUUID(); + if (item.items) { + item.items.forEach(item => { + if (item instanceof Array) { + // multi-column each item in the column + item.forEach(this.updateUuids) + } else { + // loop through children + this.updateUuids(item); + } + }) + } + }, + + /** + * Find { component: "Clipboard" } and replace with the clipboard content. + */ + replaceClipboardContent(screenConfig) { + if ( + !screenConfig + || screenConfig instanceof Array === false + ) { + throw new Error("Expected a screen configuration array"); + } + + const replaceInPage = (page) => { + page.items.forEach((item, index) => { + if (item.component === clipboardComponentName) { + // clone clipboard content to avoid modifying the original + const clipboardContent = _.cloneDeep(this.$store.getters["clipboardModule/clipboardItems"]); + // replace uuids in clipboard content + clipboardContent.forEach(this.updateUuids); + page.items.splice(index, 1, ...clipboardContent); + } + if (item.items) { + replaceInPage(item); + } + }); + } + screenConfig.forEach((item) => replaceInPage(item)); + }, + + /** + * Clear the clipboard + */ + async clearClipboard() { + const confirm = await this.$bvModal.msgBoxConfirm( + this.$t("Deleting the clipboard will permanently remove all information, and you will need to copy all components again."), + { + title: this.$t("Are you sure you want to clear clipboard?"), + size: "md", + buttonSize: "sm", + okVariant: "primary py-2 px-4", + cancelVariant: "outline-secondary py-2 px-4", + okTitle: this.$t("Confirm"), + cancelTitle: this.$t("Cancel"), + footerClass: "p-2 border-0", + hideHeaderClose: true, + centered: true, + } + ); + if (confirm) { + this.$store.dispatch("clipboardModule/clearClipboard"); + this.$root.$emit('update-clipboard'); + } + }, + + /** + * Close Clipboard + */ + closeClipboard() { + this.showClipboard = false; + }, + }, +}; diff --git a/src/mixins/index.js b/src/mixins/index.js index 99f9da503..9376c9097 100644 --- a/src/mixins/index.js +++ b/src/mixins/index.js @@ -18,3 +18,4 @@ export { default as testing } from "./testing"; export { ValidationMsg, validators } from "./ValidationRules"; export { default as VisibilityRule } from "./VisibilityRule"; export { default as watchers } from "./watchers"; +export { default as Clipboard } from "./Clipboard"; \ No newline at end of file diff --git a/src/store/modules/ClipboardManager.js b/src/store/modules/ClipboardManager.js new file mode 100644 index 000000000..81020e696 --- /dev/null +++ b/src/store/modules/ClipboardManager.js @@ -0,0 +1,79 @@ +/** + * ClipboardManager class to handle saving to and loading from + * localStorage and the server. + */ +class ClipboardManager { + + /** + * Callable property function that loads the clipboard from server. + */ + static loadFromServerFn = null; + + /** + * Callable property function that saves the clipboard to server. + */ + static saveToServerFn = null; + + /** + * Saves the clipboard items to localStorage. + * @param {Array} clipboard - The clipboard items to save. + */ + static saveToLocalStorage(clipboard) { + localStorage.setItem('clipboard', JSON.stringify(clipboard)); + } + + /** + * Loads the clipboard items from localStorage. + * @returns {Array} The clipboard items. + */ + static loadFromLocalStorage() { + const clipboardData = localStorage.getItem('clipboard'); + if (clipboardData) { + try { + return JSON.parse(clipboardData); + } catch (e) { + console.error('Failed to parse clipboard data from localStorage:', e); + return []; + } + } else { + return []; + } + } + + /** + * Saves the clipboard items to the server via POST /clipboard/create_or_update. + * @param {Array} clipboard - The clipboard items to save. + * @returns {Promise} + */ + static saveToServer(clipboard) { + // return axios.post('/clipboard/create_or_update', { clipboard }); + if (!ClipboardManager.saveToServerFn) { + return Promise.resolve(); + } + return ClipboardManager.saveToServerFn(clipboard); + } + + /** + * Loads the clipboard items from the server via GET /clipboard/get_by_user. + * @returns {Promise} The clipboard items. + */ + static loadFromServer() { + if (!ClipboardManager.loadFromServerFn) { + return Promise.resolve([]); + } + return ClipboardManager.loadFromServerFn() + .then(clipboard => { + if (Array.isArray(clipboard)) { + return clipboard; + } else { + throw new Error('Invalid server response: Expected array for clipboard content'); + } + }) + .catch(error => { + console.error('Failed to load clipboard from server:', error); + return []; + }); + } +} + +export default ClipboardManager; diff --git a/src/store/modules/clipboardModule.js b/src/store/modules/clipboardModule.js new file mode 100644 index 000000000..13a64e3e0 --- /dev/null +++ b/src/store/modules/clipboardModule.js @@ -0,0 +1,210 @@ +import { v4 as uuidv4 } from 'uuid'; +import ClipboardManager from './ClipboardManager'; + +/** + * Vuex module for managing clipboard state with localStorage synchronization. + */ +const clipboardModule = { + /** + * Indicates that this module is namespaced, which means + * all its state, mutations, actions, and getters will be + * scoped to this module. + */ + namespaced: true, + + /** + * The state of the clipboard module. + * @returns {Object} The initial state of the clipboard. + */ + state() { + return { + /** + * @type {Array} Array to store clipboard items. + */ + clipboard: [], + }; + }, + + /** + * Getters provide read-only access to the state. + */ + getters: { + /** + * Returns all items in the clipboard. + * @param {Object} state - The state of the module. + * @returns {Array} The array of clipboard items. + */ + clipboardItems: state => state.clipboard, + + /** + * Checks if an item with a specific uuid is present in the clipboard. + * @param {Object} state - The state of the module. + * @returns {Function} Function to check item presence. + */ + isInClipboard: state => item => { + if (!item || !item.uuid) { + // If the item is invalid or doesn't have an uuid, return false + return false; + } + return state.clipboard.some(clipboardItem => clipboardItem.uuid === item.uuid); + }, + }, + + /** + * Mutations are used to modify the state. + */ + mutations: { + /** + * Sets the entire clipboard state. + * @param {Object} state - The state of the module. + * @param {Array} clipboard - The new clipboard array. + */ + SET_CLIPBOARD(state, clipboard) { + if (!Array.isArray(clipboard)) { + throw new Error('Clipboard content must be an array'); + } + state.clipboard.splice(0, state.clipboard.length, ...clipboard); + }, + + /** + * Adds items to the clipboard. + * @param {Object} state - The state of the module. + * @param {any} items - The items to add. + */ + ADD_TO_CLIPBOARD(state, items) { + const itemsToAdd = Array.isArray(items) ? items : [items]; + itemsToAdd.forEach(item => { + if (!item.uuid) { + item.uuid = uuidv4(); + } + if (!state.clipboard.some(clipboardItem => clipboardItem.uuid === item.uuid)) { + state.clipboard.push(item); + } + }); + }, + + /** + * Removes a specific item from the clipboard. + * @param {Object} state - The state of the module. + * @param {any} item - The item to remove. + */ + REMOVE_FROM_CLIPBOARD(state, item) { + if (!item || !item.uuid) { + console.error('Item or item uuid is missing'); + return; + } + const index = state.clipboard.findIndex(clipboardItem => clipboardItem.uuid === item.uuid); + if (index !== -1) { + state.clipboard.splice(index, 1); + } + }, + + /** + * Clears all items from the clipboard. + * @param {Object} state - The state of the module. + */ + CLEAR_CLIPBOARD(state) { + state.clipboard.splice(0, state.clipboard.length); + }, + }, + + /** + * Actions are used to commit mutations and can contain asynchronous operations. + */ + actions: { + /** + * Initializes the clipboard by loading from localStorage and server, + * and setting up the storage event listener. + * @param {Object} context - The Vuex context. + */ + initializeClipboard({ commit }) { + // Load from localStorage + const clipboard = ClipboardManager.loadFromLocalStorage(); + commit('SET_CLIPBOARD', clipboard); + + // Load from server and update state + ClipboardManager.loadFromServer().then(serverClipboard => { + if (serverClipboard.length > 0) { + commit('SET_CLIPBOARD', serverClipboard); + ClipboardManager.saveToLocalStorage(serverClipboard); + } + }); + + // Set up storage event listener + window.addEventListener('storage', event => { + if (event.key === 'clipboard') { + const clipboard = ClipboardManager.loadFromLocalStorage(); + commit('SET_CLIPBOARD', clipboard); + } + }); + }, + + /** + * Setup saveToServerFn + * @param {Object} context - The Vuex context. + * @param {Function} saveToServerFn - The function to save the clipboard to the server. + */ + setupSaveToServerFn({ commit }, saveToServerFn) { + ClipboardManager.saveToServerFn = saveToServerFn; + }, + + /** + * Setup loadFromServerFn + * @param {Object} context - The Vuex context. + * @param {Function} loadFromServerFn - The function to load the clipboard from the server. + */ + setupLoadFromServerFn({ commit }, loadFromServerFn) { + ClipboardManager.loadFromServerFn = loadFromServerFn; + }, + + /** + * Adds an item to the clipboard. + * Updates localStorage and the server. + * @param {Object} context - The Vuex context. + * @param {any} item - The item to add. + */ + addToClipboard({ commit, state }, item) { + if (!item) { + throw new Error('Item is missing'); + } + commit('ADD_TO_CLIPBOARD', item); + // Save to localStorage and server + ClipboardManager.saveToLocalStorage(state.clipboard); + ClipboardManager.saveToServer(state.clipboard); + }, + + pushState({ commit, state }, clipboard) { + commit('SET_CLIPBOARD', clipboard); + // Save to localStorage and server + ClipboardManager.saveToLocalStorage(state.clipboard); + ClipboardManager.saveToServer(state.clipboard); + }, + + /** + * Removes an item from the clipboard. + * Updates localStorage and the server. + * @param {Object} context - The Vuex context. + * @param {any} item - The item to remove. + */ + removeFromClipboard({ commit, state }, item) { + commit('REMOVE_FROM_CLIPBOARD', item); + // Save to localStorage and server + ClipboardManager.saveToLocalStorage(state.clipboard); + ClipboardManager.saveToServer(state.clipboard); + }, + + /** + * Clears all items from the clipboard. + * Updates localStorage and the server. + * @param {Object} context - The Vuex context. + */ + clearClipboard({ commit, state }) { + commit('CLEAR_CLIPBOARD'); + // Save to localStorage and server + ClipboardManager.saveToLocalStorage(state.clipboard); + ClipboardManager.saveToServer(state.clipboard); + }, + }, +}; + +export default clipboardModule; diff --git a/src/stories/ClipboardButton.stories.js b/src/stories/ClipboardButton.stories.js new file mode 100644 index 000000000..cdaa40ee1 --- /dev/null +++ b/src/stories/ClipboardButton.stories.js @@ -0,0 +1,66 @@ +import ClipboardButton from '../components/ClipboardButton.vue'; +import { within, userEvent, expect } from "@storybook/test"; + +export default { + title: 'Components/ClipboardButton', + tags: ["autodocs"], + component: ClipboardButton, + argTypes: { + isInClipboard: { control: 'boolean' }, + }, +}; + +const Template = (args) => ({ + components: { ClipboardButton }, + setup() { + return { args }; + }, + template: '', +}); + +// Story for when the item is in the clipboard +export const InClipboard = Template.bind({}); +InClipboard.args = { + isInClipboard: true, + index: 1, + addTitle: 'Add to clipboard', + removeTitle: 'Remove from clipboard', + addToClipboard: () => {}, + removeFromClipboard: () => {}, +}; +InClipboard.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Expect the "Remove from clipboard" button to be rendered + const removeButton = await canvas.getByRole('button', { name: /Remove from clipboard/i }); + expect(removeButton).toBeInTheDocument(); + + // Simulate a click on the remove button + await userEvent.click(removeButton); + + // Ensure that the button remains visible after interaction + expect(removeButton).toBeVisible(); +}; + +// Story for when the item is not in the clipboard +export const NotInClipboard = Template.bind({}); +NotInClipboard.args = { + isInClipboard: false, + index: 1, + addToClipboard: () => {}, + removeFromClipboard: () => {}, +}; + +NotInClipboard.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Expect the "Add to clipboard" button to be rendered + const addButton = await canvas.getByRole('button', { name: /Add to clipboard/i }); + expect(addButton).toBeInTheDocument(); + + // Simulate a click on the add button + await userEvent.click(addButton); + + // Ensure that the button remains visible after interaction + expect(addButton).toBeVisible(); +}; diff --git a/src/stories/PagesDropdown.stories.js b/src/stories/PagesDropdown.stories.js index ad676b0f7..fa74095fa 100644 --- a/src/stories/PagesDropdown.stories.js +++ b/src/stories/PagesDropdown.stories.js @@ -17,6 +17,7 @@ export default { @addPage="onAddPage" @clickPage="onClick" @seeAllPages="onSeeAllPages" + @clipboard="onClipboard" /> `, data() { @@ -31,7 +32,10 @@ export default { }, onClick(index) { console.log("Click page item:", index); - } + }, + onClipboard() { + console.log("Open clipboard"); + }, } }) }; @@ -104,8 +108,8 @@ export const ClickInCreatePage = { await selectorAddPage.click(selectorAddPage); } }; -// Open the See all Pages -export const ClickInSeeAllPages = { +// Open the Clipboard +export const ClickInClipboard = { args: { data: [{ name: "Page 1" }] }, @@ -114,19 +118,18 @@ export const ClickInSeeAllPages = { const selector = canvasElement.querySelector( "[data-test=page-dropdown] button" ); - const selectorAddPage = canvasElement.querySelector( - "[data-test=see-all-pages]" + const clipboardOption = canvasElement.querySelector( + "[data-test=clipboard]" ); - console.log(selectorAddPage); await selector.click(selector); await waitFor( () => { expect(canvas.getByTestId("page-dropdown")).toContainHTML( - "See all pages" + "Clipboard" ); }, { timeout: 1000 } ); - await selectorAddPage.click(selectorAddPage); + await clipboardOption.click(clipboardOption); } }; diff --git a/tests/e2e/specs/Clipboard.spec.js b/tests/e2e/specs/Clipboard.spec.js new file mode 100644 index 000000000..50aad5b31 --- /dev/null +++ b/tests/e2e/specs/Clipboard.spec.js @@ -0,0 +1,109 @@ +describe("Clipboard Button Actions", () => { + + it("Should display an empty drop zone message when no elements are present", () => { + cy.visit("/"); + cy.openAcordeonByLabel("Clipboard"); + cy.get("[data-cy=screen-drop-zone]").should( + "contain.text", + "Place your controls here." + ); + }); + + it("Should allow adding and removing an input field to/from the clipboard", () => { + cy.visit("/"); + cy.openAcordeonByLabel("Input Fields"); + + // Step 1: Dragging FormInput control to screen drop zone + cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { + position: "bottom" + }); + + // Step 2: Click on the screen element container to activate it + cy.get('[data-cy="screen-element-container"]').click(); + + // Step 3: Verify 'Add to Clipboard' button is visible and then click it + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + + // Step 4: Verify 'Remove from Clipboard' button is visible after adding to clipboard and then click it + cy.get('[data-cy="removeFromClipboard"]').should("be.visible"); + cy.get('[data-cy="removeFromClipboard"]').click(); + cy.get('[data-cy="removeFromClipboard"]').should("not.exist"); + }); + + it("Should allow adding and removing a multi-column form to/from the clipboard", () => { + cy.visit("/"); + cy.openAcordeonByLabel("Content Fields"); // Open the multi-column controls section + cy.openAcordeonByLabel("Input Fields"); // Open the form controls section + + // Step 1: Dragging FormMultiColumn control to screen drop zone + cy.get("[data-cy=controls-FormMultiColumn]").drag( + "[data-cy=screen-drop-zone]", + { position: "bottom" } + ); + + // Step 2: Add two input fields to different columns in the multi-column layout + cy.get("[data-cy=screen-element-container]").click(); + cy.get("[data-cy=controls-FormInput]").drag( + "[data-cy=screen-element-container] .column-draggable:empty" + ); + cy.get("[data-cy=controls-FormInput]").drag( + "[data-cy=screen-element-container] .column-draggable:empty" + ); + + // Step 3: Toggle JSON format in the inspector and input custom column data + cy.get('.custom-switch:has([data-cy="inspector-jsonFormat"]) label').click(); + cy.get("[data-cy=inspector-dataJson]") + .clear() + .type( + JSON.stringify([ + { value: "1", content: "6" }, + { value: "1", content: "6" } + ]), + { parseSpecialCharSequences: false } + ); + cy.get("[data-cy=inspector-dataJson-save]").click(); + + // Step 4: Select the form input element and add it to the clipboard + cy.get('[id="form_input_1"]').click(); + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + + // Step 5: Remove the form input from the clipboard + cy.get('[data-cy="removeFromClipboard"]').should("be.visible"); + cy.get('[data-cy="removeFromClipboard"]').click(); + cy.get('[data-cy="removeFromClipboard"]').should("not.exist"); + }); + + it("Should allow adding and removing a loop form to/from the clipboard", () => { + cy.visit("/"); + cy.openAcordeonByLabel("Content Fields"); + // Step 1: Dragging FormLoop control to screen drop zone + cy.get("[data-cy=controls-FormLoop]").drag("[data-cy=screen-drop-zone]"); + cy.get("[data-cy=screen-element-container]").click(); + cy.get("[data-cy=inspector-name]").clear().type("rows"); + cy.get("[data-cy=inspector-source]").select("existing"); + cy.get("[data-cy=inspector-add]").click(); + + // Step 2: Add an input field in the Loop layout + cy.openAcordeonByLabel("Input Fields"); + cy.get("[data-cy=controls-FormInput]").drag( + "[data-cy=screen-element-container] .column-draggable div", + { position: "bottom" } + ); + + // Step 3: Select the form input element and add it to the clipboard + cy.get('#form_input_1').click(); + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + + // Step 4: Remove the form input from the clipboard + cy.get('[data-cy="removeFromClipboard"]').should("be.visible"); + cy.get('[data-cy="removeFromClipboard"]').click(); + cy.get('[data-cy="removeFromClipboard"]').should("not.exist"); + }); + +}); \ No newline at end of file diff --git a/tests/e2e/specs/ClipboardControl.spec.js b/tests/e2e/specs/ClipboardControl.spec.js new file mode 100644 index 000000000..73a476db8 --- /dev/null +++ b/tests/e2e/specs/ClipboardControl.spec.js @@ -0,0 +1,47 @@ +describe("Add Clipboard Section to Control Menu", () => { + + /** + * Test to verify that the Clipboard section is present in the control menu. + */ + it('should display the "Clipboard" section in the control menu', () => { + // Step 1: Navigate to the homepage + cy.visit("/"); + + // Step 2: Open the clipboard acordeon + cy.openAcordeonByLabel("Clipboard"); + + // Step 3: Verify that the Clipboard section is visible in the control menu + cy.contains("Clipboard").should("be.visible"); + }); + + /** + * Test to verify that the Clipboard accordion expands and shows the "Drag to Paste" control. + */ + it('should expand the Clipboard accordion and display the "Drag to Paste" control', () => { + // Step 1: Navigate to the homepage + cy.visit("/"); + + // Step 2: Open the clipboard acordeon + cy.openAcordeonByLabel("Clipboard"); + + // Step 3: Verify that the Clipboard accordion exists and is visible + cy.get('[data-cy="controls-Clipboard"]').should("exist").should("be.visible"); + }); + + /** + * Test to verify the visibility of the popover when hovering over the "Drag to Paste" control. + */ + it('should display the popover when hovering over the "Drag to Paste" control', () => { + // Step 1: Navigate to the homepage + cy.visit("/"); + + // Step 2: Open the clipboard acordeon + cy.openAcordeonByLabel("Clipboard"); + + // Step 3: Click to open the Clipboard accordion + cy.get('[data-cy="controls-Clipboard"]').click(); + + // Step 4: Verify that the popover associated with the "Drag to Paste" control is visible + cy.get('.custom-popover').should("be.visible"); + }); +}); diff --git a/tests/e2e/specs/ClipboardDragPaste.spec.js b/tests/e2e/specs/ClipboardDragPaste.spec.js new file mode 100644 index 000000000..27d855938 --- /dev/null +++ b/tests/e2e/specs/ClipboardDragPaste.spec.js @@ -0,0 +1,232 @@ +import { + addControlInsideLoop, + addControlInsideTable, +} from "../support/utils.js"; +import { nodeControls } from "../support/constants.js"; + +describe("Clipboard Drag and Paste", () => { + + it("Copy input element to clipboard", () => { + cy.window().then((win) => { + // Clear storage to remove any previous clipboard items + win.localStorage.clear(); + + // Step 1: Visit the homepage and open the 'Input Fields' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Input Fields"); + + // Step 2: Drag FormInput control to the screen's drop zone + cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { + position: "bottom" + }); + + // Step 3: Click on the screen element container to select it + cy.get('[data-cy="screen-element-container"]').click(); + + // Step 4: Copy the selected element to the clipboard + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + }); + }); + + it("Paste clipboard item to a different screen", () => { + // Step 1: Visit the homepage and open the 'Clipboard' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Clipboard"); + + // Step 2: Drag clipboard item to the screen's drop zone + cy.get('[data-cy="controls-Clipboard"]').drag('[data-cy=screen-drop-zone]'); + + // Step 3: Verify that the item has been pasted correctly (1 element should be present) + cy.get('[data-cy="screen-element-container"]').should('have.length', 1); + + // Step 4: Click on the pasted element to activate it + cy.get('[data-cy="screen-element-container"]').click(); + }); + + it("Copy multicolumn element to clipboard", () => { + cy.window().then((win) => { + // Clear storage to remove any previous clipboard items + win.localStorage.clear(); + + // Step 1: Visit the homepage and open the 'Input Fields' and 'Content Fields' accordions + cy.visit("/"); + cy.openAcordeonByLabel("Input Fields"); + cy.openAcordeonByLabel("Content Fields"); + + // Step 2: Drag FormMultiColumn control to the screen's drop zone + cy.get("[data-cy=controls-FormMultiColumn]").drag("[data-cy=screen-drop-zone]", { + position: "bottom" + }); + + // Step 3: Add a TextArea control inside the multicolumn table + addControlInsideTable(1, nodeControls.formTextArea); + + // Step 4: Click on the screen element container to select it + cy.get('[data-cy="screen-element-container"]').click(); + + // Step 5: Copy the multicolumn element to the clipboard + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + }); + }); + + it("Paste multicolumn clipboard item to a different screen", () => { + // Step 1: Visit the homepage and open the 'Clipboard' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Clipboard"); + + // Step 2: Drag clipboard item to the screen's drop zone + cy.get('[data-cy="controls-Clipboard"]').drag('[data-cy=screen-drop-zone]'); + + // Step 3: Verify the multicolumn element with TextArea exists (2 columns) + cy.get('[data-cy="screen-element-container"]').should('have.length', 1); + cy.get('[data-cy="screen-element-container"] .column-draggable').should('have.length', 2); + cy.get('[data-cy="screen-element-container"] .column-draggable').eq(1).find('textarea').should('exist'); + + // Step 4: Click on the screen element container to activate it + cy.get('[data-cy="screen-element-container"]').click(); + }); + + it("Copy loop element to clipboard", () => { + cy.window().then((win) => { + // Clear storage to remove any previous clipboard items + win.localStorage.clear(); + + // Step 1: Visit the homepage and open the 'Input Fields' and 'Content Fields' accordions + cy.visit("/"); + cy.openAcordeonByLabel("Input Fields"); + cy.openAcordeonByLabel("Content Fields"); + + // Step 2: Drag FormLoop control to the screen's drop zone + cy.get("[data-cy=controls-FormLoop]").drag("[data-cy=screen-drop-zone]", { + position: "bottom" + }); + + // Step 3: Add a TextArea control inside the loop + addControlInsideLoop(1, nodeControls.formTextArea); + + // Step 4: Click on the screen element container to select it + cy.get('[data-cy="screen-element-container"]').click({ + position: "top" + }); + + // Step 5: Copy the loop element to the clipboard + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + }); + }); + + it("Paste loop clipboard item to a different screen", () => { + // Step 1: Visit the homepage and open the 'Clipboard' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Clipboard"); + + // Step 2: Drag clipboard item to the screen's drop zone + cy.get('[data-cy="controls-Clipboard"]').drag('[data-cy=screen-drop-zone]'); + + // Step 3: Verify the loop element with TextArea exists + cy.get('[data-cy="screen-element-container"]').should('have.length', 1); + cy.get('[data-cy="screen-element-container"] .column-draggable').should('have.length', 1); + cy.get('[data-cy="screen-element-container"] .column-draggable').eq(0).find('textarea').should('exist'); + + // Step 4: Click on the screen element container to activate it + cy.get('[data-cy="screen-element-container"]').click(); + }); + + it("Copy element from inside multicolumn to clipboard", () => { + cy.window().then((win) => { + // Clear storage to remove any previous clipboard items + win.localStorage.clear(); + + // Step 1: Visit the homepage and open the 'Input Fields' and 'Content Fields' accordions + cy.visit("/"); + cy.openAcordeonByLabel("Input Fields"); + cy.openAcordeonByLabel("Content Fields"); + + // Step 2: Drag Multicolumn control to the screen's drop zone and add a TextArea inside + cy.get("[data-cy=controls-FormMultiColumn]").drag("[data-cy=screen-drop-zone]", { + position: "bottom" + }); + addControlInsideTable(1, nodeControls.formTextArea); + + // Step 3: Click on the textarea element inside the multicolumn to select it + cy.get('[data-cy="screen-element-container"] [class="control-item"]').click(); + + // Step 4: Copy the textarea element to the clipboard + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + }); + }); + + it("Paste clipboard item from inside multicolumn to a different screen", () => { + // Step 1: Visit the homepage and open the 'Clipboard' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Clipboard"); + + // Step 2: Drag clipboard item to the screen's drop zone + cy.get('[data-cy="controls-Clipboard"]').drag('[data-cy=screen-drop-zone]'); + + // Step 3: Verify that only a textarea was pasted (no multicolumn) + cy.get('[data-cy="screen-element-container"]').should('have.length', 1); + cy.get('[data-cy="screen-element-container"] .column-draggable').should('have.length', 0); + cy.get('[data-cy="screen-element-container"]').find('textarea').should('exist'); + + // Step 4: Click on the screen element container to activate it + cy.get('[data-cy="screen-element-container"]').click(); + }); + + it("Copy two input element to clipboard", () => { + cy.window().then((win) => { + // Clear storage to remove any previous clipboard items + win.localStorage.clear(); + + // Step 1: Visit the homepage and open the 'Input Fields' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Input Fields"); + + // Step 2: Drag FormInput control to the screen's drop zone + cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { + position: "bottom" + }); + + // Step 3: Click on the screen element container to select it + cy.get('[data-cy="screen-element-container"]').click(); + + // Step 4: Copy the selected element to the clipboard + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + + // Step 5: Drag a second FormInput control to the screen's drop zone + cy.get("[data-cy=controls-FormInput]").drag("[data-cy=editor-content]", { + }); + + // Step 6: Click on the screen element container to select it + cy.get('[data-cy="screen-element-container"]').eq(1).click(); + + // Step 7: Copy the selected element to the clipboard + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + }); + }); + + it("Paste clipboard items to a different screen", () => { + // Step 1: Visit the homepage and open the 'Clipboard' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Clipboard"); + + // Step 2: Drag clipboard item to the screen's drop zone + cy.get('[data-cy="controls-Clipboard"]').drag('[data-cy=screen-drop-zone]'); + + // Step 3: Verify that there are two input elements pasted + cy.get('[data-cy="screen-element-container"]').should('have.length', 2); + cy.get('[data-cy="screen-element-container"]').eq(0).find('input').should('exist'); + cy.get('[data-cy="screen-element-container"]').eq(1).find('input').should('exist'); + }); +}); diff --git a/tests/e2e/specs/ClipboardManager.spec.js b/tests/e2e/specs/ClipboardManager.spec.js new file mode 100644 index 000000000..e6724b0a3 --- /dev/null +++ b/tests/e2e/specs/ClipboardManager.spec.js @@ -0,0 +1,74 @@ +import ClipboardManager from "../../../src/store/modules/ClipboardManager"; + +describe("Clipboard Manager", () => { + + it("Should be updated when adding and removing an input field to/from the clipboard", () => { + cy.visit("/"); + cy.openAcordeonByLabel("Input Fields"); + + // Step 1: Dragging FormInput control to screen drop zone + cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { + position: "bottom" + }); + + // Step 2: Click on the screen element container to activate it + cy.get('[data-cy="screen-element-container"]').click(); + + // Step 3: Verify 'Add to Clipboard' button is visible and then click it + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist").then(() => { + // Verify it was added to the clipboard storage + const content = ClipboardManager.loadFromLocalStorage(); + expect(content.length).to.equal(1); + }); + + // Step 4: Verify 'Remove from Clipboard' button is visible after adding to clipboard and then click it + cy.get('[data-cy="removeFromClipboard"]').should("be.visible"); + cy.get('[data-cy="removeFromClipboard"]').click(); + cy.get('[data-cy="removeFromClipboard"]').should("not.exist").then(() => { + // Verify it was removed from the clipboard storage + const content = ClipboardManager.loadFromLocalStorage(); + expect(content.length).to.equal(0); + }); + }); + + it("ClipboardManager can clear the local storage", () => { + cy.window().then((win) => { + // Clear storage to remove any previous clipboard items + ClipboardManager.saveToLocalStorage([]); + + // Step 1: Visit the homepage and open the 'Input Fields' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Input Fields"); + + // Step 2: Drag FormInput control to the screen's drop zone + cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { + position: "bottom" + }); + + // Step 3: Click on the screen element container to select it + cy.get('[data-cy="screen-element-container"]').click(); + + // Step 4: Copy the selected element to the clipboard + cy.get('[data-cy="addToClipboard"]').should("be.visible"); + cy.get('[data-cy="addToClipboard"]').click(); + cy.get('[data-cy="addToClipboard"]').should("not.exist"); + }); + }); + + it("Paste clipboard item to a different screen", () => { + // Step 1: Visit the homepage and open the 'Clipboard' accordion + cy.visit("/"); + cy.openAcordeonByLabel("Clipboard"); + + // Step 2: Drag clipboard item to the screen's drop zone + cy.get('[data-cy="controls-Clipboard"]').drag('[data-cy=screen-drop-zone]'); + + // Step 3: Verify that the item has been pasted correctly (1 element should be present) + cy.get('[data-cy="screen-element-container"]').should('have.length', 1); + + // Step 4: Click on the pasted element to activate it + cy.get('[data-cy="screen-element-container"]').click(); + }); +}); \ No newline at end of file diff --git a/tests/e2e/specs/ComputedFields.spec.js b/tests/e2e/specs/ComputedFields.spec.js index 4746f8aac..8a24f1ef0 100644 --- a/tests/e2e/specs/ComputedFields.spec.js +++ b/tests/e2e/specs/ComputedFields.spec.js @@ -18,10 +18,10 @@ describe("Computed fields", () => { cy.visit("/"); cy.loadFromJson("FOUR-5139.json", 0); - // Enter preview mode + // Step 1: Enter preview mode cy.get("[data-cy=mode-preview]").click(); - // Add three inputs input in loop + // Step : Add three inputs input in loop cy.get("[data-cy=loop-loop_1-add]").click(); cy.get("[data-cy=loop-loop_1-add]").click(); cy.get("[data-cy=loop-loop_1-add]").click(); @@ -138,7 +138,7 @@ describe("Computed fields", () => { }); it("Create a javascript computed field", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" @@ -184,7 +184,7 @@ describe("Computed fields", () => { it("Create a computed field with formula", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" diff --git a/tests/e2e/specs/ComputedFieldsReadOnly.spec.js b/tests/e2e/specs/ComputedFieldsReadOnly.spec.js index 72821ed72..5a19b7e0f 100644 --- a/tests/e2e/specs/ComputedFieldsReadOnly.spec.js +++ b/tests/e2e/specs/ComputedFieldsReadOnly.spec.js @@ -3,7 +3,7 @@ import { waitUntilElementIsVisible } from "../support/utils"; describe("Computed fields", () => { it("The user should not be able to change a FormInput assigned to a computed property", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" @@ -144,7 +144,7 @@ describe("Computed fields", () => { it("The user should not be able to change a FormTextArea assigned to a computed property", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", @@ -181,7 +181,7 @@ describe("Computed fields", () => { it("The user should not be able to change a FormDatePicker assigned to a computed property", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormDatePicker]").drag( "[data-cy=screen-drop-zone]", @@ -220,7 +220,7 @@ describe("Computed fields", () => { it("The user should not be able to change a FormSelectList assigned to a computed property", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormSelectList]").drag( "[data-cy=screen-drop-zone]", @@ -275,7 +275,7 @@ describe("Computed fields", () => { it("The user should not be able to change an input assigned to a sub property of a computed property", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { diff --git a/tests/e2e/specs/CustomCss.spec.js b/tests/e2e/specs/CustomCss.spec.js index 6d9121ef0..701644e68 100644 --- a/tests/e2e/specs/CustomCss.spec.js +++ b/tests/e2e/specs/CustomCss.spec.js @@ -1,7 +1,7 @@ describe("Custom CSS", () => { it("Shows Modal", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -14,7 +14,7 @@ describe("Custom CSS", () => { it("Closes Modal", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -30,7 +30,7 @@ describe("Custom CSS", () => { it("Does Not Save Custom CSS", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -51,7 +51,7 @@ describe("Custom CSS", () => { it("Saves Custom CSS", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -76,7 +76,7 @@ describe("Custom CSS", () => { it("Does not add styling to element in design mode", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -100,7 +100,7 @@ describe("Custom CSS", () => { it("Adds styling to element in preview mode", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/DatePicker.spec.js b/tests/e2e/specs/DatePicker.spec.js index 2392dc045..f2227f377 100644 --- a/tests/e2e/specs/DatePicker.spec.js +++ b/tests/e2e/specs/DatePicker.spec.js @@ -5,7 +5,7 @@ moment.tz.setDefault("UTC"); describe("Date Picker", () => { beforeEach(() => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.window().then((win) => { win.ProcessMaker.user.timezone = "UTC"; }); diff --git a/tests/e2e/specs/DatePickerTimezone.spec.js b/tests/e2e/specs/DatePickerTimezone.spec.js index db0e5cc83..ab9153fdc 100644 --- a/tests/e2e/specs/DatePickerTimezone.spec.js +++ b/tests/e2e/specs/DatePickerTimezone.spec.js @@ -6,7 +6,7 @@ describe("Date Picker", () => { // The timezone is UTC. We set it to UTC in package.json `TZ=UTC` cy.clock(new Date(2024, 0, 0, 0, 0, 0), ['Date']); cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Set the User's timezone to Los Angeles. This is what DatePicker will use cy.window().then((win) => { diff --git a/tests/e2e/specs/DefaultValues.spec.js b/tests/e2e/specs/DefaultValues.spec.js index 4fdff56c7..db94f8b0a 100644 --- a/tests/e2e/specs/DefaultValues.spec.js +++ b/tests/e2e/specs/DefaultValues.spec.js @@ -1,7 +1,7 @@ describe("Default values", () => { it("Basic default value", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -22,7 +22,7 @@ describe("Default values", () => { it('Text Input Default value if the variable has the next format "people.firstName"', () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -46,7 +46,7 @@ describe("Default values", () => { it('Select List- Default if the variable has the next format "numbers.int"', () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormSelectList]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -83,7 +83,7 @@ describe("Default values", () => { it("Javascript default value", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.setPreviewDataInput({ name: "world" }); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" @@ -107,7 +107,7 @@ describe("Default values", () => { }); it("Initially checked checkbox", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormCheckbox]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -125,7 +125,7 @@ describe("Default values", () => { }); it("Dynamic Basic default value", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" @@ -158,7 +158,7 @@ describe("Default values", () => { }); it("Dynamic Javascript default value", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add an input field cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" diff --git a/tests/e2e/specs/DeviceVisivilityInspector.spec.js b/tests/e2e/specs/DeviceVisivilityInspector.spec.js index 7950a50c1..5b6ed760c 100644 --- a/tests/e2e/specs/DeviceVisivilityInspector.spec.js +++ b/tests/e2e/specs/DeviceVisivilityInspector.spec.js @@ -11,7 +11,7 @@ import { nodeControls } from "../support/constants.js"; describe("Device Visiblility Inspector", () => { it("Verify if an input has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -29,7 +29,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a checkbox has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormCheckbox]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -48,7 +48,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a datePicker has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormDatePicker]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -67,7 +67,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FileDownload has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-5"); + cy.openAcordeon("collapse-6"); cy.get("[data-cy=controls-FileDownload]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -86,7 +86,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FileUpload has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-5"); + cy.openAcordeon("collapse-6"); cy.get("[data-cy=controls-FileUpload]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -104,7 +104,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormImage has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormImage]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -122,7 +122,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormLoop has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormLoop]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -140,7 +140,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormMultiColumn has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormMultiColumn]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -159,7 +159,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormNestedScreen has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormNestedScreen]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -178,7 +178,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormButton has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormButton]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -196,7 +196,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormRecordList has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormRecordList]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -215,7 +215,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormHtmlViewer has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormHtmlViewer]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -234,7 +234,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormSelectList has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormSelectList]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -253,7 +253,7 @@ describe("Device Visiblility Inspector", () => { }); it("Verify if a FormTextArea has device visiblility settings", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -272,7 +272,7 @@ describe("Device Visiblility Inspector", () => { }); it("Enabled device visiblility", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -305,7 +305,7 @@ describe("Device Visiblility Inspector", () => { }); it("Disabled device visiblility", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -350,7 +350,7 @@ describe("Device Visiblility Inspector", () => { cy.visit("/"); // Step 1: Add Loop addControl("Loop"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Step 2: Add Line input inside the loop addControlInsideLoop(1, nodeControls.formInput); @@ -414,8 +414,8 @@ describe("Device Visiblility Inspector", () => { it("Verify Device Visibility of controls inside a table", () => { cy.visit("/"); + cy.openAcordeon("collapse-3"); cy.openAcordeon("collapse-2"); - cy.openAcordeon("collapse-1"); // Step 1: Add Loop addControl("Multicolumn / Table"); @@ -447,8 +447,8 @@ describe("Device Visiblility Inspector", () => { it("Verify Device Visibility of controls inside a table mobile", () => { cy.visit("/"); + cy.openAcordeon("collapse-3"); cy.openAcordeon("collapse-2"); - cy.openAcordeon("collapse-1"); // Step 1: Add Table addControl("Multicolumn / Table"); diff --git a/tests/e2e/specs/FileUpload.spec.js b/tests/e2e/specs/FileUpload.spec.js index caa23f49e..7b328549a 100644 --- a/tests/e2e/specs/FileUpload.spec.js +++ b/tests/e2e/specs/FileUpload.spec.js @@ -1,7 +1,7 @@ describe("File Upload", () => { it("Automatically sets a variable name", () => { cy.visit("/"); - cy.openAcordeon("collapse-5"); + cy.openAcordeon("collapse-6"); cy.get("[data-cy=controls-FileUpload]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -18,7 +18,7 @@ describe("File Upload", () => { it("Disables when task is self service", () => { cy.visit("/"); - cy.openAcordeon("collapse-5"); + cy.openAcordeon("collapse-6"); cy.window().then((win) => { win.ProcessMaker.isSelfService = true; }); diff --git a/tests/e2e/specs/FormImage.spec.js b/tests/e2e/specs/FormImage.spec.js index 396944ad9..4cfcea067 100644 --- a/tests/e2e/specs/FormImage.spec.js +++ b/tests/e2e/specs/FormImage.spec.js @@ -1,7 +1,7 @@ describe("Form Image", () => { it("Upload image to show", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormImage]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -22,7 +22,7 @@ describe("Form Image", () => { it("Image by variable", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormImage]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/FormInput.spec.js b/tests/e2e/specs/FormInput.spec.js index 27221e4b5..3c24aa606 100644 --- a/tests/e2e/specs/FormInput.spec.js +++ b/tests/e2e/specs/FormInput.spec.js @@ -1,7 +1,7 @@ describe("Form Input", () => { const visitAndOpenAcordeon = () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); }; const dragFormInput = () => { diff --git a/tests/e2e/specs/FormSelectList.spec.js b/tests/e2e/specs/FormSelectList.spec.js index 0da8a8dfe..e54e44ca2 100644 --- a/tests/e2e/specs/FormSelectList.spec.js +++ b/tests/e2e/specs/FormSelectList.spec.js @@ -1,7 +1,7 @@ describe("Form Select List", () => { beforeEach(() => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); // Add loop control cy.get("[data-cy=controls-FormSelectList]").drag( "[data-cy=screen-drop-zone]", diff --git a/tests/e2e/specs/FormTextArea.spec.js b/tests/e2e/specs/FormTextArea.spec.js index 6f443e5fa..d8dd1a0ad 100644 --- a/tests/e2e/specs/FormTextArea.spec.js +++ b/tests/e2e/specs/FormTextArea.spec.js @@ -1,7 +1,7 @@ describe("Form Text Area Field", () => { it("Default properties", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -17,7 +17,7 @@ describe("Form Text Area Field", () => { }); it("Variable properties", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -37,7 +37,7 @@ describe("Form Text Area Field", () => { }); it("Read Only", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -58,7 +58,7 @@ describe("Form Text Area Field", () => { // Configuration it("Placeholder", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -75,7 +75,7 @@ describe("Form Text Area Field", () => { }); it("Helper Text", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -91,7 +91,7 @@ describe("Form Text Area Field", () => { }); it("Rich Text", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -107,7 +107,7 @@ describe("Form Text Area Field", () => { }); it("Rows", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -124,7 +124,7 @@ describe("Form Text Area Field", () => { }); it("Default Value", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -141,7 +141,7 @@ describe("Form Text Area Field", () => { }); it("CSS Selector Name", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -159,7 +159,7 @@ describe("Form Text Area Field", () => { }); it("Aria Label", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -176,7 +176,7 @@ describe("Form Text Area Field", () => { }); it("Tab Order", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormTextArea]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } diff --git a/tests/e2e/specs/Loop.spec.js b/tests/e2e/specs/Loop.spec.js index 11a54de3f..018e9ee12 100644 --- a/tests/e2e/specs/Loop.spec.js +++ b/tests/e2e/specs/Loop.spec.js @@ -1,7 +1,7 @@ describe("Loop control", () => { it("Input inside loop", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); // Add loop control cy.get("[data-cy=controls-FormLoop]").drag("[data-cy=screen-drop-zone]", { position: "bottom" @@ -12,7 +12,7 @@ describe("Loop control", () => { cy.get("[data-cy=inspector-add]").click(); // Add input to loop - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag( "[data-cy=screen-element-container] .column-draggable div", { position: "bottom" } @@ -75,7 +75,7 @@ describe("Loop control", () => { it("Verify validation on visible fields", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); // Add loop control cy.get("[data-cy=controls-FormLoop]").drag("[data-cy=screen-drop-zone]", { position: "bottom" @@ -85,7 +85,7 @@ describe("Loop control", () => { cy.get("[data-cy=inspector-source]").select("existing"); // Add input to loop - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag( "[data-cy=screen-element-container] .column-draggable div", { position: "bottom" } @@ -161,7 +161,7 @@ describe("Loop control", () => { cy.on("window:alert", (msg) => (alert = msg)); // Add loop control - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormLoop]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -181,7 +181,7 @@ describe("Loop control", () => { cy.get("[data-cy=inspector-conditionalHide]").clear().type('name != "foo"'); // Add input to multicolumn - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag( ".mb-1 > :nth-child(1) > .row > :nth-child(1)", { position: "bottom" } @@ -231,7 +231,7 @@ describe("Loop control", () => { cy.on("window:alert", (msg) => (alert = msg)); // Add loop contro - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormLoop]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -252,7 +252,7 @@ describe("Loop control", () => { cy.get("[data-cy=inspector-conditionalHide]").clear().type('name != "foo"'); // Add input to nested loop - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag( ".m-2 > .column-draggable > div", { position: "bottom" } @@ -345,7 +345,7 @@ describe("Loop control", () => { cy.showValidationOnLoad(); let alert = false; cy.on("window:alert", (msg) => (alert = msg)); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); // Add loop control cy.get("[data-cy=controls-FormLoop]").drag("[data-cy=screen-drop-zone]", { @@ -371,7 +371,7 @@ describe("Loop control", () => { cy.get("[data-cy=inspector-conditionalHide]").clear().type('name != "foo"'); // Add submit button - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormButton]") .contains("Submit Button") .drag("[data-cy=screen-element-container]", { position: "bottom" }); diff --git a/tests/e2e/specs/MediaQuery.spec.js b/tests/e2e/specs/MediaQuery.spec.js index c22e1943c..d4ed1fe2f 100644 --- a/tests/e2e/specs/MediaQuery.spec.js +++ b/tests/e2e/specs/MediaQuery.spec.js @@ -9,7 +9,7 @@ describe("Media Query CSS", () => { before(() => { // run these tests as if in a desktop cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/MultiColumn.spec.js b/tests/e2e/specs/MultiColumn.spec.js index 378387748..654975b89 100644 --- a/tests/e2e/specs/MultiColumn.spec.js +++ b/tests/e2e/specs/MultiColumn.spec.js @@ -1,8 +1,8 @@ describe("MultiColumns", () => { it("Configure using JSON", () => { cy.visit("/"); + cy.openAcordeon("collapse-3"); cy.openAcordeon("collapse-2"); - cy.openAcordeon("collapse-1"); cy.get("[data-cy=controls-FormMultiColumn]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -55,7 +55,7 @@ describe("MultiColumns", () => { it("Configure using columns configuration", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormMultiColumn]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -93,7 +93,7 @@ describe("MultiColumns", () => { ); cy.get("[data-cy=inspector-add-column-width]").clear().type("8"); cy.get("[data-cy=inspector-add-column-modal] button.btn-primary").click(); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag( "[data-cy=screen-element-container] .column-draggable:empty" ); diff --git a/tests/e2e/specs/NestedScreen.spec.js b/tests/e2e/specs/NestedScreen.spec.js index 96c91524f..b5eee604a 100644 --- a/tests/e2e/specs/NestedScreen.spec.js +++ b/tests/e2e/specs/NestedScreen.spec.js @@ -80,7 +80,7 @@ describe("Nested screen", () => { it("Without a variable defined", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormNestedScreen]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } diff --git a/tests/e2e/specs/Pagination.spec.js b/tests/e2e/specs/Pagination.spec.js index 20e16884e..6ce8d6712 100644 --- a/tests/e2e/specs/Pagination.spec.js +++ b/tests/e2e/specs/Pagination.spec.js @@ -56,8 +56,8 @@ const data = { beforeEach(() => { cy.visit("/"); + cy.openAcordeon("collapse-3"); cy.openAcordeon("collapse-2"); - cy.openAcordeon("collapse-1"); cy.wait(200); cy.get("[data-cy=controls-FormRecordList]").drag( "[data-cy=screen-drop-zone]", diff --git a/tests/e2e/specs/ResponsivePreview.spec.js b/tests/e2e/specs/ResponsivePreview.spec.js index 01573e5fc..6cf1980b8 100644 --- a/tests/e2e/specs/ResponsivePreview.spec.js +++ b/tests/e2e/specs/ResponsivePreview.spec.js @@ -10,7 +10,7 @@ describe("Responsive Preview test", () => { beforeEach(() => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get(controlInputSelector).drag(screenDropZoneSelector, { position: "bottom" }); diff --git a/tests/e2e/specs/RichText.spec.js b/tests/e2e/specs/RichText.spec.js index 46c701651..19fafecc4 100644 --- a/tests/e2e/specs/RichText.spec.js +++ b/tests/e2e/specs/RichText.spec.js @@ -1,7 +1,7 @@ describe("Rich Text control", () => { it("Rich text with mustache", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormHtmlViewer]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -21,7 +21,7 @@ describe("Rich Text control", () => { it("Rich text render HTML from a Variable", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormHtmlViewer]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } diff --git a/tests/e2e/specs/ScreenTemplateSection.spec.js b/tests/e2e/specs/ScreenTemplateSection.spec.js index 1155fffae..7eff4e347 100644 --- a/tests/e2e/specs/ScreenTemplateSection.spec.js +++ b/tests/e2e/specs/ScreenTemplateSection.spec.js @@ -109,7 +109,7 @@ it("Displays Shared Templates when Shared Templates button is clicked", () => { }); }); -it("Is hidden when an Inspector Panel should open", () => { +it.only("Is hidden when an Inspector Panel should open", () => { cy.visit("/"); cy.get("[data-cy=screen-templates]").click(); @@ -118,7 +118,7 @@ it("Is hidden when an Inspector Panel should open", () => { ); cy.setPreviewDataInput({ name: "" }); - cy.openAcordeon("collapse-1"); + cy.openAcordeonByLabel("Input Fields"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/ScreenWarnings.spec.js b/tests/e2e/specs/ScreenWarnings.spec.js index 57851014c..43e71d2a2 100644 --- a/tests/e2e/specs/ScreenWarnings.spec.js +++ b/tests/e2e/specs/ScreenWarnings.spec.js @@ -18,7 +18,7 @@ describe("Screen Warnings", () => { }); it("Use script warning", () => { - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/SelectListDependentCollection.spec.js b/tests/e2e/specs/SelectListDependentCollection.spec.js index 9bd71508d..b4b0a1683 100644 --- a/tests/e2e/specs/SelectListDependentCollection.spec.js +++ b/tests/e2e/specs/SelectListDependentCollection.spec.js @@ -79,7 +79,7 @@ describe("select list dependent collection", () => { }); it("Configure collection select list", () => { - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormSelectList]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } diff --git a/tests/e2e/specs/UndoRedo.spec.js b/tests/e2e/specs/UndoRedo.spec.js index 803bd13ca..604a78b60 100644 --- a/tests/e2e/specs/UndoRedo.spec.js +++ b/tests/e2e/specs/UndoRedo.spec.js @@ -1,7 +1,7 @@ describe("Undo and Redo", () => { it("Can Undo", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -14,7 +14,7 @@ describe("Undo and Redo", () => { it("Can Redo", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/VariableNames.js b/tests/e2e/specs/VariableNames.js index 7834bce9c..0505431f9 100644 --- a/tests/e2e/specs/VariableNames.js +++ b/tests/e2e/specs/VariableNames.js @@ -1,7 +1,7 @@ describe("Default values", () => { it("Variable names with dots 2 levels", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -16,7 +16,7 @@ describe("Default values", () => { }); it("Variable names with dots 3 levels", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -36,7 +36,7 @@ describe("Default values", () => { }); it("Variable names with dots and one attribute same as the name", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/VisibilityRule.spec.js b/tests/e2e/specs/VisibilityRule.spec.js index b02b05975..76254f7b6 100644 --- a/tests/e2e/specs/VisibilityRule.spec.js +++ b/tests/e2e/specs/VisibilityRule.spec.js @@ -2,7 +2,7 @@ describe("Default values", () => { it("Check visible", () => { cy.visit("/"); cy.setPreviewDataInput({ name: "world" }); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -17,7 +17,7 @@ describe("Default values", () => { it("Check hidden", () => { cy.visit("/"); cy.setPreviewDataInput({ name: "" }); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -32,7 +32,7 @@ describe("Default values", () => { it("Check dynamic visibility rule", () => { cy.visit("/"); cy.setPreviewDataInput({ name: "" }); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/Watchers.spec.js b/tests/e2e/specs/Watchers.spec.js index d7a064ba2..b64d295ea 100644 --- a/tests/e2e/specs/Watchers.spec.js +++ b/tests/e2e/specs/Watchers.spec.js @@ -64,7 +64,7 @@ describe("Watchers", () => { it.skip("CRUD of watchers", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -144,7 +144,7 @@ describe("Watchers", () => { }); it("Test cancel", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -161,13 +161,13 @@ describe("Watchers", () => { }); it("Test variables in multi columns", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormMultiColumn]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } ); cy.get("[data-cy=screen-element-container]").click(); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag( "[data-cy=screen-element-container] .column-draggable", { position: "bottom" } @@ -181,7 +181,7 @@ describe("Watchers", () => { it("Test variables in nested screens", () => { cy.visit("/"); - cy.openAcordeon("collapse-2"); + cy.openAcordeon("collapse-3"); cy.get("[data-cy=controls-FormNestedScreen]").drag( "[data-cy=screen-drop-zone]", { position: "bottom" } @@ -202,7 +202,7 @@ describe("Watchers", () => { it("Create duplicated properties", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -265,7 +265,7 @@ describe("Watchers", () => { ); cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -349,7 +349,7 @@ describe("Watchers", () => { ); cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -408,7 +408,7 @@ describe("Watchers", () => { }); cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -557,7 +557,7 @@ describe("Watchers", () => { }); it("Focuses the first field that has an error", () => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/specs/WatchersBypass.spec.js b/tests/e2e/specs/WatchersBypass.spec.js index 4cf91e60c..77913d3f5 100644 --- a/tests/e2e/specs/WatchersBypass.spec.js +++ b/tests/e2e/specs/WatchersBypass.spec.js @@ -74,7 +74,7 @@ describe("Watchers", () => { Cypress.Commands.add('setupFormInput', (inputName) => { cy.visit("/"); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-element-container]", { position: "top" }); cy.get("[data-cy=screen-element-container]").last().click(); diff --git a/tests/e2e/specs/WatchersDragAndDrop.spec.js b/tests/e2e/specs/WatchersDragAndDrop.spec.js index 628ffc28b..f8d881802 100644 --- a/tests/e2e/specs/WatchersDragAndDrop.spec.js +++ b/tests/e2e/specs/WatchersDragAndDrop.spec.js @@ -143,7 +143,7 @@ describe('Watchers list Drag&Drop', () => { }, }); - cy.openAcordeon('collapse-1'); + cy.openAcordeon('collapse-2'); cy.get('[data-cy=controls-FormInput]').drag('[data-cy=screen-drop-zone]', { position: 'bottom', }); diff --git a/tests/e2e/specs/WrongConfigurationErrors.js b/tests/e2e/specs/WrongConfigurationErrors.js index aa0e9d032..56f3a1f7f 100644 --- a/tests/e2e/specs/WrongConfigurationErrors.js +++ b/tests/e2e/specs/WrongConfigurationErrors.js @@ -6,7 +6,7 @@ describe.skip("Wrong Configuration Errors", () => { cy.stub(win.console, "error").as("consoleError"); } }); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); @@ -27,7 +27,7 @@ describe.skip("Wrong Configuration Errors", () => { cy.stub(win.console, "error").as("consoleError"); } }); - cy.openAcordeon("collapse-1"); + cy.openAcordeon("collapse-2"); cy.get("[data-cy=controls-FormInput]").drag("[data-cy=screen-drop-zone]", { position: "bottom" }); diff --git a/tests/e2e/support/commands.js b/tests/e2e/support/commands.js index 8e833dc02..48e2910cb 100644 --- a/tests/e2e/support/commands.js +++ b/tests/e2e/support/commands.js @@ -286,8 +286,15 @@ Cypress.Commands.add("openAcordeon", (name) => { force: true }); }); +Cypress.Commands.add("openAcordeonByLabel", (label) => { + cy.get(`button`).contains(label).click({ + waitForAnimations: true, + force: true + }); +}); Cypress.Commands.add("openAllAcordeon", () => { + cy.openAcordeon("collapse-6"); cy.openAcordeon("collapse-5"); cy.openAcordeon("collapse-4"); cy.openAcordeon("collapse-3");