Merge branch 'master' into 2109-Typo-im-Dialog

This commit is contained in:
Alexander Friedland 2022-09-29 14:36:36 +02:00 committed by GitHub
commit aea4057df1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 132 additions and 23 deletions

View File

@ -1,24 +1,73 @@
# 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
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
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
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
# 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
docker build -t gradido_e2e-tests-cypress .
# run the Docker container and execute the given tests
docker run -it --network=host gradido_e2e-tests-cypress yarn run cypress-e2e-tests
# run the Docker image and execute the given tests
docker run -it --network=host gradido_e2e-tests-cypress yarn cypress-e2e
```

View File

@ -32,6 +32,7 @@ export default defineConfig({
excludeSpecPattern: "*.js",
baseUrl: "http://localhost:3000",
chromeWebSecurity: false,
defaultCommandTimeout: 10000,
supportFile: "cypress/support/index.ts",
viewportHeight: 720,
viewportWidth: 1280,

View File

@ -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_"

View File

@ -2,8 +2,8 @@
export class LoginPage {
// selectors
emailInput = "#Email-input-field";
passwordInput = "#Password-input-field";
emailInput = "input[type=email]";
passwordInput = "input[type=password]";
submitBtn = "[type=submit]";
emailHint = "#vee_Email";
passwordHint = "#vee_Password";

View File

@ -4,8 +4,8 @@ export class ProfilePage {
// selectors
openChangePassword = "[data-test=open-password-change-form]";
oldPasswordInput = "#password-input-field";
newPasswordInput = "#New-password-input-field";
newPasswordRepeatInput = "#Repeat-new-password-input-field";
newPasswordInput = "#new-password-input-field";
newPasswordRepeatInput = "#repeat-new-password-input-field";
submitNewPasswordBtn = "[data-test=submit-new-password-btn]";
goto() {
@ -19,12 +19,12 @@ export class ProfilePage {
}
enterNewPassword(password: string) {
cy.get(this.newPasswordInput).clear().type(password);
cy.get(this.newPasswordInput).find("input").clear().type(password);
return this;
}
enterRepeatPassword(password: string) {
cy.get(this.newPasswordRepeatInput).clear().type(password);
cy.get(this.newPasswordRepeatInput).find("input").clear().type(password);
return this;
}

View File

@ -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();
}
}

View File

@ -2,6 +2,9 @@
export class Toasts {
// selectors
toastSlot = ".b-toaster-slot";
toastTypeSuccess = ".b-toast-success";
toastTypeError = ".b-toast-danger";
toastTitle = ".gdd-toaster-title";
toastMessage = ".gdd-toaster-body";
}

View File

@ -25,11 +25,11 @@ Then("the user is logged in with username {string}", (username: string) => {
Then("the user cannot login", () => {
const toast = new Toasts();
cy.get(toast.toastTitle).should("contain.text", "Error!");
cy.get(toast.toastMessage).should(
"contain.text",
"No user with this credentials."
);
cy.get(toast.toastSlot).within(() => {
cy.get(toast.toastTypeError);
cy.get(toast.toastTitle).should("be.visible");
cy.get(toast.toastMessage).should("be.visible");
});
});
//

View File

@ -24,9 +24,9 @@ And("the user submits the password form", () => {
When("the user is presented a {string} message", (type: string) => {
const toast = new Toasts();
cy.get(toast.toastTitle).should("contain.text", "Success");
cy.get(toast.toastMessage).should(
"contain.text",
"Your password has been changed."
);
cy.get(toast.toastSlot).within(() => {
cy.get(toast.toastTypeSuccess);
cy.get(toast.toastTitle).should("be.visible");
cy.get(toast.toastMessage).should("be.visible");
});
});

View File

@ -14,7 +14,7 @@
}
},
"scripts": {
"cypress": "cypress run",
"cypress-e2e": "cypress run",
"lint": "eslint --max-warnings=0 --ext .js,.ts ."
},
"dependencies": {

View File

@ -29,6 +29,7 @@
required: true,
samePassword: value.password,
}"
id="repeat-new-password-input-field"
:label="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
:immediate="true"
:name="createId(register ? $t('form.passwordRepeat') : $t('form.password_new_repeat'))"