diff --git a/vuu-ui/cypress/e2e/layout-management/layout-management.cy.ts b/vuu-ui/cypress/e2e/layout-management/layout-management.cy.ts new file mode 100644 index 000000000..cb0ad7eec --- /dev/null +++ b/vuu-ui/cypress/e2e/layout-management/layout-management.cy.ts @@ -0,0 +1,76 @@ +import "cypress-iframe"; +import { ShellWithNewTheme } from "../../pages/ShellWithNewTheme"; +import { SaveLayoutDialog } from "../../pages/SaveLayoutDialog"; + +const page = new ShellWithNewTheme(); +const dialog = new SaveLayoutDialog(); + +context("Layout Management", () => { + beforeEach(() => { + page.visit(); + }); + + it("Saves and reloads layout", () => { + const savedLayoutName = "Saved Layout"; + const updatedLayoutName = "Updated Layout"; + const layoutGroup = "Layout Group"; + const layoutSaveName = "My Layout"; + + // Update open layout + page.getTab(0).dblclick(); + // eslint-disable-next-line cypress/unsafe-to-chain-command + cy.focused().type(`${savedLayoutName}{enter}`); + + // Save the updated layout + page.getContextMenuButton().click(); + page.getSaveLayoutButton().click(); + + dialog.getGroupField().type(layoutGroup); + dialog.getNameField().clear().type(layoutSaveName); + dialog.getSaveButton().click(); + + // Verify success notification + page.getToasts().should("have.length", 1); + page.getToastText("Layout Saved Successfully").should("be.visible"); + page + .getToastText(`${layoutSaveName} saved successfully`) + .should("be.visible"); + + // Update open layout again + page.getTab(0).dblclick(); + // eslint-disable-next-line cypress/unsafe-to-chain-command + cy.focused().type(`${updatedLayoutName}{enter}`); + + // Load saved layout + page.getMyLayoutsButton().click(); + page + .getLayoutTile(layoutSaveName, layoutGroup, "test-user", new Date()) + .should("be.visible") + .click(); + + // Verify saved layout is loaded + page.getTabs().should("have.length", 2); + page.getTab(0).should("contain.text", updatedLayoutName); + page.getTab(1).should("contain.text", savedLayoutName); + }); + + it("Does not save when cancel button is clicked", () => { + const layoutGroup = "Layout Group"; + const layoutSaveName = "My Layout"; + + // Go to save a layout, but cancel + page.getContextMenuButton().click(); + page.getSaveLayoutButton().click(); + + dialog.getGroupField().type(layoutGroup); + dialog.getNameField().clear().type(layoutSaveName); + dialog.getCancelButton().click(); + + // Verify no notification + page.getToasts().should("have.length", 0); + + // Verify no saved layouts show in drawer + page.getMyLayoutsButton().click(); + page.getLayoutGroup(layoutGroup).should("not.exist"); + }); +}); diff --git a/vuu-ui/cypress/pages/ShellWithNewTheme.ts b/vuu-ui/cypress/pages/ShellWithNewTheme.ts index 6195346b0..030aa9d90 100644 --- a/vuu-ui/cypress/pages/ShellWithNewTheme.ts +++ b/vuu-ui/cypress/pages/ShellWithNewTheme.ts @@ -6,22 +6,49 @@ export class ShellWithNewTheme { cy.visit(SHELL_WITH_NEW_THEME_URL); }; + getTabs: () => Cypress.Chainable> = () => { + return cy.findByRole("tablist", { name: "data tabs" }).findAllByRole("tab"); + }; + + getTab: (n: number) => Cypress.Chainable> = ( + n: number + ) => { + return this.getTabs().eq(n); + }; + getContextMenuButton: () => Cypress.Chainable> = () => { - return cy - .findByRole("tablist", { name: "data tabs" }) - .findAllByRole("tab") - .first() - .findByRole("button", { name: "context menu" }); + return this.getTab(0).findByRole("button", { name: "context menu" }); }; getSaveLayoutButton: () => Cypress.Chainable> = () => { return cy.findByRole("menuitem", { name: "Save Layout" }); }; + getRenameLayoutButton: () => Cypress.Chainable> = () => { + return cy.findByRole("menuitem", { name: "Rename" }); + }; + getMyLayoutsButton: () => Cypress.Chainable> = () => { return cy.findByRole("tab", { name: "MY LAYOUTS" }); }; + getVuuTablesButton: () => Cypress.Chainable> = () => { + return cy.findByRole("tab", { name: "VUU TABLES" }); + }; + + getFirstAvailableVuuTable: () => Cypress.Chainable> = + () => { + return cy.findAllByRole("option").first(); + }; + + getLayoutGroup: (group: string) => Cypress.Chainable> = ( + group: string + ) => { + return cy + .findByRole("listbox", { name: "my layouts" }) + .findByRole("list", { name: group }); + }; + getLayoutTile: ( layoutName: string, group: string, @@ -36,10 +63,18 @@ export class ShellWithNewTheme { const formattedDate = formatDate({ date: "dd.mm.yyyy" })(date); const layoutTileName = `${layoutName} ${creator}, ${formattedDate}`; - return cy - .findByRole("listbox", { name: "my layouts" }) - .findByRole("list", { name: group }) - .findByRole("listitem", { name: layoutTileName }) - .findByRole("button"); + return this.getLayoutGroup(group).findByRole("button", { + name: layoutTileName, + }); + }; + + getToasts: () => Cypress.Chainable> = () => { + return cy.findAllByRole("status"); + }; + + getToastText: (text: string) => Cypress.Chainable> = ( + text: string + ) => { + return cy.findByRole("status").findByText(text); }; } diff --git a/vuu-ui/packages/vuu-popups/src/notifications/NotificationsProvider.tsx b/vuu-ui/packages/vuu-popups/src/notifications/NotificationsProvider.tsx index 96fa49e33..a3d3cc93a 100644 --- a/vuu-ui/packages/vuu-popups/src/notifications/NotificationsProvider.tsx +++ b/vuu-ui/packages/vuu-popups/src/notifications/NotificationsProvider.tsx @@ -107,6 +107,7 @@ export const ToastNotification = (props: ToastNotificationProps) => {