import { errorToast, successToast } from '../pages/notifications'; /** * Getters */ export function getPersonalProjectMenuItem() { return cy.getByTestId('project-personal-menu-item'); } export function getOverviewMenuItem() { return cy.getByTestId('menu-item').contains('Overview'); } export function getAddResourceDropdown() { return cy.getByTestId('add-resource'); } export function getFolderCards() { return cy.getByTestId('folder-card'); } export function getFolderCard(name: string) { return cy.getByTestId('folder-card-name').contains(name).closest('[data-test-id="folder-card"]'); } export function getWorkflowCards() { return cy.getByTestId('resources-list-item-workflow'); } export function getWorkflowCard(name: string) { return cy .getByTestId('workflow-card-name') .contains(name) .closest('[data-test-id="resources-list-item-workflow"]'); } export function getWorkflowCardActions(name: string) { return getWorkflowCard(name).find('[data-test-id="workflow-card-actions"]'); } export function getWorkflowCardActionItem(workflowName: string, actionName: string) { return getWorkflowCardActions(workflowName) .find('span[aria-controls]') .invoke('attr', 'aria-controls') .then((popperId) => { return cy.get(`#${popperId}`).find(`[data-test-id="action-${actionName}"]`); }); } export function getDuplicateWorkflowModal() { return cy.getByTestId('duplicate-modal'); } export function getWorkflowMenu() { return cy.getByTestId('workflow-menu'); } export function getAddFolderButton() { return cy.getByTestId('add-folder-button'); } export function getListBreadcrumbs() { return cy.getByTestId('main-breadcrumbs'); } export function getHomeProjectBreadcrumb() { return getListBreadcrumbs().findChildByTestId('home-project'); } export function getListBreadcrumbItem(name: string) { return getListBreadcrumbs().findChildByTestId('breadcrumbs-item').contains(name); } export function getVisibleListBreadcrumbs() { return getListBreadcrumbs().findChildByTestId('breadcrumbs-item'); } export function getCurrentBreadcrumb() { return getListBreadcrumbs().findChildByTestId('breadcrumbs-item-current').find('input'); } export function getCurrentBreadcrumbText() { return getCurrentBreadcrumb().invoke('val'); } export function getMainBreadcrumbsEllipsis() { return getListBreadcrumbs().findChildByTestId('hidden-items-menu'); } export function getMainBreadcrumbsEllipsisMenuItems() { return cy .getByTestId('hidden-items-menu') .find('span[aria-controls]') .invoke('attr', 'aria-controls') .then((popperId) => { return cy.get(`#${popperId}`).find('li'); }); } export function getFolderCardBreadCrumbs(folderName: string) { return getFolderCard(folderName).find('[data-test-id="folder-card-breadcrumbs"]'); } export function getFolderCardBreadCrumbsEllipsis(folderName: string) { return getFolderCardBreadCrumbs(folderName).find('[data-test-id="ellipsis"]'); } export function getFolderCardHomeProjectBreadcrumb(folderName: string) { return getFolderCardBreadCrumbs(folderName).find('[data-test-id="folder-card-home-project"]'); } export function getFolderCardCurrentBreadcrumb(folderName: string) { return getFolderCardBreadCrumbs(folderName).find('[data-test-id="breadcrumbs-item-current"]'); } export function getOpenHiddenItemsTooltip() { return cy.getByTestId('hidden-items-tooltip').filter(':visible'); } export function getListActionsToggle() { return cy.getByTestId('folder-breadcrumbs-actions'); } export function getCanvasBreadcrumbs() { cy.getByTestId('canvas-breadcrumbs').should('exist'); return cy.getByTestId('canvas-breadcrumbs').findChildByTestId('folder-breadcrumbs'); } export function getListActionItem(name: string) { return cy .getByTestId('folder-breadcrumbs-actions') .find('span[aria-controls]') .invoke('attr', 'aria-controls') .then((popperId) => { return cy.get(`#${popperId}`).find(`[data-test-id="action-${name}"]`); }); } export function getInlineEditInput() { return cy.getByTestId('inline-edit-input'); } export function getFolderCardActionToggle(folderName: string) { return getFolderCard(folderName).find('[data-test-id="folder-card-actions"]'); } export function getFolderCardActionItem(folderName: string, actionName: string) { return getFolderCard(folderName) .findChildByTestId('folder-card-actions') .filter(':visible') .find('span[aria-controls]') .invoke('attr', 'aria-controls') .then((popperId) => { return cy.get(`#${popperId}`).find(`[data-test-id="action-${actionName}"]`); }); } export function getFolderDeleteModal() { return cy.getByTestId('deleteFolder-modal'); } export function getMoveFolderModal() { return cy.getByTestId('moveFolder-modal'); } export function getDeleteRadioButton() { return cy.getByTestId('delete-content-radio'); } export function getTransferContentRadioButton() { return cy.getByTestId('transfer-content-radio'); } export function getConfirmDeleteInput() { return getFolderDeleteModal().findChildByTestId('delete-data-input').find('input'); } export function getDeleteFolderModalConfirmButton() { return getFolderDeleteModal().findChildByTestId('confirm-delete-folder-button'); } export function getProjectEmptyState() { return cy.getByTestId('list-empty-state'); } export function getFolderEmptyState() { return cy.getByTestId('empty-folder-container'); } export function getProjectMenuItem(name: string) { if (name.toLowerCase() === 'personal') { return getPersonalProjectMenuItem(); } return cy.getByTestId('project-menu-item').contains(name); } export function getMoveToFolderDropdown() { return cy.getByTestId('move-to-folder-dropdown'); } export function getMoveToFolderOption(name: string) { return cy.getByTestId('move-to-folder-option').contains(name); } export function getMoveToFolderInput() { return getMoveToFolderDropdown().find('input'); } export function getProjectSharingInput() { return cy.getByTestId('project-sharing-select'); } export function getProjectSharingOption(name: string) { return cy.getByTestId('project-sharing-info').contains(name); } export function getEmptyFolderDropdownMessage(text: string) { return cy.get('.el-select-dropdown__empty').contains(text); } export function getMoveFolderConfirmButton() { return cy.getByTestId('confirm-move-folder-button'); } export function getMoveWorkflowModal() { return cy.getByTestId('moveFolder-modal'); } export function getWorkflowCardBreadcrumbs(workflowName: string) { return getWorkflowCard(workflowName).find('[data-test-id="workflow-card-breadcrumbs"]'); } export function getWorkflowCardBreadcrumbsEllipsis(workflowName: string) { return getWorkflowCardBreadcrumbs(workflowName).find('[data-test-id="ellipsis"]'); } export function getNewFolderNameInput() { return cy.get('.add-folder-modal').filter(':visible').find('input.el-input__inner'); } export function getNewFolderModalErrorMessage() { return cy.get('.el-message-box__errormsg').filter(':visible'); } export function getProjectTab(tabId: string) { return cy.getByTestId('project-tabs').find(`#${tabId}`); } /** * Actions */ export function goToPersonalProject() { getPersonalProjectMenuItem().click(); } export function createFolderInsideFolder(childName: string, parentName: string) { getFolderCard(parentName).click(); createFolderFromListHeaderButton(childName); } export function createFolderFromListHeaderButton(folderName: string) { getAddFolderButton().click(); createNewFolder(folderName); } export function createWorkflowFromEmptyState(workflowName?: string) { getFolderEmptyState().find('button').contains('Create Workflow').click(); if (workflowName) { cy.getByTestId('workflow-name-input').type(`{selectAll}{backspace}${workflowName}`, { delay: 50, }); } cy.getByTestId('workflow-save-button').click(); successToast().should('exist'); } export function createWorkflowFromProjectHeader(folderName?: string, workflowName?: string) { cy.getByTestId('add-resource-workflow').click(); if (workflowName) { cy.getByTestId('workflow-name-input').type(`{selectAll}{backspace}${workflowName}`, { delay: 50, }); } cy.getByTestId('workflow-save-button').click(); if (folderName) { successToast().should( 'contain.text', `Workflow successfully created in "Personal", within "${folderName}"`, ); } } export function createWorkflowFromListDropdown(workflowName?: string) { getListActionsToggle().click(); getListActionItem('create_workflow').click(); if (workflowName) { cy.getByTestId('workflow-name-input').type(`{selectAll}{backspace}${workflowName}`, { delay: 50, }); } cy.getByTestId('workflow-save-button').click(); successToast().should('exist'); } export function createFolderFromProjectHeader(folderName: string) { getAddResourceDropdown().click(); cy.getByTestId('action-folder').click(); createNewFolder(folderName); } export function createFolderFromListDropdown(folderName: string) { getListActionsToggle().click(); getListActionItem('create').click(); createNewFolder(folderName); } export function createFolderFromCardActions(parentName: string, folderName: string) { getFolderCardActionToggle(parentName).click(); getFolderCardActionItem(parentName, 'create').click(); createNewFolder(folderName); } export function renameFolderFromListActions(folderName: string, newName: string) { getFolderCard(folderName).click(); getListActionsToggle().click(); getListActionItem('rename').click(); getInlineEditInput().should('be.visible'); getInlineEditInput().type(`${newName}{enter}`, { delay: 50 }); successToast().should('exist'); } export function renameFolderFromCardActions(folderName: string, newName: string) { getFolderCardActionToggle(folderName).click(); getFolderCardActionItem(folderName, 'rename').click(); renameFolder(newName); } export function duplicateWorkflowFromCardActions(workflowName: string, duplicateName: string) { getWorkflowCardActions(workflowName).click(); getWorkflowCardActionItem(workflowName, 'duplicate').click(); getDuplicateWorkflowModal().find('input').first().type('{selectall}'); getDuplicateWorkflowModal().find('input').first().type(duplicateName); getDuplicateWorkflowModal().find('button').contains('Duplicate').click(); errorToast().should('not.exist'); } export function duplicateWorkflowFromWorkflowPage(duplicateName: string) { getWorkflowMenu().click(); cy.getByTestId('workflow-menu-item-duplicate').click(); getDuplicateWorkflowModal().find('input').first().type('{selectall}'); getDuplicateWorkflowModal().find('input').first().type(duplicateName); getDuplicateWorkflowModal().find('button').contains('Duplicate').click(); errorToast().should('not.exist'); } export function deleteEmptyFolderFromCardDropdown(folderName: string) { cy.intercept('DELETE', '/rest/projects/**').as('deleteFolder'); getFolderCard(folderName).click(); getListActionsToggle().click(); getListActionItem('delete').click(); cy.wait('@deleteFolder'); successToast().should('contain.text', 'Folder deleted'); } export function deleteEmptyFolderFromListDropdown(folderName: string) { cy.intercept('DELETE', '/rest/projects/**').as('deleteFolder'); getFolderCard(folderName).click(); getListActionsToggle().click(); getListActionItem('delete').click(); cy.wait('@deleteFolder'); successToast().should('contain.text', 'Folder deleted'); } export function deleteFolderWithContentsFromListDropdown(folderName: string) { getListActionsToggle().click(); getListActionItem('delete').click(); confirmFolderDelete(folderName); } export function deleteFolderWithContentsFromCardDropdown(folderName: string) { getFolderCardActionToggle(folderName).click(); getFolderCardActionItem(folderName, 'delete').click(); confirmFolderDelete(folderName); } export function deleteAndTransferFolderContentsFromCardDropdown( folderName: string, destinationName: string, ) { getFolderCardActionToggle(folderName).click(); getFolderCardActionItem(folderName, 'delete').click(); deleteFolderAndMoveContents(folderName, destinationName); } export function deleteAndTransferFolderContentsFromListDropdown(destinationName: string) { getListActionsToggle().click(); getListActionItem('delete').click(); getCurrentBreadcrumbText().then((currentFolderName) => { deleteFolderAndMoveContents(String(currentFolderName), destinationName); }); } export function createNewProject(projectName: string, options: { openAfterCreate?: boolean } = {}) { cy.getByTestId('universal-add').should('exist').click(); cy.getByTestId('navigation-menu-item').contains('Project').click(); cy.getByTestId('project-settings-name-input').type(projectName, { delay: 50 }); cy.getByTestId('project-settings-save-button').click(); successToast().should('exist'); if (options.openAfterCreate) { getProjectMenuItem(projectName).click(); } } export function moveFolderFromFolderCardActions(folderName: string, destinationName: string) { getFolderCardActionToggle(folderName).click(); getFolderCardActionItem(folderName, 'move').click(); moveFolder(folderName, destinationName); } export function moveFolderFromListActions(folderName: string, destinationName: string) { getFolderCard(folderName).click(); getListActionsToggle().click(); getListActionItem('move').click(); moveFolder(folderName, destinationName); } export function moveWorkflowToFolder(workflowName: string, folderName: string) { getWorkflowCardActions(workflowName).click(); getWorkflowCardActionItem(workflowName, 'moveToFolder').click(); getMoveFolderModal().should('be.visible'); getMoveToFolderDropdown().click(); getMoveToFolderInput().type(folderName, { delay: 50 }); getMoveToFolderOption(folderName).should('be.visible').click(); getMoveFolderConfirmButton().should('be.enabled').click(); } export function dragAndDropToFolder(sourceName: string, destinationName: string) { const draggable = `[data-test-id=draggable]:has([data-resourcename="${sourceName}"])`; const droppable = `[data-test-id=draggable]:has([data-resourcename="${destinationName}"])`; cy.get(draggable).trigger('mousedown'); cy.draganddrop(draggable, droppable, { position: 'center' }); } export function dragAndDropToProjectRoot(sourceName: string) { const draggable = `[data-test-id=draggable]:has([data-resourcename="${sourceName}"])`; const droppable = '[data-test-id="home-project"]'; cy.get(draggable).trigger('mousedown'); cy.draganddrop(draggable, droppable, { position: 'center' }); } /** * Utils */ /** * Types folder name in the prompt and waits for the folder to be created * @param name */ function createNewFolder(name: string) { cy.intercept('POST', '/rest/projects/**').as('createFolder'); cy.get('[role=dialog]') .filter(':visible') .within(() => { cy.get('input.el-input__inner').type(name, { delay: 50 }); cy.get('button.btn--confirm').click(); }); cy.wait('@createFolder'); successToast().should('exist'); } function renameFolder(newName: string) { cy.intercept('PATCH', '/rest/projects/**').as('renameFolder'); cy.get('[role=dialog]') .filter(':visible') .within(() => { cy.get('input.el-input__inner').type('{selectall}'); cy.get('input.el-input__inner').type(newName, { delay: 50 }); cy.get('button.btn--confirm').click(); }); cy.wait('@renameFolder'); successToast().should('exist'); } function confirmFolderDelete(folderName: string) { cy.intercept('DELETE', '/rest/projects/**').as('deleteFolder'); getFolderDeleteModal().should('be.visible'); getDeleteRadioButton().click(); getConfirmDeleteInput().should('be.visible'); getConfirmDeleteInput().type(`delete ${folderName}`, { delay: 50 }); getDeleteFolderModalConfirmButton().should('be.enabled').click(); cy.wait('@deleteFolder'); successToast().contains('Folder deleted').should('exist'); } function deleteFolderAndMoveContents(folderName: string, destinationName: string) { cy.intercept('DELETE', '/rest/projects/**').as('deleteFolder'); getFolderDeleteModal().should('be.visible'); getFolderDeleteModal().find('h1').first().contains(`Delete "${folderName}"`); getTransferContentRadioButton().should('be.visible').click(); getMoveToFolderDropdown().click(); getMoveToFolderInput().type(destinationName); getMoveToFolderOption(destinationName).click(); getDeleteFolderModalConfirmButton().should('be.enabled').click(); cy.wait('@deleteFolder'); successToast().should('contain.text', `Data transferred to "${destinationName}"`); } function moveFolder(folderName: string, destinationName: string) { cy.intercept('PATCH', '/rest/projects/**').as('moveFolder'); getMoveFolderModal().should('be.visible'); getMoveFolderModal().find('h1').first().contains(`Move folder ${folderName}`); // The dropdown focuses after a small delay (once modal's slide in animation is done). // On the component we listen for an event, but here the wait should be very predictable. cy.wait(500); // Try to find current folder in the dropdown // This tests that auto-focus worked as expected cy.focused().type(folderName, { delay: 50 }); // Should not be available getEmptyFolderDropdownMessage('No folders found').should('exist'); // Select destination folder getMoveToFolderInput().type(`{selectall}{backspace}${destinationName}`, { delay: 50, }); getMoveToFolderOption(destinationName).should('be.visible').click(); getMoveFolderConfirmButton().should('be.enabled').click(); cy.wait('@moveFolder'); } export function transferWorkflow( workflowName: string, projectName: string, destinationFolder?: string, ) { getMoveFolderModal().should('be.visible'); getMoveFolderModal().find('h1').first().contains(`Move workflow ${workflowName}`); cy.wait(500); getProjectSharingInput().should('be.visible').click(); cy.focused().type(projectName, { delay: 50 }); getProjectSharingOption(projectName).should('be.visible').click(); if (destinationFolder) { getMoveToFolderInput().click(); // Select destination folder cy.focused().type(destinationFolder, { delay: 50 }); getMoveToFolderOption(destinationFolder).should('be.visible').click(); } getMoveFolderConfirmButton().should('be.enabled').click(); }