New Users IdP linking account tests (#3146)

This commit is contained in:
ikhomyn 2022-08-22 18:05:57 +02:00 committed by GitHub
parent a1140191d6
commit 4f25c71eed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 376 additions and 3 deletions

View file

@ -3,13 +3,15 @@ import LoginPage from "../support/pages/LoginPage";
import CreateUserPage from "../support/pages/admin_console/manage/users/CreateUserPage";
import Masthead from "../support/pages/admin_console/Masthead";
import ListingPage from "../support/pages/admin_console/ListingPage";
import UserDetailsPage from "../support/pages/admin_console/manage/users/UserDetailsPage";
import UserDetailsPage from "../support/pages/admin_console/manage/users/user_details/UserDetailsPage";
import AttributesTab from "../support/pages/admin_console/manage/AttributesTab";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import UserGroupsPage from "../support/pages/admin_console/manage/users/UserGroupsPage";
import adminClient from "../support/util/AdminClient";
import CredentialsPage from "../support/pages/admin_console/manage/users/CredentialsPage";
import UsersPage from "cypress/support/pages/admin_console/manage/users/UsersPage";
import IdentityProviderLinksTab from "cypress/support/pages/admin_console/manage/users/user_details/tabs/IdentityProviderLinksTab";
let groupName = "group";
let groupsList: string[] = [];
@ -25,6 +27,8 @@ describe("User creation", () => {
const userDetailsPage = new UserDetailsPage();
const credentialsPage = new CredentialsPage();
const attributesTab = new AttributesTab();
const usersPage = new UsersPage();
const identityProviderLinksTab = new IdentityProviderLinksTab();
let itemId = "user_crud";
let itemIdWithGroups = "user_with_groups_crud";
@ -37,7 +41,6 @@ describe("User creation", () => {
adminClient.createGroup(groupName);
groupsList = [...groupsList, groupName];
}
keycloakBefore();
loginPage.logIn();
});
@ -207,6 +210,129 @@ describe("User creation", () => {
cy.findByTestId("empty-state").contains("No consents");
});
describe("Identity provider links", () => {
const usernameIdpLinksTest = "user_idp_link_test";
const identityProviders = [
{ testName: "Bitbucket", displayName: "BitBucket", alias: "bitbucket" },
{ testName: "Facebook", displayName: "Facebook", alias: "facebook" },
{
testName: "Keycloak-oidc",
displayName: "Keycloak OpenID Connect",
alias: "keycloak-oidc",
},
];
before(async () => {
await Promise.all([
adminClient.createUser({
username: usernameIdpLinksTest,
enabled: true,
}),
identityProviders.forEach((idp) =>
adminClient.createIdentityProvider(idp.displayName, idp.alias)
),
]);
});
after(() => adminClient.deleteUser(usernameIdpLinksTest));
beforeEach(() => {
usersPage.goToUserListTab().goToUserDetailsPage(usernameIdpLinksTest);
userDetailsPage.goToIdentityProviderLinksTab();
});
identityProviders.forEach(($idp, linkedIdpsCount) => {
it(`Link account to IdP: ${$idp.testName}`, () => {
const availableIdpsCount = identityProviders.length - linkedIdpsCount;
if (linkedIdpsCount == 0) {
identityProviderLinksTab.assertNoIdentityProvidersLinkedMessageExist(
true
);
}
identityProviderLinksTab
.assertAvailableIdentityProvidersItemsEqual(availableIdpsCount)
.clickLinkAccount($idp.testName)
.assertLinkAccountModalTitleEqual($idp.testName)
.assertLinkAccountModalIdentityProviderInputEqual($idp.testName)
.typeLinkAccountModalUserId("testUserId")
.typeLinkAccountModalUsername("testUsername")
.clickLinkAccountModalLinkBtn()
.assertNotificationIdentityProviderLinked()
.assertLinkedIdentityProvidersItemsEqual(linkedIdpsCount + 1)
.assertAvailableIdentityProvidersItemsEqual(availableIdpsCount - 1)
.assertLinkedIdentityProviderExist($idp.testName, true)
.assertAvailableIdentityProviderExist($idp.testName, false);
if (availableIdpsCount - 1 == 0) {
identityProviderLinksTab.assertNoAvailableIdentityProvidersMessageExist(
true
);
}
masthead.closeAllAlertMessages();
});
});
it("Link account to already added IdP fail", () => {
cy.wrap(null).then(() =>
adminClient.unlinkAccountIdentityProvider(
usernameIdpLinksTest,
identityProviders[0].displayName
)
);
sidebarPage.goToUsers();
usersPage.goToUserListTab().goToUserDetailsPage(usernameIdpLinksTest);
userDetailsPage.goToIdentityProviderLinksTab();
cy.wrap(null).then(() =>
adminClient.linkAccountIdentityProvider(
usernameIdpLinksTest,
identityProviders[0].displayName
)
);
identityProviderLinksTab
.clickLinkAccount(identityProviders[0].testName)
.assertLinkAccountModalTitleEqual(identityProviders[0].testName)
.assertLinkAccountModalIdentityProviderInputEqual(
identityProviders[0].testName
)
.typeLinkAccountModalUserId("testUserId")
.typeLinkAccountModalUsername("testUsername")
.clickLinkAccountModalLinkBtn()
.assertNotificationAlreadyLinkedError();
modalUtils.cancelModal();
});
identityProviders.forEach(($idp, availableIdpsCount) => {
it(`Unlink account from IdP: ${$idp.testName}`, () => {
const linkedIdpsCount = identityProviders.length - availableIdpsCount;
if (availableIdpsCount == 0) {
identityProviderLinksTab.assertNoAvailableIdentityProvidersMessageExist(
true
);
}
identityProviderLinksTab
.assertAvailableIdentityProvidersItemsEqual(availableIdpsCount)
.clickUnlinkAccount($idp.testName)
.assertUnLinkAccountModalTitleEqual($idp.testName)
.clickUnlinkAccountModalUnlinkBtn()
.assertNotificationPoviderLinkRemoved()
.assertLinkedIdentityProvidersItemsEqual(linkedIdpsCount - 1)
.assertAvailableIdentityProvidersItemsEqual(availableIdpsCount + 1)
.assertLinkedIdentityProviderExist($idp.testName, false)
.assertAvailableIdentityProviderExist($idp.testName, true);
if (linkedIdpsCount - 1 == 0) {
identityProviderLinksTab.assertNoIdentityProvidersLinkedMessageExist(
true
);
}
masthead.closeAllAlertMessages();
});
});
});
it("Reset credential of User with empty state", () => {
listingPage.goToItemDetails(itemId);
credentialsPage

View file

@ -0,0 +1,28 @@
import PageObject from "../../components/PageObject";
import ListingPage from "../../ListingPage";
const listingPage = new ListingPage();
export default class UsersPage extends PageObject {
private userListTabLink = "listTab";
private permissionsTabLink = "permissionsTab";
public goToUserListTab() {
cy.findByTestId(this.userListTabLink).click();
return this;
}
public goToPermissionsTab() {
cy.findByTestId(this.permissionsTabLink).click();
return this;
}
public goToUserDetailsPage(username: string) {
listingPage.searchItem(username);
listingPage.goToItemDetails(username);
return this;
}
}

View file

@ -1,6 +1,7 @@
import { RequiredActionAlias } from "@keycloak/keycloak-admin-client/lib/defs/requiredActionProviderRepresentation";
import PageObject from "../../../components/PageObject";
export default class UserDetailsPage {
export default class UserDetailsPage extends PageObject {
saveBtn: string;
cancelBtn: string;
emailInput: string;
@ -12,8 +13,10 @@ export default class UserDetailsPage {
enabledSwitch: string;
enabledValue: boolean;
requiredUserActions: RequiredActionAlias[];
identityProviderLinksTab: string;
constructor() {
super();
this.saveBtn = "save-user";
this.cancelBtn = "cancel-create-user";
this.emailInput = "email-input";
@ -29,6 +32,15 @@ export default class UserDetailsPage {
this.enabledSwitch = "user-enabled-switch";
this.enabledValue = true;
this.requiredUserActions = [RequiredActionAlias.UPDATE_PASSWORD];
this.identityProviderLinksTab = "identity-provider-links-tab";
}
public goToIdentityProviderLinksTab() {
cy.findByTestId(this.identityProviderLinksTab).click();
cy.intercept("/admin/realms/master").as("load");
cy.wait(["@load"]);
return this;
}
fillUserData() {

View file

@ -0,0 +1,162 @@
import Masthead from "cypress/support/pages/admin_console/Masthead";
import ModalUtils from "cypress/support/util/ModalUtils";
const modalUtils = new ModalUtils();
const masthead = new Masthead();
export default class IdentityProviderLinksTab {
private linkedProvidersSection = ".kc-linked-idps";
private availableProvidersSection = ".kc-available-idps";
private linkAccountBtn = ".pf-c-button.pf-m-link";
private linkAccountModalIdentityProviderInput = "idpNameInput";
private linkAccountModalUserIdInput = "userIdInput";
private linkAccountModalUsernameInput = "usernameInput";
private linkAccountModalLinkBtn = "Link";
public clickLinkAccount(idpName: string) {
cy.get(this.availableProvidersSection + " tr")
.contains(idpName)
.parent()
.find(this.linkAccountBtn)
.click();
return this;
}
public clickUnlinkAccount(idpName: string) {
cy.get(this.linkedProvidersSection + " tr")
.contains(idpName)
.parent()
.parent()
.find(this.linkAccountBtn)
.click();
return this;
}
public typeLinkAccountModalUserId(userId: string) {
cy.findByTestId(this.linkAccountModalUserIdInput).type(userId);
return this;
}
public typeLinkAccountModalUsername(username: string) {
cy.findByTestId(this.linkAccountModalUsernameInput).type(username);
return this;
}
public clickLinkAccountModalLinkBtn() {
cy.findByTestId(this.linkAccountModalLinkBtn).click();
cy.intercept("/admin/realms/master").as("load");
cy.wait(["@load"]);
return this;
}
public clickUnlinkAccountModalUnlinkBtn() {
modalUtils.confirmModal();
cy.intercept("/admin/realms/master").as("load");
cy.wait(["@load"]);
return this;
}
public assertNoIdentityProvidersLinkedMessageExist(exist: boolean) {
cy.get(this.linkedProvidersSection).should(
(exist ? "" : "not.") + "contain.text",
"No identity providers linked. Choose one from the list below."
);
return this;
}
public assertNoAvailableIdentityProvidersMessageExist(exist: boolean) {
cy.get(this.availableProvidersSection).should(
(exist ? "" : "not.") + "contain.text",
"No available identity providers."
);
return this;
}
public assertLinkAccountModalTitleEqual(idpName: string) {
modalUtils.assertModalTitleEqual(`Link account to ${idpName}`);
return this;
}
public assertUnLinkAccountModalTitleEqual(idpName: string) {
modalUtils.assertModalTitleEqual(`Unlink account from ${idpName}?`);
return this;
}
public assertLinkAccountModalIdentityProviderInputEqual(idpName: string) {
cy.findByTestId(this.linkAccountModalIdentityProviderInput).should(
"have.value",
idpName
);
return this;
}
public assertNotificationIdentityProviderLinked() {
masthead.checkNotificationMessage("Identity provider has been linked");
return this;
}
public assertNotificationAlreadyLinkedError() {
masthead.checkNotificationMessage(
"Could not link identity provider User is already linked with provider"
);
return this;
}
public assertNotificationPoviderLinkRemoved() {
masthead.checkNotificationMessage("The provider link has been removed");
return this;
}
public assertLinkedIdentityProvidersItemsEqual(count: number) {
if (count > 0) {
cy.get(this.linkedProvidersSection + " tbody")
.find("tr")
.should("have.length", count);
} else {
cy.get(this.linkedProvidersSection + " tbody").should("not.exist");
}
return this;
}
public assertAvailableIdentityProvidersItemsEqual(count: number) {
if (count > 0) {
cy.get(this.availableProvidersSection + " tbody")
.find("tr")
.should("have.length", count);
} else {
cy.get(this.availableProvidersSection + " tbody").should("not.exist");
}
return this;
}
public assertLinkedIdentityProviderExist(idpName: string, exist: boolean) {
cy.get(this.linkedProvidersSection).should(
(exist ? "" : "not.") + "contain.text",
idpName
);
return this;
}
public assertAvailableIdentityProviderExist(idpName: string, exist: boolean) {
cy.get(this.availableProvidersSection).should(
(exist ? "" : "not.") + "contain.text",
idpName
);
return this;
}
}

View file

@ -184,6 +184,51 @@ class AdminClient {
await this.login();
return await this.client.roles.delByName({ name });
}
async createIdentityProvider(idpDisplayName: string, alias: string) {
await this.login();
const identityProviders =
(await this.client.serverInfo.find()).identityProviders || [];
const idp = identityProviders.find(({ name }) => name === idpDisplayName);
await this.client.identityProviders.create({
providerId: idp?.id!,
displayName: idpDisplayName,
alias: alias,
});
}
async unlinkAccountIdentityProvider(
username: string,
idpDisplayName: string
) {
await this.login();
const user = await this.client.users.find({ username });
const identityProviders =
(await this.client.serverInfo.find()).identityProviders || [];
const idp = identityProviders.find(({ name }) => name === idpDisplayName);
await this.client.users.delFromFederatedIdentity({
id: user[0].id!,
federatedIdentityId: idp?.id!,
});
}
async linkAccountIdentityProvider(username: string, idpDisplayName: string) {
await this.login();
const user = await this.client.users.find({ username });
const identityProviders =
(await this.client.serverInfo.find()).identityProviders || [];
const idp = identityProviders.find(({ name }) => name === idpDisplayName);
const fedIdentity = {
identityProvider: idp?.id,
userId: "testUserIdApi",
userName: "testUserNameApi",
};
await this.client.users.addToFederatedIdentity({
id: user[0].id!,
federatedIdentityId: idp?.id!,
federatedIdentity: fedIdentity,
});
}
}
const adminClient = new AdminClient();