From 16c866524ae917aae14652cd74b1efac2ae6dd04 Mon Sep 17 00:00:00 2001 From: Jon Koops Date: Tue, 7 Feb 2023 12:00:34 +0100 Subject: [PATCH] Add Cypress tests for CIBA policy (#4318) --- .../e2e/authentication_policies_ciba.spec.ts | 84 +++++++++++++++++++ apps/admin-ui/cypress/support/forms/Form.ts | 17 ++++ .../cypress/support/forms/FormValidation.ts | 32 +++++++ apps/admin-ui/cypress/support/forms/Select.ts | 20 +++++ .../manage/authentication/CIBAPolicyPage.ts | 27 ++++++ .../src/authentication/policies/Policies.tsx | 2 +- 6 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 apps/admin-ui/cypress/e2e/authentication_policies_ciba.spec.ts create mode 100644 apps/admin-ui/cypress/support/forms/Form.ts create mode 100644 apps/admin-ui/cypress/support/forms/FormValidation.ts create mode 100644 apps/admin-ui/cypress/support/forms/Select.ts create mode 100644 apps/admin-ui/cypress/support/pages/admin-ui/manage/authentication/CIBAPolicyPage.ts diff --git a/apps/admin-ui/cypress/e2e/authentication_policies_ciba.spec.ts b/apps/admin-ui/cypress/e2e/authentication_policies_ciba.spec.ts new file mode 100644 index 0000000000..6634ef9d89 --- /dev/null +++ b/apps/admin-ui/cypress/e2e/authentication_policies_ciba.spec.ts @@ -0,0 +1,84 @@ +import Form from "../support/forms/Form"; +import FormValidation from "../support/forms/FormValidation"; +import Select from "../support/forms/Select"; +import CIBAPolicyPage from "../support/pages/admin-ui/manage/authentication/CIBAPolicyPage"; +import SidebarPage from "../support/pages/admin-ui/SidebarPage"; +import LoginPage from "../support/pages/LoginPage"; +import adminClient from "../support/util/AdminClient"; +import { keycloakBefore } from "../support/util/keycloak_hooks"; + +const loginPage = new LoginPage(); +const sidebarPage = new SidebarPage(); + +describe("Authentication - Policies - CIBA", () => { + const realmName = crypto.randomUUID(); + + before(() => adminClient.createRealm(realmName)); + after(() => adminClient.deleteRealm(realmName)); + + beforeEach(() => { + keycloakBefore(); + loginPage.logIn(); + sidebarPage.goToRealm(realmName); + sidebarPage.goToAuthentication(); + CIBAPolicyPage.goToTab(); + }); + + it("displays the initial state", () => { + Select.assertSelectedItem( + CIBAPolicyPage.getBackchannelTokenDeliveryModeSelect(), + "Poll" + ); + CIBAPolicyPage.getExpiresInput().should("have.value", "120"); + CIBAPolicyPage.getIntervalInput().should("have.value", "5"); + Form.assertSaveButtonDisabled(); + }); + + it("validates the fields", () => { + // Required fields. + CIBAPolicyPage.getExpiresInput().clear(); + CIBAPolicyPage.getIntervalInput().clear(); + + FormValidation.assertRequired(CIBAPolicyPage.getExpiresInput()); + FormValidation.assertRequired(CIBAPolicyPage.getIntervalInput()); + Form.assertSaveButtonDisabled(); + + // Fields with minimum value. + CIBAPolicyPage.getExpiresInput().type("9"); + CIBAPolicyPage.getIntervalInput().type("-1"); + + FormValidation.assertMinValue(CIBAPolicyPage.getExpiresInput(), 10); + FormValidation.assertMinValue(CIBAPolicyPage.getIntervalInput(), 0); + Form.assertSaveButtonDisabled(); + + // Fields with maximum value. + CIBAPolicyPage.getExpiresInput().clear().type("601"); + CIBAPolicyPage.getIntervalInput().clear().type("601"); + + FormValidation.assertMaxValue(CIBAPolicyPage.getExpiresInput(), 600); + FormValidation.assertMaxValue(CIBAPolicyPage.getIntervalInput(), 600); + Form.assertSaveButtonDisabled(); + }); + + it("saves the form", () => { + // Select new values for fields. + Select.selectItem( + CIBAPolicyPage.getBackchannelTokenDeliveryModeSelect(), + "Ping" + ); + CIBAPolicyPage.getExpiresInput().clear().type("140"); + CIBAPolicyPage.getIntervalInput().clear().type("20"); + + // Save form. + Form.clickSaveButton(); + CIBAPolicyPage.assertSaveSuccess(); + + // Assert values are saved. + Select.assertSelectedItem( + CIBAPolicyPage.getBackchannelTokenDeliveryModeSelect(), + "Ping" + ); + CIBAPolicyPage.getExpiresInput().should("have.value", "140"); + CIBAPolicyPage.getIntervalInput().should("have.value", "20"); + }); +}); diff --git a/apps/admin-ui/cypress/support/forms/Form.ts b/apps/admin-ui/cypress/support/forms/Form.ts new file mode 100644 index 0000000000..d96cce34ab --- /dev/null +++ b/apps/admin-ui/cypress/support/forms/Form.ts @@ -0,0 +1,17 @@ +export default class Form { + static assertSaveButtonEnabled() { + this.#getSaveButton().should("be.enabled"); + } + + static assertSaveButtonDisabled() { + this.#getSaveButton().should("be.disabled"); + } + + static clickSaveButton() { + this.#getSaveButton().click(); + } + + static #getSaveButton() { + return cy.findByTestId("save"); + } +} diff --git a/apps/admin-ui/cypress/support/forms/FormValidation.ts b/apps/admin-ui/cypress/support/forms/FormValidation.ts new file mode 100644 index 0000000000..e06cdc0c7d --- /dev/null +++ b/apps/admin-ui/cypress/support/forms/FormValidation.ts @@ -0,0 +1,32 @@ +export default class FormValidation { + static assertRequired(chain: Cypress.Chainable>) { + return this.#getHelperText(chain).should("have.text", "Required field"); + } + + static assertMinValue( + chain: Cypress.Chainable>, + minValue: number + ) { + this.#getHelperText(chain).should( + "have.text", + `Must be greater than ${minValue}` + ); + } + + static assertMaxValue( + chain: Cypress.Chainable>, + maxValue: number + ) { + this.#getHelperText(chain).should( + "have.text", + `Must be less than ${maxValue}` + ); + } + + static #getHelperText(chain: Cypress.Chainable>) { + // A regular ID selector doesn't work here so we have to query by attribute. + return chain + .invoke("attr", "id") + .then((id) => cy.get(`[id="${id}-helper"]`)); + } +} diff --git a/apps/admin-ui/cypress/support/forms/Select.ts b/apps/admin-ui/cypress/support/forms/Select.ts new file mode 100644 index 0000000000..51f6b66bb3 --- /dev/null +++ b/apps/admin-ui/cypress/support/forms/Select.ts @@ -0,0 +1,20 @@ +export default class Select { + static assertSelectedItem( + chain: Cypress.Chainable>, + itemName: string + ) { + chain.should("have.text", itemName); + } + + static selectItem( + chain: Cypress.Chainable>, + itemName: string + ) { + chain.click(); + this.#getSelectMenu(chain).contains(itemName).click(); + } + + static #getSelectMenu(chain: Cypress.Chainable>) { + return chain.parent().get(".pf-c-select__menu"); + } +} diff --git a/apps/admin-ui/cypress/support/pages/admin-ui/manage/authentication/CIBAPolicyPage.ts b/apps/admin-ui/cypress/support/pages/admin-ui/manage/authentication/CIBAPolicyPage.ts new file mode 100644 index 0000000000..8ca0d103e4 --- /dev/null +++ b/apps/admin-ui/cypress/support/pages/admin-ui/manage/authentication/CIBAPolicyPage.ts @@ -0,0 +1,27 @@ +import Masthead from "../../Masthead"; + +const masthead = new Masthead(); + +export default class CIBAPolicyPage { + static goToTab() { + cy.findByTestId("policies").click(); + cy.findByTestId("tab-ciba-policy").click(); + return this; + } + + static getBackchannelTokenDeliveryModeSelect() { + return cy.get("#cibaBackchannelTokenDeliveryMode"); + } + + static getExpiresInput() { + return cy.get("#cibaExpiresIn"); + } + + static getIntervalInput() { + return cy.get("#cibaInterval"); + } + + static assertSaveSuccess() { + masthead.checkNotificationMessage("CIBA policy successfully updated"); + } +} diff --git a/apps/admin-ui/src/authentication/policies/Policies.tsx b/apps/admin-ui/src/authentication/policies/Policies.tsx index 1d8e5f9d36..ddfa1617e9 100644 --- a/apps/admin-ui/src/authentication/policies/Policies.tsx +++ b/apps/admin-ui/src/authentication/policies/Policies.tsx @@ -72,7 +72,7 @@ export const Policies = () => { {t("cibaPolicy")}} >