diff --git a/cypress/integration/client_authorization_test.spec.ts b/cypress/integration/client_authorization_test.spec.ts index ef3e42ebe1..c2bfdae57c 100644 --- a/cypress/integration/client_authorization_test.spec.ts +++ b/cypress/integration/client_authorization_test.spec.ts @@ -4,8 +4,11 @@ import LoginPage from "../support/pages/LoginPage"; import ListingPage from "../support/pages/admin_console/ListingPage"; import Masthead from "../support/pages/admin_console/Masthead"; import SidebarPage from "../support/pages/admin_console/SidebarPage"; -import AuthorizationTab from "../support/pages/admin_console/manage/clients/AuthorizationTab"; +import AuthorizationTab from "../support/pages/admin_console/manage/clients/client_details/tabs/AuthorizationTab"; import ModalUtils from "../support/util/ModalUtils"; +import ClientDetailsPage from "../support/pages/admin_console/manage/clients/client_details/ClientDetailsPage"; +import PoliciesTab from "../support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/PoliciesTab"; +import PermissionsTab from "../support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/PermissionsTab"; describe("Client authentication subtab", () => { const loginPage = new LoginPage(); @@ -13,6 +16,9 @@ describe("Client authentication subtab", () => { const masthead = new Masthead(); const sidebarPage = new SidebarPage(); const authenticationTab = new AuthorizationTab(); + const clientDetailsPage = new ClientDetailsPage(); + const policiesSubTab = new PoliciesTab(); + const permissionsSubTab = new PermissionsTab(); const clientId = "client-authentication-" + (Math.random() + 1).toString(36).substring(7); @@ -25,11 +31,14 @@ describe("Client authentication subtab", () => { serviceAccountsEnabled: true, standardFlowEnabled: true, }); + }); + + beforeEach(() => { keycloakBefore(); loginPage.logIn(); sidebarPage.goToClients(); listingPage.searchItem(clientId).goToItemDetails(clientId); - authenticationTab.goToAuthenticationTab(); + clientDetailsPage.goToAuthorizationTab(); }); after(() => { @@ -37,72 +46,74 @@ describe("Client authentication subtab", () => { }); it("Should update the resource server settings", () => { - authenticationTab.setPolicy("DISABLED").saveSettings(); + policiesSubTab.setPolicy("DISABLED").formUtils().save(); masthead.checkNotificationMessage("Resource successfully updated", true); }); it("Should create a resource", () => { - authenticationTab.goToResourceSubTab(); - authenticationTab.assertDefaultResource(); - - authenticationTab - .goToCreateResource() + const resourcesSubtab = authenticationTab.goToResourcesSubTab(); + listingPage.assertDefaultResource(); + resourcesSubtab + .createResource() .fillResourceForm({ name: "Resource", displayName: "The display name", type: "type", uris: ["one", "two"], }) + .formUtils() .save(); - masthead.checkNotificationMessage("Resource created successfully", true); sidebarPage.waitForPageLoad(); - authenticationTab.cancel(); + authenticationTab.formUtils().cancel(); }); it("Should create a scope", () => { - authenticationTab.goToScopeSubTab(); authenticationTab - .goToCreateScope() + .goToScopesSubTab() + .createAuthorizationScope() .fillScopeForm({ name: "The scope", displayName: "Display something", iconUri: "res://something", }) + .formUtils() .save(); masthead.checkNotificationMessage( "Authorization scope created successfully", true ); - authenticationTab.goToScopeSubTab(); + authenticationTab.goToScopesSubTab(); listingPage.itemExist("The scope"); }); it("Should create a policy", () => { - authenticationTab.goToPolicySubTab(); + authenticationTab.goToPoliciesSubTab(); cy.intercept( "GET", "/admin/realms/master/clients/*/authz/resource-server/policy/regex/*" ).as("get"); - authenticationTab - .goToCreatePolicy("regex") + policiesSubTab + .createPolicy("regex") .fillBasePolicyForm({ name: "Regex policy", description: "Policy for regex", targetClaim: "I don't know", regexPattern: ".*?", }) + .formUtils() .save(); cy.wait(["@get"]); masthead.checkNotificationMessage("Successfully created the policy", true); + sidebarPage.waitForPageLoad(); - authenticationTab.cancel(); + authenticationTab.formUtils().cancel(); }); it("Should delete a policy", () => { - authenticationTab.goToPolicySubTab(); + authenticationTab.goToPoliciesSubTab(); listingPage.deleteItem("Regex policy"); new ModalUtils().confirmModal(); @@ -110,37 +121,35 @@ describe("Client authentication subtab", () => { }); it("Should create a client policy", () => { - authenticationTab.goToPolicySubTab(); + authenticationTab.goToPoliciesSubTab(); cy.intercept( "GET", "/admin/realms/master/clients/*/authz/resource-server/policy/client/*" ).as("get"); - authenticationTab - .goToCreatePolicy("client") + policiesSubTab + .createPolicy("client") .fillBasePolicyForm({ name: "Client policy", description: "Extra client field", }) .inputClient("master-realm") + .formUtils() .save(); - cy.wait(["@get"]); masthead.checkNotificationMessage("Successfully created the policy", true); + sidebarPage.waitForPageLoad(); - authenticationTab.cancel(); + authenticationTab.formUtils().cancel(); }); it("Should create a permission", () => { authenticationTab.goToPermissionsSubTab(); - authenticationTab - .goToCreatePermission("resource") - .fillPermissionForm({ - name: "Permission name", - description: "Something describing this permission", - }) - .selectResource("Default Resource") - .save(); + permissionsSubTab.createPermission("resource").fillPermissionForm({ + name: "Permission name", + description: "Something describing this permission", + }); + permissionsSubTab.selectResource("Default Resource").formUtils().save(); cy.intercept( "/admin/realms/master/clients/*/authz/resource-server/resource?first=0&max=10" ).as("load"); @@ -149,21 +158,22 @@ describe("Client authentication subtab", () => { true ); cy.wait(["@load"]); + sidebarPage.waitForPageLoad(); - authenticationTab.cancel(); + authenticationTab.formUtils().cancel(); }); it.skip("Should copy auth details", () => { - authenticationTab.goToExportSubTab(); + const exportTab = authenticationTab.goToExportSubTab(); sidebarPage.waitForPageLoad(); - authenticationTab.copy(); + exportTab.copy(); masthead.checkNotificationMessage("Authorization details copied.", true); }); it("Should export auth details", () => { - authenticationTab.goToExportSubTab(); + const exportTab = authenticationTab.goToExportSubTab(); sidebarPage.waitForPageLoad(); - authenticationTab.export(); + exportTab.export(); masthead.checkNotificationMessage( "Successfully exported authorization details.", diff --git a/cypress/integration/client_scopes_test.spec.ts b/cypress/integration/client_scopes_test.spec.ts index 165624fd68..d997b1dbec 100644 --- a/cypress/integration/client_scopes_test.spec.ts +++ b/cypress/integration/client_scopes_test.spec.ts @@ -25,7 +25,6 @@ describe("Client Scopes test", () => { "Are you sure you want to delete this client scope"; const notificationMessageDeletionConfirmation = "The client scope has been deleted"; - const clientScopeName = "client-scope-test"; const openIDConnectItemText = "OpenID Connect"; const clientScope = { diff --git a/cypress/integration/clients_test.spec.ts b/cypress/integration/clients_test.spec.ts index dcb4b5409d..4683a7f9a8 100644 --- a/cypress/integration/clients_test.spec.ts +++ b/cypress/integration/clients_test.spec.ts @@ -1,36 +1,32 @@ import LoginPage from "../support/pages/LoginPage"; -import Masthead from "../support/pages/admin_console/Masthead"; -import ListingPage, { +import { Filter, FilterAssignedType, } from "../support/pages/admin_console/ListingPage"; -import SidebarPage from "../support/pages/admin_console/SidebarPage"; import CreateClientPage from "../support/pages/admin_console/manage/clients/CreateClientPage"; -import ModalUtils from "../support/util/ModalUtils"; -import AdvancedTab from "../support/pages/admin_console/manage/clients/AdvancedTab"; import adminClient from "../support/util/AdminClient"; -import InitialAccessTokenTab from "../support/pages/admin_console/manage/clients/InitialAccessTokenTab"; import { keycloakBefore } from "../support/util/keycloak_hooks"; import RoleMappingTab from "../support/pages/admin_console/manage/RoleMappingTab"; -import KeysTab from "../support/pages/admin_console/manage/clients/KeysTab"; -import ClientScopesTab from "../support/pages/admin_console/manage/clients/ClientScopesTab"; import CreateRealmRolePage from "../support/pages/admin_console/manage/realm_roles/CreateRealmRolePage"; import AssociatedRolesPage from "../support/pages/admin_console/manage/realm_roles/AssociatedRolesPage"; import ClientRolesTab from "../support/pages/admin_console/manage/clients/ClientRolesTab"; +import InitialAccessTokenTab from "../support/pages/admin_console/manage/clients/tabs/InitialAccessTokenTab"; +import AdvancedTab from "../support/pages/admin_console/manage/clients/client_details/tabs/AdvancedTab"; +import ClientDetailsPage, { + ClientsDetailsTab, +} from "../support/pages/admin_console/manage/clients/client_details/ClientDetailsPage"; +import CommonPage from "../support/pages/CommonPage"; let itemId = "client_crud"; const loginPage = new LoginPage(); const associatedRolesPage = new AssociatedRolesPage(); -const masthead = new Masthead(); -const sidebarPage = new SidebarPage(); -const listingPage = new ListingPage(); const createClientPage = new CreateClientPage(); -const modalUtils = new ModalUtils(); +const clientDetailsPage = new ClientDetailsPage(); const createRealmRolePage = new CreateRealmRolePage(); +const commonPage = new CommonPage(); describe("Clients test", () => { describe("Client details - Client scopes subtab", () => { - const clientScopesTab = new ClientScopesTab(); const clientId = "client-scopes-subtab-test"; const clientScopeName = "client-scope-test"; const clientScopeNameDefaultType = "client-scope-test-default-type"; @@ -71,11 +67,12 @@ describe("Clients test", () => { beforeEach(() => { keycloakBefore(); loginPage.logIn(); - sidebarPage.goToClients(); + commonPage.sidebar().goToClients(); cy.intercept("/admin/realms/master/clients/*").as("fetchClient"); - listingPage.searchItem(clientId).goToItemDetails(clientId); + commonPage.tableToolbarUtils().searchItem(clientId); + commonPage.tableUtils().clickRowItemLink(clientId); cy.wait("@fetchClient"); - clientScopesTab.goToClientScopesTab(); + clientDetailsPage.goToClientScopesTab(); }); after(async () => { @@ -88,39 +85,51 @@ describe("Clients test", () => { }); it("Should list client scopes", () => { - listingPage.itemsGreaterThan(1).itemExist(clientScopeName + 0); + commonPage + .tableUtils() + .checkRowItemsGreaterThan(1) + .checkRowItemExists(clientScopeName + 0); }); it("Should search existing client scope by name", () => { - listingPage - .searchItem(clientScopeName + 0, false) - .itemExist(clientScopeName + 0) - .itemsEqualTo(2); + commonPage.tableToolbarUtils().searchItem(clientScopeName + 0, false); + commonPage + .tableUtils() + .checkRowItemExists(clientScopeName + 0) + .checkRowItemsEqualTo(2); }); it("Should search non-existent client scope by name", () => { - const itemName = "non-existent-item"; - listingPage.searchItem(itemName, false).checkTableExists(false); + commonPage.tableToolbarUtils().searchItem("non-existent-item", false); + commonPage.tableUtils().checkIfExists(false); + commonPage.emptyState().checkIfExists(true); }); it("Should search existing client scope by assigned type", () => { - listingPage - .selectFilter(Filter.AssignedType) - .selectSecondaryFilterAssignedType(FilterAssignedType.Default) - .itemExist(FilterAssignedType.Default) - .itemExist(FilterAssignedType.Optional, false) - .selectSecondaryFilterAssignedType(FilterAssignedType.Optional) - .itemExist(FilterAssignedType.Default, false) - .itemExist(FilterAssignedType.Optional) - .selectSecondaryFilterAssignedType(FilterAssignedType.AllTypes) - .itemExist(FilterAssignedType.Default) - .itemExist(FilterAssignedType.Optional); + commonPage + .tableToolbarUtils() + .selectSearchType(Filter.AssignedType) + .selectSecondarySearchType(FilterAssignedType.Default); + commonPage + .tableUtils() + .checkRowItemExists(FilterAssignedType.Default) + .checkRowItemExists(FilterAssignedType.Optional, false); + commonPage + .tableToolbarUtils() + .selectSecondarySearchType(FilterAssignedType.Optional); + commonPage + .tableUtils() + .checkRowItemExists(FilterAssignedType.Default, false) + .checkRowItemExists(FilterAssignedType.Optional); + commonPage + .tableToolbarUtils() + .selectSecondarySearchType(FilterAssignedType.AllTypes); + commonPage + .tableUtils() + .checkRowItemExists(FilterAssignedType.Default) + .checkRowItemExists(FilterAssignedType.Optional); }); - /*it("Should empty search", () => { - - });*/ - const newItemsWithExpectedAssignedTypes = [ [clientScopeNameOptionalType, FilterAssignedType.Optional], [clientScopeNameDefaultType, FilterAssignedType.Default], @@ -128,15 +137,20 @@ describe("Clients test", () => { newItemsWithExpectedAssignedTypes.forEach(($type) => { const [itemName, assignedType] = $type; it(`Should add client scope ${itemName} with ${assignedType} assigned type`, () => { - listingPage.clickPrimaryButton(); - modalUtils.checkModalTitle("Add client scopes to " + clientId); - listingPage.clickItemCheckbox(itemName); - modalUtils.confirmModalWithItem(assignedType); - masthead.checkNotificationMessage("Scope mapping successfully updated"); - listingPage - .searchItem(itemName, false) - .itemExist(itemName) - .itemExist(assignedType); + commonPage.tableToolbarUtils().addClientScope(); + commonPage + .modalUtils() + .checkModalTitle("Add client scopes to " + clientId); + commonPage.tableUtils().selectRowItemCheckbox(itemName); + commonPage.modalUtils().confirmModalWithItem(assignedType); + commonPage + .masthead() + .checkNotificationMessage("Scope mapping successfully updated"); + commonPage.tableToolbarUtils().searchItem(itemName, false); + commonPage + .tableUtils() + .checkRowItemExists(itemName) + .checkRowItemExists(assignedType); }); }); @@ -147,60 +161,64 @@ describe("Clients test", () => { expectedItemAssignedTypes.forEach(($assignedType) => { const itemName = clientScopeName + 0; it(`Should change item ${itemName} AssignedType to ${$assignedType} from search bar`, () => { - listingPage - .searchItem(itemName, false) - .clickItemCheckbox(itemName) - .changeTypeToOfSelectedItems($assignedType); - masthead.checkNotificationMessage("Scope mapping updated"); - listingPage.searchItem(itemName, false).itemExist($assignedType); + commonPage.tableToolbarUtils().searchItem(itemName, false); + commonPage.tableUtils().selectRowItemCheckbox(itemName); + commonPage.tableToolbarUtils().changeTypeTo($assignedType); + commonPage.masthead().checkNotificationMessage("Scope mapping updated"); + commonPage.tableToolbarUtils().searchItem(itemName, false); + commonPage.tableUtils().checkRowItemExists($assignedType); }); }); it("Should show items on next page are more than 11", () => { - listingPage.showNextPageTableItems().itemsGreaterThan(1); + commonPage.sidebar().waitForPageLoad(); + commonPage.tableToolbarUtils().clickNextPageButton(); + commonPage.tableUtils().checkRowItemsGreaterThan(1); }); it("Should remove client scope from item bar", () => { const itemName = clientScopeName + 0; - listingPage.searchItem(itemName, false).removeItem(itemName); - masthead.checkNotificationMessage(msgScopeMappingRemoved); - listingPage.searchItem(itemName, false).checkTableExists(false); + commonPage.tableToolbarUtils().searchItem(itemName, false); + commonPage.tableUtils().selectRowItemAction(itemName, "Remove"); + commonPage.masthead().checkNotificationMessage(msgScopeMappingRemoved); + commonPage.tableToolbarUtils().searchItem(itemName, false); + commonPage.tableUtils().checkRowItemExists(itemName, false); }); - /*it("Should remove client scope from search bar", () => { - //covered by next test - });*/ - // TODO: https://github.com/keycloak/keycloak-admin-ui/issues/1854 it("Should remove multiple client scopes from search bar", () => { const itemName1 = clientScopeName + 1; const itemName2 = clientScopeName + 2; - listingPage - .clickSearchBarActionButton() - .checkDropdownItemIsDisabled("Remove") - .searchItem(clientScopeName, false) - .clickItemCheckbox(itemName1) - .clickItemCheckbox(itemName2) - .clickSearchBarActionButton() - .clickSearchBarActionItem("Remove"); - masthead.checkNotificationMessage(msgScopeMappingRemoved); - listingPage - .searchItem(clientScopeName, false) - .itemExist(itemName1, false) - .itemExist(itemName2, false) - .clickSearchBarActionButton(); - //.checkDropdownItemIsDisabled("Remove"); + commonPage.tableToolbarUtils().clickSearchButton(); + commonPage.tableToolbarUtils().checkActionItemIsEnabled("Remove", false); + commonPage.tableToolbarUtils().searchItem(clientScopeName, false); + commonPage + .tableUtils() + .selectRowItemCheckbox(itemName1) + .selectRowItemCheckbox(itemName2); + commonPage.tableToolbarUtils().clickSearchButton(); + commonPage.tableToolbarUtils().clickActionItem("Remove"); + commonPage.masthead().checkNotificationMessage(msgScopeMappingRemoved); + commonPage.tableToolbarUtils().searchItem(clientScopeName, false); + commonPage + .tableUtils() + .checkRowItemExists(itemName1, false) + .checkRowItemExists(itemName2, false); + commonPage.tableToolbarUtils().clickSearchButton(); }); - //TODO: https://github.com/keycloak/keycloak-admin-ui/issues/1874 - /* it("Should show initial items after filtering", () => { - listingPage - .selectFilter(Filter.AssignedType) - .selectFilterAssignedType(FilterAssignedType.Optional) - .selectFilter(Filter.Name) - .itemExist(FilterAssignedType.Default) - .itemExist(FilterAssignedType.Optional); - });*/ + //fails, issue https://github.com/keycloak/keycloak-admin-ui/issues/1874 + it.skip("Should show initial items after filtering", () => { + commonPage + .tableToolbarUtils() + .selectSearchType(Filter.AssignedType) + .selectSecondarySearchType(FilterAssignedType.Optional) + .selectSearchType(Filter.Name); + commonPage + .tableUtils() + .checkRowItemExists(FilterAssignedType.Default) + .checkRowItemExists(FilterAssignedType.Optional); + }); }); describe("Client creation", () => { @@ -210,11 +228,11 @@ describe("Clients test", () => { }); beforeEach(() => { - sidebarPage.goToClients(); + commonPage.sidebar().goToClients(); }); it("Should cancel creating client", () => { - listingPage.goToCreateItem(); + commonPage.tableToolbarUtils().createClient(); createClientPage.continue().checkClientIdRequiredMessage(); @@ -227,7 +245,7 @@ describe("Clients test", () => { }); it("Should check settings elements", () => { - listingPage.goToCreateItem(); + commonPage.tableToolbarUtils().clickPrimaryButton(); const clientId = "Test settings"; createClientPage @@ -236,8 +254,10 @@ describe("Clients test", () => { .checkCapabilityConfigElements() .save(); - masthead.checkNotificationMessage("Client created successfully"); - sidebarPage.waitForPageLoad(); + commonPage + .masthead() + .checkNotificationMessage("Client created successfully"); + commonPage.sidebar().waitForPageLoad(); createClientPage .checkCapabilityConfigElements() @@ -246,12 +266,12 @@ describe("Clients test", () => { .checkLogoutSettingsElements() .deleteClientFromActionDropdown(); - modalUtils.confirmModal(); - listingPage.itemExist(clientId, false); + commonPage.modalUtils().confirmModal(); + commonPage.tableUtils().checkRowItemExists(clientId, false); }); it("Should navigate to previous using 'back' button", () => { - listingPage.goToCreateItem(); + commonPage.tableToolbarUtils().createClient(); createClientPage.continue().checkClientIdRequiredMessage(); @@ -264,7 +284,7 @@ describe("Clients test", () => { }); it("Should fail creating client", () => { - listingPage.goToCreateItem(); + commonPage.tableToolbarUtils().createClient(); createClientPage.continue().checkClientIdRequiredMessage(); @@ -277,18 +297,22 @@ describe("Clients test", () => { createClientPage.fillClientData("account").continue().save(); // The error should inform about duplicated name/id - masthead.checkNotificationMessage( - "Could not create client: 'Client account already exists'" - ); + commonPage + .masthead() + .checkNotificationMessage( + "Could not create client: 'Client account already exists'" + ); }); it("Client CRUD test", () => { itemId += "_" + (Math.random() + 1).toString(36).substring(7); // Create - listingPage.itemExist(itemId, false).goToCreateItem(); + commonPage.tableUtils().checkRowItemExists(itemId, false); + commonPage.tableToolbarUtils().clickPrimaryButton(); createClientPage.cancel(); - listingPage.itemExist(itemId, false).goToCreateItem(); + commonPage.tableUtils().checkRowItemExists(itemId, false); + commonPage.tableToolbarUtils().clickPrimaryButton(); createClientPage .selectClientType("openid-connect") @@ -303,22 +327,30 @@ describe("Clients test", () => { .clickStandardFlow() .save(); - masthead.checkNotificationMessage("Client created successfully"); + commonPage + .masthead() + .checkNotificationMessage("Client created successfully"); - sidebarPage.goToClients(); + commonPage.sidebar().goToClients(); - listingPage.searchItem("John Doe", false).checkEmptyList(); - listingPage.searchItem("").itemExist("account"); - listingPage.searchItem(itemId).itemExist(itemId); + commonPage.tableToolbarUtils().searchItem("John Doe", false); + commonPage.emptyState().checkIfExists(true); + commonPage.tableToolbarUtils().searchItem(""); + commonPage.tableUtils().checkRowItemExists("account"); + commonPage.tableToolbarUtils().searchItem(itemId); + commonPage.tableUtils().checkRowItemExists(itemId); // Delete - listingPage.deleteItem(itemId); - sidebarPage.waitForPageLoad(); - modalUtils.checkModalTitle(`Delete ${itemId} ?`).confirmModal(); - - masthead.checkNotificationMessage("The client has been deleted"); - - listingPage.itemExist(itemId, false); + commonPage.tableUtils().selectRowItemAction(itemId, "Delete"); + commonPage.sidebar().waitForPageLoad(); + commonPage + .modalUtils() + .checkModalTitle(`Delete ${itemId} ?`) + .confirmModal(); + commonPage + .masthead() + .checkNotificationMessage("The client has been deleted"); + commonPage.tableUtils().checkRowItemExists(itemId, false); }); it("Initial access token can't be created with 0 days and count", () => { @@ -342,45 +374,52 @@ describe("Clients test", () => { .fillNewTokenData(1, 3) .save(); - modalUtils.checkModalTitle("Initial access token details").closeModal(); + commonPage + .modalUtils() + .checkModalTitle("Initial access token details") + .closeModal(); - masthead.checkNotificationMessage( - "New initial access token has been created" - ); + commonPage + .masthead() + .checkNotificationMessage("New initial access token has been created"); initialAccessTokenTab.shouldNotBeEmpty(); - listingPage - .searchItem("John Doe", false) - .checkEmptyList() - .searchItem("", false); + commonPage.tableToolbarUtils().searchItem("John Doe", false); + commonPage.emptyState().checkIfExists(true); + commonPage.tableToolbarUtils().searchItem("", false); initialAccessTokenTab.getFirstId((id) => { - listingPage.checkRowColumnValue(id, 4, "4").itemExist(id); + commonPage + .tableUtils() + .checkRowItemValueByItemName(id, 4, "4") + .checkRowItemValueByItemName(id, 5, "4") + .checkRowItemExists(id); }); - listingPage.goToCreateItem(); + commonPage.tableToolbarUtils().clickPrimaryButton("Create"); initialAccessTokenTab.fillNewTokenData(1, 3).save(); - modalUtils.closeModal(); + commonPage.modalUtils().closeModal(); initialAccessTokenTab.getFirstId((id) => { - listingPage.deleteItem(id); - sidebarPage.waitForPageLoad(); - modalUtils + commonPage.tableUtils().selectRowItemAction(id, "Delete"); + commonPage.sidebar().waitForPageLoad(); + commonPage + .modalUtils() .checkModalTitle("Delete initial access token?") .confirmModal(); }); - masthead.checkNotificationMessage( - "Initial access token deleted successfully" - ); + commonPage + .masthead() + .checkNotificationMessage("Initial access token deleted successfully"); initialAccessTokenTab.shouldNotBeEmpty(); initialAccessTokenTab.getFirstId((id) => { - listingPage.deleteItem(id); - sidebarPage.waitForPageLoad(); - modalUtils.confirmModal(); + commonPage.tableUtils().selectRowItemAction(id, "Delete"); + commonPage.sidebar().waitForPageLoad(); + commonPage.modalUtils().confirmModal(); }); initialAccessTokenTab.shouldBeEmpty(); }); @@ -393,25 +432,28 @@ describe("Clients test", () => { before(() => { keycloakBefore(); loginPage.logIn(); - sidebarPage.goToClients(); + commonPage.sidebar().goToClients(); client = "client_" + (Math.random() + 1).toString(36).substring(7); - listingPage.goToCreateItem(); + commonPage.tableToolbarUtils().createClient(); createClientPage .selectClientType("openid-connect") .fillClientData(client) .continue() .save(); - masthead.checkNotificationMessage("Client created successfully", true); + commonPage + .masthead() + .checkNotificationMessage("Client created successfully", true); }); beforeEach(() => { keycloakBefore(); loginPage.logIn(); - sidebarPage.goToClients(); - listingPage.searchItem(client).goToItemDetails(client); + commonPage.sidebar().goToClients(); + commonPage.tableToolbarUtils().searchItem(client); + commonPage.tableUtils().clickRowItemLink(client); rolesTab.goToRolesTab(); }); @@ -428,81 +470,90 @@ describe("Clients test", () => { it("Should create client role", () => { rolesTab.goToCreateRoleFromEmptyState(); createRealmRolePage.fillRealmRoleData(itemId).save(); - masthead.checkNotificationMessage("Role created", true); + commonPage.masthead().checkNotificationMessage("Role created", true); }); it("Should update client role description", () => { - listingPage.searchItem(itemId, false).goToItemDetails(itemId); const updateDescription = "updated description"; + commonPage.tableToolbarUtils().searchItem(itemId, false); + commonPage.tableUtils().clickRowItemLink(itemId); createRealmRolePage.updateDescription(updateDescription).save(); - masthead.checkNotificationMessage("The role has been saved", true); + commonPage + .masthead() + .checkNotificationMessage("The role has been saved", true); createRealmRolePage.checkDescription(updateDescription); }); it("Should add attribute to client role", () => { cy.intercept("/admin/realms/master/roles-by-id/*").as("load"); - listingPage.goToItemDetails(itemId); + commonPage.tableUtils().clickRowItemLink(itemId); rolesTab.goToAttributesTab(); cy.wait(["@load", "@load"]); - rolesTab.addAttribute(); - - masthead.checkNotificationMessage("The role has been saved", true); + rolesTab.addAttribute(1, "crud_attribute_key", "crud_attribute_value"); + rolesTab.tableUtils().checkRowItemsEqualTo(2); + commonPage + .masthead() + .checkNotificationMessage("The role has been saved", true); }); it("Should delete attribute from client role", () => { cy.intercept("/admin/realms/master/roles-by-id/*").as("load"); - listingPage.goToItemDetails(itemId); + commonPage.tableUtils().clickRowItemLink(itemId); rolesTab.goToAttributesTab(); cy.wait(["@load", "@load"]); - rolesTab.deleteAttribute(); - masthead.checkNotificationMessage("The role has been saved", true); + rolesTab.deleteAttribute(1); + commonPage + .masthead() + .checkNotificationMessage("The role has been saved", true); }); it("Should create client role to be deleted", () => { rolesTab.goToCreateRoleFromToolbar(); createRealmRolePage.fillRealmRoleData("client_role_to_be_deleted").save(); - masthead.checkNotificationMessage("Role created", true); + commonPage.masthead().checkNotificationMessage("Role created", true); }); it("Should fail to create duplicate client role", () => { rolesTab.goToCreateRoleFromToolbar(); createRealmRolePage.fillRealmRoleData(itemId).save(); - masthead.checkNotificationMessage( - `Could not create role: Role with name ${itemId} already exists`, - true - ); + commonPage + .masthead() + .checkNotificationMessage( + `Could not create role: Role with name ${itemId} already exists`, + true + ); }); it("Should search existing client role", () => { - listingPage.searchItem(itemId, false).itemExist(itemId); + commonPage.tableToolbarUtils().searchItem(itemId, false); + commonPage.tableUtils().checkRowItemExists(itemId); }); it("Should search non-existing role test", () => { - listingPage.searchItem("role_DNE", false); - cy.findByTestId(listingPage.emptyState).should("exist"); + commonPage.tableToolbarUtils().searchItem("role_DNE", false); + commonPage.emptyState().checkIfExists(true); }); it("roles empty search test", () => { - listingPage.searchItem("", false); - cy.get("table:visible"); + commonPage.tableToolbarUtils().searchItem("", false); + commonPage.tableUtils().checkIfExists(true); }); it("Add associated roles test", () => { - listingPage.searchItem(itemId, false).goToItemDetails(itemId); + commonPage.tableToolbarUtils().searchItem(itemId, false); + commonPage.tableUtils().clickRowItemLink(itemId); // Add associated realm role associatedRolesPage.addAssociatedRealmRole("create-realm"); - masthead.checkNotificationMessage( - "Associated roles have been added", - true - ); + commonPage + .masthead() + .checkNotificationMessage("Associated roles have been added", true); // Add associated client role associatedRolesPage.addAssociatedRoleFromSearchBar("create-client", true); - masthead.checkNotificationMessage( - "Associated roles have been added", - true - ); + commonPage + .masthead() + .checkNotificationMessage("Associated roles have been added", true); rolesTab.goToAssociatedRolesTab(); @@ -511,39 +562,45 @@ describe("Clients test", () => { "manage-consent", true ); - masthead.checkNotificationMessage( - "Associated roles have been added", - true - ); + commonPage + .masthead() + .checkNotificationMessage("Associated roles have been added", true); }); it("Should hide inherited roles test", () => { - listingPage.searchItem(itemId, false).goToItemDetails(itemId); - rolesTab.goToAssociatedRolesTab(); - rolesTab.hideInheritedRoles(); + commonPage.tableToolbarUtils().searchItem(itemId, false); + commonPage.tableUtils().clickRowItemLink(itemId); + rolesTab.goToAssociatedRolesTab().hideInheritedRoles(); }); it("Should delete associated roles test", () => { - listingPage.searchItem(itemId, false).goToItemDetails(itemId); + commonPage.tableToolbarUtils().searchItem(itemId, false); + commonPage.tableUtils().clickRowItemLink(itemId); rolesTab.goToAssociatedRolesTab(); - listingPage.removeItem("create-realm"); - sidebarPage.waitForPageLoad(); - modalUtils.checkModalTitle("Remove associated role?").confirmModal(); - sidebarPage.waitForPageLoad(); + commonPage.tableUtils().selectRowItemAction("create-realm", "Remove"); + commonPage.sidebar().waitForPageLoad(); + commonPage + .modalUtils() + .checkModalTitle("Remove associated role?") + .confirmModal(); + commonPage.sidebar().waitForPageLoad(); - masthead.checkNotificationMessage( - "Associated roles have been removed", - true - ); + commonPage + .masthead() + .checkNotificationMessage("Associated roles have been removed", true); - listingPage.removeItem("manage-consent"); - sidebarPage.waitForPageLoad(); - modalUtils.checkModalTitle("Remove associated role?").confirmModal(); + commonPage.tableUtils().selectRowItemAction("manage-consent", "Remove"); + commonPage.sidebar().waitForPageLoad(); + commonPage + .modalUtils() + .checkModalTitle("Remove associated role?") + .confirmModal(); }); it("Should delete associated role from search bar test", () => { - listingPage.searchItem(itemId, false).goToItemDetails(itemId); - sidebarPage.waitForPageLoad(); + commonPage.tableToolbarUtils().searchItem(itemId, false); + commonPage.tableUtils().clickRowItemLink(itemId); + commonPage.sidebar().waitForPageLoad(); rolesTab.goToAssociatedRolesTab(); cy.get('td[data-label="Role name"]') @@ -555,29 +612,34 @@ describe("Clients test", () => { associatedRolesPage.removeAssociatedRoles(); - sidebarPage.waitForPageLoad(); - modalUtils.checkModalTitle("Remove associated roles?").confirmModal(); - sidebarPage.waitForPageLoad(); + commonPage.sidebar().waitForPageLoad(); + commonPage + .modalUtils() + .checkModalTitle("Remove associated roles?") + .confirmModal(); + commonPage.sidebar().waitForPageLoad(); - masthead.checkNotificationMessage( - "Associated roles have been removed", - true - ); + commonPage + .masthead() + .checkNotificationMessage("Associated roles have been removed", true); }); it("Should delete client role test", () => { - listingPage.deleteItem(itemId); - sidebarPage.waitForPageLoad(); - modalUtils.checkModalTitle("Delete role?").confirmModal(); + commonPage.tableUtils().selectRowItemAction(itemId, "Delete"); + commonPage.sidebar().waitForPageLoad(); + commonPage.modalUtils().checkModalTitle("Delete role?").confirmModal(); }); it("Should delete client role from role details test", () => { - listingPage - .searchItem("client_role_to_be_deleted", false) - .goToItemDetails("client_role_to_be_deleted"); + commonPage + .tableToolbarUtils() + .searchItem("client_role_to_be_deleted", false); + commonPage.tableUtils().clickRowItemLink("client_role_to_be_deleted"); createRealmRolePage.clickActionMenu("Delete this role"); - modalUtils.confirmModal(); - masthead.checkNotificationMessage("The role has been deleted", true); + commonPage.modalUtils().confirmModal(); + commonPage + .masthead() + .checkNotificationMessage("The role has been deleted", true); }); }); @@ -591,22 +653,19 @@ describe("Clients test", () => { }); beforeEach(() => { - sidebarPage.goToClients(); - + commonPage.sidebar().goToClients(); client = "client_" + (Math.random() + 1).toString(36).substring(7); - - listingPage.goToCreateItem(); - + commonPage.tableToolbarUtils().createClient(); createClientPage .selectClientType("openid-connect") .fillClientData(client) .continue(); - sidebarPage.waitForPageLoad(); + commonPage.sidebar().waitForPageLoad(); createClientPage.save(); - advancedTab.goToAdvancedTab(); + clientDetailsPage.goToAdvancedTab(); }); afterEach(() => { @@ -651,7 +710,7 @@ describe("Clients test", () => { }); beforeEach(() => { - sidebarPage.goToClients(); + commonPage.sidebar().goToClients(); }); after(() => { @@ -659,37 +718,38 @@ describe("Clients test", () => { }); it("List", () => { - listingPage - .searchItem(serviceAccountName) - .goToItemDetails(serviceAccountName); + commonPage.tableToolbarUtils().searchItem(serviceAccountName); + commonPage.tableUtils().clickRowItemLink(serviceAccountName); serviceAccountTab .goToServiceAccountTab() .checkRoles(["manage-account", "offline_access", "uma_authorization"]); }); it.skip("Assign", () => { - listingPage.goToItemDetails(serviceAccountName); + commonPage.tableUtils().clickRowItemLink(serviceAccountName); serviceAccountTab .goToServiceAccountTab() .assignRole(false) .selectRow("create-realm") .assign(); - masthead.checkNotificationMessage("Role mapping updated"); + commonPage.masthead().checkNotificationMessage("Role mapping updated"); serviceAccountTab.selectRow("create-realm").unAssign(); - sidebarPage.waitForPageLoad(); - modalUtils.checkModalTitle("Remove mapping?").confirmModal(); - masthead.checkNotificationMessage("Scope mapping successfully removed"); + commonPage.sidebar().waitForPageLoad(); + commonPage.modalUtils().checkModalTitle("Remove mapping?").confirmModal(); + commonPage + .masthead() + .checkNotificationMessage("Scope mapping successfully removed"); }); }); describe("Mapping tab", () => { - const clientScopeTab = new ClientScopesTab(); const mappingClient = "mapping-client"; beforeEach(() => { keycloakBefore(); loginPage.logIn(); - sidebarPage.goToClients(); - listingPage.searchItem(mappingClient).goToItemDetails(mappingClient); + commonPage.sidebar().goToClients(); + commonPage.tableToolbarUtils().searchItem(mappingClient); + commonPage.tableUtils().clickRowItemLink(mappingClient); }); before(() => { @@ -705,17 +765,22 @@ describe("Clients test", () => { }); it("Add mapping to openid client", () => { - clientScopeTab.goToClientScopesTab().clickDedicatedScope(mappingClient); - cy.findByTestId("mappersTab").click(); - cy.findByText("Add predefined mapper").click(); - cy.get("table input").first().click(); - cy.findByTestId("confirm").click(); - masthead.checkNotificationMessage("Mapping successfully created"); + clientDetailsPage + .goToClientScopesTab() + .clickDedicatedScope(mappingClient) + .goToMappersTab() + .addPredefinedMapper(); + clientDetailsPage.modalUtils().table().clickHeaderItem(1, "input"); + clientDetailsPage.modalUtils().add(); + clientDetailsPage + .masthead() + .checkNotificationMessage("Mapping successfully created"); }); }); describe("Keys tab test", () => { const keysName = "keys-client"; + before(() => { keycloakBefore(); loginPage.logIn(); @@ -727,8 +792,9 @@ describe("Clients test", () => { }); beforeEach(() => { - sidebarPage.goToClients(); - listingPage.searchItem(keysName).goToItemDetails(keysName); + commonPage.sidebar().goToClients(); + commonPage.tableToolbarUtils().searchItem(keysName); + commonPage.tableUtils().clickRowItemLink(keysName); }); after(() => { @@ -736,20 +802,21 @@ describe("Clients test", () => { }); it("Change use JWKS Url", () => { - const keysTab = new KeysTab(); - keysTab.goToTab().checkSaveDisabled(); - keysTab.toggleUseJwksUrl().checkSaveDisabled(false); + const keysTab = clientDetailsPage.goToKeysTab(); + keysTab.formUtils().checkSaveButtonIsDisabled(true); + keysTab.toggleUseJwksUrl().formUtils().checkSaveButtonIsDisabled(false); }); it("Generate new keys", () => { - const keysTab = new KeysTab(); - keysTab.goToTab().clickGenerate(); - + const keysTab = clientDetailsPage.goToKeysTab(); + keysTab.clickGenerate(); keysTab.fillGenerateModal("keyname", "123", "1234").clickConfirm(); - masthead.checkNotificationMessage( - "New key pair and certificate generated successfully" - ); + commonPage + .masthead() + .checkNotificationMessage( + "New key pair and certificate generated successfully" + ); }); }); @@ -759,27 +826,26 @@ describe("Clients test", () => { before(() => { keycloakBefore(); loginPage.logIn(); - sidebarPage.goToClients(); - listingPage.searchItem(clientName).goToItemDetails(clientName); + commonPage.sidebar().goToClients(); + commonPage.tableToolbarUtils().searchItem(clientName); + commonPage.tableUtils().clickRowItemLink(clientName); }); it("Displays the correct tabs", () => { - cy.findByTestId("client-tabs") - .findByTestId("clientSettingsTab") - .should("exist"); - - cy.findByTestId("client-tabs").findByTestId("rolesTab").should("exist"); - - cy.findByTestId("client-tabs") - .findByTestId("advancedTab") - .should("exist"); - - cy.findByTestId("client-tabs").find("li").should("have.length", 3); + clientDetailsPage + .goToSettingsTab() + .tabUtils() + .checkTabExists(ClientsDetailsTab.Settings, true) + .checkTabExists(ClientsDetailsTab.Roles, true) + .checkTabExists(ClientsDetailsTab.Advanced, true) + .checkNumberOfTabsIsEqual(3); }); it("Hides the delete action", () => { - cy.findByTestId("action-dropdown").click(); - cy.findByTestId("delete-client").should("not.exist"); + commonPage + .actionToolbarUtils() + .clickActionToggleButton() + .checkActionItemExists("Delete", false); }); }); @@ -795,9 +861,10 @@ describe("Clients test", () => { publicClient: false, bearerOnly: true, }); - sidebarPage.goToClients(); + commonPage.sidebar().goToClients(); cy.intercept("/admin/realms/master/clients/*").as("fetchClient"); - listingPage.searchItem(clientId).goToItemDetails(clientId); + commonPage.tableToolbarUtils().searchItem(clientId); + commonPage.tableUtils().clickRowItemLink(clientId); cy.wait("@fetchClient"); }); @@ -806,8 +873,12 @@ describe("Clients test", () => { }); it("Shows an explainer text for bearer only clients", () => { - cy.findByTestId("bearer-only-explainer-label").trigger("mouseenter"); - cy.findByTestId("bearer-only-explainer-tooltip").should("exist"); + commonPage + .actionToolbarUtils() + .bearerOnlyExplainerLabelElement.trigger("mouseenter"); + commonPage + .actionToolbarUtils() + .bearerOnlyExplainerTooltipElement.should("exist"); }); it("Hides the capability config section", () => { diff --git a/cypress/support/pages/CommonElements.ts b/cypress/support/pages/CommonElements.ts new file mode 100644 index 0000000000..1e60610019 --- /dev/null +++ b/cypress/support/pages/CommonElements.ts @@ -0,0 +1,54 @@ +import { trim } from "lodash-es"; + +export default class CommonElements { + protected parentSelector; + protected primaryBtn; + protected secondaryBtn; + protected secondaryBtnLink; + protected dropdownMenuItem; + protected selectMenuItem; + protected dropdownToggleBtn; + protected dropdownSelectToggleBtn; + protected dropdownSelectToggleItem; + + constructor(parentSelector = "") { + this.parentSelector = trim(parentSelector) + " "; + this.primaryBtn = this.parentSelector + ".pf-c-button.pf-m-primary"; + this.secondaryBtn = this.parentSelector + ".pf-c-button.pf-m-secondary"; + this.secondaryBtnLink = this.parentSelector + ".pf-c-button.pf-m-link"; + this.dropdownMenuItem = + this.parentSelector + ".pf-c-dropdown__menu .pf-c-dropdown__menu-item"; + this.selectMenuItem = + this.parentSelector + ".pf-c-select__menu .pf-c-select__menu-item"; + this.dropdownToggleBtn = this.parentSelector + ".pf-c-dropdown__toggle"; + this.dropdownSelectToggleBtn = this.parentSelector + ".pf-c-select__toggle"; + this.dropdownSelectToggleItem = + this.parentSelector + ".pf-c-select__menu > li"; + } + + clickSecondaryBtn(buttonName: string) { + cy.get(this.secondaryBtn).contains(buttonName).click(); + return this; + } + + checkIfExists(exist: boolean) { + cy.get(this.parentSelector).should((!exist ? "not." : "") + "exist"); + return this; + } + + checkElementIsDisabled( + element: Cypress.Chainable>, + disabled: boolean + ) { + element.then(($btn) => { + if ($btn.hasClass("pf-m-disabled")) { + element.should( + (!disabled ? "not." : "") + "have.class", + "pf-m-disabled" + ); + } else { + element.should((!disabled ? "not." : "") + "have.attr", "disabled"); + } + }); + } +} diff --git a/cypress/support/pages/CommonPage.ts b/cypress/support/pages/CommonPage.ts new file mode 100644 index 0000000000..238f31e04b --- /dev/null +++ b/cypress/support/pages/CommonPage.ts @@ -0,0 +1,57 @@ +import Masthead from "./admin_console/Masthead"; +import SidebarPage from "./admin_console/SidebarPage"; +import TabUtils from "./admin_console/components/TabPage"; +import FormUtils from "./admin_console/components/FormPage"; +import ModalUtils from "../util/ModalUtils"; +import ActionToolbarUtils from "./admin_console/components/ActionToolbarPage"; +import TableToolbarUtils from "./admin_console/components/TableToolbarPage"; +import TableUtils from "./admin_console/components/TablePage"; +import EmptyStatePage from "./admin_console/components/EmptyStatePage"; + +export default class CommonPage { + private mastheadPage = new Masthead(); + private sidebarPage = new SidebarPage(); + private tabUtilsObj = new TabUtils(); + private formUtilsObj = new FormUtils(); + private modalUtilsObj = new ModalUtils(); + private actionToolbarUtilsObj = new ActionToolbarUtils(); + private tableUtilsObj = new TableUtils(); + private tableToolbarUtilsObj = new TableToolbarUtils(); + private emptyStatePage = new EmptyStatePage(); + + masthead() { + return this.mastheadPage; + } + + sidebar() { + return this.sidebarPage; + } + + tabUtils() { + return this.tabUtilsObj; + } + + formUtils() { + return this.formUtilsObj; + } + + modalUtils() { + return this.modalUtilsObj; + } + + actionToolbarUtils() { + return this.actionToolbarUtilsObj; + } + + tableUtils() { + return this.tableUtilsObj; + } + + tableToolbarUtils() { + return this.tableToolbarUtilsObj; + } + + emptyState() { + return this.emptyStatePage; + } +} diff --git a/cypress/support/pages/admin_console/ListingPage.ts b/cypress/support/pages/admin_console/ListingPage.ts index 056775a6a2..0d24a10840 100644 --- a/cypress/support/pages/admin_console/ListingPage.ts +++ b/cypress/support/pages/admin_console/ListingPage.ts @@ -1,3 +1,5 @@ +import CommonElements from "../CommonElements"; + export enum Filter { Name = "Name", AssignedType = "Assigned type", @@ -25,7 +27,7 @@ export enum FilterSession { ServiceAccount = "Service account", } -export default class ListingPage { +export default class ListingPage extends CommonElements { private searchInput = ".pf-c-toolbar__item .pf-c-search-input__text-input:visible"; private tableToolbar = ".pf-c-toolbar"; @@ -57,6 +59,7 @@ export default class ListingPage { private dropdownItem = ".pf-c-dropdown__menu-item"; private changeTypeToButton = ".pf-c-select__toggle"; private toolbarChangeType = "#change-type-dropdown"; + private tableNameColumnPrefix = "name-column-"; showPreviousPageTableItems() { cy.get(this.previousPageBtn).first().click(); @@ -341,4 +344,23 @@ export default class ListingPage { return this; } + + private getResourceLink(name: string) { + return cy.findByTestId(this.tableNameColumnPrefix + name); + } + + goToResourceDetails(name: string) { + this.getResourceLink(name).click(); + return this; + } + + assertDefaultResource() { + this.assertResource("Default Resource"); + return this; + } + + assertResource(name: string) { + this.getResourceLink(name).should("exist"); + return this; + } } diff --git a/cypress/support/pages/admin_console/Masthead.ts b/cypress/support/pages/admin_console/Masthead.ts index a84905eb1a..a43d49d712 100644 --- a/cypress/support/pages/admin_console/Masthead.ts +++ b/cypress/support/pages/admin_console/Masthead.ts @@ -1,4 +1,5 @@ -export default class Masthead { +import CommonElements from "../CommonElements"; +export default class Masthead extends CommonElements { private logoBtn = "#masthead-logo"; private helpBtn = "#help"; private closeAlertMessageBtn = ".pf-c-alert__action button"; diff --git a/cypress/support/pages/admin_console/SidebarPage.ts b/cypress/support/pages/admin_console/SidebarPage.ts index 9794140986..dd080b082d 100644 --- a/cypress/support/pages/admin_console/SidebarPage.ts +++ b/cypress/support/pages/admin_console/SidebarPage.ts @@ -1,4 +1,6 @@ -export default class SidebarPage { +import CommonElements from "../CommonElements"; + +export default class SidebarPage extends CommonElements { private realmsDrpDwn = "#realm-select button.pf-c-dropdown__toggle"; private realmsList = '#realm-select ul[role="menu"]'; private createRealmBtn = "add-realm"; diff --git a/cypress/support/pages/admin_console/components/ActionToolbarPage.ts b/cypress/support/pages/admin_console/components/ActionToolbarPage.ts new file mode 100644 index 0000000000..41d8427413 --- /dev/null +++ b/cypress/support/pages/admin_console/components/ActionToolbarPage.ts @@ -0,0 +1,28 @@ +import CommonElements from "../../CommonElements"; + +export default class ActionToolbarPage extends CommonElements { + constructor() { + super(".pf-l-level.pf-m-gutter"); + } + + get bearerOnlyExplainerLabelElement() { + return cy + .get(this.parentSelector) + .findByTestId("bearer-only-explainer-label"); + } + + get bearerOnlyExplainerTooltipElement() { + return cy.findByTestId("bearer-only-explainer-tooltip"); + } + + clickActionToggleButton() { + cy.get(this.parentSelector).findByTestId("action-dropdown").click(); + return this; + } + + checkActionItemExists(itemName: string, exists: boolean) { + const condition = exists ? "exist" : "not.exist"; + cy.get(this.dropdownMenuItem).contains(itemName).should(condition); + return this; + } +} diff --git a/cypress/support/pages/admin_console/components/EmptyStatePage.ts b/cypress/support/pages/admin_console/components/EmptyStatePage.ts new file mode 100644 index 0000000000..e507e0e108 --- /dev/null +++ b/cypress/support/pages/admin_console/components/EmptyStatePage.ts @@ -0,0 +1,7 @@ +import CommonElements from "../../CommonElements"; + +export default class EmptyStatePage extends CommonElements { + constructor() { + super(".pf-c-empty-state__content"); + } +} diff --git a/cypress/support/pages/admin_console/components/FormPage.ts b/cypress/support/pages/admin_console/components/FormPage.ts new file mode 100644 index 0000000000..d94b1f51fd --- /dev/null +++ b/cypress/support/pages/admin_console/components/FormPage.ts @@ -0,0 +1,35 @@ +import CommonElements from "../../CommonElements"; + +export default class FormPage extends CommonElements { + constructor() { + super(".pf-c-form:visible"); + } + + save() { + cy.get(this.primaryBtn).contains("Save").click(); + return this; + } + + add() { + cy.get(this.primaryBtn).contains("Add").click(); + return this; + } + + cancel() { + cy.get(this.secondaryBtnLink).contains("Cancel").click(); + return this; + } + + revert() { + cy.get(this.secondaryBtnLink).contains("Revert").click(); + return this; + } + + checkSaveButtonIsDisabled(disabled: boolean) { + this.checkElementIsDisabled( + cy.get(this.primaryBtn).contains("Save"), + disabled + ); + return this; + } +} diff --git a/cypress/support/pages/admin_console/components/TabPage.ts b/cypress/support/pages/admin_console/components/TabPage.ts new file mode 100644 index 0000000000..eac2aa04e1 --- /dev/null +++ b/cypress/support/pages/admin_console/components/TabPage.ts @@ -0,0 +1,35 @@ +import CommonElements from "../../CommonElements"; + +export default class TabPage extends CommonElements { + protected tabItemSelector: string; + + constructor() { + super(".pf-c-tabs"); + this.tabItemSelector = this.parentSelector + ".pf-c-tabs__item"; + } + + clickTab(tabName: string) { + cy.get(this.tabItemSelector).contains(tabName).click(); + this.checkIsCurrentTab(tabName); + return this; + } + + checkIsCurrentTab(tabName: string) { + cy.get(this.tabItemSelector) + .contains(tabName) + .parent() + .should("have.class", "pf-m-current"); + return this; + } + + checkTabExists(tabName: string, exists: boolean) { + const condition = exists ? "exist" : "not.exist"; + cy.get(this.tabItemSelector).contains(tabName).should(condition); + return this; + } + + checkNumberOfTabsIsEqual(number: number) { + cy.get(this.tabItemSelector).should("have.length", number); + return this; + } +} diff --git a/cypress/support/pages/admin_console/components/TablePage.ts b/cypress/support/pages/admin_console/components/TablePage.ts new file mode 100644 index 0000000000..a91b87dc10 --- /dev/null +++ b/cypress/support/pages/admin_console/components/TablePage.ts @@ -0,0 +1,117 @@ +import CommonElements from "../../CommonElements"; + +export default class TablePage extends CommonElements { + private tableRowItem: string; + private tableRowItemChckBx: string; + private tableHeaderRowItem: string; + static tableSelector = "table[aria-label]"; + + constructor(parentElement?: string) { + if (parentElement) { + super(parentElement); + } else { + super(TablePage.tableSelector + ":visible"); + } + this.tableRowItem = + this.parentSelector + "tbody tr[data-ouia-component-type]"; + this.tableHeaderRowItem = + this.parentSelector + "thead tr[data-ouia-component-type]"; + this.tableRowItemChckBx = ".pf-c-table__check"; + } + + selectRowItemCheckbox(itemName: string) { + cy.get(this.tableRowItem) + .contains(itemName) + .parentsUntil("tbody") + .find(this.tableRowItemChckBx) + .click(); + return this; + } + + clickRowItemLink(itemName: string) { + cy.get(this.tableRowItem).contains(itemName).click(); + return this; + } + + selectRowItemAction(itemName: string, actionItemName: string) { + cy.get(this.tableRowItem) + .contains(itemName) + .parentsUntil("tbody") + .find(".pf-c-dropdown__toggle") + .click(); + cy.get(this.dropdownMenuItem).contains(actionItemName).click(); + return this; + } + + typeValueToRowItem(row: number, column: number, value: string) { + cy.get(this.tableRowItem + ":nth-child(" + row + ")") + .find("td:nth-child(" + column + ")") + .type(value); + return this; + } + + clickRowItemByIndex(row: number, column: number, appendChildren?: string) { + cy.get(this.tableRowItem + ":nth-child(" + row + ")") + .find("td:nth-child(" + column + ") " + appendChildren) + .click(); + return this; + } + + clickRowItemByItemName( + itemName: string, + column: number, + appendChildren?: string + ) { + cy.get(this.tableRowItem) + .find("td:nth-child(" + column + ") " + appendChildren) + .contains(itemName) + .click(); + return this; + } + + clickHeaderItem(column: number, appendChildren?: string) { + cy.get(this.tableHeaderRowItem) + .find("td:nth-child(" + column + ") " + appendChildren) + .click(); + return this; + } + + checkRowItemsEqualTo(amount: number) { + cy.get(this.tableRowItem).its("length").should("be.eq", amount); + return this; + } + + checkRowItemsGreaterThan(amount: number) { + cy.get(this.tableRowItem).its("length").should("be.gt", amount); + return this; + } + + checkRowItemExists(itemName: string, exist = true) { + cy.get(this.tableRowItem) + .contains(itemName) + .should((!exist ? "not." : "") + "exist"); + return this; + } + + checkRowItemValueByItemName(itemName: string, column: number, value: string) { + cy.get(this.tableRowItem) + .contains(itemName) + .parentsUntil("tbody") + .find("td:nth-child(" + column + ")") + .should("have.text", value); + return this; + } + + checkRowItemValueByIndex( + row: number, + column: number, + value: string, + appendChildren?: string + ) { + cy.get(this.tableRowItem + ":nth-child(" + row + ")") + .find("td:nth-child(" + column + ") " + appendChildren) + .should("have.text", value) + .should("have.value", value); + return this; + } +} diff --git a/cypress/support/pages/admin_console/components/TableToolbarPage.ts b/cypress/support/pages/admin_console/components/TableToolbarPage.ts new file mode 100644 index 0000000000..2c7429f785 --- /dev/null +++ b/cypress/support/pages/admin_console/components/TableToolbarPage.ts @@ -0,0 +1,130 @@ +import CommonElements from "../../CommonElements"; +import type { Filter, FilterAssignedType } from "../ListingPage"; + +export default class TableToolbar extends CommonElements { + private searchBtn: string; + private searchInput: string; + private changeTypeBtn: string; + private nextPageBtn: string; + private previousPageBtn: string; + private searchTypeDropdownBtn: string; + private searchTypeSelectToggleBtn: string; + private actionToggleBtn: string; + + constructor() { + super(".pf-c-toolbar:visible"); + this.searchBtn = + this.parentSelector + "button[aria-label='Search']:visible"; + this.searchInput = + this.parentSelector + ".pf-c-search-input__text-input:visible"; + this.changeTypeBtn = this.parentSelector + "#change-type-dropdown"; + this.nextPageBtn = this.parentSelector + "button[data-action=next]"; + this.previousPageBtn = this.parentSelector + "button[data-action=previous]"; + this.searchTypeDropdownBtn = + this.parentSelector + "[class*='searchtype'] .pf-c-dropdown__toggle"; + this.searchTypeSelectToggleBtn = + this.parentSelector + "[class*='searchtype'] .pf-c-select__toggle"; + this.actionToggleBtn = this.dropdownToggleBtn + "[aria-label='Actions']"; + } + + clickNextPageButton(isUpperButton = true) { + if (isUpperButton) { + cy.get(this.nextPageBtn).first().click(); + } else { + cy.get(this.nextPageBtn).last().click(); + } + return this; + } + + clickPreviousPageButton(isUpperButton = true) { + if (isUpperButton) { + cy.get(this.previousPageBtn).first().click(); + } else { + cy.get(this.previousPageBtn).last().click(); + } + return this; + } + + clickActionItem(actionItemName: string) { + cy.get(this.actionToggleBtn).click(); + cy.get(this.dropdownMenuItem).contains(actionItemName).click(); + return this; + } + + clickSearchButton() { + cy.get(this.searchBtn).click(); + return this; + } + + clickPrimaryButton(itemName?: string) { + if (itemName == undefined) { + cy.get(this.primaryBtn).click(); + } else { + cy.get(this.primaryBtn).contains(itemName).click(); + } + return this; + } + + clickDropdownMenuItem(itemName: string) { + cy.get(this.dropdownMenuItem).contains(itemName).click(); + return this; + } + + searchItem(searchValue: string, wait = true) { + if (wait) { + const searchUrl = `/admin/realms/master/*${searchValue}*`; + cy.intercept(searchUrl).as("search"); + } + cy.get(this.searchInput).clear(); + if (searchValue) { + cy.get(this.searchInput).type(searchValue); + } + cy.get(this.searchBtn).click(); + if (wait) { + cy.wait(["@search"]); + } + return this; + } + + selectSearchType(itemName: Filter) { + cy.get(this.searchTypeDropdownBtn).click(); + cy.get(this.dropdownMenuItem).contains(itemName).click(); + return this; + } + + selectSecondarySearchType(itemName: FilterAssignedType) { + cy.get(this.searchTypeSelectToggleBtn).click(); + cy.get(this.dropdownSelectToggleItem).contains(itemName).click(); + return this; + } + + changeTypeTo(itemName: FilterAssignedType) { + cy.get(this.changeTypeBtn).click(); + cy.get(this.dropdownSelectToggleItem).contains(itemName).click(); + return this; + } + + addClientScope() { + cy.get(this.primaryBtn).contains("Add client scope").click(); + return this; + } + + createClient() { + cy.get(this.primaryBtn).contains("Create client").click(); + return this; + } + + addMapper() { + cy.get(this.primaryBtn).contains("Add mapper").click(); + return this; + } + + checkActionItemIsEnabled(actionItemName: string, enabled: boolean) { + cy.get(this.actionToggleBtn).click(); + cy.get(this.dropdownMenuItem) + .contains(actionItemName) + .should((!enabled ? "not." : "") + "be.disabled"); + cy.get(this.actionToggleBtn).click(); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/client_scopes/ClientScopesPage.ts b/cypress/support/pages/admin_console/manage/client_scopes/ClientScopesPage.ts new file mode 100644 index 0000000000..d5515eef8a --- /dev/null +++ b/cypress/support/pages/admin_console/manage/client_scopes/ClientScopesPage.ts @@ -0,0 +1,3 @@ +import CommonPage from "../../../CommonPage"; + +export default class ClientScopesPage extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/client_scopes/CreateClientScopePage.ts b/cypress/support/pages/admin_console/manage/client_scopes/CreateClientScopePage.ts index cc349d4d21..225cb1907d 100644 --- a/cypress/support/pages/admin_console/manage/client_scopes/CreateClientScopePage.ts +++ b/cypress/support/pages/admin_console/manage/client_scopes/CreateClientScopePage.ts @@ -1,4 +1,6 @@ -export default class CreateClientScopePage { +import CommonPage from "../../../CommonPage"; + +export default class CreateClientScopePage extends CommonPage { settingsTab: string; mappersTab: string; clientScopeNameInput: string; @@ -14,6 +16,7 @@ export default class CreateClientScopePage { cancelBtn: string; constructor() { + super(); this.settingsTab = ".pf-c-tabs__item:nth-child(1)"; this.mappersTab = ".pf-c-tabs__item:nth-child(2)"; diff --git a/cypress/support/pages/admin_console/manage/clients/AuthorizationTab.ts b/cypress/support/pages/admin_console/manage/clients/AuthorizationTab.ts deleted file mode 100644 index 5b6cfdf3aa..0000000000 --- a/cypress/support/pages/admin_console/manage/clients/AuthorizationTab.ts +++ /dev/null @@ -1,189 +0,0 @@ -import type PolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/policyRepresentation"; -import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; -import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/scopeRepresentation"; -import grantClipboardAccess from "../../../../util/grantClipboardAccess"; - -type PermissionType = "resource" | "scope"; - -export default class AuthorizationTab { - private tabName = "authorizationTab"; - private resourcesTabName = "authorizationResources"; - private scopeTabName = "authorizationScopes"; - private policyTabName = "authorizationPolicies"; - private permissionsTabName = "authorizationPermissions"; - private exportTabName = "authorizationExport"; - private exportDownloadButton = "authorization-export-download"; - private exportCopyButton = "authorization-export-copy"; - private nameColumnPrefix = "name-column-"; - private emptyPolicyCreateButton = "no-policies-empty-action"; - private createPolicyButton = "createPolicy"; - private createResourceButton = "createResource"; - private createScopeButton = "no-authorization-scopes-empty-action"; - private createPermissionDropdown = "permissionCreateDropdown"; - private permissionResourceDropdown = "#resources"; - - goToAuthenticationTab() { - cy.findByTestId(this.tabName).click(); - return this; - } - - goToResourceSubTab() { - cy.findByTestId(this.resourcesTabName).click(); - return this; - } - - goToScopeSubTab() { - cy.findByTestId(this.scopeTabName).click(); - return this; - } - - goToPolicySubTab() { - cy.findByTestId(this.policyTabName).click(); - return this; - } - - goToPermissionsSubTab() { - cy.findByTestId(this.permissionsTabName).click(); - return this; - } - - goToExportSubTab() { - cy.intercept( - "/admin/realms/master/clients/*/authz/resource-server/settings" - ).as("export-load"); - cy.findByTestId(this.exportTabName).click(); - cy.wait(["@export-load"]); - return this; - } - - goToCreateResource() { - cy.findByTestId(this.createResourceButton).click(); - return this; - } - - goToCreateScope() { - cy.findByTestId(this.createScopeButton).click(); - return this; - } - - goToCreatePolicy(type: string, first: boolean | undefined = false) { - if (first) { - cy.findByTestId(this.emptyPolicyCreateButton).click(); - } else { - cy.findByTestId(this.createPolicyButton).click(); - } - cy.findByTestId(type).click(); - return this; - } - - goToCreatePermission(type: PermissionType) { - cy.findByTestId(this.createPermissionDropdown).click(); - cy.findByTestId(`create-${type}`).click(); - return this; - } - - fillBasePolicyForm(policy: { [key: string]: string }) { - Object.entries(policy).map(([key, value]) => - cy.findByTestId(key).type(value) - ); - return this; - } - - inputClient(clientName: string) { - cy.get("#clients").click(); - cy.get("ul li").contains(clientName).click(); - return this; - } - - fillResourceForm(resource: ResourceRepresentation) { - Object.entries(resource).map(([key, value]) => { - if (Array.isArray(value)) { - for (let index = 0; index < value.length; index++) { - const v = value[index]; - cy.get(`input[name="${key}[${index}]"]`).type(v); - cy.findByTestId("addValue").click(); - } - } else { - cy.get(`#${key}`).type(value); - } - }); - return this; - } - - fillScopeForm(scope: ScopeRepresentation) { - Object.entries(scope).map(([key, value]) => cy.get(`#${key}`).type(value)); - return this; - } - - fillPermissionForm(permission: PolicyRepresentation) { - Object.entries(permission).map(([key, value]) => - cy.get(`#${key}`).type(value) - ); - return this; - } - - selectResource(name: string) { - cy.get(this.permissionResourceDropdown) - .click() - .parent() - .parent() - .findByText(name) - .click(); - return this; - } - - setPolicy(policyName: string) { - cy.findByTestId(policyName).click(); - return this; - } - - copy() { - grantClipboardAccess(); - cy.get("#authorizationDetails").focus(); - cy.findByTestId(this.exportCopyButton).click(); - return this; - } - - export() { - cy.findByTestId(this.exportDownloadButton).click(); - return this; - } - - save() { - cy.findByTestId("save").click(); - return this; - } - - cancel() { - cy.findByTestId("cancel").click(); - return this; - } - - saveSettings() { - cy.findByTestId("authenticationSettingsSave").click(); - return this; - } - - pressCancel() { - cy.findByTestId("cancel").click(); - return this; - } - - private getResourceLink(name: string) { - return cy.findByTestId(this.nameColumnPrefix + name); - } - - goToResourceDetails(name: string) { - this.getResourceLink(name).click(); - return this; - } - - assertDefaultResource() { - return this.assertResource("Default Resource"); - } - - assertResource(name: string) { - this.getResourceLink(name).should("exist"); - return this; - } -} diff --git a/cypress/support/pages/admin_console/manage/clients/ClientRolesTab.ts b/cypress/support/pages/admin_console/manage/clients/ClientRolesTab.ts index 0f24322418..a642327388 100644 --- a/cypress/support/pages/admin_console/manage/clients/ClientRolesTab.ts +++ b/cypress/support/pages/admin_console/manage/clients/ClientRolesTab.ts @@ -1,16 +1,35 @@ -export default class ClientRolesTab { +import CommonPage from "../../../CommonPage"; + +enum ClientRolesTabItems { + Details = "Details", + Attributes = "Attributes", + UsersInRole = "Users in role", +} + +export default class ClientRolesTab extends CommonPage { private createRoleBtn = "create-role"; private createRoleEmptyStateBtn = "no-roles-for-this-client-empty-action"; private hideInheritedRolesChkBox = "#kc-hide-inherited-roles-checkbox"; - private rolesTab = "rolesTab"; private associatedRolesTab = ".kc-associated-roles-tab > button"; - private attributesTab = ".kc-attributes-tab > button"; private attributeKeyInput = "attribute-key-input"; private attributeValueInput = "attribute-value-input"; - private addAttributeButton = "attribute-add-row"; private removeFirstAttributeButton = "#minus-button-0"; - private saveAttributesButton = "save-attributes"; + + goToDetailsTab() { + this.tabUtils().clickTab(ClientRolesTabItems.Details); + return this; + } + + goToAttributesTab() { + this.tabUtils().clickTab(ClientRolesTabItems.Attributes); + return this; + } + + goToUsersInRoleTab() { + this.tabUtils().clickTab(ClientRolesTabItems.UsersInRole); + return this; + } goToRolesTab() { cy.findByTestId(this.rolesTab).click(); @@ -22,11 +41,6 @@ export default class ClientRolesTab { return this; } - goToAttributesTab() { - cy.get(this.attributesTab).click(); - return this; - } - goToCreateRoleFromToolbar() { cy.findByTestId(this.createRoleBtn).click(); return this; @@ -42,34 +56,32 @@ export default class ClientRolesTab { return this; } - saveAttribute() { - cy.findByTestId(this.saveAttributesButton).click(); + clickAddAnAttributeButton() { + this.tableUtils().clickRowItemByItemName("Add an attribute", 1, "button"); return this; } - addAttribute() { - cy.findByTestId(this.attributeKeyInput).type("crud_attribute_key"); - - cy.findByTestId(this.attributeValueInput).type("crud_attribute_value"); - - cy.findByTestId(this.addAttributeButton).click(); - - this.saveAttribute(); - - cy.get("table") - .should("have.class", "kc-attributes__table") - .get("tbody") - .children() - .should("have.length", 2); - + clickDeleteAttributeButton(row: number) { + this.tableUtils().clickRowItemByIndex(row, 3, "button"); return this; } - deleteAttribute() { - cy.get(this.removeFirstAttributeButton).click(); - this.saveAttribute(); - cy.findByTestId(this.attributeKeyInput).should("have.value", ""); - cy.findByTestId(this.attributeValueInput).should("have.value", ""); + addAttribute(rowIndex: number, key: string, value: string) { + this.tableUtils() + .typeValueToRowItem(rowIndex, 1, key) + .typeValueToRowItem(rowIndex, 2, value); + this.clickAddAnAttributeButton(); + this.formUtils().save(); + return this; + } + + deleteAttribute(rowIndex: number) { + this.clickDeleteAttributeButton(rowIndex); + this.formUtils().save(); + this.tableUtils() + .checkRowItemValueByIndex(rowIndex, 1, "", "input") + .checkRowItemValueByIndex(rowIndex, 2, "", "input"); + return this; } hideInheritedRoles() { diff --git a/cypress/support/pages/admin_console/manage/clients/ClientScopesTab.ts b/cypress/support/pages/admin_console/manage/clients/ClientScopesTab.ts deleted file mode 100644 index 7e9e2a6a8a..0000000000 --- a/cypress/support/pages/admin_console/manage/clients/ClientScopesTab.ts +++ /dev/null @@ -1,13 +0,0 @@ -export default class ClientScopesTab { - private clientScopesTab = "clientScopesTab"; - - goToClientScopesTab() { - cy.findByTestId(this.clientScopesTab).click(); - return this; - } - - clickDedicatedScope(clientId: string) { - cy.findByText(`${clientId}-dedicated`).click(); - return this; - } -} diff --git a/cypress/support/pages/admin_console/manage/clients/ClientsPage.ts b/cypress/support/pages/admin_console/manage/clients/ClientsPage.ts new file mode 100644 index 0000000000..039ae82a74 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/ClientsPage.ts @@ -0,0 +1,23 @@ +import CommonPage from "../../../CommonPage"; +import ClientsListTab from "./tabs/ClientsListTab"; +import InitialAccessTokenTab from "./tabs/InitialAccessTokenTab"; + +enum ClientsTab { + ClientsList = "Clients list", + InitialAccessToken = "Initial access token", +} + +export default class ClientsPage extends CommonPage { + private clientsListTab = new ClientsListTab(); + private initialAccessTokenTab = new InitialAccessTokenTab(); + + goToClientsListTab() { + this.tabUtils().clickTab(ClientsTab.ClientsList); + return this.clientsListTab; + } + + goToInitialAccessTokenTab() { + this.tabUtils().clickTab(ClientsTab.InitialAccessToken); + return this.initialAccessTokenTab; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts b/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts index daf0e5e530..305208483d 100644 --- a/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts +++ b/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts @@ -1,4 +1,6 @@ -export default class CreateClientPage { +import CommonPage from "../../../CommonPage"; + +export default class CreateClientPage extends CommonPage { private clientTypeDrpDwn = ".pf-c-select__toggle"; private clientTypeList = ".pf-c-select__toggle + ul"; private clientIdInput = "#kc-client-id"; diff --git a/cypress/support/pages/admin_console/manage/clients/CreateInitialAccessTokenPage.ts b/cypress/support/pages/admin_console/manage/clients/CreateInitialAccessTokenPage.ts new file mode 100644 index 0000000000..8010e295fb --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/CreateInitialAccessTokenPage.ts @@ -0,0 +1,18 @@ +import CommonPage from "../../../CommonPage"; + +export default class CreateInitialAccessTokenPage extends CommonPage { + private expirationInput = "expiration"; + private countInput = "count"; + private countPlusBtn = '[data-testid="count"] [aria-label="Plus"]'; + + fillNewTokenData(expiration: number, count: number) { + cy.findByTestId(this.expirationInput).clear().type(expiration.toString()); + cy.findByTestId(this.countInput).clear(); + + for (let i = 0; i < count; i++) { + cy.get(this.countPlusBtn).click(); + } + + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/ClientDetailsPage.ts b/cypress/support/pages/admin_console/manage/clients/client_details/ClientDetailsPage.ts new file mode 100644 index 0000000000..b46f95521c --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/ClientDetailsPage.ts @@ -0,0 +1,65 @@ +import CommonPage from "../../../../CommonPage"; +import AdvancedTab from "./tabs/AdvancedTab"; +import AuthorizationTab from "./tabs/AuthorizationTab"; +import ClientScopesTab from "./tabs/ClientScopesTab"; +import CredentialsTab from "./tabs/CredentialsTab"; +import KeysTab from "./tabs/KeysTab"; +import RolesTab from "./tabs/RolesTab"; +import SettingsTab from "./tabs/SettingsTab"; + +export enum ClientsDetailsTab { + Settings = "Settings", + Keys = "Keys", + Credentials = "Credentials", + Roles = "Roles", + ClientScopes = "Client scopes", + Authorization = "Authorization", + ServiceAccountsRoles = "Service accounts roles", + Advanced = "Advanced", + Scope = "Scope", +} + +export default class ClientDetailsPage extends CommonPage { + private settingsTab = new SettingsTab(); + private keysTab = new KeysTab(); + private credentialsTab = new CredentialsTab(); + private rolesTab = new RolesTab(); + private clientScopesTab = new ClientScopesTab(); + private authorizationTab = new AuthorizationTab(); + private advancedTab = new AdvancedTab(); + + goToSettingsTab() { + this.tabUtils().clickTab(ClientsDetailsTab.Settings); + return this.settingsTab; + } + + goToKeysTab() { + this.tabUtils().clickTab(ClientsDetailsTab.Keys); + return this.keysTab; + } + + goToCredentials() { + this.tabUtils().clickTab(ClientsDetailsTab.Credentials); + return this.credentialsTab; + } + + goToRolesTab() { + this.tabUtils().clickTab(ClientsDetailsTab.Roles); + return this.rolesTab; + } + + goToClientScopesTab() { + this.tabUtils().clickTab(ClientsDetailsTab.ClientScopes); + return this.clientScopesTab; + } + + goToAuthorizationTab() { + this.tabUtils().clickTab(ClientsDetailsTab.Authorization); + return this.authorizationTab; + } + + goToAdvancedTab() { + this.tabUtils().clickTab(ClientsDetailsTab.Advanced); + return this.advancedTab; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/CreateAuthorizationScopePage.ts b/cypress/support/pages/admin_console/manage/clients/client_details/CreateAuthorizationScopePage.ts new file mode 100644 index 0000000000..acffbf8b41 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/CreateAuthorizationScopePage.ts @@ -0,0 +1,9 @@ +import CommonPage from "../../../../CommonPage"; +import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/scopeRepresentation"; + +export default class CreateAuthorizationScopePage extends CommonPage { + fillScopeForm(scope: ScopeRepresentation) { + Object.entries(scope).map(([key, value]) => cy.get(`#${key}`).type(value)); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/CreatePermissionPage.ts b/cypress/support/pages/admin_console/manage/clients/client_details/CreatePermissionPage.ts new file mode 100644 index 0000000000..ea4c422060 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/CreatePermissionPage.ts @@ -0,0 +1,11 @@ +import CommonPage from "../../../../CommonPage"; +import type PolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/policyRepresentation"; + +export default class CreatePermissionPage extends CommonPage { + fillPermissionForm(permission: PolicyRepresentation) { + Object.entries(permission).map(([key, value]) => + cy.get(`#${key}`).type(value) + ); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/CreateResourcePage.ts b/cypress/support/pages/admin_console/manage/clients/client_details/CreateResourcePage.ts new file mode 100644 index 0000000000..e9d4c6b300 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/CreateResourcePage.ts @@ -0,0 +1,19 @@ +import CommonPage from "../../../../CommonPage"; +import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; + +export default class CreateResourcePage extends CommonPage { + fillResourceForm(resource: ResourceRepresentation) { + Object.entries(resource).map(([key, value]) => { + if (Array.isArray(value)) { + for (let index = 0; index < value.length; index++) { + const v = value[index]; + cy.get(`input[name="${key}[${index}]"]`).type(v); + cy.findByTestId("addValue").click(); + } + } else { + cy.get(`#${key}`).type(value); + } + }); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesMappersTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesMappersTab.ts new file mode 100644 index 0000000000..d16391a68e --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesMappersTab.ts @@ -0,0 +1,43 @@ +import CommonPage from "../../../../CommonPage"; + +enum mapperType { + FromPredefinedMappers = "From predefined mappers", + ByConfiguration = "By configuration", +} + +enum mapperTypeEmptyState { + AddPredefinedMapper = "Add predefined mapper", + ConfigureaNewMapper = "Configure a new mapper", +} + +export default class DedicatedScopesMappersTab extends CommonPage { + addMapperFromPredefinedMappers() { + this.emptyState().checkIfExists(false); + this.tableToolbarUtils() + .addMapper() + .clickDropdownMenuItem(mapperType.ByConfiguration); + return this; + } + + addMapperByConfiguration() { + this.emptyState().checkIfExists(false); + this.tableToolbarUtils() + .addMapper() + .clickDropdownMenuItem(mapperType.FromPredefinedMappers); + return this; + } + + addPredefinedMapper() { + this.emptyState() + .checkIfExists(true) + .clickSecondaryBtn(mapperTypeEmptyState.AddPredefinedMapper); + return this; + } + + configureNewMapper() { + this.emptyState() + .checkIfExists(true) + .clickSecondaryBtn(mapperTypeEmptyState.ConfigureaNewMapper); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesPage.ts b/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesPage.ts new file mode 100644 index 0000000000..76539251e3 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesPage.ts @@ -0,0 +1,23 @@ +import CommonPage from "../../../../CommonPage"; +import DedicatedScopesMappersTab from "./DedicatedScopesMappersTab"; +import DedicatedScopesScopeTab from "./DedicatedScopesScopeTab"; + +export enum DedicatedScopesTab { + Mappers = "Mappers", + Scope = "Scope", +} + +export default class DedicatedScopesPage extends CommonPage { + private mappersTab = new DedicatedScopesMappersTab(); + private scopeTab = new DedicatedScopesScopeTab(); + + goToMappersTab() { + this.tabUtils().clickTab(DedicatedScopesTab.Mappers); + return this.mappersTab; + } + + goToScopeTab() { + this.tabUtils().clickTab(DedicatedScopesTab.Scope); + return this.scopeTab; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesScopeTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesScopeTab.ts new file mode 100644 index 0000000000..c7a145d7e1 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/DedicatedScopesScopeTab.ts @@ -0,0 +1,3 @@ +import CommonPage from "../../../../CommonPage"; + +export default class DedicatedScopesScopeTab extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/clients/AdvancedTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/AdvancedTab.ts similarity index 93% rename from cypress/support/pages/admin_console/manage/clients/AdvancedTab.ts rename to cypress/support/pages/admin_console/manage/clients/client_details/tabs/AdvancedTab.ts index eb747f4934..d1a3a2d28b 100644 --- a/cypress/support/pages/admin_console/manage/clients/AdvancedTab.ts +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/AdvancedTab.ts @@ -1,6 +1,7 @@ import moment from "moment"; +import CommonPage from "../../../../../CommonPage"; -export default class AdvancedTab { +export default class AdvancedTab extends CommonPage { private setToNowBtn = "#setToNow"; private clearBtn = "#clear"; private pushBtn = "#push"; @@ -17,13 +18,6 @@ export default class AdvancedTab { private fineGrainSaveBtn = "#fineGrainSave"; private fineGrainRevertBtn = "#fineGrainRevert"; - private advancedTab = "advancedTab"; - - goToAdvancedTab() { - cy.findByTestId(this.advancedTab).click(); - return this; - } - setRevocationToNow() { cy.get(this.setToNowBtn).click(); return this; diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/AuthorizationTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/AuthorizationTab.ts new file mode 100644 index 0000000000..1c5d81b8fa --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/AuthorizationTab.ts @@ -0,0 +1,63 @@ +import CommonPage from "../../../../../CommonPage"; +import SettingsTab from "./authorization_subtabs/SettingsTab"; +import ResourcesTab from "./authorization_subtabs/ResourcesTab"; +import ScopesTab from "./authorization_subtabs/ScopesTab"; +import PoliciesTab from "./authorization_subtabs/PoliciesTab"; +import PermissionsTab from "./authorization_subtabs/PermissionsTab"; +import EvaluateTab from "./authorization_subtabs/EvaluateTab"; +import ExportTab from "./authorization_subtabs/ExportTab"; + +enum AuthorizationSubTab { + Settings = "Settings", + Resources = "Resources", + Scopes = "Scopes", + Policies = "Policies", + Permissions = "Permissions", + Evaluate = "Evaluate", + Export = "Export", +} + +export default class AuthorizationTab extends CommonPage { + private settingsSubTab = new SettingsTab(); + private resourcesSubTab = new ResourcesTab(); + private scopesSubTab = new ScopesTab(); + private policiesSubTab = new PoliciesTab(); + private permissionsSubTab = new PermissionsTab(); + private evaluateSubTab = new EvaluateTab(); + private exportSubTab = new ExportTab(); + + goToSettingsSubTab() { + this.tabUtils().clickTab(AuthorizationSubTab.Settings); + return this.settingsSubTab; + } + + goToResourcesSubTab() { + this.tabUtils().clickTab(AuthorizationSubTab.Resources); + return this.resourcesSubTab; + } + + goToScopesSubTab() { + this.tabUtils().clickTab(AuthorizationSubTab.Scopes); + return this.scopesSubTab; + } + + goToPoliciesSubTab() { + this.tabUtils().clickTab(AuthorizationSubTab.Policies); + return this.policiesSubTab; + } + + goToPermissionsSubTab() { + this.tabUtils().clickTab(AuthorizationSubTab.Permissions); + return this.permissionsSubTab; + } + + goToEvaluateSubTab() { + this.tabUtils().clickTab(AuthorizationSubTab.Evaluate); + return this.evaluateSubTab; + } + + goToExportSubTab() { + this.tabUtils().clickTab(AuthorizationSubTab.Export); + return this.exportSubTab; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/ClientScopesTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/ClientScopesTab.ts new file mode 100644 index 0000000000..5df3b8c519 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/ClientScopesTab.ts @@ -0,0 +1,30 @@ +import CommonPage from "../../../../../CommonPage"; +import SetupTab from "./clientscopes_subtabs/SetupTab"; +import EvaluateTab from "./clientscopes_subtabs/EvaluateTab"; +import DedicatedScopesPage from "../DedicatedScopesPage"; + +enum ClientScopesSubTab { + Setup = "Setup", + Evaluate = "Evaluate", +} + +export default class ClientScopesTab extends CommonPage { + private setupSubTab = new SetupTab(); + private evaluateSubTab = new EvaluateTab(); + private dedicatedScopesPage = new DedicatedScopesPage(); + + goToSetupSubTab() { + this.tabUtils().clickTab(ClientScopesSubTab.Setup); + return this.setupSubTab; + } + + goToEvaluateSubTab() { + this.tabUtils().clickTab(ClientScopesSubTab.Evaluate); + return this.evaluateSubTab; + } + + clickDedicatedScope(clientId: string) { + cy.findByText(`${clientId}-dedicated`).click(); + return this.dedicatedScopesPage; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/CredentialsTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/CredentialsTab.ts new file mode 100644 index 0000000000..348b8c2c9d --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/CredentialsTab.ts @@ -0,0 +1,3 @@ +import CommonPage from "../../../../../CommonPage"; + +export default class CredentialsTab extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/clients/KeysTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/KeysTab.ts similarity index 56% rename from cypress/support/pages/admin_console/manage/clients/KeysTab.ts rename to cypress/support/pages/admin_console/manage/clients/client_details/tabs/KeysTab.ts index dcdb577939..e4c0c93d52 100644 --- a/cypress/support/pages/admin_console/manage/clients/KeysTab.ts +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/KeysTab.ts @@ -1,24 +1,12 @@ -export default class KeysTab { - private tabName = "keysTab"; +import CommonPage from "../../../../../CommonPage"; + +export default class KeysTab extends CommonPage { + private generateBtn = "generate"; + private confirmBtn = "confirm"; private useJwksUrl = "useJwksUrl"; - private saveKeys = "saveKeys"; - private generate = "generate"; private keyAlias = "keyAlias"; private keyPassword = "keyPassword"; private storePassword = "storePassword"; - private confirm = "confirm"; - - goToTab() { - cy.findByTestId(this.tabName).click(); - return this; - } - - checkSaveDisabled(disabled = true) { - cy.findByTestId(this.saveKeys).should( - (!disabled ? "not." : "") + "be.disabled" - ); - return this; - } toggleUseJwksUrl() { cy.findByTestId(this.useJwksUrl).click({ force: true }); @@ -26,12 +14,12 @@ export default class KeysTab { } clickGenerate() { - cy.findByTestId(this.generate).click(); + cy.findByTestId(this.generateBtn).click(); return this; } clickConfirm() { - cy.findByTestId(this.confirm).click(); + cy.findByTestId(this.confirmBtn).click(); return this; } diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/RolesTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/RolesTab.ts new file mode 100644 index 0000000000..a192e1c1b9 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/RolesTab.ts @@ -0,0 +1,3 @@ +import CommonPage from "../../../../../CommonPage"; + +export default class RolesTab extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/SettingsTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/SettingsTab.ts new file mode 100644 index 0000000000..3880cf38d2 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/SettingsTab.ts @@ -0,0 +1,3 @@ +import CommonPage from "../../../../../CommonPage"; + +export default class SettingsTab extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/EvaluateTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/EvaluateTab.ts new file mode 100644 index 0000000000..dfd3ff9307 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/EvaluateTab.ts @@ -0,0 +1,3 @@ +import CommonPage from "../../../../../../CommonPage"; + +export default class EvaluateTab extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ExportTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ExportTab.ts new file mode 100644 index 0000000000..2fd08a6f1e --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ExportTab.ts @@ -0,0 +1,18 @@ +import grantClipboardAccess from "../../../../../../../util/grantClipboardAccess"; +import CommonPage from "../../../../../../CommonPage"; + +export default class ExportTab extends CommonPage { + private exportDownloadBtn = "authorization-export-download"; + private exportCopyBtn = "authorization-export-copy"; + + copy() { + grantClipboardAccess(); + cy.findByTestId(this.exportCopyBtn).click(); + return this; + } + + export() { + cy.findByTestId(this.exportDownloadBtn).click(); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/PermissionsTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/PermissionsTab.ts new file mode 100644 index 0000000000..633407bd58 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/PermissionsTab.ts @@ -0,0 +1,25 @@ +import CommonPage from "../../../../../../CommonPage"; +import CreatePermissionPage from "../../CreatePermissionPage"; +type PermissionType = "resource" | "scope"; + +export default class PermissionsTab extends CommonPage { + private createPermissionPage = new CreatePermissionPage(); + private createPermissionDrpDwn = "permissionCreateDropdown"; + private permissionResourceDrpDwn = "#resources"; + + createPermission(type: PermissionType) { + cy.findByTestId(this.createPermissionDrpDwn).click(); + cy.findByTestId(`create-${type}`).click(); + return this.createPermissionPage; + } + + selectResource(name: string) { + cy.get(this.permissionResourceDrpDwn) + .click() + .parent() + .parent() + .findByText(name) + .click(); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/PoliciesTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/PoliciesTab.ts new file mode 100644 index 0000000000..5eb8d421cf --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/PoliciesTab.ts @@ -0,0 +1,34 @@ +import CommonPage from "../../../../../../CommonPage"; + +export default class PoliciesTab extends CommonPage { + private emptyPolicyCreateBtn = "no-policies-empty-action"; + private createPolicyBtn = "createPolicy"; + + createPolicy(type: string, first = false) { + if (first) { + cy.findByTestId(this.emptyPolicyCreateBtn).click(); + } else { + cy.findByTestId(this.createPolicyBtn).click(); + } + cy.findByTestId(type).click(); + return this; + } + + fillBasePolicyForm(policy: { [key: string]: string }) { + Object.entries(policy).map(([key, value]) => + cy.findByTestId(key).type(value) + ); + return this; + } + + setPolicy(policyName: string) { + cy.findByTestId(policyName).click(); + return this; + } + + inputClient(clientName: string) { + cy.get("#clients").click(); + cy.get("ul li").contains(clientName).click(); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ResourcesTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ResourcesTab.ts new file mode 100644 index 0000000000..4736a1e285 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ResourcesTab.ts @@ -0,0 +1,13 @@ +import CommonPage from "../../../../../../CommonPage"; +import CreateResourcePage from "../../CreateResourcePage"; + +export default class ResourcesTab extends CommonPage { + private createResourcePage = new CreateResourcePage(); + private createResourceBtn = "createResource"; + + createResource() { + cy.findByTestId(this.createResourceBtn).click(); + + return this.createResourcePage; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ScopesTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ScopesTab.ts new file mode 100644 index 0000000000..5cc8af97e8 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/ScopesTab.ts @@ -0,0 +1,12 @@ +import CommonPage from "../../../../../../CommonPage"; +import CreateAuthorizationScopePage from "../../CreateAuthorizationScopePage"; + +export default class ScopesTab extends CommonPage { + private createAuthorizationScopePage = new CreateAuthorizationScopePage(); + private createScopeBtn = "no-authorization-scopes-empty-action"; + + createAuthorizationScope() { + cy.findByTestId(this.createScopeBtn).click(); + return this.createAuthorizationScopePage; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/SettingsTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/SettingsTab.ts new file mode 100644 index 0000000000..9e5b81876e --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/authorization_subtabs/SettingsTab.ts @@ -0,0 +1,8 @@ +import CommonPage from "../../../../../../CommonPage"; + +export default class SettingsTab extends CommonPage { + saveSettings() { + cy.findByTestId("authenticationSettingsSave").click(); + return this; + } +} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/clientscopes_subtabs/EvaluateTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/clientscopes_subtabs/EvaluateTab.ts new file mode 100644 index 0000000000..dfd3ff9307 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/clientscopes_subtabs/EvaluateTab.ts @@ -0,0 +1,3 @@ +import CommonPage from "../../../../../../CommonPage"; + +export default class EvaluateTab extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/clients/client_details/tabs/clientscopes_subtabs/SetupTab.ts b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/clientscopes_subtabs/SetupTab.ts new file mode 100644 index 0000000000..981cb72ba8 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/client_details/tabs/clientscopes_subtabs/SetupTab.ts @@ -0,0 +1,14 @@ +import CommonPage from "../../../../../../CommonPage"; + +export enum SetupTabFilterItem { + Name = "Name", + AssignedType = "Assigned type", +} + +export enum SetupTabAssignedTypeItem { + AllTypes = "All types", + Default = "Default", + Optional = "Optional", +} + +export default class SetupTab extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/clients/tabs/ClientsListTab.ts b/cypress/support/pages/admin_console/manage/clients/tabs/ClientsListTab.ts new file mode 100644 index 0000000000..3423a24f06 --- /dev/null +++ b/cypress/support/pages/admin_console/manage/clients/tabs/ClientsListTab.ts @@ -0,0 +1,3 @@ +import CommonPage from "../../../../CommonPage"; + +export default class ClientsListTab extends CommonPage {} diff --git a/cypress/support/pages/admin_console/manage/clients/InitialAccessTokenTab.ts b/cypress/support/pages/admin_console/manage/clients/tabs/InitialAccessTokenTab.ts similarity index 94% rename from cypress/support/pages/admin_console/manage/clients/InitialAccessTokenTab.ts rename to cypress/support/pages/admin_console/manage/clients/tabs/InitialAccessTokenTab.ts index fccc13a7f1..0958922797 100644 --- a/cypress/support/pages/admin_console/manage/clients/InitialAccessTokenTab.ts +++ b/cypress/support/pages/admin_console/manage/clients/tabs/InitialAccessTokenTab.ts @@ -1,4 +1,6 @@ -export default class InitialAccessTokenTab { +import CommonPage from "../../../../CommonPage"; + +export default class InitialAccessTokenTab extends CommonPage { private initialAccessTokenTab = "initialAccessToken"; private emptyAction = "no-initial-access-tokens-empty-action"; diff --git a/cypress/support/util/ModalUtils.ts b/cypress/support/util/ModalUtils.ts index c581262512..f24ac85bf2 100644 --- a/cypress/support/util/ModalUtils.ts +++ b/cypress/support/util/ModalUtils.ts @@ -1,13 +1,29 @@ -export default class ModalUtils { +import TablePage from "../pages/admin_console/components/TablePage"; +import CommonElements from "../pages/CommonElements"; + +export default class ModalUtils extends CommonElements { private modalTitle = ".pf-c-modal-box .pf-c-modal-box__title-text"; private modalMessage = ".pf-c-modal-box .pf-c-modal-box__body"; - private confirmModalBtn = "confirm"; private cancelModalBtn = "cancel"; private closeModalBtn = ".pf-c-modal-box .pf-m-plain"; private copyToClipboardBtn = '[id*="copy-button"]'; private addModalDropdownBtn = "#add-dropdown > button"; private addModalDropdownItem = "#add-dropdown [role='menuitem']"; + private tablePage = new TablePage(TablePage.tableSelector); + + constructor() { + super(".pf-c-modal-box"); + } + + table() { + return this.tablePage; + } + + add() { + cy.get(this.primaryBtn).contains("Add").click(); + return this; + } confirmModal() { cy.findByTestId(this.confirmModalBtn).click({ force: true });