mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 09:36:44 +00:00
fix(editor): Addressing internal testing feedback for folders (no-changelog) (#13997)
This commit is contained in:
committed by
GitHub
parent
305ea0fb32
commit
1f56a24bbd
@@ -22,6 +22,31 @@ export function getFolderCards() {
|
||||
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 getAddFolderButton() {
|
||||
return cy.getByTestId('add-folder-button');
|
||||
}
|
||||
@@ -34,6 +59,10 @@ 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');
|
||||
}
|
||||
@@ -94,13 +123,14 @@ export function getFolderCardActionToggle(folderName: string) {
|
||||
return getFolderCard(folderName).find('[data-test-id="folder-card-actions"]');
|
||||
}
|
||||
|
||||
export function getFolderCardActionItem(name: string) {
|
||||
return cy
|
||||
.getByTestId('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-${name}"]`);
|
||||
return cy.get(`#${popperId}`).find(`[data-test-id="action-${actionName}"]`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -108,10 +138,18 @@ 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');
|
||||
}
|
||||
@@ -119,6 +157,61 @@ export function getConfirmDeleteInput() {
|
||||
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 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');
|
||||
}
|
||||
/**
|
||||
* Actions
|
||||
*/
|
||||
@@ -136,8 +229,46 @@ export function createFolderFromListHeaderButton(folderName: string) {
|
||||
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) {
|
||||
getPersonalProjectMenuItem().click();
|
||||
getAddResourceDropdown().click();
|
||||
cy.getByTestId('action-folder').click();
|
||||
createNewFolder(folderName);
|
||||
@@ -151,7 +282,7 @@ export function createFolderFromListDropdown(folderName: string) {
|
||||
|
||||
export function createFolderFromCardActions(parentName: string, folderName: string) {
|
||||
getFolderCardActionToggle(parentName).click();
|
||||
getFolderCardActionItem('create').click();
|
||||
getFolderCardActionItem(parentName, 'create').click();
|
||||
createNewFolder(folderName);
|
||||
}
|
||||
|
||||
@@ -164,7 +295,7 @@ export function renameFolderFromListActions(folderName: string, newName: string)
|
||||
|
||||
export function renameFolderFromCardActions(folderName: string, newName: string) {
|
||||
getFolderCardActionToggle(folderName).click();
|
||||
getFolderCardActionItem('rename').click();
|
||||
getFolderCardActionItem(folderName, 'rename').click();
|
||||
renameFolder(newName);
|
||||
}
|
||||
|
||||
@@ -194,9 +325,63 @@ export function deleteFolderWithContentsFromListDropdown(folderName: string) {
|
||||
|
||||
export function deleteFolderWithContentsFromCardDropdown(folderName: string) {
|
||||
getFolderCardActionToggle(folderName).click();
|
||||
getFolderCardActionItem('delete').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();
|
||||
getCurrentBreadcrumb()
|
||||
.find('span')
|
||||
.invoke('text')
|
||||
.then((currentFolderName) => {
|
||||
deleteFolderAndMoveContents(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();
|
||||
}
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
@@ -240,3 +425,34 @@ function confirmFolderDelete(folderName: string) {
|
||||
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 "${folderName}" to another folder`);
|
||||
getMoveToFolderDropdown().click();
|
||||
// Try to find current folder in the dropdown
|
||||
getMoveToFolderInput().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');
|
||||
}
|
||||
|
||||
@@ -105,11 +105,13 @@ export function getNodeOutputHint() {
|
||||
}
|
||||
|
||||
export function getWorkflowCards() {
|
||||
return cy.getByTestId('resources-list-item');
|
||||
return cy.getByTestId('resources-list-item-workflow');
|
||||
}
|
||||
|
||||
export function getWorkflowCard(workflowName: string) {
|
||||
return getWorkflowCards().contains(workflowName).parents('[data-test-id="resources-list-item"]');
|
||||
return getWorkflowCards()
|
||||
.contains(workflowName)
|
||||
.parents('[data-test-id="resources-list-item-workflow"]');
|
||||
}
|
||||
|
||||
export function getWorkflowCardContent(workflowName: string) {
|
||||
|
||||
@@ -21,7 +21,7 @@ const switchBetweenEditorAndWorkflowlist = () => {
|
||||
cy.getByTestId('menu-item').first().click();
|
||||
cy.wait(['@getUsers', '@getWorkflows', '@getActiveWorkflows', '@getProjects']);
|
||||
|
||||
cy.getByTestId('resources-list-item').first().click();
|
||||
cy.getByTestId('resources-list-item-workflow').first().click();
|
||||
|
||||
workflowPage.getters.canvasNodes().first().should('be.visible');
|
||||
workflowPage.getters.canvasNodes().last().should('be.visible');
|
||||
|
||||
@@ -514,7 +514,7 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
||||
workflowsPage.getters.workflowCards().should('have.length', 3);
|
||||
workflowsPage.getters
|
||||
.workflowCards()
|
||||
.filter(':has(.n8n-badge:contains("Project"))')
|
||||
.filter(':has([data-test-id="workflow-card-breadcrumbs"]:contains("Project"))')
|
||||
.should('have.length', 2);
|
||||
workflowsPage.getters.workflowCardActions('Workflow in Home project').click();
|
||||
workflowsPage.getters.workflowMoveButton().click();
|
||||
|
||||
@@ -4,6 +4,12 @@ import {
|
||||
createFolderFromListHeaderButton,
|
||||
createFolderFromProjectHeader,
|
||||
createFolderInsideFolder,
|
||||
createNewProject,
|
||||
createWorkflowFromEmptyState,
|
||||
createWorkflowFromListDropdown,
|
||||
createWorkflowFromProjectHeader,
|
||||
deleteAndTransferFolderContentsFromCardDropdown,
|
||||
deleteAndTransferFolderContentsFromListDropdown,
|
||||
deleteEmptyFolderFromCardDropdown,
|
||||
deleteEmptyFolderFromListDropdown,
|
||||
deleteFolderWithContentsFromCardDropdown,
|
||||
@@ -14,14 +20,27 @@ import {
|
||||
getFolderCardActionItem,
|
||||
getFolderCardActionToggle,
|
||||
getFolderCards,
|
||||
getFolderEmptyState,
|
||||
getHomeProjectBreadcrumb,
|
||||
getListBreadcrumbItem,
|
||||
getListBreadcrumbs,
|
||||
getMainBreadcrumbsEllipsis,
|
||||
getMainBreadcrumbsEllipsisMenuItems,
|
||||
getNewFolderModalErrorMessage,
|
||||
getNewFolderNameInput,
|
||||
getOverviewMenuItem,
|
||||
getPersonalProjectMenuItem,
|
||||
getProjectEmptyState,
|
||||
getProjectMenuItem,
|
||||
getVisibleListBreadcrumbs,
|
||||
getWorkflowCard,
|
||||
getWorkflowCardBreadcrumbs,
|
||||
getWorkflowCardBreadcrumbsEllipsis,
|
||||
getWorkflowCards,
|
||||
goToPersonalProject,
|
||||
moveFolderFromFolderCardActions,
|
||||
moveFolderFromListActions,
|
||||
moveWorkflowToFolder,
|
||||
renameFolderFromCardActions,
|
||||
renameFolderFromListActions,
|
||||
} from '../composables/folders';
|
||||
@@ -44,6 +63,7 @@ describe('Folders', () => {
|
||||
|
||||
describe('Create and navigate folders', () => {
|
||||
it('should create folder from the project header', () => {
|
||||
getPersonalProjectMenuItem().click();
|
||||
createFolderFromProjectHeader('My Folder');
|
||||
getFolderCards().should('have.length.greaterThan', 0);
|
||||
// Clicking on the success toast should navigate to the folder
|
||||
@@ -51,6 +71,33 @@ describe('Folders', () => {
|
||||
getCurrentBreadcrumb().should('contain.text', 'My Folder');
|
||||
});
|
||||
|
||||
it('should not allow illegal folder names', () => {
|
||||
// Validation logic is thoroughly tested in unit tests
|
||||
// Here we just make sure everything is working in the full UI
|
||||
const ILLEGAL_CHARACTERS_NAME = 'hello[';
|
||||
const ONLY_DOTS_NAME = '...';
|
||||
const REGULAR_NAME = 'My Folder';
|
||||
|
||||
getPersonalProjectMenuItem().click();
|
||||
getAddResourceDropdown().click();
|
||||
cy.getByTestId('action-folder').click();
|
||||
getNewFolderNameInput().type(ILLEGAL_CHARACTERS_NAME, { delay: 50 });
|
||||
getNewFolderModalErrorMessage().should(
|
||||
'contain.text',
|
||||
'Folder name cannot contain the following characters',
|
||||
);
|
||||
getNewFolderNameInput().clear();
|
||||
getNewFolderNameInput().type(ONLY_DOTS_NAME, { delay: 50 });
|
||||
getNewFolderModalErrorMessage().should(
|
||||
'contain.text',
|
||||
'Folder name cannot contain only dots',
|
||||
);
|
||||
getNewFolderNameInput().clear();
|
||||
getNewFolderModalErrorMessage().should('contain.text', 'Folder name cannot be empty');
|
||||
getNewFolderNameInput().type(REGULAR_NAME, { delay: 50 });
|
||||
getNewFolderModalErrorMessage().should('not.exist');
|
||||
});
|
||||
|
||||
it('should create folder from the list header button', () => {
|
||||
goToPersonalProject();
|
||||
// First create a folder so list appears
|
||||
@@ -78,9 +125,9 @@ describe('Folders', () => {
|
||||
getFolderCard('Created from card dropdown').should('exist');
|
||||
createFolderFromCardActions('Created from card dropdown', 'Child Folder');
|
||||
successToast().should('exist');
|
||||
// Open parent folder to see the new child folder
|
||||
getFolderCard('Created from card dropdown').click();
|
||||
// Should be automatically navigated to the new folder
|
||||
getFolderCard('Child Folder').should('exist');
|
||||
getCurrentBreadcrumb().should('contain.text', 'Created from card dropdown');
|
||||
});
|
||||
|
||||
it('should navigate folders using breadcrumbs and dropdown menu', () => {
|
||||
@@ -88,7 +135,7 @@ describe('Folders', () => {
|
||||
createFolderFromProjectHeader('Navigate Test');
|
||||
// Open folder using menu item
|
||||
getFolderCardActionToggle('Navigate Test').click();
|
||||
getFolderCardActionItem('open').click();
|
||||
getFolderCardActionItem('Navigate Test', 'open').click();
|
||||
getCurrentBreadcrumb().should('contain.text', 'Navigate Test');
|
||||
// Create new child folder and navigate to it
|
||||
createFolderFromListHeaderButton('Child Folder');
|
||||
@@ -165,12 +212,72 @@ describe('Folders', () => {
|
||||
|
||||
// In personal, we should see previously created folders
|
||||
getPersonalProjectMenuItem().click();
|
||||
getAddResourceDropdown().click();
|
||||
cy.getByTestId('action-folder').should('exist');
|
||||
createFolderFromProjectHeader('Personal Folder');
|
||||
getFolderCards().should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Empty State', () => {
|
||||
it('should show project empty state when no folders exist', () => {
|
||||
createNewProject('Test empty project', { openAfterCreate: true });
|
||||
getProjectEmptyState().should('exist');
|
||||
});
|
||||
|
||||
it('should toggle folder empty state correctly', () => {
|
||||
createNewProject('Test empty folder', { openAfterCreate: true });
|
||||
createFolderFromProjectHeader('My Folder');
|
||||
getProjectEmptyState().should('not.exist');
|
||||
getFolderCard('My Folder').should('exist');
|
||||
getFolderCard('My Folder').click();
|
||||
getFolderEmptyState().should('exist');
|
||||
// Create a new workflow from the empty state
|
||||
createWorkflowFromEmptyState('My Workflow');
|
||||
// Toast should inform that the workflow was created in the folder
|
||||
successToast().should(
|
||||
'contain.text',
|
||||
'Workflow successfully created in "Test empty folder", within "My Folder"',
|
||||
);
|
||||
// Go back to the folder
|
||||
getProjectMenuItem('Test empty folder').click();
|
||||
getFolderCard('My Folder').should('exist');
|
||||
getFolderCard('My Folder').click();
|
||||
// Should not show empty state anymore
|
||||
getFolderEmptyState().should('not.exist');
|
||||
getWorkflowCards().should('have.length.greaterThan', 0);
|
||||
// Also when filtering and there are no results, empty state CTA should not show
|
||||
cy.getByTestId('resources-list-search').type('non-existing', { delay: 20 });
|
||||
getWorkflowCards().should('not.exist');
|
||||
getFolderEmptyState().should('not.exist');
|
||||
// But there should be a message saying that no results were found
|
||||
cy.getByTestId('resources-list-empty').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Create workflows inside folders', () => {
|
||||
it('should create workflows in folders in all supported ways', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Workflows go here');
|
||||
// 1. From empty state
|
||||
getFolderCard('Workflows go here').should('exist').click();
|
||||
createWorkflowFromEmptyState('Created from empty state');
|
||||
goToPersonalProject();
|
||||
getFolderCard('Workflows go here').click();
|
||||
getWorkflowCard('Created from empty state').should('exist');
|
||||
// 2. From the project header
|
||||
createWorkflowFromProjectHeader('Workflows go here', 'Created from project header');
|
||||
goToPersonalProject();
|
||||
getFolderCard('Workflows go here').click();
|
||||
getWorkflowCard('Created from project header').should('exist');
|
||||
// 3. From list breadcrumbs
|
||||
createWorkflowFromListDropdown('Created from list breadcrumbs');
|
||||
goToPersonalProject();
|
||||
getFolderCard('Workflows go here').click();
|
||||
getWorkflowCard('Created from list breadcrumbs').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Rename and delete folders', () => {
|
||||
it('should rename folder from main dropdown', () => {
|
||||
goToPersonalProject();
|
||||
@@ -224,6 +331,175 @@ describe('Folders', () => {
|
||||
deleteFolderWithContentsFromCardDropdown('I also have family');
|
||||
});
|
||||
|
||||
// TODO: Once we have backend endpoint that lists project folders, test transfer when deleting
|
||||
it('should transfer contents when deleting non-empty folder - from card dropdown', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Move my contents');
|
||||
createFolderFromProjectHeader('Destination');
|
||||
createFolderInsideFolder('Child 1', 'Move my contents');
|
||||
getHomeProjectBreadcrumb().click();
|
||||
getFolderCard('Move my contents').should('exist');
|
||||
deleteAndTransferFolderContentsFromCardDropdown('Move my contents', 'Destination');
|
||||
getFolderCard('Destination').click();
|
||||
// Should show the contents of the moved folder
|
||||
getFolderCard('Child 1').should('exist');
|
||||
});
|
||||
|
||||
it('should transfer contents when deleting non-empty folder - from list breadcrumbs', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Move me too');
|
||||
createFolderFromProjectHeader('Destination 2');
|
||||
createFolderInsideFolder('Child 1', 'Move me too');
|
||||
deleteAndTransferFolderContentsFromListDropdown('Destination 2');
|
||||
getFolderCard('Destination').click();
|
||||
// Should show the contents of the moved folder
|
||||
getFolderCard('Child 1').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Move folders and workflows', () => {
|
||||
it('should move empty folder to another folder - from folder card action', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Move me - I am empty');
|
||||
createFolderFromProjectHeader('Destination 3');
|
||||
moveFolderFromFolderCardActions('Move me - I am empty', 'Destination 3');
|
||||
getFolderCard('Destination 3').click();
|
||||
getFolderCard('Move me - I am empty').should('exist');
|
||||
getFolderCard('Move me - I am empty').click();
|
||||
getFolderEmptyState().should('exist');
|
||||
successToast().should('contain.text', 'Move me - I am empty has been moved to Destination 3');
|
||||
// Breadcrumbs should show the destination folder
|
||||
getListBreadcrumbItem('Destination 3').should('exist');
|
||||
});
|
||||
|
||||
it('should move folder with contents to another folder - from folder card action', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Move me - I have family');
|
||||
createFolderFromProjectHeader('Destination 4');
|
||||
// Create a workflow and a folder inside the folder
|
||||
createFolderInsideFolder('Child 1', 'Move me - I have family');
|
||||
createWorkflowFromProjectHeader('Move me - I have family');
|
||||
goToPersonalProject();
|
||||
// Move the folder
|
||||
moveFolderFromFolderCardActions('Move me - I have family', 'Destination 4');
|
||||
successToast().should(
|
||||
'contain.text',
|
||||
'Move me - I have family has been moved to Destination 4',
|
||||
);
|
||||
// Go to destination folder and check if contents are there
|
||||
getFolderCard('Destination 4').click();
|
||||
// Moved folder should be there
|
||||
getFolderCard('Move me - I have family').should('exist').click();
|
||||
// Both the workflow and the folder should be there
|
||||
getFolderCards().should('have.length', 1);
|
||||
getWorkflowCards().should('have.length', 1);
|
||||
// Breadcrumbs should show the destination folder
|
||||
getListBreadcrumbItem('Destination 4').should('exist');
|
||||
});
|
||||
|
||||
it('should move empty folder to another folder - from list breadcrumbs', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Move me too - I am empty');
|
||||
createFolderFromProjectHeader('Destination 5');
|
||||
moveFolderFromListActions('Move me too - I am empty', 'Destination 5');
|
||||
// Since we moved the current folder, we should be in the destination folder
|
||||
getCurrentBreadcrumb().should('contain.text', 'Destination 5');
|
||||
});
|
||||
|
||||
it('should move folder with contents to another folder - from list dropdown', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Move me - I have family 2');
|
||||
createFolderFromProjectHeader('Destination 6');
|
||||
// Create a workflow and a folder inside the folder
|
||||
createFolderInsideFolder('Child 1', 'Move me - I have family 2');
|
||||
createWorkflowFromProjectHeader('Move me - I have family 2');
|
||||
// Navigate back to folder
|
||||
goToPersonalProject();
|
||||
getFolderCard('Move me - I have family 2').should('exist');
|
||||
// Move the folder
|
||||
moveFolderFromListActions('Move me - I have family 2', 'Destination 6');
|
||||
// Since we moved the current folder, we should be in the destination folder
|
||||
getCurrentBreadcrumb().should('contain.text', 'Destination 6');
|
||||
// Moved folder should be there
|
||||
getFolderCard('Move me - I have family 2').should('exist').click();
|
||||
// After navigating to the moved folder, both the workflow and the folder should be there
|
||||
getFolderCards().should('have.length', 1);
|
||||
getWorkflowCards().should('have.length', 1);
|
||||
// Breadcrumbs should show the destination folder
|
||||
getListBreadcrumbItem('Destination 6').should('exist');
|
||||
});
|
||||
|
||||
it('should move folder to project root - from folder card action', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Test parent');
|
||||
createFolderInsideFolder('Move me to root', 'Test parent');
|
||||
moveFolderFromFolderCardActions('Move me to root', 'Personal');
|
||||
// Parent folder should be empty
|
||||
getFolderEmptyState().should('exist');
|
||||
// Child folder should be in the root
|
||||
goToPersonalProject();
|
||||
getFolderCard('Move me to root').should('exist');
|
||||
// Navigate to the moved folder and check breadcrumbs
|
||||
getFolderCard('Move me to root').click();
|
||||
getHomeProjectBreadcrumb().should('contain.text', 'Personal');
|
||||
getListBreadcrumbs().findChildByTestId('breadcrumbs-item').should('not.exist');
|
||||
getCurrentBreadcrumb().should('contain.text', 'Move me to root');
|
||||
});
|
||||
|
||||
it('should move workflow from project root to folder', () => {
|
||||
goToPersonalProject();
|
||||
createWorkflowFromProjectHeader(undefined, 'Move me');
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Workflow destination');
|
||||
moveWorkflowToFolder('Move me', 'Workflow destination');
|
||||
successToast().should('contain.text', 'Move me has been moved to Workflow destination');
|
||||
// Navigate to the destination folder
|
||||
getFolderCard('Workflow destination').click();
|
||||
// Moved workflow should be there
|
||||
getWorkflowCards().should('have.length', 1);
|
||||
getWorkflowCard('Move me').should('exist');
|
||||
});
|
||||
|
||||
it('should move workflow to another folder', () => {
|
||||
goToPersonalProject();
|
||||
createFolderFromProjectHeader('Moving workflow from here');
|
||||
createFolderFromProjectHeader('Moving workflow to here');
|
||||
getFolderCard('Moving workflow from here').click();
|
||||
createWorkflowFromProjectHeader(undefined, 'Move me');
|
||||
goToPersonalProject();
|
||||
getFolderCard('Moving workflow from here').click();
|
||||
getWorkflowCard('Move me').should('exist');
|
||||
moveWorkflowToFolder('Move me', 'Moving workflow to here');
|
||||
// Now folder should be empty
|
||||
getFolderEmptyState().should('exist');
|
||||
// Navigate to the destination folder
|
||||
getHomeProjectBreadcrumb().click();
|
||||
getFolderCard('Moving workflow to here').click();
|
||||
// Moved workflow should be there
|
||||
getWorkflowCards().should('have.length', 1);
|
||||
getWorkflowCard('Move me').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Workflow card breadcrumbs', () => {
|
||||
it('should correctly show workflow card breadcrumbs', () => {
|
||||
createNewProject('Test workflow breadcrumbs', { openAfterCreate: true });
|
||||
createFolderFromProjectHeader('Parent Folder');
|
||||
createFolderInsideFolder('Child Folder', 'Parent Folder');
|
||||
getFolderCard('Child Folder').click();
|
||||
createFolderFromListHeaderButton('Child Folder 2');
|
||||
getFolderCard('Child Folder 2').click();
|
||||
createWorkflowFromEmptyState('Breadcrumbs Test');
|
||||
// Go to overview page
|
||||
getOverviewMenuItem().click();
|
||||
getWorkflowCard('Breadcrumbs Test').should('exist');
|
||||
getWorkflowCardBreadcrumbs('Breadcrumbs Test').should('exist');
|
||||
getWorkflowCardBreadcrumbsEllipsis('Breadcrumbs Test').should('exist');
|
||||
getWorkflowCardBreadcrumbsEllipsis('Breadcrumbs Test').realHover({ position: 'topLeft' });
|
||||
cy.get('[role=tooltip]').should('exist');
|
||||
cy.get('[role=tooltip]').should(
|
||||
'contain.text',
|
||||
'est workflow breadcrumbs / Parent Folder / Child Folder / Child Folder 2',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,12 +19,12 @@ export class WorkflowsPage extends BasePage {
|
||||
cy.getByTestId('add-resource-workflow').should('be.visible');
|
||||
return cy.getByTestId('add-resource-workflow');
|
||||
},
|
||||
workflowCards: () => cy.getByTestId('resources-list-item'),
|
||||
workflowCards: () => cy.getByTestId('resources-list-item-workflow'),
|
||||
workflowCard: (workflowName: string) =>
|
||||
this.getters
|
||||
.workflowCards()
|
||||
.contains(workflowName)
|
||||
.parents('[data-test-id="resources-list-item"]'),
|
||||
.parents('[data-test-id="resources-list-item-workflow"]'),
|
||||
workflowTags: (workflowName: string) =>
|
||||
this.getters.workflowCard(workflowName).findChildByTestId('workflow-card-tags'),
|
||||
workflowCardContent: (workflowName: string) =>
|
||||
|
||||
Reference in New Issue
Block a user