From c35834043fb11ca9f746de2664709b03a2e98b3c Mon Sep 17 00:00:00 2001 From: Peter Makowski Date: Thu, 4 Apr 2024 11:01:14 +0200 Subject: [PATCH] test: e2e test for static routes --- cypress.config.ts | 4 +- cypress/e2e/with-users/subnets/add.spec.ts | 17 +--- .../with-users/subnets/staticroutes.spec.ts | 80 +++++++++++++++++++ cypress/support/commands.ts | 28 ++++++- cypress/support/e2e.ts | 8 ++ .../DeleteStaticRouteForm.test.tsx | 2 +- .../EditStaticRouteForm.tsx | 2 +- 7 files changed, 120 insertions(+), 21 deletions(-) create mode 100644 cypress/e2e/with-users/subnets/staticroutes.spec.ts diff --git a/cypress.config.ts b/cypress.config.ts index b48e5038840..722ff27fe83 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -36,9 +36,9 @@ export default defineConfig({ VITE_BASENAME: "/r", nonAdminPassword: "test", nonAdminUsername: "user", - password: "test", + password: "maas", skipA11yFailures: false, - username: "admin", + username: "maas", }, projectId: "gp2cox", retries: { diff --git a/cypress/e2e/with-users/subnets/add.spec.ts b/cypress/e2e/with-users/subnets/add.spec.ts index bc51a22b554..6eab330e338 100644 --- a/cypress/e2e/with-users/subnets/add.spec.ts +++ b/cypress/e2e/with-users/subnets/add.spec.ts @@ -30,21 +30,6 @@ context("Subnets - Add", () => { cy.findByRole("button", { name: "Add VLAN" }).click(); }; - const completeAddSubnetForm = ( - subnetName: string, - cidr: string, - fabric: string, - vid: string, - vlan: string - ) => { - openAddForm("Subnet"); - cy.findByRole("textbox", { name: "CIDR" }).type(cidr); - cy.findByRole("textbox", { name: "Name" }).type(subnetName); - cy.findByRole("combobox", { name: "Fabric" }).select(fabric); - cy.findByRole("combobox", { name: "VLAN" }).select(`${vid} (${vlan})`); - cy.findByRole("button", { name: "Add Subnet" }).click(); - }; - const completeForm = (formName: string, name: string) => { openAddForm(formName); cy.findByRole("textbox", { name: "Name (optional)" }).type(name); @@ -115,7 +100,7 @@ context("Subnets - Add", () => { completeForm("Fabric", fabricName); completeForm("Space", spaceName); completeAddVlanForm(vid, vlanName, fabricName, spaceName); - completeAddSubnetForm(subnetName, cidr, fabricName, vid, vlanName); + cy.addSubnet(subnetName, cidr, fabricName, vid, vlanName); cy.findAllByRole("link", { name: fabricName }).should("have.length", 2); diff --git a/cypress/e2e/with-users/subnets/staticroutes.spec.ts b/cypress/e2e/with-users/subnets/staticroutes.spec.ts new file mode 100644 index 00000000000..5a1a9828c7d --- /dev/null +++ b/cypress/e2e/with-users/subnets/staticroutes.spec.ts @@ -0,0 +1,80 @@ +import { generateMAASURL } from "../../utils"; + +context("Static Routes", () => { + beforeEach(() => { + cy.login(); + cy.visit(generateMAASURL("/networks?by=fabric")); + cy.waitForPageToLoad(); + cy.viewport("macbook-11"); + }); + it("allows adding, editing, and deleting a static route", () => { + // Add static route + cy.findByRole("grid", { name: "Subnets by Fabric" }).within(() => { + cy.get("tbody").find('td[aria-label="subnet"]').find("a").first().click(); + }); + cy.findByRole("heading", { level: 1 }).invoke("text").as("subnet"); + + cy.findByRole("button", { name: /add static route/i }).click(); + cy.get("@subnet").then((subnet: unknown) => { + cy.findByRole("complementary", { name: /Add static route/i }).within( + () => { + const staticRoute = (subnet as string).split("/")[0]; + cy.wrap(staticRoute).as("staticRoute"); + cy.findByLabelText(/gateway ip/i).type(staticRoute); + cy.findByLabelText(/destination/i).select(1); + } + ); + }); + cy.findByRole("button", { name: /save/i }).click(); + cy.findByRole("complementary", { name: /Add static route/i }).should( + "not.exist" + ); + + // Edit static route + cy.findByRole("region", { name: /Static routes/i }).within(() => { + cy.get("tbody tr") + .first() + .findByRole("button", { name: /edit/i }) + .click(); + }); + + cy.findByRole("complementary", { name: /Edit static route/i }).within( + () => { + cy.findByLabelText(/gateway ip/i).type("{Backspace}1"); + cy.findByRole("button", { name: /save/i }).click(); + } + ); + + // Verify the change has been saved and side panel closed + cy.get("@staticRoute").then((staticRoute: unknown) => { + cy.findByRole("region", { name: /Static routes/i }).within(() => { + cy.findByText(staticRoute as string); + }); + }); + cy.findByRole("complementary", { name: /Add static route/i }).should( + "not.exist" + ); + + // Delete the static route + cy.findByRole("region", { name: /Static routes/i }).within(() => { + cy.get("tbody tr") + .first() + .findByRole("gridcell", { name: /actions/i }) + .findByRole("button", { name: /delete/i }) + .click(); + }); + + // Verify it's been deleted and side panel closed + cy.findByRole("complementary", { name: /Delete static route/i }).within( + () => { + cy.findByRole("button", { name: /delete/i }).click(); + } + ); + cy.get("@staticRoute").then((staticRoute: unknown) => { + cy.findByRole("region", { name: /Static routes/i }).within(() => { + cy.findByText(staticRoute as string).should("not.exist"); + }); + }); + cy.findByRole("region", { name: /side panel/i }).should("not.exist"); + }); +}); diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 62270f420c7..43228ab1af2 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -1,7 +1,13 @@ import "@testing-library/cypress/add-commands"; import type { Result } from "axe-core"; import { LONG_TIMEOUT } from "../constants"; -import { generateMAASURL, generateMac, generateName } from "../e2e/utils"; +import { + generateId, + generateMAASURL, + generateMac, + generateName, + generateVid, +} from "../e2e/utils"; import type { A11yPageContext } from "./e2e"; Cypress.Commands.add("login", (options) => { @@ -101,6 +107,26 @@ Cypress.Commands.add("addMachines", (hostnames: string[]) => { }); }); +Cypress.Commands.add( + "addSubnet", + ({ + subnetName = `cy-subnet-${generateId()}`, + cidr = "192.168.122.18", + fabric = `cy-fabric-${generateId()}`, + vid = generateVid(), + vlan = `cy-vlan-${vid}`, + }) => { + cy.visit(generateMAASURL("/networks?by=fabric")); + cy.findByRole("button", { name: "Add" }).click(); + cy.findByRole("button", { name: "Subnet" }).click(); + cy.findByRole("textbox", { name: "CIDR" }).type(cidr); + cy.findByRole("textbox", { name: "Name" }).type(subnetName); + cy.findByRole("combobox", { name: "Fabric" }).select(fabric); + cy.findByRole("combobox", { name: "VLAN" }).select(`${vid} (${vlan})`); + cy.findByRole("button", { name: "Add Subnet" }).click(); + } +); + function logViolations(violations: Result[], pageContext: A11yPageContext) { const divider = "\n====================================================================================================\n"; diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index c240aa14159..18cf436bee2 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -6,6 +6,13 @@ import "@percy/cypress"; import "./commands"; export type A11yPageContext = { url?: string; title?: string }; +export type SubnetOptions = { + subnetName?: string; + cidr?: string; + fabric?: string; + vid?: string; + vlan?: string; +}; declare global { namespace Cypress { interface Chainable { @@ -27,6 +34,7 @@ declare global { }): Cypress.Chainable>; getMainNavigation(): Cypress.Chainable>; expandMainNavigation(): void; + addSubnet(options: SubnetOptions): void; } } } diff --git a/src/app/subnets/views/SubnetDetails/StaticRoutes/DeleteStaticRouteform/DeleteStaticRouteForm.test.tsx b/src/app/subnets/views/SubnetDetails/StaticRoutes/DeleteStaticRouteform/DeleteStaticRouteForm.test.tsx index fa99e60f548..86f4fc5f7d2 100644 --- a/src/app/subnets/views/SubnetDetails/StaticRoutes/DeleteStaticRouteform/DeleteStaticRouteForm.test.tsx +++ b/src/app/subnets/views/SubnetDetails/StaticRoutes/DeleteStaticRouteform/DeleteStaticRouteForm.test.tsx @@ -12,7 +12,7 @@ const mockStore = configureStore(); const subnet = factory.subnet({ id: 1, cidr: "172.16.1.0/24" }); const destinationSubnet = factory.subnet({ id: 2, cidr: "223.16.1.0/24" }); -const staticroute = factory.staticRoute({ id: 1, subnet: subnet.id }); +const staticroute = factory.staticRoute({ id: 1, destination: subnet.id }); state = factory.rootState({ user: factory.userState({ auth: factory.authState({ diff --git a/src/app/subnets/views/SubnetDetails/StaticRoutes/EditStaticRouteForm/EditStaticRouteForm.tsx b/src/app/subnets/views/SubnetDetails/StaticRoutes/EditStaticRouteForm/EditStaticRouteForm.tsx index f052ef5875e..50886b46a67 100644 --- a/src/app/subnets/views/SubnetDetails/StaticRoutes/EditStaticRouteForm/EditStaticRouteForm.tsx +++ b/src/app/subnets/views/SubnetDetails/StaticRoutes/EditStaticRouteForm/EditStaticRouteForm.tsx @@ -63,7 +63,7 @@ const EditStaticRouteForm = ({ useFetchActions([staticRouteActions.fetch, subnetActions.fetch]); - if (!staticRoute || loading) { + if (!staticRouteId || !staticRoute || loading) { return ( );