playwright rewrite (#36276)

* initial version playwright rewrite

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* small refactor cancel button

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added policies ciba to playwright

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added policies spec

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added flow tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added axe tests for flows

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added more tests for authentication flows

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added client advanced test to playwright

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added client authorization tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added axe check

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added test for initial access token

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added registration policies test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added client scope test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added client scope tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* updated dependency

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added client role test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* fix running playwright tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added client saml

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added saml test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added events test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* more groups tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added group role test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added realm settings i18n tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added oidc and saml test for identity provider

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* fix tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* update ci to run playwright instead of cypress

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* add masthead test and use component instead

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added organizations test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added export realm test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added partial import

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added realm roles

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* add realm client policies test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added client profile tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* merge errors

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* realm settings

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added realm settings general test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* add login tab and localization

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* realm settings accessibility test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added user profile test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added realm create test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added realm user registration spec

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added sessions test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added kerberos test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added ldap mapper test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added ldap test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* removed cypress tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* added user tab test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* run playwright tests instead of jest tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* fixed some tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* fixed tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* fixed some more tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* fix test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* fixed tests

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* fix test

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* removed cypress

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* remove cyperss

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* Remove some more workflow remanants from Cypress

Signed-off-by: Jon Koops <jonkoops@gmail.com>
Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* lock file

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* pr review

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

---------

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Signed-off-by: Jon Koops <jonkoops@gmail.com>
Co-authored-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
Erik Jan de Wit
2025-03-12 12:35:22 +01:00
committed by GitHub
parent b1a7c79311
commit 095a194ec3
338 changed files with 10508 additions and 29025 deletions

View File

@@ -1,20 +0,0 @@
name: Cache Cypress
description: Caches Cypress binary to speed up the build.
runs:
using: composite
steps:
- id: cache-key
name: Cache key based on Cypress version
shell: bash
run: echo "key=cypress-binary-$(jq -r '.devDependencies.cypress' js/apps/admin-ui/package.json)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Cache Cypress binary
with:
# See: https://docs.cypress.io/app/references/advanced-installation#Binary-cache
path: |
~/.cache/Cypress
/AppData/Local/Cypress/Cache
~/Library/Caches/Cypress
key: ${{ runner.os }}-${{ steps.cache-key.outputs.key }}

View File

@@ -23,17 +23,7 @@ runs:
- name: PNPM store cache
uses: ./.github/actions/pnpm-store-cache
- name: Cypress binary cache
uses: ./.github/actions/cypress-cache
- name: Install dependencies
shell: bash
run: pnpm install --prefer-offline --frozen-lockfile
working-directory: js
# This step is only needed to ensure that the Cypress binary is installed.
# If the binary was retrieved from the cache, this step is a no-op.
- name: Install Cypress dependencies
shell: bash
working-directory: js/apps/admin-ui
run: pnpm exec cypress install

View File

@@ -132,9 +132,6 @@ jobs:
- run: pnpm --fail-if-no-match --filter ${{ env.WORKSPACE }} build
working-directory: js
- run: pnpm --fail-if-no-match --filter ${{ env.WORKSPACE }} cy:check-types
working-directory: js
account-ui-e2e:
name: Account UI E2E
needs:
@@ -170,7 +167,7 @@ jobs:
working-directory: js
- name: Run Playwright tests
run: pnpm --fail-if-no-match --filter ${{ env.WORKSPACE }} test
run: pnpm --fail-if-no-match --filter ${{ env.WORKSPACE }} test:integration
working-directory: js
- name: Upload Playwright report
@@ -216,7 +213,6 @@ jobs:
WORKSPACE: keycloak-admin-ui
strategy:
matrix:
container: [1, 2, 3, 4, 5]
browser: [chrome, firefox]
exclude:
# Only test with Firefox on scheduled runs
@@ -225,18 +221,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install Google Chrome
if: matrix.browser == 'chrome'
uses: browser-actions/setup-chrome@v1
with:
chrome-version: stable
- name: Install Firefox
if: matrix.browser == 'firefox'
uses: browser-actions/setup-firefox@v1
with:
firefox-version: latest
- uses: ./.github/actions/pnpm-setup
- name: Compile Admin Client
@@ -261,21 +245,21 @@ jobs:
KC_BOOTSTRAP_ADMIN_CLIENT_ID: temporary-admin-service
KC_BOOTSTRAP_ADMIN_CLIENT_SECRET: temporary-admin-service
- name: Start LDAP server
run: pnpm --fail-if-no-match --filter ${{ env.WORKSPACE }} cy:ldap-server &
- name: Install Playwright browsers
run: pnpm --fail-if-no-match --filter ${{ env.WORKSPACE }} exec playwright install --with-deps
working-directory: js
- name: Run Cypress
uses: cypress-io/github-action@v6
- name: Run Playwright tests
run: pnpm --fail-if-no-match --filter ${{ env.WORKSPACE }} test:integration
working-directory: js
- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
install: false
browser: ${{ matrix.browser }}
wait-on: http://localhost:8080
working-directory: js/apps/admin-ui
env:
SPLIT: ${{ strategy.job-total }}
SPLIT_INDEX: ${{ strategy.job-index }}
SPLIT_RANDOM_SEED: ${{ needs.generate-test-seed.outputs.seed }}
name: admin-ui-playwright-report
path: js/apps/admin-ui/playwright-report
retention-days: 30
- name: Upload server logs
if: always()
@@ -284,15 +268,6 @@ jobs:
name: admin-ui-server-log-${{ matrix.container }}-${{ matrix.browser }}
path: ~/server.log
- name: Upload Cypress videos
uses: actions/upload-artifact@v4
if: always() && github.repository != 'keycloak/keycloak-private'
with:
name: cypress-videos-${{ matrix.container }}-${{ matrix.browser }}
path: js/apps/admin-ui/cypress/videos
if-no-files-found: ignore
retention-days: 10
check:
name: Status Check - Keycloak JavaScript CI
if: always()

View File

@@ -1,6 +1,6 @@
# Keycloak Admin UI
This project is the next generation of the Keycloak Administration UI. It is written with React and [PatternFly 4](https://www.patternfly.org/v4/) and uses [Vite](https://vitejs.dev/guide/) and [Cypress](https://docs.cypress.io/guides/overview/why-cypress).
This project is the next generation of the Keycloak Administration UI. It is written with React and [PatternFly 4](https://www.patternfly.org/v4/) and uses [Vite](https://vitejs.dev/guide/) and [Playwright](hhttps://playwright.dev/).
## Development
@@ -46,9 +46,9 @@ Every time you create a commit it should be automatically linted and formatted f
pnpm lint
```
## Integration testing with Cypress
## Integration testing with Playwright
This repository contains integration tests developed with the [Cypress framework](https://www.cypress.io/).
This repository contains integration tests developed with the [Playwright framework](https://playwright.dev/).
### Prerequisites
@@ -56,21 +56,10 @@ Ensure the Keycloak and development server are running as [outlined previously](
### Running the tests
You can run the tests using the interactive graphical user interface using the following command:
```bash
pnpm cy:open
```
You can run the tests using the interactive graphical user [Visual Studio Code plugin](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright)
Alternatively the tests can also run headless as follows:
```
pnpm cy:run
pnpm test:integration
```
For more information about the Cypress command-line interface consult [the documentation](https://docs.cypress.io/guides/guides/command-line).
### Project Structure
You can find information about the project structure in the [official Cypress documentation](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests#Folder-structure).
Read more about [how to write tests](./cypress/WRITING_TESTS.md)

View File

@@ -1,78 +0,0 @@
import { defineConfig } from "cypress";
import cypressSplit from "cypress-split";
import fs from "node:fs";
import { isAsyncFunction } from "node:util/types";
const isCI = process.env.CI === "true";
const retryCount = parseInt(process.env.RETRY_COUNT || "0");
export default defineConfig({
video: isCI,
projectId: "j4yhox",
chromeWebSecurity: false,
viewportWidth: 1920,
viewportHeight: 1200,
defaultCommandTimeout: 30000,
numTestsKeptInMemory: 30,
experimentalMemoryManagement: true,
retries: {
runMode: retryCount,
},
e2e: {
baseUrl: "http://localhost:8080",
slowTestThreshold: 30000,
specPattern: "cypress/e2e/**/*.{js,jsx,ts,tsx}",
setupNodeEvents(on, config) {
on("before:browser:launch", (browser, launchOptions) => {
if (browser.family === "firefox") {
// launchOptions.preferences is a map of preference names to values
// login is not working in firefox when testing_localhost_is_secure_when_hijacked is false
launchOptions.preferences[
"network.proxy.testing_localhost_is_secure_when_hijacked"
] = true;
}
return launchOptions;
});
// after:spec collides with cypressSplit function below and is overridden there
function afterSpecRemoveSuccessfulVideos(spec, results) {
if (results?.video) {
// Do we have failures for any retry attempts?
const failures = results.tests.some((test) =>
test.attempts.some((attempt) => attempt.state === "failed"),
);
if (!failures) {
// delete the video if the spec passed and no tests retried
fs.rmSync(results.video, { force: true });
}
}
}
function chainedOn(event, callback) {
if (event === "after:spec") {
if (isAsyncFunction(callback)) {
on(event, async (spec, results) => {
afterSpecRemoveSuccessfulVideos(spec, results);
await callback(spec, results);
});
} else {
on(event, (spec, results) => {
afterSpecRemoveSuccessfulVideos(spec, results);
callback(spec, results);
});
}
} else {
on(event, callback);
}
}
cypressSplit(chainedOn, config);
return config;
},
},
});

View File

@@ -1,87 +0,0 @@
## How to write tests
### Create PageObjects for the page screens to reuse the methods
Don't do this:
```typescript
cy.findByTestId("rs-keys-tab").click();
cy.findByTestId("rs-providers-tab").click();
cy.findAllByTestId("provider-name-link")
.contains("test_hmac-generated")
.click();
```
Instead use a page object as it is a lot easier to get the intended functionality of the test:
```typescript
realmSettings.goToProvidersTab();
realmSettings.fillOutForm({ name: "test" }).save();
```
#### Clean code
Write locators in the PageObject layer and in object variables when possible to avoid hardcoding.
Set type of element at the end of the variable name (e.g. saveBtn, nameInput, userDrpDwn…)
Avoid adding “click” to name methods, methods should be named as an action “goToX”, “openX”, “createX”, etc.
Consistent naming (e.g goToTab methods, somewhere named goToTab, other goToXTab)
### Test structure
We have `keycloakBefore` that will navigate to the main page, control request errors and wait for the load to finish.
You can then have multiple test or create a new `describe` block to setup some data for your test.
```typescript
describe("Realm roles test", () => {
before(() => {
keycloakBefore();
loginPage.logIn();
});
beforeEach(() => {
sidebarPage.goToRealmRoles();
});
```
Example of `describe` to setup data for that test:
```typescript
import adminClient from "../support/util/AdminClient";
describe("Edit role details", () => {
before(() => {
adminClient.createRealmRole({
name: editRoleName,
description,
});
});
after(() => {
adminClient.deleteRealmRole(editRoleName);
});
it("Should edit realm role details", () => {
// ...
```
### Waiting for results
Sometimes you will get the following error:
> Cypress failed because the element has been detached from the DOM
This is because the DOM has been updated in between selectors. You can remedy this by waiting on REST calls.
You can see the rest calls in the cypress IDE.
```typescript
cy.intercept("/admin/realms/master/").as("search");
// ... pressing a button that will perform the search
cy.wait(["@search"]); // wait for the call named search
```
If there were no calls and you still get this error, try using `{force: true}`, but try not to use it everywhere. For example, there could be an unexpected open modal blocking the element, so even the user wouldnt be able to use that element.
### Some more reading:
* [Moises document](https://docs.google.com/document/d/11sm1IpEvVLHO59JEVmwgNOUD0zoP4YMvInIU4v5iVNk/edit)
* [Cypress blog do not get too detached](https://www.cypress.io/blog/2020/07/22/do-not-get-too-detached/)
* [See the clients_test.spec as an example](./cypress/e2e/clients_test.spec.ts)

View File

@@ -1,77 +0,0 @@
import { keycloakBefore } from "../support/util/keycloak_hooks";
import Masthead from "../support/pages/admin-ui/Masthead";
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import OTPPolicies from "../support/pages/admin-ui/manage/authentication/OTPPolicies";
import WebAuthnPolicies from "../support/pages/admin-ui/manage/authentication/WebAuthnPolicies";
describe("Policies", () => {
const masthead = new Masthead();
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
describe("OTP policies tab", () => {
const otpPoliciesPage = new OTPPolicies();
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToAuthentication();
otpPoliciesPage.goToTab();
});
it("should change to hotp", () => {
otpPoliciesPage.checkSupportedApplications(
"FreeOTP",
"Google Authenticator",
"Microsoft Authenticator",
);
otpPoliciesPage.setPolicyType("hotp").increaseInitialCounter().save();
masthead.checkNotificationMessage("OTP policy successfully updated");
otpPoliciesPage.checkSupportedApplications(
"FreeOTP",
"Google Authenticator",
);
});
});
describe("Webauthn policies tabs", () => {
const webauthnPage = new WebAuthnPolicies();
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToAuthentication();
});
it("should fill webauthn settings", () => {
webauthnPage.goToTab();
webauthnPage.fillSelects({
webAuthnPolicyAttestationConveyancePreference: "Indirect",
webAuthnPolicyRequireResidentKey: "Yes",
webAuthnPolicyUserVerificationRequirement: "Preferred",
});
webauthnPage.webAuthnPolicyCreateTimeout(30).save();
masthead.checkNotificationMessage(
"Updated webauthn policies successfully",
);
});
it("should fill webauthn passwordless settings", () => {
webauthnPage.goToPasswordlessTab();
webauthnPage
.fillSelects(
{
webAuthnPolicyAttestationConveyancePreference: "Indirect",
webAuthnPolicyRequireResidentKey: "Yes",
webAuthnPolicyUserVerificationRequirement: "Preferred",
},
true,
)
.save();
masthead.checkNotificationMessage(
"Updated webauthn policies successfully",
);
});
});
});

View File

@@ -1,85 +0,0 @@
import Form from "../support/forms/Form";
import FormValidation from "../support/forms/FormValidation";
import Select from "../support/forms/Select";
import CIBAPolicyPage from "../support/pages/admin-ui/manage/authentication/CIBAPolicyPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
describe("Authentication - Policies - CIBA", () => {
const realmName = crypto.randomUUID();
before(() => adminClient.createRealm(realmName));
after(() => adminClient.deleteRealm(realmName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
sidebarPage.goToAuthentication();
CIBAPolicyPage.goToTab();
});
it("displays the initial state", () => {
Select.assertSelectedItem(
CIBAPolicyPage.getBackchannelTokenDeliveryModeSelect(),
"Poll",
);
CIBAPolicyPage.getExpiresInput().should("have.value", "120");
CIBAPolicyPage.getIntervalInput().should("have.value", "5");
Form.assertSaveButtonDisabled();
});
it("validates the fields", () => {
// Required fields.
CIBAPolicyPage.getExpiresInput().clear();
CIBAPolicyPage.getIntervalInput().clear();
FormValidation.assertRequired(CIBAPolicyPage.getExpiresInput());
FormValidation.assertRequired(CIBAPolicyPage.getIntervalInput());
Form.assertSaveButtonDisabled();
// Fields with minimum value.
CIBAPolicyPage.getExpiresInput().type("9");
CIBAPolicyPage.getIntervalInput().type("-1");
FormValidation.assertMinValue(CIBAPolicyPage.getExpiresInput(), 10);
FormValidation.assertMinValue(CIBAPolicyPage.getIntervalInput(), 0);
Form.assertSaveButtonDisabled();
// Fields with maximum value.
CIBAPolicyPage.getExpiresInput().clear().type("601");
CIBAPolicyPage.getIntervalInput().clear().type("601");
FormValidation.assertMaxValue(CIBAPolicyPage.getExpiresInput(), 600);
FormValidation.assertMaxValue(CIBAPolicyPage.getIntervalInput(), 600);
Form.assertSaveButtonDisabled();
});
it("saves the form", () => {
// Select new values for fields.
Select.selectItem(
CIBAPolicyPage.getBackchannelTokenDeliveryModeSelect(),
"Ping",
);
CIBAPolicyPage.getExpiresInput().clear().type("140");
CIBAPolicyPage.getIntervalInput().clear().type("20");
// Save form.
Form.clickSaveButton();
CIBAPolicyPage.assertSaveSuccess();
// Assert values are saved.
Select.assertSelectedItem(
CIBAPolicyPage.getBackchannelTokenDeliveryModeSelect(),
"Ping",
);
CIBAPolicyPage.getExpiresInput().should("have.value", "140");
CIBAPolicyPage.getIntervalInput().should("have.value", "20");
});
});

View File

@@ -1,386 +0,0 @@
import { keycloakBefore } from "../support/util/keycloak_hooks";
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import DuplicateFlowModal from "../support/pages/admin-ui/manage/authentication/DuplicateFlowModal";
import FlowDetails from "../support/pages/admin-ui/manage/authentication/FlowDetail";
import RequiredActions from "../support/pages/admin-ui/manage/authentication/RequiredActions";
import adminClient from "../support/util/AdminClient";
import PasswordPolicies from "../support/pages/admin-ui/manage/authentication/PasswordPolicies";
import ModalUtils from "../support/util/ModalUtils";
import CommonPage from "../support/pages/CommonPage";
import BindFlowModal from "../support/pages/admin-ui/manage/authentication/BindFlowModal";
import OTPPolicies from "../support/pages/admin-ui/manage/authentication/OTPPolicies";
import WebAuthnPolicies from "../support/pages/admin-ui/manage/authentication/WebAuthnPolicies";
import CIBAPolicyPage from "../support/pages/admin-ui/manage/authentication/CIBAPolicyPage";
import FlowDiagram from "../support/pages/admin-ui/manage/authentication/FlowDiagram";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const commonPage = new CommonPage();
const listingPage = new ListingPage();
const realmName = "test" + crypto.randomUUID();
describe("Authentication test", () => {
const detailPage = new FlowDetails();
const diagramView = new FlowDiagram();
const duplicateFlowModal = new DuplicateFlowModal();
const modalUtil = new ModalUtils();
before(() => adminClient.createRealm(realmName));
after(() => adminClient.deleteRealm(realmName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
sidebarPage.goToAuthentication();
});
it("authentication empty search test", () => {
commonPage.tableToolbarUtils().searchItem("", false);
commonPage.tableUtils().checkIfExists(true);
});
it("authentication search flow", () => {
const itemId = "Browser";
commonPage.tableToolbarUtils().searchItem(itemId, false);
commonPage.tableUtils().checkRowItemExists(itemId);
});
it("should create duplicate of existing flow", () => {
listingPage.clickRowDetails("Browser").clickDetailMenu("Duplicate");
duplicateFlowModal.fill("Copy of browser");
masthead.checkNotificationMessage("Flow successfully duplicated");
detailPage.flowExists("Copy of browser");
});
it("Should fail duplicate with empty flow name", () => {
listingPage.clickRowDetails("Browser").clickDetailMenu("Duplicate");
duplicateFlowModal.fill().shouldShowError("Required field");
modalUtil.cancelModal();
});
it("Should fail duplicate with duplicated name", () => {
listingPage.clickRowDetails("Browser").clickDetailMenu("Duplicate");
duplicateFlowModal.fill("browser");
masthead.checkNotificationMessage(
"Could not duplicate flow: New flow alias name already exists",
);
});
it("Should show the details of a flow as a table", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.executionExists("Cookie");
});
// as of 03/28/24, drag and drop is not working
it.skip("Should move kerberos down", () => {
listingPage.goToItemDetails("Copy of browser");
const fromRow = "Kerberos";
detailPage.expectPriorityChange(fromRow, () => {
detailPage.moveRowTo(
fromRow,
`[data-testid="Identity Provider Redirector"]`,
);
});
});
it("Should edit flow details", () => {
const name = "Copy of browser";
listingPage.goToItemDetails(name);
const commonPage = new CommonPage();
commonPage
.actionToolbarUtils()
.clickActionToggleButton()
.clickDropdownItem("Edit info");
duplicateFlowModal.fill(name, "Other description");
masthead.checkNotificationMessage("Flow successfully updated");
});
it("Should change requirement of cookie", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.changeRequirement("Cookie", "Required");
masthead.checkNotificationMessage("Flow successfully updated");
});
it("Should switch to diagram mode", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.goToDiagram();
diagramView.exists();
});
it("Should add a execution", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.addExecution(
"Copy of browser forms",
"reset-credentials-choose-user",
);
masthead.checkNotificationMessage("Flow successfully updated");
detailPage.executionExists("Choose User");
});
it("should add a condition", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.addCondition(
"Copy of browser Browser - Conditional OTP",
"conditional-user-role",
);
masthead.checkNotificationMessage("Flow successfully updated");
});
it("Should add a sub-flow", () => {
const flowName = "SubFlow";
listingPage.goToItemDetails("Copy of browser");
detailPage.addSubFlow(
"Copy of browser Browser - Conditional OTP",
flowName,
);
masthead.checkNotificationMessage("Flow successfully updated");
detailPage.flowExists(flowName);
});
it("Should remove an execution", () => {
listingPage.goToItemDetails("Copy of browser");
detailPage.executionExists("Cookie").clickRowDelete("Cookie");
modalUtil.confirmModal();
detailPage.executionExists("Cookie", false);
});
it("Should set as default in action menu", () => {
const bindFlow = new BindFlowModal();
listingPage.clickRowDetails("Copy of browser").clickDetailMenu("Bind flow");
bindFlow.fill("Direct grant flow").save();
masthead.checkNotificationMessage("Flow successfully updated");
});
const flowName = "Empty Flow";
it("should create flow from scratch", () => {
listingPage.goToCreateItem();
detailPage.fillCreateForm(
flowName,
"Some nice description about what this flow does so that we can use it later",
"Client flow",
);
masthead.checkNotificationMessage("Flow created");
detailPage.addSubFlowToEmpty(flowName, "EmptySubFlow");
masthead.checkNotificationMessage("Flow successfully updated");
detailPage.flowExists(flowName);
});
it("Should delete a flow from action menu", () => {
listingPage.clickRowDetails(flowName).clickDetailMenu("Delete");
modalUtil.confirmModal();
masthead.checkNotificationMessage("Flow successfully deleted");
});
it("add webauthn authentication to browserflow", () => {
const flowName = "WebAuthn Browser";
listingPage.clickRowDetails("Browser").clickDetailMenu("Duplicate");
duplicateFlowModal.fill(flowName);
detailPage.clickRowDelete("WebAuthn Browser Browser - Conditional OTP");
modalUtil.confirmModal();
commonPage
.actionToolbarUtils()
.clickActionToggleButton()
.clickDropdownItem("Bind flow");
new BindFlowModal().fill("Direct grant flow").save();
masthead.checkNotificationMessage("Flow successfully updated");
});
it("Should display the default browser flow diagram", () => {
sidebarPage.goToRealm("master");
sidebarPage.goToAuthentication();
listingPage.goToItemDetails("browser");
detailPage.goToDiagram();
diagramView.exists();
diagramView.edgesExist([
{ from: "Start", to: "Cookie" },
{ from: "Cookie", to: "End" },
{ from: "Cookie", to: "Identity Provider Redirector" },
{ from: "Identity Provider Redirector", to: "End" },
{ from: "Identity Provider Redirector", to: "Username Password Form" },
{ from: "Username Password Form", to: "Condition - user configured" },
{ from: "Condition - user configured", to: "OTP Form" },
{ from: "Condition - user configured", to: "End" },
{ from: "OTP Form", to: "End" },
]);
});
});
describe("Required actions", () => {
const requiredActionsPage = new RequiredActions();
before(() => adminClient.createRealm(realmName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
sidebarPage.goToAuthentication();
requiredActionsPage.goToTab();
});
after(() => adminClient.deleteRealm(realmName));
it("should enable delete account", () => {
const action = "Delete Account";
requiredActionsPage.switchAction(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isChecked(action);
});
it("should register an unregistered action", () => {
const action = "Verify Profile";
requiredActionsPage.isChecked(action).isDefaultEnabled(action);
requiredActionsPage.switchAction(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.switchAction(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isChecked(action).isDefaultEnabled(action);
});
it("should set action as default", () => {
const action = "Configure OTP";
requiredActionsPage.setAsDefault(action);
masthead.checkNotificationMessage("Updated required action successfully");
requiredActionsPage.isDefaultChecked(action);
});
it("should reorder required actions", () => {
const action = "Terms and Conditions";
requiredActionsPage.moveRowTo(action, "Update Profile");
masthead.checkNotificationMessage("Updated required action successfully");
});
});
describe("Password policies tab", () => {
const passwordPoliciesPage = new PasswordPolicies();
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToAuthentication();
passwordPoliciesPage.goToTab();
});
it("should add password policies", () => {
passwordPoliciesPage
.shouldShowEmptyState()
.addPolicy("Not Recently Used")
.save();
masthead.checkNotificationMessage("Password policies successfully updated");
});
it("should remove password policies", () => {
passwordPoliciesPage.removePolicy("remove-passwordHistory").save();
masthead.checkNotificationMessage("Password policies successfully updated");
passwordPoliciesPage.shouldShowEmptyState();
});
});
describe("Accessibility tests for authentication", () => {
const realmName = "a11y-realm";
const flowName = "SubFlow";
const requiredActionsPage = new RequiredActions();
const passwordPoliciesPage = new PasswordPolicies();
const otpPoliciesPage = new OTPPolicies();
const webAuthnPolicies = new WebAuthnPolicies();
const detailPage = new FlowDetails();
before(() => adminClient.createRealm(realmName));
after(() => adminClient.deleteRealm(realmName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
sidebarPage.goToAuthentication();
cy.injectAxe();
});
it("Check a11y violations on load/ authentication tab/ flows sub tab", () => {
cy.checkA11y();
});
it("Check a11y violations on load/ authentication tab/ flows sub tab/ creating flow form", () => {
listingPage.goToCreateItem();
cy.checkA11y();
cy.findByTestId("cancel").click();
});
it("Check a11y violations on load/ authentication tab/ flows sub tab/ creating flow", () => {
listingPage.goToCreateItem();
detailPage.fillCreateForm(
flowName,
"Some nice description about what this flow does",
"Client flow",
);
cy.checkA11y();
});
it("Check a11y violations on load/ authentication tab/ flows sub tab/ creating flow form", () => {
listingPage.goToItemDetails("reset credentials");
cy.checkA11y();
});
it("Check a11y violations on load/ authentication tab/ required actions sub tab", () => {
requiredActionsPage.goToTab();
cy.checkA11y();
});
it("Check a11y violations on load/ policies tab/ password policy sub tab", () => {
passwordPoliciesPage.goToTab();
cy.checkA11y();
});
it("Check a11y violations on load/ authentication tab/ policies sub tab/ adding policy", () => {
passwordPoliciesPage.goToTab().addPolicy("Not Recently Used");
cy.checkA11y();
});
it("Check a11y violations on load/ policies tab/ otp policy sub tab", () => {
otpPoliciesPage.goToTab();
cy.checkA11y();
});
it("Check a11y violations on load/ policies tab/ WebAuthn Policies sub tab", () => {
webAuthnPolicies.goToTab();
cy.checkA11y();
});
it("Check a11y violations on load/ policies tab/ WebAuthn Passwordless Policies sub tab", () => {
webAuthnPolicies.goToPasswordlessTab();
cy.checkA11y();
});
it("Check a11y violations on load/ policies tab/ CIBA Policy sub tab", () => {
CIBAPolicyPage.goToTab();
cy.checkA11y();
});
});

View File

@@ -1,149 +0,0 @@
import ClientDetailsPage from "../support/pages/admin-ui/manage/clients/client_details/ClientDetailsPage";
import AdvancedTab from "../support/pages/admin-ui/manage/clients/client_details/tabs/AdvancedTab";
import CreateClientPage from "../support/pages/admin-ui/manage/clients/CreateClientPage";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import CommonPage from "../support/pages/CommonPage";
import LoginPage from "../support/pages/LoginPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const advancedTab = new AdvancedTab();
const realmSettings = new RealmSettingsPage();
const createClientPage = new CreateClientPage();
const clientDetailsPage = new ClientDetailsPage();
const commonPage = new CommonPage();
const loginPage = new LoginPage();
describe("Advanced tab test", () => {
const realmName = `clients-realm-${crypto.randomUUID()}`;
let client: string;
before(() => adminClient.createRealm(realmName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
client = "client_" + crypto.randomUUID();
commonPage.tableToolbarUtils().createClient();
createClientPage
.selectClientType("OpenID Connect")
.fillClientData(client)
.continue();
commonPage.sidebar().waitForPageLoad();
createClientPage.continue().save();
commonPage
.masthead()
.checkNotificationMessage("Client created successfully");
clientDetailsPage.goToAdvancedTab();
});
after(() => adminClient.deleteRealm(realmName));
it("Clustering", () => {
advancedTab.expandClusterNode();
advancedTab.checkEmptyClusterNode();
advancedTab.registerNodeManually().fillHost("localhost").saveHost();
advancedTab.checkTestClusterAvailability(true);
commonPage.masthead().checkNotificationMessage("Node successfully added");
advancedTab.deleteClusterNode();
commonPage.modalUtils().confirmModal();
commonPage.masthead().checkNotificationMessage("Node successfully removed");
advancedTab.checkEmptyClusterNode();
});
it("Fine grain OpenID connect configuration", () => {
const algorithm = "ES384";
advancedTab.selectAccessTokenSignatureAlgorithm(algorithm).saveFineGrain();
advancedTab.selectAccessTokenSignatureAlgorithm("HS384").revertFineGrain();
advancedTab.checkAccessTokenSignatureAlgorithm(algorithm);
});
it("OIDC Compatibility Modes configuration", () => {
advancedTab.clickAllCompatibilitySwitch();
advancedTab.saveCompatibility();
advancedTab.jumpToCompatability();
advancedTab.clickExcludeSessionStateSwitch();
advancedTab.clickUseRefreshTokenForClientCredentialsGrantSwitch();
advancedTab.revertCompatibility();
});
it("Client Offline Session Max", () => {
configureOfflineSessionMaxInRealmSettings(true);
cy.findByTestId("token-lifespan-clientOfflineSessionMax").should("exist");
configureOfflineSessionMaxInRealmSettings(false);
cy.findByTestId("token-lifespan-clientOfflineSessionMax").should(
"not.exist",
);
function configureOfflineSessionMaxInRealmSettings(enabled: boolean) {
commonPage.sidebar().goToRealmSettings();
realmSettings.goToSessionsTab();
realmSettings.setOfflineSessionMaxSwitch(enabled);
realmSettings.saveSessions();
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().searchItem(client);
commonPage.tableUtils().clickRowItemLink(client);
clientDetailsPage.goToAdvancedTab();
}
});
it("Advanced settings", () => {
advancedTab.jumpToAdvanced();
advancedTab.clickAdvancedSwitches();
advancedTab.jumpToAdvanced();
advancedTab.selectKeyForCodeExchangeInput("S256");
advancedTab.saveAdvanced();
advancedTab.jumpToAdvanced();
advancedTab.checkAdvancedSwitchesOn();
advancedTab.checkKeyForCodeExchangeInput("S256");
advancedTab.selectKeyForCodeExchangeInput("plain");
advancedTab.checkKeyForCodeExchangeInput("plain");
advancedTab.jumpToAdvanced();
advancedTab.clickAdvancedSwitches();
advancedTab.revertAdvanced();
advancedTab.jumpToAdvanced();
advancedTab.checkKeyForCodeExchangeInput("S256");
//uncomment when revert button reverts all switches
//and ACR to LoA Mapping + Default ACR Values
//advancedTab.checkAdvancedSwitchesOn();
});
it("Authentication flow override", () => {
advancedTab.jumpToAuthFlow();
advancedTab.selectBrowserFlowInput("browser");
advancedTab.selectDirectGrantInput("docker auth");
advancedTab.checkBrowserFlowInput("browser");
advancedTab.checkDirectGrantInput("docker auth");
advancedTab.revertAuthFlowOverride();
advancedTab.jumpToAuthFlow();
advancedTab.checkBrowserFlowInput("Choose...");
advancedTab.checkDirectGrantInput("Choose...");
advancedTab.selectBrowserFlowInput("browser");
advancedTab.selectDirectGrantInput("docker auth");
advancedTab.saveAuthFlowOverride();
advancedTab.selectBrowserFlowInput("first broker login");
advancedTab.selectDirectGrantInput("first broker login");
advancedTab.revertAuthFlowOverride();
//revert doesn't work after saving.
//advancedTab.CheckBrowserFlowInput("browser");
//advancedTab.CheckDirectGrantInput("docker auth");
});
});

View File

@@ -1,285 +0,0 @@
import { keycloakBefore } from "../support/util/keycloak_hooks";
import adminClient from "../support/util/AdminClient";
import LoginPage from "../support/pages/LoginPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import AuthorizationTab from "../support/pages/admin-ui/manage/clients/client_details/tabs/AuthorizationTab";
import ModalUtils from "../support/util/ModalUtils";
import ClientDetailsPage from "../support/pages/admin-ui/manage/clients/client_details/ClientDetailsPage";
import PoliciesTab from "../support/pages/admin-ui/manage/clients/client_details/tabs/authorization_subtabs/PoliciesTab";
import PermissionsTab from "../support/pages/admin-ui/manage/clients/client_details/tabs/authorization_subtabs/PermissionsTab";
import CreateResourcePage from "../support/pages/admin-ui/manage/clients/client_details/CreateResourcePage";
describe("Client authentication subtab", () => {
const loginPage = new LoginPage();
const listingPage = new ListingPage();
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-" + crypto.randomUUID();
before(() =>
adminClient.createClient({
protocol: "openid-connect",
clientId,
publicClient: false,
authorizationServicesEnabled: true,
serviceAccountsEnabled: true,
standardFlowEnabled: true,
}),
);
after(() => {
adminClient.deleteClient(clientId);
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClients();
listingPage.searchItem(clientId).goToItemDetails(clientId);
clientDetailsPage.goToAuthorizationTab();
});
it("Should update the resource server settings", () => {
policiesSubTab.setPolicy("DISABLED").formUtils().save();
masthead.checkNotificationMessage("Resource successfully updated", true);
});
it("Should create a resource", () => {
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.formUtils().cancel();
});
it("Edit a resource", () => {
authenticationTab.goToResourcesSubTab();
listingPage.goToItemDetails("Resource");
new CreateResourcePage()
.fillResourceForm({
displayName: "updated",
})
.formUtils()
.save();
masthead.checkNotificationMessage("Resource successfully updated");
sidebarPage.waitForPageLoad();
authenticationTab.formUtils().cancel();
});
it("Should create a scope", () => {
authenticationTab
.goToScopesSubTab()
.createAuthorizationScope()
.fillScopeForm({
name: "The scope",
displayName: "Display something",
iconUri: "res://something",
})
.formUtils()
.save();
masthead.checkNotificationMessage(
"Authorization scope created successfully",
true,
);
authenticationTab.goToScopesSubTab();
listingPage.itemExist("The scope");
});
it("Should create a policy", () => {
authenticationTab.goToPoliciesSubTab();
cy.intercept(
"GET",
"/admin/realms/master/clients/*/authz/resource-server/policy/regex/*",
).as("get");
policiesSubTab
.createPolicy("regex")
.fillBasePolicyForm({
name: "Regex policy",
description: "Policy for regex",
targetClaim: "I don't know",
pattern: ".*?",
})
.formUtils()
.save();
cy.wait(["@get"]);
masthead.checkNotificationMessage("Successfully created the policy", true);
sidebarPage.waitForPageLoad();
authenticationTab.formUtils().cancel();
});
it("Should delete a policy", () => {
authenticationTab.goToPoliciesSubTab();
listingPage.deleteItem("Regex policy");
new ModalUtils().confirmModal();
masthead.checkNotificationMessage("The Policy successfully deleted", true);
});
it("Should create a client policy", () => {
authenticationTab.goToPoliciesSubTab();
cy.intercept(
"GET",
"/admin/realms/master/clients/*/authz/resource-server/policy/client/*",
).as("get");
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.formUtils().cancel();
});
it("Should create a permission", () => {
authenticationTab.goToPermissionsSubTab();
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&permission=false",
).as("load");
masthead.checkNotificationMessage(
"Successfully created the permission",
true,
);
authenticationTab.formUtils().cancel();
});
it.skip("Should copy auth details", () => {
const exportTab = authenticationTab.goToExportSubTab();
sidebarPage.waitForPageLoad();
exportTab.copy();
masthead.checkNotificationMessage("Authorization details copied.", true);
});
it("Should export auth details", () => {
const exportTab = authenticationTab.goToExportSubTab();
sidebarPage.waitForPageLoad();
exportTab.export();
masthead.checkNotificationMessage(
"Successfully exported authorization details.",
true,
);
});
describe("Client authorization tab access for view-realm-authorization", () => {
const clientId = "realm-view-authz-client-" + crypto.randomUUID();
beforeEach(async () => {
const [, testUser] = await Promise.all([
adminClient.createRealm("realm-view-authz"),
adminClient.createUser({
// Create user in master realm
username: "test-view-authz-user",
enabled: true,
credentials: [{ type: "password", value: "password" }],
}),
]);
await Promise.all([
adminClient.addClientRoleToUser(
testUser.id!,
"realm-view-authz-realm",
["view-realm", "view-users", "view-authorization", "view-clients"],
),
adminClient.createClient({
realm: "realm-view-authz",
clientId,
authorizationServicesEnabled: true,
serviceAccountsEnabled: true,
standardFlowEnabled: true,
}),
]);
});
after(() =>
Promise.all([
adminClient.deleteClient(clientId),
adminClient.deleteUser("test-view-authz-user"),
adminClient.deleteRealm("realm-view-authz"),
]),
);
it("Should view autorization tab", () => {
sidebarPage.waitForPageLoad();
masthead.signOut();
sidebarPage.waitForPageLoad();
loginPage.logIn("test-view-authz-user", "password");
keycloakBefore();
sidebarPage.waitForPageLoad().goToRealm("realm-view-authz");
cy.reload();
sidebarPage.waitForPageLoad().goToClients();
listingPage
.searchItem(clientId, true, "realm-view-authz")
.goToItemDetails(clientId);
clientDetailsPage.goToAuthorizationTab();
authenticationTab.goToResourcesSubTab();
sidebarPage.waitForPageLoad();
listingPage.goToItemDetails("Resource");
sidebarPage.waitForPageLoad();
cy.go("back");
authenticationTab.goToScopesSubTab();
sidebarPage.waitForPageLoad();
authenticationTab.goToPoliciesSubTab();
sidebarPage.waitForPageLoad();
authenticationTab.goToPermissionsSubTab();
sidebarPage.waitForPageLoad();
authenticationTab.goToEvaluateSubTab();
sidebarPage.waitForPageLoad();
});
});
describe("Accessibility tests for client authorization", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClients();
listingPage.searchItem(clientId).goToItemDetails(clientId);
clientDetailsPage.goToAuthorizationTab();
cy.injectAxe();
});
it("Check a11y violations on load/ client authorization", () => {
cy.checkA11y();
});
});
});

View File

@@ -1,86 +0,0 @@
import InitialAccessTokenTab from "../support/pages/admin-ui/manage/clients/tabs/InitialAccessTokenTab";
import CommonPage from "../support/pages/CommonPage";
import LoginPage from "../support/pages/LoginPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const commonPage = new CommonPage();
const loginPage = new LoginPage();
describe("Client initial access tokens", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToClients();
});
it("Initial access token can't be created with 0 days and count", () => {
const initialAccessTokenTab = new InitialAccessTokenTab();
initialAccessTokenTab
.goToInitialAccessTokenTab()
.shouldBeEmpty()
.goToCreateFromEmptyList()
.fillNewTokenData(0, 0)
.checkExpirationGreaterThanZeroError()
.checkCountValue(1)
.checkSaveButtonIsDisabled();
});
it("Initial access token", () => {
const initialAccessTokenTab = new InitialAccessTokenTab();
initialAccessTokenTab
.goToInitialAccessTokenTab()
.shouldBeEmpty()
.goToCreateFromEmptyList()
.fillNewTokenData(1, 3)
.save();
commonPage
.modalUtils()
.checkModalTitle("Initial access token details")
.closeModal();
commonPage
.masthead()
.checkNotificationMessage("New initial access token has been created");
initialAccessTokenTab.shouldNotBeEmpty();
commonPage.tableToolbarUtils().searchItem("John Doe", false);
commonPage.emptyState().checkIfExists(true);
commonPage.tableToolbarUtils().searchItem("", false);
initialAccessTokenTab.getFirstId((id) => {
commonPage
.tableUtils()
.checkRowItemValueByItemName(id, 4, "4")
.checkRowItemValueByItemName(id, 5, "4")
.checkRowItemExists(id);
});
commonPage.tableToolbarUtils().clickPrimaryButton("Create");
initialAccessTokenTab.fillNewTokenData(1, 3).save();
commonPage.modalUtils().closeModal();
initialAccessTokenTab.getFirstId((id) => {
commonPage.tableUtils().selectRowItemAction(id, "Delete");
commonPage.sidebar().waitForPageLoad();
commonPage
.modalUtils()
.checkModalTitle("Delete initial access token?")
.confirmModal();
});
commonPage
.masthead()
.checkNotificationMessage("Initial access token deleted successfully");
initialAccessTokenTab.shouldNotBeEmpty();
initialAccessTokenTab.getFirstId((id) => {
commonPage.tableUtils().selectRowItemAction(id, "Delete");
commonPage.sidebar().waitForPageLoad();
commonPage.modalUtils().confirmModal();
});
initialAccessTokenTab.shouldBeEmpty();
});
});

View File

@@ -1,144 +0,0 @@
import ListingPage from "../support/pages/admin-ui/ListingPage";
import { ClientRegistrationPage } from "../support/pages/admin-ui/manage/clients/ClientRegistrationPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const listingPage = new ListingPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const clientRegistrationPage = new ClientRegistrationPage();
describe("Client registration policies tab", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClients();
clientRegistrationPage.goToClientRegistrationTab();
sidebarPage.waitForPageLoad();
});
describe("Anonymous client policies subtab", () => {
it("check anonymous clients list is not empty", () => {
cy.findByTestId("clientRegistration-anonymous")
.find("tr")
.should("have.length.gt", 0);
});
it("add anonymous client registration policy", () => {
clientRegistrationPage
.createAnonymousPolicy()
.selectRow("max-clients")
.fillPolicyForm({
name: "newAnonymPolicy1",
})
.formUtils()
.save();
masthead.checkNotificationMessage(
"New client policy created successfully",
);
clientRegistrationPage.formUtils().cancel();
listingPage.itemExist("newAnonymPolicy1");
});
it("edit anonymous client registration policy", () => {
const policy = "newAnonymPolicy1";
clientRegistrationPage.findAndSelectInAnonymousPoliciesTable(policy);
cy.findByTestId("name").clear();
clientRegistrationPage
.fillPolicyForm({
name: "policy2",
})
.formUtils()
.save();
masthead.checkNotificationMessage("Client policy updated successfully");
clientRegistrationPage.formUtils().cancel();
listingPage.itemExist("policy2");
});
it("delete anonymous client registration policy", () => {
const policy = "policy2";
listingPage.deleteItem(policy);
cy.findByTestId("confirm").click();
masthead.checkNotificationMessage(
"Client registration policy deleted successfully",
);
});
});
describe("Authenticated client policies subtab", () => {
beforeEach(() => {
clientRegistrationPage.goToAuthenticatedSubTab();
sidebarPage.waitForPageLoad();
});
it("check authenticated clients list is not empty", () => {
cy.findByTestId("clientRegistration-authenticated")
.find("tr")
.should("have.length.gt", 0);
});
it("add authenticated client registration policy", () => {
clientRegistrationPage
.createAuthenticatedPolicy()
.selectRow("scope")
.fillPolicyForm({
name: "newAuthPolicy1",
})
.formUtils()
.save();
masthead.checkNotificationMessage(
"New client policy created successfully",
);
clientRegistrationPage.formUtils().cancel();
listingPage.itemExist("newAuthPolicy1");
});
it("edit authenticated client registration policy", () => {
const policy = "newAuthPolicy1";
clientRegistrationPage.findAndSelectInAuthenticatedPoliciesTable(policy);
cy.findByTestId("name").clear();
clientRegistrationPage
.fillPolicyForm({
name: "policy3",
})
.formUtils()
.save();
masthead.checkNotificationMessage("Client policy updated successfully");
clientRegistrationPage.formUtils().cancel();
listingPage.itemExist("policy3");
});
it("delete authenticated client registration policy", () => {
const policy = "policy3";
listingPage.deleteItem(policy);
cy.findByTestId("confirm").click();
masthead.checkNotificationMessage(
"Client registration policy deleted successfully",
);
});
});
});
describe("Accessibility tests for client registration policies", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClients();
clientRegistrationPage.goToClientRegistrationTab();
sidebarPage.waitForPageLoad();
cy.injectAxe();
});
it("Check a11y violations on load/ client registration policies", () => {
cy.checkA11y();
});
});

View File

@@ -1,309 +0,0 @@
import ListingPage, {
Filter,
FilterAssignedType,
} from "../support/pages/admin-ui/ListingPage";
import ClientDetailsPage from "../support/pages/admin-ui/manage/clients/client_details/ClientDetailsPage";
import CommonPage from "../support/pages/CommonPage";
import LoginPage from "../support/pages/LoginPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const clientDetailsPage = new ClientDetailsPage();
const commonPage = new CommonPage();
const listingPage = new ListingPage();
describe("Client details - Client scopes subtab", () => {
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: "",
protocol: "openid-connect",
attributes: {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"gui.order": "1",
"consent.screen.text": "",
},
};
const msgScopeMappingRemoved = "Scope mapping successfully removed";
const realmName = `clients-realm-${crypto.randomUUID()}`;
before(async () => {
await adminClient.createRealm(realmName);
await adminClient.inRealm(realmName, () =>
adminClient.createClient({
clientId,
protocol: "openid-connect",
publicClient: false,
}),
);
for (let i = 0; i < 5; i++) {
clientScope.name = clientScopeName + i;
await adminClient.inRealm(realmName, () =>
adminClient.createClientScope(clientScope),
);
await adminClient.inRealm(realmName, () =>
adminClient.addDefaultClientScopeInClient(
clientScopeName + i,
clientId,
),
);
}
clientScope.name = clientScopeNameDefaultType;
await adminClient.inRealm(realmName, () =>
adminClient.createClientScope(clientScope),
);
clientScope.name = clientScopeNameOptionalType;
await adminClient.inRealm(realmName, () =>
adminClient.createClientScope(clientScope),
);
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().searchItem(clientId);
cy.intercept(`/admin/realms/${realmName}/clients/*`).as("fetchClient");
commonPage.tableUtils().clickRowItemLink(clientId);
cy.wait("@fetchClient");
clientDetailsPage.goToClientScopesTab();
});
after(() => adminClient.deleteRealm(realmName));
it("Should list client scopes", () => {
commonPage
.tableUtils()
.checkRowItemsGreaterThan(1)
.checkRowItemExists(clientScopeName + 0);
});
it("Should search existing client scope by name", () => {
commonPage.tableToolbarUtils().searchItem(clientScopeName + 0, false);
commonPage
.tableUtils()
.checkRowItemExists(clientScopeName + 0)
.checkRowItemsEqualTo(1);
});
it("Should search non-existent client scope by name", () => {
commonPage.tableToolbarUtils().searchItem("non-existent-item", false);
commonPage.tableUtils().checkIfExists(false);
commonPage.emptyState().checkIfExists(true);
});
it("Should search existing client scope by assigned type", () => {
commonPage
.tableToolbarUtils()
.selectSearchType(Filter.Name, 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);
});
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`, () => {
commonPage.tableToolbarUtils().addClientScope();
commonPage
.modalUtils()
.checkModalTitle("Add client scopes to " + clientId);
commonPage.tableUtils().selectRowItemCheckbox(itemName);
commonPage.modalUtils().confirmModalWithItem(assignedType);
commonPage.masthead().checkNotificationMessage("Scope mapping updated");
commonPage.tableToolbarUtils().searchItem(itemName, false);
commonPage
.tableUtils()
.checkRowItemExists(itemName)
.checkRowItemExists(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`, () => {
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", () => {
commonPage.sidebar().waitForPageLoad();
commonPage.tableToolbarUtils().clickNextPageButton();
commonPage.tableUtils().checkRowItemsGreaterThan(1);
});
it("Should remove client scope from item bar", () => {
const itemName = clientScopeName + 0;
commonPage.tableToolbarUtils().searchItem(itemName, false);
commonPage.tableUtils().selectRowItemAction(itemName, "Remove");
commonPage.modalUtils().confirmModal();
commonPage.masthead().checkNotificationMessage(msgScopeMappingRemoved);
commonPage.tableToolbarUtils().searchItem(itemName, false);
listingPage.assertNoResults();
});
it("Should remove multiple client scopes from search bar", () => {
const itemName1 = clientScopeName + 1;
const itemName2 = clientScopeName + 2;
cy.intercept(`/admin/realms/${realmName}/client-scopes`).as("load");
commonPage.tableToolbarUtils().clickSearchButton();
cy.wait("@load");
cy.wait(1000);
commonPage.tableToolbarUtils().checkActionItemIsEnabled("Remove", false);
commonPage.tableToolbarUtils().searchItem(clientScopeName, false);
commonPage
.tableUtils()
.selectRowItemCheckbox(itemName1)
.selectRowItemCheckbox(itemName2);
cy.intercept(`/admin/realms/${realmName}/client-scopes`).as("load");
commonPage.tableToolbarUtils().clickSearchButton();
cy.wait("@load");
cy.wait(1000);
commonPage.tableToolbarUtils().clickActionItem("Remove");
commonPage.masthead().checkNotificationMessage(msgScopeMappingRemoved);
commonPage.tableToolbarUtils().searchItem(clientScopeName, false);
commonPage
.tableUtils()
.checkRowItemExists(itemName1, false)
.checkRowItemExists(itemName2, false);
commonPage.tableToolbarUtils().clickSearchButton();
});
it("Should show initial items after filtering", () => {
commonPage
.tableToolbarUtils()
.selectSearchType(Filter.Name, Filter.AssignedType)
.selectSecondarySearchType(FilterAssignedType.Optional)
.selectSearchType(Filter.AssignedType, Filter.Name);
commonPage
.tableUtils()
.checkRowItemExists(FilterAssignedType.Default, false)
.checkRowItemExists(FilterAssignedType.Optional);
});
describe("Client scopes evaluate subtab", () => {
const clientName = "testClient";
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
});
before(async () => {
await adminClient.inRealm(realmName, () =>
adminClient.createClient({
protocol: "openid-connect",
clientId: clientName,
publicClient: false,
}),
);
await adminClient.inRealm(realmName, () =>
adminClient.createUser({
username: "admin-a",
enabled: true,
}),
);
});
after(async () => {
await adminClient.inRealm(realmName, () =>
adminClient.deleteClient(clientName),
);
});
it("check effective protocol mappers list is not empty and find effective protocol mapper locale", () => {
commonPage.tableToolbarUtils().searchItem(clientName);
commonPage.tableUtils().clickRowItemLink(clientName);
clientDetailsPage.goToClientScopesEvaluateTab();
cy.findByTestId("effective-protocol-mappers")
.find("tr")
.should("have.length.gt", 0);
});
it("check role scope mappings list list is not empty and find role scope mapping admin", () => {
commonPage.tableToolbarUtils().searchItem(clientName);
commonPage.tableUtils().clickRowItemLink(clientName);
clientDetailsPage.goToClientScopesEvaluateTab();
clientDetailsPage.goToClientScopesEvaluateEffectiveRoleScopeMappingsTab();
cy.findByTestId("effective-role-scope-mappings")
.find("tr")
.should("have.length.gt", 0);
});
it("check generated id token and user info", () => {
commonPage.tableToolbarUtils().searchItem(clientName);
commonPage.tableUtils().clickRowItemLink(clientName);
clientDetailsPage.goToClientScopesEvaluateTab();
cy.get("div#generatedAccessToken").contains("No generated access token");
clientDetailsPage.goToClientScopesEvaluateGeneratedIdTokenTab();
cy.get("div#generatedIdToken").contains("No generated id token");
clientDetailsPage.goToClientScopesEvaluateGeneratedUserInfoTab();
cy.get("div#generatedUserInfo").contains("No generated user info");
cy.get("[data-testid='user'] input").type("admin-a");
cy.get(".pf-v5-c-menu__item-text").click();
clientDetailsPage.goToClientScopesEvaluateGeneratedAccessTokenTab();
cy.get("div#generatedAccessToken").contains(
'"preferred_username": "admin-a"',
);
cy.get("div#generatedAccessToken").contains('"scope": "');
clientDetailsPage.goToClientScopesEvaluateGeneratedIdTokenTab();
cy.get("div#generatedIdToken").contains(
'"preferred_username": "admin-a"',
);
clientDetailsPage.goToClientScopesEvaluateGeneratedUserInfoTab();
cy.get("div#generatedIdToken").contains(
'"preferred_username": "admin-a"',
);
cy.get("div#generatedIdToken").contains('"sid"');
});
});
});

View File

@@ -1,493 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ListingPage, {
Filter,
FilterAssignedType,
FilterProtocol,
} from "../support/pages/admin-ui/ListingPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import CreateClientScopePage from "../support/pages/admin-ui/manage/client_scopes/CreateClientScopePage";
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";
import DedicatedScopesMappersTab from "../support/pages/admin-ui/manage/clients/client_details/DedicatedScopesMappersTab";
import ClientDetailsPage from "../support/pages/admin-ui/manage/clients/client_details/ClientDetailsPage";
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();
const dedicatedScopesMappersTab = new DedicatedScopesMappersTab();
const clientDetailsPage = new ClientDetailsPage();
describe("Client Scopes test", () => {
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 () => {
for (let i = 0; i < 5; i++) {
clientScope.name = clientScopeName + i;
await adminClient.createClientScope(clientScope);
}
});
after(async () => {
for (let i = 0; i < 5; i++) {
if (await adminClient.existsClientScope(clientScopeName + i)) {
await adminClient.deleteClientScope(clientScopeName + i);
}
}
});
describe("Client Scope filter list items", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClientScopes();
});
it("should filter item by name", () => {
const itemName = clientScopeName + 0;
listingPage
.checkEmptySearch()
.searchItem(itemName, false)
.itemsEqualTo(1)
.itemExist(itemName, true);
});
it("should filter items by Assigned type All types", () => {
listingPage
.selectClientScopeFilter(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
.selectClientScopeFilter(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
.selectClientScopeFilter(Filter.AssignedType)
.selectSecondaryFilterAssignedType(FilterAssignedType.Optional)
.itemExist(FilterAssignedType.Default, false)
.itemExist(FilterAssignedType.Optional, true)
.itemExist(FilterAssignedType.None, false);
});
it("should filter items by Protocol All", () => {
listingPage
.selectClientScopeFilter(Filter.Protocol)
.selectSecondaryFilterProtocol(FilterProtocol.All);
sidebarPage.waitForPageLoad();
listingPage
.showNextPageTableItems()
.itemExist(FilterProtocol.SAML, true)
.itemExist(openIDConnectItemText, true); //using FilterProtocol.OpenID will fail, text does not match.
});
it("should filter items by Protocol SAML", () => {
listingPage
.selectClientScopeFilter(Filter.Protocol)
.selectSecondaryFilterProtocol(FilterProtocol.SAML)
.itemExist(FilterProtocol.SAML, true)
.itemExist(openIDConnectItemText, false); //using FilterProtocol.OpenID will fail, text does not match.
});
it("should filter items by Protocol OpenID", () => {
listingPage
.selectClientScopeFilter(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);
});
});
describe("Client Scope modify list items", () => {
const itemName = clientScopeName + 0;
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
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);
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 ", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClientScopes();
});
it("should delete item from item bar", () => {
listingPage
.checkInSearchBarChangeTypeToButtonIsDisabled()
.clickItemCheckbox(clientScopeName + 0)
.deleteItem(clientScopeName + 0);
modalUtils
.checkModalMessage(modalMessageDeleteConfirmation)
.confirmModal();
masthead.checkNotificationMessage(
notificationMessageDeletionConfirmation,
);
listingPage.checkInSearchBarChangeTypeToButtonIsDisabled();
});
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();
});
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(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClientScopes();
});
it("should fail creating client scope", () => {
sidebarPage.waitForPageLoad();
listingPage.goToCreateItem();
createClientScopePage.save_is_disabled(true);
createClientScopePage.fillClientScopeData("address").save();
masthead.checkNotificationMessage(
"Could not create client scope: 'Client Scope address already exists'",
);
createClientScopePage.fillClientScopeData("");
createClientScopePage.save_is_disabled(true);
});
it("hides 'consent text' field when 'display consent' switch is disabled", () => {
sidebarPage.waitForPageLoad();
listingPage.goToCreateItem();
createClientScopePage
.getSwitchDisplayOnConsentScreenInput()
.should("be.checked");
createClientScopePage.getConsentScreenTextInput().should("exist");
createClientScopePage.switchDisplayOnConsentScreen();
createClientScopePage
.getSwitchDisplayOnConsentScreenInput()
.should("not.be.checked");
createClientScopePage.getConsentScreenTextInput().should("not.exist");
});
it("Client scope CRUD test", () => {
itemId += "_" + crypto.randomUUID();
// Create
listingPage.itemExist(itemId, false).goToCreateItem();
createClientScopePage.fillClientScopeData(itemId).save();
masthead.checkNotificationMessage("Client scope created");
sidebarPage.goToClientScopes();
sidebarPage.waitForPageLoad();
// Delete
listingPage
.searchItem(itemId, false)
.itemExist(itemId)
.deleteItem(itemId);
modalUtils
.checkModalMessage(modalMessageDeleteConfirmation)
.confirmModal();
masthead.checkNotificationMessage("The client scope has been deleted");
listingPage.itemExist(itemId, false);
});
});
describe("Scope tab test", () => {
const scopeTab = new RoleMappingTab("client-scope");
const scopeName = "address";
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClientScopes();
});
it("Assign and unassign role", () => {
const role = "admin";
const roleType = "roles";
listingPage.searchItem(scopeName, false).goToItemDetails(scopeName);
scopeTab
.goToScopeTab()
.assignRole()
.changeRoleTypeFilter(roleType)
.selectRow(role)
.assign();
masthead.checkNotificationMessage("Role mapping updated");
scopeTab.checkRoles([role]);
scopeTab.hideInheritedRoles().selectRow(role).unAssign();
modalUtils.checkModalTitle("Remove role?").confirmModal();
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]);
});
});
describe("Accessibility tests for client scopes", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClientScopes();
cy.injectAxe();
});
const scopeName = "a11y_" + crypto.randomUUID();
after(async () => {
await adminClient.deleteClientScope(scopeName);
});
it("Check a11y violations on load/ client scopes", () => {
cy.checkA11y();
});
it("Check a11y violations on empty client scope", () => {
listingPage.goToCreateItem();
cy.checkA11y();
});
it("Check a11y violations on client scope details", () => {
const clientScopeDetailsPage = new ClientScopeDetailsPage();
const mappersTab = new MappersTab();
const predefinedMapperName = "Predefined Mapper test";
const predefinedMapper = "Allowed Web Origins";
const scopeTab = new RoleMappingTab("client-scope");
const role = "admin";
const roleType = "roles";
listingPage.goToCreateItem();
createClientScopePage.fillClientScopeData(scopeName).save();
cy.checkA11y();
clientScopeDetailsPage.goToMappersTab();
cy.checkA11y();
dedicatedScopesMappersTab.addPredefinedMapper();
cy.checkA11y();
clientDetailsPage.modalUtils().table().clickHeaderItem(1, "input");
cy.findByTestId("confirm").click();
cy.checkA11y();
mappersTab.addMappersByConfiguration(
predefinedMapper,
predefinedMapperName,
);
cy.checkA11y();
sidebarPage.goToClientScopes();
listingPage.searchItem(scopeName, false).goToItemDetails(scopeName);
clientScopeDetailsPage.goToScopesTab();
cy.checkA11y();
cy.findByTestId("no-roles-for-this-client-scope-empty-action").click();
cy.checkA11y();
cy.findByTestId("cancel").click();
scopeTab
.goToScopeTab()
.assignRole()
.changeRoleTypeFilter(roleType)
.selectRow(role)
.assign();
cy.checkA11y();
});
});
});

View File

@@ -1,220 +0,0 @@
import AttributesTab from "../support/pages/admin-ui/manage/AttributesTab";
import ClientRolesTab from "../support/pages/admin-ui/manage/clients/ClientRolesTab";
import AssociatedRolesPage from "../support/pages/admin-ui/manage/realm_roles/AssociatedRolesPage";
import createRealmRolePage from "../support/pages/admin-ui/manage/realm_roles/CreateRealmRolePage";
import CommonPage from "../support/pages/CommonPage";
import LoginPage from "../support/pages/LoginPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const associatedRolesPage = new AssociatedRolesPage();
const attributesTab = new AttributesTab();
const commonPage = new CommonPage();
const loginPage = new LoginPage();
describe("Roles tab test", () => {
const realmName = `clients-realm-${crypto.randomUUID()}`;
const itemId = `client_crud${crypto.randomUUID()}`;
const rolesTab = new ClientRolesTab();
const client = "client_" + crypto.randomUUID();
const createRealmRoleName = `create-realm-${crypto.randomUUID()}`;
before(async () => {
await adminClient.createRealm(realmName);
await adminClient.inRealm(realmName, () =>
adminClient.createClient({
clientId: client,
protocol: "openid-connect",
publicClient: false,
}),
);
await adminClient.inRealm(realmName, () =>
adminClient.createRealmRole({
name: createRealmRoleName,
}),
);
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().searchItem(client);
commonPage.tableUtils().clickRowItemLink(client);
rolesTab.goToRolesTab();
});
after(() => adminClient.deleteRealm(realmName));
it("Should fail to create client role with empty name", () => {
rolesTab.goToCreateRoleFromEmptyState();
createRealmRolePage.fillRealmRoleData("").save();
createRealmRolePage.checkRealmRoleNameRequiredMessage();
});
it("Should create client role", () => {
rolesTab.goToCreateRoleFromEmptyState();
createRealmRolePage.fillRealmRoleData(itemId).save();
commonPage.masthead().checkNotificationMessage("Role created", true);
});
it("Should update client role description", () => {
const updateDescription = "updated description";
commonPage.tableToolbarUtils().searchItem(itemId, false);
commonPage.tableUtils().clickRowItemLink(itemId);
createRealmRolePage.updateDescription(updateDescription).save();
commonPage
.masthead()
.checkNotificationMessage("The role has been saved", true);
createRealmRolePage.checkDescription(updateDescription);
});
it("Should add attribute to client role", () => {
commonPage.tableUtils().clickRowItemLink(itemId);
rolesTab.goToAttributesTab();
attributesTab
.addAttribute("crud_attribute_key", "crud_attribute_value")
.save();
attributesTab.assertRowItemsEqualTo(1);
commonPage
.masthead()
.checkNotificationMessage("The role has been saved", true);
});
it("Should delete attribute from client role", () => {
commonPage.tableUtils().clickRowItemLink(itemId);
rolesTab.goToAttributesTab();
attributesTab.deleteAttribute(0);
attributesTab.assertEmpty();
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();
commonPage.masthead().checkNotificationMessage("Role created", true);
});
it("Should fail to create duplicate client role", () => {
rolesTab.goToCreateRoleFromToolbar();
createRealmRolePage.fillRealmRoleData(itemId).save();
commonPage
.masthead()
.checkNotificationMessage(
`Could not create role: Role with name ${itemId} already exists`,
true,
);
});
it("Should search existing client role", () => {
commonPage.tableToolbarUtils().searchItem(itemId, false);
commonPage.tableUtils().checkRowItemExists(itemId);
});
it("Should search non-existing role test", () => {
commonPage.tableToolbarUtils().searchItem("role_DNE", false);
commonPage.emptyState().checkIfExists(true);
});
it("roles empty search test", () => {
commonPage.tableToolbarUtils().searchItem("", false);
commonPage.tableUtils().checkIfExists(true);
});
it("Add associated roles test", () => {
commonPage.tableToolbarUtils().searchItem(itemId, false);
commonPage.tableUtils().clickRowItemLink(itemId);
// Add associated realm role
associatedRolesPage.addAssociatedRealmRole(createRealmRoleName);
commonPage
.masthead()
.checkNotificationMessage("Associated roles have been added", true);
// Add associated client role
associatedRolesPage.addAssociatedRoleFromSearchBar("manage-account", true);
commonPage
.masthead()
.checkNotificationMessage("Associated roles have been added", true);
rolesTab.goToAssociatedRolesTab();
// Add associated client role
associatedRolesPage.addAssociatedRoleFromSearchBar("manage-consent", true);
commonPage
.masthead()
.checkNotificationMessage("Associated roles have been added", true);
});
it("Should hide inherited roles test", () => {
commonPage.tableToolbarUtils().searchItem(itemId, false);
commonPage.tableUtils().clickRowItemLink(itemId);
rolesTab.goToAssociatedRolesTab().hideInheritedRoles();
});
it("Should delete associated roles test", () => {
commonPage.tableToolbarUtils().searchItem(itemId, false);
commonPage.tableUtils().clickRowItemLink(itemId);
rolesTab.goToAssociatedRolesTab();
commonPage
.tableUtils()
.selectRowItemAction(createRealmRoleName, "Unassign");
commonPage.sidebar().waitForPageLoad();
commonPage.modalUtils().checkModalTitle("Remove role?").confirmModal();
commonPage.sidebar().waitForPageLoad();
commonPage
.masthead()
.checkNotificationMessage("Role mapping updated", true);
commonPage.tableUtils().selectRowItemAction("manage-consent", "Unassign");
commonPage.sidebar().waitForPageLoad();
commonPage.modalUtils().checkModalTitle("Remove role?").confirmModal();
});
it("Should delete associated role from search bar test", () => {
commonPage.tableToolbarUtils().searchItem(itemId, false);
commonPage.tableUtils().clickRowItemLink(itemId);
commonPage.sidebar().waitForPageLoad();
rolesTab.goToAssociatedRolesTab();
cy.get("td")
.contains("manage-account")
.parent()
.within(() => {
cy.get("input").click();
});
associatedRolesPage.removeAssociatedRoles();
commonPage.sidebar().waitForPageLoad();
commonPage.modalUtils().checkModalTitle("Remove role?").confirmModal();
commonPage.sidebar().waitForPageLoad();
commonPage
.masthead()
.checkNotificationMessage("Role mapping updated", true);
});
it("Should delete client role test", () => {
commonPage.tableUtils().selectRowItemAction(itemId, "Delete");
commonPage.sidebar().waitForPageLoad();
commonPage.modalUtils().checkModalTitle("Delete role?").confirmModal();
});
it("Should delete client role from role details test", () => {
commonPage
.tableToolbarUtils()
.searchItem("client_role_to_be_deleted", false);
commonPage.tableUtils().clickRowItemLink("client_role_to_be_deleted");
createRealmRolePage.clickActionMenu("Delete this role");
commonPage.modalUtils().confirmModal();
commonPage
.masthead()
.checkNotificationMessage("The role has been deleted", true);
});
});

View File

@@ -1,59 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import { AdvancedSamlTab } from "../support/pages/admin-ui/manage/clients/client_details/tabs/AdvancedSamlTab";
import ClientDetailsPage from "../support/pages/admin-ui/manage/clients/client_details/ClientDetailsPage";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const listingPage = new ListingPage();
const advancedTab = new AdvancedSamlTab();
describe("Clients Saml advanced tab", () => {
describe("Fine Grain SAML Endpoint Configuration", () => {
const clientName = "advanced-tab";
before(() => {
adminClient.createClient({
protocol: "saml",
clientId: clientName,
publicClient: false,
});
});
after(() => {
adminClient.deleteClient(clientName);
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClients();
listingPage.searchItem(clientName).goToItemDetails(clientName);
new ClientDetailsPage().goToAdvancedTab();
});
it("Should Terms of service URL", () => {
const termsOfServiceUrl = "http://some.url/terms-of-service.html";
advancedTab.termsOfServiceUrl(termsOfServiceUrl).saveFineGrain();
masthead.checkNotificationMessage("Client successfully updated");
advancedTab
.termsOfServiceUrl("http://not.saveing.this/")
.revertFineGrain();
advancedTab.checkTermsOfServiceUrl(termsOfServiceUrl);
});
it("Invalid terms of service URL", () => {
advancedTab.termsOfServiceUrl("not a url").saveFineGrain();
masthead.checkNotificationMessage(
"Client could not be updated: invalid_input",
);
});
});
});

View File

@@ -1,192 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import ModalUtils from "../support/util/ModalUtils";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import SettingsTab from "../support/pages/admin-ui/manage/clients/client_details/tabs/SettingsTab";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const listingPage = new ListingPage();
const modalUtils = new ModalUtils();
describe("Clients SAML tests", () => {
describe("SAML test", () => {
const samlClientName = "saml";
before(() => {
adminClient.createClient({
protocol: "saml",
clientId: samlClientName,
publicClient: false,
});
});
after(() => {
adminClient.deleteClient(samlClientName);
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClients();
listingPage.searchItem(samlClientName).goToItemDetails(samlClientName);
});
it("should display the saml sections on details screen", () => {
cy.get(".pf-v5-c-jump-links__list").should(($ul) => {
expect($ul)
.to.contain("SAML capabilities")
.to.contain("Signature and Encryption");
});
});
it("should save force name id format", () => {
cy.get(".pf-v5-c-jump-links__list").contains("SAML capabilities").click();
cy.findByTestId("attributes.saml🍺force🍺post🍺binding").click({
force: true,
});
cy.findByTestId("settings-save").click();
masthead.checkNotificationMessage("Client successfully updated");
});
});
describe("SAML keys tab", () => {
const clientId = "saml-keys";
before(() => {
adminClient.createClient({
clientId,
protocol: "saml",
});
});
after(() => {
adminClient.deleteClient(clientId);
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClients();
listingPage.searchItem(clientId).goToItemDetails(clientId);
cy.findByTestId("keysTab").click();
});
it("should doesn't disable signature when cancel", () => {
cy.findByTestId("clientSignature").click({ force: true });
modalUtils
.checkModalTitle('Disable "Client signature required"')
.cancelModal();
cy.findAllByTestId("certificate").should("have.length", 1);
});
it("should disable client signature", () => {
cy.intercept(
"admin/realms/master/clients/*/certificates/saml.signing",
).as("load");
cy.findByTestId("clientSignature").click({ force: true });
modalUtils
.checkModalTitle('Disable "Client signature required"')
.confirmModal();
masthead.checkNotificationMessage("Client successfully updated");
cy.findAllByTestId("certificate").should("have.length", 0);
});
it("should enable Encryption keys config", () => {
cy.findByTestId("encryptAssertions").click({ force: true });
cy.findByTestId("generate").click();
masthead.checkNotificationMessage(
"New key pair and certificate generated successfully",
);
modalUtils.confirmModal();
cy.findAllByTestId("certificate").should("have.length", 1);
});
});
describe("SAML settings tab", () => {
const clientId = "saml-settings";
const settingsTab = new SettingsTab();
before(() => {
adminClient.createClient({
clientId,
protocol: "saml",
});
});
after(() => {
adminClient.deleteClient(clientId);
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToClients();
listingPage.searchItem(clientId).goToItemDetails(clientId);
});
it("should check SAML capabilities", () => {
cy.get(".pf-v5-c-jump-links__list").contains("SAML capabilities").click();
settingsTab.assertNameIdFormatDropdown();
settingsTab.assertSAMLCapabilitiesSwitches();
});
it("should check signature and encryption", () => {
cy.get(".pf-v5-c-jump-links__list")
.contains("Signature and Encryption")
.click();
settingsTab.assertSignatureAlgorithmDropdown();
settingsTab.assertSignatureKeyNameDropdown();
settingsTab.assertCanonicalizationDropdown();
settingsTab.assertSignatureEncryptionSwitches();
});
it("should check access settings", () => {
cy.get(".pf-v5-c-jump-links__list").contains("Access settings").click();
const validUrl =
"http://localhost:8180/realms/master/protocol/" +
clientId +
"/clients/";
const invalidUrlError = "Client could not be updated: invalid_input";
cy.findByTestId("rootUrl").type("Invalid URL");
settingsTab.clickSaveBtn();
masthead.checkNotificationMessage(invalidUrlError);
cy.findByTestId("rootUrl").clear();
cy.findByTestId("baseUrl").type("Invalid URL");
settingsTab.clickSaveBtn();
masthead.checkNotificationMessage(invalidUrlError);
cy.findByTestId("baseUrl").clear();
cy.findByTestId("rootUrl").type(validUrl);
cy.findByTestId("baseUrl").type(validUrl);
settingsTab.clickSaveBtn();
masthead.checkNotificationMessage("Client successfully updated");
settingsTab.assertAccessSettings();
});
it("should check login settings", () => {
cy.get(".pf-v5-c-jump-links__list").contains("Login settings").click();
settingsTab.assertLoginThemeDropdown();
settingsTab.assertLoginSettings();
});
});
});

View File

@@ -1,617 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import CreateClientPage from "../support/pages/admin-ui/manage/clients/CreateClientPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import RoleMappingTab from "../support/pages/admin-ui/manage/RoleMappingTab";
import ClientRolesTab from "../support/pages/admin-ui/manage/clients/ClientRolesTab";
import ClientDetailsPage, {
ClientsDetailsTab,
} from "../support/pages/admin-ui/manage/clients/client_details/ClientDetailsPage";
import CommonPage from "../support/pages/CommonPage";
import DedicatedScopesMappersTab from "../support/pages/admin-ui/manage/clients/client_details/DedicatedScopesMappersTab";
import { ClientRegistrationPage } from "../support/pages/admin-ui/manage/clients/ClientRegistrationPage";
let itemId = "client_crud";
const loginPage = new LoginPage();
const createClientPage = new CreateClientPage();
const clientDetailsPage = new ClientDetailsPage();
const commonPage = new CommonPage();
const listingPage = new ListingPage();
const dedicatedScopesMappersTab = new DedicatedScopesMappersTab();
describe("Clients test", () => {
const realmName = `clients-realm-${crypto.randomUUID()}`;
before(() => adminClient.createRealm(realmName));
after(() => adminClient.deleteRealm(realmName));
describe("Client creation", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
});
it("Should cancel creating client", () => {
commonPage.tableToolbarUtils().createClient();
createClientPage.continue().checkClientIdRequiredMessage();
createClientPage
.fillClientData("")
.selectClientType("OpenID Connect")
.cancel();
cy.url().should("not.include", "/add-client");
});
it("Should check settings elements", () => {
commonPage.tableToolbarUtils().clickPrimaryButton();
const clientId = "Test settings";
createClientPage
.fillClientData(clientId)
.continue()
.checkCapabilityConfigElements()
.continue()
.save();
commonPage
.masthead()
.checkNotificationMessage("Client created successfully");
commonPage.sidebar().waitForPageLoad();
createClientPage
.checkCapabilityConfigElements()
.checkAccessSettingsElements()
.checkLoginSettingsElements()
.checkLogoutSettingsElements()
.deleteClientFromActionDropdown();
commonPage.modalUtils().confirmModal();
commonPage.tableUtils().checkRowItemExists(clientId, false);
});
it("Should navigate to previous using 'back' button", () => {
commonPage.tableToolbarUtils().createClient();
createClientPage.continue().checkClientIdRequiredMessage();
createClientPage
.fillClientData("test_client")
.selectClientType("OpenID Connect")
.continue()
.back()
.checkGeneralSettingsStepActive();
});
it("Should fail creating client", () => {
commonPage.tableToolbarUtils().createClient();
createClientPage.continue().checkClientIdRequiredMessage();
createClientPage
.fillClientData("")
.selectClientType("OpenID Connect")
.continue()
.checkClientIdRequiredMessage();
createClientPage.fillClientData("account").continue().continue().save();
// The error should inform about duplicated name/id
commonPage
.masthead()
.checkNotificationMessage(
"Could not create client: 'Client account already exists'",
);
});
it("Client CRUD test", () => {
itemId += "_" + crypto.randomUUID();
// Create
commonPage.tableUtils().checkRowItemExists(itemId, false);
commonPage.tableToolbarUtils().clickPrimaryButton();
createClientPage.cancel();
commonPage.tableUtils().checkRowItemExists(itemId, false);
commonPage.tableToolbarUtils().clickPrimaryButton();
createClientPage
.selectClientType("OpenID Connect")
.fillClientData(itemId)
.continue()
.switchClientAuthentication()
.clickDirectAccess()
.clickImplicitFlow()
.clickOAuthDeviceAuthorizationGrant()
.clickOidcCibaGrant()
.clickServiceAccountRoles()
.clickStandardFlow()
.continue()
.save();
commonPage
.masthead()
.checkNotificationMessage("Client created successfully");
commonPage.sidebar().goToClients();
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
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("Should fail to create imported client with empty ID", () => {
commonPage.sidebar().goToClients();
cy.findByTestId("importClient").click();
cy.findByTestId("clientId").click();
cy.findByText("Save").click();
cy.findByText("Required field");
});
const identicalClientId = "identical";
it("Should fail to create client with same ID", () => {
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().createClient();
createClientPage
.fillClientData(identicalClientId)
.continue()
.continue()
.save();
commonPage.masthead().closeAllAlertMessages();
commonPage.sidebar().goToClients();
cy.findByTestId("importClient").click();
cy.findByTestId("realm-file").selectFile(
"cypress/fixtures/partial-import-test-data/import-identical-client.json",
{
action: "drag-drop",
},
);
cy.wait(1000);
//cy.findByTestId("realm-file").contains('"clientId": "identical"')
cy.findByTestId("clientId").click();
cy.findByText("Save").click();
commonPage
.masthead()
.checkNotificationMessage(
"Could not import client: Client identical already exists",
true,
);
});
it("should delete 'identical' client id", () => {
commonPage.sidebar().goToClients();
cy.wrap(null).then(() =>
adminClient.inRealm(realmName, () =>
adminClient.deleteClient(identicalClientId),
),
);
});
});
describe("Service account tab test", () => {
const serviceAccountTab = new RoleMappingTab("user");
const serviceAccountName = `service-account-client${crypto.randomUUID()}`;
const createRealmRoleName = `create-realm-${crypto.randomUUID()}`;
const createRealmRoleType = `roles`;
before(async () => {
await adminClient.inRealm(realmName, () =>
adminClient.createClient({
protocol: "openid-connect",
clientId: serviceAccountName,
publicClient: false,
authorizationServicesEnabled: true,
serviceAccountsEnabled: true,
standardFlowEnabled: true,
}),
);
await adminClient.inRealm(realmName, () =>
adminClient.createRealmRole({
name: createRealmRoleName,
}),
);
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
});
after(async () => {
await adminClient.inRealm(realmName, () =>
adminClient.deleteClient(serviceAccountName),
);
await adminClient.inRealm(realmName, () =>
adminClient.deleteRealmRole(createRealmRoleName),
);
});
it("List", () => {
commonPage.tableToolbarUtils().searchItem(serviceAccountName);
commonPage.tableUtils().clickRowItemLink(serviceAccountName);
serviceAccountTab
.goToServiceAccountTab()
.checkRoles(["offline_access", "uma_authorization"], false)
.checkRoles([`default-roles-${realmName}`, "uma_protection"])
.unhideInheritedRoles();
commonPage.sidebar().waitForPageLoad();
serviceAccountTab
.checkRoles([
`default-roles-${realmName}`,
"offline_access",
"uma_authorization",
"uma_protection",
])
.hideInheritedRoles();
commonPage.sidebar().waitForPageLoad();
serviceAccountTab
.checkRoles(["offline_access", "uma_authorization"], false)
.checkRoles([`default-roles-${realmName}`, "uma_protection"]);
listingPage
.searchItem("testing", false)
.checkEmptyList()
.searchItem("", false);
serviceAccountTab
.checkRoles(["offline_access", "uma_authorization"], false)
.checkRoles([`default-roles-${realmName}`, "uma_protection"]);
});
it("Assign", () => {
commonPage.tableUtils().clickRowItemLink(serviceAccountName);
serviceAccountTab
.goToServiceAccountTab()
.assignRole(false)
.changeRoleTypeFilter(createRealmRoleType)
.selectRow(createRealmRoleName, true)
.assign();
commonPage.masthead().checkNotificationMessage("Role mapping updated");
serviceAccountTab.selectRow(createRealmRoleName).unAssign();
commonPage.sidebar().waitForPageLoad();
commonPage.modalUtils().checkModalTitle("Remove role?").confirmModal();
commonPage.masthead().checkNotificationMessage("Role mapping updated");
//cy.intercept(`/admin/realms/${realmName}/users`).as("assignRoles");
serviceAccountTab
.checkRoles([createRealmRoleName], false)
.assignRole(false);
//cy.wait("@assignRoles");
commonPage.sidebar().waitForPageLoad();
serviceAccountTab
.changeRoleTypeFilter("roles")
.selectRow("offline_access", true)
.selectRow(createRealmRoleName, true)
.assign();
commonPage.masthead().checkNotificationMessage("Role mapping updated");
commonPage.sidebar().waitForPageLoad();
serviceAccountTab.unhideInheritedRoles();
commonPage.sidebar().waitForPageLoad();
serviceAccountTab.hideInheritedRoles();
serviceAccountTab.selectRow("offline_access").unAssign();
commonPage.modalUtils().confirmModal();
serviceAccountTab
.checkRoles(["admin", "offline_access"], false)
.checkRoles([createRealmRoleName]);
listingPage.clickRowDetails(createRealmRoleName);
serviceAccountTab.unAssignFromDropdown();
commonPage.modalUtils().confirmModal();
commonPage.sidebar().waitForPageLoad();
serviceAccountTab.unhideInheritedRoles();
serviceAccountTab
.checkRoles([createRealmRoleName], false)
.checkRoles([
`default-roles-${realmName}`,
"offline_access",
"uma_authorization",
"uma_protection",
]);
});
});
describe("Mapping tab", () => {
const mappingClient = "mapping-client";
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().searchItem(mappingClient);
commonPage.tableUtils().clickRowItemLink(mappingClient);
});
before(() =>
adminClient.inRealm(realmName, () =>
adminClient.createClient({
protocol: "openid-connect",
clientId: mappingClient,
publicClient: false,
}),
),
);
after(() =>
adminClient.inRealm(realmName, () =>
adminClient.deleteClient(mappingClient),
),
);
it("Add mapping to openid client", () => {
clientDetailsPage
.goToClientScopesTab()
.clickDedicatedScope(mappingClient);
dedicatedScopesMappersTab.addPredefinedMapper();
clientDetailsPage.modalUtils().table().clickHeaderItem(1, "input");
clientDetailsPage.modalUtils().confirmModal();
clientDetailsPage
.masthead()
.checkNotificationMessage("Mapping successfully created");
});
});
describe("Keys tab test", () => {
const keysName = "keys-client";
before(
async () =>
await adminClient.inRealm(realmName, () =>
adminClient.createClient({
protocol: "openid-connect",
clientId: keysName,
publicClient: false,
}),
),
);
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().searchItem(keysName);
commonPage.tableUtils().clickRowItemLink(keysName);
});
after(() =>
adminClient.inRealm(realmName, () => adminClient.deleteClient(keysName)),
);
it("Generate new keys", () => {
const keysTab = clientDetailsPage.goToKeysTab();
keysTab.clickGenerate();
keysTab.fillGenerateModal("JKS", "keyname", "123", "1234").clickConfirm();
commonPage
.masthead()
.checkNotificationMessage(
"New key pair and certificate generated successfully",
);
});
});
describe("Realm client", () => {
const clientName = `${realmName}-realm`;
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
// Stay in master realm, do not switch to ${realmName} realm
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().searchItem(clientName);
commonPage.tableUtils().clickRowItemLink(clientName);
});
it("Displays the correct tabs", () => {
clientDetailsPage.goToSettingsTab();
clientDetailsPage
.tabUtils()
.checkTabExists(ClientsDetailsTab.Settings, true)
.checkTabExists(ClientsDetailsTab.Roles, true)
.checkTabExists(ClientsDetailsTab.Sessions, true)
.checkTabExists(ClientsDetailsTab.Permissions, true)
.checkTabExists(ClientsDetailsTab.Advanced, true)
.checkTabExists(ClientsDetailsTab.UserEvents, true)
.checkNumberOfTabsIsEqual(6);
});
it("Hides the delete action", () => {
commonPage
.actionToolbarUtils()
.clickActionToggleButton()
.checkActionItemExists("Delete", false);
});
});
describe("Bearer only", () => {
const clientId = "bearer-only";
before(
async () =>
await adminClient.inRealm(realmName, () =>
adminClient.createClient({
clientId,
protocol: "openid-connect",
publicClient: false,
bearerOnly: true,
}),
),
);
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
cy.intercept(`/admin/realms/${realmName}/clients/*`).as("fetchClient");
commonPage.tableToolbarUtils().searchItem(clientId);
commonPage.tableUtils().clickRowItemLink(clientId);
cy.wait("@fetchClient");
});
after(() =>
adminClient.inRealm(realmName, () => adminClient.deleteClient(clientId)),
);
it("Shows an explainer text for bearer only clients", () => {
commonPage
.actionToolbarUtils()
.bearerOnlyExplainerLabelElement.trigger("mouseenter");
commonPage
.actionToolbarUtils()
.bearerOnlyExplainerTooltipElement.should("exist");
});
it("Hides the capability config section", () => {
cy.findByTestId("capability-config-form").should("not.exist");
cy.findByTestId("jump-link-capability-config").should("not.exist");
});
});
describe("Generated home URLs for built-in clients", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
});
it("Check account-console Home URL", () => {
cy.findByTestId("client-home-url-account-console").contains("/account/");
});
it("Check security-admin-console Home URL", () => {
cy.findByTestId("client-home-url-security-admin-console").contains(
"/console/",
);
});
});
describe("Accessibility tests for clients", () => {
const clientId = "a11y-client";
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
commonPage.sidebar().goToRealm(realmName);
commonPage.sidebar().goToClients();
cy.injectAxe();
});
it("Check a11y violations on load/ clients list tab", () => {
cy.checkA11y();
});
it("Check a11y violations on create client page", () => {
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().createClient();
createClientPage.fillClientData(clientId);
cy.checkA11y();
createClientPage.continue();
cy.checkA11y();
createClientPage.continue();
cy.checkA11y();
});
it("Check a11y violations on client details page", () => {
const rolesTab = new ClientRolesTab();
commonPage.sidebar().goToClients();
commonPage.tableToolbarUtils().createClient();
createClientPage.fillClientData(clientId).continue().continue().save();
cy.checkA11y();
rolesTab.goToRolesTab();
cy.checkA11y();
clientDetailsPage.goToClientScopesTab();
cy.checkA11y();
clientDetailsPage.goToClientScopesEvaluateTab();
cy.checkA11y();
clientDetailsPage.goToClientScopesEvaluateEffectiveRoleScopeMappingsTab();
cy.checkA11y();
clientDetailsPage.goToClientScopesEvaluateGeneratedAccessTokenTab();
cy.checkA11y();
clientDetailsPage.goToClientScopesEvaluateGeneratedIdTokenTab();
cy.checkA11y();
clientDetailsPage.goToClientScopesEvaluateGeneratedUserInfoTab();
cy.checkA11y();
clientDetailsPage.goToAdvancedTab();
cy.checkA11y();
});
it("Check a11y violations in delete dialog", () => {
commonPage.tableToolbarUtils().searchItem(clientId, false);
commonPage.tableUtils().selectRowItemAction(clientId, "Delete");
cy.checkA11y();
cy.findAllByTestId("confirm").click();
});
it("Check a11y violations on client registration/ anonymous access policies tab", () => {
const clientRegistration = new ClientRegistrationPage();
clientRegistration.goToClientRegistrationTab();
cy.checkA11y();
});
it("Check a11y violations on client registration/ authenticated access policies tab", () => {
const clientRegistration = new ClientRegistrationPage();
clientRegistration.goToClientRegistrationTab();
cy.findByTestId("authenticated").click();
cy.checkA11y();
});
});
});

View File

@@ -1,502 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import UserEventsTab, {
UserEventSearchData,
} from "../support/pages/admin-ui/manage/events/tabs/UserEventsTab";
import AdminEventsTab from "../support/pages/admin-ui/manage/events/tabs/AdminEventsTab";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import EventsPage, {
EventsTab,
} from "../support/pages/admin-ui/manage/events/EventsPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import adminClient from "../support/util/AdminClient";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const userEventsTab = new UserEventsTab();
const eventsPage = new EventsPage();
const adminEventsTab = new AdminEventsTab();
const realmSettingsPage = new RealmSettingsPage();
const masthead = new Masthead();
const listingPage = new ListingPage();
const dateFrom = new Date();
dateFrom.setDate(dateFrom.getDate() - 100);
const dateFromFormatted = `${dateFrom.getFullYear()}-${dateFrom.getMonth()}-${dateFrom.getDay()}`;
const dateTo = new Date();
dateTo.setDate(dateTo.getDate() + 100);
const dateToFormatted = `${dateTo.getFullYear()}-${dateTo.getMonth()}-${dateTo.getDay()}`;
describe.skip("Events tests", () => {
const eventsTestUser = {
eventsTestUserId: "",
userRepresentation: {
username: "events-test" + crypto.randomUUID(),
enabled: true,
credentials: [{ value: "events-test" }],
},
};
const eventsTestUserClientId = "admin-cli";
before(async () => {
const result = await adminClient.createUser(
eventsTestUser.userRepresentation,
);
eventsTestUser.eventsTestUserId = result.id!;
});
after(() =>
adminClient.deleteUser(eventsTestUser.userRepresentation.username),
);
describe("User events list", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToEvents();
});
it("Show empty when no save events", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToEventsTab()
.goToUserEventsSettingsSubTab()
.enableSaveEventsSwitch()
.save()
.clearUserEvents();
cy.wait(5000);
sidebarPage.goToEvents();
eventsPage.goToUserEventsTab();
userEventsTab.assertNoSearchResultsExist(true);
});
it("Expand item to see more information", () => {
listingPage.expandRow(0).assertExpandedRowContainText(0, "code_id");
});
});
describe("Search user events list", () => {
const eventTypes = [
"LOGOUT",
"CODE_TO_TOKEN",
"CODE_TO_TOKEN_ERROR",
"LOGIN_ERROR",
"LOGIN",
];
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToEvents();
});
it("Check search dropdown display", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToEventsTab()
.goToUserEventsSettingsSubTab()
.disableSaveEventsSwitch()
.save();
cy.wait(5000);
masthead.signOut();
loginPage.logIn();
cy.visit("/");
sidebarPage.goToEvents();
eventsPage.tabUtils().checkIsCurrentTab(EventsTab.UserEvents);
userEventsTab.assertSearchUserEventDropdownMenuExist(true);
});
it("Check user events search form fields display", () => {
userEventsTab
.openSearchUserEventDropdownMenu()
.assertUserSearchDropdownMenuHasLabels();
});
it("Check event type dropdown options exist", () => {
userEventsTab
.openSearchUserEventDropdownMenu()
.openEventTypeSelectMenu()
.clickEventTypeSelectItem(eventTypes[0])
.clickEventTypeSelectItem(eventTypes[1])
.clickEventTypeSelectItem(eventTypes[2])
.clickEventTypeSelectItem(eventTypes[3])
.closeEventTypeSelectMenu();
});
it("Check `search events` button disabled by default", () => {
userEventsTab
.openSearchUserEventDropdownMenu()
.assertSearchEventBtnIsEnabled(false);
});
it("Check user events search and removal work", () => {
userEventsTab
.searchUserEventByEventType([eventTypes[0]])
.assertEventTypeChipGroupItemExist(eventTypes[0], true)
.assertEventTypeChipGroupItemExist(eventTypes[1], false)
.assertEventTypeChipGroupItemExist(eventTypes[2], false)
.assertEventTypeChipGroupItemExist(eventTypes[3], false)
.assertNoSearchResultsExist(true)
.removeEventTypeChipGroupItem(eventTypes[0])
.assertEventTypeChipGroupExist(false);
});
it("Check for no events logged", () => {
userEventsTab
.searchUserEventByUserId("test")
.assertNoSearchResultsExist(true);
});
it("Check `search events` button enabled", () => {
userEventsTab
.openSearchUserEventDropdownMenu()
.assertSearchEventBtnIsEnabled(false)
.typeUserId("11111")
.assertSearchEventBtnIsEnabled(true);
});
it("Search by user ID", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToEventsTab()
.goToUserEventsSettingsSubTab()
.enableSaveEventsSwitch()
.save();
sidebarPage.goToEvents();
cy.wrap(null).then(() =>
adminClient.loginUser(
eventsTestUser.userRepresentation.username,
eventsTestUser.userRepresentation.credentials[0].value,
eventsTestUserClientId,
),
);
userEventsTab
.searchUserEventByUserId(eventsTestUser.eventsTestUserId)
.assertUserIdChipGroupExist(true)
.assertEventTypeChipGroupExist(false)
.assertClientChipGroupExist(false)
.assertDateFromChipGroupExist(false)
.assertDateToChipGroupExist(false);
listingPage.itemsGreaterThan(0);
});
it("Search by event type", () => {
userEventsTab
.searchUserEventByEventType([eventTypes[4]])
.assertUserIdChipGroupExist(false)
.assertEventTypeChipGroupExist(true)
.assertClientChipGroupExist(false)
.assertDateFromChipGroupExist(false)
.assertDateToChipGroupExist(false);
listingPage.itemsGreaterThan(0);
});
it("Search by client", () => {
userEventsTab
.searchUserEventByClient(eventsTestUserClientId)
.assertUserIdChipGroupExist(false)
.assertEventTypeChipGroupExist(false)
.assertClientChipGroupExist(true)
.assertDateFromChipGroupExist(false)
.assertDateToChipGroupExist(false);
listingPage.itemsGreaterThan(0);
});
it("Search by date from", () => {
userEventsTab
.searchUserEventByDateFrom(dateFromFormatted)
.assertUserIdChipGroupExist(false)
.assertEventTypeChipGroupExist(false)
.assertClientChipGroupExist(false)
.assertDateFromChipGroupExist(true)
.assertDateToChipGroupExist(false);
listingPage.itemsGreaterThan(0);
});
it("Search by dato to", () => {
userEventsTab
.searchUserEventByDateTo(dateToFormatted)
.assertUserIdChipGroupExist(false)
.assertEventTypeChipGroupExist(false)
.assertClientChipGroupExist(false)
.assertDateFromChipGroupExist(false)
.assertDateToChipGroupExist(true);
listingPage.itemsGreaterThan(0);
});
it("Search by Ip Adress to", () => {
userEventsTab
.assertIpAddressChipGroupExist(true)
.assertUserIdChipGroupExist(false)
.assertEventTypeChipGroupExist(false)
.assertClientChipGroupExist(false)
.assertDateFromChipGroupExist(false)
.assertDateToChipGroupExist(false);
listingPage.itemsGreaterThan(0);
});
it("Search by all elements", () => {
const searchData = new UserEventSearchData();
searchData.client = eventsTestUserClientId;
searchData.userId = eventsTestUser.eventsTestUserId;
searchData.eventType = [eventTypes[4]];
searchData.dateFrom = dateFromFormatted;
searchData.dateTo = dateToFormatted;
userEventsTab
.searchUserEvent(searchData)
.assertUserIdChipGroupExist(true)
.assertEventTypeChipGroupExist(true)
.assertClientChipGroupExist(true)
.assertDateFromChipGroupExist(true)
.assertDateToChipGroupExist(true);
listingPage.itemsGreaterThan(0);
});
it("Check `search user events` button enabled", () => {
userEventsTab
.openSearchUserEventDropdownMenu()
.typeIpAddress("11111")
.assertSearchEventBtnIsEnabled(true);
});
});
describe("Admin events list", () => {
const realmName = crypto.randomUUID();
before(() => adminClient.createRealm(realmName));
after(() => adminClient.deleteRealm(realmName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
});
it("Show events", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToEventsTab()
.goToAdminEventsSettingsSubTab()
.enableSaveEvents()
.save();
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
listingPage.itemsGreaterThan(0);
});
it("Show empty when no save events", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToEventsTab()
.goToAdminEventsSettingsSubTab()
.disableSaveEvents()
.save({ waitForRealm: false, waitForConfig: true })
.clearAdminEvents();
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
adminEventsTab.assertNoSearchResultsExist(true);
});
});
describe("Search admin events list", () => {
const resourceTypes = ["REALM"];
const operationTypes = ["UPDATE"];
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
});
it("Search by resource types", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToEventsTab()
.goToAdminEventsSettingsSubTab()
.enableSaveEvents()
.save({ waitForRealm: false, waitForConfig: true });
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
adminEventsTab
.searchAdminEventByResourceTypes([resourceTypes[0]])
.assertResourceTypesChipGroupExist(true);
listingPage.itemsGreaterThan(0);
});
it("Search by operation types", () => {
adminEventsTab
.searchAdminEventByOperationTypes([operationTypes[0]])
.assertOperationTypesChipGroupExist(true);
listingPage.itemsGreaterThan(0);
});
it("Search by resource path", () => {
adminEventsTab
.searchAdminEventByResourcePath("test")
.assertResourcePathChipGroupExist(true);
});
it("Search by realm", () => {
adminEventsTab
.searchAdminEventByRealm("master")
.assertRealmChipGroupExist(true);
});
it("Search by client", () => {
adminEventsTab
.searchAdminEventByClient("admin-cli")
.assertClientChipGroupExist(true);
});
it("Search by user ID", () => {
adminEventsTab
.searchAdminEventByUser("test")
.assertUserChipGroupExist(true);
});
it("Search by IP address", () => {
adminEventsTab
.searchAdminEventByIpAddress("test")
.assertIpAddressChipGroupExist(true);
});
it("Search by date from", () => {
adminEventsTab
.searchAdminEventByDateTo(dateToFormatted)
.assertDateToChipGroupExist(true);
});
it("Search by date to", () => {
adminEventsTab
.searchAdminEventByDateFrom(dateFromFormatted)
.assertDateFromChipGroupExist(true);
});
});
describe("Search admin events", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
});
it("Check admin events search form fields display", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToEventsTab()
.goToAdminEventsSettingsSubTab()
.disableSaveEvents()
.save({ waitForRealm: false, waitForConfig: true });
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
adminEventsTab
.openSearchAdminEventDropdownMenu()
.assertAdminSearchDropdownMenuHasLabels();
});
it("Check `search admin events` button disabled by default", () => {
adminEventsTab
.openSearchAdminEventDropdownMenu()
.assertSearchAdminBtnEnabled(false);
});
it("Check admin events search and removal work", () => {
sidebarPage.goToEvents();
eventsPage
.goToAdminEventsTab()
.searchAdminEventByResourcePath("events/config")
.assertResourcePathChipGroupItemExist("events/config", true)
.removeResourcePathChipGroup();
listingPage.itemContainValue("UPDATE", 3, "UPDATE");
});
it("Check for no events logged", () => {
adminEventsTab
.searchAdminEventByResourcePath("events/test")
.assertNoSearchResultsExist(true);
});
it("Check `search admin events` button enabled", () => {
adminEventsTab
.openSearchAdminEventDropdownMenu()
.typeIpAddress("11111")
.assertSearchAdminBtnEnabled(true);
});
});
describe("Check more button opens auth and representation dialogs", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
});
it("Check auth dialog opens and is not empty", () => {
listingPage.clickRowDetails("UPDATE").clickDetailMenu("Auth");
adminEventsTab.assertAuthDialogIsNotEmpty();
});
it("Check representation dialog opens and is not empty", () => {
listingPage.clickRowDetails("UPDATE").clickDetailMenu("Representation");
adminEventsTab.assertRepresentationDialogIsNotEmpty();
});
});
describe("Accessibility tests for events", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToEvents();
cy.injectAxe();
});
it("Check a11y violations on load/ user events tab", () => {
cy.checkA11y();
});
it("Check a11y violations in user events search form", () => {
userEventsTab.openSearchUserEventDropdownMenu();
cy.checkA11y();
});
it("Check a11y violations on admin events tab", () => {
eventsPage.goToAdminEventsTab();
cy.checkA11y();
});
it("Check a11y violations in admin events search form", () => {
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
adminEventsTab.openSearchAdminEventDropdownMenu();
cy.checkA11y();
});
it("Check a11y violations in Auth dialog", () => {
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
listingPage.clickRowDetails("CREATE").clickDetailMenu("Auth");
cy.checkA11y();
});
it("Check a11y violations in Representation dialog", () => {
sidebarPage.goToEvents();
eventsPage.goToAdminEventsTab();
listingPage.clickRowDetails("CREATE").clickDetailMenu("Representation");
cy.checkA11y();
});
});
});

View File

@@ -1,539 +0,0 @@
import GroupModal from "../support/pages/admin-ui/manage/groups/GroupModal";
import GroupDetailPage from "../support/pages/admin-ui/manage/groups/group_details/GroupDetailPage";
import AttributesTab from "../support/pages/admin-ui/manage/AttributesTab";
import { SearchGroupPage } from "../support/pages/admin-ui/manage/groups/SearchGroupPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import GroupPage from "../support/pages/admin-ui/manage/groups/GroupPage";
import ChildGroupsTab from "../support/pages/admin-ui/manage/groups/group_details/tabs/ChildGroupsTab";
import MembersTab from "../support/pages/admin-ui/manage/groups/group_details/tabs/MembersTab";
import adminClient from "../support/util/AdminClient";
import { range } from "lodash-es";
import RoleMappingTab from "../support/pages/admin-ui/manage/RoleMappingTab";
import CommonPage from "../support/pages/CommonPage";
describe("Group test", () => {
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const groupModal = new GroupModal();
const searchGroupPage = new SearchGroupPage();
const attributesTab = new AttributesTab();
const groupPage = new GroupPage();
const groupDetailPage = new GroupDetailPage();
const childGroupsTab = new ChildGroupsTab();
const membersTab = new MembersTab();
const commonPage = new CommonPage();
const groupNamePrefix = "group_";
let groupName: string;
const groupNames: string[] = [];
const predefinedGroups = ["level", "level1", "level2", "level3"];
const emptyGroup = "empty-group";
let users: { id: string; username: string }[] = [];
const username = "test-user";
const duplicatedGroupErrorMessage = {
mainGroup: "Could not create group Top level group named '",
childGroup: "Could not create group Sibling group named '",
};
before(async () => {
users = await Promise.all(
range(5).map((index) => {
const user = adminClient
.createUser({
username: username + index,
enabled: true,
})
.then((user) => {
return { id: user.id!, username: username + index };
});
return user;
}),
);
});
after(
async () =>
await Promise.all([
adminClient.deleteGroups(),
...range(5).map((index) => adminClient.deleteUser(username + index)),
]),
);
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToGroups();
groupName = groupNamePrefix + crypto.randomUUID();
groupNames.push(groupName);
});
describe("List", () => {
it("Create group from empty option", () => {
groupPage
.assertNoGroupsInThisRealmEmptyStateMessageExist(true)
.createGroup(groupName, true)
.assertNotificationGroupCreated()
.searchGroup(groupName, true)
.assertGroupItemExist(groupName, true);
});
it("Create group from search bar", () => {
groupPage
.assertNoGroupsInThisRealmEmptyStateMessageExist(false)
.createGroup(groupName, false)
.assertNotificationGroupCreated()
.searchGroup(groupName, true)
.assertGroupItemExist(groupName, true);
});
it("Fail to create group with empty name", () => {
groupPage
.assertNoGroupsInThisRealmEmptyStateMessageExist(false)
.createGroup(" ", false)
.assertNotificationCouldNotCreateGroupWithEmptyName();
groupModal.closeModal();
});
it("Fail to create group with duplicated name", () => {
groupPage
.assertNoGroupsInThisRealmEmptyStateMessageExist(false)
.createGroup(groupName, false)
.createGroup(groupName, false)
.assertNotificationCouldNotCreateGroupWithDuplicatedName(
groupName,
duplicatedGroupErrorMessage.mainGroup,
);
groupModal.closeModal();
groupPage.searchGroup(groupName).assertGroupItemsEqual(1);
});
it("Empty search", () => {
groupPage.searchGroup(" ").assertNoSearchResultsMessageExist(true);
});
it("Search group that exists", () => {
groupPage
.searchGroup(groupNames[0])
.assertGroupItemExist(groupNames[0], true);
});
it("Search group that does not exists", () => {
groupPage
.searchGroup("not-existent-group")
.assertNoSearchResultsMessageExist(true);
});
it("Duplicate group from item bar", () => {
groupPage
.duplicateGroupItem(groupNames[0])
.assertNotificationGroupDuplicated();
});
it("Delete group from item bar", () => {
groupPage
.searchGroup(groupNames[0], true)
.deleteGroupItem(groupNames[0])
.assertNotificationGroupDeleted()
.searchGroup(groupNames[0], true)
.assertNoSearchResultsMessageExist(true);
});
it("Delete group from search bar", () => {
groupPage
.selectGroupItemCheckbox([groupNames[1]])
.deleteSelectedGroups()
.assertNotificationGroupDeleted()
.searchGroup(groupNames[1])
.assertNoSearchResultsMessageExist(true);
});
it("Delete groups from search bar", () => {
cy.wrap(null).then(() =>
adminClient.createGroup("group_multiple_deletion_test"),
);
cy.reload();
groupPage
.selectGroupItemCheckboxAllRows()
.deleteSelectedGroups()
.assertNotificationGroupsDeleted()
.assertNoGroupsInThisRealmEmptyStateMessageExist(true);
});
});
describe("Search group under current group", () => {
before(async () => {
const createdGroups = await adminClient.createSubGroups(predefinedGroups);
await Promise.all([
range(5).map((index) => {
adminClient.addUserToGroup(
users[index].id!,
createdGroups[index % 3].id,
);
}),
]);
});
it("Search child group in group", () => {
groupPage
.goToGroupChildGroupsTab(predefinedGroups[0])
.searchGroup(predefinedGroups[1])
.assertGroupItemExist(predefinedGroups[1], true);
});
it("Search non existing child group in group", () => {
groupPage
.goToGroupChildGroupsTab(predefinedGroups[0])
.searchGroup("non-existent-sub-group")
.assertNoSearchResultsMessageExist(true);
});
it("Empty search in group", () => {
groupPage
.goToGroupChildGroupsTab(predefinedGroups[0])
.searchGroup(" ")
.assertNoSearchResultsMessageExist(true);
});
});
describe("Group Actions", () => {
const groupNameDeleteHeaderAction = "group_test_delete_header_action";
before(async () => {
await adminClient.createGroup(groupNameDeleteHeaderAction);
});
after(async () => {
await adminClient.deleteGroups();
});
describe("Search globally", () => {
it("Navigate to parent group details", () => {
searchGroupPage
.searchGroup(predefinedGroups[0])
.goToGroupChildGroupsTab(predefinedGroups[0])
.assertGroupItemExist(predefinedGroups[1], true);
});
});
it("Rename group", () => {
groupPage.goToGroupChildGroupsTab(predefinedGroups[0]);
groupDetailPage
.renameGroup("new_group_name")
.assertNotificationGroupUpdated()
.assertHeaderGroupNameEqual("new_group_name")
.renameGroup(predefinedGroups[0])
.assertNotificationGroupUpdated()
.assertHeaderGroupNameEqual(predefinedGroups[0]);
});
it("Delete group from group details", () => {
groupPage.goToGroupChildGroupsTab(groupNameDeleteHeaderAction);
groupDetailPage
.headerActionDeleteGroup()
.assertNotificationGroupDeleted()
.assertGroupItemExist(groupNameDeleteHeaderAction, false);
});
});
describe("Child Groups", () => {
before(async () => {
await adminClient.createGroup(predefinedGroups[0]);
});
after(async () => {
await adminClient.deleteGroups();
});
beforeEach(() => {
groupPage.goToGroupChildGroupsTab(predefinedGroups[0]);
});
it("Check empty state", () => {
childGroupsTab.assertNoGroupsInThisSubGroupEmptyStateMessageExist(true);
});
it("Create group from empty state", () => {
childGroupsTab
.createGroup(predefinedGroups[1], true)
.assertNotificationGroupCreated();
});
it("Create group from search bar", () => {
childGroupsTab
.createGroup(predefinedGroups[2], false)
.assertNotificationGroupCreated();
});
it("Fail to create group with empty name", () => {
childGroupsTab
.createGroup(" ", false)
.assertNotificationCouldNotCreateGroupWithEmptyName();
});
// https://github.com/keycloak/keycloak-admin-ui/issues/2726
it("Fail to create group with duplicated name", () => {
childGroupsTab
.createGroup(predefinedGroups[2], false)
.assertNotificationCouldNotCreateGroupWithDuplicatedName(
predefinedGroups[2],
duplicatedGroupErrorMessage.childGroup,
);
});
it("Move group from item bar", () => {
childGroupsTab
.moveGroupItemAction(predefinedGroups[1], [
predefinedGroups[0],
predefinedGroups[2],
])
.goToGroupChildGroupsTab(predefinedGroups[2])
.assertGroupItemExist(predefinedGroups[1], true);
});
it("Search group", () => {
childGroupsTab
.searchGroup(predefinedGroups[2])
.assertGroupItemExist(predefinedGroups[2], true);
});
it("Show child group in groups", () => {
childGroupsTab
.goToGroupChildGroupsTab(predefinedGroups[2])
.goToGroupChildGroupsTab(predefinedGroups[1])
.assertNoGroupsInThisSubGroupEmptyStateMessageExist(true);
});
it("Delete group from search bar", () => {
childGroupsTab
.goToGroupChildGroupsTab(predefinedGroups[2])
.selectGroupItemCheckbox([predefinedGroups[1]])
.deleteSelectedGroups()
.assertNotificationGroupDeleted();
});
it("Delete group from item bar", () => {
childGroupsTab
.deleteGroupItem(predefinedGroups[2])
.assertNotificationGroupDeleted()
.assertNoGroupsInThisSubGroupEmptyStateMessageExist(true);
});
});
describe("Members", () => {
before(async () => {
const createdGroups = await adminClient.createSubGroups(predefinedGroups);
await Promise.all([
range(5).map((index) => {
adminClient.addUserToGroup(
users[index].id!,
createdGroups[index % 3].id,
);
}),
adminClient.createGroup(emptyGroup),
adminClient.createUser({ username: "new", enabled: true }),
]);
});
after(() => adminClient.deleteUser("new"));
beforeEach(() => {
groupPage.goToGroupChildGroupsTab(predefinedGroups[0]);
childGroupsTab.goToMembersTab();
});
it("Add member from search bar", () => {
membersTab
.addMember(["new"], false)
.assertNotificationUserAddedToTheGroup(1);
});
it("Show members with sub-group users", () => {
membersTab
.assertUserItemExist(users[0].username, true)
.assertUserItemExist("new", true)
.assertUserItemExist(users[3].username, true)
.clickCheckboxIncludeSubGroupUsers()
.assertUserItemExist("new", true)
.assertUserItemExist(users[0].username, true)
.assertUserItemExist(users[1].username, true)
.assertUserItemExist(users[2].username, true)
.assertUserItemExist(users[3].username, true)
.assertUserItemExist(users[4].username, true)
.goToChildGroupsTab()
.goToGroupChildGroupsTab(predefinedGroups[1])
.goToMembersTab()
.assertUserItemExist(users[1].username, true)
.assertUserItemExist(users[4].username, true)
.goToChildGroupsTab()
.goToGroupChildGroupsTab(predefinedGroups[2])
.goToMembersTab()
.assertUserItemExist(users[2].username, true);
});
it("Add member from empty state", () => {
sidebarPage.goToGroups();
groupPage.goToGroupChildGroupsTab(emptyGroup);
childGroupsTab.goToMembersTab();
membersTab
.addMember([users[0].username, users[1].username], true)
.assertNotificationUserAddedToTheGroup(2);
});
it("Leave group from search bar", () => {
sidebarPage.goToGroups();
groupPage.goToGroupChildGroupsTab(emptyGroup);
childGroupsTab.goToMembersTab();
membersTab
.selectUserItemCheckbox([users[0].username])
.leaveGroupSelectedUsers()
.assertNotificationUserLeftTheGroup(1)
.assertUserItemExist(users[0].username, false);
});
it("Leave group from item bar", () => {
sidebarPage.goToGroups();
groupPage.goToGroupChildGroupsTab(emptyGroup);
childGroupsTab.goToMembersTab();
membersTab
.leaveGroupUserItem(users[1].username)
.assertNotificationUserLeftTheGroup(1)
.assertNoUsersFoundEmptyStateMessageExist(true);
});
it("Show memberships from item bar", () => {
sidebarPage.goToGroups();
groupPage.goToGroupChildGroupsTab(predefinedGroups[0]);
childGroupsTab.goToMembersTab();
membersTab
.showGroupMembershipsItem(users[3].username)
.assertGroupItemExist(predefinedGroups[0], true)
.cancelShowGroupMembershipsModal();
});
});
describe("Breadcrumbs", () => {
it("Navigate to parent group", () => {
groupPage
.goToGroupChildGroupsTab(predefinedGroups[0])
.goToGroupChildGroupsTab(predefinedGroups[1])
.goToGroupChildGroupsTab(predefinedGroups[2])
.goToGroupChildGroupsTab(predefinedGroups[3]);
cy.reload();
groupPage.clickBreadcrumbItem(predefinedGroups[2]);
groupDetailPage.assertHeaderGroupNameEqual(predefinedGroups[2]);
groupPage.clickBreadcrumbItem(predefinedGroups[1]);
groupDetailPage.assertHeaderGroupNameEqual(predefinedGroups[1]);
groupPage.clickBreadcrumbItem(predefinedGroups[0]);
groupDetailPage.assertHeaderGroupNameEqual(predefinedGroups[0]);
groupPage
.clickBreadcrumbItem("Groups")
.assertGroupItemExist(predefinedGroups[0], true);
});
});
describe("Attributes", () => {
beforeEach(() => {
groupPage.goToGroupChildGroupsTab(predefinedGroups[0]);
groupDetailPage.goToAttributesTab();
});
it("Add attribute", () => {
attributesTab.addAttribute("key", "value").save();
groupPage.assertNotificationGroupUpdated();
});
it("Remove attribute", () => {
attributesTab.deleteAttribute(0);
attributesTab.assertEmpty();
groupPage.assertNotificationGroupUpdated();
});
it("Revert changes", () => {
attributesTab
.addAttribute("key", "value")
.addAnAttributeButton()
.revert()
.assertEmpty();
});
});
describe("'Move to' function", () => {
it("Move group to other group", () => {
groupPage
.moveGroupItemAction(predefinedGroups[0], [emptyGroup])
.goToGroupChildGroupsTab(emptyGroup)
.assertGroupItemExist(predefinedGroups[0], true);
});
it("Move group to root", () => {
groupPage
.goToGroupChildGroupsTab(emptyGroup)
.moveGroupItemAction(predefinedGroups[0], ["root"]);
sidebarPage.goToGroups();
groupPage.assertGroupItemExist(predefinedGroups[0], true);
});
});
describe("Role mappings", () => {
const roleMappingTab = new RoleMappingTab("group");
beforeEach(() => {
groupPage.goToGroupChildGroupsTab(predefinedGroups[0]);
groupDetailPage.goToRoleMappingTab();
});
it("Check empty state", () => {
commonPage.emptyState().checkIfExists(true);
});
it("Assign roles from empty state", () => {
roleMappingTab.assignRole();
roleMappingTab
.changeRoleTypeFilter("roles")
.selectRow("default-roles-")
.assign();
});
it("Show and search roles", () => {
groupDetailPage.checkDefaultRole();
});
it("Check hide inherited roles option", () => {
roleMappingTab.unhideInheritedRoles();
roleMappingTab.hideInheritedRoles();
});
it("Remove roles", () => {
roleMappingTab.selectRow("default-roles");
roleMappingTab.unAssign();
groupDetailPage.deleteRole();
});
});
describe("Permissions", () => {
beforeEach(() => {
groupPage.goToGroupChildGroupsTab(predefinedGroups[0]);
groupDetailPage.goToPermissionsTab();
});
it("enable/disable permissions", () => {
groupDetailPage.enablePermissionSwitch();
});
});
describe("Accessibility tests for groups", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToGroups();
cy.injectAxe();
});
it("Check a11y violations on load/ groups", () => {
cy.checkA11y();
});
});
});

View File

@@ -1,179 +0,0 @@
import RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import ProviderPage from "../support/pages/admin-ui/manage/providers/ProviderPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const providersPage = new ProviderPage();
const usernameI18nTest = "user_i18n_test";
let usernameI18nId: string;
let originalMasterRealm: RealmRepresentation;
describe("i18n tests", () => {
before(() => {
cy.wrap(null).then(async () => {
const realm = (await adminClient.getRealm("master"))!;
originalMasterRealm = realm;
realm.supportedLocales = ["en", "de", "de-CH", "fo"];
realm.internationalizationEnabled = true;
await adminClient.updateRealm("master", realm);
const { id: userId } = await adminClient.createUser({
username: usernameI18nTest,
enabled: true,
credentials: [
{ type: "password", temporary: false, value: usernameI18nTest },
],
});
usernameI18nId = userId!;
await adminClient.addRealmRoleToUser(usernameI18nId, "admin");
});
});
after(async () => {
await adminClient.deleteUser(usernameI18nTest);
if (originalMasterRealm) {
await adminClient.updateRealm("master", originalMasterRealm);
}
});
afterEach(async () => {
await adminClient.removeAllLocalizationTexts();
});
const realmLocalizationEn = "realmSettings en";
const themeLocalizationEn = "Realm settings";
const realmLocalizationDe = "realmSettings de";
const themeLocalizationDe = "Realm-Einstellungen";
const realmLocalizationDeCh = "realmSettings de-CH";
it("should use THEME localization for fallback (en) when language without theme localization is requested and no realm localization exists", () => {
updateUserLocale("fo");
goToUserFederationPage();
sidebarPage.checkRealmSettingsLinkContainsText(themeLocalizationEn);
});
it("should use THEME localization for language when language with theme localization is requested and no realm localization exists", () => {
updateUserLocale("de");
goToUserFederationPage();
sidebarPage.checkRealmSettingsLinkContainsText(themeLocalizationDe);
});
it("should use REALM localization for fallback (en) when language without theme localization is requested and realm localization exists for fallback (en)", () => {
addCommonRealmSettingsLocalizationText("en", realmLocalizationEn);
updateUserLocale("fo");
goToUserFederationPage();
sidebarPage.checkRealmSettingsLinkContainsText(realmLocalizationEn);
});
it("should use THEME localization for language when language with theme localization is requested and realm localization exists for fallback (en) only", () => {
addCommonRealmSettingsLocalizationText("en", realmLocalizationEn);
updateUserLocale("de");
goToUserFederationPage();
sidebarPage.checkRealmSettingsLinkContainsText(themeLocalizationDe);
});
it("should use REALM localization for language when language is requested and realm localization exists for language", () => {
addCommonRealmSettingsLocalizationText("de", realmLocalizationDe);
updateUserLocale("de");
goToUserFederationPage();
sidebarPage.checkRealmSettingsLinkContainsText(realmLocalizationDe);
});
// TODO: currently skipped due to https://github.com/keycloak/keycloak/issues/20412
it.skip("should use REALM localization for region when region is requested and realm localization exists for region", () => {
addCommonRealmSettingsLocalizationText("de-CH", realmLocalizationDeCh);
updateUserLocale("de-CH");
goToUserFederationPage();
sidebarPage.checkRealmSettingsLinkContainsText(realmLocalizationDeCh);
});
it("should use REALM localization for language when language is requested and realm localization exists for fallback (en), language, region", () => {
addCommonRealmSettingsLocalizationText("en", realmLocalizationEn);
addCommonRealmSettingsLocalizationText("de", realmLocalizationDe);
addCommonRealmSettingsLocalizationText("de-CH", realmLocalizationDeCh);
updateUserLocale("de");
goToUserFederationPage();
sidebarPage.checkRealmSettingsLinkContainsText(realmLocalizationDe);
});
it("should use REALM localization for language when region is requested and realm localization exists for fallback (en), language", () => {
addCommonRealmSettingsLocalizationText("en", realmLocalizationEn);
addCommonRealmSettingsLocalizationText("de", realmLocalizationDe);
updateUserLocale("de-CH");
goToUserFederationPage();
sidebarPage.checkRealmSettingsLinkContainsText(realmLocalizationDe);
});
it("should apply plurals and interpolation for THEME localization", () => {
updateUserLocale("en");
goToUserFederationPage();
providersPage.assertCardContainsText("ldap", "Add Ldap providers");
});
it("should apply plurals and interpolation for REALM localization", () => {
addLocalization(
"en",
"addProvider_other",
"addProvider_other en: {{provider}}",
);
updateUserLocale("en");
goToUserFederationPage();
providersPage.assertCardContainsText("ldap", "addProvider_other en: Ldap");
});
function goToUserFederationPage() {
loginPage.logIn(usernameI18nTest, usernameI18nTest);
keycloakBefore();
sidebarPage.goToUserFederation();
}
function updateUserLocale(locale: string) {
cy.wrap(null).then(() =>
adminClient.updateUser(usernameI18nId, {
attributes: { locale: locale },
}),
);
}
function addCommonRealmSettingsLocalizationText(
locale: string,
value: string,
) {
addLocalization(locale, "realmSettings", value);
}
function addLocalization(locale: string, key: string, value: string) {
cy.wrap(null).then(() =>
adminClient.addLocalizationText(locale, key, value),
);
}
});

View File

@@ -1,157 +0,0 @@
import { SERVER_URL } from "../support/constants";
import LoginPage from "../support/pages/LoginPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import AddMapperPage from "../support/pages/admin-ui/manage/identity_providers/AddMapperPage";
import CreateProviderPage from "../support/pages/admin-ui/manage/identity_providers/CreateProviderPage";
import ProviderBaseAdvancedSettingsPage, {
ClientAssertionSigningAlg,
ClientAuthentication,
PromptSelect,
} from "../support/pages/admin-ui/manage/identity_providers/ProviderBaseAdvancedSettingsPage";
import ProviderBaseGeneralSettingsPage from "../support/pages/admin-ui/manage/identity_providers/ProviderBaseGeneralSettingsPage";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
describe("OIDC identity provider test", () => {
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const masthead = new Masthead();
const listingPage = new ListingPage();
const createProviderPage = new CreateProviderPage();
const addMapperPage = new AddMapperPage();
const createSuccessMsg = "Identity provider successfully created";
const createMapperSuccessMsg = "Mapper created successfully.";
const deletePrompt = "Delete provider?";
const deleteSuccessMsg = "Provider successfully deleted.";
const discoveryUrl = `${SERVER_URL}/realms/master/.well-known/openid-configuration`;
const authorizationUrl = `${SERVER_URL}/realms/master/protocol/openid-connect/auth`;
describe("OIDC Identity provider creation", () => {
const oidcProviderName = "oidc";
const secret = "123";
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToIdentityProviders();
});
it("should create an OIDC provider using discovery url", () => {
createProviderPage
.checkVisible(oidcProviderName)
.clickCard(oidcProviderName);
// createProviderPage.checkAddButtonDisabled();
createProviderPage
.fillDiscoveryUrl(discoveryUrl)
.shouldBeSuccessful()
.fillDisplayName(oidcProviderName)
.fill(oidcProviderName, secret)
.clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
createProviderPage.shouldHaveAuthorizationUrl(authorizationUrl);
});
it("should test all settings", () => {
const providerBaseGeneralSettingsPage =
new ProviderBaseGeneralSettingsPage();
const providerBaseAdvancedSettingsPage =
new ProviderBaseAdvancedSettingsPage();
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(oidcProviderName);
//general settings
cy.findByTestId("displayName").click().type("OIDC");
cy.findByTestId("jump-link-general-settings").click();
providerBaseGeneralSettingsPage.typeDisplayOrder("1");
createProviderPage.clickSave();
masthead.checkNotificationMessage("Provider successfully updated", true);
//OIDC Settings and save/revert buttons
providerBaseAdvancedSettingsPage.assertOIDCUrl("authorization");
providerBaseAdvancedSettingsPage.assertOIDCUrl("token");
//OIDC Switches
providerBaseAdvancedSettingsPage.assertOIDCSignatureSwitch();
providerBaseAdvancedSettingsPage.assertOIDCPKCESwitch();
//Client Authentication
providerBaseAdvancedSettingsPage.assertOIDCClientAuthentication(
ClientAuthentication.basicAuth,
);
providerBaseAdvancedSettingsPage.assertOIDCClientAuthentication(
ClientAuthentication.post,
);
providerBaseAdvancedSettingsPage.assertOIDCClientAuthentication(
ClientAuthentication.jwt,
);
providerBaseAdvancedSettingsPage.assertOIDCClientAuthentication(
ClientAuthentication.jwtPrivKey,
);
//Client assertion signature algorithm
Object.entries(ClientAssertionSigningAlg).forEach(([, value]) => {
providerBaseAdvancedSettingsPage.assertOIDCClientAuthSignAlg(value);
});
//Client assertion audience
providerBaseAdvancedSettingsPage.typeClientAssertionAudience(
"http://localhost:8180",
);
providerBaseAdvancedSettingsPage.assertClientAssertionAudienceInputEqual(
"http://localhost:8180",
);
//JWT X509 Headers
providerBaseAdvancedSettingsPage.assertOIDCJWTX509HeadersSwitch();
//OIDC Advanced Settings
providerBaseAdvancedSettingsPage.assertOIDCSettingsAdvancedSwitches();
providerBaseAdvancedSettingsPage.selectPromptOption(PromptSelect.none);
providerBaseAdvancedSettingsPage.selectPromptOption(PromptSelect.consent);
providerBaseAdvancedSettingsPage.selectPromptOption(PromptSelect.login);
providerBaseAdvancedSettingsPage.selectPromptOption(PromptSelect.select);
providerBaseAdvancedSettingsPage.selectPromptOption(
PromptSelect.unspecified,
);
//Advanced Settings
providerBaseAdvancedSettingsPage.assertAdvancedSettings();
});
it("should add OIDC mapper of type Attribute Importer", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(oidcProviderName);
addMapperPage.goToMappersTab();
addMapperPage.emptyStateAddMapper();
addMapperPage.addOIDCAttrImporterMapper("OIDC Attribute Importer");
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should add OIDC mapper of type Claim To Role", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(oidcProviderName);
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addOIDCClaimToRoleMapper("OIDC Claim to Role");
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should cancel the addition of the OIDC mapper", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(oidcProviderName);
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.cancelNewMapper();
addMapperPage.shouldGoToMappersTab();
});
it("clean up providers", () => {
const modalUtils = new ModalUtils();
sidebarPage.goToIdentityProviders();
listingPage.itemExist(oidcProviderName).deleteItem(oidcProviderName);
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
});
});
});

View File

@@ -1,189 +0,0 @@
import { SERVER_URL } from "../support/constants";
import LoginPage from "../support/pages/LoginPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import AddMapperPage from "../support/pages/admin-ui/manage/identity_providers/AddMapperPage";
import CreateProviderPage from "../support/pages/admin-ui/manage/identity_providers/CreateProviderPage";
import ProviderSAMLSettings from "../support/pages/admin-ui/manage/identity_providers/social/ProviderSAMLSettings";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
describe("SAML identity provider test", () => {
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const masthead = new Masthead();
const listingPage = new ListingPage();
const createProviderPage = new CreateProviderPage();
const addMapperPage = new AddMapperPage();
const createSuccessMsg = "Identity provider successfully created";
const saveSuccessMsg = "Provider successfully updated";
const createMapperSuccessMsg = "Mapper created successfully.";
const saveMapperSuccessMsg = "Mapper saved successfully.";
const deletePrompt = "Delete provider?";
const deleteSuccessMsg = "Provider successfully deleted.";
const classRefName = "acClassRef-1";
const declRefName = "acDeclRef-1";
const samlDiscoveryUrl = `${SERVER_URL}/realms/master/protocol/saml/descriptor`;
const samlDisplayName = "saml";
describe("SAML identity provider creation", () => {
const samlProviderName = "saml";
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToIdentityProviders();
});
it("should create a SAML provider using entity descriptor", () => {
createProviderPage
.checkVisible(samlProviderName)
.clickCard(samlProviderName);
// createProviderPage.checkAddButtonDisabled();
createProviderPage
.fillDisplayName(samlDisplayName)
.fillDiscoveryUrl(samlDiscoveryUrl)
.shouldBeSuccessful()
.clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
});
it("should add auth constraints to existing SAML provider", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
createProviderPage
.fillAuthnContextClassRefs(classRefName)
.clickClassRefsAdd()
.fillAuthnContextDeclRefs(declRefName)
.clickDeclRefsAdd()
.clickSave();
masthead.checkNotificationMessage(saveSuccessMsg, true);
});
it("should add SAML mapper of type Advanced Attribute to Role", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
addMapperPage.emptyStateAddMapper();
addMapperPage.addAdvancedAttrToRoleMapper("SAML mapper");
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should add SAML mapper of type Username Template Importer", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addUsernameTemplateImporterMapper(
"SAML Username Template Importer Mapper",
);
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should add SAML mapper of type Hardcoded User Session Attribute", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addHardcodedUserSessionAttrMapper(
"Hardcoded User Session Attribute",
);
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should add SAML mapper of type Attribute Importer", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addSAMLAttrImporterMapper("Attribute Importer");
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should add SAML mapper of type Hardcoded Role", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addHardcodedRoleMapper("Hardcoded Role");
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should add SAML mapper of type Hardcoded Attribute", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addHardcodedAttrMapper("Hardcoded Attribute");
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should add SAML mapper of type SAML Attribute To Role", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addSAMLAttributeToRoleMapper("SAML Attribute To Role");
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should edit Username Template Importer mapper", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
listingPage.goToItemDetails("SAML Username Template Importer Mapper");
addMapperPage.editUsernameTemplateImporterMapper();
masthead.checkNotificationMessage(saveMapperSuccessMsg, true);
});
it("should edit SAML mapper", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
addMapperPage.goToMappersTab();
listingPage.goToItemDetails("SAML mapper");
addMapperPage.editSAMLorOIDCMapper();
masthead.checkNotificationMessage(saveMapperSuccessMsg, true);
});
it("should edit SAML settings", () => {
const providerSAMLSettings = new ProviderSAMLSettings();
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
providerSAMLSettings.disableProviderSwitch();
sidebarPage.goToIdentityProviders();
cy.findByText("Disabled");
listingPage.goToItemDetails(samlProviderName);
providerSAMLSettings.enableProviderSwitch();
cy.get(".pf-v5-c-jump-links__list").contains("SAML settings").click();
providerSAMLSettings.assertIdAndURLFields();
providerSAMLSettings.assertNameIdPolicyFormat();
providerSAMLSettings.assertPrincipalType();
providerSAMLSettings.assertSAMLSwitches();
providerSAMLSettings.assertSignatureAlgorithm();
providerSAMLSettings.assertValidateSignatures();
providerSAMLSettings.assertTextFields();
cy.get(".pf-v5-c-jump-links__list")
.contains("Requested AuthnContext Constraints")
.click();
providerSAMLSettings.assertAuthnContext();
});
it("clean up providers", () => {
const modalUtils = new ModalUtils();
sidebarPage.goToIdentityProviders();
listingPage.itemExist(samlProviderName).deleteItem(samlProviderName);
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
});
});
});

View File

@@ -1,408 +0,0 @@
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import CreateProviderPage from "../support/pages/admin-ui/manage/identity_providers/CreateProviderPage";
import ModalUtils from "../support/util/ModalUtils";
import OrderDialog from "../support/pages/admin-ui/manage/identity_providers/OrderDialog";
import AddMapperPage from "../support/pages/admin-ui/manage/identity_providers/AddMapperPage";
import ProviderFacebookGeneralSettings from "../support/pages/admin-ui/manage/identity_providers/social/ProviderFacebookGeneralSettings";
import ProviderBaseGeneralSettingsPage from "../support/pages/admin-ui/manage/identity_providers/ProviderBaseGeneralSettingsPage";
import ProviderBaseAdvancedSettingsPage from "../support/pages/admin-ui/manage/identity_providers/ProviderBaseAdvancedSettingsPage";
import ProviderGithubGeneralSettings from "../support/pages/admin-ui/manage/identity_providers/social/ProviderGithubGeneralSettings";
import ProviderGoogleGeneralSettings from "../support/pages/admin-ui/manage/identity_providers/social/ProviderGoogleGeneralSettings";
import ProviderMicrosoftGeneralSettings from "../support/pages/admin-ui/manage/identity_providers/social/ProviderMicrosoftGeneralSettings";
import ProviderOpenshiftGeneralSettings from "../support/pages/admin-ui/manage/identity_providers/social/ProviderOpenshiftGeneralSettings";
import ProviderPaypalGeneralSettings from "../support/pages/admin-ui/manage/identity_providers/social/ProviderPaypalGeneralSettings";
import ProviderStackoverflowGeneralSettings from "../support/pages/admin-ui/manage/identity_providers/social/ProviderStackoverflowGeneralSettings";
import adminClient from "../support/util/AdminClient";
import GroupPage from "../support/pages/admin-ui/manage/groups/GroupPage";
import CommonPage from "../support/pages/CommonPage";
describe("Identity provider test", () => {
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const masthead = new Masthead();
const listingPage = new ListingPage();
const createProviderPage = new CreateProviderPage();
const addMapperPage = new AddMapperPage();
const groupPage = new GroupPage();
const commonPage = new CommonPage();
const createSuccessMsg = "Identity provider successfully created";
const createFailMsg =
"Could not create the identity provider: Identity Provider github already exists";
const createMapperSuccessMsg = "Mapper created successfully.";
const changeSuccessMsg =
"Successfully changed display order of identity providers";
const deletePrompt = "Delete provider?";
const deleteSuccessMsg = "Provider successfully deleted.";
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToIdentityProviders();
});
const socialLoginIdentityProvidersWithCustomFiels = {
Facebook: new ProviderFacebookGeneralSettings(),
Github: new ProviderGithubGeneralSettings(),
Google: new ProviderGoogleGeneralSettings(),
Microsoft: new ProviderMicrosoftGeneralSettings(),
"Openshift-v3": new ProviderOpenshiftGeneralSettings(),
"Openshift-v4": new ProviderOpenshiftGeneralSettings(),
Paypal: new ProviderPaypalGeneralSettings(),
Stackoverflow: new ProviderStackoverflowGeneralSettings(),
};
function getSocialIdpClassInstance(idpTestName: string) {
let instance = new ProviderBaseGeneralSettingsPage();
Object.entries(socialLoginIdentityProvidersWithCustomFiels).find(
([key, value]) => {
if (key === idpTestName) {
instance = value;
return true;
}
return false;
},
);
return instance;
}
describe("Identity provider creation", () => {
const identityProviderName = "github";
describe("Custom fields tests", () => {
const socialLoginIdentityProviders = [
{ testName: "Bitbucket", displayName: "BitBucket", alias: "bitbucket" },
{ testName: "Facebook", displayName: "Facebook", alias: "facebook" },
{ testName: "Github", displayName: "GitHub", alias: "github" },
{ testName: "Gitlab", displayName: "Gitlab", alias: "gitlab" },
{ testName: "Google", displayName: "Google", alias: "google" },
{ testName: "Instagram", displayName: "Instagram", alias: "instagram" },
{
testName: "LinkedIn",
displayName: "LinkedIn",
alias: "linkedin-openid-connect",
},
{ testName: "Microsoft", displayName: "Microsoft", alias: "microsoft" },
{
testName: "Openshift-v4",
displayName: "Openshift v4",
alias: "openshift-v4",
},
{ testName: "Paypal", displayName: "PayPal", alias: "paypal" },
{
testName: "Stackoverflow",
displayName: "StackOverflow",
alias: "stackoverflow",
},
{ testName: "Twitter", displayName: "Twitter", alias: "twitter" },
];
after(async () => {
await Promise.all(
socialLoginIdentityProviders.map((idp) =>
adminClient.deleteIdentityProvider(idp.alias),
),
);
});
socialLoginIdentityProviders.forEach(($idp, linkedIdpsCount) => {
it(`should create social login provider ${$idp.testName} with custom fields`, () => {
if (linkedIdpsCount == 0) {
createProviderPage.clickCard($idp.alias);
} else {
createProviderPage.clickCreateDropdown().clickItem($idp.alias);
}
const instance = getSocialIdpClassInstance($idp.testName);
instance
.typeClientId("1")
.typeClientId("")
.typeClientSecret("1")
.typeClientSecret("")
.assertRequiredFieldsErrorsExist()
.fillData($idp.testName)
.clickAdd()
.assertNotificationIdpCreated()
.assertFilledDataEqual($idp.testName);
});
});
});
it("should create github provider", () => {
createProviderPage.checkGitHubCardVisible().clickGitHubCard();
createProviderPage.checkAddButtonDisabled();
createProviderPage.fill(identityProviderName).checkAddButtonDisabled();
createProviderPage.fill(identityProviderName, "123").clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
sidebarPage.goToIdentityProviders();
listingPage.itemExist(identityProviderName);
});
it("fail to make duplicate github provider", () => {
createProviderPage
.clickCreateDropdown()
.clickItem("github")
.fill("github2", "123")
.clickAdd();
masthead.checkNotificationMessage(createFailMsg, true);
});
it("should create facebook provider", () => {
createProviderPage
.clickCreateDropdown()
.clickItem("facebook")
.fill("facebook", "123")
.clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
});
it("search for existing provider by name", () => {
sidebarPage.goToIdentityProviders();
listingPage.searchItem(identityProviderName, false);
listingPage.itemExist(identityProviderName, true);
});
it("search for non-existing provider by name", () => {
sidebarPage.goToIdentityProviders();
listingPage.searchItem("not-existing-provider", false);
groupPage.assertNoSearchResultsMessageExist(true);
});
it("create and delete provider by item details", () => {
createProviderPage
.clickCreateDropdown()
.clickItem("linkedin-openid-connect")
.fill("linkedin-openid-connect", "123")
.clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
commonPage
.actionToolbarUtils()
.clickActionToggleButton()
.clickDropdownItem("Delete");
const modalUtils = new ModalUtils();
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
});
it.skip("should change order of providers", () => {
const orderDialog = new OrderDialog();
const providers = [identityProviderName, "facebook", "bitbucket"];
sidebarPage.goToIdentityProviders();
listingPage.itemExist("facebook");
sidebarPage.goToIdentityProviders();
listingPage.itemExist(identityProviderName);
createProviderPage
.clickCreateDropdown()
.clickItem("bitbucket")
.fill("bitbucket", "123")
.clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
cy.wait(2000);
sidebarPage.goToIdentityProviders();
listingPage.itemExist(identityProviderName);
orderDialog.openDialog().checkOrder(providers);
orderDialog.moveRowTo("facebook", identityProviderName);
orderDialog.checkOrder(["bitbucket", identityProviderName, "facebook"]);
orderDialog.clickSave();
masthead.checkNotificationMessage(changeSuccessMsg);
});
it("should delete provider", () => {
const modalUtils = new ModalUtils();
listingPage.deleteItem(identityProviderName);
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
});
it("should add facebook social mapper", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("facebook");
addMapperPage.goToMappersTab();
addMapperPage.emptyStateAddMapper();
addMapperPage.fillSocialMapper("facebook mapper");
// addMapperPage.saveNewMapper();
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should add Social mapper of type Attribute Importer", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("facebook");
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.fillSocialMapper("facebook attribute importer");
masthead.checkNotificationMessage(createMapperSuccessMsg, true);
});
it("should edit facebook mapper", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("facebook");
addMapperPage.goToMappersTab();
listingPage.goToItemDetails("facebook attribute importer");
addMapperPage.editSocialMapper();
});
it("should delete facebook mapper", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("facebook");
addMapperPage.goToMappersTab();
listingPage.deleteItem("facebook attribute importer");
cy.findByTestId("confirm").click();
});
it("clean up providers", () => {
const modalUtils = new ModalUtils();
// TODO: Re-enable this code when the 'should change order of providers' is no longer skipped.
// sidebarPage.goToIdentityProviders();
// listingPage.itemExist("bitbucket").deleteItem("bitbucket");
// modalUtils.checkModalTitle(deletePrompt).confirmModal();
// masthead.checkNotificationMessage(deleteSuccessMsg, true);
sidebarPage.goToIdentityProviders();
listingPage.itemExist("facebook").deleteItem("facebook");
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
});
});
describe("should check provider details", () => {
const identityProviderName = "github";
const githubSettings = new ProviderGithubGeneralSettings();
const advancedSettings = new ProviderBaseAdvancedSettingsPage();
it("creating github provider", () => {
createProviderPage.checkGitHubCardVisible().clickGitHubCard();
createProviderPage.checkAddButtonDisabled();
createProviderPage
.fill(identityProviderName)
.fill(identityProviderName, "123")
.clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
sidebarPage.goToIdentityProviders();
listingPage.itemExist(identityProviderName);
});
it("should check general settings", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("github");
githubSettings.fillData("github");
cy.findByTestId("idp-details-save").click();
});
it("should check input switches and inputs", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("github");
advancedSettings.typeScopesInput("openid");
advancedSettings.assertScopesInputEqual("openid");
advancedSettings.assertStoreTokensSwitchTurnedOn(false);
advancedSettings.assertAcceptsPromptNoneForwardFromClientSwitchTurnedOn(
false,
);
advancedSettings.assertDisableUserInfoSwitchTurnedOn(false);
advancedSettings.assertTrustEmailSwitchTurnedOn(false);
advancedSettings.assertAccountLinkingOnlySwitchTurnedOn(false);
advancedSettings.assertHideOnLoginPageSwitchTurnedOn(false);
advancedSettings.clickStoreTokensSwitch();
advancedSettings.clickAcceptsPromptNoneForwardFromClientSwitch();
advancedSettings.clickDisableUserInfoSwitch();
advancedSettings.clickTrustEmailSwitch();
advancedSettings.clickAccountLinkingOnlySwitch();
advancedSettings.clickHideOnLoginPageSwitch();
advancedSettings.assertDoNotImportUsersSwitchTurnedOn(false);
advancedSettings.assertSyncModeShown(true);
advancedSettings.clickdoNotStoreUsersSwitch();
advancedSettings.assertDoNotImportUsersSwitchTurnedOn(true);
advancedSettings.assertSyncModeShown(false);
advancedSettings.clickdoNotStoreUsersSwitch();
advancedSettings.assertDoNotImportUsersSwitchTurnedOn(false);
advancedSettings.assertSyncModeShown(true);
advancedSettings.clickEssentialClaimSwitch();
advancedSettings.typeClaimNameInput("claim-name");
advancedSettings.typeClaimValueInput("claim-value");
advancedSettings.ensureAdvancedSettingsAreVisible();
advancedSettings.assertStoreTokensSwitchTurnedOn(true);
advancedSettings.assertAcceptsPromptNoneForwardFromClientSwitchTurnedOn(
true,
);
advancedSettings.assertDisableUserInfoSwitchTurnedOn(true);
advancedSettings.assertTrustEmailSwitchTurnedOn(true);
advancedSettings.assertAccountLinkingOnlySwitchTurnedOn(true);
advancedSettings.assertHideOnLoginPageSwitchTurnedOn(true);
advancedSettings.assertEssentialClaimSwitchTurnedOn(true);
advancedSettings.assertClaimInputEqual("claim-name");
advancedSettings.assertClaimValueInputEqual("claim-value");
cy.findByTestId("idp-details-save").click();
masthead.checkNotificationMessage("Provider successfully updated");
});
it("should revert and save options", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("github");
cy.findByTestId("jump-link-advanced-settings").click();
advancedSettings.assertStoreTokensSwitchTurnedOn(true);
advancedSettings.assertAcceptsPromptNoneForwardFromClientSwitchTurnedOn(
true,
);
advancedSettings.clickStoreTokensSwitch();
advancedSettings.clickAcceptsPromptNoneForwardFromClientSwitch();
advancedSettings.ensureAdvancedSettingsAreVisible();
advancedSettings.assertStoreTokensSwitchTurnedOn(false);
advancedSettings.assertAcceptsPromptNoneForwardFromClientSwitchTurnedOn(
false,
);
cy.findByTestId("idp-details-revert").click();
advancedSettings.assertStoreTokensSwitchTurnedOn(true);
advancedSettings.assertAcceptsPromptNoneForwardFromClientSwitchTurnedOn(
true,
);
});
it("should delete providers", () => {
const modalUtils = new ModalUtils();
sidebarPage.goToIdentityProviders();
listingPage.itemExist("github").deleteItem("github");
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
});
});
describe("Accessibility tests for identity providers", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToIdentityProviders();
cy.injectAxe();
});
it("Check a11y violations on load/ identity providers", () => {
cy.checkA11y();
});
});
});

View File

@@ -1,139 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import adminClient from "../support/util/AdminClient";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const helpLabel = ".pf-v5-c-form__group-label-help";
describe("Masthead tests", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
});
describe("Desktop view", () => {
it("Go to account console and back to admin console", () => {
sidebarPage.waitForPageLoad();
masthead.accountManagement();
cy.url().should("contain", "/realms/master/account");
});
it("Sign out reachs to log in screen", () => {
sidebarPage.waitForPageLoad();
masthead.signOut();
sidebarPage.waitForPageLoad();
loginPage.isLogInPage();
});
it("Go to realm info", () => {
sidebarPage.goToClients();
masthead.toggleUsernameDropdown().clickRealmInfo();
cy.get(".pf-v5-l-grid").should("contain.text", "Welcome");
});
it("Should go to documentation page", () => {
masthead.clickGlobalHelp();
masthead
.getDocumentationLink()
.invoke("attr", "href")
.then((href) => {
if (!href) return;
masthead.clickDocumentationLink();
cy.origin(href, () => {
cy.get("#header").should(
"contain.text",
"Server Administration Guide",
);
});
});
});
it("Enable/disable help mode in desktop mode", () => {
masthead.assertIsDesktopView();
cy.findByTestId("infoTab").click();
cy.get(helpLabel).should("exist");
masthead.toggleGlobalHelp();
masthead.clickGlobalHelp();
cy.get(helpLabel).should("not.exist");
masthead.toggleGlobalHelp();
cy.get(helpLabel).should("exist");
});
});
describe("Login works for unprivileged users", () => {
const realmName = `test-realm-${crypto.randomUUID()}`;
const username = `test-user-${crypto.randomUUID()}`;
before(async () => {
await adminClient.createRealm(realmName, { enabled: true });
await adminClient.inRealm(realmName, () =>
adminClient.createUser({
username,
enabled: true,
emailVerified: true,
credentials: [{ type: "password", value: "test" }],
firstName: "Test",
lastName: "User",
email: "test@keycloak.org",
}),
);
});
after(() => adminClient.deleteRealm(realmName));
it("Login without privileges to see admin console", () => {
sidebarPage.waitForPageLoad();
masthead.signOut();
cy.visit(`/admin/${realmName}/console`);
cy.get('[role="progressbar"]').should("not.exist");
cy.get("#username").type(username);
cy.get("#password").type("test");
cy.get("#kc-login").click();
sidebarPage.waitForPageLoad();
masthead.signOut();
sidebarPage.waitForPageLoad();
loginPage.isLogInPage();
});
});
describe("Mobile view", () => {
it("Mobile menu is shown when in mobile view", () => {
cy.viewport("samsung-s10");
masthead.assertIsMobileView();
});
it("Enable/disable help mode in mobile view", () => {
cy.viewport("samsung-s10");
masthead
.assertIsMobileView()
.toggleUsernameDropdown()
.toggleMobileViewHelp();
masthead.toggleMobileViewHelp();
cy.findByTestId("helpIcon").should("exist");
});
});
describe("Accessibility tests for masthead", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.waitForPageLoad();
masthead.accountManagement();
cy.injectAxe();
});
it("Check a11y violations on load/ masthead", () => {
cy.checkA11y();
});
});
});

View File

@@ -1,148 +0,0 @@
import Form from "../support/forms/Form";
import LoginPage from "../support/pages/LoginPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import IdentityProviderTab from "../support/pages/admin-ui/manage/organization/IdentityProviderTab";
import MembersTab from "../support/pages/admin-ui/manage/organization/MemberTab";
import OrganizationPage from "../support/pages/admin-ui/manage/organization/OrganizationPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
const loginPage = new LoginPage();
const listingPage = new ListingPage();
const page = new OrganizationPage();
const realmSettingsPage = new RealmSettingsPage();
const sidebarPage = new SidebarPage();
describe.skip("Organization CRUD", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealmSettings();
realmSettingsPage.setSwitch("organizationsEnabled", true);
realmSettingsPage.saveGeneral();
});
it("should create new organization", () => {
page.goToTab();
page.goToCreate();
Form.assertSaveButtonDisabled();
page.fillCreatePage({ name: "orgName" });
Form.assertSaveButtonEnabled();
page.fillCreatePage({
name: "orgName",
domain: ["ame.org", "test.nl"],
description: "some description",
});
Form.clickSaveButton();
page.assertSaveSuccess();
});
it("should modify existing organization", () => {
cy.wrap(null).then(() =>
adminClient.createOrganization({
name: "editName",
domains: [{ name: "go.org", verified: false }],
}),
);
page.goToTab();
listingPage.goToItemDetails("editName");
const newValue = "newName";
page.fillNameField(newValue).should("have.value", newValue);
Form.clickSaveButton();
page.assertSaveSuccess();
page.goToTab();
listingPage.itemExist(newValue);
});
it("should delete from list", () => {
page.goToTab();
listingPage.deleteItem("orgName");
page.modalUtils().confirmModal();
page.assertDeleteSuccess();
});
it.skip("should delete from details page", () => {
page.goToTab();
listingPage.goToItemDetails("newName");
page
.actionToolbarUtils()
.clickActionToggleButton()
.clickDropdownItem("Delete");
page.modalUtils().confirmModal();
page.assertDeleteSuccess();
});
});
describe.skip("Members", () => {
const membersTab = new MembersTab();
before(() => {
adminClient.createOrganization({
name: "member",
domains: [{ name: "o.com", verified: false }],
});
adminClient.createUser({ username: "realm-user", enabled: true });
});
after(() => {
adminClient.deleteOrganization("member");
adminClient.deleteUser("realm-user");
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
page.goToTab();
});
it("should add member", () => {
listingPage.goToItemDetails("member");
membersTab.goToTab();
membersTab.clickAddRealmUser();
membersTab.modalUtils().assertModalVisible(true);
membersTab.modalUtils().table().selectRowItemCheckbox("realm-user");
membersTab.modalUtils().add();
membersTab.assertMemberAddedSuccess();
membersTab.tableUtils().checkRowItemExists("realm-user");
});
});
describe.skip("Identity providers", () => {
const idpTab = new IdentityProviderTab();
before(() => {
adminClient.createOrganization({
name: "idp",
domains: [{ name: "o.com", verified: false }],
});
adminClient.createIdentityProvider("BitBucket", "bitbucket");
});
after(() => {
adminClient.deleteOrganization("idp");
adminClient.deleteIdentityProvider("bitbucket");
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
page.goToTab();
});
it("should add idp", () => {
listingPage.goToItemDetails("idp");
idpTab.goToTab();
idpTab.emptyState().checkIfExists(true);
idpTab.emptyState().clickPrimaryBtn();
idpTab.fillForm({ name: "bitbucket", domain: "o.com", public: true });
idpTab.modalUtils().confirmModal();
idpTab.assertAddedSuccess();
idpTab.tableUtils().checkRowItemExists("bitbucket");
});
});

View File

@@ -1,59 +0,0 @@
import PartialExportModal from "../support/pages/admin-ui/configure/realm_settings/PartialExportModal";
import RealmSettings from "../support/pages/admin-ui/configure/realm_settings/RealmSettings";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
describe("Partial realm export", () => {
const REALM_NAME = "Partial-export-test-realm";
before(() => adminClient.createRealm(REALM_NAME));
after(() => adminClient.deleteRealm(REALM_NAME));
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const modal = new PartialExportModal();
const realmSettings = new RealmSettings();
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(REALM_NAME).goToRealmSettings();
realmSettings.clickActionMenu();
modal.open();
});
it("Closes the dialog", () => {
modal.cancelButton().click();
modal.exportButton().should("not.exist");
});
it("Shows a warning message", () => {
modal.warningMessage().should("not.exist");
modal.includeGroupsAndRolesSwitch().click({ force: true });
modal.warningMessage().should("exist");
modal.includeGroupsAndRolesSwitch().click({ force: true });
modal.warningMessage().should("not.exist");
modal.includeClientsSwitch().click({ force: true });
modal.warningMessage().should("exist");
modal.includeClientsSwitch().click({ force: true });
modal.warningMessage().should("not.exist");
});
it("Exports the realm", () => {
modal.includeGroupsAndRolesSwitch().click({ force: true });
modal.includeClientsSwitch().click({ force: true });
cy.intercept("POST", `/admin/realms/${REALM_NAME}/partial-export*`).as(
"export",
);
modal.exportButton().click();
cy.wait("@export");
cy.readFile(Cypress.config("downloadsFolder") + "/realm-export.json");
modal.exportButton().should("not.exist");
});
});

View File

@@ -1,130 +0,0 @@
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import PartialImportModal from "../support/pages/admin-ui/configure/realm_settings/PartialImportModal";
import RealmSettings from "../support/pages/admin-ui/configure/realm_settings/RealmSettings";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import adminClient from "../support/util/AdminClient";
describe("Partial import test", () => {
const TEST_REALM = "Partial-import-test-realm";
const TEST_REALM_2 = "Partial-import-test-realm-2";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const modal = new PartialImportModal();
const realmSettings = new RealmSettings();
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(TEST_REALM);
sidebarPage.goToRealmSettings();
realmSettings.clickActionMenu();
});
before(() =>
Promise.all([
adminClient.createRealm(TEST_REALM),
adminClient.createRealm(TEST_REALM_2),
]),
);
after(async () => {
await Promise.all([
adminClient.deleteRealm(TEST_REALM),
adminClient.deleteRealm(TEST_REALM_2),
]);
});
it("Opens and closes partial import dialog", () => {
modal.open();
modal.importButton().should("be.disabled");
modal.cancelButton().click();
modal.importButton().should("not.exist");
});
it("Import button only enabled if JSON has something to import", () => {
modal.open();
modal.textArea().type("{}", { force: true });
modal.importButton().should("be.disabled");
modal.cancelButton().click();
});
it("Displays user options after multi-realm import", () => {
modal.open();
modal.typeResourceFile("multi-realm.json");
// Import button should be disabled if no checkboxes selected
modal.importButton().should("be.disabled");
modal.usersCheckbox().click();
modal.importButton().should("be.enabled");
modal.groupsCheckbox().click();
modal.importButton().should("be.enabled");
modal.groupsCheckbox().click();
modal.usersCheckbox().click();
modal.importButton().should("be.disabled");
// verify resource counts
modal.userCount().contains("1 Users");
modal.groupCount().contains("1 Groups");
modal.clientCount().contains("1 Clients");
modal.idpCount().contains("1 Identity providers");
modal.realmRolesCount().contains("2 Realm roles");
modal.clientRolesCount().contains("1 Client roles");
// import button should disable when switching realms
modal.usersCheckbox().click();
modal.importButton().should("be.enabled");
modal.selectRealm("realm2");
modal.importButton().should("be.disabled");
modal.clientCount().contains("2 Clients");
modal.clientsCheckbox().click();
modal.importButton().click();
cy.contains("2 records added");
cy.contains("customer-portal");
cy.contains("customer-portal2");
modal.closeButton().click();
});
it("Displays user options after realmless import and does the import", () => {
sidebarPage.goToRealm(TEST_REALM_2);
sidebarPage.goToRealmSettings();
realmSettings.clickActionMenu();
modal.open();
modal.typeResourceFile("client-only.json");
modal.realmSelector().should("not.exist");
modal.clientCount().contains("1 Clients");
modal.usersCheckbox().should("not.exist");
modal.groupsCheckbox().should("not.exist");
modal.idpCheckbox().should("not.exist");
modal.realmRolesCheckbox().should("not.exist");
modal.clientRolesCheckbox().should("not.exist");
modal.clientsCheckbox().click();
modal.importButton().click();
cy.contains("One record added");
cy.contains("customer-portal3");
modal.closeButton().click();
});
it("Should clear the input with the button", () => {
modal.open();
//clear button should be disabled if there is nothing in the dialog
modal.clearButton().should("be.disabled");
modal.textArea().should("have.text", "");
modal.textArea().type("{}", { force: true });
modal.textArea().should("have.text", "{}");
modal.clearButton().should("not.be.disabled");
modal.clearButton().click();
modal.clickClearConfirmButton();
modal.textArea().should("have.text", "");
});
});

View File

@@ -1,332 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ModalUtils from "../support/util/ModalUtils";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import createRealmRolePage from "../support/pages/admin-ui/manage/realm_roles/CreateRealmRolePage";
import AssociatedRolesPage from "../support/pages/admin-ui/manage/realm_roles/AssociatedRolesPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import adminClient from "../support/util/AdminClient";
import ClientRolesTab from "../support/pages/admin-ui/manage/clients/ClientRolesTab";
import KeyValueInput from "../support/pages/admin-ui/manage/KeyValueInput";
let itemId = "realm_role_crud";
const loginPage = new LoginPage();
const masthead = new Masthead();
const modalUtils = new ModalUtils();
const sidebarPage = new SidebarPage();
const listingPage = new ListingPage();
const associatedRolesPage = new AssociatedRolesPage();
const rolesTab = new ClientRolesTab();
describe("Realm roles test", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealmRoles();
});
it("should fail creating realm role", () => {
listingPage.goToCreateItem();
createRealmRolePage.save().checkRealmRoleNameRequiredMessage();
createRealmRolePage.fillRealmRoleData("admin").save();
// The error should inform about duplicated name/id (THIS MESSAGE DOES NOT HAVE QUOTES AS THE OTHERS)
masthead.checkNotificationMessage(
"Could not create role: Role with name admin already exists",
true,
);
});
it("shouldn't create a realm role based with only whitespace name", () => {
listingPage.goToCreateItem();
createRealmRolePage
.fillRealmRoleData(" ")
.checkRealmRoleNameRequiredMessage();
});
it("Realm role CRUD test", () => {
itemId += "_" + crypto.randomUUID();
// Create
listingPage.itemExist(itemId, false).goToCreateItem();
createRealmRolePage.fillRealmRoleData(itemId).save();
masthead.checkNotificationMessage("Role created", true);
sidebarPage.goToRealmRoles();
const fetchUrl = "/admin/realms/master/roles?first=0&max=11";
cy.intercept(fetchUrl).as("fetch");
listingPage.deleteItem(itemId);
cy.wait(["@fetch"]);
modalUtils.checkModalTitle("Delete role?").confirmModal();
masthead.checkNotificationMessage("The role has been deleted", true);
listingPage.itemExist(itemId, false);
itemId = "realm_role_crud";
});
it("should delete role from details action", () => {
itemId += "_" + crypto.randomUUID();
listingPage.goToCreateItem();
createRealmRolePage.fillRealmRoleData(itemId).save();
masthead.checkNotificationMessage("Role created", true);
createRealmRolePage.clickActionMenu("Delete this role");
modalUtils.confirmModal();
masthead.checkNotificationMessage("The role has been deleted", true);
itemId = "realm_role_crud";
});
it("should not be able to delete default role", () => {
const defaultRole = "default-roles-master";
listingPage.itemExist(defaultRole).deleteItem(defaultRole);
masthead.checkNotificationMessage(
"You cannot delete a default role.",
true,
);
});
it("Add associated roles test", () => {
itemId += "_" + crypto.randomUUID();
// Create
listingPage.itemExist(itemId, false).goToCreateItem();
createRealmRolePage.fillRealmRoleData(itemId).save();
masthead.checkNotificationMessage("Role created", true);
// Add associated realm role from action dropdown
associatedRolesPage.addAssociatedRealmRole("create-realm");
masthead.checkNotificationMessage("Associated roles have been added", true);
// Add associated realm role from search bar
associatedRolesPage.addAssociatedRoleFromSearchBar("offline_access");
masthead.checkNotificationMessage("Associated roles have been added", true);
rolesTab.goToAssociatedRolesTab();
// Add associated client role from search bar
associatedRolesPage.addAssociatedRoleFromSearchBar("manage-account", true);
masthead.checkNotificationMessage("Associated roles have been added", true);
rolesTab.goToAssociatedRolesTab();
// Add associated client role
associatedRolesPage.addAssociatedRoleFromSearchBar("manage-consent", true);
masthead.checkNotificationMessage("Associated roles have been added", true);
rolesTab.goToAssociatedRolesTab();
// Add associated client role
associatedRolesPage.addAssociatedRoleFromSearchBar(
"manage-account-links",
true,
);
masthead.checkNotificationMessage("Associated roles have been added", true);
});
it("should search existing associated role by name and go to it", () => {
listingPage
.searchItem("create-realm", false)
.itemExist("create-realm")
.goToItemDetails("create-realm");
cy.findByTestId("view-header").should("contain.text", "create-realm");
cy.findByTestId("cancel").click();
});
it("should go to default-roles-master link role name and check assign roles table is not empty", () => {
listingPage.goToItemDetails("default-roles-master");
rolesTab.goToDefaultGroupsTab();
cy.findByTestId("assigned-roles").find("tr").should("have.length.gt", 0);
cy.findByTestId("empty-state").contains("No default groups");
rolesTab.goToDefaultRolesTab();
cy.findByTestId("assigned-roles").find("tr").should("have.length.gt", 0);
});
it("Should search non-existent associated role by name", () => {
const itemName = "non-existent-associated-role";
listingPage.searchItem(itemName, false);
listingPage.assertNoResults();
});
it("Should hide inherited roles test", () => {
listingPage.searchItem(itemId, false).goToItemDetails(itemId);
rolesTab.goToAssociatedRolesTab();
rolesTab.hideInheritedRoles();
});
it("Should fail to remove role when all unchecked from search bar", () => {
listingPage.searchItem(itemId, false).goToItemDetails(itemId);
rolesTab.goToAssociatedRolesTab();
associatedRolesPage.isRemoveAssociatedRolesBtnDisabled();
});
it("Should delete single non-inherited role item", () => {
listingPage.searchItem(itemId, false).goToItemDetails(itemId);
rolesTab.goToAssociatedRolesTab();
listingPage.removeItem("create-realm");
sidebarPage.waitForPageLoad();
modalUtils.checkModalTitle("Remove role?").confirmModal();
sidebarPage.waitForPageLoad();
masthead.checkNotificationMessage("Role mapping updated", true);
});
it("Should delete all roles from search bar", () => {
listingPage.searchItem(itemId, false).goToItemDetails(itemId);
sidebarPage.waitForPageLoad();
rolesTab.goToAssociatedRolesTab();
cy.get('input[name="check-all"]').check();
associatedRolesPage.removeAssociatedRoles();
sidebarPage.waitForPageLoad();
modalUtils.checkModalTitle("Remove role?").confirmModal();
sidebarPage.waitForPageLoad();
masthead.checkNotificationMessage("Role mapping updated", true);
});
it("Should delete associated roles from list test", () => {
itemId = "realm_role_crud";
itemId += "_" + crypto.randomUUID();
// Create
listingPage.itemExist(itemId, false).goToCreateItem();
createRealmRolePage.fillRealmRoleData(itemId).save();
masthead.checkNotificationMessage("Role created", true);
// Add associated realm role from action dropdown
associatedRolesPage.addAssociatedRealmRole("create-realm");
masthead.checkNotificationMessage("Associated roles have been added", true);
// Add associated realm role from search bar
associatedRolesPage.addAssociatedRoleFromSearchBar("offline_access");
masthead.checkNotificationMessage("Associated roles have been added", true);
rolesTab.goToAssociatedRolesTab();
// delete associated roles from list
listingPage.removeItem("create-realm");
sidebarPage.waitForPageLoad();
modalUtils.checkModalTitle("Remove role?").confirmModal();
sidebarPage.waitForPageLoad();
masthead.checkNotificationMessage("Role mapping updated", true);
listingPage.removeItem("offline_access");
sidebarPage.waitForPageLoad();
modalUtils.checkModalTitle("Remove role?").confirmModal();
sidebarPage.waitForPageLoad();
masthead.checkNotificationMessage("Role mapping updated", true);
});
describe("edit role details", () => {
const editRoleName = "going to edit";
const description = "some description";
const updateDescription = "updated description";
before(() =>
adminClient.createRealmRole({
name: editRoleName,
description,
}),
);
after(() => adminClient.deleteRealmRole(editRoleName));
it("should edit realm role details", () => {
listingPage.itemExist(editRoleName).goToItemDetails(editRoleName);
createRealmRolePage.checkNameDisabled().checkDescription(description);
createRealmRolePage.updateDescription(updateDescription).save();
masthead.checkNotificationMessage("The role has been saved", true);
createRealmRolePage.checkDescription(updateDescription);
});
const keyValue = new KeyValueInput("attributes");
it("should add attribute", () => {
listingPage.itemExist(editRoleName).goToItemDetails(editRoleName);
createRealmRolePage.goToAttributesTab();
keyValue.fillKeyValue({ key: "one", value: "1" }).validateRows(1);
keyValue.save();
masthead.checkNotificationMessage("The role has been saved", true);
keyValue.validateRows(1);
});
it("should add attribute multiple", () => {
listingPage.itemExist(editRoleName).goToItemDetails(editRoleName);
createRealmRolePage.goToAttributesTab();
keyValue
.fillKeyValue({ key: "two", value: "2" })
.fillKeyValue({ key: "three", value: "3" })
.save()
.validateRows(3);
});
it("should delete attribute", () => {
listingPage.itemExist(editRoleName).goToItemDetails(editRoleName);
createRealmRolePage.goToAttributesTab();
keyValue.deleteRow(1).save().validateRows(2);
});
});
describe("Accessibility tests for realm roles", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealmRoles();
cy.injectAxe();
});
const role = "a11y-role" + crypto.randomUUID();
const defaultRolesMaster = "default-roles-master";
it("Check a11y violations on load/ realm roles", () => {
cy.checkA11y();
});
it("Check a11y violations on default-roles-master default tab and default roles tabs", () => {
listingPage.goToItemDetails(defaultRolesMaster);
cy.checkA11y();
rolesTab.goToDefaultGroupsTab();
cy.checkA11y();
});
it("Check a11y violations on empty create role form", () => {
rolesTab.goToCreateRoleFromToolbar();
cy.checkA11y();
});
it("Check a11y violations on role details", () => {
const permissionSwitch = "permissionSwitch";
rolesTab.goToCreateRoleFromToolbar();
createRealmRolePage.fillRealmRoleData(role).save();
cy.checkA11y();
rolesTab.goToAttributesTab();
cy.checkA11y();
rolesTab.goToUsersInRoleTab();
cy.checkA11y();
rolesTab.goToPermissionsTab();
cy.findByTestId(permissionSwitch).parent().click();
cy.checkA11y();
sidebarPage.goToRealmRoles();
listingPage.deleteItem(role);
cy.checkA11y();
cy.findByTestId("confirm").click();
});
});
});

View File

@@ -1,186 +0,0 @@
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import adminClient from "../support/util/AdminClient";
import ModalUtils from "../support/util/ModalUtils";
import Masthead from "../support/pages/admin-ui/Masthead";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const modalUtils = new ModalUtils();
const masthead = new Masthead();
describe("Realm settings client policies tab tests", () => {
const realmName = "Realm_" + crypto.randomUUID();
const realmSettingsPage = new RealmSettingsPage(realmName);
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage
.waitForPageLoad()
.goToRealm(realmName)
.goToRealmSettings()
.waitForPageLoad();
realmSettingsPage.goToClientPoliciesTab().goToClientPoliciesList();
});
before(() => adminClient.createRealm(realmName));
after(() => {
adminClient.deleteRealm(realmName);
});
it("Complete new client form and cancel", () => {
realmSettingsPage
.checkDisplayPoliciesTab()
.createNewClientPolicyFromEmptyState("Test", "Test Description", true)
.checkNewClientPolicyForm()
.cancelNewClientPolicyCreation()
.checkEmptyPolicyList();
});
it("Complete new client form and submit", () => {
const url = `/admin/realms/${realmName}/client-policies/policies`;
cy.intercept("PUT", url).as("save");
realmSettingsPage.createNewClientPolicyFromEmptyState(
"Test",
"Test Description",
);
masthead.checkNotificationMessage("New policy created");
cy.wait("@save");
});
it("Should perform client profile search by profile name", () => {
realmSettingsPage.searchClientPolicy("Test");
});
it("Should not have conditions configured by default", () => {
realmSettingsPage.shouldNotHaveConditionsConfigured();
});
it("Should cancel adding a new condition to a client profile", () => {
realmSettingsPage.shouldCancelAddingCondition();
});
it("Should add a new client-roles condition to a client profile", () => {
realmSettingsPage.shouldAddClientRolesCondition();
});
it("Should add a new client-scopes condition to a client profile", () => {
realmSettingsPage.shouldAddClientScopesCondition();
});
it("Should edit the client-roles condition of a client profile", () => {
realmSettingsPage.shouldEditClientRolesCondition();
});
it("Should edit the client-scopes condition of a client profile", () => {
realmSettingsPage.shouldEditClientScopesCondition();
});
it("Should cancel deleting condition from a client profile", () => {
realmSettingsPage.deleteClientRolesCondition();
sidebarPage.waitForPageLoad();
modalUtils
.checkModalTitle("Delete condition?")
.checkModalMessage(
"This action will permanently delete client-roles. This cannot be undone.",
)
.checkConfirmButtonText("Delete")
.cancelButtonContains("Cancel")
.cancelModal();
realmSettingsPage.checkConditionsListContains("client-roles");
});
it("Should delete client-roles condition from a client profile", () => {
realmSettingsPage.deleteClientRolesCondition();
sidebarPage.waitForPageLoad();
modalUtils.confirmModal();
realmSettingsPage.checkConditionsListContains("client-scopes");
});
it("Should delete client-scopes condition from a client profile", () => {
realmSettingsPage.shouldDeleteClientScopesCondition();
});
it("Check cancelling the client policy deletion", () => {
realmSettingsPage.deleteClientPolicyItemFromTable("Test");
modalUtils
.checkModalMessage(
"This action will permanently delete the policy Test. This cannot be undone.",
)
.cancelModal();
realmSettingsPage.checkElementInList("Test");
});
it("Check deleting the client policy", () => {
realmSettingsPage.deleteClientPolicyItemFromTable("Test");
modalUtils.confirmModal();
masthead.checkNotificationMessage("Client policy deleted");
realmSettingsPage.checkEmptyPolicyList();
});
it("Check navigating between Form View and JSON editor", () => {
realmSettingsPage.shouldNavigateBetweenFormAndJSONViewPolicies();
});
it("Should not create duplicate client profile", () => {
const url = `admin/realms/${realmName}/client-policies/policies`;
cy.intercept("PUT", url).as("save");
realmSettingsPage.createNewClientPolicyFromEmptyState(
"Test",
"Test Description",
);
masthead.checkNotificationMessage("New policy created");
cy.wait("@save");
sidebarPage.goToRealmSettings();
realmSettingsPage.goToClientPoliciesTab().goToClientPoliciesList();
realmSettingsPage.createNewClientPolicyFromList(
"Test",
"Test Again Description",
true,
);
realmSettingsPage.shouldShowErrorWhenDuplicate();
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToClientPoliciesTab()
.goToClientPoliciesList()
.deleteClientPolicyItemFromTable("Test");
modalUtils.confirmModal();
cy.wait("@save");
masthead.checkNotificationMessage("Client policy deleted");
realmSettingsPage.checkEmptyPolicyList();
});
it("Check deleting newly created client policy from create view via dropdown", () => {
const url = `admin/realms/${realmName}/client-policies/policies`;
cy.intercept("PUT", url).as("save");
realmSettingsPage.createNewClientPolicyFromEmptyState(
"Test again",
"Test Again Description",
);
masthead.checkNotificationMessage("New policy created");
sidebarPage.waitForPageLoad();
cy.wait("@save");
realmSettingsPage.deleteClientPolicyFromDetails();
modalUtils.confirmModal();
masthead.checkNotificationMessage("Client policy deleted");
sidebarPage.waitForPageLoad();
realmSettingsPage.checkEmptyPolicyList();
});
it("Check reloading JSON policies", () => {
realmSettingsPage.shouldReloadJSONPolicies();
});
});

View File

@@ -1,184 +0,0 @@
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import adminClient from "../support/util/AdminClient";
import ModalUtils from "../support/util/ModalUtils";
import Masthead from "../support/pages/admin-ui/Masthead";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const modalUtils = new ModalUtils();
const masthead = new Masthead();
describe("Realm settings client profiles tab tests", () => {
const profileName = "Test";
const editedProfileName = "Edit";
const realmName = "Realm_" + crypto.randomUUID();
const realmSettingsPage = new RealmSettingsPage(realmName);
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.waitForPageLoad().goToRealm(realmName).goToRealmSettings();
realmSettingsPage.goToClientPoliciesTab().goToClientProfilesList();
});
before(() => adminClient.createRealm(realmName));
after(() => adminClient.deleteRealm(realmName));
it("Go to client policies profiles tab", () => {
realmSettingsPage.shouldDisplayProfilesTab();
});
it("Check new client form is displaying", () => {
realmSettingsPage.shouldDisplayNewClientProfileForm();
});
it("Complete new client form and cancel", () => {
realmSettingsPage
.createClientProfile(profileName, "Test Description")
.cancelClientProfileCreation()
.checkElementNotInList(profileName);
});
it("Complete new client form and submit", () => {
const url = `admin/realms/${realmName}/client-policies/profiles`;
cy.intercept("PUT", url).as("save");
realmSettingsPage
.createClientProfile(profileName, "Test Description")
.saveClientProfileCreation();
cy.wait("@save");
masthead.checkNotificationMessage("New client profile created");
});
it("Should perform client profile search by profile name", () => {
realmSettingsPage.searchClientProfile(profileName);
});
it("Should search non-existent client profile", () => {
realmSettingsPage.searchNonExistingClientProfile("nonExistentProfile");
cy.findByTestId("empty-state").should("be.visible");
});
it("Should navigate to client profile", () => {
realmSettingsPage.searchClientProfile(profileName);
realmSettingsPage.goToClientProfileByNameLink(profileName);
cy.findByTestId("view-header").should("have.text", profileName);
});
it("Check navigating between Form View and JSON editor", () => {
realmSettingsPage.shouldNavigateBetweenFormAndJSONView();
});
it("Check saving changed JSON profiles", () => {
realmSettingsPage.shouldSaveChangedJSONProfiles();
realmSettingsPage.deleteClientPolicyItemFromTable(profileName);
modalUtils.confirmModal();
masthead.checkNotificationMessage("Client profile deleted");
realmSettingsPage.checkElementNotInList(profileName);
});
it("Should not create duplicate client profile", () => {
const url = `admin/realms/${realmName}/client-policies/profiles`;
cy.intercept("PUT", url).as("save");
realmSettingsPage
.createClientProfile(profileName, "Test Description")
.saveClientProfileCreation();
cy.wait("@save");
sidebarPage.goToRealmSettings();
realmSettingsPage.goToClientPoliciesTab().goToClientProfilesList();
sidebarPage.waitForPageLoad();
realmSettingsPage
.createClientProfile(profileName, "Test Description")
.saveClientProfileCreation();
cy.wait("@save");
masthead.checkNotificationMessage(
"Could not create client profile: 'proposed client profile name duplicated.'",
);
});
it("Should edit client profile", () => {
realmSettingsPage.shouldEditClientProfile();
});
it("Should check that edited client profile is now listed", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage
.goToClientPoliciesTab()
.goToClientProfilesList()
.shouldCheckEditedClientProfileListed();
});
it("Should show error when client profile left blank", () => {
realmSettingsPage.shouldShowErrorWhenNameBlank();
});
it("Should revert back to the previous profile name", () => {
realmSettingsPage.shouldReloadClientProfileEdits();
});
it("Should not have executors configured by default", () => {
realmSettingsPage.shouldNotHaveExecutorsConfigured();
});
it("Should cancel adding a new executor to a client profile", () => {
realmSettingsPage.shouldCancelAddingExecutor();
});
it("Should add a new executor to a client profile", () => {
realmSettingsPage.shouldAddExecutor();
});
it("Should cancel deleting executor from a client profile", () => {
realmSettingsPage.shouldCancelDeletingExecutor();
});
it("Should cancel editing executor", () => {
realmSettingsPage.openProfileDetails(editedProfileName).editExecutor(4000);
sidebarPage.waitForPageLoad();
realmSettingsPage
.cancelEditingExecutor()
.checkExecutorNotInList()
.editExecutor()
.checkAvailablePeriodExecutor(3600);
});
it("Should edit executor", () => {
realmSettingsPage
.openProfileDetails(editedProfileName)
.editExecutor(4000)
.saveExecutor();
masthead.checkNotificationMessage("Executor updated successfully");
realmSettingsPage.editExecutor();
// TODO: UNCOMMENT LINE WHEN ISSUE 2037 IS FIXED
//.checkAvailablePeriodExecutor(4000);
});
it("Should delete executor from a client profile", () => {
realmSettingsPage.shouldDeleteExecutor();
});
it("Check cancelling the client profile deletion", () => {
realmSettingsPage.deleteClientPolicyItemFromTable(editedProfileName);
modalUtils
.checkModalMessage(
"This action will permanently delete the profile " +
editedProfileName +
". This cannot be undone.",
)
.cancelModal();
realmSettingsPage.checkElementInList(editedProfileName);
});
it("Check deleting the client profile", () => {
realmSettingsPage.deleteClientPolicyItemFromTable(editedProfileName);
modalUtils.confirmModal();
masthead.checkNotificationMessage("Client profile deleted");
sidebarPage.waitForPageLoad();
realmSettingsPage.checkElementNotInList(editedProfileName);
});
});

View File

@@ -1,418 +0,0 @@
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import adminClient from "../support/util/AdminClient";
import KeysTab from "../support/pages/admin-ui/manage/realm_settings/KeysTab";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const masthead = new Masthead();
const modalUtils = new ModalUtils();
const realmSettingsPage = new RealmSettingsPage();
const keysTab = new KeysTab();
describe("Realm settings events tab tests", () => {
const realmName = "Realm_" + crypto.randomUUID();
const listingPage = new ListingPage();
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
});
before(async () => {
await adminClient.createRealm(realmName);
});
after(async () => {
await adminClient.deleteRealm(realmName);
});
const goToDetails = () => {
const keysUrl = `/admin/realms/${realmName}/keys`;
cy.intercept(keysUrl).as("keysFetch");
keysTab.goToKeysTab();
cy.findByTestId("rs-providers-tab").click();
cy.findAllByTestId("provider-name-link")
.contains("test_aes-generated")
.click();
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
cy.findByTestId("rs-providers-tab").click();
cy.findAllByTestId("provider-name-link")
.contains("test_hmac-generated")
.click();
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
cy.findByTestId("rs-providers-tab").click();
cy.findAllByTestId("provider-name-link").contains("test_rsa").click();
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
cy.findByTestId("rs-providers-tab").click();
cy.findAllByTestId("provider-name-link")
.contains("test_rsa-generated")
.click();
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
cy.findByTestId("rs-providers-tab").click();
cy.findAllByTestId("provider-name-link")
.contains("test_rsa-enc-generated")
.click();
cy.wait(["@keysFetch"]);
return this;
};
const goToKeys = () => {
const keysUrl = `/admin/realms/${realmName}/keys`;
cy.intercept(keysUrl).as("keysFetch");
keysTab.goToKeysTab();
cy.findByTestId("rs-keys-list-tab").click();
cy.wait(["@keysFetch"]);
return this;
};
it("Enable user events", () => {
cy.intercept("GET", `/admin/realms/${realmName}/events/config`).as("load");
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-realm-events-tab").click();
cy.findByTestId("rs-events-tab").click();
cy.wait("@load");
realmSettingsPage
.toggleSwitch(realmSettingsPage.enableEvents, false)
.save(realmSettingsPage.eventsUserSave);
masthead.checkNotificationMessage("Successfully saved configuration");
realmSettingsPage.clearEvents("user");
modalUtils
.checkModalMessage(
"If you clear all events of this realm, all records will be permanently cleared in the database",
)
.confirmModal();
masthead.checkNotificationMessage("The user events have been cleared");
const events = ["Client info", "Client info error"];
cy.intercept("GET", `/admin/realms/${realmName}/events/config`).as(
"fetchConfig",
);
realmSettingsPage.addUserEvents(events).clickAdd();
masthead.checkNotificationMessage("Successfully saved configuration");
cy.wait(["@fetchConfig"]);
sidebarPage.waitForPageLoad();
cy.wait(1000);
for (const event of events) {
listingPage.searchItem(event, false).itemExist(event);
}
});
it("Go to keys tab", () => {
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
});
it("add Providers", () => {
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
cy.findByTestId("rs-providers-tab").click();
realmSettingsPage.toggleAddProviderDropdown();
cy.findByTestId("option-aes-generated").click();
realmSettingsPage.enterUIDisplayName("test_aes-generated");
realmSettingsPage.addProvider();
realmSettingsPage.toggleAddProviderDropdown();
cy.findByTestId("option-ecdsa-generated").click();
realmSettingsPage.enterUIDisplayName("test_ecdsa-generated");
realmSettingsPage.toggleSwitch("active", false);
realmSettingsPage.toggleSwitch("ecGenerateCertificate", false);
realmSettingsPage.addProvider();
realmSettingsPage.toggleAddProviderDropdown();
cy.findByTestId("option-hmac-generated").click();
realmSettingsPage.enterUIDisplayName("test_hmac-generated");
realmSettingsPage.toggleSwitch("enabled", false);
realmSettingsPage.addProvider();
realmSettingsPage.toggleAddProviderDropdown();
cy.findByTestId("option-rsa-generated").click();
realmSettingsPage.enterUIDisplayName("test_rsa-generated");
realmSettingsPage.addProvider();
realmSettingsPage.toggleAddProviderDropdown();
cy.findByTestId("option-rsa-enc-generated").click();
realmSettingsPage.enterUIDisplayName("test_rsa-enc-generated");
realmSettingsPage.addProvider();
});
it("search providers", () => {
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
cy.findByTestId("rs-providers-tab").click();
// search providers
cy.findByTestId("provider-search-input").type("rsa{enter}");
listingPage.checkTableLength(4, "kc-draggable-table");
cy.findByTestId("provider-search-input").clear().type("{enter}");
});
it("go to details", () => {
sidebarPage.goToRealmSettings();
goToDetails();
});
it("Test keys", () => {
sidebarPage.goToRealmSettings();
goToKeys();
realmSettingsPage.testSelectFilter();
});
it.skip("Should search active keys", () => {
sidebarPage.goToRealmSettings();
goToKeys();
realmSettingsPage.switchToActiveFilter();
listingPage.searchItem("rs", false);
listingPage.checkTableLength(3, "kc-keys-list");
});
it("Should search passive keys", () => {
sidebarPage.goToRealmSettings();
goToKeys();
realmSettingsPage.switchToPassiveFilter();
listingPage.searchItem("ec", false);
listingPage.checkTableLength(1, "kc-keys-list");
});
it("Should search disabled keys", () => {
sidebarPage.goToRealmSettings();
goToKeys();
realmSettingsPage.switchToDisabledFilter();
listingPage.searchItem("hs", false);
listingPage.checkTableLength(1, "kc-keys-list");
});
it("delete provider", () => {
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
cy.findByTestId("rs-providers-tab").click();
realmSettingsPage.deleteProvider("test_aes-generated");
});
it("list keys", () => {
sidebarPage.goToRealmSettings();
keysTab.goToKeysTab();
realmSettingsPage.checkKeyPublic();
});
it("Realm header settings", () => {
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-security-defenses-tab").click();
cy.findByTestId("browserSecurityHeaders.xFrameOptions").clear();
cy.findByTestId("browserSecurityHeaders.xFrameOptions").type("DENY");
cy.findByTestId("headers-form-tab-save").should("be.enabled").click();
masthead.checkNotificationMessage("Realm successfully updated");
});
it("Brute force detection", () => {
sidebarPage.goToRealmSettings();
cy.findAllByTestId("rs-security-defenses-tab").click();
cy.get("#pf-tab-20-bruteForce").click();
cy.get("#kc-brute-force-mode").click();
cy.findByTestId("select-brute-force-mode")
.contains("Lockout temporarily")
.click();
cy.findByTestId("waitIncrementSeconds").type("1");
cy.findByTestId("maxFailureWaitSeconds").type("1");
cy.findByTestId("maxDeltaTimeSeconds").type("1");
cy.findByTestId("minimumQuickLoginWaitSeconds").type("1");
cy.findByTestId("brute-force-tab-save").should("be.enabled").click();
masthead.checkNotificationMessage("Realm successfully updated");
});
it("add session data", () => {
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-sessions-tab").click();
realmSettingsPage.populateSessionsPage();
realmSettingsPage.save("sessions-tab-save");
masthead.checkNotificationMessage("Realm successfully updated");
});
it("check that sessions data was saved", () => {
sidebarPage.goToAuthentication();
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-sessions-tab").click();
cy.findByTestId(realmSettingsPage.ssoSessionIdleInput).should(
"have.value",
1,
);
cy.findByTestId(realmSettingsPage.ssoSessionMaxInput).should(
"have.value",
2,
);
cy.findByTestId(realmSettingsPage.ssoSessionIdleRememberMeInput).should(
"have.value",
3,
);
cy.findByTestId(realmSettingsPage.ssoSessionMaxRememberMeInput).should(
"have.value",
4,
);
cy.findByTestId(realmSettingsPage.clientSessionIdleInput).should(
"have.value",
5,
);
cy.findByTestId(realmSettingsPage.clientSessionMaxInput).should(
"have.value",
6,
);
cy.findByTestId(realmSettingsPage.offlineSessionIdleInput).should(
"have.value",
7,
);
cy.findByTestId(realmSettingsPage.offlineSessionMaxSwitch).should(
"have.value",
"on",
);
cy.findByTestId(realmSettingsPage.loginTimeoutInput).should(
"have.value",
9,
);
cy.findByTestId(realmSettingsPage.loginActionTimeoutInput).should(
"have.value",
10,
);
});
it("add token data", () => {
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-tokens-tab").click();
realmSettingsPage.populateTokensPage();
realmSettingsPage.save("tokens-tab-save");
masthead.checkNotificationMessage("Realm successfully updated");
});
it("check that token data was saved", () => {
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-tokens-tab").click();
cy.findByTestId(realmSettingsPage.accessTokenLifespanInput).should(
"have.value",
1,
);
cy.findByTestId(realmSettingsPage.parRequestUriLifespanInput).should(
"have.value",
2,
);
cy.findByTestId(realmSettingsPage.accessTokenLifespanImplicitInput).should(
"have.value",
2,
);
cy.findByTestId(realmSettingsPage.clientLoginTimeoutInput).should(
"have.value",
3,
);
cy.findByTestId(realmSettingsPage.userInitiatedActionLifespanInput).should(
"have.value",
4,
);
cy.findByTestId(realmSettingsPage.defaultAdminInitatedInput).should(
"have.value",
5,
);
cy.findByTestId(realmSettingsPage.emailVerificationInput).should(
"have.value",
6,
);
cy.findByTestId(realmSettingsPage.idpEmailVerificationInput).should(
"have.value",
7,
);
cy.findByTestId(realmSettingsPage.forgotPasswordInput).should(
"have.value",
8,
);
cy.findByTestId(realmSettingsPage.executeActionsInput).should(
"have.value",
9,
);
});
});
describe("Realm settings events tab tests", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-realm-events-tab").click();
cy.findByTestId("rs-event-listeners-tab").click();
});
it("Should display event listeners form", () => {
realmSettingsPage.shouldDisplayEventListenersForm();
});
it("Should revert saving event listener", () => {
realmSettingsPage.shouldRevertSavingEventListener();
});
it("Should save event listener", () => {
realmSettingsPage.shouldSaveEventListener();
});
it("Should remove event from event listener", () => {
realmSettingsPage.shouldRemoveEventFromEventListener();
});
it("Should remove all events from event listener and re-save original", () => {
realmSettingsPage.shouldRemoveAllEventListeners();
realmSettingsPage.shouldReSaveEventListener();
});
});

View File

@@ -1,184 +0,0 @@
import { SERVER_URL } from "../support/constants";
import LoginPage from "../support/pages/LoginPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const masthead = new Masthead();
const realmSettingsPage = new RealmSettingsPage();
describe("Realm settings general tab tests", () => {
const realmName = "Realm_" + crypto.randomUUID();
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
});
before(async () => {
await adminClient.createRealm(realmName);
});
after(async () => {
await adminClient.deleteRealm(realmName);
});
it("Test all general tab switches", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.toggleSwitch(
realmSettingsPage.managedAccessSwitch,
false,
);
realmSettingsPage.save(realmSettingsPage.generalSaveBtn);
masthead.checkNotificationMessage("Realm successfully updated", true);
realmSettingsPage.toggleSwitch(
realmSettingsPage.managedAccessSwitch,
false,
);
realmSettingsPage.save(realmSettingsPage.generalSaveBtn);
masthead.checkNotificationMessage("Realm successfully updated", true);
});
it("Test realm enable/disable switch", () => {
sidebarPage.goToRealmSettings();
// Enable realm
realmSettingsPage.toggleSwitch(`${realmName}-switch`);
masthead.checkNotificationMessage("Realm successfully updated", true);
realmSettingsPage.assertSwitch(`${realmName}-switch`, true);
// Disable realm
realmSettingsPage.toggleSwitch(`${realmName}-switch`, false);
realmSettingsPage.disableRealm();
masthead.checkNotificationMessage("Realm successfully updated", true);
});
it("Fail to set Realm ID to empty", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.clearRealmId();
realmSettingsPage.saveGeneral();
cy.findByTestId("realm-id-error").should("have.text", "Required field");
});
it("Modify Display name", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.fillDisplayName("display_name");
realmSettingsPage.save(realmSettingsPage.generalSaveBtn);
masthead.checkNotificationMessage("Realm successfully updated", true);
});
it("Check Display name value", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.getDisplayName("display_name");
});
it("Modify front end URL", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.fillFrontendURL("www.example.com");
// TODO: Fix internal server error 500 when front-end URL is saved
// realmSettingsPage.save(realmSettingsPage.generalSaveBtn);
// masthead.checkNotificationMessage("Realm successfully updated", true);
realmSettingsPage.getFrontendURL("www.example.com");
realmSettingsPage.clearFrontendURL();
});
it("Select SSL all requests", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.fillRequireSSL("All requests");
realmSettingsPage.save(realmSettingsPage.generalSaveBtn);
masthead.checkNotificationMessage("Realm successfully updated", true);
});
it("Verify SSL all requests displays", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.getRequireSSL("All requests");
});
it("Select SSL external requests", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.fillRequireSSL("External requests");
realmSettingsPage.save(realmSettingsPage.generalSaveBtn);
masthead.checkNotificationMessage("Realm successfully updated", true);
});
it("Verify SSL external requests displays", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.getRequireSSL("External requests");
});
it("Select SSL None", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.fillRequireSSL("None");
realmSettingsPage.save(realmSettingsPage.generalSaveBtn);
masthead.checkNotificationMessage("Realm successfully updated", true);
});
it("Verify SSL None displays", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.getRequireSSL("None");
});
it("Check Access Endpoints OpenID Endpoint Configuration link", () => {
sidebarPage.goToRealmSettings();
// Check link exists
cy.get("a")
.contains("OpenID Endpoint Configuration")
.should(
"have.attr",
"href",
`${SERVER_URL}/realms/${realmName}/.well-known/openid-configuration`,
)
.should("have.attr", "target", "_blank")
.should("have.attr", "rel", "noreferrer noopener");
});
it("Access Endpoints OpenID Endpoint Configuration link", () => {
sidebarPage.goToRealmSettings();
// Check the link is live
cy.get("a")
.contains("OpenID Endpoint Configuration")
.then((link) => {
cy.request(link.prop("href")).its("status").should("eq", 200);
});
});
it("Check if Access Endpoints SAML 2.0 Identity Provider Metadata link exists", () => {
sidebarPage.goToRealmSettings();
cy.get("a")
.contains("SAML 2.0 Identity Provider Metadata")
.should(
"have.attr",
"href",
`${SERVER_URL}/realms/${realmName}/protocol/saml/descriptor`,
)
.should("have.attr", "target", "_blank")
.should("have.attr", "rel", "noreferrer noopener");
});
it("Access Endpoints SAML 2.0 Identity Provider Metadata link", () => {
sidebarPage.goToRealmSettings();
// Check the link is live
cy.get("a")
.contains("SAML 2.0 Identity Provider Metadata ")
.then((link) => {
cy.request(link.prop("href")).its("status").should("eq", 200);
});
});
it("Verify 'Revert' button works", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.fillDisplayName("should_be_reverted");
realmSettingsPage.revert(realmSettingsPage.generalRevertBtn);
realmSettingsPage.getDisplayName("display_name");
});
});

View File

@@ -1,433 +0,0 @@
import FormValidation from "../support/forms/FormValidation";
import LoginPage from "../support/pages/LoginPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import KeysTab from "../support/pages/admin-ui/manage/realm_settings/KeysTab";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import UserRegistration from "../support/pages/admin-ui/manage/realm_settings/UserRegistration";
import adminClient from "../support/util/AdminClient";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const masthead = new Masthead();
const realmSettingsPage = new RealmSettingsPage();
const userRegistration = new UserRegistration();
const keysTab = new KeysTab();
const modalUtils = new ModalUtils();
describe("Realm settings tabs tests", () => {
const realmName = "Realm_" + crypto.randomUUID();
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
});
before(async () => {
await adminClient.createRealm(realmName);
});
after(async () => {
await adminClient.deleteRealm(realmName);
});
const addBundle = () => {
realmSettingsPage.addKeyValuePair("123", "abc");
return this;
};
it("shows the 'user profile' tab", () => {
sidebarPage.goToRealmSettings();
cy.findByTestId(realmSettingsPage.userProfileTab).should("exist");
});
// Clicking multiple toggles in succession causes quick re-renderings of the screen
// and there will be a noticeable flicker during the test.
// Sometimes, this will screw up the test and cause Cypress to hang.
// Clicking to another section each time fixes the problem.
function reloadRealm() {
sidebarPage.goToClientScopes();
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLoginTab();
}
function testToggle(realmSwitch: string, expectedValue: string) {
realmSettingsPage.toggleSwitch(realmSwitch);
reloadRealm();
cy.findByTestId(realmSwitch).should("have.value", expectedValue);
}
it("Go to login tab", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLoginTab();
testToggle(realmSettingsPage.userRegSwitch, "on");
testToggle(realmSettingsPage.forgotPwdSwitch, "on");
testToggle(realmSettingsPage.rememberMeSwitch, "on");
testToggle(realmSettingsPage.loginWithEmailSwitch, "off");
testToggle(realmSettingsPage.duplicateEmailsSwitch, "on");
// Check other values
cy.findByTestId(realmSettingsPage.emailAsUsernameSwitch).should(
"have.value",
"off",
);
cy.findByTestId(realmSettingsPage.verifyEmailSwitch).should(
"have.value",
"off",
);
});
it("Go to email tab", () => {
// Configure an e-mail address so we can test the connection settings.
cy.wrap(null).then(async () => {
const adminUser = await adminClient.getAdminUser();
await adminClient.updateUser(adminUser.id!, {
email: "admin@example.com",
});
});
sidebarPage.goToRealmSettings();
realmSettingsPage.goToEmailTab();
//required fields not filled in or not filled properly
realmSettingsPage.addSenderEmail("not a valid email");
realmSettingsPage.fillFromDisplayName("displayName");
realmSettingsPage.fillReplyToEmail("replyTo@email.com");
realmSettingsPage.fillPort("10");
cy.findByTestId("email-tab-save").click();
FormValidation.assertMessage(
realmSettingsPage.getFromInput(),
"You must enter a valid email.",
);
FormValidation.assertRequired(realmSettingsPage.getHostInput());
cy.findByTestId("email-tab-revert").click();
cy.findByTestId("smtpServer.from").should("be.empty");
cy.findByTestId("smtpServer.fromDisplayName").should("be.empty");
cy.findByTestId("smtpServer.port").should("be.empty");
realmSettingsPage.addSenderEmail("example@example.com");
realmSettingsPage.toggleCheck(realmSettingsPage.enableSslCheck);
realmSettingsPage.toggleCheck(realmSettingsPage.enableStartTlsCheck);
realmSettingsPage.fillHostField("localhost");
cy.findByTestId(realmSettingsPage.testConnectionButton).click();
masthead.checkNotificationMessage("Error! Failed to send email", true);
});
it("Go to themes tab", () => {
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-themes-tab").click();
realmSettingsPage.selectLoginThemeType("keycloak");
realmSettingsPage.selectAccountThemeType("keycloak");
realmSettingsPage.selectEmailThemeType("base");
realmSettingsPage.saveThemes();
});
describe("Go to security defenses tab", () => {
it("Realm header settings- update single input", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToSecurityDefensesTab();
cy.findByTestId("browserSecurityHeaders.xFrameOptions").clear();
cy.findByTestId("browserSecurityHeaders.xFrameOptions").type("DENY");
realmSettingsPage.saveSecurityDefensesHeaders();
masthead.checkNotificationMessage("Realm successfully updated");
});
it("Realm header settings- update all inputs", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToSecurityDefensesTab();
cy.findByTestId("browserSecurityHeaders.xFrameOptions").clear();
cy.findByTestId("browserSecurityHeaders.xFrameOptions").type(
"SAMEORIGIN",
);
cy.findByTestId("browserSecurityHeaders.contentSecurityPolicy").clear();
cy.findByTestId("browserSecurityHeaders.contentSecurityPolicy").type(
"default-src 'self'",
);
cy.findByTestId("browserSecurityHeaders.strictTransportSecurity").clear();
cy.findByTestId("browserSecurityHeaders.strictTransportSecurity").type(
"max-age=31536000",
);
cy.findByTestId("browserSecurityHeaders.xContentTypeOptions").clear();
cy.findByTestId("browserSecurityHeaders.xContentTypeOptions").type(
"nosniff",
);
cy.findByTestId("browserSecurityHeaders.xRobotsTag").clear();
cy.findByTestId("browserSecurityHeaders.xRobotsTag").type("none");
cy.findByTestId("browserSecurityHeaders.strictTransportSecurity").clear();
cy.findByTestId("browserSecurityHeaders.strictTransportSecurity").type(
"max-age=31537000",
);
cy.findByTestId("browserSecurityHeaders.referrerPolicy").clear();
cy.findByTestId("browserSecurityHeaders.referrerPolicy").type("referrer");
realmSettingsPage.saveSecurityDefensesHeaders();
masthead.checkNotificationMessage("Realm successfully updated");
});
it("Brute force detection- update values", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToSecurityDefensesTab();
realmSettingsPage.goToSecurityDefensesBruteForceTab();
cy.get("#kc-brute-force-mode").click();
cy.findByTestId("select-brute-force-mode")
.contains("Lockout temporarily")
.click();
cy.findByTestId("waitIncrementSeconds").type("1");
cy.findByTestId("maxFailureWaitSeconds").type("1");
cy.findByTestId("maxDeltaTimeSeconds").type("1");
cy.findByTestId("minimumQuickLoginWaitSeconds").type("1");
realmSettingsPage.saveSecurityDefensesBruteForce();
masthead.checkNotificationMessage("Realm successfully updated");
});
});
describe("Go to localization tab", () => {
it("Locales tab - Add locale", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationLocalesSubTab();
cy.findByTestId("internationalizationEnabled").click({ force: true });
cy.get(realmSettingsPage.supportedLocalesTypeahead)
.click()
.get(".pf-v5-c-menu__list-item")
.contains("Danish")
.click({ force: true });
cy.findByTestId("internationalizationEnabled").click({ force: true });
cy.intercept("GET", `/admin/realms/${realmName}/localization/en*`).as(
"load",
);
cy.findByTestId("localization-tab-save").click();
cy.wait("@load");
masthead.checkNotificationMessage("Realm successfully updated");
});
it("Realm Overrides - Add and delete bundle", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationRealmOverridesSubTab();
addBundle();
masthead.checkNotificationMessage(
"Success! The translation has been added.",
);
cy.findByTestId("editable-rows-table")
.contains("td", "123")
.should("be.visible");
cy.get(".pf-v5-c-table__action button").click();
cy.contains("button", "Delete").click();
cy.findByTestId("confirm").click();
masthead.checkNotificationMessage("Successfully removed translation(s).");
});
it("Realm Overrides - Search for and delete bundle", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationRealmOverridesSubTab();
addBundle();
cy.get('input[aria-label="Search"]').type("123");
cy.findByTestId("editable-rows-table")
.contains("td", "123")
.should("be.visible");
cy.findByTestId("selectAll").click();
cy.get('[data-testid="toolbar-deleteBtn"]').click();
cy.findByTestId("delete-selected-TranslationBtn").click();
cy.findByTestId("confirm").click();
masthead.checkNotificationMessage("Successfully removed translation(s).");
});
it("Realm Overrides - Edit and cancel edit message bundle", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationRealmOverridesSubTab();
addBundle();
cy.findByTestId("editTranslationBtn-0").click();
cy.findByTestId("editTranslationCancelBtn-0").click();
cy.findByTestId("editTranslationBtn-0").click();
cy.findByTestId("editTranslationValueInput-0")
.click()
.clear()
.type("def");
cy.findByTestId("editTranslationAcceptBtn-0").click();
cy.findByTestId("editable-rows-table")
.contains("td", "def")
.should("be.visible");
cy.get(".pf-v5-c-table__action button").click();
cy.contains("button", "Delete").click();
cy.findByTestId("confirm").click();
masthead.checkNotificationMessage("Successfully removed translation(s).");
});
it("Effective Message Bundles - Check before search message", () => {
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationEffectiveMessageBundlesSubTab();
cy.contains("h1", "Search for effective messages");
});
});
describe("Accessibility tests for realm settings", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealmSettings();
cy.injectAxe();
});
it("Check a11y violations on load/ realm settings/ general tab", () => {
cy.checkA11y();
});
it("Check a11y violations on login tab", () => {
realmSettingsPage.goToLoginTab();
cy.checkA11y();
});
it("Check a11y violations on email tab", () => {
realmSettingsPage.goToEmailTab();
cy.checkA11y();
});
it("Check a11y violations on themes tab", () => {
realmSettingsPage.goToThemesTab();
cy.checkA11y();
});
it("Check a11y violations on keys tab/ keys list sub tab", () => {
keysTab.goToKeysTab();
cy.checkA11y();
});
it("Check a11y violations on keys tab/ providers sub tab", () => {
keysTab.goToProvidersTab();
cy.checkA11y();
});
it("Check a11y violations on keys tab/ providers sub tab / adding provider", () => {
keysTab.goToProvidersTab();
cy.findByTestId("addProviderDropdown").click();
cy.checkA11y();
modalUtils.closeModal();
});
it("Check a11y violations on events tab/ event listeners sub tab", () => {
realmSettingsPage.goToEventsTab();
cy.checkA11y();
});
it("Check a11y violations on events tab/ user events settings sub tab", () => {
realmSettingsPage.goToEventsTab().goToUserEventsSettingsSubTab();
cy.checkA11y();
});
it("Check a11y violations on events tab/ admin events settings sub tab", () => {
realmSettingsPage.goToEventsTab().goToAdminEventsSettingsSubTab();
cy.checkA11y();
});
it("Check a11y violations on localization locales sub tab", () => {
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationLocalesSubTab();
cy.checkA11y();
});
it("Check a11y violations on localization realm overrides sub tab", () => {
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationRealmOverridesSubTab();
cy.checkA11y();
});
it("Check a11y violations on localization realm overrides sub tab/ adding message bundle", () => {
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationRealmOverridesSubTab();
cy.findByTestId("add-translationBtn").click();
cy.checkA11y();
modalUtils.cancelModal();
});
it("Check a11y violations on localization effective message bundles sub tab", () => {
realmSettingsPage.goToLocalizationTab();
realmSettingsPage.goToLocalizationEffectiveMessageBundlesSubTab();
cy.checkA11y();
});
it("Check a11y violations on security defenses tab", () => {
realmSettingsPage.goToSecurityDefensesTab();
cy.checkA11y();
});
it("Check a11y violations on sessions tab", () => {
realmSettingsPage.goToSessionsTab();
cy.checkA11y();
});
it("Check a11y violations on tokens tab", () => {
realmSettingsPage.goToTokensTab();
cy.checkA11y();
});
it("Check a11y violations on client policies tab/ profiles sub tab", () => {
realmSettingsPage.goToClientPoliciesTab().goToClientProfilesList();
cy.checkA11y();
});
it("Check a11y violations on client policies tab/ creating profile", () => {
realmSettingsPage.goToClientPoliciesTab().goToClientProfilesList();
cy.findByTestId("createProfile").click();
cy.checkA11y();
cy.findByTestId("cancelCreateProfile").click();
});
it("Check a11y violations on client policies tab/ policies sub tab", () => {
realmSettingsPage.goToClientPoliciesTab().goToClientPoliciesList();
cy.checkA11y();
});
it("Check a11y violations on client policies tab/ creating policy", () => {
realmSettingsPage.goToClientPoliciesTab().goToClientPoliciesList();
cy.findByTestId("no-client-policies-empty-action").click();
cy.checkA11y();
cy.findByTestId("cancelCreatePolicy").click();
});
it("Check a11y violations on user registration tab/ default roles sub tab", () => {
userRegistration.goToTab();
cy.checkA11y();
});
it("Check a11y violations on user registration tab/ default roles sub tab/ assigning role", () => {
userRegistration.goToTab();
cy.findByTestId("assignRole").click();
cy.checkA11y();
modalUtils.cancelModal();
});
});
});

View File

@@ -1,421 +0,0 @@
import ListingPage from "../support/pages/admin-ui/ListingPage";
import UserProfile from "../support/pages/admin-ui/manage/realm_settings/UserProfile";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import ModalUtils from "../support/util/ModalUtils";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import CreateUserPage from "../support/pages/admin-ui/manage/users/CreateUserPage";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const userProfileTab = new UserProfile();
const listingPage = new ListingPage();
const modalUtils = new ModalUtils();
const masthead = new Masthead();
const realmSettingsPage = new RealmSettingsPage();
const createUserPage = new CreateUserPage();
// Selectors
const getUserProfileTab = () => userProfileTab.goToTab();
const getAttributesTab = () => userProfileTab.goToAttributesTab();
const getAttributesGroupTab = () => userProfileTab.goToAttributesGroupTab();
const usernameAttributeName = "username";
const emailAttributeName = "email";
describe("User profile tabs", () => {
const realmName = "Realm_" + crypto.randomUUID();
const attributeName = "Test";
const attributeDisplayName = "Test display name";
before(() => adminClient.createRealm(realmName));
after(() => adminClient.deleteRealm(realmName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
sidebarPage.goToRealmSettings();
});
describe("Attributes sub tab tests", () => {
it("Goes to create attribute page", () => {
getUserProfileTab();
getAttributesTab();
userProfileTab.clickOnCreateAttributeButton();
});
it("Completes new attribute form and performs cancel", () => {
getUserProfileTab();
getAttributesTab();
userProfileTab
.clickOnCreateAttributeButton()
.setAttributeNames(attributeName, attributeDisplayName)
.cancelAttributeCreation()
.checkElementNotInList(attributeName);
});
it("Completes new attribute form and performs submit", () => {
getUserProfileTab();
getAttributesTab();
userProfileTab
.clickOnCreateAttributeButton()
.setAttributeNames(attributeName, attributeDisplayName)
.saveAttributeCreation()
.assertNotificationSaved();
});
it("Modifies existing attribute and performs save", () => {
const attrName = "ModifyTest";
getUserProfileTab();
createAttributeDefinition(attrName);
userProfileTab
.selectElementInList(attrName)
.editAttribute("Edited display name")
.saveAttributeCreation()
.assertNotificationSaved();
});
it("Adds and removes validator to/from existing attribute and performs save", () => {
getUserProfileTab();
userProfileTab
.selectElementInList(attributeName)
.cancelAddingValidator(emailAttributeName);
userProfileTab.addValidator(emailAttributeName);
cy.get('tbody [data-label="Validator name"]').contains(
emailAttributeName,
);
userProfileTab.cancelRemovingValidator();
userProfileTab.removeValidator();
cy.get(".kc-emptyValidators").contains("No validators.");
});
});
describe("Attribute groups sub tab tests", () => {
const group = "Test" + crypto.randomUUID();
before(() => adminClient.addGroupToProfile(realmName, group));
it("Deletes an attributes group", () => {
getUserProfileTab();
getAttributesGroupTab();
listingPage.deleteItem(group);
modalUtils.confirmModal();
listingPage.itemExist(group, false);
});
});
describe("Check attributes are displayed and editable on user create/edit", () => {
it("Checks that not required attribute is not present when user is created with email as username and edit username set to disabled", () => {
const attrName = "newAttribute1";
getUserProfileTab();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer.setNoAttributePermissions(),
);
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLoginTab();
cy.wait(1000);
realmSettingsPage
.assertSwitch(realmSettingsPage.emailAsUsernameSwitch, false)
.assertSwitch(realmSettingsPage.editUsernameSwitch, false);
// Create user
sidebarPage.goToUsers();
cy.wait(1000);
createUserPage
.goToCreateUser()
.assertAttributeFieldExists(attrName, false)
.setUsername(`testuser7-${crypto.randomUUID()}`)
.create()
.assertNotificationCreated()
.assertAttributeFieldExists(attrName, false);
sidebarPage.goToRealmSettings();
getUserProfileTab();
getAttributesTab();
listingPage.deleteItem(attrName);
modalUtils.confirmModal();
masthead.checkNotificationMessage("Attribute deleted");
});
it("Checks that not required attribute is not present when user is created/edited with email as username enabled", () => {
const attrName = "newAttribute2";
getUserProfileTab();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer.setNoAttributePermissions(),
);
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLoginTab();
cy.wait(1000);
realmSettingsPage
.setSwitch(realmSettingsPage.emailAsUsernameSwitch, true)
.assertSwitch(realmSettingsPage.emailAsUsernameSwitch, true)
.assertSwitch(realmSettingsPage.editUsernameSwitch, false);
// Create user
sidebarPage.goToUsers();
createUserPage
.goToCreateUser()
.setAttributeValue(
emailAttributeName,
`testuser8-${crypto.randomUUID()}@gmail.com`,
)
.assertAttributeFieldExists(attrName, false)
.create()
.assertNotificationCreated();
// Edit user
createUserPage
.assertAttributeFieldExists(attrName, false)
.setAttributeValue(
emailAttributeName,
`testuser9-${crypto.randomUUID()}@gmail.com`,
)
.update()
.assertNotificationUpdated();
deleteAttributeDefinition(attrName);
});
it("Checks that not required attribute with permissions to view/edit is present when user is created", () => {
const attrName = "newAttribute3";
getUserProfileTab();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer.setAllAttributePermissions(),
);
sidebarPage.goToRealmSettings();
realmSettingsPage.goToLoginTab();
cy.wait(1000);
realmSettingsPage
.setSwitch(realmSettingsPage.emailAsUsernameSwitch, false)
.assertSwitch(realmSettingsPage.emailAsUsernameSwitch, false)
.setSwitch(realmSettingsPage.editUsernameSwitch, false)
.assertSwitch(realmSettingsPage.editUsernameSwitch, false);
// Create user
sidebarPage.goToUsers();
createUserPage
.goToCreateUser()
.assertAttributeFieldExists(attrName, true)
.setUsername(`testuser10-${crypto.randomUUID()}`)
.create()
.assertNotificationCreated()
.assertAttributeFieldExists(attrName, true);
deleteAttributeDefinition(attrName);
});
it("Checks that required attribute with permissions to view/edit is present and required when user is created", () => {
const attrName = "newAttribute4";
getUserProfileTab();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer.setAllAttributePermissions().setAttributeRequired(),
);
// Create user
sidebarPage.goToUsers();
createUserPage
.goToCreateUser()
.assertAttributeLabel(attrName, attrName)
.setUsername(`testuser11-${crypto.randomUUID()}`)
.create()
.assertValidationErrorRequired(attrName);
createUserPage
.setAttributeValue(attrName, "MyAttribute")
.create()
.assertNotificationCreated();
deleteAttributeDefinition(attrName);
});
it("Checks that required attribute with permissions to view/edit is accepted when user is created", () => {
const attrName = "newAttribute5";
getUserProfileTab();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer.setAllAttributePermissions().setAttributeRequired(),
);
// Create user
sidebarPage.goToUsers();
createUserPage
.goToCreateUser()
.assertAttributeLabel(attrName, attrName)
.setUsername(`testuser12-${crypto.randomUUID()}`)
.setAttributeValue(attrName, "MyAttribute")
.create()
.assertNotificationCreated();
deleteAttributeDefinition(attrName);
});
it("Checks that attribute group is visible when user with existing attribute is created", () => {
const group = "personalInfo";
getUserProfileTab();
getAttributesGroupTab()
.clickOnCreatesAttributesGroupButton()
.createAttributeGroup(group, group)
.saveAttributesGroupCreation()
.assertNotificationUpdated();
getAttributesTab();
userProfileTab
.selectElementInList(usernameAttributeName)
.setAttributeGroup(group)
.saveAttributeCreation()
.assertNotificationSaved();
// Create user
sidebarPage.goToUsers();
createUserPage
.goToCreateUser()
.assertGroupDisplayName(group, group)
.setUsername(`testuser14-${crypto.randomUUID()}`)
.create()
.assertNotificationCreated();
sidebarPage.goToRealmSettings();
getUserProfileTab();
getAttributesTab();
userProfileTab
.selectElementInList(usernameAttributeName)
.resetAttributeGroup()
.saveAttributeCreation()
.assertNotificationSaved();
});
it("Checks that attribute group is visible when user with a new attribute is created", () => {
const group = "contact";
const attrName = "address";
getUserProfileTab();
getAttributesGroupTab()
.clickOnCreatesAttributesGroupButton()
.createAttributeGroup(group, group)
.saveAttributesGroupCreation()
.assertNotificationUpdated();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer.setAllAttributePermissions(),
);
userProfileTab
.selectElementInList(attrName)
.setAttributeGroup(group)
.saveAttributeCreation()
.assertNotificationSaved();
// Create user
sidebarPage.goToUsers();
const initialAttrValue = "MyNewAddress1";
createUserPage
.goToCreateUser()
.assertGroupDisplayName(group, group)
.assertAttributeLabel(attrName, attrName)
.setUsername(`testuser13-${crypto.randomUUID()}`)
.setAttributeValue(attrName, initialAttrValue)
.create()
.assertNotificationCreated()
.assertAttributeValue(attrName, initialAttrValue);
// Edit attribute
const newAttrValue = "MyNewAddress2";
createUserPage
.setAttributeValue(attrName, newAttrValue)
.update()
.assertNotificationUpdated()
.assertAttributeValue(attrName, newAttrValue);
sidebarPage.goToRealmSettings();
getUserProfileTab();
getAttributesTab();
userProfileTab
.selectElementInList(attrName)
.resetAttributeGroup()
.saveAttributeCreation()
.assertNotificationSaved();
deleteAttributeDefinition(attrName);
});
it("Checks that attribute with select-annotation is displayed and editable when user is created/edited", () => {
const userName = `select-test-user-${crypto.randomUUID()}`;
const attrName = "select-test-attr";
const opt1 = "opt1";
const opt2 = "opt2";
const supportedOptions = [opt1, opt2];
getUserProfileTab();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer
.setAllAttributePermissions()
.clickAddValidator()
.selectValidatorType("options")
.setListFieldValues("options", supportedOptions)
.clickSave(),
);
// Create user
sidebarPage.goToUsers();
createUserPage
.goToCreateUser()
.assertAttributeLabel(attrName, attrName)
.assertAttributeSelect(attrName, supportedOptions, "Select an option")
.setUsername(userName)
.setAttributeValueOnSelect(attrName, opt1)
.create()
.assertNotificationCreated()
.assertAttributeLabel(attrName, attrName)
.assertAttributeSelect(attrName, supportedOptions, opt1);
// Edit attribute
createUserPage
.setAttributeValueOnSelect(attrName, opt2)
.update()
.assertNotificationUpdated()
.assertAttributeLabel(attrName, attrName)
.assertAttributeSelect(attrName, supportedOptions, opt2);
});
});
function deleteAttributeDefinition(attrName: string) {
sidebarPage.goToRealmSettings();
getUserProfileTab();
getAttributesTab();
listingPage.deleteItem(attrName);
modalUtils.confirmModal();
masthead.checkNotificationMessage("Attribute deleted");
}
function createAttributeDefinition(
attrName: string,
attrConfigurer?: (attrConfigurer: UserProfile) => void,
) {
userProfileTab
.goToAttributesTab()
.clickOnCreateAttributeButton()
.setAttributeNames(attrName, attrName);
if (attrConfigurer) {
attrConfigurer(userProfileTab);
}
userProfileTab.saveAttributeCreation().assertNotificationSaved();
}
});

View File

@@ -1,131 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import CreateRealmPage from "../support/pages/admin-ui/CreateRealmPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import RealmSettings from "../support/pages/admin-ui/configure/realm_settings/RealmSettings";
import ModalUtils from "../support/util/ModalUtils";
import CommonPage from "../support/pages/CommonPage";
const masthead = new Masthead();
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const createRealmPage = new CreateRealmPage();
const realmSettings = new RealmSettings();
const modalUtils = new ModalUtils();
const commonPage = new CommonPage();
const testRealmName = "Test-realm-" + crypto.randomUUID();
const newRealmName = "New-Test-realm-" + crypto.randomUUID();
const editedRealmName = "Edited-Test-realm-" + crypto.randomUUID();
const testDisabledName = "Test-Disabled";
const specialCharsName = "%22-" + crypto.randomUUID();
describe("Realm tests", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
});
after(() =>
Promise.all(
[testRealmName, newRealmName, editedRealmName, specialCharsName].map(
(realm) => adminClient.deleteRealm(realm),
),
),
);
it("should fail creating duplicated or empty name realm", () => {
sidebarPage.goToCreateRealm();
createRealmPage.createRealm(false).verifyRealmNameFieldInvalid();
createRealmPage.fillRealmName("master").createRealm();
masthead.checkNotificationMessage(
"Could not create realm Conflict detected. See logs for details",
);
createRealmPage.cancelRealmCreation();
});
it("should create Test realm", () => {
sidebarPage.goToCreateRealm();
// Test and clear resource field
createRealmPage.fillCodeEditor();
createRealmPage.clearTextField();
createRealmPage.fillRealmName(testRealmName).createRealm();
masthead.checkNotificationMessage("Realm created successfully");
});
it("CRUD test of Disabled realm", () => {
sidebarPage.goToCreateRealm();
sidebarPage.waitForPageLoad();
createRealmPage.fillRealmName(testDisabledName).createRealm();
masthead.checkNotificationMessage("Realm created successfully");
cy.reload();
sidebarPage.goToRealm(testDisabledName).goToRealmSettings();
createRealmPage.disableRealm();
modalUtils.confirmModal();
masthead.checkNotificationMessage("Realm successfully updated");
sidebarPage.goToRealm(testDisabledName).goToRealmSettings();
realmSettings.clickActionMenu();
cy.findByText("Delete").click();
modalUtils.cancelModal();
cy.reload();
sidebarPage.waitForPageLoad();
sidebarPage.goToRealm(testDisabledName).goToRealmSettings();
realmSettings.clickActionMenu();
cy.findByText("Delete").click();
modalUtils.confirmModal();
masthead.checkNotificationMessage("The realm has been deleted");
// Show current realms
sidebarPage.realmExists("Test-Disabled", false);
});
it("should create realm from new a realm", () => {
sidebarPage.goToCreateRealm();
createRealmPage.fillRealmName(newRealmName).createRealm();
masthead.checkNotificationMessage("Realm created successfully");
sidebarPage.goToCreateRealm();
createRealmPage.fillRealmName(editedRealmName).createRealm();
masthead.checkNotificationMessage("Realm created successfully");
// Show current realms
sidebarPage.showCurrentRealms(4);
});
it("should change to Test realm", () => {
sidebarPage.goToRealm(editedRealmName);
sidebarPage.getCurrentRealm().should("eq", editedRealmName);
sidebarPage
.goToRealm(testRealmName)
.getCurrentRealm()
.should("eq", testRealmName);
});
it("should create realm with special characters", () => {
sidebarPage.goToCreateRealm();
createRealmPage.fillRealmName(specialCharsName).createRealm();
sidebarPage.goToRealm(specialCharsName);
sidebarPage.goToClients();
commonPage.tableUtils().checkRowItemExists("account");
});
});

View File

@@ -1,70 +0,0 @@
import ListingPage from "../support/pages/admin-ui/ListingPage";
import ClientRolesTab from "../support/pages/admin-ui/manage/clients/ClientRolesTab";
import UserRegistration, {
GroupPickerDialog,
} from "../support/pages/admin-ui/manage/realm_settings/UserRegistration";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import adminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import ModalUtils from "../support/util/ModalUtils";
describe("Realm settings - User registration tab", () => {
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const modalUtils = new ModalUtils();
const masthead = new Masthead();
const listingPage = new ListingPage();
const groupPicker = new GroupPickerDialog();
const userRegistration = new UserRegistration();
const rolesTab = new ClientRolesTab();
const groupName = "The default group";
before(() => adminClient.createGroup(groupName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealmSettings();
userRegistration.goToTab();
});
after(() => adminClient.deleteGroups());
it("Add admin role", () => {
const role = "admin";
const roleType = "roles";
userRegistration.addRole();
sidebarPage.waitForPageLoad();
userRegistration.changeRoleTypeFilter(roleType).selectRow(role).assign();
masthead.checkNotificationMessage("Associated roles have been added");
listingPage.searchItem(role, false).itemExist(role);
sidebarPage.goToRealmRoles();
listingPage.goToItemDetails("admin");
rolesTab.goToUsersInRoleTab();
cy.findByTestId("users-in-role-table").contains("admin");
});
it("Remove admin role", () => {
const role = "admin";
listingPage.markItemRow(role).removeMarkedItems("Unassign");
sidebarPage.waitForPageLoad();
modalUtils
.checkModalTitle("Remove role?")
.checkModalMessage("Are you sure you want to remove this role?")
.checkConfirmButtonText("Remove")
.confirmModal();
masthead.checkNotificationMessage("Role mapping updated");
});
it("Add default group", () => {
userRegistration.goToDefaultGroupTab().addDefaultGroup();
groupPicker.checkTitle("Add default groups").clickRow(groupName).clickAdd();
masthead.checkNotificationMessage("New group added to the default groups");
listingPage.itemExist(groupName);
});
});

View File

@@ -1,165 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import SessionsPage from "../support/pages/admin-ui/manage/sessions/SessionsPage";
import CommonPage from "../support/pages/CommonPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import PageObject from "../support/pages/admin-ui/components/PageObject";
import adminClient from "../support/util/AdminClient";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const sessionsPage = new SessionsPage();
const commonPage = new CommonPage();
const listingPage = new ListingPage();
const page = new PageObject();
describe("Sessions test", () => {
const admin = "admin";
const client = "security-admin-console";
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToSessions();
});
describe("Sessions list view", () => {
it("check item values", () => {
listingPage.searchItem(client, false);
commonPage
.tableUtils()
.checkRowItemExists(admin)
.checkRowItemExists(client)
.assertRowItemActionExist(admin, "Sign out");
});
it("go to item accessed clients link", () => {
listingPage.searchItem(client, false);
commonPage.tableUtils().clickRowItemLink(client);
});
});
describe("Offline sessions", () => {
const clientId = "offline-client-" + crypto.randomUUID();
const username = "user-" + crypto.randomUUID();
beforeEach(async () => {
await Promise.all([
adminClient.createClient({
protocol: "openid-connect",
clientId,
publicClient: false,
directAccessGrantsEnabled: true,
clientAuthenticatorType: "client-secret",
secret: "secret",
standardFlowEnabled: true,
}),
adminClient.createUser({
// Create user in master realm
username: username,
enabled: true,
credentials: [{ type: "password", value: "password" }],
}),
]);
await adminClient.auth({
username,
password: "password",
grantType: "password",
clientId,
clientSecret: "secret",
scopes: ["openid", "offline_access"],
});
});
after(() =>
Promise.all([
adminClient.deleteClient(clientId),
adminClient.deleteUser(username),
]),
);
it("check offline token", () => {
sidebarPage.waitForPageLoad();
listingPage.searchItem(clientId, false);
sidebarPage.waitForPageLoad();
// Now check that offline session exists (online one has been logged off above)
// and that it is possible to revoke it
commonPage
.tableUtils()
.checkRowItemExists(username)
.selectRowItemAction(username, "Revoke");
});
});
describe("Search", () => {
it("search existing session", () => {
listingPage.searchItem(admin, false);
listingPage.itemExist(admin, true);
page.assertEmptyStateExist(false);
});
it("search non-existant session", () => {
listingPage.searchItem("non-existant-session", false);
page.assertEmptyStateExist(true);
});
});
//TODO seems these tests are not stable on CI
describe.skip("revocation", () => {
it("Clear revocation notBefore", () => {
sessionsPage.clearNotBefore();
});
it("Check if notBefore cleared", () => {
sessionsPage.checkNotBeforeCleared();
});
it("Set revocation notBefore", () => {
sessionsPage.setToNow();
});
it("Check if notBefore saved", () => {
sessionsPage.checkNotBeforeValueExists();
});
it("Push when URI not configured", () => {
sessionsPage.pushRevocation();
commonPage
.masthead()
.checkNotificationMessage(
"No push sent. No admin URI configured or no registered cluster nodes available",
);
});
});
describe("Accessibility tests for sessions", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToSessions();
cy.injectAxe();
});
it("Check a11y violations on load/ sessions", () => {
cy.checkA11y();
});
it("Check a11y violations on revocation dialog", () => {
cy.findByTestId("action-dropdown").click();
cy.findByTestId("revocation").click();
cy.checkA11y();
cy.findByTestId("cancel").click();
});
it("Check a11y violations on sign out all active sessions dialog", () => {
cy.findByTestId("action-dropdown").click();
cy.findByTestId("logout-all").click();
cy.checkA11y();
cy.findByTestId("cancel").click();
});
});
});

View File

@@ -1,251 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import ProviderPage from "../support/pages/admin-ui/manage/providers/ProviderPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import PriorityDialog from "../support/pages/admin-ui/manage/providers/PriorityDialog";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const providersPage = new ProviderPage();
const modalUtils = new ModalUtils();
const provider = "kerberos";
const initCapProvider = provider.charAt(0).toUpperCase() + provider.slice(1);
const kerberosName = "my-kerberos";
const kerberosRealm = "my-realm";
const kerberosPrincipal = "my-principal";
const kerberosKeytab = "my-keytab";
const firstKerberosName = `${kerberosName}-1`;
const firstKerberosRealm = `${kerberosRealm}-1`;
const firstKerberosPrincipal = `${kerberosPrincipal}-1`;
const firstKerberosKeytab = `${kerberosKeytab}-1`;
const secondKerberosName = `${kerberosName}-2`;
const secondKerberosRealm = `${kerberosRealm}-2`;
const secondKerberosPrincipal = `${kerberosPrincipal}-2`;
const secondKerberosKeytab = `${kerberosKeytab}-2`;
const defaultPolicy = "DEFAULT";
const weeklyPolicy = "EVICT_WEEKLY";
const dailyPolicy = "EVICT_DAILY";
const lifespanPolicy = "MAX_LIFESPAN";
const noCachePolicy = "NO_CACHE";
const defaultKerberosDay = "Sunday";
const defaultKerberosHour = "00";
const defaultKerberosMinute = "00";
const newKerberosDay = "Wednesday";
const newKerberosHour = "15";
const newKerberosMinute = "55";
const maxLifespan = 5;
const addProviderMenu = "Add new provider";
const createdSuccessMessage = "User federation provider successfully created";
const savedSuccessMessage = "User federation provider successfully saved";
const deletedSuccessMessage = "The user federation provider has been deleted.";
const deleteModalTitle = "Delete user federation provider?";
const disableModalTitle = "Disable user federation provider?";
const changeSuccessMsg =
"Successfully changed the priority order of user federation providers";
describe("User Fed Kerberos tests", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToUserFederation();
});
it("Should create Kerberos provider from empty state", () => {
// if tests don't start at empty state, e.g. user has providers configured locally,
// create a new card from the card view instead
cy.get("body").then(($body) => {
if ($body.find(`[data-testid=kerberos-card]`).length > 0) {
providersPage.clickNewCard(provider);
} else {
providersPage.clickMenuCommand(addProviderMenu, initCapProvider);
}
});
providersPage.fillKerberosRequiredData(
firstKerberosName,
firstKerberosRealm,
firstKerberosPrincipal,
firstKerberosKeytab,
);
providersPage.save(provider);
masthead.checkNotificationMessage(createdSuccessMessage);
sidebarPage.goToUserFederation();
});
it("Should enable debug, password authentication, and first login", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.toggleSwitch(providersPage.debugSwitch);
providersPage.toggleSwitch(providersPage.passwordAuthSwitch);
providersPage.toggleSwitch(providersPage.firstLoginSwitch);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstKerberosName);
providersPage.verifyToggle(providersPage.debugSwitch, "on");
providersPage.verifyToggle(providersPage.passwordAuthSwitch, "on");
providersPage.verifyToggle(providersPage.firstLoginSwitch, "on");
});
it("Should set cache policy to evict_daily", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.selectCacheType(dailyPolicy);
providersPage.changeCacheTime("hour", newKerberosHour);
providersPage.changeCacheTime("minute", newKerberosMinute);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstKerberosName);
expect(cy.contains(dailyPolicy).should("exist"));
expect(cy.contains(defaultPolicy).should("not.exist"));
});
it("Should set cache policy to default", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.selectCacheType(defaultPolicy);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstKerberosName);
expect(cy.contains(defaultPolicy).should("exist"));
expect(cy.contains(dailyPolicy).should("not.exist"));
});
it("Should set cache policy to evict_weekly", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.selectCacheType(weeklyPolicy);
providersPage.changeCacheTime("day", newKerberosDay);
providersPage.changeCacheTime("hour", newKerberosHour);
providersPage.changeCacheTime("minute", newKerberosMinute);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstKerberosName);
expect(cy.contains(weeklyPolicy).should("exist"));
expect(cy.contains(defaultPolicy).should("not.exist"));
});
it("Should set cache policy to max_lifespan", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.selectCacheType(lifespanPolicy);
providersPage.fillMaxLifespanData(maxLifespan);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstKerberosName);
expect(cy.contains(lifespanPolicy).should("exist"));
expect(cy.contains(weeklyPolicy).should("not.exist"));
});
it("Should set cache policy to no_cache", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.selectCacheType(noCachePolicy);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstKerberosName);
expect(cy.contains(noCachePolicy).should("exist"));
expect(cy.contains(lifespanPolicy).should("not.exist"));
});
it("Should edit existing Kerberos provider and cancel", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.selectCacheType(weeklyPolicy);
providersPage.changeCacheTime("day", defaultKerberosDay);
providersPage.changeCacheTime("hour", defaultKerberosHour);
providersPage.changeCacheTime("minute", defaultKerberosMinute);
providersPage.cancel(provider);
providersPage.clickExistingCard(firstKerberosName);
providersPage.selectCacheType(weeklyPolicy);
providersPage.verifyChangedHourInput(newKerberosHour, defaultKerberosHour);
sidebarPage.goToUserFederation();
});
it("Should disable an existing Kerberos provider", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.disableEnabledSwitch(initCapProvider);
modalUtils.checkModalTitle(disableModalTitle).confirmModal();
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
expect(cy.contains("Disabled").should("exist"));
});
it("Should enable an existing previously-disabled Kerberos provider", () => {
providersPage.clickExistingCard(firstKerberosName);
providersPage.enableEnabledSwitch(initCapProvider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
expect(cy.contains("Enabled").should("exist"));
});
it("Should create new Kerberos provider using the New Provider dropdown", () => {
providersPage.clickMenuCommand(addProviderMenu, initCapProvider);
providersPage.fillKerberosRequiredData(
secondKerberosName,
secondKerberosRealm,
secondKerberosPrincipal,
secondKerberosKeytab,
);
providersPage.save(provider);
masthead.checkNotificationMessage(createdSuccessMessage);
sidebarPage.goToUserFederation();
});
it.skip("Should change the priority order of Kerberos providers", () => {
const priorityDialog = new PriorityDialog();
const providers = [firstKerberosName, secondKerberosName];
sidebarPage.goToUserFederation();
providersPage.clickMenuCommand(addProviderMenu, initCapProvider);
sidebarPage.goToUserFederation();
priorityDialog.openDialog().checkOrder(providers);
priorityDialog.clickSave();
masthead.checkNotificationMessage(changeSuccessMsg, true);
});
it("Should delete a Kerberos provider from card view using the card's menu", () => {
providersPage.deleteCardFromCard(secondKerberosName);
modalUtils.checkModalTitle(deleteModalTitle).confirmModal();
masthead.checkNotificationMessage(deletedSuccessMessage);
});
it("Should delete a Kerberos provider using the Settings view's Action menu", () => {
providersPage.deleteCardFromMenu(firstKerberosName);
modalUtils.checkModalTitle(deleteModalTitle).confirmModal();
masthead.checkNotificationMessage(deletedSuccessMessage);
});
});

View File

@@ -1,237 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import GroupModal from "../support/pages/admin-ui/manage/groups/GroupModal";
import ProviderPage from "../support/pages/admin-ui/manage/providers/ProviderPage";
import CreateClientPage from "../support/pages/admin-ui/manage/clients/CreateClientPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import GroupPage from "../support/pages/admin-ui/manage/groups/GroupPage";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const listingPage = new ListingPage();
const groupModal = new GroupModal();
const createClientPage = new CreateClientPage();
const groupPage = new GroupPage();
const providersPage = new ProviderPage();
const modalUtils = new ModalUtils();
const provider = "ldap";
const allCapProvider = provider.toUpperCase();
const ldapName = "ldap-mappers-testing";
const ldapVendor = "Active Directory";
// connection and authentication settings
const connectionUrlValid = "ldap://localhost:3004";
const bindTypeSimple = "simple";
const truststoreSpiAlways = "Always";
const connectionTimeoutTwoSecs = "2000";
const bindDnCnDc = "cn=user,dc=test";
const bindCredsValid = "user";
// ldap searching and updating
const editModeReadOnly = "READ_ONLY";
const firstUsersDn = "user-dn-1";
const firstUserLdapAtt = "uid";
const firstRdnLdapAtt = "uid";
const firstUuidLdapAtt = "entryUUID";
const firstUserObjClasses = "inetOrgPerson, organizationalPerson";
const addProviderMenu = "Add new provider";
const providerCreatedSuccess = "User federation provider successfully created";
const mapperCreatedSuccess = "Mapping successfully created";
const providerDeleteSuccess = "The user federation provider has been deleted.";
const providerDeleteTitle = "Delete user federation provider?";
const mapperDeletedSuccess = "Mapping successfully deleted";
const mapperDeleteTitle = "Delete mapping?";
const groupDeleteTitle = "Delete group?";
const groupCreatedSuccess = "Group created";
const groupDeletedSuccess = "Group deleted";
const clientCreatedSuccess = "Client created successfully";
const clientDeletedSuccess = "The client has been deleted";
const roleCreatedSuccess = "Role created";
const groupName = "aa-uf-mappers-group";
const clientName = "aa-uf-mappers-client";
const roleName = "aa-uf-mappers-role";
// mapperType variables
const hcAttMapper = "hardcoded-attribute-mapper";
const hcLdapGroupMapper = "hardcoded-ldap-group-mapper";
const hcLdapAttMapper = "hardcoded-ldap-attribute-mapper";
const roleLdapMapper = "role-ldap-mapper";
const hcLdapRoleMapper = "hardcoded-ldap-role-mapper";
// Used by "Delete default mappers" test
const creationDateMapper = "creation date";
const emailMapper = "email";
const lastNameMapper = "last name";
const modifyDateMapper = "modify date";
describe("User Fed LDAP mapper tests", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToUserFederation();
});
it("Create LDAP provider from empty state", () => {
// if tests don't start at empty state, e.g. user has providers configured locally,
// create a new card from the card view instead
cy.get("body").then(($body) => {
if ($body.find(`[data-testid=ldap-card]`).length > 0) {
providersPage.clickNewCard(provider);
} else {
providersPage.clickMenuCommand(addProviderMenu, allCapProvider);
}
});
providersPage.fillLdapGeneralData(ldapName, ldapVendor);
providersPage.fillLdapConnectionData(
connectionUrlValid,
bindTypeSimple,
truststoreSpiAlways,
connectionTimeoutTwoSecs,
bindDnCnDc,
bindCredsValid,
);
providersPage.toggleSwitch(providersPage.enableStartTls);
providersPage.toggleSwitch(providersPage.connectionPooling);
providersPage.fillLdapSearchingData(
editModeReadOnly,
firstUsersDn,
firstUserLdapAtt,
firstRdnLdapAtt,
firstUuidLdapAtt,
firstUserObjClasses,
);
providersPage.save(provider);
masthead.checkNotificationMessage(providerCreatedSuccess);
sidebarPage.goToUserFederation();
});
// create a new group
it("Create group", () => {
sidebarPage.goToGroups();
groupPage.openCreateGroupModal(true);
groupModal.setGroupNameInput(groupName).create();
masthead.checkNotificationMessage(groupCreatedSuccess);
});
// create a new client and then new role for that client
it("Create client and role", () => {
sidebarPage.goToClients();
listingPage.goToCreateItem();
createClientPage
.selectClientType("OpenID Connect")
.fillClientData(clientName)
.continue()
.continue()
.save();
masthead.checkNotificationMessage(clientCreatedSuccess);
providersPage.createRole(roleName);
masthead.checkNotificationMessage(roleCreatedSuccess);
sidebarPage.goToClients();
listingPage.searchItem(clientName).itemExist(clientName);
});
// delete four default mappers
it("Delete default mappers", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
listingPage.itemExist(creationDateMapper).deleteItem(creationDateMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(creationDateMapper, false);
listingPage.itemExist(emailMapper).deleteItem(emailMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(emailMapper, false);
listingPage.itemExist(lastNameMapper).deleteItem(lastNameMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(lastNameMapper, false);
listingPage.itemExist(modifyDateMapper).deleteItem(modifyDateMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(modifyDateMapper, false);
});
// create one of each hardcoded mapper type
it("Create hardcoded attribute mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(hcAttMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(hcAttMapper, true);
});
it("Create hardcoded ldap group mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(hcLdapGroupMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(hcLdapGroupMapper, true);
});
it("Create hardcoded ldap attribute mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(hcLdapAttMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(hcLdapAttMapper, true);
});
it("Create hardcoded ldap role mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(hcLdapRoleMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(hcLdapRoleMapper, true);
});
it("Create role ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(roleLdapMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(roleLdapMapper, true);
});
// *** test cleanup ***
it("Cleanup - delete LDAP provider", () => {
providersPage.deleteCardFromMenu(ldapName);
modalUtils.checkModalTitle(providerDeleteTitle).confirmModal();
masthead.checkNotificationMessage(providerDeleteSuccess);
});
it("Cleanup - delete group", () => {
sidebarPage.goToGroups();
listingPage.deleteItem(groupName);
modalUtils.checkModalTitle(groupDeleteTitle).confirmModal();
masthead.checkNotificationMessage(groupDeletedSuccess);
});
it("Cleanup - delete client", () => {
sidebarPage.goToClients();
listingPage.deleteItem(clientName);
modalUtils.checkModalTitle(`Delete ${clientName} ?`).confirmModal();
masthead.checkNotificationMessage(clientDeletedSuccess);
});
});

View File

@@ -1,276 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import ProviderPage from "../support/pages/admin-ui/manage/providers/ProviderPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const listingPage = new ListingPage();
const providersPage = new ProviderPage();
const modalUtils = new ModalUtils();
const provider = "ldap";
const allCapProvider = provider.toUpperCase();
const ldapName = "ldap-mappers-testing";
const ldapVendor = "Active Directory";
// connection and authentication settings
const connectionUrlValid = "ldap://localhost:3004";
const bindTypeSimple = "simple";
const truststoreSpiAlways = "Always";
const connectionTimeoutTwoSecs = "2000";
const bindDnCnDc = "cn=user,dc=test";
const bindCredsValid = "user";
// ldap searching and updating
const editModeReadOnly = "READ_ONLY";
const firstUsersDn = "user-dn-1";
const firstUserLdapAtt = "uid";
const firstRdnLdapAtt = "uid";
const firstUuidLdapAtt = "entryUUID";
const firstUserObjClasses = "inetOrgPerson, organizationalPerson";
const addProviderMenu = "Add new provider";
const providerCreatedSuccess = "User federation provider successfully created";
const mapperCreatedSuccess = "Mapping successfully created";
const mapperUpdatedSuccess = "Mapping successfully updated";
const providerDeleteSuccess = "The user federation provider has been deleted.";
const providerDeleteTitle = "Delete user federation provider?";
const mapperDeletedSuccess = "Mapping successfully deleted";
const mapperDeleteTitle = "Delete mapping?";
// mapperType variables
const msadUserAcctMapper = "msad-user-account-control-mapper";
const msadLdsUserAcctMapper = "msad-lds-user-account-control-mapper";
const userAttLdapMapper = "user-attribute-ldap-mapper";
const fullNameLdapMapper = "full-name-ldap-mapper";
const groupLdapMapper = "group-ldap-mapper";
const certLdapMapper = "certificate-ldap-mapper";
const mapperNames = [
`${msadUserAcctMapper}-test`,
`${msadLdsUserAcctMapper}-test`,
`${userAttLdapMapper}-test`,
`${fullNameLdapMapper}-test`,
`${groupLdapMapper}-test`,
];
const multiMapperNames = mapperNames.slice(2);
const singleMapperName = mapperNames.slice(4);
const uniqueSearchTerm = "group";
const multipleSearchTerm = "ldap";
const nonexistingSearchTerm = "redhat";
// Used by "Delete default mappers" test
const creationDateMapper = "creation date";
const emailMapper = "email";
const lastNameMapper = "last name";
const modifyDateMapper = "modify date";
const usernameMapper = "username";
const firstNameMapper = "first name";
const MsadAccountControlsMapper = "MSAD account controls";
describe("User Fed LDAP mapper tests", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToUserFederation();
});
it("Create LDAP provider from empty state", () => {
// if tests don't start at empty state, e.g. user has providers configured locally,
// create a new card from the card view instead
cy.get("body").then(($body) => {
if ($body.find(`[data-testid=ldap-card]`).length > 0) {
providersPage.clickNewCard(provider);
} else {
providersPage.clickMenuCommand(addProviderMenu, allCapProvider);
}
});
providersPage.fillLdapGeneralData(ldapName, ldapVendor);
providersPage.fillLdapConnectionData(
connectionUrlValid,
bindTypeSimple,
truststoreSpiAlways,
connectionTimeoutTwoSecs,
bindDnCnDc,
bindCredsValid,
);
providersPage.toggleSwitch(providersPage.enableStartTls);
providersPage.toggleSwitch(providersPage.connectionPooling);
providersPage.fillLdapSearchingData(
editModeReadOnly,
firstUsersDn,
firstUserLdapAtt,
firstRdnLdapAtt,
firstUuidLdapAtt,
firstUserObjClasses,
);
providersPage.save(provider);
masthead.checkNotificationMessage(providerCreatedSuccess);
sidebarPage.goToUserFederation();
});
// delete default mappers
it("Delete default mappers", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
listingPage.itemExist(creationDateMapper).deleteItem(creationDateMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(creationDateMapper, false);
listingPage.itemExist(emailMapper).deleteItem(emailMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(emailMapper, false);
listingPage.itemExist(lastNameMapper).deleteItem(lastNameMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(lastNameMapper, false);
listingPage.itemExist(modifyDateMapper).deleteItem(modifyDateMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(modifyDateMapper, false);
listingPage.itemExist(usernameMapper).deleteItem(usernameMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(usernameMapper, false);
listingPage.itemExist(firstNameMapper).deleteItem(firstNameMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
listingPage.itemExist(firstNameMapper, false);
listingPage
.itemExist(MsadAccountControlsMapper)
.deleteItem(MsadAccountControlsMapper);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess, true);
});
// mapper CRUD tests
// create mapper
it("Create certificate ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(certLdapMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(certLdapMapper, true);
});
// update mapper
it("Update certificate ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
listingPage.goToItemDetails(`${certLdapMapper}-test`);
providersPage.updateMapper(certLdapMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperUpdatedSuccess);
});
// delete mapper
it("Delete certificate ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
listingPage.deleteItem(`${certLdapMapper}-test`);
modalUtils.checkModalTitle(mapperDeleteTitle).confirmModal();
masthead.checkNotificationMessage(mapperDeletedSuccess);
});
// create one of each non-hardcoded mapper type except
// certificate ldap mapper which was already tested in CRUD section
it("Create user account control mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(msadUserAcctMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(msadUserAcctMapper, true);
});
it("Create msad lds user account control mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(msadLdsUserAcctMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(msadLdsUserAcctMapper, true);
});
it("Create user attribute ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(userAttLdapMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(userAttLdapMapper, true);
});
it("Create full name ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(fullNameLdapMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(fullNameLdapMapper, true);
});
it("Create group ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(groupLdapMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(groupLdapMapper, true);
});
it("Should return one search result for mapper with unique string", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
listingPage.searchItem(uniqueSearchTerm, false);
singleMapperName.map((mapperName) => listingPage.itemExist(mapperName));
});
it("Should return multiple search results for mappers that share common string", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
listingPage.searchItem(multipleSearchTerm, false);
multiMapperNames.map((mapperName) => listingPage.itemExist(mapperName));
});
it("Should return all mappers in search results when no string is specified", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
listingPage.searchItem("", false);
mapperNames.map((mapperName) => listingPage.itemExist(mapperName));
});
it("Should return no search results for string that does not exist in any mappers", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
listingPage.searchItem(nonexistingSearchTerm, false);
listingPage.assertNoResults();
});
// *** test cleanup ***
it("Cleanup - delete LDAP provider", () => {
providersPage.deleteCardFromMenu(ldapName);
modalUtils.checkModalTitle(providerDeleteTitle).confirmModal();
masthead.checkNotificationMessage(providerDeleteSuccess);
});
});

View File

@@ -1,576 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import ProviderPage from "../support/pages/admin-ui/manage/providers/ProviderPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import adminClient from "../support/util/AdminClient";
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const providersPage = new ProviderPage();
const modalUtils = new ModalUtils();
const provider = "ldap";
const allCapProvider = provider.toUpperCase();
const firstLdapName = "my-ldap";
const firstLdapVendor = "Active Directory";
const secondLdapName = `${firstLdapName}-2`;
const secondLdapVendor = "Other";
const updatedLdapName = `${firstLdapName}-updated`;
// connection and authentication settings
const connectionUrlValid = "ldap://localhost:3004";
const bindTypeSimple = "simple";
const truststoreSpiAlways = "Always";
const connectionTimeoutTwoSecs = "2000";
const bindDnCnDc = "cn=user,dc=test";
const bindCredsValid = "user";
const connectionUrlInvalid = "ldap://nowhere.com";
const bindTypeNone = "none";
const truststoreSpiNever = "Never";
const bindDnCnOnly = "cn=read-only-admin";
const bindCredsInvalid = "not-my-password";
// kerberos integration settings
const kerberosRealm = "FOO.ORG";
const serverPrincipal = "HTTP/host.foo.org@FOO.ORG";
const keyTab = "/etc/krb5.keytab";
// ldap synchronization settings
const batchSize = "100";
const fullSyncPeriod = "604800";
const userSyncPeriod = "86400";
// ldap searching and updating
const editModeReadOnly = "READ_ONLY";
const editModeWritable = "WRITABLE";
const editModeUnsynced = "UNSYNCED";
const firstUsersDn = "user-dn-1";
const firstUserLdapAtt = "uid";
const firstRdnLdapAtt = "uid";
const firstUuidLdapAtt = "entryUUID";
const firstUserObjClasses = "inetOrgPerson, organizationalPerson";
const firstUserLdapFilter = "(first-filter)";
const firstReadTimeout = "5000";
const searchScopeOneLevel = "One Level";
const searchScopeSubtree = "Subtree";
const secondUsersDn = "user-dn-2";
const secondUserLdapAtt = "cn";
const secondRdnLdapAtt = "cn";
const secondUuidLdapAtt = "objectGUID";
const secondUserObjClasses = "person, organizationalPerson, user";
const secondUserLdapFilter = "(second-filter)";
const secondReadTimeout = "5000";
const defaultPolicy = "DEFAULT";
const weeklyPolicy = "EVICT_WEEKLY";
const dailyPolicy = "EVICT_DAILY";
const lifespanPolicy = "MAX_LIFESPAN";
const noCachePolicy = "NO_CACHE";
const defaultLdapDay = "Sunday";
const defaultLdapHour = "00";
const defaultLdapMinute = "00";
const newLdapDay = "Wednesday";
const newLdapHour = "15";
const newLdapMinute = "55";
const maxLifespan = 5;
const addProviderMenu = "Add new provider";
const createdSuccessMessage = "User federation provider successfully created";
const savedSuccessMessage = "User federation provider successfully saved";
const deletedSuccessMessage = "The user federation provider has been deleted.";
const deleteModalTitle = "Delete user federation provider?";
const disableModalTitle = "Disable user federation provider?";
const validatePasswordPolicyFailMessage =
"User federation provider could not be saved: Validate Password Policy is applicable only with WRITABLE edit mode";
const userImportingDisabledFailMessage =
"User federation provider could not be saved: Can not disable Importing users when LDAP provider mode is UNSYNCED";
const ldapTestSuccessMsg = "Successfully connected to LDAP";
const ldapTestFailMsg = "Error when trying to connect to LDAP: 'UnknownHost'";
describe("User Federation LDAP tests", () => {
const realmName = `ldap-realm-${crypto.randomUUID()}`;
before(() => adminClient.createRealm(realmName));
after(() => adminClient.deleteRealm(realmName));
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToRealm(realmName);
sidebarPage.goToUserFederation();
});
it("Should create LDAP provider from empty state", () => {
// if tests don't start at empty state, e.g. user has providers configured locally,
// create a new card from the card view instead
cy.get("body").then(($body) => {
if ($body.find(`[data-testid=ldap-card]`).length > 0) {
providersPage.clickNewCard(provider);
} else {
providersPage.clickMenuCommand(addProviderMenu, allCapProvider);
}
});
providersPage.fillLdapGeneralData(firstLdapName, firstLdapVendor);
providersPage.fillLdapConnectionData(
connectionUrlInvalid,
bindTypeSimple,
truststoreSpiNever,
connectionTimeoutTwoSecs,
bindDnCnOnly,
bindCredsInvalid,
);
providersPage.fillLdapSearchingData(
editModeReadOnly,
firstUsersDn,
firstUserLdapAtt,
firstRdnLdapAtt,
firstUuidLdapAtt,
firstUserObjClasses,
firstUserLdapFilter,
searchScopeOneLevel,
firstReadTimeout,
);
providersPage.save(provider);
masthead.checkNotificationMessage(createdSuccessMessage);
sidebarPage.goToUserFederation();
});
it("Should fail updating advanced settings", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.toggleSwitch(providersPage.ldapv3PwSwitch);
providersPage.toggleSwitch(providersPage.validatePwPolicySwitch);
providersPage.toggleSwitch(providersPage.trustEmailSwitch);
providersPage.save(provider);
masthead.checkNotificationMessage(validatePasswordPolicyFailMessage);
sidebarPage.goToUserFederation();
});
it("Should update advanced settings", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.toggleSwitch(providersPage.ldapv3PwSwitch);
providersPage.toggleSwitch(providersPage.validatePwPolicySwitch);
providersPage.toggleSwitch(providersPage.trustEmailSwitch);
providersPage.fillLdapSearchingData(
editModeWritable,
secondUsersDn,
secondUserLdapAtt,
secondRdnLdapAtt,
secondUuidLdapAtt,
secondUserObjClasses,
);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
providersPage.verifyToggle(providersPage.ldapv3PwSwitch, "on");
providersPage.verifyToggle(providersPage.validatePwPolicySwitch, "on");
providersPage.verifyToggle(providersPage.trustEmailSwitch, "on");
});
it("Should set cache policy to evict_daily", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(dailyPolicy);
providersPage.changeCacheTime("hour", newLdapHour);
providersPage.changeCacheTime("minute", newLdapMinute);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
expect(cy.contains(dailyPolicy).should("exist"));
expect(cy.contains(defaultPolicy).should("not.exist"));
});
it("Should set cache policy to default", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(defaultPolicy);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
expect(cy.contains(defaultPolicy).should("exist"));
expect(cy.contains(dailyPolicy).should("not.exist"));
});
it("Should set cache policy to evict_weekly", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(weeklyPolicy);
providersPage.changeCacheTime("day", newLdapDay);
providersPage.changeCacheTime("hour", newLdapHour);
providersPage.changeCacheTime("minute", newLdapMinute);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
expect(cy.contains(weeklyPolicy).should("exist"));
expect(cy.contains(defaultPolicy).should("not.exist"));
});
it("Update connection and authentication settings and save", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.fillLdapConnectionData(
connectionUrlInvalid,
bindTypeNone,
truststoreSpiNever,
connectionTimeoutTwoSecs,
);
providersPage.toggleSwitch(providersPage.enableStartTls);
providersPage.toggleSwitch(providersPage.connectionPooling);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
// now verify
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
providersPage.verifyTextField(
providersPage.connectionUrlInput,
connectionUrlInvalid,
);
providersPage.verifyTextField(
providersPage.connectionTimeoutInput,
connectionTimeoutTwoSecs,
);
providersPage.verifySelect(
providersPage.truststoreSpiInput,
truststoreSpiNever,
);
providersPage.verifySelect(providersPage.bindTypeInput, bindTypeNone);
providersPage.verifyToggle(providersPage.enableStartTls, "on");
providersPage.verifyToggle(providersPage.connectionPooling, "on");
sidebarPage.goToUserFederation();
});
it("Should fail connection and authentication tests", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.testConnection();
masthead.checkNotificationMessage(ldapTestFailMsg);
providersPage.testAuthorization();
masthead.checkNotificationMessage(ldapTestFailMsg);
sidebarPage.goToUserFederation();
});
it("Should make changes and pass connection and authentication tests", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.fillLdapConnectionData(
connectionUrlValid,
bindTypeSimple,
truststoreSpiAlways,
connectionTimeoutTwoSecs,
bindDnCnDc,
bindCredsValid,
);
providersPage.toggleSwitch(providersPage.enableStartTls);
providersPage.toggleSwitch(providersPage.connectionPooling);
providersPage.save(provider);
providersPage.testConnection();
masthead.checkNotificationMessage(ldapTestSuccessMsg);
providersPage.testAuthorization();
masthead.checkNotificationMessage(ldapTestSuccessMsg);
sidebarPage.goToUserFederation();
});
it("Should update Kerberos integration settings and save", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.toggleSwitch(providersPage.allowKerberosAuth);
providersPage.toggleSwitch(providersPage.debug);
providersPage.toggleSwitch(providersPage.useKerberosForPwAuth);
providersPage.fillTextField(
providersPage.ldapKerberosRealmInput,
kerberosRealm,
);
providersPage.fillTextField(
providersPage.ldapServerPrincipalInput,
serverPrincipal,
);
providersPage.fillTextField(providersPage.ldapKeyTabInput, keyTab);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
// now verify
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
providersPage.verifyTextField(
providersPage.ldapKerberosRealmInput,
kerberosRealm,
);
providersPage.verifyTextField(
providersPage.ldapServerPrincipalInput,
serverPrincipal,
);
providersPage.verifyTextField(providersPage.ldapKeyTabInput, keyTab);
providersPage.verifyToggle(providersPage.allowKerberosAuth, "on");
providersPage.verifyToggle(providersPage.debug, "on");
providersPage.verifyToggle(providersPage.useKerberosForPwAuth, "on");
sidebarPage.goToUserFederation();
});
it("Should update Synchronization settings and save", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.toggleSwitch(providersPage.importUsers);
providersPage.toggleSwitch(providersPage.periodicFullSync);
providersPage.toggleSwitch(providersPage.periodicUsersSync);
providersPage.fillTextField(providersPage.ldapBatchSizeInput, batchSize);
providersPage.fillTextField(
providersPage.ldapFullSyncPeriodInput,
fullSyncPeriod,
);
providersPage.fillTextField(
providersPage.ldapUsersSyncPeriodInput,
userSyncPeriod,
);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
// now verify
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
providersPage.verifyTextField(providersPage.ldapBatchSizeInput, batchSize);
providersPage.verifyTextField(
providersPage.ldapFullSyncPeriodInput,
fullSyncPeriod,
);
providersPage.verifyTextField(
providersPage.ldapUsersSyncPeriodInput,
userSyncPeriod,
);
providersPage.verifyToggle(providersPage.periodicFullSync, "on");
providersPage.verifyToggle(providersPage.periodicUsersSync, "on");
providersPage.verifyToggle(providersPage.importUsers, "on");
sidebarPage.goToUserFederation();
});
it("Should update LDAP searching and updating settings and save", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.fillLdapSearchingData(
editModeWritable,
secondUsersDn,
secondUserLdapAtt,
secondRdnLdapAtt,
secondUuidLdapAtt,
secondUserObjClasses,
secondUserLdapFilter,
searchScopeSubtree,
secondReadTimeout,
);
providersPage.toggleSwitch(providersPage.ldapPagination);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
// now verify
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
providersPage.verifySelect(
providersPage.ldapEditModeInput,
editModeWritable,
);
providersPage.verifyTextField(
providersPage.ldapUsersDnInput,
secondUsersDn,
);
providersPage.verifyTextField(
providersPage.ldapUserLdapAttInput,
secondUserLdapAtt,
);
providersPage.verifyTextField(
providersPage.ldapRdnLdapAttInput,
secondRdnLdapAtt,
);
providersPage.verifyTextField(
providersPage.ldapUuidLdapAttInput,
secondUuidLdapAtt,
);
providersPage.verifyTextField(
providersPage.ldapUserObjClassesInput,
secondUserObjClasses,
);
providersPage.verifyTextField(
providersPage.ldapUserLdapFilter,
secondUserLdapFilter,
);
providersPage.verifySelect(
providersPage.ldapSearchScopeInput,
searchScopeSubtree,
);
providersPage.verifyTextField(
providersPage.ldapReadTimeout,
secondReadTimeout,
);
providersPage.verifyToggle(providersPage.ldapPagination, "on");
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
providersPage.fillSelect(providersPage.ldapEditModeInput, editModeUnsynced);
providersPage.toggleSwitch(providersPage.importUsers);
providersPage.save(provider);
masthead.checkNotificationMessage(validatePasswordPolicyFailMessage);
providersPage.toggleSwitch(providersPage.importUsers);
providersPage.toggleSwitch(providersPage.validatePwPolicySwitch);
providersPage.save(provider);
masthead.checkNotificationMessage(userImportingDisabledFailMessage);
providersPage.toggleSwitch(providersPage.importUsers);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
// now verify
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
providersPage.verifySelect(
providersPage.ldapEditModeInput,
editModeUnsynced,
);
});
it("Should update display name", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.fillLdapGeneralData(updatedLdapName);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(updatedLdapName);
sidebarPage.goToUserFederation();
});
it("Should update existing LDAP provider and cancel", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(weeklyPolicy);
providersPage.changeCacheTime("day", defaultLdapDay);
providersPage.changeCacheTime("hour", defaultLdapHour);
providersPage.changeCacheTime("minute", defaultLdapMinute);
providersPage.cancel(provider);
providersPage.clickExistingCard(updatedLdapName);
providersPage.selectCacheType(weeklyPolicy);
providersPage.verifyChangedHourInput(newLdapHour, defaultLdapHour);
sidebarPage.goToUserFederation();
});
it("Should set cache policy to max_lifespan", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(lifespanPolicy);
providersPage.fillMaxLifespanData(maxLifespan);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
expect(cy.contains(lifespanPolicy).should("exist"));
expect(cy.contains(weeklyPolicy).should("not.exist"));
});
it("Should set cache policy to no_cache", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.selectCacheType(noCachePolicy);
providersPage.save(provider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
providersPage.clickExistingCard(firstLdapName);
expect(cy.contains(noCachePolicy).should("exist"));
expect(cy.contains(lifespanPolicy).should("not.exist"));
});
it("Should disable an existing LDAP provider", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.disableEnabledSwitch(allCapProvider);
modalUtils.checkModalTitle(disableModalTitle).confirmModal();
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
expect(cy.contains("Disabled").should("exist"));
});
it("Should enable a previously-disabled LDAP provider", () => {
providersPage.clickExistingCard(firstLdapName);
providersPage.enableEnabledSwitch(allCapProvider);
masthead.checkNotificationMessage(savedSuccessMessage);
sidebarPage.goToUserFederation();
expect(cy.contains("Enabled").should("exist"));
});
it("Should create new LDAP provider using New Provider dropdown", () => {
providersPage.clickMenuCommand(addProviderMenu, allCapProvider);
providersPage.fillLdapGeneralData(secondLdapName, secondLdapVendor);
providersPage.fillLdapConnectionData(
connectionUrlValid,
bindTypeSimple,
truststoreSpiNever,
connectionTimeoutTwoSecs,
bindDnCnOnly,
bindCredsInvalid,
);
providersPage.fillLdapSearchingData(
editModeWritable,
secondUsersDn,
secondUserLdapAtt,
secondRdnLdapAtt,
secondUuidLdapAtt,
secondUserObjClasses,
);
providersPage.save(provider);
masthead.checkNotificationMessage(createdSuccessMessage);
sidebarPage.goToUserFederation();
});
it("Should delete LDAP provider from card view using card menu", () => {
providersPage.deleteCardFromCard(secondLdapName);
modalUtils.checkModalTitle(deleteModalTitle).confirmModal();
masthead.checkNotificationMessage(deletedSuccessMessage);
});
it("Should delete LDAP provider using Settings view Action menu", () => {
providersPage.deleteCardFromMenu(firstLdapName);
modalUtils.checkModalTitle(deleteModalTitle).confirmModal();
masthead.checkNotificationMessage(deletedSuccessMessage);
});
});

View File

@@ -1,19 +0,0 @@
import LoginPage from "../support/pages/LoginPage";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
describe("Accessibility tests for user federation", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToUserFederation();
cy.injectAxe();
});
it("Check a11y violations on load/ user federation", () => {
cy.checkA11y();
});
});

View File

@@ -1,100 +0,0 @@
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import adminClient from "../support/util/AdminClient";
import {
DefaultUserAttribute,
UserFilterType,
} from "../support/pages/admin-ui/manage/users/UsersListingPage";
import UsersPage from "../support/pages/admin-ui/manage/users/UsersPage";
describe("Query by user attributes", () => {
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const usersPage = new UsersPage();
const listingPage = usersPage.listing();
const emailSuffix = "@example.org";
const user1Username = "user-attrs-1";
const user1FirstName = "John";
const user1LastName = "Doe";
const user1Pwd = "pwd";
const user2Username = "user-attrs-2";
const user2FirstName = "Jane";
const user2LastName = user1LastName;
before(async () => {
await cleanupTestData();
const user1 = await adminClient.createUser({
username: user1Username,
credentials: [
{
type: "password",
value: user1Pwd,
},
],
email: user1Username + emailSuffix,
firstName: user1FirstName,
lastName: user1LastName,
enabled: true,
});
const user1Id = user1.id!;
await adminClient.addClientRoleToUser(user1Id, "master-realm", [
"view-users",
]);
await adminClient.createUser({
username: user2Username,
email: user2Username + emailSuffix,
firstName: user2FirstName,
lastName: user2LastName,
enabled: true,
});
});
beforeEach(() => {
loginPage.logIn(user1Username, user1Pwd);
keycloakBefore();
sidebarPage.goToUsers();
});
after(async () => {
await cleanupTestData();
});
async function cleanupTestData() {
await adminClient.deleteUser(user1Username, true);
await adminClient.deleteUser(user2Username, true);
}
it("Query with one attribute condition", () => {
listingPage
.selectUserSearchFilter(UserFilterType.AttributeSearch)
.openUserAttributesSearchForm()
.addUserAttributeSearchCriteria(
DefaultUserAttribute.lastName,
user1LastName,
)
.triggerAttributesSearch()
.itemExist(user1Username, true)
.itemExist(user2Username, true);
});
it("Query with two attribute conditions", () => {
listingPage
.selectUserSearchFilter(UserFilterType.AttributeSearch)
.openUserAttributesSearchForm()
.addUserAttributeSearchCriteria(
DefaultUserAttribute.lastName,
user1LastName,
)
.addUserAttributeSearchCriteria(
DefaultUserAttribute.firstName,
user1FirstName,
)
.triggerAttributesSearch()
.itemExist(user1Username, true)
.itemExist(user2Username, false);
});
});

View File

@@ -1,84 +0,0 @@
import UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
import LoginPage from "../support/pages/LoginPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import UsersPage from "../support/pages/admin-ui/manage/users/UsersPage";
import UserDetailsPage from "../support/pages/admin-ui/manage/users/user_details/UserDetailsPage";
import adminClient from "../support/util/AdminClient";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const usersPage = new UsersPage();
const userDetailsPage = new UserDetailsPage();
const masthead = new Masthead();
const modal = new ModalUtils();
const createUser = (fields: UserRepresentation) =>
cy
.wrap(null)
.then(() =>
adminClient.createUser({ username: crypto.randomUUID(), ...fields }),
);
const deleteUser = (username: string) =>
cy.wrap(null).then(() => adminClient.deleteUser(username));
describe("User enable/disable", () => {
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToUsers();
});
it("disables a user", () => {
createUser({ enabled: true }).then(({ username }) => {
usersPage.goToUserDetailsPage(username!);
userDetailsPage.assertEnabled(username!);
userDetailsPage.toggleEnabled(username!);
modal.confirmModal();
masthead.checkNotificationMessage("The user has been saved");
cy.wait(1000);
userDetailsPage.assertDisabled(username!);
return deleteUser(username!);
});
});
it("enables a user", () => {
createUser({ enabled: false }).then(({ username }) => {
usersPage.goToUserDetailsPage(username!);
userDetailsPage.assertDisabled(username!);
userDetailsPage.toggleEnabled(username!);
masthead.checkNotificationMessage("The user has been saved");
cy.wait(1000);
userDetailsPage.assertEnabled(username!);
return deleteUser(username!);
});
});
// See: https://github.com/keycloak/keycloak/issues/19647
it("ensures submitting doesn't reset the enabled state", () => {
createUser({ enabled: true }).then(({ username }) => {
usersPage.goToUserDetailsPage(username!);
userDetailsPage.assertEnabled(username!);
userDetailsPage.toggleEnabled(username!);
modal.confirmModal();
masthead.checkNotificationMessage("The user has been saved");
cy.wait(1000);
userDetailsPage.assertDisabled(username!);
userDetailsPage.save();
masthead.checkNotificationMessage("The user has been saved");
cy.wait(1000);
userDetailsPage.assertDisabled(username!);
return deleteUser(username!);
});
});
});

View File

@@ -1,626 +0,0 @@
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
import LoginPage from "../support/pages/LoginPage";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import CreateUserPage from "../support/pages/admin-ui/manage/users/CreateUserPage";
import Masthead from "../support/pages/admin-ui/Masthead";
import ListingPage from "../support/pages/admin-ui/ListingPage";
import UserDetailsPage from "../support/pages/admin-ui/manage/users/user_details/UserDetailsPage";
import AttributesTab from "../support/pages/admin-ui/manage/AttributesTab";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks";
import UserGroupsPage from "../support/pages/admin-ui/manage/users/UserGroupsPage";
import adminClient from "../support/util/AdminClient";
import CredentialsPage from "../support/pages/admin-ui/manage/users/CredentialsPage";
import UsersPage from "../support/pages/admin-ui/manage/users/UsersPage";
import IdentityProviderLinksTab from "../support/pages/admin-ui/manage/users/user_details/tabs/IdentityProviderLinksTab";
import RoleMappingTab from "../support/pages/admin-ui/manage/RoleMappingTab";
import CommonPage from "../support/pages/CommonPage";
let groupName = "group";
let groupsList: string[] = [];
describe("User creation", () => {
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const realmSettingsPage = new RealmSettingsPage();
const createUserPage = new CreateUserPage();
const userGroupsPage = new UserGroupsPage();
const masthead = new Masthead();
const modalUtils = new ModalUtils();
const listingPage = new ListingPage();
const userDetailsPage = new UserDetailsPage();
const credentialsPage = new CredentialsPage();
const attributesTab = new AttributesTab(true);
const usersPage = new UsersPage();
const identityProviderLinksTab = new IdentityProviderLinksTab();
let itemId = "user_crud";
let itemIdWithGroups = "user_with_groups_crud";
let itemIdWithCred = "user_crud_cred";
const itemCredential = "Password";
before(async () => {
for (let i = 0; i <= 2; i++) {
groupName += "_" + crypto.randomUUID();
await adminClient.createGroup(groupName);
groupsList = [...groupsList, groupName];
}
});
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToUsers();
});
after(() => adminClient.deleteGroups());
it("Go to create User page", () => {
createUserPage.goToCreateUser();
cy.url().should("include", "users/add-user");
// Verify Cancel button works
createUserPage.cancel();
cy.url().should("not.include", "/add-user");
});
it("Create user test", () => {
itemId += "_" + crypto.randomUUID();
// Create
createUserPage.goToCreateUser();
createUserPage.createUser(itemId);
createUserPage.create();
masthead.checkNotificationMessage("The user has been created");
});
it("Should check temporary admin user existence", () => {
const commonPage = new CommonPage();
// check banner visibility first
cy.get(".pf-v5-c-banner").should(
"contain.text",
"You are logged in as a temporary admin user.",
);
commonPage.tableToolbarUtils().searchItem("admin", false);
commonPage.tableUtils().checkRowItemExists("admin");
commonPage
.tableUtils()
.checkTemporaryAdminLabelExists("temporary-admin-label");
});
it("Create user with groups test", () => {
itemIdWithGroups += crypto.randomUUID();
// Add user from search bar
createUserPage.goToCreateUser();
createUserPage.createUser(itemIdWithGroups);
createUserPage.toggleAddGroupModal();
const groupsListCopy = groupsList.slice(0, 1);
groupsListCopy.forEach((element) => {
cy.findByTestId(`${element}-check`).click();
});
createUserPage.joinGroups();
createUserPage.create();
masthead.checkNotificationMessage("The user has been created");
});
it("Create user with credentials test", () => {
itemIdWithCred += "_" + crypto.randomUUID();
// Add user from search bar
createUserPage.goToCreateUser();
createUserPage.createUser(itemIdWithCred);
userDetailsPage.fillUserData();
createUserPage.create();
masthead.checkNotificationMessage("The user has been created");
sidebarPage.waitForPageLoad();
credentialsPage
.goToCredentialsTab()
.clickEmptyStatePasswordBtn()
.fillPasswordForm()
.clickConfirmationBtn()
.clickSetPasswordBtn();
});
it("Search existing user test", () => {
listingPage.searchItem(itemId).itemExist(itemId);
});
it("Search non-existing user test", () => {
listingPage.searchItem("user_DNE");
listingPage.assertNoResults();
});
it("User details test", () => {
sidebarPage.waitForPageLoad();
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
userDetailsPage.fillUserData().save();
masthead.checkNotificationMessage("The user has been saved");
sidebarPage.waitForPageLoad();
sidebarPage.goToUsers();
listingPage.searchItem(itemId).itemExist(itemId);
});
it("Select Unmanaged attributes", () => {
sidebarPage.goToRealmSettings();
sidebarPage.waitForPageLoad();
realmSettingsPage.fillUnmanagedAttributes("Enabled");
realmSettingsPage.save(realmSettingsPage.generalSaveBtn);
masthead.checkNotificationMessage("Realm successfully updated", true);
});
it("User attributes test", () => {
listingPage.goToItemDetails(itemId);
attributesTab
.goToAttributesTab()
.addAttribute("key_test", "value_test")
.save();
masthead.checkNotificationMessage("The user has been saved");
attributesTab
.addAttribute("LDAP_ID", "value_test")
.addAttribute("LDAP_ID", "another_value_test")
.addAttribute("c", "d")
.save();
masthead.checkNotificationMessage("The user has not been saved: ");
cy.get(".pf-v5-c-helper-text__item-text")
.filter(':contains("Update of read-only attribute rejected")')
.should("have.length", 2);
cy.reload();
userDetailsPage.goToDetailsTab();
attributesTab
.goToAttributesTab()
.checkAttribute("key_test", true)
.deleteAttribute(0);
userDetailsPage.goToDetailsTab();
attributesTab.goToAttributesTab().checkAttribute("key_test", false);
});
it("User attributes with multiple values test", () => {
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
cy.intercept("PUT", `/admin/realms/master/users/*`).as("save-user");
const attributeKey = "key-multiple";
attributesTab
.goToAttributesTab()
.addAttribute(attributeKey, "other value")
.save();
masthead.checkNotificationMessage("The user has been saved");
cy.wait("@save-user").should(({ request, response }) => {
expect(response?.statusCode).to.equal(204);
expect(request.body.attributes, "response body").deep.contains({
"key-multiple": ["other value"],
});
});
});
it("Add user to groups test", () => {
// Go to user groups
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
userGroupsPage.goToGroupsTab();
userGroupsPage.toggleAddGroupModal();
const groupsListCopy = groupsList.slice(0, 3);
groupsListCopy.forEach((element) => {
cy.findByTestId(`${element}-check`).click();
});
userGroupsPage.joinGroups();
});
it("Leave group test", () => {
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
// Go to user groups
userGroupsPage.goToGroupsTab();
cy.findByTestId(`leave-${groupsList[0]}`).click();
cy.findByTestId("confirm").click({ force: true });
});
it("search and leave group", () => {
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
userGroupsPage.goToGroupsTab();
listingPage.searchItem("group");
userGroupsPage.leaveGroupButtonDisabled();
listingPage.clickTableHeaderItemCheckboxAllRows();
userGroupsPage.leaveGroupButtonEnabled();
userGroupsPage.leaveGroup();
});
it("Go to user consents test", () => {
listingPage.searchItem(itemId).itemExist(itemId);
sidebarPage.waitForPageLoad();
listingPage.goToItemDetails(itemId);
cy.findByTestId("user-consents-tab").click();
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(async () => {
await adminClient.deleteUser(usernameIdpLinksTest);
await Promise.all(
identityProviders.map((idp) =>
adminClient.deleteIdentityProvider(idp.alias),
),
);
});
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,
);
}
});
});
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,
);
}
});
});
});
it("Reset credential of User with empty state", () => {
listingPage.goToItemDetails(itemId);
credentialsPage
.goToCredentialsTab()
.clickEmptyStateResetBtn()
.fillResetCredentialForm();
masthead.checkNotificationMessage(
"Failed: Failed to send execute actions email",
);
});
it("Reset credential of User with existing credentials", () => {
listingPage.goToItemDetails(itemIdWithCred);
credentialsPage
.goToCredentialsTab()
.clickResetBtn()
.fillResetCredentialForm();
masthead.checkNotificationMessage(
"Failed: Failed to send execute actions email",
);
});
it("Edit credential label", () => {
listingPage.goToItemDetails(itemIdWithCred);
credentialsPage
.goToCredentialsTab()
.clickEditCredentialLabelBtn()
.fillEditCredentialForm()
.clickEditConfirmationBtn();
masthead.checkNotificationMessage(
"The user label has been changed successfully.",
);
});
it("Show credential data dialog", () => {
listingPage.goToItemDetails(itemIdWithCred);
credentialsPage
.goToCredentialsTab()
.clickShowDataDialogBtn()
.clickCloseDataDialogBtn();
});
it("Delete credential", () => {
listingPage.goToItemDetails(itemIdWithCred);
credentialsPage.goToCredentialsTab();
cy.wait(2000);
cy.get("table")
.contains(itemCredential)
.parentsUntil("tbody")
.find(".pf-v5-c-table__action .pf-v5-c-menu-toggle")
.click();
cy.get("table").contains("Delete").click();
modalUtils.checkModalTitle("Delete credentials?").confirmModal();
masthead.checkNotificationMessage(
"The credentials has been deleted successfully.",
);
});
it("Delete user from search bar test", () => {
// Delete
sidebarPage.waitForPageLoad();
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.deleteItemFromSearchBar(itemId);
modalUtils.checkModalTitle("Delete user " + itemId + "?").confirmModal();
masthead.checkNotificationMessage("The user has been deleted");
sidebarPage.waitForPageLoad();
listingPage.itemExist(itemId, false);
});
it("Delete user with groups test", () => {
// Delete
listingPage.deleteItem(itemIdWithGroups);
modalUtils
.checkModalTitle("Delete user " + itemIdWithGroups + "?")
.confirmModal();
masthead.checkNotificationMessage("The user has been deleted");
sidebarPage.waitForPageLoad();
listingPage.itemExist(itemIdWithGroups, false);
});
it("Delete user with credential test", () => {
// Delete
listingPage.deleteItem(itemIdWithCred);
modalUtils
.checkModalTitle("Delete user " + itemIdWithCred + "?")
.confirmModal();
masthead.checkNotificationMessage("The user has been deleted");
sidebarPage.waitForPageLoad();
listingPage.itemExist(itemIdWithCred, false);
});
describe("Accessibility tests for users", () => {
const a11yUser = "a11y-user";
const role = "admin";
const roleType = "roles";
const roleMappingTab = new RoleMappingTab("");
beforeEach(() => {
loginPage.logIn();
keycloakBefore();
sidebarPage.goToUsers();
cy.injectAxe();
});
it("Check a11y violations on load/ users list", () => {
cy.checkA11y();
});
it("Check a11y violations on empty create user form", () => {
createUserPage.goToCreateUser();
cy.checkA11y();
});
it("Check a11y violations on user details tab", () => {
createUserPage.goToCreateUser();
createUserPage.createUser(a11yUser);
userDetailsPage.fillUserData();
createUserPage.create();
cy.checkA11y();
});
it("Check a11y violations on user credentials tab setting a password", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
credentialsPage.goToCredentialsTab();
credentialsPage
.clickEmptyStatePasswordBtn()
.fillPasswordForm()
.clickConfirmationBtn()
.clickSetPasswordBtn();
cy.checkA11y();
});
it("Check a11y violations on user credentials tab resetting a password", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
credentialsPage.goToCredentialsTab();
credentialsPage.clickResetBtn();
cy.checkA11y();
modalUtils.cancelModal();
});
it("Check a11y violations on user role mapping tab", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
roleMappingTab.goToRoleMappingTab();
cy.checkA11y();
});
it("Check a11y violations on user role mapping tab assigning a role dialog", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
roleMappingTab.goToRoleMappingTab();
cy.findByTestId("assignRole").click();
cy.checkA11y();
roleMappingTab.changeRoleTypeFilter(roleType).selectRow(role).assign();
});
it("Check a11y violations on user groups tab", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
userGroupsPage.goToGroupsTab();
cy.checkA11y();
});
it("Check a11y violations on user groups tab joining group dialog", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
userGroupsPage.goToGroupsTab();
cy.findByTestId("no-groups-empty-action").click();
cy.checkA11y();
});
it("Check a11y violations on user groups tab joining group", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
userGroupsPage.goToGroupsTab();
cy.findByTestId("no-groups-empty-action").click();
const groupsListCopy = groupsList.slice(0, 1);
groupsListCopy.forEach((element) => {
cy.findByTestId(`${element}-check`).click();
});
createUserPage.joinGroups();
cy.checkA11y();
});
it("Check a11y violations on user consents tab", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
userDetailsPage.goToConsentsTab();
cy.checkA11y();
});
it("Check a11y violations on user identity provider links tab", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
userDetailsPage.goToIdentityProviderLinksTab();
cy.checkA11y();
});
it("Check a11y violations on user sessions tab", () => {
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
userDetailsPage.goToSessionsTab();
cy.checkA11y();
});
it("Check a11y violations on user deleting dialog", () => {
const commonPage = new CommonPage();
usersPage.goToUserListTab().goToUserDetailsPage(a11yUser);
commonPage
.actionToolbarUtils()
.clickActionToggleButton()
.clickDropdownItem("Delete");
cy.checkA11y();
cy.findByTestId("confirm").click();
});
});
});

View File

@@ -1,4 +0,0 @@
{
"port": 3004,
"searchBase": "dc=test"
}

View File

@@ -1,7 +0,0 @@
[
{
"dn": "cn=user,dc=test",
"objectClass": "person",
"cn": "user-login"
}
]

View File

@@ -1,39 +0,0 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
import "@testing-library/cypress/add-commands";
import "@4tw/cypress-drag-drop";
import "cypress-axe";
Cypress.Commands.overwrite("checkA11y", (originalFn, options) => {
const mergedOptions = {
/* eslint-disable @typescript-eslint/no-misused-spread */
...(typeof options === "object" ? options : {}),
includedImpacts: ["critical", "serious"],
};
return originalFn(undefined, mergedOptions);
});

View File

@@ -1 +0,0 @@
export const SERVER_URL = "http://localhost:8080";

View File

@@ -1,20 +0,0 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import "./commands";
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@@ -1,17 +0,0 @@
export default class Form {
static assertSaveButtonEnabled() {
this.#getSaveButton().should("be.enabled");
}
static assertSaveButtonDisabled() {
this.#getSaveButton().should("be.disabled");
}
static clickSaveButton() {
this.#getSaveButton().click();
}
static #getSaveButton() {
return cy.findByTestId("save");
}
}

View File

@@ -1,33 +0,0 @@
export default class FormValidation {
static assertRequired(chain: Cypress.Chainable<JQuery<HTMLElement>>) {
return this.assertMessage(chain, "Required field");
}
static assertMessage(
chain: Cypress.Chainable<JQuery<HTMLElement>>,
expectedMessage: string,
) {
return this.#getHelperText(chain).should("have.text", expectedMessage);
}
static assertMinValue(
chain: Cypress.Chainable<JQuery<HTMLElement>>,
minValue: number,
) {
this.assertMessage(chain, `Must be greater than ${minValue}`);
}
static assertMaxValue(
chain: Cypress.Chainable<JQuery<HTMLElement>>,
maxValue: number,
) {
this.assertMessage(chain, `Must be less than ${maxValue}`);
}
static #getHelperText(chain: Cypress.Chainable<JQuery<HTMLElement>>) {
// A regular ID selector doesn't work here so we have to query by attribute.
return chain
.invoke("attr", "data-testid")
.then((id) => cy.get(`[data-testid="${id}-helper"]`));
}
}

View File

@@ -1,20 +0,0 @@
export default class Select {
static assertSelectedItem(
chain: Cypress.Chainable<JQuery<HTMLElement>>,
itemName: string,
) {
chain.parent().should("have.text", itemName);
}
static selectItem(
chain: Cypress.Chainable<JQuery<HTMLElement>>,
itemName: string,
) {
chain.click();
this.#getSelectMenu(chain).contains(itemName).click();
}
static #getSelectMenu(chain: Cypress.Chainable<JQuery<HTMLElement>>) {
return chain.parent().get(".pf-v5-c-menu__list");
}
}

View File

@@ -1,61 +0,0 @@
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;
protected tableKebabBtn;
constructor(parentSelector = "") {
this.parentSelector = trim(parentSelector) + " ";
this.primaryBtn = this.parentSelector + ".pf-v5-c-button.pf-m-primary";
this.secondaryBtn = this.parentSelector + ".pf-v5-c-button.pf-m-secondary";
this.secondaryBtnLink = this.parentSelector + ".pf-v5-c-button.pf-m-link";
this.dropdownMenuItem =
this.parentSelector + ".pf-v5-c-menu__list .pf-v5-c-menu__item";
this.selectMenuItem =
this.parentSelector + ".pf-v5-c-menu__list .pf-v5-c-menu__list-item";
this.dropdownToggleBtn = this.parentSelector + ".pf-v5-c-menu-toggle";
this.tableKebabBtn = this.parentSelector + ".pf-v5-c-menu-toggle";
this.dropdownSelectToggleBtn = this.parentSelector + ".pf-v5-c-menu-toggle";
this.dropdownSelectToggleItem =
this.parentSelector + ".pf-v5-c-menu__list > li";
}
clickPrimaryBtn() {
cy.get(this.primaryBtn).click();
return this;
}
clickSecondaryBtn(buttonName: string, force = false) {
cy.get(this.secondaryBtn).contains(buttonName).click({ force: force });
return this;
}
checkIfExists(exist: boolean) {
cy.get(this.parentSelector).should((!exist ? "not." : "") + "exist");
return this;
}
checkElementIsDisabled(
element: Cypress.Chainable<JQuery<HTMLElement>>,
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");
}
});
}
}

View File

@@ -1,57 +0,0 @@
import Masthead from "./admin-ui/Masthead";
import SidebarPage from "./admin-ui/SidebarPage";
import TabUtils from "./admin-ui/components/TabPage";
import FormUtils from "./admin-ui/components/FormPage";
import ModalUtils from "../util/ModalUtils";
import ActionToolbarUtils from "./admin-ui/components/ActionToolbarPage";
import TableToolbarUtils from "./admin-ui/components/TableToolbarPage";
import TableUtils from "./admin-ui/components/TablePage";
import EmptyStatePage from "./admin-ui/components/EmptyStatePage";
export default class CommonPage {
#mastheadPage = new Masthead();
#sidebarPage = new SidebarPage();
#tabUtilsObj = new TabUtils();
#formUtilsObj = new FormUtils();
#modalUtilsObj = new ModalUtils();
#actionToolbarUtilsObj = new ActionToolbarUtils();
#tableUtilsObj = new TableUtils();
#tableToolbarUtilsObj = new TableToolbarUtils();
#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;
}
}

View File

@@ -1,38 +0,0 @@
export default class LoginPage {
#userNameInput = "#username";
#passwordInput = "#password";
#submitBtn = "#kc-login";
#oldLoadContainer = "#loading";
#loadContainer = "div.keycloak__loading-container";
isLogInPage() {
cy.get(this.#userNameInput).should("exist");
cy.url().should("include", "/auth");
return this;
}
logIn(userName = "admin", password = "admin") {
cy.session(
[userName, password],
() => {
cy.visit("/");
cy.get('[role="progressbar"]').should("not.exist");
cy.get(this.#oldLoadContainer).should("not.exist");
cy.get(this.#loadContainer).should("not.exist");
cy.get(this.#userNameInput).type(userName);
cy.get(this.#passwordInput).type(password);
cy.get(this.#submitBtn).click();
},
{
validate() {
cy.get('[role="progressbar"]').should("not.exist");
},
},
);
}
}

View File

@@ -1,8 +0,0 @@
export default class ListingPage {
#actionMenu = "action-dropdown";
clickAction(action: string) {
cy.findByTestId(this.#actionMenu).click().findByTestId(action).click();
return this;
}
}

View File

@@ -1,63 +0,0 @@
import FormValidation from "../../forms/FormValidation";
export default class CreateRealmPage {
#modalClearBtn = "clear-button";
#realmNameInput = "realm";
#enabledSwitch = ".pf-v5-c-toolbar .pf-v5-c-switch__toggle";
#createBtn = '[data-testid="create"]';
#cancelBtn = '[data-testid="cancel"]';
#codeEditor = ".w-tc-editor-text";
#getClearBtn() {
return cy.findByText("Clear");
}
fillRealmName(realmName: string) {
cy.findByTestId(this.#realmNameInput).clear().type(realmName);
return this;
}
fillCodeEditor() {
cy.get(this.#codeEditor).type("clear this field");
return this;
}
createRealm(wait = true) {
if (wait) {
cy.intercept("POST", "/admin/realms").as("createRealm");
cy.get(this.#createBtn).click();
cy.wait("@createRealm");
} else {
cy.get(this.#createBtn).click();
}
return this;
}
disableRealm() {
cy.get(this.#enabledSwitch).click();
return this;
}
cancelRealmCreation() {
cy.get(this.#cancelBtn).click();
return this;
}
clearTextField() {
this.#getClearBtn().click();
cy.findByTestId(this.#modalClearBtn).click();
return this;
}
verifyRealmNameFieldInvalid() {
FormValidation.assertRequired(cy.findByTestId(this.#realmNameInput));
return this;
}
}

View File

@@ -1,487 +0,0 @@
import CommonElements from "../CommonElements";
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",
}
export enum FilterSession {
AllSessionTypes = "All session types",
RegularSSO = "Regular SSO",
Offline = "Offline",
DirectGrant = "Direct grant",
ServiceAccount = "Service account",
}
export default class ListingPage extends CommonElements {
#tableToolbar = "section .pf-v5-c-toolbar";
#itemsRows = "table:visible";
#deleteUserButton = "delete-user-btn";
#emptyListImg = '[role="tabpanel"]:not([hidden]) [data-testid="empty-state"]';
#emptyState = "empty-state";
#itemRowDrpDwn = ".pf-v5-c-table__action button";
#itemRowSelect = "[data-testid='cell-dropdown']";
#itemRowSelectItem = ".pf-v5-c-menu__item";
#itemCheckbox = ".pf-v5-c-table__check";
public exportBtn = '[role="menuitem"]:nth-child(1)';
public deleteBtn = '[role="menuitem"]:nth-child(2)';
#searchBtn =
".pf-v5-c-page__main .pf-v5-c-toolbar__content-section button.pf-m-control:visible";
#listHeaderPrimaryBtn =
".pf-v5-c-page__main .pf-v5-c-toolbar__content-section .pf-m-primary:visible";
#listHeaderSecondaryBtn =
".pf-v5-c-page__main .pf-v5-c-toolbar__content-section .pf-m-link";
#previousPageBtn =
".pf-v5-c-pagination:not([class*=pf-m-bottom]) button[data-action=previous]";
#nextPageBtn =
".pf-v5-c-pagination:not([class*=pf-m-bottom]) button[data-action=next]";
public tableRowItem = "tbody tr[data-ouia-component-type]:visible";
#table = "table[aria-label]";
#filterSessionDropdownButton = ".pf-v5-c-select button:nth-child(1)";
#filterDropdownButton = "[data-testid='clientScopeSearchType']";
#protocolFilterDropdownButton = "[data-testid='clientScopeSearchProtocol']";
#kebabMenu = "[data-testid='kebab']";
#dropdownItem = ".pf-v5-c-menu__list-item";
#toolbarChangeType = "#change-type-dropdown";
#tableNameColumnPrefix = "name-column-";
#rowGroup = "table:visible tbody[role='rowgroup']";
#tableHeaderCheckboxItemAllRows = "input[aria-label='Select all rows']";
#searchBtnInModal =
".pf-v5-c-modal-box .pf-v5-c-toolbar__content-section button.pf-m-control:visible";
#menuContent = ".pf-v5-c-menu__content";
#menuItemText = ".pf-v5-c-menu__item-text";
#getSearchInput() {
return cy.findAllByTestId("table-search-input").last().find("input");
}
showPreviousPageTableItems() {
cy.get(this.#previousPageBtn).first().click();
return this;
}
showNextPageTableItems() {
cy.get("body").then(($body) => {
if (!$body.find('[data-testid="' + this.#nextPageBtn + '"]').length) {
cy.get(this.#nextPageBtn).scrollIntoView();
cy.get(this.#nextPageBtn).click();
}
});
return this;
}
goToCreateItem() {
cy.get(this.#listHeaderPrimaryBtn).click();
return this;
}
goToImportItem() {
cy.get(this.#listHeaderSecondaryBtn).click();
return this;
}
searchItem(searchValue: string, wait = true, realm = "master") {
if (wait) {
const searchUrl = `/admin/realms/${realm}/**/*${searchValue}*`;
cy.intercept(searchUrl).as("search");
}
this.#getSearchInput().click({ force: true });
this.#getSearchInput().clear();
if (searchValue) {
this.#getSearchInput().type(searchValue);
cy.get(this.#searchBtn).click({ force: true });
} else {
// TODO: Remove else and move clickSearchButton outside of the if
this.#getSearchInput().type("{enter}");
}
if (wait) {
cy.wait(["@search"]);
}
return this;
}
searchItemInModal(searchValue: string) {
this.#getSearchInput().click({ force: true });
this.#getSearchInput().clear();
if (searchValue) {
this.#getSearchInput().type(searchValue);
}
cy.get(this.#searchBtnInModal).click({ force: true });
}
checkTableLength(length: number, identifier: string) {
cy.get("table")
.should("have.class", identifier)
.get("tbody")
.children()
.should("have.length", length);
}
clickSearchBarActionButton() {
cy.get(this.#tableToolbar).find(this.#kebabMenu).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)
.parentsUntil("tbody")
.find(this.#itemRowDrpDwn)
.click({ force: true });
return this;
}
markItemRow(itemName: string) {
cy.get(this.#itemsRows)
.contains(itemName)
.parentsUntil("tbody")
.find('input[name*="checkrow"]')
.click();
return this;
}
removeMarkedItems(name: string = "Remove") {
cy.get(this.#listHeaderSecondaryBtn).contains(name).click();
return this;
}
checkRowColumnValue(itemName: string, column: number, value: string) {
cy.get(this.#itemsRows)
.contains(itemName)
.parentsUntil("tbody")
.find("td:nth-child(" + column + ")")
.should("have.text", value);
return this;
}
clickDetailMenu(name: string) {
cy.get(this.#itemsRows).contains(name).click();
return this;
}
clickMenuDelete() {
cy.get(this.#menuContent)
.find(this.#menuItemText)
.contains("Delete")
.click({ force: true });
return this;
}
clickMenuDuplicate() {
cy.get(this.#menuContent)
.find(this.#menuItemText)
.contains("Duplicate")
.click({ force: true });
return this;
}
clickItemCheckbox(itemName: string) {
cy.get(this.#itemsRows)
.contains(itemName)
.parentsUntil("tbody")
.find(this.#itemCheckbox)
.click();
return this;
}
clickTableHeaderItemCheckboxAllRows() {
cy.get(this.#tableHeaderCheckboxItemAllRows).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)
.should((!exist ? "not." : "") + "exist");
return this;
}
goToItemDetails(itemName: string) {
cy.get(this.#itemsRows).contains(itemName).click({ force: true });
return this;
}
checkEmptyList() {
cy.get(this.#emptyListImg).should("be.visible");
return this;
}
deleteItem(itemName: string) {
this.clickRowDetails(itemName);
this.clickMenuDelete();
return this;
}
duplicateItem(itemName: string) {
this.clickRowDetails(itemName);
this.clickMenuDuplicate();
return this;
}
removeItem(itemName: string) {
this.clickRowDetails(itemName);
this.clickDetailMenu("Unassign");
return this;
}
deleteItemFromSearchBar(itemName: string) {
this.markItemRow(itemName);
cy.findByTestId(this.#deleteUserButton).click();
return this;
}
exportItem(itemName: string) {
this.clickRowDetails(itemName);
this.clickDetailMenu("Export");
return this;
}
checkEmptySearch() {
cy.get(this.tableRowItem).its("length").as("initialCount");
this.searchItem("", false);
cy.get(this.tableRowItem).its("length").as("finalCount");
cy.get("@initialCount").then((initial) => {
cy.get("@finalCount").then((final) => {
expect(initial).to.eq(final);
});
});
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;
}
selectClientScopeFilter(filter: Filter) {
return this.selectFilter("clientScopeSearch", filter);
}
protected selectFilter(searchTypeButtonTestId: string, filterStr: string) {
cy.get(`[data-testid='${searchTypeButtonTestId}']`).click();
cy.get(this.#dropdownItem).contains(filterStr).click();
return this;
}
selectSecondaryFilter(itemName: string) {
cy.get(this.#filterDropdownButton).click();
cy.get(this.#itemRowSelectItem).contains(itemName).click();
return this;
}
selectSecondaryFilterAssignedType(assignedType: FilterAssignedType) {
this.selectSecondaryFilter(assignedType);
return this;
}
selectSecondaryFilterProtocol(protocol: FilterProtocol) {
cy.get(this.#protocolFilterDropdownButton).click();
cy.get(this.#itemRowSelectItem).contains(protocol).click();
return this;
}
selectSecondaryFilterSession(sessionName: FilterSession) {
cy.get(this.#filterSessionDropdownButton).click();
cy.get(this.#itemRowSelectItem).contains(sessionName);
return this;
}
changeTypeToOfSelectedItems(assignedType: FilterAssignedType) {
cy.intercept("/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.#toolbarChangeType)
.first()
.click();
cy.get(this.#itemsRows)
.contains(itemName)
.parentsUntil("tbody")
.find(this.#toolbarChangeType)
.contains(assignedType)
.click();
return this;
}
checkInSearchBarChangeTypeToButtonIsDisabled(disabled: boolean = true) {
let condition = "be.disabled";
if (!disabled) {
condition = "be.enabled";
}
cy.get(this.#toolbarChangeType).first().should(condition);
return this;
}
checkDropdownItemIsDisabled(itemName: string, disabled: boolean = true) {
cy.get(this.#dropdownItem)
.contains(itemName)
.should((disabled ? "" : "not.") + "be.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;
}
#getResourceLink(name: string) {
return cy.findByTestId(this.#tableNameColumnPrefix + name);
}
goToResourceDetails(name: string) {
this.#getResourceLink(name).click();
return this;
}
assertNoResults() {
cy.findByTestId(this.#emptyState).should("exist");
}
assertDefaultResource() {
this.assertResource("Default Resource");
return this;
}
assertResource(name: string) {
this.#getResourceLink(name).should("exist");
return this;
}
#getRowGroup(index = 0) {
return cy.get(this.#rowGroup).eq(index);
}
expandRow(index = 0) {
this.#getRowGroup(index)
.find("[class='pf-v5-c-button pf-m-plain'][id*='expandable']")
.click();
return this;
}
collapseRow(index = 0) {
this.#getRowGroup(index)
.find(
"[class='pf-v5-c-button pf-m-plain pf-m-expanded'][id*='expandable']",
)
.click();
return this;
}
assertExpandedRowContainText(index = 0, text: string) {
this.#getRowGroup(index)
.find("tr[class='pf-v5-c-table__expandable-row pf-m-expanded']")
.should("contain.text", text);
return this;
}
assertRowIsExpanded(index = 0, isExpanded: boolean) {
this.#getRowGroup(index)
.find(
"[class='pf-v5-c-button pf-m-plain pf-m-expanded'][id*='expandable']",
)
.should((!isExpanded ? "not." : "") + "exist");
return this;
}
}

View File

@@ -1,141 +0,0 @@
import CommonElements from "../CommonElements";
export default class Masthead extends CommonElements {
#logoBtn = ".pf-v5-c-page__header-brand-link img";
#helpBtn = "#help";
#userDrpDwn = "#user-dropdown";
#userDrpDwnKebab = "#user-dropdown-kebab";
#lastAlert = "last-alert";
#globalAlerts = "global-alerts";
#documentationLink = "#link";
#backToAdminConsoleLink = "referrer-link";
#userDrpdwnItem = ".pf-v5-c-menu__item";
#getLastAlert() {
return cy.findByTestId(this.#lastAlert);
}
#getAlerts() {
return cy.findAllByTestId(this.#globalAlerts);
}
checkIsAdminUI() {
cy.get(this.#logoBtn).should("exist");
cy.get(this.#userDrpDwn).should("exist");
return this;
}
setMobileMode(isMobileMode: boolean) {
if (isMobileMode) {
cy.viewport("iphone-6");
} else {
cy.viewport(1024, 768);
}
}
toggleGlobalHelp() {
cy.get(this.#helpBtn).click();
cy.get("#enableHelp").click({ force: true });
}
toggleUsernameDropdown() {
this.userDropdown().click();
return this;
}
toggleMobileViewHelp() {
cy.get(this.#userDrpdwnItem).contains("Help").click();
return this;
}
clickRealmInfo() {
cy.get(this.#userDrpdwnItem).contains("Realm info").click();
return this;
}
clickGlobalHelp() {
cy.get(this.#helpBtn).click();
return this;
}
getDocumentationLink() {
return cy.get(this.#documentationLink);
}
clickDocumentationLink() {
this.getDocumentationLink()
.find("a")
.invoke("removeAttr", "target")
.click();
return this;
}
goToAdminConsole() {
cy.findByTestId(this.#backToAdminConsoleLink).click({ force: true });
return this;
}
userDropdown() {
return cy
.document()
.then(({ documentElement }) => documentElement.getBoundingClientRect())
.then(({ width }) =>
cy.get(width < 1024 ? this.#userDrpDwnKebab : this.#userDrpDwn),
);
}
signOut() {
this.toggleUsernameDropdown();
cy.get("#sign-out").click();
Cypress.session.clearAllSavedSessions();
}
accountManagement() {
this.toggleUsernameDropdown();
cy.get("#manage-account").click();
}
checkNotificationMessage(message: string | RegExp, closeNotification = true) {
const alertElement = this.#getLastAlert();
if (typeof message === "string") {
alertElement.should(($el) => expect($el).to.contain.text(message));
} else {
alertElement.should(($el) => expect($el).to.match(message));
}
if (closeNotification) {
this.#getLastAlert().find("button").last().click({ force: true });
}
return this;
}
closeLastAlertMessage() {
this.#getLastAlert().find("button").click();
return this;
}
closeAllAlertMessages() {
this.#getAlerts().find("button").click({
force: true,
multiple: true,
});
return this;
}
assertIsDesktopView() {
cy.get(this.#userDrpDwn).should("be.visible");
cy.get(this.#userDrpDwnKebab).should("not.be.visible");
return this;
}
assertIsMobileView() {
cy.get(this.#userDrpDwn).should("not.be.visible");
cy.get(this.#userDrpDwnKebab).should("be.visible");
return this;
}
}

View File

@@ -1,165 +0,0 @@
import CommonElements from "../CommonElements";
export default class SidebarPage extends CommonElements {
#realmsDrpDwn = "realmSelector";
#createRealmBtn = "add-realm";
#clientsBtn = "#nav-item-clients";
#clientScopesBtn = "#nav-item-client-scopes";
#realmRolesBtn = "#nav-item-roles";
#usersBtn = "#nav-item-users";
#groupsBtn = "#nav-item-groups";
#sessionsBtn = "#nav-item-sessions";
#eventsBtn = "#nav-item-events";
#realmSettingsBtn = "#nav-item-realm-settings";
#authenticationBtn = "#nav-item-authentication";
#identityProvidersBtn = "#nav-item-identity-providers";
#userFederationBtn = "#nav-item-user-federation";
realmsElements = '[id="realm-select"] li';
showCurrentRealms(length: number) {
cy.findByTestId(this.#realmsDrpDwn).click();
cy.get(this.realmsElements).contains("Loading realms…").should("not.exist");
cy.get(this.realmsElements).should(
"have.length",
length + 2, // account for recent realms
);
cy.findByTestId(this.#realmsDrpDwn).click({ force: true });
return this;
}
realmExists(realmName: string, exists = true) {
cy.findByTestId(this.#realmsDrpDwn).click();
cy.get(this.realmsElements).contains("Loading realms…").should("not.exist");
cy.get(this.realmsElements)
.contains(realmName)
.should((exists ? "" : "not.") + "exist");
cy.findByTestId(this.#realmsDrpDwn).click();
return this;
}
getCurrentRealm() {
return cy.findByTestId(this.#realmsDrpDwn).scrollIntoView().invoke("text");
}
goToRealm(realmName: string) {
this.waitForPageLoad();
cy.intercept("GET", "/admin/realms/master/ui-ext/realms/names/*").as(
"getRealms",
);
cy.findByTestId(this.#realmsDrpDwn).click();
cy.get(this.realmsElements).contains("Loading realms…").should("not.exist");
cy.get(this.realmsElements).contains(realmName).click();
this.waitForPageLoad();
return this;
}
goToCreateRealm() {
this.waitForPageLoad();
cy.findByTestId(this.#createRealmBtn).click();
this.waitForPageLoad();
return this;
}
goToClients() {
this.waitForPageLoad();
cy.get(this.#clientsBtn).click({ force: true });
this.waitForPageLoad();
return this;
}
goToClientScopes() {
this.waitForPageLoad();
cy.get(this.#clientScopesBtn).click();
this.waitForPageLoad();
return this;
}
goToRealmRoles() {
cy.get(this.#realmRolesBtn).click();
this.waitForPageLoad();
return this;
}
goToUsers() {
this.waitForPageLoad();
cy.get(this.#usersBtn).click();
this.waitForPageLoad();
return this;
}
goToGroups() {
this.waitForPageLoad();
cy.get(this.#groupsBtn).click();
this.waitForPageLoad();
return this;
}
goToSessions() {
this.waitForPageLoad();
cy.get(this.#sessionsBtn).click();
this.waitForPageLoad();
return this;
}
goToEvents() {
this.waitForPageLoad();
cy.get(this.#eventsBtn).click();
this.waitForPageLoad();
return this;
}
goToRealmSettings() {
this.waitForPageLoad();
cy.get(this.#realmSettingsBtn).click({ force: true });
this.waitForPageLoad();
return this;
}
goToAuthentication() {
this.waitForPageLoad();
cy.get(this.#authenticationBtn).click();
this.waitForPageLoad();
return this;
}
goToIdentityProviders() {
this.waitForPageLoad();
cy.get(this.#identityProvidersBtn).click();
this.waitForPageLoad();
return this;
}
goToUserFederation() {
this.waitForPageLoad();
cy.get(this.#userFederationBtn).click();
this.waitForPageLoad();
return this;
}
waitForPageLoad() {
cy.get('[role="progressbar"]').should("not.exist");
return this;
}
checkRealmSettingsLinkContainsText(expectedText: string) {
cy.get(this.#realmSettingsBtn).should("contain", expectedText);
}
}

View File

@@ -1,37 +0,0 @@
import CommonElements from "../../CommonElements";
export default class ActionToolbarPage extends CommonElements {
constructor() {
super(".pf-v5-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;
}
#getDropdownItem(itemName: string) {
return cy.get(this.dropdownMenuItem).contains(itemName);
}
checkActionItemExists(itemName: string, exists: boolean) {
const condition = exists ? "exist" : "not.exist";
this.#getDropdownItem(itemName).should(condition);
return this;
}
clickDropdownItem(itemName: string) {
this.#getDropdownItem(itemName).click();
return this;
}
}

View File

@@ -1,7 +0,0 @@
import CommonElements from "../../CommonElements";
export default class EmptyStatePage extends CommonElements {
constructor() {
super(".pf-v5-c-empty-state__content");
}
}

View File

@@ -1,35 +0,0 @@
import CommonElements from "../../CommonElements";
export default class FormPage extends CommonElements {
constructor() {
super(".pf-v5-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;
}
}

View File

@@ -1,393 +0,0 @@
export default class PageObject {
#selectItemSelectedIcon = ".pf-v5-c-menu-toggle__toggle-icon";
#drpDwnMenuList = ".pf-v5-c-menu__list";
#drpDwnMenuItem = ".pf-v5-c-menu__item";
#drpDwnMenuToggleBtn = ".pf-v5-c-menu-toggle";
#selectMenuList = ".pf-v5-c-menu__list";
#selectMenuItem = ".pf-v5-c-menu__list-item";
#selectMenuToggleBtn = ".pf-v5-c-menu-toggle";
#switchInput = ".pf-v5-c-switch__input";
#formLabel = ".pf-v5-c-form__label";
#chipGroupCloseBtn = ".pf-v5-c-chip-group__close";
#chipItem = ".pf-v5-c-chip-group__list-item";
#emptyStateDiv = ".pf-v5-c-empty-state:visible";
#toolbarActionsButton = ".pf-v5-c-toolbar button[aria-label='Actions']";
#breadcrumbItem = ".pf-v5-c-breadcrumb .pf-v5-c-breadcrumb__item";
genericChipGroupSelector = ".pf-v5-c-chip-group";
protected assertExist(element: Cypress.Chainable<JQuery>, exist: boolean) {
element.should((!exist ? "not." : "") + "exist");
return this;
}
protected assertIsVisible(
element: Cypress.Chainable<JQuery>,
isVisible: boolean,
) {
element.should((!isVisible ? "not." : "") + "be.visible");
return this;
}
protected assertIsEnabled(
element: Cypress.Chainable<JQuery>,
isEnabled = true,
) {
element.then(($btn) => {
if ($btn.hasClass("pf-m-disabled")) {
element.should(
(isEnabled ? "not." : "") + "have.class",
"pf-m-disabled",
);
} else {
element.should((isEnabled ? "not." : "") + "have.attr", "disabled");
}
});
return this;
}
protected assertIsDisabled(element: Cypress.Chainable<JQuery>) {
return this.assertIsEnabled(element, false);
}
protected assertHaveText(element: Cypress.Chainable<JQuery>, text: string) {
element.should("have.text", text);
return this;
}
protected assertHaveValue(element: Cypress.Chainable<JQuery>, value: string) {
element.should("have.value", value);
return this;
}
protected assertSwitchStateOn(
element?: Cypress.Chainable<JQuery>,
isOn = true,
) {
(element ?? cy.get(this.#switchInput))
.parent()
.contains(isOn ? "On" : "Off")
.should("be.visible");
return this;
}
protected assertSwitchStateOff(element?: Cypress.Chainable<JQuery>) {
return this.assertSwitchStateOn(element, false);
}
protected assertDropdownMenuIsOpen(
isOpen = true,
element?: Cypress.Chainable<JQuery>,
) {
this.assertExist(element ?? cy.get(this.#drpDwnMenuList), isOpen);
return this;
}
protected assertDropdownMenuIsClosed(element?: Cypress.Chainable<JQuery>) {
return this.assertDropdownMenuIsOpen(
false,
element ?? cy.get(this.#drpDwnMenuList),
);
}
protected clickDropdownMenuItem(
itemName: string,
element?: Cypress.Chainable<JQuery>,
) {
(element ?? cy.get(this.#drpDwnMenuItem).contains(itemName)).click();
return this;
}
protected clickDropdownMenuToggleButton(
itemName: string,
element?: Cypress.Chainable<JQuery>,
) {
element =
element ??
cy
.get(this.#drpDwnMenuToggleBtn)
.parent()
.contains(itemName)
.parent()
.parent();
element.click();
return this;
}
protected openDropdownMenu(
itemName: string,
element?: Cypress.Chainable<JQuery>,
) {
element =
element ??
cy
.get(this.#drpDwnMenuToggleBtn)
.parent()
.contains(itemName)
.parent()
.parent();
this.clickDropdownMenuToggleButton(itemName, element);
this.assertDropdownMenuIsOpen(true);
return this;
}
protected closeDropdownMenu(
itemName: string,
element?: Cypress.Chainable<JQuery>,
) {
element =
element ??
cy
.get(this.#drpDwnMenuToggleBtn)
.parent()
.contains(itemName)
.parent()
.parent();
this.clickDropdownMenuToggleButton(itemName, element);
this.assertDropdownMenuIsOpen(false);
return this;
}
protected assertDropdownMenuItemIsSelected(
itemName: string,
isSelected: boolean,
element?: Cypress.Chainable<JQuery>,
) {
element = element ?? cy.get(this.#drpDwnMenuItem);
this.assertExist(
element.contains(itemName).find(this.#selectItemSelectedIcon),
isSelected,
);
return this;
}
protected assertDropdownMenuHasItems(
items: string[],
element?: Cypress.Chainable<JQuery>,
) {
const initialElement = element;
for (const item of items) {
element = initialElement ?? cy.get(this.#drpDwnMenuList);
this.assertExist(element.find(this.#drpDwnMenuItem).contains(item), true);
}
return this;
}
protected assertDropdownMenuHasLabels(
items: string[],
element?: Cypress.Chainable<JQuery>,
) {
const initialElement = element;
for (const item of items) {
element = initialElement ?? cy.get(this.#drpDwnMenuList);
this.assertExist(element.find(this.#formLabel).contains(item), true);
}
return this;
}
protected assertDropdownMenuItemsEqualTo(
number: number,
element?: Cypress.Chainable<JQuery>,
) {
element = element ?? cy.get(this.#drpDwnMenuList);
element.find(this.#drpDwnMenuItem).should(($item) => {
expect($item).to.have.length(number);
});
return this;
}
protected assertSelectMenuIsOpen(
isOpen = true,
element?: Cypress.Chainable<JQuery>,
) {
element = element ?? cy.get(this.#selectMenuList);
return this.assertDropdownMenuIsOpen(isOpen, element);
}
protected assertSelectMenuIsClosed(element?: Cypress.Chainable<JQuery>) {
element = element ?? cy.get(this.#selectMenuList);
return this.assertDropdownMenuIsClosed(element);
}
protected clickSelectMenuItem(
itemName: string,
element?: Cypress.Chainable<JQuery>,
) {
element =
element ??
cy.get(this.#selectMenuItem).contains(new RegExp(`^${itemName}$`));
return this.clickDropdownMenuItem(itemName, element);
}
protected clickSelectMenuToggleButton(
itemName: string,
element?: Cypress.Chainable<JQuery>,
) {
element =
element ??
cy.get(this.#selectMenuToggleBtn).contains(itemName).parent().parent();
return this.clickDropdownMenuToggleButton(itemName, element);
}
protected openSelectMenu(itemName: string, element?: Cypress.Chainable<any>) {
element =
element ??
cy.get(this.#selectMenuToggleBtn).contains(itemName).parent().parent();
this.clickDropdownMenuToggleButton(itemName, element);
this.assertSelectMenuIsOpen(true);
return this;
}
protected closeSelectMenu(
itemName: string,
element?: Cypress.Chainable<JQuery>,
) {
element =
element ??
cy.get(this.#selectMenuToggleBtn).contains(itemName).parent().parent();
this.clickDropdownMenuToggleButton(itemName, element);
this.assertSelectMenuIsOpen(false);
return this;
}
protected assertSelectMenuItemIsSelected(
itemName: string,
isSelected: boolean,
element?: Cypress.Chainable<JQuery>,
) {
element = element ?? cy.get(this.#selectMenuItem);
return this.assertDropdownMenuItemIsSelected(itemName, isSelected, element);
}
protected assertSelectMenuHasItems(
items: string[],
element?: Cypress.Chainable<JQuery>,
) {
const initialElement = element;
for (const item of items) {
element = initialElement ?? cy.get(this.#selectMenuList);
this.assertExist(element.find(this.#selectMenuItem).contains(item), true);
}
return this;
}
protected assertSelectMenuItemsEqualTo(
number: number,
element?: Cypress.Chainable<JQuery>,
) {
element = element ?? cy.get(this.#selectMenuList);
element.find(this.#selectMenuItem).should(($item) => {
expect($item).to.have.length(number);
});
return this;
}
#getChipGroup(groupSelector: string, groupName: string) {
return cy.get(groupSelector).contains(groupName).parent().parent();
}
#getChipGroupWithLabel(groupSelector: string, label: string) {
cy.get(groupSelector)
.parent()
.find(".pf-v5-c-chip-group__label")
.contains(label);
return cy.get(groupSelector);
}
#getChipGroupItem(
groupSelector: string,
groupName: string,
itemName: string,
) {
return this.#getChipGroup(groupSelector, groupName)
.find(this.#chipItem)
.contains(itemName)
.parent();
}
protected removeChipGroup(groupSelector: string, groupName: string) {
this.#getChipGroup(groupSelector, groupName)
.find(this.#chipGroupCloseBtn)
.find("button")
.click();
return this;
}
protected removeChipGroupItem(
groupSelector: string,
groupName: string,
itemName: string,
) {
this.#getChipGroupItem(groupSelector, groupName, itemName)
.find("button")
.click();
return this;
}
protected assertChipGroupExist(
groupSelector: string,
groupName: string,
exist: boolean,
) {
this.assertExist(cy.contains(groupSelector, groupName), exist);
return this;
}
protected clickToolbarAction(itemName: string) {
cy.get(this.#toolbarActionsButton).click();
this.clickDropdownMenuItem(itemName);
return this;
}
protected assertChipGroupItemExist(
groupSelector: string,
groupName: string,
itemName: string,
exist: boolean,
) {
this.assertExist(
this.#getChipGroup(groupSelector, groupName).contains(
this.#chipItem,
itemName,
),
exist,
);
return this;
}
protected assertLabeledChipGroupItemExist(
groupSelector: string,
labelName: string,
itemName: string,
exist: boolean,
) {
this.assertExist(
this.#getChipGroupWithLabel(groupSelector, labelName).contains(
this.#chipItem,
itemName,
),
exist,
);
return this;
}
assertEmptyStateExist(exist: boolean) {
if (exist) {
cy.get(this.#emptyStateDiv).should("exist").should("be.visible");
} else {
cy.get(this.#emptyStateDiv).should("not.exist");
}
return this;
}
protected clickBreadcrumbItem(itemName: string) {
cy.get(this.#breadcrumbItem).contains(itemName).click();
return this;
}
protected waitForPageLoad() {
cy.get('[role="progressbar"]').should("not.exist");
return this;
}
}

View File

@@ -1,46 +0,0 @@
import CommonElements from "../../CommonElements";
export default class TabPage extends CommonElements {
protected tabItemSelector: string;
protected tabsList: string;
constructor() {
super(".pf-v5-c-tabs");
this.tabItemSelector = ".pf-v5-c-tabs__item";
this.tabsList = '[role="tablist"]';
}
#getTab(tabName: string, index: number | undefined = 0) {
return cy
.get(this.parentSelector)
.eq(index)
.find(this.tabItemSelector)
.contains(tabName);
}
clickTab(tabName: string, index: number | undefined = 0) {
this.#getTab(tabName, index).click();
this.checkIsCurrentTab(tabName, index);
return this;
}
checkIsCurrentTab(tabName: string, index: number | undefined = 0) {
this.#getTab(tabName, index).parent().should("have.class", "pf-m-current");
return this;
}
checkTabExists(
tabName: string,
exists: boolean,
index: number | undefined = 0,
) {
const condition = exists ? "exist" : "not.exist";
this.#getTab(tabName, index).should(condition);
return this;
}
checkNumberOfTabsIsEqual(number: number) {
cy.get(this.tabsList).find("li").should("have.length", number);
return this;
}
}

View File

@@ -1,191 +0,0 @@
import CommonElements from "../../CommonElements";
export default class TablePage extends CommonElements {
#tableRowItem: string;
#tableRowItemChckBx: string;
#tableHeaderRowItem: string;
#tableKebabMenu: string;
#tableInModal: boolean;
static tableSelector = ".pf-v5-c-table";
constructor(parentElement?: string) {
super(parentElement ?? TablePage.tableSelector + ":visible");
this.#tableRowItem = this.parentSelector + "tbody tr";
this.#tableHeaderRowItem = this.parentSelector + "thead tr";
this.#tableRowItemChckBx = ".pf-v5-c-table__check";
this.#tableKebabMenu = ".pf-v5-c-menu";
this.#tableInModal = false;
}
setTableInModal(value: boolean) {
this.#tableInModal = value;
}
selectRowItemCheckbox(itemName: string) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem,
)
.contains(itemName)
.parentsUntil("tbody")
.find(this.#tableRowItemChckBx)
.click();
return this;
}
clickRowItemLink(itemName: string) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem,
)
.contains(itemName)
.click({ force: true });
return this;
}
selectRowItemAction(itemName: string, actionItemName: string) {
this.#getRowItemAction(itemName, actionItemName).click();
return this;
}
assertRowItemActionExist(itemName: string, actionItemName: string) {
this.#getRowItemAction(itemName, actionItemName).should("exist");
return this;
}
#getRowItemAction(itemName: string, actionItemName: string) {
return cy
.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem,
)
.contains(itemName)
.parentsUntil("tbody")
.find(".pf-v5-c-table__action .pf-v5-c-menu-toggle")
.click()
.get(this.#tableKebabMenu)
.contains(actionItemName);
}
typeValueToRowItem(row: number, column: number, value: string) {
cy.get(
(this.#tableInModal ? ".pf-v5-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.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem +
":nth-child(" +
row +
")",
)
.find("td:nth-child(" + column + ") " + appendChildren)
.click();
return this;
}
clickRowItemByItemName(
itemName: string,
column: number,
appendChildren?: string,
) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem,
)
.find("td:nth-child(" + column + ") " + appendChildren)
.contains(itemName)
.click();
return this;
}
clickHeaderItem(column: number, appendChildren?: string) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableHeaderRowItem,
)
.find("th:nth-child(" + column + ") " + appendChildren)
.click();
return this;
}
checkRowItemsEqualTo(amount: number) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem,
)
.its("length")
.should("be.eq", amount);
return this;
}
checkRowItemsGreaterThan(amount: number) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem,
)
.its("length")
.should("be.gt", amount);
return this;
}
checkRowItemExists(itemName: string, exist = true) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem,
)
.contains(itemName)
.should((!exist ? "not." : "") + "exist");
return this;
}
checkTemporaryAdminLabelExists(labelId: string, exist = true) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
this.#tableRowItem,
)
.find(`#${labelId}`)
.should((!exist ? "not." : "") + "exist");
return this;
}
checkRowItemValueByItemName(itemName: string, column: number, value: string) {
cy.get(
(this.#tableInModal ? ".pf-v5-c-modal-box.pf-m-md " : "") +
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.#tableInModal ? ".pf-v5-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);
return this;
}
}

View File

@@ -1,130 +0,0 @@
import CommonElements from "../../CommonElements";
import type { Filter, FilterAssignedType } from "../ListingPage";
export default class TableToolbar extends CommonElements {
#searchBtn: string;
#searchInput: string;
#changeTypeBtn: string;
#nextPageBtn: string;
#previousPageBtn: string;
#searchTypeDropdownBtn: string;
#actionToggleBtn: string;
constructor() {
super(".pf-v5-c-toolbar:visible");
this.#searchBtn =
this.parentSelector + "button[aria-label='Search']:visible";
this.#searchInput =
this.parentSelector + ".pf-v5-c-text-input-group__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 = "[data-testid='clientScopeSearchType']";
this.#actionToggleBtn = "[data-testid='kebab']";
}
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({ force: true });
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/*/*${searchValue}*`;
cy.intercept(searchUrl).as("search");
}
cy.get(this.#searchInput).clear();
if (searchValue) {
cy.get(this.#searchInput).type(searchValue);
this.clickSearchButton();
} else {
// TODO: Remove else and move clickSearchButton outside of the if
cy.get(this.#searchInput).type("{enter}");
}
if (wait) {
cy.wait(["@search"]);
}
return this;
}
selectSearchType(existingName: Filter, itemName: Filter) {
cy.contains("button", existingName).click();
cy.get(this.dropdownMenuItem).contains(itemName).click();
return this;
}
selectSecondarySearchType(itemName: FilterAssignedType) {
cy.get(this.#searchTypeDropdownBtn).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;
}
}

View File

@@ -1,25 +0,0 @@
export default class PartialExportModal {
open() {
cy.findByTestId("openPartialExportModal").click();
}
exportButton() {
return cy.findByTestId("export-button");
}
cancelButton() {
return cy.findByTestId("cancel-button");
}
includeGroupsAndRolesSwitch() {
return cy.get("#include-groups-and-roles-check");
}
includeClientsSwitch() {
return cy.get("#include-clients-check");
}
warningMessage() {
return cy.findByTestId("warning-message");
}
}

View File

@@ -1,96 +0,0 @@
export default class GroupModal {
#openPartialImport = "openPartialImportModal";
open() {
cy.findByTestId(this.#openPartialImport).click();
return this;
}
typeResourceFile = (filename: string) => {
cy.get("#partial-import-file-filename").selectFile(
"cypress/fixtures/partial-import-test-data/" + filename,
{ action: "drag-drop" },
);
};
textArea() {
return cy.get(".w-tc-editor-text");
}
importButton() {
return cy.findByTestId("import-button");
}
cancelButton() {
return cy.findByTestId("cancel-button");
}
clearButton() {
return cy.get("button").contains("Clear");
}
clickClearConfirmButton() {
cy.findByTestId("clear-button").click();
}
closeButton() {
return cy.findByTestId("close-button");
}
usersCheckbox() {
return cy.findByTestId("users-checkbox");
}
clientsCheckbox() {
return cy.findByTestId("clients-checkbox");
}
groupsCheckbox() {
return cy.findByTestId("groups-checkbox");
}
idpCheckbox() {
return cy.findByTestId("identityProviders-checkbox");
}
realmRolesCheckbox() {
return cy.findByTestId("realmRoles-checkbox");
}
clientRolesCheckbox() {
return cy.findByTestId("clientRoles-checkbox");
}
userCount() {
return this.usersCheckbox().get("label");
}
clientCount() {
return this.clientsCheckbox().get("label");
}
groupCount() {
return this.groupsCheckbox().get("label");
}
idpCount() {
return this.idpCheckbox().get("label");
}
realmRolesCount() {
return this.realmRolesCheckbox().get("label");
}
clientRolesCount() {
return this.clientRolesCheckbox().get("label");
}
realmSelector() {
return cy.get("#realm-selector");
}
selectRealm(realm: string) {
this.realmSelector().click();
cy.findByTestId(realm + "-select-option").click();
}
}

View File

@@ -1,8 +0,0 @@
export default class RealmSettings {
#actionDropdown = "action-dropdown";
clickActionMenu() {
cy.findByTestId(this.#actionDropdown).click();
return this;
}
}

View File

@@ -1,101 +0,0 @@
export default class AttributesTab {
#saveAttributeBtn = "attributes-save";
#attributesTab = "attributes";
#emptyState = "attributes-empty-state";
#addAttributeBtn: string;
#keyInput: string;
#valueInput: string;
#removeBtn: string;
constructor(isForUser = false) {
if (isForUser) {
this.#addAttributeBtn = "unmanagedAttributes-add-row";
this.#keyInput = "unmanagedAttributes-key";
this.#valueInput = "unmanagedAttributes-value";
this.#removeBtn = "unmanagedAttributes-remove";
} else {
this.#addAttributeBtn = "attributes-add-row";
this.#keyInput = "attributes-key";
this.#valueInput = "attributes-value";
this.#removeBtn = "attributes-remove";
}
}
public goToAttributesTab() {
cy.findByTestId(this.#attributesTab).click();
return this;
}
public addAttribute(key: string, value: string) {
this.addAnAttributeButton();
cy.findAllByTestId(this.#keyInput)
.its("length")
.then((length) => {
this.#keyInputAt(length - 1).type(key, { force: true });
this.#valueInputAt(length - 1).type(value, { force: true });
});
return this;
}
public checkAttribute(key: string, exist: boolean) {
cy.findByTestId(this.#keyInput).should((exist ? "" : "not.") + "exist");
if (exist) {
cy.findAllByTestId(this.#keyInput).invoke("val").should("eq", key);
}
return this;
}
public save() {
cy.findByTestId(this.#saveAttributeBtn).click();
return this;
}
public revert() {
cy.get(".pf-v5-c-button.pf-m-link").contains("Revert").click();
return this;
}
public deleteAttributeButton(row: number) {
this.#removeButtonAt(row).click({ force: true });
return this;
}
public addAnAttributeButton() {
cy.wait(1000);
cy.findByTestId(this.#addAttributeBtn).click();
return this;
}
public deleteAttribute(rowIndex: number) {
this.deleteAttributeButton(rowIndex);
this.save();
return this;
}
public assertEmpty() {
cy.findByTestId(this.#emptyState).should("exist");
}
public assertRowItemsEqualTo(amount: number) {
cy.findAllByTestId(this.#keyInput).its("length").should("be.eq", amount);
return this;
}
#keyInputAt(index: number) {
return cy.findAllByTestId(this.#keyInput).eq(index);
}
#valueInputAt(index: number) {
return cy.findAllByTestId(this.#valueInput).eq(index);
}
#removeButtonAt(index: number) {
return cy.findAllByTestId(this.#removeBtn).eq(index);
}
}

View File

@@ -1,45 +0,0 @@
import type { KeyValueType } from "../../../../../src/components/key-value-form/key-value-convert";
export default class KeyValueInput {
#name: string;
constructor(name: string) {
this.#name = name;
}
fillKeyValue({ key, value }: KeyValueType) {
cy.findByTestId(`${this.#name}-add-row`).click();
cy.findAllByTestId(`${this.#name}-key`)
.its("length")
.then((length) => {
this.keyInputAt(length - 1).type(key);
this.valueInputAt(length - 1).type(value);
});
return this;
}
deleteRow(index: number) {
cy.findAllByTestId(`${this.#name}-remove`).eq(index).click();
return this;
}
validateRows(numberOfRows: number) {
cy.findAllByTestId(`${this.#name}-key`).should("have.length", numberOfRows);
return this;
}
save() {
cy.findByTestId("attributes-save").click();
return this;
}
keyInputAt(index: number) {
return cy.findAllByTestId(`${this.#name}-key`).eq(index);
}
valueInputAt(index: number) {
return cy.findAllByTestId(`${this.#name}-value`).eq(index);
}
}

View File

@@ -1,33 +0,0 @@
import type { KeyValueType } from "../../../../../src/components/key-value-form/key-value-convert";
export default class LegacyKeyValueInput {
#name: string;
constructor(name: string) {
this.#name = name;
}
fillKeyValue({ key, value }: KeyValueType, index = 0) {
cy.findByTestId(`${this.#name}.${index}.key`).clear();
cy.findByTestId(`${this.#name}.${index}.key`).type(key);
cy.findByTestId(`${this.#name}.${index}.value`).clear();
cy.findByTestId(`${this.#name}.${index}.value`).type(value);
cy.findByTestId(`${this.#name}-add-row`).click();
return this;
}
deleteRow(index: number) {
cy.findByTestId(`${this.#name}.${index}.remove`).click();
return this;
}
validateRows(numberOfRows: number) {
cy.findAllByTestId("row").should("have.length", numberOfRows);
return this;
}
save() {
cy.findByTestId("save-attributes").click();
return this;
}
}

View File

@@ -1,111 +0,0 @@
const expect = chai.expect;
export default class RoleMappingTab {
#type = "client";
#serviceAccountTab = "serviceAccountTab";
#scopeTab = "scopeTab";
#assignEmptyRoleBtn = (type: string) =>
`no-roles-for-this-${type}-empty-action`;
#assignRoleBtn = "assignRole";
#unAssignBtn = "unAssignRole";
#unAssignDrpDwnBtn = '.pf-v5-c-table__action li button[role="menuitem"]';
#assignBtn = "assign";
#hideInheritedRolesBtn = "#hideInheritedRoles";
#assignedRolesTable = "assigned-roles";
#namesColumn = "td:visible";
#roleMappingTab = "role-mapping-tab";
#filterTypeDropdown = "filter-type-dropdown";
constructor(type: string) {
this.#type = type;
}
goToServiceAccountTab() {
cy.findByTestId(this.#serviceAccountTab).click();
return this;
}
goToScopeTab() {
cy.findByTestId(this.#scopeTab).click();
return this;
}
assignRole(notEmpty = true) {
cy.findByTestId(
notEmpty ? this.#assignEmptyRoleBtn(this.#type) : this.#assignRoleBtn,
).click();
return this;
}
assign() {
cy.findByTestId(this.#assignBtn).click();
return this;
}
unAssign() {
cy.findByTestId(this.#unAssignBtn).click();
return this;
}
unAssignFromDropdown() {
cy.get(this.#unAssignDrpDwnBtn).click();
return this;
}
hideInheritedRoles() {
cy.get(this.#hideInheritedRolesBtn).check();
return this;
}
unhideInheritedRoles() {
cy.get(this.#hideInheritedRolesBtn).uncheck({ force: true });
return this;
}
changeRoleTypeFilter(filter: string) {
// Invert the filter because the testid of the DropdownItem is the current filter
const option = filter == "roles" ? "clients" : "roles";
cy.findByTestId(this.#filterTypeDropdown).click();
cy.findByTestId(option).click();
cy.get('[role="progressbar"]').should("not.exist");
return this;
}
selectRow(name: string, modal = false) {
cy.get(modal ? ".pf-v5-c-modal-box " : "" + this.#namesColumn)
.contains(name)
.parents("tr")
.within(() => {
cy.get("input").click();
});
return this;
}
checkRoles(roleNames: string[], exist = true) {
if (roleNames.length) {
cy.findByTestId(this.#assignedRolesTable)
.get(this.#namesColumn)
.should((roles) => {
for (let index = 0; index < roleNames.length; index++) {
const roleName = roleNames[index];
if (exist) {
expect(roles).to.contain(roleName);
} else {
expect(roles).not.to.contain(roleName);
}
}
});
} else {
cy.findByTestId(this.#assignedRolesTable).should("not.exist");
}
return this;
}
goToRoleMappingTab() {
cy.findByTestId(this.#roleMappingTab).click();
return this;
}
}

View File

@@ -1,18 +0,0 @@
import ModalUtils from "../../../../util/ModalUtils";
export default class BindFlowModal extends ModalUtils {
#bindingType = "#chooseBindingType";
#dropdownSelectToggleItem = ".pf-v5-c-menu__list > li";
fill(bindingType: string) {
cy.get(this.#bindingType).click();
cy.get(this.#dropdownSelectToggleItem).contains(bindingType).click();
return this;
}
save() {
cy.findAllByTestId("save").click();
return this;
}
}

View File

@@ -1,27 +0,0 @@
import Masthead from "../../Masthead";
const masthead = new Masthead();
export default class CIBAPolicyPage {
static goToTab() {
cy.findByTestId("policies").click();
cy.findByTestId("tab-ciba-policy").click();
return this;
}
static getBackchannelTokenDeliveryModeSelect() {
return cy.get("#cibaBackchannelTokenDeliveryMode");
}
static getExpiresInput() {
return cy.findByTestId("attributes.cibaExpiresIn");
}
static getIntervalInput() {
return cy.findByTestId("attributes.cibaInterval");
}
static assertSaveSuccess() {
masthead.checkNotificationMessage("CIBA policy successfully updated");
}
}

View File

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

View File

@@ -1,120 +0,0 @@
import Select from "../../../../forms/Select";
type RequirementType = "Required" | "Alternative" | "Disabled" | "Conditional";
export default class FlowDetails {
executionExists(name: string, exist = true) {
this.#getExecution(name).should((!exist ? "not." : "") + "exist");
return this;
}
flowExists(name: string) {
cy.findAllByText(name).should("exist");
return this;
}
#getExecution(name: string) {
return cy.findByTestId(name);
}
moveRowTo(from: string, to: string) {
cy.findAllByTestId(from).drag(to);
return this;
}
expectPriorityChange(execution: string, callback: () => void) {
cy.findAllByTestId(execution).then((rowDetails) => {
const executionId = rowDetails.children().attr("data-id");
cy.intercept(
"POST",
`/admin/realms/test*/authentication/executions/${executionId}/lower-priority`,
).as("priority");
callback();
cy.wait("@priority");
});
}
changeRequirement(execution: string, requirement: RequirementType) {
this.#getExecution(execution)
.parentsUntil(".keycloak__authentication__flow-row")
.find(".keycloak__authentication__requirement-dropdown")
.click()
.parent()
.contains(requirement)
.click();
return this;
}
goToDiagram() {
cy.get("#diagramView").click();
return this;
}
#clickEditDropdownForFlow(subFlowName: string, option: string) {
cy.findByTestId(`${subFlowName}-edit-dropdown`)
.click()
.parent()
.contains(option)
.click();
}
addExecution(subFlowName: string, executionTestId: string) {
this.#clickEditDropdownForFlow(subFlowName, "Add execution");
cy.get(".pf-v5-c-pagination").should("exist");
cy.findByTestId(executionTestId).click();
cy.findByTestId("modal-add").click();
return this;
}
addCondition(subFlowName: string, executionTestId: string) {
this.#clickEditDropdownForFlow(subFlowName, "Add condition");
cy.findByTestId(executionTestId).click();
cy.findByTestId("modal-add").click();
return this;
}
addSubFlow(subFlowName: string, name: string) {
this.#clickEditDropdownForFlow(subFlowName, "Add sub-flow");
this.#fillSubFlowModal(subFlowName, name);
return this;
}
clickRowDelete(name: string) {
cy.findByTestId(`${name}-delete`).click();
return this;
}
#fillSubFlowModal(subFlowName: string, name: string) {
cy.get(".pf-v5-c-modal-box__title-text").contains(
"Add sub-flow to " + subFlowName,
);
cy.findByTestId("name").type(name);
cy.findByTestId("modal-add").click();
}
fillCreateForm(
name: string,
description: string,
type: "Basic flow" | "Client flow",
) {
cy.findByTestId("alias").type(name);
cy.findByTestId("description").type(description);
Select.selectItem(cy.get("#providerId"), type);
cy.findByTestId("create").click();
return this;
}
addSubFlowToEmpty(subFlowName: string, name: string) {
cy.findByTestId("addSubFlow").click();
this.#fillSubFlowModal(subFlowName, name);
return this;
}
}

View File

@@ -1,35 +0,0 @@
type Edge = { from: string; to: string };
export default class FlowDiagram {
exists() {
cy.get(".react-flow").should("exist");
}
edgesExist(edges: Edge[]) {
edges.forEach((edge) => {
this.#labelToId(edge.from).then((fromId) => {
this.#labelToId(edge.to).then((toId) => {
const label = `Edge from ${fromId} to ${toId}`;
cy.get(`[aria-label="${label}"]`);
});
});
});
return this;
}
#labelToId(label: string) {
return cy.findByText(label).then((node) => {
const id = node.attr("data-id");
if (id) {
return cy.wrap(id);
}
// if data-id does not exist, we're looking at a subflow, which has the data-id
// on the grandparent
return cy
.wrap(node)
.parent()
.parent()
.then((n) => cy.wrap(n.attr("data-id")));
});
}
}

View File

@@ -1,28 +0,0 @@
export default class OTPPolicies {
goToTab() {
cy.findAllByTestId("policies").click().get("#pf-tab-2-otpPolicy").click();
return this;
}
setPolicyType(type: string) {
cy.findByTestId(type).click();
return this;
}
increaseInitialCounter() {
cy.get('#otpPolicyInitialCounter [aria-label="Plus"]').click();
return this;
}
checkSupportedApplications(...supportedApplications: string[]) {
cy.findByTestId("supportedApplications")
.children()
.should("have.text", supportedApplications.join(""));
return this;
}
save() {
cy.findByTestId("save").click();
return this;
}
}

View File

@@ -1,26 +0,0 @@
export default class PasswordPolicies {
goToTab() {
cy.findAllByTestId("policies").click();
return this;
}
shouldShowEmptyState() {
cy.findByTestId("empty-state").should("exist");
return this;
}
addPolicy(name: string) {
cy.findByTestId("add-policy").click().parent().contains(name).click();
return this;
}
removePolicy(name: string) {
cy.findByTestId(name).click();
return this;
}
save() {
cy.findByTestId("save").click();
return this;
}
}

View File

@@ -1,52 +0,0 @@
export default class RequiredActions {
#toId(name: string) {
return name.replace(/\s/g, "\\ ");
}
#toKey(name: string) {
return name.replace(/\s/g, "-");
}
#getEnabledSwitch(name: string) {
return `#enable-${this.#toKey(name)}`;
}
#getDefaultSwitch(name: string) {
return `#default-${this.#toKey(name)}`;
}
goToTab() {
cy.findByTestId("requiredActions").click();
}
switchAction(name: string) {
cy.get(this.#getEnabledSwitch(name)).scrollIntoView();
cy.get(this.#getEnabledSwitch(name)).click({ force: true });
return this;
}
isChecked(name: string) {
cy.get(this.#getEnabledSwitch(name)).should("be.checked");
return this;
}
isDefaultEnabled(name: string) {
cy.get(this.#getDefaultSwitch(name)).should("be.enabled");
return this;
}
setAsDefault(name: string) {
cy.get(this.#getDefaultSwitch(name)).click({ force: true });
return this;
}
isDefaultChecked(name: string) {
cy.get(this.#getEnabledSwitch(name)).should("be.checked");
return this;
}
moveRowTo(from: string, to: string) {
cy.get("#" + this.#toId(from)).drag("#" + this.#toId(to));
return this;
}
}

View File

@@ -1,35 +0,0 @@
export default class WebAuthnPolicies {
webAuthnPolicyCreateTimeout(value: number) {
cy.findByTestId("webAuthnPolicyCreateTimeout").clear();
cy.findByTestId("webAuthnPolicyCreateTimeout").type(String(value));
return this;
}
goToTab() {
cy.findByTestId("policies").click();
cy.get("#pf-tab-3-webauthnPolicy").click();
return this;
}
goToPasswordlessTab() {
cy.findByTestId("policies").click();
cy.get("#pf-tab-4-webauthnPasswordlessPolicy").click();
return this;
}
fillSelects(data: Record<string, string>, isPasswordLess: boolean = false) {
for (const prop of Object.keys(data)) {
cy.get(
`#${
isPasswordLess ? prop.replace("Policy", "PolicyPasswordless") : prop
}`,
).click();
cy.get(".pf-v5-c-menu__list").contains(data[prop]).click();
}
return this;
}
save() {
cy.findByTestId("save").click();
return this;
}
}

View File

@@ -1,115 +0,0 @@
import CommonPage from "../../../CommonPage";
export default class CreateClientScopePage extends CommonPage {
settingsTab: string;
mappersTab: string;
clientScopeNameInput: string;
clientScopeNameError: string;
clientScopeDescriptionInput: string;
clientScopeTypeDrpDwn: string;
clientScopeTypeList: string;
displayOnConsentInput: string;
displayOnConsentSwitch: string;
consentScreenTextInput: string;
includeInTokenSwitch: string;
displayOrderInput: string;
saveBtn: string;
cancelBtn: string;
constructor() {
super();
this.settingsTab = ".pf-v5-c-tabs__item:nth-child(1)";
this.mappersTab = ".pf-v5-c-tabs__item:nth-child(2)";
this.clientScopeNameInput = "name";
this.clientScopeNameError = "#name-helper";
this.clientScopeDescriptionInput = "description";
this.clientScopeTypeDrpDwn = "#kc-protocol";
this.clientScopeTypeList = "#kc-protocol + ul";
this.displayOnConsentInput = "attributes.display🍺on🍺consent🍺screen";
this.displayOnConsentSwitch =
'[for="attributes.display🍺on🍺consent🍺screen"] .pf-v5-c-switch__toggle';
this.consentScreenTextInput = "attributes.consent🍺screen🍺text";
this.includeInTokenSwitch = "#attributes.include🍺in🍺token🍺scope-on";
this.displayOrderInput = "attributes.gui🍺order";
this.saveBtn = '[type="submit"]';
this.cancelBtn = '[type="button"]';
}
//#region General Settings
fillClientScopeData(
name: string,
description = "",
consentScreenText = "",
displayOrder = "",
) {
cy.findByTestId(this.clientScopeNameInput).clear();
if (name) {
cy.findByTestId(this.clientScopeNameInput).type(name);
}
if (description) {
cy.findByTestId(this.clientScopeDescriptionInput).type(description);
}
if (consentScreenText) {
cy.findByTestId(this.consentScreenTextInput).type(consentScreenText);
}
if (displayOrder) {
cy.findByTestId(this.displayOrderInput).type(displayOrder);
}
return this;
}
selectClientScopeType(clientScopeType: string) {
cy.get(this.clientScopeTypeDrpDwn).click();
cy.get(this.clientScopeTypeList).contains(clientScopeType).click();
return this;
}
getSwitchDisplayOnConsentScreenInput() {
return cy.findByTestId(this.displayOnConsentInput);
}
getConsentScreenTextInput() {
return cy.findByTestId(this.consentScreenTextInput);
}
switchDisplayOnConsentScreen() {
cy.get(this.displayOnConsentSwitch).click();
return this;
}
switchIncludeInTokenScope() {
cy.get(this.includeInTokenSwitch).click();
return this;
}
//#endregion
save() {
cy.get(this.saveBtn).click();
return this;
}
save_is_disabled(value: boolean) {
cy.get(this.saveBtn)
.invoke("attr", "aria-disabled")
.should("eq", value ? "true" : "false");
return this;
}
cancel() {
cy.get(this.cancelBtn).click();
return this;
}
}

View File

@@ -1,31 +0,0 @@
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 {
#settingsTab = new SettingsTab();
#scopesTab = new ScopeTab();
#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;
}
}

View File

@@ -1,64 +0,0 @@
import CommonPage from "../../../../../CommonPage";
export default class MappersTab extends CommonPage {
#addMapperBtn = "#mapperAction";
#fromPredefinedMappersBtn =
'ul[class="pf-v5-c-menu__list"] > li:nth-child(1) button';
#byConfigurationBtn =
'ul[class="pf-v5-c-menu__list"] > li:nth-child(2) button';
#mapperConfigurationList =
'ul[aria-label="Add predefined mappers"] > li:not([id=header])';
#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;
}
}

View File

@@ -1,3 +0,0 @@
import CommonPage from "../../../../../CommonPage";
export default class ScopeTab extends CommonPage {}

View File

@@ -1,3 +0,0 @@
import PageObject from "../../../../components/PageObject";
export default class SettingsTab extends PageObject {}

View File

@@ -1,52 +0,0 @@
import CommonPage from "../../../../../../CommonPage";
export enum ClaimJsonType {
String = "String",
Long = "long",
Int = "int",
Boolean = "boolean",
Json = "JSON",
}
export default class MapperDetailsPage extends CommonPage {
#userAttributeInput = '[data-testid="config.user🍺attribute"]';
#tokenClaimNameInput = '[data-testid="claim.name"]';
#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;
}
}

View File

@@ -1,52 +0,0 @@
import CommonPage from "../../../CommonPage";
export class ClientRegistrationPage extends CommonPage {
goToClientRegistrationTab() {
this.tabUtils().clickTab("registration");
return this;
}
goToAuthenticatedSubTab() {
cy.findAllByTestId("authenticated").click();
return this;
}
createPolicy() {
cy.findAllByTestId("createPolicy").click({ force: true });
return this;
}
createAnonymousPolicy() {
cy.findByTestId("createPolicy-anonymous").click();
return this;
}
createAuthenticatedPolicy() {
cy.findByTestId("createPolicy-authenticated").click();
return this;
}
findAndSelectInAnonymousPoliciesTable(policy: string) {
cy.findByTestId("clientRegistration-anonymous")
.find("tr")
.contains(policy)
.click();
}
findAndSelectInAuthenticatedPoliciesTable(policy: string) {
cy.findByTestId("clientRegistration-authenticated")
.find("tr")
.contains(policy)
.click();
}
selectRow(name: string) {
cy.findAllByTestId(name).click();
return this;
}
fillPolicyForm(props: { name: string }) {
cy.findAllByTestId("name").type(props.name);
return this;
}
}

View File

@@ -1,78 +0,0 @@
import CommonPage from "../../../CommonPage";
enum ClientRolesTabItems {
Details = "Details",
Attributes = "Attributes",
UsersInRole = "Users in role",
Permissions = "Permissions",
}
export default class ClientRolesTab extends CommonPage {
#createRoleBtn = "create-role";
#createRoleEmptyStateBtn = "no-roles-for-this-client-empty-action";
#hideInheritedRolesChkBox = "#hideInheritedRoles";
#rolesTab = "rolesTab";
#associatedRolesTab = "associatedRolesTab";
#defaultRolesTab = "default-roles-tab";
#defaultGroupsTab = "default-groups-tab";
goToDetailsTab() {
this.tabUtils().clickTab(ClientRolesTabItems.Details);
return this;
}
goToAttributesTab() {
this.tabUtils().clickTab(ClientRolesTabItems.Attributes);
return this;
}
goToUsersInRoleTab() {
this.tabUtils().clickTab(ClientRolesTabItems.UsersInRole);
return this;
}
goToPermissionsTab() {
this.tabUtils().clickTab(ClientRolesTabItems.Permissions);
return this;
}
goToRolesTab() {
cy.findByTestId(this.#rolesTab).click();
return this;
}
goToAssociatedRolesTab() {
cy.findByTestId(this.#associatedRolesTab).click();
return this;
}
goToCreateRoleFromToolbar() {
cy.findByTestId(this.#createRoleBtn).click();
return this;
}
goToCreateRoleFromEmptyState() {
cy.findByTestId(this.#createRoleEmptyStateBtn).click();
return this;
}
fillClientRoleData() {
cy.findByTestId(this.#createRoleBtn).click();
return this;
}
hideInheritedRoles() {
cy.get(this.#hideInheritedRolesChkBox).check();
return this;
}
goToDefaultRolesTab() {
cy.findByTestId(this.#defaultRolesTab).click();
return this;
}
goToDefaultGroupsTab() {
cy.findByTestId(this.#defaultGroupsTab).click();
return this;
}
}

View File

@@ -1,23 +0,0 @@
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 {
#clientsListTab = new ClientsListTab();
#initialAccessTokenTab = new InitialAccessTokenTab();
goToClientsListTab() {
this.tabUtils().clickTab(ClientsTab.ClientsList);
return this.#clientsListTab;
}
goToInitialAccessTokenTab() {
this.tabUtils().clickTab(ClientsTab.InitialAccessToken);
return this.#initialAccessTokenTab;
}
}

View File

@@ -1,309 +0,0 @@
import Select from "../../../../forms/Select";
import CommonPage from "../../../CommonPage";
export default class CreateClientPage extends CommonPage {
#clientTypeDrpDwn = "#protocol";
#clientIdInput = "#clientId";
#clientIdError = "#clientId + div";
#clientNameInput = "#name";
#clientDescriptionInput = "#kc-description";
#alwaysDisplayInUISwitch =
'[for="kc-always-display-in-ui-switch"] .pf-v5-c-switch__toggle';
#frontchannelLogoutSwitch =
'[for="kc-frontchannelLogout-switch"] .pf-v5-c-switch__toggle';
#clientAuthenticationSwitch =
'[for="kc-authentication-switch"] > .pf-v5-c-switch__toggle';
#clientAuthenticationSwitchInput = "#kc-authentication-switch";
#clientAuthorizationSwitch =
'[for="kc-authorization-switch"] > .pf-v5-c-switch__toggle';
#clientAuthorizationSwitchInput = "#kc-authorization-switch";
#standardFlowChkBx = "#kc-flow-standard";
#directAccessChkBx = "#kc-flow-direct";
#implicitFlowChkBx = "#kc-flow-implicit";
#oidcCibaGrantChkBx = "#kc-oidc-ciba-grant";
#deviceAuthGrantChkBx = "#kc-oauth-device-authorization-grant";
#serviceAccountRolesChkBx = "#kc-flow-service-account";
#rootUrlInput = "rootUrl";
#homeUrlInput = "baseUrl";
#firstValidRedirectUrlInput = "redirectUris0";
#firstWebOriginsInput = "webOrigins0";
#adminUrlInput = "adminUrl";
#loginThemeDrpDwn = "#login_theme";
#loginThemeList = 'ul[class="pf-v5-c-menu__list"]';
#consentRequiredSwitch = '[for="consentRequired"] .pf-v5-c-switch__toggle';
#consentRequiredSwitchInput = "#consentRequired";
#displayClientOnScreenSwitch =
'[for="attributes.display🍺on🍺consent🍺screen"].pf-v5-c-switch';
#displayClientOnScreenSwitchInput =
"#attributes\\.display🍺on🍺consent🍺screen";
#clientConsentScreenText = "attributes.consent🍺screen🍺text";
#frontChannelLogoutSwitch =
'[for="kc-frontchannelLogout-switch"] > .pf-v5-c-switch__toggle';
#frontChannelLogoutSwitchInput = "#kc-frontchannelLogout-switch";
#frontChannelLogoutInput = "frontchannelLogoutUrl";
#frontChannelLogoutSessionRequiredSwitchInput =
"#attributes\\.frontchannel🍺logout🍺session🍺required";
#backChannelLogoutInput = "backchannelLogoutUrl";
#backChannelLogoutSessionRequiredSwitchInput =
"#backchannelLogoutSessionRequired";
#backChannelLogoutRevoqueSwitch =
'.pf-v5-c-form__group-control [for="backchannelLogoutRevokeOfflineSessions"] > .pf-v5-c-switch__toggle';
#backChannelLogoutRevoqueSwitchInput =
"#backchannelLogoutRevokeOfflineSessions";
#actionDrpDwn = "action-dropdown";
#deleteClientBtn = "delete-client";
#saveBtn = "Save";
#continueBtn = "Next";
#backBtn = "Back";
#cancelBtn = "Cancel";
//#region General Settings
selectClientType(clientType: string) {
Select.selectItem(cy.get(this.#clientTypeDrpDwn), clientType);
return this;
}
fillClientData(
id: string,
name = "",
description = "",
alwaysDisplay?: boolean,
frontchannelLogout?: boolean,
) {
cy.get(this.#clientIdInput).clear();
if (id) {
cy.get(this.#clientIdInput).type(id);
}
if (name) {
cy.get(this.#clientNameInput).type(name);
}
if (description) {
cy.get(this.#clientDescriptionInput).type(description);
}
if (alwaysDisplay) {
cy.get(this.#alwaysDisplayInUISwitch).click();
}
if (frontchannelLogout) {
cy.get(this.#frontchannelLogoutSwitch).click();
}
return this;
}
changeSwitches(switches: string[]) {
for (const uiSwitch of switches) {
cy.findByTestId(uiSwitch).check({ force: true });
}
return this;
}
checkClientIdRequiredMessage() {
cy.get(this.#clientIdInput)
.parent()
.should("have.class", "pf-v5-c-form-control pf-m-error");
return this;
}
checkGeneralSettingsStepActive() {
cy.get(".pf-v5-c-wizard__nav-link")
.contains("General settings")
.should("have.class", "pf-m-current");
return this;
}
//#endregion
//#region Capability config
switchClientAuthentication() {
cy.get(this.#clientAuthenticationSwitch).click();
return this;
}
switchClientAuthorization() {
cy.get(this.#clientAuthorizationSwitch).click();
return this;
}
clickStandardFlow() {
cy.get(this.#standardFlowChkBx).click();
return this;
}
clickDirectAccess() {
cy.get(this.#directAccessChkBx).click();
return this;
}
clickImplicitFlow() {
cy.get(this.#implicitFlowChkBx).click();
return this;
}
clickServiceAccountRoles() {
cy.get(this.#serviceAccountRolesChkBx).click();
return this;
}
clickOAuthDeviceAuthorizationGrant() {
cy.get(this.#deviceAuthGrantChkBx).click();
return this;
}
clickOidcCibaGrant() {
cy.get(this.#oidcCibaGrantChkBx).click();
return this;
}
//#endregion
save() {
cy.contains("button", this.#saveBtn).click();
return this;
}
continue() {
cy.contains("button", this.#continueBtn).click();
return this;
}
back() {
cy.contains("button", this.#backBtn).click();
return this;
}
cancel() {
cy.contains("button", this.#cancelBtn).click();
return this;
}
checkCapabilityConfigElements() {
cy.get(this.#oidcCibaGrantChkBx).scrollIntoView();
cy.get(this.#clientAuthenticationSwitchInput).should("not.be.disabled");
cy.get(this.#clientAuthorizationSwitchInput).should("be.disabled");
cy.get(this.#standardFlowChkBx).should("not.be.disabled");
cy.get(this.#directAccessChkBx).should("not.be.disabled");
cy.get(this.#implicitFlowChkBx).should("not.be.disabled");
cy.get(this.#serviceAccountRolesChkBx).should("be.disabled");
cy.get(this.#deviceAuthGrantChkBx).should("not.be.disabled");
cy.get(this.#oidcCibaGrantChkBx).should("be.disabled");
cy.get(this.#clientAuthenticationSwitch).click();
cy.get(this.#clientAuthorizationSwitchInput).should("not.be.disabled");
cy.get(this.#serviceAccountRolesChkBx).should("not.be.disabled");
cy.get(this.#oidcCibaGrantChkBx).should("not.be.disabled");
cy.get(this.#clientAuthorizationSwitch).click();
cy.get(this.#serviceAccountRolesChkBx).should("be.disabled");
cy.get(this.#oidcCibaGrantChkBx).should("not.be.disabled");
cy.get(this.#clientAuthorizationSwitch).click();
cy.get(this.#serviceAccountRolesChkBx).should("not.be.disabled");
cy.get(this.#clientAuthenticationSwitch).click();
cy.get(this.#serviceAccountRolesChkBx).should("be.disabled");
cy.get(this.#oidcCibaGrantChkBx).should("be.disabled");
return this;
}
checkAccessSettingsElements() {
cy.findByTestId(this.#adminUrlInput).scrollIntoView();
cy.findByTestId(this.#rootUrlInput).should("not.be.disabled");
cy.findByTestId(this.#homeUrlInput).should("not.be.disabled");
cy.findByTestId(this.#firstValidRedirectUrlInput).should("not.be.disabled");
cy.findByTestId(this.#firstWebOriginsInput).should("not.be.disabled");
cy.findByTestId(this.#adminUrlInput).should("not.be.disabled");
return this;
}
checkLoginSettingsElements() {
cy.findByTestId(this.#clientConsentScreenText).scrollIntoView();
cy.get(this.#loginThemeDrpDwn).should("not.be.disabled");
cy.get(this.#consentRequiredSwitchInput).should("not.be.disabled");
cy.get(this.#displayClientOnScreenSwitchInput).should("be.disabled");
cy.findByTestId(this.#clientConsentScreenText).should("be.disabled");
cy.get(this.#loginThemeDrpDwn).click();
cy.get(this.#loginThemeList).findByText("base").should("exist");
cy.get(this.#loginThemeList).findByText("keycloak").should("exist");
cy.get(this.#loginThemeDrpDwn).click();
cy.get(this.#consentRequiredSwitch).click();
cy.get(this.#displayClientOnScreenSwitchInput).should("not.be.disabled");
cy.findByTestId(this.#clientConsentScreenText).should("be.disabled");
cy.get(this.#displayClientOnScreenSwitch).click();
cy.findByTestId(this.#clientConsentScreenText).should("not.be.disabled");
cy.get(this.#displayClientOnScreenSwitch).click();
cy.findByTestId(this.#clientConsentScreenText).should("be.disabled");
cy.get(this.#consentRequiredSwitch).click();
cy.get(this.#displayClientOnScreenSwitchInput).should("be.disabled");
return this;
}
checkLogoutSettingsElements() {
cy.get(this.#frontChannelLogoutSessionRequiredSwitchInput).scrollIntoView();
cy.get(this.#frontChannelLogoutSwitchInput).should("not.be.disabled");
cy.findByTestId(this.#frontChannelLogoutInput).should("not.be.disabled");
cy.get(this.#frontChannelLogoutSessionRequiredSwitchInput).should(
"not.be.disabled",
);
cy.findByTestId(this.#backChannelLogoutInput).should("not.exist");
cy.get(this.#backChannelLogoutSessionRequiredSwitchInput).should(
"not.exist",
);
cy.get(this.#backChannelLogoutRevoqueSwitchInput).should("not.exist");
cy.get(this.#frontChannelLogoutSwitch).click();
cy.findByTestId(this.#frontChannelLogoutInput).should("not.exist");
cy.get(this.#frontChannelLogoutSessionRequiredSwitchInput).should(
"not.exist",
);
cy.findByTestId(this.#backChannelLogoutInput).should("not.be.disabled");
cy.get(this.#backChannelLogoutSessionRequiredSwitchInput).should(
"not.be.disabled",
);
cy.get(this.#backChannelLogoutRevoqueSwitchInput).should("not.be.disabled");
cy.get(this.#frontChannelLogoutSwitch).click();
cy.findByTestId(this.#frontChannelLogoutInput).should("not.be.disabled");
return this;
}
deleteClientFromActionDropdown() {
cy.findAllByTestId(this.#actionDrpDwn).click();
cy.findAllByTestId(this.#deleteClientBtn).click();
return this;
}
}

View File

@@ -1,18 +0,0 @@
import CommonPage from "../../../CommonPage";
export default class CreateInitialAccessTokenPage extends CommonPage {
#expirationInput = "expiration";
#countInput = "count";
#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;
}
}

View File

@@ -1,111 +0,0 @@
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",
Sessions = "Sessions",
Permissions = "Permissions",
ClientScopes = "Client scopes",
Authorization = "Authorization",
ServiceAccountsRoles = "Service accounts roles",
Advanced = "Advanced",
Scope = "Scope",
UserEvents = "Events",
}
export default class ClientDetailsPage extends CommonPage {
#settingsTab = new SettingsTab();
#keysTab = new KeysTab();
#credentialsTab = new CredentialsTab();
#rolesTab = new RolesTab();
#clientScopesTab = new ClientScopesTab();
#authorizationTab = new AuthorizationTab();
#advancedTab = new AdvancedTab();
#clientScopesSetupTab = "clientScopesSetupTab";
#clientScopesEvaluateTab = "clientScopesEvaluateTab";
#evaluateEffectiveProtocolMappersTab = "effective-protocol-mappers-tab";
#evaluateEffectiveRoleScopeMappingsTab = "effective-role-scope-mappings-tab";
#evaluateGeneratedAccessTokenTab = "generated-access-token-tab";
#evaluateGeneratedIdTokenTab = "generated-id-token-tab";
#evaluateGeneratedUserInfoTab = "generated-user-info-tab";
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;
}
goToClientScopesSetupTab() {
cy.findByTestId(this.#clientScopesSetupTab).click();
return this;
}
goToClientScopesEvaluateTab() {
this.goToClientScopesTab();
cy.findByTestId(this.#clientScopesEvaluateTab).click();
return this;
}
goToClientScopesEvaluateEffectiveProtocolMappersTab() {
cy.findByTestId(this.#evaluateEffectiveProtocolMappersTab).click();
return this;
}
goToClientScopesEvaluateEffectiveRoleScopeMappingsTab() {
cy.findByTestId(this.#evaluateEffectiveRoleScopeMappingsTab).click();
return this;
}
goToClientScopesEvaluateGeneratedAccessTokenTab() {
cy.findByTestId(this.#evaluateGeneratedAccessTokenTab).click();
return this;
}
goToClientScopesEvaluateGeneratedIdTokenTab() {
cy.findByTestId(this.#evaluateGeneratedIdTokenTab).click();
return this;
}
goToClientScopesEvaluateGeneratedUserInfoTab() {
cy.findByTestId(this.#evaluateGeneratedUserInfoTab).click();
return this;
}
}

View File

@@ -1,9 +0,0 @@
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;
}
}

Some files were not shown because too many files have changed in this diff Show More