mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into 2109-Typo-im-Dialog
This commit is contained in:
commit
aea4057df1
@ -1,24 +1,73 @@
|
|||||||
# Gradido End-to-End Testing with [Cypress](https://www.cypress.io/) (CI-ready via Docker)
|
# Gradido End-to-End Testing with [Cypress](https://www.cypress.io/) (CI-ready via Docker)
|
||||||
|
|
||||||
|
A setup to show-case Cypress as an end-to-end testing tool for Gradido running in a Docker container.
|
||||||
|
The tests are organized in feature files written in Gherkin syntax.
|
||||||
|
|
||||||
|
|
||||||
|
## Features under test
|
||||||
|
|
||||||
|
So far these features are initially tested
|
||||||
|
- [User authentication](https://github.com/gradido/gradido/blob/master/e2e-tests/cypress/tests/cypress/e2e/User.Authentication.feature)
|
||||||
|
- [User profile - change password](https://github.com/gradido/gradido/blob/master/e2e-tests/cypress/tests/cypress/e2e/UserProfile.ChangePassword.feature)
|
||||||
|
- [User registration]((https://github.com/gradido/gradido/blob/master/e2e-tests/cypress/tests/cypress/e2e/User.Registration.feature)) (WIP)
|
||||||
|
|
||||||
A sample setup to show-case Cypress as an end-to-end testing tool for Gradido running in a Docker container.
|
|
||||||
Here we have a simple UI-based happy path login test running against the DEV system.
|
|
||||||
|
|
||||||
## Precondition
|
## Precondition
|
||||||
Since dependencies and configurations for Github Actions integration is not set up yet, please run in root directory
|
|
||||||
|
Before running the tests, change to the repo's root directory (gradido).
|
||||||
|
|
||||||
|
### Boot up the system under test
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up
|
docker-compose up
|
||||||
```
|
```
|
||||||
|
|
||||||
to boot up the DEV system, before running the test.
|
### Seed the database
|
||||||
|
|
||||||
|
The database has to be seeded upfront to every test run.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# change to the backend directory
|
||||||
|
cd /path/to/gradido/gradido/backend
|
||||||
|
|
||||||
|
# install all dependencies
|
||||||
|
yarn
|
||||||
|
|
||||||
|
# seed the database (everytime before running the tests)
|
||||||
|
yarn seed
|
||||||
|
```
|
||||||
|
|
||||||
## Execute the test
|
## Execute the test
|
||||||
|
|
||||||
|
This setup will be integrated in the Gradido Github Actions to automatically support the CI/CD process.
|
||||||
|
For now the test setup can only be used locally in two modes.
|
||||||
|
|
||||||
|
### Run Cypress directly from the code
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# change to the tests directory
|
||||||
|
cd /path/to/gradido/e2e-tests/cypress/tests
|
||||||
|
|
||||||
|
# install all dependencies
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# a) run the tests on command line
|
||||||
|
yarn cypress run
|
||||||
|
|
||||||
|
# b) open the Cypress GUI to run the tests in interactive mode
|
||||||
|
yarn cypress open
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Run Cyprss from a separate Docker container
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# change to the cypress directory
|
||||||
|
cd /path/to/gradido/e2e-tests/cypress/
|
||||||
|
|
||||||
# build a Docker image from the Dockerfile
|
# build a Docker image from the Dockerfile
|
||||||
docker build -t gradido_e2e-tests-cypress .
|
docker build -t gradido_e2e-tests-cypress .
|
||||||
|
|
||||||
# run the Docker container and execute the given tests
|
# run the Docker image and execute the given tests
|
||||||
docker run -it --network=host gradido_e2e-tests-cypress yarn run cypress-e2e-tests
|
docker run -it --network=host gradido_e2e-tests-cypress yarn cypress-e2e
|
||||||
```
|
```
|
||||||
|
|||||||
@ -32,6 +32,7 @@ export default defineConfig({
|
|||||||
excludeSpecPattern: "*.js",
|
excludeSpecPattern: "*.js",
|
||||||
baseUrl: "http://localhost:3000",
|
baseUrl: "http://localhost:3000",
|
||||||
chromeWebSecurity: false,
|
chromeWebSecurity: false,
|
||||||
|
defaultCommandTimeout: 10000,
|
||||||
supportFile: "cypress/support/index.ts",
|
supportFile: "cypress/support/index.ts",
|
||||||
viewportHeight: 720,
|
viewportHeight: 720,
|
||||||
viewportWidth: 1280,
|
viewportWidth: 1280,
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
Feature: User registration
|
||||||
|
As a user
|
||||||
|
I want to register to create an account
|
||||||
|
|
||||||
|
@skip
|
||||||
|
Scenario: Register successfully
|
||||||
|
Given the browser navigates to page "/register"
|
||||||
|
When the user fills name and email "Regina" "Register" "regina@register.com"
|
||||||
|
And the user agrees to the privacy policy
|
||||||
|
And the user submits the registration form
|
||||||
|
Then the user can use a provided activation link
|
||||||
|
And the user can set a password "Aa12345_"
|
||||||
|
And the user can login with the credentials "regina@register.com" "Aa12345_"
|
||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
export class LoginPage {
|
export class LoginPage {
|
||||||
// selectors
|
// selectors
|
||||||
emailInput = "#Email-input-field";
|
emailInput = "input[type=email]";
|
||||||
passwordInput = "#Password-input-field";
|
passwordInput = "input[type=password]";
|
||||||
submitBtn = "[type=submit]";
|
submitBtn = "[type=submit]";
|
||||||
emailHint = "#vee_Email";
|
emailHint = "#vee_Email";
|
||||||
passwordHint = "#vee_Password";
|
passwordHint = "#vee_Password";
|
||||||
|
|||||||
@ -4,8 +4,8 @@ export class ProfilePage {
|
|||||||
// selectors
|
// selectors
|
||||||
openChangePassword = "[data-test=open-password-change-form]";
|
openChangePassword = "[data-test=open-password-change-form]";
|
||||||
oldPasswordInput = "#password-input-field";
|
oldPasswordInput = "#password-input-field";
|
||||||
newPasswordInput = "#New-password-input-field";
|
newPasswordInput = "#new-password-input-field";
|
||||||
newPasswordRepeatInput = "#Repeat-new-password-input-field";
|
newPasswordRepeatInput = "#repeat-new-password-input-field";
|
||||||
submitNewPasswordBtn = "[data-test=submit-new-password-btn]";
|
submitNewPasswordBtn = "[data-test=submit-new-password-btn]";
|
||||||
|
|
||||||
goto() {
|
goto() {
|
||||||
@ -19,12 +19,12 @@ export class ProfilePage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enterNewPassword(password: string) {
|
enterNewPassword(password: string) {
|
||||||
cy.get(this.newPasswordInput).clear().type(password);
|
cy.get(this.newPasswordInput).find("input").clear().type(password);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
enterRepeatPassword(password: string) {
|
enterRepeatPassword(password: string) {
|
||||||
cy.get(this.newPasswordRepeatInput).clear().type(password);
|
cy.get(this.newPasswordRepeatInput).find("input").clear().type(password);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
export class RegistrationPage {
|
||||||
|
// selectors
|
||||||
|
firstnameInput = "#registerFirstname";
|
||||||
|
lastnameInput = "#registerLastname";
|
||||||
|
emailInput = "#Email-input-field";
|
||||||
|
checkbox = "#registerCheckbox";
|
||||||
|
submitBtn = "[type=submit]";
|
||||||
|
|
||||||
|
RegistrationThanxHeadline = ".test-message-headline";
|
||||||
|
RegistrationThanxText = ".test-message-subtitle";
|
||||||
|
|
||||||
|
goto() {
|
||||||
|
cy.visit("/register");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
enterFirstname(firstname: string) {
|
||||||
|
cy.get(this.firstnameInput).clear().type(firstname);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
enterLastname(lastname: string) {
|
||||||
|
cy.get(this.lastnameInput).clear().type(lastname);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
enterEmail(email: string) {
|
||||||
|
cy.get(this.emailInput).clear().type(email);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPrivacyCheckbox() {
|
||||||
|
cy.get(this.checkbox).click({ force: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
submitRegistrationPage() {
|
||||||
|
cy.get(this.submitBtn).should("be.enabled");
|
||||||
|
cy.get(this.submitBtn).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
export class Toasts {
|
export class Toasts {
|
||||||
// selectors
|
// selectors
|
||||||
|
toastSlot = ".b-toaster-slot";
|
||||||
|
toastTypeSuccess = ".b-toast-success";
|
||||||
|
toastTypeError = ".b-toast-danger";
|
||||||
toastTitle = ".gdd-toaster-title";
|
toastTitle = ".gdd-toaster-title";
|
||||||
toastMessage = ".gdd-toaster-body";
|
toastMessage = ".gdd-toaster-body";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,11 +25,11 @@ Then("the user is logged in with username {string}", (username: string) => {
|
|||||||
|
|
||||||
Then("the user cannot login", () => {
|
Then("the user cannot login", () => {
|
||||||
const toast = new Toasts();
|
const toast = new Toasts();
|
||||||
cy.get(toast.toastTitle).should("contain.text", "Error!");
|
cy.get(toast.toastSlot).within(() => {
|
||||||
cy.get(toast.toastMessage).should(
|
cy.get(toast.toastTypeError);
|
||||||
"contain.text",
|
cy.get(toast.toastTitle).should("be.visible");
|
||||||
"No user with this credentials."
|
cy.get(toast.toastMessage).should("be.visible");
|
||||||
);
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@ -24,9 +24,9 @@ And("the user submits the password form", () => {
|
|||||||
|
|
||||||
When("the user is presented a {string} message", (type: string) => {
|
When("the user is presented a {string} message", (type: string) => {
|
||||||
const toast = new Toasts();
|
const toast = new Toasts();
|
||||||
cy.get(toast.toastTitle).should("contain.text", "Success");
|
cy.get(toast.toastSlot).within(() => {
|
||||||
cy.get(toast.toastMessage).should(
|
cy.get(toast.toastTypeSuccess);
|
||||||
"contain.text",
|
cy.get(toast.toastTitle).should("be.visible");
|
||||||
"Your password has been changed."
|
cy.get(toast.toastMessage).should("be.visible");
|
||||||
);
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"cypress": "cypress run",
|
"cypress-e2e": "cypress run",
|
||||||
"lint": "eslint --max-warnings=0 --ext .js,.ts ."
|
"lint": "eslint --max-warnings=0 --ext .js,.ts ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
required: true,
|
required: true,
|
||||||
samePassword: value.password,
|
samePassword: value.password,
|
||||||
}"
|
}"
|
||||||
|
id="repeat-new-password-input-field"
|
||||||
:label="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
|
:label="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
|
||||||
:immediate="true"
|
:immediate="true"
|
||||||
:name="createId(register ? $t('form.passwordRepeat') : $t('form.password_new_repeat'))"
|
:name="createId(register ? $t('form.passwordRepeat') : $t('form.password_new_repeat'))"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user