Add Client Scopes Mappers tests (#4398)
This commit is contained in:
parent
9848ce6948
commit
1ca3f87df4
9 changed files with 298 additions and 27 deletions
|
@ -11,11 +11,19 @@ import { keycloakBefore } from "../support/util/keycloak_hooks";
|
|||
import RoleMappingTab from "../support/pages/admin-ui/manage/RoleMappingTab";
|
||||
import ModalUtils from "../support/util/ModalUtils";
|
||||
import adminClient from "../support/util/AdminClient";
|
||||
import ClientScopeDetailsPage from "../support/pages/admin-ui/manage/client_scopes/client_scope_details/ClientScopeDetailsPage";
|
||||
import CommonPage from "../support/pages/CommonPage";
|
||||
import MappersTab from "../support/pages/admin-ui/manage/client_scopes/client_scope_details/tabs/MappersTab";
|
||||
import MapperDetailsPage, {
|
||||
ClaimJsonType,
|
||||
} from "../support/pages/admin-ui/manage/client_scopes/client_scope_details/tabs/mappers/MapperDetailsPage";
|
||||
|
||||
let itemId = "client_scope_crud";
|
||||
const loginPage = new LoginPage();
|
||||
const masthead = new Masthead();
|
||||
const sidebarPage = new SidebarPage();
|
||||
|
||||
const commonPage = new CommonPage();
|
||||
const listingPage = new ListingPage();
|
||||
const createClientScopePage = new CreateClientScopePage();
|
||||
const modalUtils = new ModalUtils();
|
||||
|
@ -163,7 +171,6 @@ describe("Client Scopes test", () => {
|
|||
listingPage
|
||||
.searchItem(clientScopeName, false)
|
||||
.clickRowSelectItem(itemName, $assignedType);
|
||||
// sidebarPage.waitForPageLoad(); //not working
|
||||
cy.wait(2000);
|
||||
listingPage.searchItem(itemName, false).itemExist($assignedType);
|
||||
});
|
||||
|
@ -199,7 +206,6 @@ describe("Client Scopes test", () => {
|
|||
sidebarPage.goToClientScopes();
|
||||
});
|
||||
|
||||
//TODO: Partially blocked by https://github.com/keycloak/keycloak-admin-ui/issues/1854
|
||||
it("should delete item from item bar", () => {
|
||||
listingPage
|
||||
.checkInSearchBarChangeTypeToButtonIsDisabled()
|
||||
|
@ -211,10 +217,9 @@ describe("Client Scopes test", () => {
|
|||
masthead.checkNotificationMessage(
|
||||
notificationMessageDeletionConfirmation
|
||||
);
|
||||
//listingPage.checkInSearchBarChangeTypeToButtonIsDisabled();
|
||||
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()
|
||||
|
@ -227,10 +232,9 @@ describe("Client Scopes test", () => {
|
|||
masthead.checkNotificationMessage(
|
||||
notificationMessageDeletionConfirmation
|
||||
);
|
||||
//listingPage.checkInSearchBarChangeTypeToButtonIsDisabled();
|
||||
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()
|
||||
|
@ -245,7 +249,7 @@ describe("Client Scopes test", () => {
|
|||
masthead.checkNotificationMessage(
|
||||
notificationMessageDeletionConfirmation
|
||||
);
|
||||
//listingPage.checkInSearchBarChangeTypeToButtonIsDisabled();
|
||||
listingPage.checkInSearchBarChangeTypeToButtonIsDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -262,7 +266,6 @@ describe("Client Scopes test", () => {
|
|||
|
||||
createClientScopePage.fillClientScopeData("address").save();
|
||||
|
||||
// The error should inform about duplicated name/id
|
||||
masthead.checkNotificationMessage(
|
||||
"Could not create client scope: 'Client Scope address already exists'"
|
||||
);
|
||||
|
@ -316,10 +319,17 @@ describe("Client Scopes test", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("Scope test", () => {
|
||||
describe("Scope tab test", () => {
|
||||
const scopeTab = new RoleMappingTab("client-scope");
|
||||
const scopeName = "address";
|
||||
it.skip("Assign role", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
loginPage.logIn();
|
||||
keycloakBefore();
|
||||
sidebarPage.goToClientScopes();
|
||||
});
|
||||
|
||||
it("Assign and unassign role", () => {
|
||||
const role = "admin";
|
||||
listingPage.searchItem(scopeName, false).goToItemDetails(scopeName);
|
||||
scopeTab.goToScopeTab().assignRole().selectRow(role).assign();
|
||||
|
@ -330,4 +340,68 @@ describe("Client Scopes test", () => {
|
|||
scopeTab.checkRoles([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Mappers tab test", () => {
|
||||
const clientScopeDetailsPage = new ClientScopeDetailsPage();
|
||||
const mappersTab = new MappersTab();
|
||||
const mapperDetailsTab = new MapperDetailsPage();
|
||||
const scopeName = "address";
|
||||
|
||||
beforeEach(() => {
|
||||
loginPage.logIn();
|
||||
keycloakBefore();
|
||||
sidebarPage.goToClientScopes();
|
||||
});
|
||||
|
||||
it("CRUD mappers", () => {
|
||||
const predefinedMapperName = "Predefined Mapper test";
|
||||
const predefinedMapper = "Allowed Web Origins";
|
||||
const mappers1 = ["birthdate"];
|
||||
const mappers2 = ["email verified", "email", "family name"];
|
||||
|
||||
listingPage.searchItem(scopeName, false).goToItemDetails(scopeName);
|
||||
clientScopeDetailsPage
|
||||
.goToMappersTab()
|
||||
.addPredefinedMappers(mappers1)
|
||||
.addPredefinedMappers(mappers2);
|
||||
|
||||
listingPage.searchItem(mappers1[0], false).goToItemDetails(mappers1[0]);
|
||||
|
||||
mapperDetailsTab
|
||||
.fillUserAttribute(mappers1[0] + "1")
|
||||
.fillTokenClaimName(mappers1[0] + "2")
|
||||
.changeClaimJsonType(ClaimJsonType.Long);
|
||||
|
||||
commonPage.formUtils().save();
|
||||
commonPage
|
||||
.masthead()
|
||||
.checkNotificationMessage("Mapping successfully updated");
|
||||
|
||||
sidebarPage.goToClientScopes();
|
||||
listingPage.searchItem(scopeName, false).goToItemDetails(scopeName);
|
||||
|
||||
clientScopeDetailsPage.goToMappersTab();
|
||||
|
||||
listingPage.searchItem(mappers1[0], false).goToItemDetails(mappers1[0]);
|
||||
|
||||
mapperDetailsTab
|
||||
.checkUserAttribute(mappers1[0] + "1")
|
||||
.checkTokenClaimName(mappers1[0] + "2")
|
||||
.checkClaimJsonType(ClaimJsonType.Long);
|
||||
|
||||
commonPage.formUtils().cancel();
|
||||
|
||||
mappersTab
|
||||
.removeMappers(mappers1.concat(mappers2))
|
||||
.addMappersByConfiguration(predefinedMapper, predefinedMapperName);
|
||||
|
||||
sidebarPage.goToClientScopes();
|
||||
listingPage.searchItem(scopeName, false).goToItemDetails(scopeName);
|
||||
clientScopeDetailsPage.goToMappersTab();
|
||||
|
||||
commonPage.tableUtils().checkRowItemExists(predefinedMapperName, true);
|
||||
|
||||
mappersTab.removeMappers([predefinedMapperName]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@ export default class TablePage extends CommonElements {
|
|||
private tableRowItem: string;
|
||||
private tableRowItemChckBx: string;
|
||||
private tableHeaderRowItem: string;
|
||||
private tableInModal: boolean;
|
||||
static tableSelector = "table[aria-label]";
|
||||
|
||||
constructor(parentElement?: string) {
|
||||
|
@ -17,10 +18,17 @@ export default class TablePage extends CommonElements {
|
|||
this.tableHeaderRowItem =
|
||||
this.parentSelector + "thead tr[data-ouia-component-type]";
|
||||
this.tableRowItemChckBx = ".pf-c-table__check";
|
||||
this.tableInModal = false;
|
||||
}
|
||||
|
||||
setTableInModal(value: boolean) {
|
||||
this.tableInModal = value;
|
||||
}
|
||||
|
||||
selectRowItemCheckbox(itemName: string) {
|
||||
cy.get(this.tableRowItem)
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") + this.tableRowItem
|
||||
)
|
||||
.contains(itemName)
|
||||
.parentsUntil("tbody")
|
||||
.find(this.tableRowItemChckBx)
|
||||
|
@ -29,12 +37,18 @@ export default class TablePage extends CommonElements {
|
|||
}
|
||||
|
||||
clickRowItemLink(itemName: string) {
|
||||
cy.get(this.tableRowItem).contains(itemName).click();
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") + this.tableRowItem
|
||||
)
|
||||
.contains(itemName)
|
||||
.click();
|
||||
return this;
|
||||
}
|
||||
|
||||
selectRowItemAction(itemName: string, actionItemName: string) {
|
||||
cy.get(this.tableRowItem)
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") + this.tableRowItem
|
||||
)
|
||||
.contains(itemName)
|
||||
.parentsUntil("tbody")
|
||||
.find(".pf-c-dropdown__toggle")
|
||||
|
@ -44,14 +58,26 @@ export default class TablePage extends CommonElements {
|
|||
}
|
||||
|
||||
typeValueToRowItem(row: number, column: number, value: string) {
|
||||
cy.get(this.tableRowItem + ":nth-child(" + row + ")")
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") +
|
||||
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 + ")")
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") +
|
||||
this.tableRowItem +
|
||||
":nth-child(" +
|
||||
row +
|
||||
")"
|
||||
)
|
||||
.find("td:nth-child(" + column + ") " + appendChildren)
|
||||
.click();
|
||||
return this;
|
||||
|
@ -62,7 +88,9 @@ export default class TablePage extends CommonElements {
|
|||
column: number,
|
||||
appendChildren?: string
|
||||
) {
|
||||
cy.get(this.tableRowItem)
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") + this.tableRowItem
|
||||
)
|
||||
.find("td:nth-child(" + column + ") " + appendChildren)
|
||||
.contains(itemName)
|
||||
.click();
|
||||
|
@ -70,31 +98,46 @@ export default class TablePage extends CommonElements {
|
|||
}
|
||||
|
||||
clickHeaderItem(column: number, appendChildren?: string) {
|
||||
cy.get(this.tableHeaderRowItem)
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") +
|
||||
this.tableHeaderRowItem
|
||||
)
|
||||
.find("td:nth-child(" + column + ") " + appendChildren)
|
||||
.click();
|
||||
return this;
|
||||
}
|
||||
|
||||
checkRowItemsEqualTo(amount: number) {
|
||||
cy.get(this.tableRowItem).its("length").should("be.eq", amount);
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") + this.tableRowItem
|
||||
)
|
||||
.its("length")
|
||||
.should("be.eq", amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
checkRowItemsGreaterThan(amount: number) {
|
||||
cy.get(this.tableRowItem).its("length").should("be.gt", amount);
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") + this.tableRowItem
|
||||
)
|
||||
.its("length")
|
||||
.should("be.gt", amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
checkRowItemExists(itemName: string, exist = true) {
|
||||
cy.get(this.tableRowItem)
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") + this.tableRowItem
|
||||
)
|
||||
.contains(itemName)
|
||||
.should((!exist ? "not." : "") + "exist");
|
||||
return this;
|
||||
}
|
||||
|
||||
checkRowItemValueByItemName(itemName: string, column: number, value: string) {
|
||||
cy.get(this.tableRowItem)
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") + this.tableRowItem
|
||||
)
|
||||
.contains(itemName)
|
||||
.parentsUntil("tbody")
|
||||
.find("td:nth-child(" + column + ")")
|
||||
|
@ -108,7 +151,13 @@ export default class TablePage extends CommonElements {
|
|||
value: string,
|
||||
appendChildren?: string
|
||||
) {
|
||||
cy.get(this.tableRowItem + ":nth-child(" + row + ")")
|
||||
cy.get(
|
||||
(this.tableInModal ? ".pf-c-modal-box.pf-m-md " : "") +
|
||||
this.tableRowItem +
|
||||
":nth-child(" +
|
||||
row +
|
||||
")"
|
||||
)
|
||||
.find("td:nth-child(" + column + ") " + appendChildren)
|
||||
.should("have.text", value)
|
||||
.should("have.value", value);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const expect = chai.expect;
|
||||
export default class RoleMappingTab {
|
||||
private type = "client";
|
||||
private tab = "serviceAccountTab";
|
||||
private serviceAccountTab = "serviceAccountTab";
|
||||
private scopeTab = "scopeTab";
|
||||
private assignEmptyRoleBtn = (type: string) =>
|
||||
`no-roles-for-this-${type}-empty-action`;
|
||||
|
@ -19,7 +19,7 @@ export default class RoleMappingTab {
|
|||
}
|
||||
|
||||
goToServiceAccountTab() {
|
||||
cy.findByTestId(this.tab).click();
|
||||
cy.findByTestId(this.serviceAccountTab).click();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
import CommonPage from "../../../CommonPage";
|
||||
|
||||
export default class ClientScopesPage extends CommonPage {}
|
|
@ -0,0 +1,31 @@
|
|||
import CommonPage from "../../../../CommonPage";
|
||||
import SettingsTab from "./tabs/SettingsTab";
|
||||
import MappersTab from "./tabs/MappersTab";
|
||||
import ScopeTab from "./tabs/ScopeTab";
|
||||
|
||||
export enum ClientScopeDetailsTab {
|
||||
SettingsTab = "Settings",
|
||||
MappersTab = "Mappers",
|
||||
Scope = "Scope",
|
||||
}
|
||||
|
||||
export default class ClientScopeDetailsPage extends CommonPage {
|
||||
private settingsTab = new SettingsTab();
|
||||
private scopesTab = new ScopeTab();
|
||||
private mappersTab = new MappersTab();
|
||||
|
||||
goToSettingsTab() {
|
||||
this.tabUtils().clickTab(ClientScopeDetailsTab.SettingsTab);
|
||||
return this.settingsTab;
|
||||
}
|
||||
|
||||
goToMappersTab() {
|
||||
this.tabUtils().clickTab(ClientScopeDetailsTab.MappersTab);
|
||||
return this.mappersTab;
|
||||
}
|
||||
|
||||
goToScopesTab() {
|
||||
this.tabUtils().clickTab(ClientScopeDetailsTab.Scope);
|
||||
return this.scopesTab;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
import CommonPage from "../../../../../CommonPage";
|
||||
|
||||
export default class MappersTab extends CommonPage {
|
||||
private addMapperBtn = "#mapperAction";
|
||||
private fromPredefinedMappersBtn =
|
||||
'ul[aria-labelledby="mapperAction"] > li:nth-child(1) a';
|
||||
private byConfigurationBtn =
|
||||
'ul[aria-labelledby="mapperAction"] > li:nth-child(2) a';
|
||||
private mapperConfigurationList =
|
||||
'ul[aria-label="Add predefined mappers"] > li:not([id=header])';
|
||||
|
||||
private mapperNameInput = "#name";
|
||||
|
||||
addPredefinedMappers(mappersNames: string[]) {
|
||||
cy.get(this.addMapperBtn).click();
|
||||
cy.get(this.fromPredefinedMappersBtn).click();
|
||||
|
||||
this.tableUtils().setTableInModal(true);
|
||||
for (const mapperName of mappersNames) {
|
||||
this.tableUtils().selectRowItemCheckbox(mapperName);
|
||||
}
|
||||
this.tableUtils().setTableInModal(false);
|
||||
|
||||
this.modalUtils().confirmModal();
|
||||
this.masthead().checkNotificationMessage("Mapping successfully created");
|
||||
this.sidebar().waitForPageLoad();
|
||||
cy.contains(mappersNames[0]).should("exist");
|
||||
|
||||
for (const mapperName of mappersNames) {
|
||||
this.tableUtils().checkRowItemExists(mapperName, true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
addMappersByConfiguration(predefinedMapperName: string, mapperName: string) {
|
||||
cy.get(this.addMapperBtn).click();
|
||||
cy.get(this.byConfigurationBtn).click();
|
||||
|
||||
cy.get(this.mapperConfigurationList).contains(predefinedMapperName).click();
|
||||
|
||||
cy.get(this.mapperNameInput).type(mapperName);
|
||||
|
||||
this.formUtils().save();
|
||||
this.masthead().checkNotificationMessage("Mapping successfully created");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
removeMappers(mappersNames: string[]) {
|
||||
for (const mapperName of mappersNames) {
|
||||
this.tableUtils().checkRowItemExists(mapperName);
|
||||
this.tableUtils().selectRowItemAction(mapperName, "Delete");
|
||||
this.sidebar().waitForPageLoad();
|
||||
this.masthead().checkNotificationMessage("Mapping successfully deleted");
|
||||
this.sidebar().waitForPageLoad();
|
||||
this.tableUtils().checkRowItemExists(mapperName, false);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
import CommonPage from "../../../../../CommonPage";
|
||||
|
||||
export default class ScopeTab extends CommonPage {}
|
|
@ -0,0 +1,3 @@
|
|||
import PageObject from "../../../../components/PageObject";
|
||||
|
||||
export default class SettingsTab extends PageObject {}
|
|
@ -0,0 +1,52 @@
|
|||
import CommonPage from "../../../../../../CommonPage";
|
||||
|
||||
export enum ClaimJsonType {
|
||||
String = "String",
|
||||
Long = "long",
|
||||
Int = "int",
|
||||
Boolean = "boolean",
|
||||
Json = "JSON",
|
||||
}
|
||||
|
||||
export default class MapperDetailsPage extends CommonPage {
|
||||
private userAttributeInput = '[id="user.attribute"]';
|
||||
private tokenClaimNameInput = '[id="claim.name"]';
|
||||
private claimJsonType = '[id="jsonType.label"]';
|
||||
|
||||
fillUserAttribute(userAttribute: string) {
|
||||
cy.get(this.userAttributeInput).clear().type(userAttribute);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
checkUserAttribute(userAttribute: string) {
|
||||
cy.get(this.userAttributeInput).should("have.value", userAttribute);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
fillTokenClaimName(name: string) {
|
||||
cy.get(this.tokenClaimNameInput).clear().type(name);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
checkTokenClaimName(name: string) {
|
||||
cy.get(this.tokenClaimNameInput).should("have.value", name);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
changeClaimJsonType(type: string) {
|
||||
cy.get(this.claimJsonType).click();
|
||||
cy.get(this.claimJsonType).parent().contains(type).click();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
checkClaimJsonType(type: string) {
|
||||
cy.get(this.claimJsonType).should("contain", type);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue