Created more tests for the authentication flow (#2633)

This commit is contained in:
Erik Jan de Wit 2022-05-18 11:16:47 +02:00 committed by GitHub
parent cc7ec1cf7f
commit d8d28e1d7c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 125 additions and 89 deletions

View file

@ -8,38 +8,57 @@ import FlowDetails from "../support/pages/admin_console/manage/authentication/Fl
import RequiredActions from "../support/pages/admin_console/manage/authentication/RequiredActions";
import adminClient from "../support/util/AdminClient";
import PasswordPolicies from "../support/pages/admin_console/manage/authentication/PasswordPolicies";
import ModalUtils from "../support/util/ModalUtils";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const listingPage = new ListingPage();
describe("Authentication test", () => {
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const listingPage = new ListingPage();
const detailPage = new FlowDetails();
const duplicateFlowModal = new DuplicateFlowModal();
const modalUtil = new ModalUtils();
beforeEach(() => {
before(() => {
keycloakBefore();
loginPage.logIn();
sidebarPage.waitForPageLoad();
});
beforeEach(() => {
sidebarPage.goToAuthentication();
});
it("should create duplicate of existing flow", () => {
const modalDialog = new DuplicateFlowModal();
listingPage.clickRowDetails("Browser").clickDetailMenu("Duplicate");
modalDialog.fill("Copy of browser");
duplicateFlowModal.fill("Copy of browser");
masthead.checkNotificationMessage("Flow successfully duplicated");
listingPage.itemExist("Copy of browser");
});
it("Should fail duplicate with empty flow name", () => {
listingPage.clickRowDetails("Browser").clickDetailMenu("Duplicate");
duplicateFlowModal.fill().shouldShowError("Required field");
modalUtil.cancelModal();
});
it("Should fail duplicate with duplicated name", () => {
listingPage.clickRowDetails("Browser").clickDetailMenu("Duplicate");
duplicateFlowModal.fill("browser");
masthead.checkNotificationMessage(
"Could not duplicate flow: New flow alias name already exists"
);
});
it("should show the details of a flow as a table", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.executionExists("Cookie");
});
it("should move kerberos down", () => {
it.skip("should move kerberos down", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.moveRowTo("Kerberos", "Identity Provider Redirector");
@ -94,6 +113,13 @@ describe("Authentication test", () => {
detailPage.flowExists(flowName);
});
it("Should remove an execution", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.executionExists("Cookie").clickRowDelete("Cookie");
modalUtil.confirmModal();
detailPage.executionExists("Cookie", false);
});
it("should create flow from scratch", () => {
const flowName = "Flow";
listingPage.goToCreateItem();
@ -109,78 +135,76 @@ describe("Authentication test", () => {
detailPage.flowExists(flowName);
});
});
describe("Required actions", () => {
const requiredActionsPage = new RequiredActions();
beforeEach(() => {
keycloakBefore();
loginPage.logIn();
sidebarPage.goToRealm("Test");
sidebarPage.goToAuthentication();
requiredActionsPage.goToTab();
});
describe("Required actions", () => {
const requiredActionsPage = new RequiredActions();
before(() => {
adminClient.createRealm("Test");
});
after(() => {
adminClient.deleteRealm("Test");
});
it("should enable delete account", () => {
const action = "Delete Account";
requiredActionsPage.enableAction(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isChecked(action);
});
it("should register an unregistered action", () => {
const action = "Verify Profile";
requiredActionsPage.enableAction(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isChecked(action).isDefaultEnabled(action);
});
it("should set action as default", () => {
const action = "Configure OTP";
requiredActionsPage.setAsDefault(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isDefaultChecked(action);
});
it("should reorder required actions", () => {
const action = "Terms and Conditions";
requiredActionsPage.moveRowTo(action, "Update Profile");
masthead.checkNotificationMessage("Updated required action successfully");
});
before(() => {
cy.wrap(adminClient.createRealm("Test"));
keycloakBefore();
loginPage.logIn();
sidebarPage.goToRealm("Test");
});
describe("Password policies tab", () => {
const passwordPoliciesPage = new PasswordPolicies();
beforeEach(() => {
keycloakBefore();
loginPage.logIn();
sidebarPage.goToAuthentication();
passwordPoliciesPage.goToTab();
});
beforeEach(() => {
sidebarPage.goToAuthentication();
requiredActionsPage.goToTab();
});
it("should add password policies", () => {
passwordPoliciesPage
.shouldShowEmptyState()
.addPolicy("Not Recently Used")
.save();
masthead.checkNotificationMessage(
"Password policies successfully updated"
);
});
after(() => {
adminClient.deleteRealm("Test");
});
it("should remove password policies", () => {
passwordPoliciesPage.removePolicy("remove-passwordHistory").save();
masthead.checkNotificationMessage(
"Password policies successfully updated"
);
passwordPoliciesPage.shouldShowEmptyState();
});
it("should enable delete account", () => {
const action = "Delete Account";
requiredActionsPage.enableAction(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isChecked(action);
});
it("should register an unregistered action", () => {
const action = "Verify Profile";
requiredActionsPage.enableAction(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isChecked(action).isDefaultEnabled(action);
});
it("should set action as default", () => {
const action = "Configure OTP";
requiredActionsPage.setAsDefault(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isDefaultChecked(action);
});
it("should reorder required actions", () => {
const action = "Terms and Conditions";
requiredActionsPage.moveRowTo(action, "Update Profile");
masthead.checkNotificationMessage("Updated required action successfully");
});
});
describe("Password policies tab", () => {
const passwordPoliciesPage = new PasswordPolicies();
beforeEach(() => {
keycloakBefore();
loginPage.logIn();
sidebarPage.goToAuthentication();
passwordPoliciesPage.goToTab();
});
it("should add password policies", () => {
passwordPoliciesPage
.shouldShowEmptyState()
.addPolicy("Not Recently Used")
.save();
masthead.checkNotificationMessage("Password policies successfully updated");
});
it("should remove password policies", () => {
passwordPoliciesPage.removePolicy("remove-passwordHistory").save();
masthead.checkNotificationMessage("Password policies successfully updated");
passwordPoliciesPage.shouldShowEmptyState();
});
});

View file

@ -2,14 +2,20 @@ export default class DuplicateFlowModal {
private aliasInput = "alias";
private descriptionInput = "description";
private confirmButton = "confirm";
private errorText = ".pf-m-error";
fill(name?: string, description?: string) {
cy.findByTestId(this.aliasInput).clear();
if (name) {
cy.findByTestId(this.aliasInput).clear().type(name);
cy.findByTestId(this.aliasInput).type(name);
if (description) cy.get(this.descriptionInput).type(description);
}
cy.findByTestId(this.confirmButton).click();
return this;
}
shouldShowError(message: string) {
cy.get(this.errorText).invoke("text").should("contain", message);
}
}

View file

@ -1,8 +1,8 @@
type RequirementType = "Required" | "Alternative" | "Disabled" | "Conditional";
export default class FlowDetails {
executionExists(name: string) {
this.getExecution(name).should("exist");
executionExists(name: string, exist = true) {
this.getExecution(name).should((!exist ? "not." : "") + "exist");
return this;
}
@ -76,6 +76,12 @@ export default class FlowDetails {
return this;
}
clickRowDelete(name: string) {
cy.findByTestId(`${name}-delete`).click();
return this;
}
private fillSubFlowModal(subFlowName: string, name: string) {
cy.get(".pf-c-modal-box__title-text").contains(
"Add step to " + subFlowName

View file

@ -41,7 +41,7 @@ export const DuplicateFlowModal = ({
}, [name, description, setValue]);
const save = async () => {
await trigger();
if (!(await trigger())) return;
const form = getValues();
try {
await adminClient.authenticationManagement.copyFlow({

View file

@ -130,13 +130,13 @@ export default function FlowDetails() {
}
};
const update = async (
execution: AuthenticationExecutionInfoRepresentation
) => {
const update = async (execution: ExpandableExecution) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { executionList, isCollapsed, ...ex } = execution;
try {
await adminClient.authenticationManagement.updateExecution(
{ flow: flow?.alias! },
execution
ex
);
refresh();
addAlert(t("updateFlowSuccess"), AlertVariant.success);

View file

@ -2,11 +2,11 @@ import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { Select, SelectOption, SelectVariant } from "@patternfly/react-core";
import type AuthenticationExecutionInfoRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationExecutionInfoRepresentation";
import type { ExpandableExecution } from "../execution-model";
type FlowRequirementDropdownProps = {
flow: AuthenticationExecutionInfoRepresentation;
onChange: (flow: AuthenticationExecutionInfoRepresentation) => void;
flow: ExpandableExecution;
onChange: (flow: ExpandableExecution) => void;
};
export const FlowRequirementDropdown = ({

View file

@ -15,7 +15,6 @@ import {
} from "@patternfly/react-core";
import { TrashIcon } from "@patternfly/react-icons";
import type AuthenticationExecutionInfoRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationExecutionInfoRepresentation";
import type { AuthenticationProviderRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigRepresentation";
import type { ExpandableExecution } from "../execution-model";
import type { Flow } from "./modals/AddSubFlowModal";
@ -30,7 +29,7 @@ type FlowRowProps = {
builtIn: boolean;
execution: ExpandableExecution;
onRowClick: (execution: ExpandableExecution) => void;
onRowChange: (execution: AuthenticationExecutionInfoRepresentation) => void;
onRowChange: (execution: ExpandableExecution) => void;
onAddExecution: (
execution: ExpandableExecution,
type: AuthenticationProviderRepresentation
@ -115,6 +114,7 @@ export const FlowRow = ({
<Tooltip content={t("common:delete")}>
<Button
variant="plain"
data-testid={`${execution.displayName}-delete`}
aria-label={t("common:delete")}
onClick={() => onDelete(execution)}
>