mirror of
https://github.com/keycloak/keycloak.git
synced 2025-12-17 04:24:48 -06:00
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:
20
.github/actions/cypress-cache/action.yml
vendored
20
.github/actions/cypress-cache/action.yml
vendored
@@ -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 }}
|
||||
10
.github/actions/pnpm-setup/action.yml
vendored
10
.github/actions/pnpm-setup/action.yml
vendored
@@ -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
|
||||
|
||||
51
.github/workflows/js-ci.yml
vendored
51
.github/workflows/js-ci.yml
vendored
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -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 wouldn’t 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)
|
||||
@@ -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",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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"');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
@@ -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", "");
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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!);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"port": 3004,
|
||||
"searchBase": "dc=test"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
[
|
||||
{
|
||||
"dn": "cn=user,dc=test",
|
||||
"objectClass": "person",
|
||||
"cn": "user-login"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
export const SERVER_URL = "http://localhost:8080";
|
||||
@@ -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')
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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"]`));
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export default class ListingPage {
|
||||
#actionMenu = "action-dropdown";
|
||||
|
||||
clickAction(action: string) {
|
||||
cy.findByTestId(this.#actionMenu).click().findByTestId(action).click();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import CommonElements from "../../CommonElements";
|
||||
|
||||
export default class EmptyStatePage extends CommonElements {
|
||||
constructor() {
|
||||
super(".pf-v5-c-empty-state__content");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export default class RealmSettings {
|
||||
#actionDropdown = "action-dropdown";
|
||||
|
||||
clickActionMenu() {
|
||||
cy.findByTestId(this.#actionDropdown).click();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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")));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import CommonPage from "../../../../../CommonPage";
|
||||
|
||||
export default class ScopeTab extends CommonPage {}
|
||||
@@ -1,3 +0,0 @@
|
||||
import PageObject from "../../../../components/PageObject";
|
||||
|
||||
export default class SettingsTab extends PageObject {}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user