From 83d9018f6d3214c1360f7122cacf7e39be0783aa Mon Sep 17 00:00:00 2001 From: ikhomyn <89014675+ikhomyn@users.noreply.github.com> Date: Tue, 22 Feb 2022 13:46:49 +0100 Subject: [PATCH] new Client->details->ClientScopes and ClientScopes tests (#1967) --- .../integration/client_scopes_test.spec.ts | 278 +++++++++++++++--- cypress/integration/clients_test.spec.ts | 130 +++++++- .../pages/admin_console/ListingPage.ts | 200 +++++++++++++ cypress/support/util/AdminClient.ts | 9 + cypress/support/util/ModalUtils.ts | 9 + src/client-scopes/ChangeTypeDropdown.tsx | 2 +- src/client-scopes/ClientScopesSection.tsx | 9 +- src/clients/scopes/ClientScopes.tsx | 1 - 8 files changed, 593 insertions(+), 45 deletions(-) diff --git a/cypress/integration/client_scopes_test.spec.ts b/cypress/integration/client_scopes_test.spec.ts index 3a0b5ca3b3..46dac263f4 100644 --- a/cypress/integration/client_scopes_test.spec.ts +++ b/cypress/integration/client_scopes_test.spec.ts @@ -1,9 +1,16 @@ import LoginPage from "../support/pages/LoginPage"; import Masthead from "../support/pages/admin_console/Masthead"; -import ListingPage from "../support/pages/admin_console/ListingPage"; +import ListingPage, { + Filter, + FilterAssignedType, + FilterProtocol, +} from "../support/pages/admin_console/ListingPage"; import SidebarPage from "../support/pages/admin_console/SidebarPage"; import CreateClientScopePage from "../support/pages/admin_console/manage/client_scopes/CreateClientScopePage"; -import { keycloakBefore } from "../support/util/keycloak_hooks"; +import { + keycloakBefore, + keycloakBeforeEach, +} from "../support/util/keycloak_hooks"; import RoleMappingTab from "../support/pages/admin_console/manage/RoleMappingTab"; import ModalUtils from "../support/util/ModalUtils"; import AdminClient from "../support/util/AdminClient"; @@ -17,56 +24,261 @@ const createClientScopePage = new CreateClientScopePage(); const modalUtils = new ModalUtils(); describe("Client Scopes test", () => { - describe("Client Scope list items ", () => { - const clientScopeName = "client-scope-test"; - const clientScope = { - name: clientScopeName, - description: "", - protocol: "openid-connect", - attributes: { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "gui.order": "1", - "consent.screen.text": "", - }, - }; + const modalMessageDeleteConfirmation = + "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 = { + name: clientScopeName, + description: "", + protocol: "openid-connect", + attributes: { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "gui.order": "1", + "consent.screen.text": "", + }, + }; - before(async () => { - const client = new AdminClient(); - for (let i = 0; i < 5; i++) { - clientScope.name = clientScopeName + i; - await client.createClientScope(clientScope); + before(async () => { + const client = new AdminClient(); + for (let i = 0; i < 5; i++) { + clientScope.name = clientScopeName + i; + await client.createClientScope(clientScope); + } + }); + + after(async () => { + const client = new AdminClient(); + for (let i = 0; i < 5; i++) { + if (await client.existsClientScope(clientScopeName + i)) { + await client.deleteClientScope(clientScopeName + i); } + } + }); + + describe("Client Scope filter list items", () => { + before(() => { + keycloakBefore(); + loginPage.logIn(); }); beforeEach(() => { - keycloakBefore(); - loginPage.logIn(); + keycloakBeforeEach(); sidebarPage.goToClientScopes(); }); - after(async () => { - const client = new AdminClient(); - for (let i = 0; i < 5; i++) { - await client.deleteClientScope(clientScopeName + i); - } + it("should filter item by name", () => { + const itemName = clientScopeName + 0; + listingPage + .searchItem(itemName, false) + .itemsEqualTo(1) + .itemExist(itemName, true); + }); + + it("should filter items by Assigned type All types", () => { + listingPage + .selectFilter(Filter.AssignedType) + .selectSecondaryFilterAssignedType(FilterAssignedType.AllTypes) + .itemExist(FilterAssignedType.Default, true) + .itemExist(FilterAssignedType.Optional, true) + .itemExist(FilterAssignedType.None, true); + }); + + it("should filter items by Assigned type Default", () => { + listingPage + .selectFilter(Filter.AssignedType) + .selectSecondaryFilterAssignedType(FilterAssignedType.Default) + .itemExist(FilterAssignedType.Default, true) + .itemExist(FilterAssignedType.Optional, false) + .itemExist(FilterAssignedType.None, false); + }); + + it("should filter items by Assigned type Optional", () => { + listingPage + .selectFilter(Filter.AssignedType) + .selectSecondaryFilterAssignedType(FilterAssignedType.Optional) + .itemExist(FilterAssignedType.Default, false) + .itemExist(FilterAssignedType.Optional, true) + .itemExist(FilterAssignedType.None, false); + }); + + //TODO https://github.com/keycloak/keycloak-admin-ui/issues/1959 + it("should filter items by Protocol All", () => { + listingPage + .selectFilter(Filter.Protocol) + .selectSecondaryFilterProtocol(FilterProtocol.All) + .showNextPageTableItems() + .itemExist(FilterProtocol.SAML, true) + .itemExist(openIDConnectItemText, true); //using FilterProtocol.OpenID will fail, text does not match. + }); + + //TODO https://github.com/keycloak/keycloak-admin-ui/issues/1959 + it("should filter items by Protocol SAML", () => { + listingPage + .selectFilter(Filter.Protocol) + .selectSecondaryFilterProtocol(FilterProtocol.SAML) + .itemExist(FilterProtocol.SAML, true) + .itemExist(openIDConnectItemText, false); //using FilterProtocol.OpenID will fail, text does not match. + }); + + //TODO https://github.com/keycloak/keycloak-admin-ui/issues/1959 + it("should filter items by Protocol OpenID", () => { + listingPage + .selectFilter(Filter.Protocol) + .selectSecondaryFilterProtocol(FilterProtocol.OpenID) + .itemExist(FilterProtocol.SAML, false) + .itemExist(openIDConnectItemText, true); //using FilterProtocol.OpenID will fail, text does not match. }); it("should show items on next page are more than 11", () => { listingPage.showNextPageTableItems(); + listingPage.itemsGreaterThan(1); + }); + }); - cy.get(listingPage.tableRowItem).its("length").should("be.gt", 1); + describe("Client Scope modify list items", () => { + const itemName = clientScopeName + 0; + before(() => { + keycloakBefore(); + loginPage.logIn(); + }); + + beforeEach(() => { + keycloakBeforeEach(); + sidebarPage.goToClientScopes(); + }); + + it("should modify selected item type to Default from search bar", () => { + listingPage + .clickItemCheckbox(itemName) + .changeTypeToOfSelectedItems(FilterAssignedType.Default); + listingPage.itemContainValue(itemName, 2, FilterAssignedType.Default); + }); + + it("should modify selected item type to Optional from search bar", () => { + listingPage + .clickItemCheckbox(itemName) + .changeTypeToOfSelectedItems(FilterAssignedType.Optional); + listingPage.itemContainValue(itemName, 2, FilterAssignedType.Optional); + }); + + const expectedItemAssignedTypes = [ + FilterAssignedType.Default, + FilterAssignedType.Optional, + FilterAssignedType.None, + ]; + expectedItemAssignedTypes.forEach(($assignedType) => { + const itemName = clientScopeName + 0; + it(`should modify item ${itemName} AssignedType to ${$assignedType} from item bar`, () => { + listingPage + .searchItem(clientScopeName, false) + .clickRowSelectItem(itemName, $assignedType); + // sidebarPage.waitForPageLoad(); //not working + cy.wait(2000); + listingPage.searchItem(itemName, false).itemExist($assignedType); + }); + }); + + it("should not allow to modify item AssignedType from search bar when no item selected", () => { + const itemName = clientScopeName + 0; + listingPage + .searchItem(itemName, false) + .checkInSearchBarChangeTypeToButtonIsDisabled() + .clickSearchBarActionButton() + .checkDropdownItemIsDisabled("Delete") + .clickItemCheckbox(itemName) + .checkInSearchBarChangeTypeToButtonIsDisabled(false) + .clickSearchBarActionButton() + .checkDropdownItemIsDisabled("Delete", false) + .clickItemCheckbox(itemName) + .checkInSearchBarChangeTypeToButtonIsDisabled() + .clickSearchBarActionButton() + .checkDropdownItemIsDisabled("Delete"); + }); + + //TODO: blocked by https://github.com/keycloak/keycloak-admin-ui/issues/1952 + //it("should export item from item bar", () => { + + //}); + }); + + describe("Client Scope delete list items ", () => { + before(() => { + keycloakBefore(); + loginPage.logIn(); + }); + + beforeEach(() => { + keycloakBeforeEach(); + sidebarPage.goToClientScopes(); + }); + + //TODO: Partially blocked by https://github.com/keycloak/keycloak-admin-ui/issues/1854 + it("should delete item from item bar", () => { + listingPage + .checkInSearchBarChangeTypeToButtonIsDisabled() + .clickItemCheckbox(clientScopeName + 0) + .deleteItem(clientScopeName + 0); + modalUtils + .checkModalMessage(modalMessageDeleteConfirmation) + .confirmModal(); + masthead.checkNotificationMessage( + notificationMessageDeletionConfirmation + ); + //listingPage.checkInSearchBarChangeTypeToButtonIsDisabled(); + }); + + //TODO: Partially blocked by https://github.com/keycloak/keycloak-admin-ui/issues/1854 + it("should delete selected item from search bar", () => { + listingPage + .checkInSearchBarChangeTypeToButtonIsDisabled() + .clickItemCheckbox(clientScopeName + 1) + .clickSearchBarActionButton() + .clickSearchBarActionItem("Delete"); + modalUtils + .checkModalMessage(modalMessageDeleteConfirmation) + .confirmModal(); + masthead.checkNotificationMessage( + notificationMessageDeletionConfirmation + ); + //listingPage.checkInSearchBarChangeTypeToButtonIsDisabled(); + }); + + //TODO: Partially blocked by https://github.com/keycloak/keycloak-admin-ui/issues/1854 + it("should delete multiple selected items from search bar", () => { + listingPage + .checkInSearchBarChangeTypeToButtonIsDisabled() + .clickItemCheckbox(clientScopeName + 2) + .clickItemCheckbox(clientScopeName + 3) + .clickItemCheckbox(clientScopeName + 4) + .clickSearchBarActionButton() + .clickSearchBarActionItem("Delete"); + modalUtils + .checkModalMessage(modalMessageDeleteConfirmation) + .confirmModal(); + masthead.checkNotificationMessage( + notificationMessageDeletionConfirmation + ); + //listingPage.checkInSearchBarChangeTypeToButtonIsDisabled(); }); }); describe("Client Scope creation", () => { - beforeEach(() => { + before(() => { keycloakBefore(); loginPage.logIn(); + }); + + beforeEach(() => { + keycloakBeforeEach(); sidebarPage.goToClientScopes(); }); it("should fail creating client scope", () => { + sidebarPage.waitForPageLoad(); listingPage.goToCreateItem(); createClientScopePage.save().checkClientNameRequiredMessage(); @@ -102,7 +314,7 @@ describe("Client Scopes test", () => { .deleteItem(itemId); modalUtils - .checkModalMessage("Are you sure you want to delete this client scope") + .checkModalMessage(modalMessageDeleteConfirmation) .confirmModal(); masthead.checkNotificationMessage("The client scope has been deleted"); @@ -115,12 +327,6 @@ describe("Client Scopes test", () => { const scopeTab = new RoleMappingTab(); const scopeName = "address"; - beforeEach(() => { - keycloakBefore(); - loginPage.logIn(); - sidebarPage.goToClientScopes(); - }); - it("Assign role", () => { const role = "offline_access"; listingPage.searchItem(scopeName, false).goToItemDetails(scopeName); diff --git a/cypress/integration/clients_test.spec.ts b/cypress/integration/clients_test.spec.ts index 4f31efe140..d0ba790af9 100644 --- a/cypress/integration/clients_test.spec.ts +++ b/cypress/integration/clients_test.spec.ts @@ -1,6 +1,9 @@ import LoginPage from "../support/pages/LoginPage"; import Masthead from "../support/pages/admin_console/Masthead"; -import ListingPage from "../support/pages/admin_console/ListingPage"; +import ListingPage, { + 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"; @@ -25,10 +28,12 @@ const modalUtils = new ModalUtils(); describe("Clients test", () => { describe("Client details - Client scopes subtab", () => { - const clientScopesTab = new ClientScopesTab(); const client = new AdminClient(); + const clientScopesTab = new ClientScopesTab(); const clientId = "client-scopes-subtab-test"; const clientScopeName = "client-scope-test"; + const clientScopeNameDefaultType = "client-scope-test-default-type"; + const clientScopeNameOptionalType = "client-scope-test-optional-type"; const clientScope = { name: clientScopeName, description: "", @@ -40,6 +45,7 @@ describe("Clients test", () => { "consent.screen.text": "", }, }; + const msgScopeMappingRemoved = "Scope mapping successfully removed"; before(async () => { client.createClient({ @@ -55,6 +61,10 @@ describe("Clients test", () => { clientId ); } + clientScope.name = clientScopeNameDefaultType; + await client.createClientScope(clientScope); + clientScope.name = clientScopeNameOptionalType; + await client.createClientScope(clientScope); }); beforeEach(() => { @@ -72,12 +82,124 @@ describe("Clients test", () => { for (let i = 0; i < 5; i++) { await client.deleteClientScope(clientScopeName + i); } + await client.deleteClientScope(clientScopeNameDefaultType); + await client.deleteClientScope(clientScopeNameOptionalType); + }); + + it("should list client scopes", () => { + listingPage.itemsGreaterThan(1).itemExist(clientScopeName + 0); + }); + + it("should search existing client scope by name", () => { + listingPage + .searchItem(clientScopeName + 0, false) + .itemExist(clientScopeName + 0) + .itemsEqualTo(2); + }); + + it("should search non-existent client scope by name", () => { + const itemName = "non-existent-item"; + listingPage.searchItem(itemName, false).checkTableExists(false); + }); + + 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); + }); + + /*it("should empty search", () => { + + });*/ + + const newItemsWithExpectedAssignedTypes = [ + [clientScopeNameOptionalType, FilterAssignedType.Optional], + [clientScopeNameDefaultType, FilterAssignedType.Default], + ]; + 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); + }); + }); + + const expectedItemAssignedTypes = [ + FilterAssignedType.Optional, + FilterAssignedType.Default, + ]; + 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); + }); }); it("should show items on next page are more than 11", () => { - listingPage.showNextPageTableItems(); - cy.get(listingPage.tableRowItem).its("length").should("be.gt", 1); + listingPage.showNextPageTableItems().itemsGreaterThan(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); + }); + + /*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"); + }); + + //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); + });*/ }); describe("Client creation", () => { diff --git a/cypress/support/pages/admin_console/ListingPage.ts b/cypress/support/pages/admin_console/ListingPage.ts index f2d46768c4..05c38cfc94 100644 --- a/cypress/support/pages/admin_console/ListingPage.ts +++ b/cypress/support/pages/admin_console/ListingPage.ts @@ -1,10 +1,41 @@ +export enum Filter { + Name = "Name", + AssignedType = "Assigned type", + Protocol = "Protocol", +} + +export enum FilterAssignedType { + AllTypes = "All types", + Default = "Default", + Optional = "Optional", + None = "None", +} + +export enum FilterProtocol { + All = "All", + SAML = "SAML", + OpenID = "openid-connect", //TODO: text to be unified with item text +} + +export enum FilterSession { + AllSessionTypes = "All session types", + RegularSSO = "Regular SSO", + Offline = "Offline", + DirectGrant = "Direct grant", + ServiceAccount = "Service account", +} + export default class ListingPage { private searchInput = '.pf-c-toolbar__item [type="search"]:visible'; + private tableToolbar = ".pf-c-toolbar"; private itemsRows = "table:visible"; private emptyListImg = '[role="tabpanel"]:not([hidden]) [data-testid="empty-state"]'; private progressBar = '[role="progressbar"]'; private itemRowDrpDwn = ".pf-c-dropdown__toggle"; + private itemRowSelect = ".pf-c-select__toggle:nth-child(1)"; + private itemRowSelectItem = ".pf-c-select__menu-item"; + private itemCheckbox = ".pf-c-table__check"; public exportBtn = '[role="menuitem"]:nth-child(1)'; public deleteBtn = '[role="menuitem"]:nth-child(2)'; private searchBtn = @@ -18,6 +49,12 @@ export default class ListingPage { private nextPageBtn = "div[class=pf-c-pagination__nav-control] button[data-action=next]:visible"; public tableRowItem = "tbody tr[data-ouia-component-type]:visible"; + private table = "table[aria-label]"; + private filterSessionDropdownButton = ".pf-c-select button:nth-child(1)"; + private filterDropdownButton = "[class*='searchtype'] button"; + private dropdownItem = ".pf-c-dropdown__menu-item"; + private changeTypeToButton = ".pf-c-select__toggle"; + private toolbarChangeType = "#change-type-dropdown"; showPreviousPageTableItems() { cy.get(this.previousPageBtn).first().click(); @@ -62,6 +99,21 @@ export default class ListingPage { return this; } + clickSearchBarActionButton() { + cy.get(this.tableToolbar).find(this.itemRowDrpDwn).last().click(); + + return this; + } + + clickSearchBarActionItem(itemName: string) { + cy.get(this.tableToolbar) + .find(this.dropdownItem) + .contains(itemName) + .click(); + + return this; + } + clickRowDetails(itemName: string) { cy.get(this.itemsRows) .contains(itemName) @@ -99,6 +151,37 @@ export default class ListingPage { return this; } + clickItemCheckbox(itemName: string) { + cy.get(this.itemsRows) + .contains(itemName) + .parentsUntil("tbody") + .find(this.itemCheckbox) + .click(); + return this; + } + + clickRowSelectButton(itemName: string) { + cy.get(this.itemsRows) + .contains(itemName) + .parentsUntil("tbody") + .find(this.itemRowSelect) + .click(); + return this; + } + + clickPrimaryButton() { + cy.get(this.listHeaderPrimaryBtn).click(); + + return this; + } + + clickRowSelectItem(rowItemName: string, selectItemName: string) { + this.clickRowSelectButton(rowItemName); + cy.get(this.itemRowSelectItem).contains(selectItemName).click(); + + return this; + } + itemExist(itemName: string, exist = true) { cy.get(this.itemsRows) .contains(itemName) @@ -132,4 +215,121 @@ export default class ListingPage { return this; } + + removeItem(itemName: string) { + this.clickRowDetails(itemName); + this.clickDetailMenu("Remove"); + + return this; + } + + itemsEqualTo(amount: number) { + cy.get(this.tableRowItem).its("length").should("be.eq", amount); + + return this; + } + + itemsGreaterThan(amount: number) { + cy.get(this.tableRowItem).its("length").should("be.gt", amount); + + return this; + } + + itemContainValue(itemName: string, colIndex: number, value: string) { + cy.get(this.itemsRows) + .contains(itemName) + .parentsUntil("tbody") + .find("td") + .eq(colIndex) + .should("contain", value); + + return this; + } + + selectFilter(filter: Filter) { + cy.get(this.filterDropdownButton).first().click(); + cy.get(this.dropdownItem).contains(filter).click(); + + return this; + } + + selectSecondaryFilter(itemName: string) { + cy.get(this.filterDropdownButton).last().click(); + cy.get(this.itemRowSelectItem).contains(itemName).click(); + + return this; + } + + selectSecondaryFilterAssignedType(assignedType: FilterAssignedType) { + this.selectSecondaryFilter(assignedType); + + return this; + } + + selectSecondaryFilterProtocol(protocol: FilterProtocol) { + this.selectSecondaryFilter(protocol); + + return this; + } + + selectSecondaryFilterSession(sessionName: FilterSession) { + cy.get(this.filterSessionDropdownButton).click(); + cy.get(this.itemRowSelectItem).contains(sessionName); + + return this; + } + + changeTypeToOfSelectedItems(assignedType: FilterAssignedType) { + cy.intercept("/auth/admin/realms/master/client-scopes").as("load"); + cy.get(this.toolbarChangeType).click(); + cy.get(this.itemRowSelectItem).contains(assignedType).click(); + cy.wait("@load"); + return this; + } + + changeTypeToOfItem(assignedType: FilterAssignedType, itemName: string) { + cy.get(this.itemsRows) + .contains(itemName) + .parentsUntil("tbody") + .find(this.changeTypeToButton) + .first() + .click(); + + cy.get(this.itemsRows) + .contains(itemName) + .parentsUntil("tbody") + .find(this.changeTypeToButton) + .contains(assignedType) + .click(); + + return this; + } + + checkInSearchBarChangeTypeToButtonIsDisabled(disabled: boolean = true) { + let condition = "be.disabled"; + if (!disabled) { + condition = "be.enabled"; + } + cy.get(this.changeTypeToButton).first().should(condition); + + return this; + } + + checkDropdownItemIsDisabled(itemName: string, disabled: boolean = true) { + cy.get(this.dropdownItem) + .contains(itemName) + .should("have.attr", "aria-disabled", String(disabled)); + + return this; + } + + checkTableExists(exists: boolean = true) { + let condition = "be.visible"; + if (!exists) { + condition = "not.be.visible"; + } + cy.get(this.table).should(condition); + + return this; + } } diff --git a/cypress/support/util/AdminClient.ts b/cypress/support/util/AdminClient.ts index 423a26e170..75f9b6727d 100644 --- a/cypress/support/util/AdminClient.ts +++ b/cypress/support/util/AdminClient.ts @@ -113,6 +113,15 @@ export default class AdminClient { return await this.client.clientScopes.del({ id: clientScope?.id! }); } + async existsClientScope(clientScopeName: string) { + await this.login(); + return (await this.client.clientScopes.findOneByName({ + name: clientScopeName, + })) == undefined + ? false + : true; + } + async addDefaultClientScopeInClient( clientScopeName: string, clientId: string diff --git a/cypress/support/util/ModalUtils.ts b/cypress/support/util/ModalUtils.ts index 6d1aa822ae..c581262512 100644 --- a/cypress/support/util/ModalUtils.ts +++ b/cypress/support/util/ModalUtils.ts @@ -6,6 +6,8 @@ export default class ModalUtils { 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']"; confirmModal() { cy.findByTestId(this.confirmModalBtn).click({ force: true }); @@ -19,6 +21,13 @@ export default class ModalUtils { return this; } + confirmModalWithItem(itemName: string) { + cy.get(this.addModalDropdownBtn).click(); + cy.get(this.addModalDropdownItem).contains(itemName).click(); + + return this; + } + cancelModal() { cy.findByTestId(this.cancelModalBtn).click({ force: true }); diff --git a/src/client-scopes/ChangeTypeDropdown.tsx b/src/client-scopes/ChangeTypeDropdown.tsx index 8528087c29..c359342c99 100644 --- a/src/client-scopes/ChangeTypeDropdown.tsx +++ b/src/client-scopes/ChangeTypeDropdown.tsx @@ -32,7 +32,7 @@ export const ChangeTypeDropdown = ({ return (