Add cypress framework (#271)
* Add cypress framework * Add PR change requests * Add initial .yml file for cypress tests * Modify Run Keycloak line * Modify Run Keycloak lines * Modify Cypress test run * Modify wait times * Add more time * Modify yarn start to npx http-server * Try Cypress separate step * Add test to set new admin console * Modify uses to run * Change yarn to npx http-server * Add parameter to npx http-server * Trigger GitHub actions * Trigger GitHub actions * Modify client_scope test messages * Set headless mode * Add steps to store artifacts * Modify .yml * Rebase onto realm fix and update real role message * Update yaml file for artifact upload
This commit is contained in:
parent
ce0ce6d59e
commit
daec4957f2
29 changed files with 6601 additions and 3 deletions
53
.github/workflows/cypress.yml
vendored
Normal file
53
.github/workflows/cypress.yml
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
name: Cypress run
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
cypress-run:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- run: npm install -g yarn
|
||||||
|
- run: yarn install
|
||||||
|
- run: yarn build
|
||||||
|
|
||||||
|
- name: Run Keycloak
|
||||||
|
run: ./start.js & sleep 40
|
||||||
|
|
||||||
|
- name: Run Admin Console
|
||||||
|
run: npx http-server ./build -P http://localhost:8180/auth/ & sleep 30
|
||||||
|
|
||||||
|
- name: Create admin user and add Admin Console client
|
||||||
|
run: cd tests && npx cypress run --headless --browser chrome --spec cypress/integration/00_set_new_admin_console.spec.js && cd ..
|
||||||
|
|
||||||
|
- name: Cypress run
|
||||||
|
run: cd tests && npx cypress run --headless --browser chrome --config ignoreTestFiles=00_set_new_admin_console.spec.js && cd ..
|
||||||
|
|
||||||
|
- name: Add Cypress videos artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: cypress-videos
|
||||||
|
path: tests/assets/videos
|
||||||
|
|
||||||
|
- name: Add Cypress screenshots artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: cypress-screenshots
|
||||||
|
path: tests/assets/screenshots
|
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -114,7 +114,7 @@ temp/
|
||||||
**/*.backup.*
|
**/*.backup.*
|
||||||
**/*.back.*
|
**/*.back.*
|
||||||
|
|
||||||
node_modules
|
**/node_modules
|
||||||
|
|
||||||
*.sublime*
|
*.sublime*
|
||||||
|
|
||||||
|
@ -135,4 +135,9 @@ server/
|
||||||
|
|
||||||
# VS Code #
|
# VS Code #
|
||||||
###########
|
###########
|
||||||
*.code-workspace
|
**/*.code-workspace
|
||||||
|
|
||||||
|
# Cypress #
|
||||||
|
###########
|
||||||
|
**/assets
|
||||||
|
**/cypress.env.json
|
||||||
|
|
|
@ -13,7 +13,9 @@
|
||||||
"postinstall": "grunt",
|
"postinstall": "grunt",
|
||||||
"start": "snowpack dev",
|
"start": "snowpack dev",
|
||||||
"storybook": "start-storybook -p 6006 -s public",
|
"storybook": "start-storybook -p 6006 -s public",
|
||||||
"test": "jest"
|
"test": "jest",
|
||||||
|
"start:cypress": "cd tests && npx cypress open",
|
||||||
|
"start:cypress-tests": "cd tests && npx cypress run --config ignoreTestFiles=00_set_new_admin_console.spec.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@patternfly/patternfly": "^4.65.6",
|
"@patternfly/patternfly": "^4.65.6",
|
||||||
|
|
72
tests/README.md
Normal file
72
tests/README.md
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
# Keycloak UI Test Suite in Cypress
|
||||||
|
|
||||||
|
This repository contains the UI tests for Keycloak developed with Cypress framework
|
||||||
|
|
||||||
|
## Run the test suite
|
||||||
|
### Prerequisites
|
||||||
|
* `Keycloak distribution` has to be [downloaded](https://www.keycloak.org/downloads) and started on 8081 port.
|
||||||
|
**note**: the port in at the test suite side in [cypress.json](cypress.json) or at the Keycloak side, see [Keycloak Getting Started Guide](https://www.keycloak.org/docs/latest/getting_started/#starting-the-keycloak-server),
|
||||||
|
* `npm package manager` has to be [downloaded](https://nodejs.org/en/download/) and installed.
|
||||||
|
|
||||||
|
### via Cypress Test Runner
|
||||||
|
|
||||||
|
**By using `npx`:**
|
||||||
|
|
||||||
|
**note**: [npx](https://www.npmjs.com/package/npx) is included with `npm > v5.2` or can be installed separately.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx cypress open
|
||||||
|
```
|
||||||
|
|
||||||
|
After a moment, the Cypress Test Runner will launch:
|
||||||
|
|
||||||
|
![image](https://drive.google.com/uc?export=view&id=1i4_VABpM29VwrrAcvEY31w7EuymifcwV)
|
||||||
|
|
||||||
|
### via terminal
|
||||||
|
|
||||||
|
**By executing:**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$(npm bin)/cypress run
|
||||||
|
```
|
||||||
|
|
||||||
|
...or...
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./node_modules/.bin/cypress run
|
||||||
|
```
|
||||||
|
|
||||||
|
...or... (requires npm@5.2.0 or greater)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx cypress run
|
||||||
|
```
|
||||||
|
**To execute a specific test on a specific browser run:**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cypress run --spec "cypress/integration/example-test.spec.js" --browser chrome
|
||||||
|
```
|
||||||
|
**note**: the complete list of parameters can be found in the [official Cypress documentation](https://docs.cypress.io/guides/guides/command-line.html#Commands).
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```text
|
||||||
|
/assets (added to .gitignore)
|
||||||
|
/videos - if test fails, the video is stored here
|
||||||
|
/screenshots - if test fails, the screenshot is stored here
|
||||||
|
/cypress
|
||||||
|
/fixtures - external pieces of static data that can be used by your tests
|
||||||
|
/integration - used for test files (supported filetypes are .js, .jsx, .coffee and .cjsx)
|
||||||
|
/plugins
|
||||||
|
- index.js - extends Cypress behaviour, custom plugins are imported before every single spec file run
|
||||||
|
/support - reusable behaviour
|
||||||
|
- commands.js - custom commands
|
||||||
|
- index.js - runs before each test file
|
||||||
|
|
||||||
|
/cypress.json - Cypress configuration file
|
||||||
|
/jsconfig.json - Cypress code autocompletion is enabled here
|
||||||
|
```
|
||||||
|
**note**: More about the project structure in the [official Cypress documentation](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Folder-Structure).
|
||||||
|
## License
|
||||||
|
|
||||||
|
* [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
8
tests/cypress.json
Normal file
8
tests/cypress.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"screenshotsFolder": "assets/screenshots",
|
||||||
|
"videosFolder": "assets/videos",
|
||||||
|
"baseUrl": "http://localhost:8080",
|
||||||
|
"chromeWebSecurity": false,
|
||||||
|
"viewportWidth": 1360,
|
||||||
|
"viewportHeight": 768
|
||||||
|
}
|
5
tests/cypress/fixtures/example.json
Normal file
5
tests/cypress/fixtures/example.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name": "Using fixtures to represent data",
|
||||||
|
"email": "hello@cypress.io",
|
||||||
|
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||||
|
}
|
28
tests/cypress/integration/00_set_new_admin_console.spec.js
Normal file
28
tests/cypress/integration/00_set_new_admin_console.spec.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import LoginPage from '../support/pages/LoginPage.js'
|
||||||
|
import WelcomePage from '../support/pages/WelcomePage.js'
|
||||||
|
import OldClientPage from '../support/pages/admin_console/manage/clients/OldClientPage.js'
|
||||||
|
|
||||||
|
describe('Set up test', function () {
|
||||||
|
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const welcomePage = new WelcomePage();
|
||||||
|
const oldClientPage = new OldClientPage();
|
||||||
|
|
||||||
|
describe('Set up test', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('http://localhost:8180/auth')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Create admin user and adds admin console client', function () {
|
||||||
|
welcomePage
|
||||||
|
.createAdminUser()
|
||||||
|
.goToAdminConsole();
|
||||||
|
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
oldClientPage
|
||||||
|
.goToClients()
|
||||||
|
.addNewAdminConsole();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
85
tests/cypress/integration/client_scopes_test.spec.js
Normal file
85
tests/cypress/integration/client_scopes_test.spec.js
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import LoginPage from '../support/pages/LoginPage.js'
|
||||||
|
import HeaderPage from '../support/pages/admin_console/HeaderPage.js'
|
||||||
|
import ListingPage from '../support/pages/admin_console/ListingPage.js'
|
||||||
|
import SidebarPage from '../support/pages/admin_console/SidebarPage.js'
|
||||||
|
import CreateClientScopePage from '../support/pages/admin_console/manage/client_scopes/CreateClientScopePage.js'
|
||||||
|
|
||||||
|
describe('Client Scopes test', function () {
|
||||||
|
|
||||||
|
const itemId = 'client_scope_1';
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const headerPage = new HeaderPage();
|
||||||
|
const sidebarPage = new SidebarPage();
|
||||||
|
const listingPage = new ListingPage();
|
||||||
|
const createClientScopePage = new CreateClientScopePage();
|
||||||
|
|
||||||
|
describe('Client Scope creation', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail creating client scope', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToClientScopes();
|
||||||
|
|
||||||
|
listingPage.goToCreateItem();
|
||||||
|
|
||||||
|
createClientScopePage
|
||||||
|
.save()
|
||||||
|
.checkClientNameRequiredMessage();
|
||||||
|
|
||||||
|
createClientScopePage
|
||||||
|
.fillClientScopeData('address')
|
||||||
|
.save()
|
||||||
|
.checkClientNameRequiredMessage(false);
|
||||||
|
|
||||||
|
// The error should inform about duplicated name/id
|
||||||
|
headerPage.checkNotificationMessage('Could not create client scope: \'Error: Request failed with status code 409\'');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create client scope', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToClientScopes();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId, false)
|
||||||
|
.goToCreateItem();
|
||||||
|
|
||||||
|
createClientScopePage
|
||||||
|
.fillClientScopeData(itemId)
|
||||||
|
.save();
|
||||||
|
|
||||||
|
headerPage.checkNotificationMessage('Client scope created');
|
||||||
|
|
||||||
|
sidebarPage.goToClientScopes();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId)
|
||||||
|
.searchItem(itemId)
|
||||||
|
.itemExist(itemId);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Client scope elimination', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should delete client scope', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToClientScopes();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId)
|
||||||
|
.deleteItem(itemId); // There should be a confirmation pop-up
|
||||||
|
|
||||||
|
headerPage.checkNotificationMessage('The client scope has been deleted');
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId, false);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
101
tests/cypress/integration/clients_test.spec.js
Normal file
101
tests/cypress/integration/clients_test.spec.js
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import LoginPage from '../support/pages/LoginPage.js'
|
||||||
|
import HeaderPage from '../support/pages/admin_console/HeaderPage.js'
|
||||||
|
import ListingPage from '../support/pages/admin_console/ListingPage.js'
|
||||||
|
import SidebarPage from '../support/pages/admin_console/SidebarPage.js'
|
||||||
|
import CreateClientPage from '../support/pages/admin_console/manage/clients/CreateClientPage.js'
|
||||||
|
|
||||||
|
describe('Clients test', function () {
|
||||||
|
|
||||||
|
const itemId = 'client_1';
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const headerPage = new HeaderPage();
|
||||||
|
const sidebarPage = new SidebarPage();
|
||||||
|
const listingPage = new ListingPage();
|
||||||
|
const createClientPage = new CreateClientPage();
|
||||||
|
|
||||||
|
describe('Client creation', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail creating client', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToClients();
|
||||||
|
|
||||||
|
listingPage.goToCreateItem();
|
||||||
|
|
||||||
|
createClientPage
|
||||||
|
.continue()
|
||||||
|
.checkClientTypeRequiredMessage()
|
||||||
|
.checkClientIdRequiredMessage();
|
||||||
|
|
||||||
|
createClientPage
|
||||||
|
.fillClientData(itemId)
|
||||||
|
.continue()
|
||||||
|
.checkClientTypeRequiredMessage()
|
||||||
|
.checkClientIdRequiredMessage(false);
|
||||||
|
|
||||||
|
createClientPage
|
||||||
|
.fillClientData('')
|
||||||
|
.selectClientType('openid-connect')
|
||||||
|
.continue()
|
||||||
|
.checkClientTypeRequiredMessage(false)
|
||||||
|
.checkClientIdRequiredMessage();
|
||||||
|
|
||||||
|
createClientPage
|
||||||
|
.fillClientData('account')
|
||||||
|
.continue()
|
||||||
|
.continue();
|
||||||
|
|
||||||
|
// The error should inform about duplicated name/id
|
||||||
|
headerPage.checkNotificationMessage('Could not create client: \'Error: Request failed with status code 409\'');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create client', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToClients();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId, false)
|
||||||
|
.goToCreateItem();
|
||||||
|
|
||||||
|
createClientPage
|
||||||
|
.selectClientType('openid-connect')
|
||||||
|
.fillClientData(itemId)
|
||||||
|
.continue()
|
||||||
|
.continue();
|
||||||
|
|
||||||
|
headerPage.checkNotificationMessage('Client created successfully');
|
||||||
|
|
||||||
|
sidebarPage.goToClients();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId)
|
||||||
|
.searchItem(itemId)
|
||||||
|
.itemExist(itemId);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Client elimination', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should delete client', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToClients();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId)
|
||||||
|
.deleteItem(itemId); // There should be a confirmation pop-up
|
||||||
|
|
||||||
|
headerPage.checkNotificationMessage('The client has been deleted');
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId, false);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
31
tests/cypress/integration/login_test.spec.js
Normal file
31
tests/cypress/integration/login_test.spec.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import LoginPage from './../support/pages/LoginPage.js'
|
||||||
|
import HeaderPage from './../support/pages/admin_console/HeaderPage.js'
|
||||||
|
|
||||||
|
describe('Logging In', function () {
|
||||||
|
|
||||||
|
const username = 'admin'
|
||||||
|
const password = 'admin'
|
||||||
|
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const headerPage = new HeaderPage();
|
||||||
|
|
||||||
|
describe('Login form submission', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('displays errors on login', function () {
|
||||||
|
loginPage.logIn('wrong', 'user{enter}')
|
||||||
|
.checkErrorMessage('Invalid username or password.')
|
||||||
|
.isLogInPage();
|
||||||
|
})
|
||||||
|
|
||||||
|
it('redirects to admin console on success', function () {
|
||||||
|
loginPage.logIn(username, password);
|
||||||
|
|
||||||
|
headerPage.isAdminConsole();
|
||||||
|
|
||||||
|
cy.getCookie('KEYCLOAK_SESSION_LEGACY').should('exist')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
88
tests/cypress/integration/realm_roles_test.spec.js
Normal file
88
tests/cypress/integration/realm_roles_test.spec.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
import LoginPage from '../support/pages/LoginPage.js'
|
||||||
|
import HeaderPage from '../support/pages/admin_console/HeaderPage.js'
|
||||||
|
import ListingPage from '../support/pages/admin_console/ListingPage.js'
|
||||||
|
import SidebarPage from '../support/pages/admin_console/SidebarPage.js'
|
||||||
|
import CreateRealmRolePage from '../support/pages/admin_console/manage/realm_roles/CreateRealmRolePage.js'
|
||||||
|
|
||||||
|
describe('Realm roles test', function () {
|
||||||
|
|
||||||
|
const itemId = 'realm_role_1';
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const headerPage = new HeaderPage();
|
||||||
|
const sidebarPage = new SidebarPage();
|
||||||
|
const listingPage = new ListingPage();
|
||||||
|
const createRealmRolePage = new CreateRealmRolePage();
|
||||||
|
|
||||||
|
describe('Realm roles creation', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail creating realm role', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToRealmRoles();
|
||||||
|
|
||||||
|
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)
|
||||||
|
headerPage.checkNotificationMessage('Could not create role: Role with name admin already exists');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create realm role', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToRealmRoles();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId, false)
|
||||||
|
.goToCreateItem();
|
||||||
|
|
||||||
|
createRealmRolePage
|
||||||
|
.fillRealmRoleData(itemId)
|
||||||
|
.save();
|
||||||
|
|
||||||
|
headerPage.checkNotificationMessage('Role created');
|
||||||
|
|
||||||
|
sidebarPage.goToRealmRoles();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId)
|
||||||
|
.searchItem(itemId)
|
||||||
|
.itemExist(itemId);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Realm roles elimination', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should delete realm role', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToRealmRoles();
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId)
|
||||||
|
.deleteItem(itemId);
|
||||||
|
|
||||||
|
headerPage
|
||||||
|
.checkModalTitle('Delete role?')
|
||||||
|
.confirmModal();
|
||||||
|
|
||||||
|
headerPage.checkNotificationMessage('The role has been deleted');
|
||||||
|
|
||||||
|
listingPage
|
||||||
|
.itemExist(itemId, false);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
50
tests/cypress/integration/realm_test.spec.js
Normal file
50
tests/cypress/integration/realm_test.spec.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import LoginPage from '../support/pages/LoginPage.js'
|
||||||
|
import SidebarPage from '../support/pages/admin_console/SidebarPage.js'
|
||||||
|
import CreateRealmPage from '../support/pages/admin_console/CreateRealmPage.js'
|
||||||
|
import HeaderPage from '../support/pages/admin_console/HeaderPage.js'
|
||||||
|
|
||||||
|
describe('Realms test', function () {
|
||||||
|
|
||||||
|
const loginPage = new LoginPage();
|
||||||
|
const sidebarPage = new SidebarPage();
|
||||||
|
const createRealmPage = new CreateRealmPage();
|
||||||
|
const headerPage = new HeaderPage();
|
||||||
|
|
||||||
|
describe('Realm creation', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
cy.visit('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail creating Master realm', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToCreateRealm();
|
||||||
|
createRealmPage
|
||||||
|
.fillRealmName('master')
|
||||||
|
.createRealm();
|
||||||
|
|
||||||
|
headerPage.checkNotificationMessage('Error: Request failed with status code 409');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create Test realm', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.goToCreateRealm();
|
||||||
|
createRealmPage
|
||||||
|
.fillRealmName('Test')
|
||||||
|
.createRealm();
|
||||||
|
|
||||||
|
headerPage.checkNotificationMessage('Realm created');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change to Test realm', function () {
|
||||||
|
loginPage.logIn();
|
||||||
|
|
||||||
|
sidebarPage.getCurrentRealm().should('eq', 'Master');
|
||||||
|
|
||||||
|
sidebarPage
|
||||||
|
.goToRealm('Test')
|
||||||
|
.getCurrentRealm().should('eq', 'Test');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
20
tests/cypress/plugins/index.js
Normal file
20
tests/cypress/plugins/index.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// ***********************************************************
|
||||||
|
// This example plugins/index.js can be used to load plugins
|
||||||
|
//
|
||||||
|
// You can change the location of this file or turn off loading
|
||||||
|
// the plugins file with the 'pluginsFile' configuration option.
|
||||||
|
//
|
||||||
|
// You can read more here:
|
||||||
|
// https://on.cypress.io/plugins-guide
|
||||||
|
// ***********************************************************
|
||||||
|
|
||||||
|
// This function is called when a project is opened or re-opened (e.g. due to
|
||||||
|
// the project's config changing)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Cypress.PluginConfig}
|
||||||
|
*/
|
||||||
|
module.exports = (on, config) => {
|
||||||
|
// `on` is used to hook into various events Cypress emits
|
||||||
|
// `config` is the resolved Cypress config
|
||||||
|
}
|
25
tests/cypress/support/commands.js
Normal file
25
tests/cypress/support/commands.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// ***********************************************
|
||||||
|
// 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) => { ... })
|
20
tests/cypress/support/index.js
Normal file
20
tests/cypress/support/index.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// ***********************************************************
|
||||||
|
// 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')
|
38
tests/cypress/support/pages/LoginPage.js
Normal file
38
tests/cypress/support/pages/LoginPage.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
export default class LoginPage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.userNameInput = "#username";
|
||||||
|
this.passwordInput = "#password";
|
||||||
|
this.submitBtn = "#kc-login";
|
||||||
|
|
||||||
|
this.errorText = ".kc-feedback-text";
|
||||||
|
}
|
||||||
|
|
||||||
|
isLogInPage() {
|
||||||
|
cy.get(this.userNameInput).should('exist');
|
||||||
|
cy.url().should('include', '/auth');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
logIn(userName = "admin", password = "admin") {
|
||||||
|
cy.get(this.userNameInput).type(userName);
|
||||||
|
cy.get(this.passwordInput).type(password);
|
||||||
|
|
||||||
|
cy.get(this.submitBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkErrorIsDisplayed() {
|
||||||
|
cy.get(this.userDrpDwn).should('exist');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkErrorMessage(message) {
|
||||||
|
cy.get(this.errorText).invoke('text').should('contain', message);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
27
tests/cypress/support/pages/WelcomePage.js
Normal file
27
tests/cypress/support/pages/WelcomePage.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
export default class WelcomePage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.userNameInput = "#username";
|
||||||
|
this.passwordInput = "#password";
|
||||||
|
this.confirmPasswordInput = "#passwordConfirmation";
|
||||||
|
this.createBtn = "#create-button";
|
||||||
|
|
||||||
|
this.adminConsoleBtn = ".welcome-primary-link a";
|
||||||
|
}
|
||||||
|
|
||||||
|
createAdminUser(userName = "admin", password = "admin") {
|
||||||
|
cy.get(this.userNameInput).type(userName);
|
||||||
|
cy.get(this.passwordInput).type(password);
|
||||||
|
cy.get(this.confirmPasswordInput).type(password);
|
||||||
|
|
||||||
|
cy.get(this.createBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToAdminConsole() {
|
||||||
|
cy.get(this.adminConsoleBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
25
tests/cypress/support/pages/admin_console/CreateRealmPage.js
Normal file
25
tests/cypress/support/pages/admin_console/CreateRealmPage.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
export default class CreateRealmPage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.browseBtn = '#kc-realm-filename-browse-button';
|
||||||
|
this.clearBtn = '.pf-c-file-upload__file-select button:last-child';
|
||||||
|
this.realmFileNameInput = '#kc-realm-filename';
|
||||||
|
this.realmNameInput = '#kc-realm-name';
|
||||||
|
this.enabledSwitch = '[for="kc-realm-enabled-switch"] span.pf-c-switch__toggle';
|
||||||
|
|
||||||
|
this.createBtn = '.pf-c-form__group:last-child button[type="submit"]';
|
||||||
|
this.cancelBtn = '.pf-c-form__group:last-child button[type="button"]';
|
||||||
|
}
|
||||||
|
|
||||||
|
fillRealmName(realmName) {
|
||||||
|
cy.get(this.realmNameInput).type(realmName);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
createRealm() {
|
||||||
|
cy.get(this.createBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
92
tests/cypress/support/pages/admin_console/HeaderPage.js
Normal file
92
tests/cypress/support/pages/admin_console/HeaderPage.js
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
export default class HeaderPage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.menuBtn = '#nav-toggle';
|
||||||
|
this.logoBtn = 'img[alt="Logo"]';
|
||||||
|
this.helpBtn = '#help';
|
||||||
|
|
||||||
|
this.userDrpDwn = '[id*="pf-dropdown-toggle-id"]';
|
||||||
|
this.manageAccountBtn = '.pf-c-page__header-tools-item [role*="menu"] li:nth-child(1)';
|
||||||
|
this.serverInfoBtn = '.pf-c-page__header-tools-item [role*="menu"] li:nth-child(2)';
|
||||||
|
this.signOutBtn = '.pf-c-page__header-tools-item [role*="menu"] li:nth-child(4)';
|
||||||
|
|
||||||
|
this.notificationList = '.pf-c-alert-group.pf-m-toast';
|
||||||
|
|
||||||
|
this.modalTitle = '.pf-c-modal-box .pf-c-modal-box__title-text';
|
||||||
|
this.modalMessage = '.pf-c-modal-box .pf-c-modal-box__body';
|
||||||
|
|
||||||
|
this.confirmModalBtn = '#modal-confirm';
|
||||||
|
this.cancelModalBtn = '#modal-cancel';
|
||||||
|
this.closeModalBtn = '.pf-c-modal-box .pf-m-plain';
|
||||||
|
}
|
||||||
|
|
||||||
|
goToAdminConsole() {
|
||||||
|
cy.visit('');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToManageAccount() {
|
||||||
|
cy.get(this.userDrpDwn).click();
|
||||||
|
cy.get(this.manageAccountBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToServerInfo() {
|
||||||
|
cy.get(this.userDrpDwn).click();
|
||||||
|
cy.get(this.serverInfoBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
signOut() {
|
||||||
|
cy.get(this.userDrpDwn).click();
|
||||||
|
cy.get(this.signOutBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
isAdminConsole() {
|
||||||
|
cy.get(this.logoBtn).should('exist');
|
||||||
|
cy.get(this.userDrpDwn).should('exist');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkNotificationMessage(message) {
|
||||||
|
cy.contains(message).should('exist');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmModal() {
|
||||||
|
cy.get(this.confirmModalBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelModal() {
|
||||||
|
cy.get(this.cancelModalBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeModal() {
|
||||||
|
cy.get(this.closeModalBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkModalTitle(title) {
|
||||||
|
cy.get(this.modalTitle).invoke('text').should('eq', title);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkModalMessage(message) {
|
||||||
|
cy.get(this.modalMessage).invoke('text').should('eq', message);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
58
tests/cypress/support/pages/admin_console/ListingPage.js
Normal file
58
tests/cypress/support/pages/admin_console/ListingPage.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
export default class ListingPage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.searchInput = '.pf-c-toolbar__item [type="search"]';
|
||||||
|
this.itemsRows = '.pf-c-page__main-section tbody > tr';
|
||||||
|
this.itemRowDrpDwn = '.pf-c-dropdown > button';
|
||||||
|
this.exportBtn = '[role="menuitem"]:nth-child(1)';
|
||||||
|
this.deleteBtn = '[role="menuitem"]:nth-child(2)';
|
||||||
|
this.searchBtn = '.pf-c-page__main .pf-c-toolbar__content-section button.pf-m-control';
|
||||||
|
this.createBtn = '.pf-c-page__main .pf-c-toolbar__content-section button.pf-m-primary';
|
||||||
|
this.importBtn = '.pf-c-page__main .pf-c-toolbar__content-section button.pf-m-link';
|
||||||
|
}
|
||||||
|
|
||||||
|
goToCreateItem() {
|
||||||
|
cy.get(this.createBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToImportItem() {
|
||||||
|
cy.get(this.importBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
searchItem(searchValue) {
|
||||||
|
cy.get(this.searchInput).type(searchValue);
|
||||||
|
cy.get(this.searchBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemExist(itemName, exist = true) {
|
||||||
|
cy.get(this.itemsRows).contains(itemName).should((!exist ? 'not.': '') + 'exist')
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToItemDetails(itemName) {
|
||||||
|
cy.get(this.itemsRows).contains(itemName).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteItem(itemName) {
|
||||||
|
cy.get(this.itemsRows).contains(itemName).parentsUntil('tbody').find(this.itemRowDrpDwn).click();
|
||||||
|
cy.get(this.itemsRows).contains('Delete').click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
exportItem(itemName) {
|
||||||
|
cy.get(this.itemsRows).contains(itemName).parentsUntil('tbody').find(this.itemRowDrpDwn).click();
|
||||||
|
cy.get(this.itemsRows).contains('Export').click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
105
tests/cypress/support/pages/admin_console/SidebarPage.js
Normal file
105
tests/cypress/support/pages/admin_console/SidebarPage.js
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
export default class SidebarPage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.realmsDrpDwn = '#realm-select-toggle';
|
||||||
|
this.realmsList = '#realm-select ul';
|
||||||
|
this.createRealmBtn = '#realm-select li:last-child a';
|
||||||
|
|
||||||
|
this.clientsBtn = '#nav-item-clients';
|
||||||
|
this.clientScopesBtn = '#nav-item-client-scopes';
|
||||||
|
this.realmRolesBtn = '#nav-item-roles';
|
||||||
|
this.usersBtn = '#nav-item-users';
|
||||||
|
this.groupsBtn = '#nav-item-groups';
|
||||||
|
this.sessionsBtn = '#nav-item-sessions';
|
||||||
|
this.eventsBtn = '#nav-item-events';
|
||||||
|
|
||||||
|
this.realmSettingsBtn = '#nav-item-realm-settings';
|
||||||
|
this.authenticationBtn = '#nav-item-authentication';
|
||||||
|
this.identityProvidersBtn = '#nav-item-identity-providers';
|
||||||
|
this.userFederationBtn = '#nav-item-user-federation';
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentRealm() {
|
||||||
|
return cy.get(this.realmsDrpDwn).invoke('text');
|
||||||
|
}
|
||||||
|
|
||||||
|
goToRealm(realmName) {
|
||||||
|
cy.get(this.realmsDrpDwn).click();
|
||||||
|
cy.get(this.realmsList).contains(realmName).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToCreateRealm() {
|
||||||
|
cy.get(this.realmsDrpDwn).click();
|
||||||
|
cy.get(this.createRealmBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToClients() {
|
||||||
|
cy.get(this.clientsBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToClientScopes() {
|
||||||
|
cy.get(this.clientScopesBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToRealmRoles() {
|
||||||
|
cy.get(this.realmRolesBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToUsers() {
|
||||||
|
cy.get(this.usersBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToGroups() {
|
||||||
|
cy.get(this.groupsBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToSessions() {
|
||||||
|
cy.get(this.sessionsBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToEvents() {
|
||||||
|
cy.get(this.eventsBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToRealmSettings() {
|
||||||
|
cy.get(this.realmSettingsBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToAuthentication() {
|
||||||
|
cy.get(this.authenticationBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToIdentityProviders() {
|
||||||
|
cy.get(this.identityProvidersBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
goToUserFederation() {
|
||||||
|
cy.get(this.userFederationBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
export default class CreateClientScopePage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.settingsTab = '.pf-c-tabs__item:nth-child(1)';
|
||||||
|
this.mappersTab = '.pf-c-tabs__item:nth-child(2)';
|
||||||
|
|
||||||
|
this.clientScopeNameInput = '#kc-name';
|
||||||
|
this.clientScopeNameError = '#kc-name-helper';
|
||||||
|
this.clientScopeDescriptionInput = '#kc-description';
|
||||||
|
this.clientScopeTypeDrpDwn = '#kc-protocol';
|
||||||
|
this.clientScopeTypeList = '#kc-protocol + ul';
|
||||||
|
this.displayOnConsentSwitch = '[id="kc-display.on.consent.screen"] + .pf-c-switch__toggle';
|
||||||
|
this.consentScreenTextInput = '#kc-consent-screen-text';
|
||||||
|
this.includeInTokenSwitch = '[id="includeInTokenScope"] + .pf-c-switch__toggle';
|
||||||
|
this.displayOrderInput = '#kc-gui-order';
|
||||||
|
|
||||||
|
this.saveBtn = '[type="submit"]';
|
||||||
|
this.cancelBtn = '[type="button"]';
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region General Settings
|
||||||
|
fillClientScopeData(name, description = '', consentScreenText = '', displayOrder = '') {
|
||||||
|
cy.get(this.clientScopeNameInput).clear();
|
||||||
|
|
||||||
|
if(name) {
|
||||||
|
cy.get(this.clientScopeNameInput).type(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(description) {
|
||||||
|
cy.get(this.clientScopeDescriptionInput).type(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(consentScreenText) {
|
||||||
|
cy.get(this.consentScreenTextInput).type(consentScreenText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(displayOrder) {
|
||||||
|
cy.get(this.displayOrderInput).type(displayOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectClientScopeType(clientScopeType) {
|
||||||
|
cy.get(this.clientScopeTypeDrpDwn).click();
|
||||||
|
cy.get(this.clientScopeTypeList).contains(clientScopeType).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkClientNameRequiredMessage(exist = true) {
|
||||||
|
cy.get(this.clientScopeNameError).should((!exist ? 'not.': '') + 'exist');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
cy.get(this.cancelBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
export default class CreateClientPage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.clientTypeDrpDwn = '.pf-c-select__toggle';
|
||||||
|
this.clientTypeError = '.pf-c-select + div';
|
||||||
|
this.clientTypeList = '.pf-c-select__toggle + ul';
|
||||||
|
this.clientIdInput = '#kc-client-id';
|
||||||
|
this.clientIdError = '#kc-client-id + div';
|
||||||
|
this.clientNameInput = '#kc-name';
|
||||||
|
this.clientDescriptionInput = '#kc-description';
|
||||||
|
|
||||||
|
this.clientAuthenticationSwitch = '[for="kc-authentication"] .pf-c-switch__toggle';
|
||||||
|
this.clientAuthorizationSwitch = '[for="kc-authorization"] .pf-c-switch__toggle';
|
||||||
|
this.standardFlowChkBx = '#kc-flow-standard';
|
||||||
|
this.directAccessChkBx = '#kc-flow-direct';
|
||||||
|
this.implicitFlowChkBx = '#kc-flow-implicit';
|
||||||
|
this.serviceAccountRolesChkBx = '#kc-flow-service-account';
|
||||||
|
|
||||||
|
this.continueBtn = '.pf-c-wizard__footer .pf-m-primary';
|
||||||
|
this.backBtn = '.pf-c-wizard__footer .pf-m-secondary';
|
||||||
|
this.cancelBtn = '.pf-c-wizard__footer .pf-m-link';
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region General Settings
|
||||||
|
selectClientType(clientType) {
|
||||||
|
cy.get(this.clientTypeDrpDwn).click();
|
||||||
|
cy.get(this.clientTypeList).contains(clientType).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
fillClientData(id, name = '', description = '') {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkClientTypeRequiredMessage(exist = true) {
|
||||||
|
cy.get(this.clientTypeError).should((!exist ? 'not.': '') + 'exist');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkClientIdRequiredMessage(exist = true) {
|
||||||
|
cy.get(this.clientIdError).should((!exist ? 'not.': '') + 'exist');
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
continue() {
|
||||||
|
cy.get(this.continueBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
back() {
|
||||||
|
cy.get(this.backBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
cy.get(this.cancelBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
export default class CreateClientPage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.goToClientsBtn = '[href="#/realms/master/clients"]';
|
||||||
|
this.createClientBtn = '#createClient';
|
||||||
|
|
||||||
|
this.clientIdInput = '#clientId';
|
||||||
|
this.rootUrlInput = '#rootUrl';
|
||||||
|
|
||||||
|
this.saveBtn = '[kc-save]';
|
||||||
|
}
|
||||||
|
|
||||||
|
goToClients() {
|
||||||
|
cy.get(this.goToClientsBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addNewAdminConsole() {
|
||||||
|
cy.get(this.createClientBtn).click();
|
||||||
|
|
||||||
|
cy.get(this.clientIdInput).type('security-admin-console-v2');
|
||||||
|
cy.get(this.rootUrlInput).type('http://localhost:8080/');
|
||||||
|
|
||||||
|
cy.get(this.saveBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
export default class CreateRealmRolePage {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.realmRoleNameInput = '#kc-name';
|
||||||
|
this.realmRoleNameError = '#kc-name-helper';
|
||||||
|
this.realmRoleDescriptionInput = '#kc-role-description';
|
||||||
|
|
||||||
|
this.saveBtn = '[type="submit"]';
|
||||||
|
this.cancelBtn = '[type="button"]';
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region General Settings
|
||||||
|
fillRealmRoleData(name, description = '') {
|
||||||
|
cy.get(this.realmRoleNameInput).clear();
|
||||||
|
|
||||||
|
if(name) {
|
||||||
|
cy.get(this.realmRoleNameInput).type(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(description) {
|
||||||
|
cy.get(this.realmRoleDescriptionInput).type(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkRealmRoleNameRequiredMessage(exist = true) {
|
||||||
|
cy.get(this.realmRoleNameError).should((!exist ? 'not.': '') + 'exist');
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
save() {
|
||||||
|
cy.get(this.saveBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
cy.get(this.cancelBtn).click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
6
tests/jsconfig.json
Normal file
6
tests/jsconfig.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"include": [
|
||||||
|
"./node_modules/cypress",
|
||||||
|
"cypress/**/*.js"
|
||||||
|
]
|
||||||
|
}
|
3964
tests/package-lock.json
generated
Normal file
3964
tests/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
14
tests/package.json
Normal file
14
tests/package.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"name": "cypress-keycloak-ui-testsuite",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "UI tests for Keycloak using Cypress.",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cypress open"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"cypress": "^5.6.0"
|
||||||
|
}
|
||||||
|
}
|
1403
tests/yarn.lock
Normal file
1403
tests/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue