diff --git a/e2e-tests/cypress/cypress/e2e/User.Authentication.ResetPassword.feature b/e2e-tests/cypress/cypress/e2e/User.Authentication.ResetPassword.feature
new file mode 100644
index 000000000..55ca87215
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/User.Authentication.ResetPassword.feature
@@ -0,0 +1,25 @@
+Feature: User Authentication - reset password
+ As a user
+ I want to reset my password from the sign in page
+
+ # TODO for these pre-conditions utilize seeding or API check, if user exists in test system
+ # Background:
+ # Given the following "users" are in the database:
+ # | email | password | name |
+ # | bibi@bloxberg.de | Aa12345_ | Bibi Bloxberg |
+
+ Scenario: Reset password from signin page successfully
+ Given the user navigates to page "/login"
+ And the user navigates to the forgot password page
+ When the user enters the e-mail address "bibi@bloxberg.de"
+ And the user submits the e-mail form
+ Then the user receives an e-mail containing the password reset link
+ When the user opens the password reset link in the browser
+ And the user enters the password "12345Aa_"
+ And the user repeats the password "12345Aa_"
+ And the user submits the password form
+ And the user clicks the sign in button
+ Then the user submits the credentials "bibi@bloxberg.de" "Aa12345_"
+ And the user cannot login
+ But the user submits the credentials "bibi@bloxberg.de" "12345Aa_"
+ And the user is logged in with username "Bibi Bloxberg"
diff --git a/e2e-tests/cypress/cypress/e2e/User.Authentication.feature b/e2e-tests/cypress/cypress/e2e/User.Authentication.feature
new file mode 100644
index 000000000..3b460efc6
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/User.Authentication.feature
@@ -0,0 +1,17 @@
+Feature: User authentication
+ As a user
+ I want to be able to sign in - only with valid credentials
+ In order to be able to posts and do other contributions as myself
+ Furthermore I want to be able to stay logged in and logout again
+
+ # TODO for these pre-conditions utilize seeding or API check, if user exists in test system
+ # Background:
+ # Given the following "users" are in the database:
+ # | email | password | name |
+ # | bibi@bloxberg.de | Aa12345_ | Bibi Bloxberg |
+
+ Scenario: Log in successfully
+ Given the user navigates to page "/login"
+ When the user submits the credentials "bibi@bloxberg.de" "Aa12345_"
+ Then the user is logged in with username "Bibi Bloxberg"
+
diff --git a/e2e-tests/cypress/cypress/e2e/User.Registration.feature b/e2e-tests/cypress/cypress/e2e/User.Registration.feature
new file mode 100644
index 000000000..ed53bb4b0
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/User.Registration.feature
@@ -0,0 +1,13 @@
+Feature: User registration
+ As a user
+ I want to register to create an account
+
+ @skip
+ Scenario: Register successfully
+ Given the user 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_"
diff --git a/e2e-tests/cypress/cypress/e2e/UserProfile.ChangePassword.feature b/e2e-tests/cypress/cypress/e2e/UserProfile.ChangePassword.feature
new file mode 100644
index 000000000..aa853f6ff
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/UserProfile.ChangePassword.feature
@@ -0,0 +1,27 @@
+Feature: User profile - change password
+ As a user
+ I want the option to change my password on my profile page.
+
+ Background:
+ # TODO for these pre-conditions utilize seeding or API check, if user exists in test system
+ # Given the following "users" are in the database:
+ # | email | password | name |
+ # | bibi@bloxberg.de | Aa12345_ | Bibi Bloxberg | |
+
+ # TODO instead of credentials use the name of an user object (see seeds in backend)
+ Given the user is logged in as "bibi@bloxberg.de" "Aa12345_"
+
+ Scenario: Change password successfully
+ Given the user navigates to page "/profile"
+ And the user opens the change password menu
+ When the user fills the password form with:
+ | Old password | Aa12345_ |
+ | New password | 12345Aa_ |
+ | Repeat new password | 12345Aa_ |
+ And the user submits the password form
+ And the user is presented a "success" message
+ And the user logs out
+ Then the user submits the credentials "bibi@bloxberg.de" "Aa12345_"
+ And the user cannot login
+ But the user submits the credentials "bibi@bloxberg.de" "12345Aa_"
+ And the user is logged in with username "Bibi Bloxberg"
diff --git a/e2e-tests/cypress/cypress/e2e/models/ForgotPasswordPage.ts b/e2e-tests/cypress/cypress/e2e/models/ForgotPasswordPage.ts
new file mode 100644
index 000000000..b97bc8ee7
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/ForgotPasswordPage.ts
@@ -0,0 +1,18 @@
+///
+
+export class ForgotPasswordPage {
+ // selectors
+ emailInput = 'input[type=email]'
+ submitBtn = 'button[type=submit]'
+ successComponent = '[data-test="forgot-password-success"]'
+
+ enterEmail(email: string) {
+ cy.get(this.emailInput).clear().type(email)
+ return this
+ }
+
+ submitEmail() {
+ cy.get(this.submitBtn).click()
+ return this
+ }
+}
diff --git a/e2e-tests/cypress/cypress/e2e/models/LoginPage.ts b/e2e-tests/cypress/cypress/e2e/models/LoginPage.ts
new file mode 100644
index 000000000..52aa5d19b
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/LoginPage.ts
@@ -0,0 +1,35 @@
+///
+
+export class LoginPage {
+ // selectors
+ emailInput = 'input[type=email]'
+ passwordInput = 'input[type=password]'
+ forgotPasswordLink = '[data-test="forgot-password-link"]'
+ submitBtn = '[type=submit]'
+ emailHint = '#vee_Email'
+ passwordHint = '#vee_Password'
+
+ goto() {
+ cy.visit('/')
+ return this
+ }
+
+ enterEmail(email: string) {
+ cy.get(this.emailInput).clear().type(email)
+ return this
+ }
+
+ enterPassword(password: string) {
+ cy.get(this.passwordInput).clear().type(password)
+ return this
+ }
+
+ submitLogin() {
+ cy.get(this.submitBtn).click()
+ return this
+ }
+
+ openForgotPasswordPage() {
+ cy.get(this.forgotPasswordLink).click()
+ }
+}
diff --git a/e2e-tests/cypress/cypress/e2e/models/OverviewPage.ts b/e2e-tests/cypress/cypress/e2e/models/OverviewPage.ts
new file mode 100644
index 000000000..345124c66
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/OverviewPage.ts
@@ -0,0 +1,10 @@
+///
+
+export class OverviewPage {
+ navbarName = '[data-test="navbar-item-username"]'
+
+ goto() {
+ cy.visit('/overview')
+ return this
+ }
+}
diff --git a/e2e-tests/cypress/cypress/e2e/models/ProfilePage.ts b/e2e-tests/cypress/cypress/e2e/models/ProfilePage.ts
new file mode 100644
index 000000000..4d5b98a53
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/ProfilePage.ts
@@ -0,0 +1,35 @@
+///
+
+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'
+ submitNewPasswordBtn = '[data-test=submit-new-password-btn]'
+
+ goto() {
+ cy.visit('/profile')
+ return this
+ }
+
+ enterOldPassword(password: string) {
+ cy.get(this.oldPasswordInput).clear().type(password)
+ return this
+ }
+
+ enterNewPassword(password: string) {
+ cy.get(this.newPasswordInput).find('input').clear().type(password)
+ return this
+ }
+
+ enterRepeatPassword(password: string) {
+ cy.get(this.newPasswordRepeatInput).find('input').clear().type(password)
+ return this
+ }
+
+ submitPasswordForm() {
+ cy.get(this.submitNewPasswordBtn).click()
+ return this
+ }
+}
diff --git a/e2e-tests/cypress/cypress/e2e/models/RegistrationPage.ts b/e2e-tests/cypress/cypress/e2e/models/RegistrationPage.ts
new file mode 100644
index 000000000..8cae26a26
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/RegistrationPage.ts
@@ -0,0 +1,42 @@
+///
+
+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()
+ }
+}
diff --git a/e2e-tests/cypress/cypress/e2e/models/ResetPasswordPage.ts b/e2e-tests/cypress/cypress/e2e/models/ResetPasswordPage.ts
new file mode 100644
index 000000000..20134de6d
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/ResetPasswordPage.ts
@@ -0,0 +1,32 @@
+///
+
+export class ResetPasswordPage {
+ // selectors
+ newPasswordBlock = '#new-password-input-field'
+ newPasswordRepeatBlock = '#repeat-new-password-input-field'
+ resetPasswordBtn = 'button[type=submit]'
+ resetPasswordMessageBlock = '[data-test="reset-password-message"]'
+ signinBtn = '.btn.test-message-button'
+
+ enterNewPassword(password: string) {
+ cy.get(this.newPasswordBlock).find('input[type=password]').type(password)
+ return this
+ }
+
+ repeatNewPassword(password: string) {
+ cy.get(this.newPasswordRepeatBlock)
+ .find('input[type=password]')
+ .type(password)
+ return this
+ }
+
+ submitNewPassword() {
+ cy.get(this.resetPasswordBtn).click()
+ return this
+ }
+
+ openSigninPage() {
+ cy.get(this.signinBtn).click()
+ return this
+ }
+}
diff --git a/e2e-tests/cypress/cypress/e2e/models/SideNavMenu.ts b/e2e-tests/cypress/cypress/e2e/models/SideNavMenu.ts
new file mode 100644
index 000000000..ccd177b66
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/SideNavMenu.ts
@@ -0,0 +1,17 @@
+///
+
+export class SideNavMenu {
+ // selectors
+ profileMenu = '[data-test=profile-menu]'
+ logoutMenu = '[data-test=logout-menu]'
+
+ openUserProfile() {
+ cy.get(this.profileMenu).click()
+ return this
+ }
+
+ logout() {
+ cy.get(this.logoutMenu).click()
+ return this
+ }
+}
diff --git a/e2e-tests/cypress/cypress/e2e/models/Toasts.ts b/e2e-tests/cypress/cypress/e2e/models/Toasts.ts
new file mode 100644
index 000000000..efd5052fb
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/Toasts.ts
@@ -0,0 +1,10 @@
+///
+
+export class Toasts {
+ // selectors
+ toastSlot = '.b-toaster-slot'
+ toastTypeSuccess = '.b-toast-success'
+ toastTypeError = '.b-toast-danger'
+ toastTitle = '.gdd-toaster-title'
+ toastMessage = '.gdd-toaster-body'
+}
diff --git a/e2e-tests/cypress/cypress/e2e/models/UserEMailSite.ts b/e2e-tests/cypress/cypress/e2e/models/UserEMailSite.ts
new file mode 100644
index 000000000..f46f5677b
--- /dev/null
+++ b/e2e-tests/cypress/cypress/e2e/models/UserEMailSite.ts
@@ -0,0 +1,17 @@
+///
+
+export class UserEMailSite {
+ // selectors
+ emailInbox = '.sidebar-emails-container'
+ emailList = '.email-list'
+ emailMeta = '.email-meta'
+ emailSubject = '.subject'
+
+ openRecentPasswordResetEMail() {
+ cy.get(this.emailList)
+ .find('email-item')
+ .filter(':contains(asswor)')
+ .click()
+ expect(cy.get(this.emailSubject)).to('contain', 'asswor')
+ }
+}
diff --git a/e2e-tests/cypress/cypress/fixtures/users.json b/e2e-tests/cypress/cypress/fixtures/users.json
new file mode 100644
index 000000000..f13e203f0
--- /dev/null
+++ b/e2e-tests/cypress/cypress/fixtures/users.json
@@ -0,0 +1,7 @@
+{
+ "user": {
+ "email": "bibi@bloxberg.de",
+ "password": "Aa12345_",
+ "name": "Bibi Bloxberg"
+ }
+}
diff --git a/e2e-tests/cypress/cypress/support/e2e.ts b/e2e-tests/cypress/cypress/support/e2e.ts
new file mode 100644
index 000000000..2f3557566
--- /dev/null
+++ b/e2e-tests/cypress/cypress/support/e2e.ts
@@ -0,0 +1,40 @@
+import jwtDecode from 'jwt-decode'
+
+Cypress.Commands.add('login', (email, password) => {
+ cy.clearLocalStorage('vuex')
+
+ cy.request({
+ method: 'POST',
+ url: Cypress.env('backendURL'),
+ body: {
+ operationName: null,
+ variables: {
+ email: email,
+ password: password,
+ },
+ query: Cypress.env('loginQuery'),
+ },
+ }).then(async (response) => {
+ const tokens = response.headers.token
+ const token = Array.isArray(tokens) ? tokens[0] : tokens
+ let tokenTime
+
+ if (!token) return
+ // to avoid JWT InvalidTokenError, the decoding of the token is wrapped
+ // in a try-catch block (see
+ // https://github.com/auth0/jwt-decode/issues/65#issuecomment-395493807)
+ try {
+ tokenTime = jwtDecode(token).exp
+ } catch (tokenDecodingError) {
+ cy.log('JWT decoding error: ', tokenDecodingError)
+ }
+
+ const vuexToken = {
+ token: token,
+ tokenTime: tokenTime,
+ }
+
+ cy.visit('/')
+ window.localStorage.setItem('vuex', JSON.stringify(vuexToken))
+ })
+})
diff --git a/e2e-tests/cypress/cypress/support/index.ts b/e2e-tests/cypress/cypress/support/index.ts
new file mode 100644
index 000000000..f8d1abacf
--- /dev/null
+++ b/e2e-tests/cypress/cypress/support/index.ts
@@ -0,0 +1,14 @@
+/* eslint-disable @typescript-eslint/no-namespace */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+///
+
+import './e2e'
+
+declare global {
+ namespace Cypress {
+ interface Chainable {
+ login(email: string, password: string): Chainable
+ }
+ }
+}
diff --git a/e2e-tests/cypress/cypress/support/step_definitions/common_steps.ts b/e2e-tests/cypress/cypress/support/step_definitions/common_steps.ts
new file mode 100644
index 000000000..c5d3004ac
--- /dev/null
+++ b/e2e-tests/cypress/cypress/support/step_definitions/common_steps.ts
@@ -0,0 +1,39 @@
+import { Given, Then, When } from '@badeball/cypress-cucumber-preprocessor'
+import { OverviewPage } from '../../e2e/models/OverviewPage'
+import { SideNavMenu } from '../../e2e/models/SideNavMenu'
+import { Toasts } from '../../e2e/models/Toasts'
+
+Given('the user navigates to page {string}', (page: string) => {
+ cy.visit(page)
+})
+
+// login related
+
+Given(
+ 'the user is logged in as {string} {string}',
+ (email: string, password: string) => {
+ cy.login(email, password)
+ }
+)
+
+Then('the user is logged in with username {string}', (username: string) => {
+ const overviewPage = new OverviewPage()
+ cy.url().should('include', '/overview')
+ cy.get(overviewPage.navbarName).should('contain', username)
+})
+
+Then('the user cannot login', () => {
+ const toast = new Toasts()
+ cy.get(toast.toastSlot).within(() => {
+ cy.get(toast.toastTypeError)
+ cy.get(toast.toastTitle).should('be.visible')
+ cy.get(toast.toastMessage).should('be.visible')
+ })
+})
+
+// logout
+
+Then('the user logs out', () => {
+ const sideNavMenu = new SideNavMenu()
+ sideNavMenu.logout()
+})
diff --git a/e2e-tests/cypress/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/cypress/support/step_definitions/email_steps.ts
new file mode 100644
index 000000000..b313442f2
--- /dev/null
+++ b/e2e-tests/cypress/cypress/support/step_definitions/email_steps.ts
@@ -0,0 +1,45 @@
+import { Then, When } from '@badeball/cypress-cucumber-preprocessor'
+import { ResetPasswordPage } from '../../e2e/models/ResetPasswordPage'
+import { UserEMailSite } from '../../e2e/models/UserEMailSite'
+
+const userEMailSite = new UserEMailSite()
+const resetPasswordPage = new ResetPasswordPage()
+
+Then('the user receives an e-mail containing the password reset link', () => {
+ cy.origin(
+ Cypress.env('mailserverURL'),
+ { args: userEMailSite },
+ (userEMailSite) => {
+ const linkPattern = /\/reset-password\/[0-9]+\d/
+
+ cy.visit('/') // navigate to user's e-maile site (on fake mail server)
+ cy.get(userEMailSite.emailInbox).should('be.visible')
+
+ cy.get(userEMailSite.emailList)
+ .find('.email-item')
+ .filter(':contains(asswor)')
+ .first()
+ .click()
+
+ cy.get(userEMailSite.emailMeta)
+ .find(userEMailSite.emailSubject)
+ .contains('asswor')
+
+ cy.get('.email-content')
+ .find('.plain-text')
+ .contains(linkPattern)
+ .invoke('text')
+ .then((text) => {
+ const resetPasswordLink = text.match(linkPattern)[0]
+ cy.task('setResetPasswordLink', resetPasswordLink)
+ })
+ }
+ )
+})
+
+When('the user opens the password reset link in the browser', () => {
+ cy.task('getResetPasswordLink').then((passwordResetLink) => {
+ cy.visit(passwordResetLink)
+ })
+ cy.get(resetPasswordPage.newPasswordRepeatBlock).should('be.visible')
+})
diff --git a/e2e-tests/cypress/cypress/support/step_definitions/user_authentication_steps.ts b/e2e-tests/cypress/cypress/support/step_definitions/user_authentication_steps.ts
new file mode 100644
index 000000000..5b25f5391
--- /dev/null
+++ b/e2e-tests/cypress/cypress/support/step_definitions/user_authentication_steps.ts
@@ -0,0 +1,69 @@
+import { When, And } from '@badeball/cypress-cucumber-preprocessor'
+import { ForgotPasswordPage } from '../../e2e/models/ForgotPasswordPage'
+import { LoginPage } from '../../e2e/models/LoginPage'
+import { ResetPasswordPage } from '../../e2e/models/ResetPasswordPage'
+
+const loginPage = new LoginPage()
+const forgotPasswordPage = new ForgotPasswordPage()
+const resetPasswordPage = new ResetPasswordPage()
+
+// login related
+
+When('the user submits no credentials', () => {
+ loginPage.submitLogin()
+})
+
+When(
+ 'the user submits the credentials {string} {string}',
+ (email: string, password: string) => {
+ cy.intercept('POST', '/graphql', (req) => {
+ if (
+ req.body.hasOwnProperty('query') &&
+ req.body.query.includes('mutation')
+ ) {
+ req.alias = 'login'
+ }
+ })
+
+ loginPage.enterEmail(email)
+ loginPage.enterPassword(password)
+ loginPage.submitLogin()
+ cy.wait('@login').then((interception) => {
+ expect(interception.response.statusCode).equals(200)
+ })
+ }
+)
+
+// password reset related
+
+And('the user navigates to the forgot password page', () => {
+ loginPage.openForgotPasswordPage()
+ cy.url().should('include', '/forgot-password')
+})
+
+When('the user enters the e-mail address {string}', (email: string) => {
+ forgotPasswordPage.enterEmail(email)
+})
+
+And('the user submits the e-mail form', () => {
+ forgotPasswordPage.submitEmail()
+ cy.get(forgotPasswordPage.successComponent).should('be.visible')
+})
+
+And('the user enters the password {string}', (password: string) => {
+ resetPasswordPage.enterNewPassword(password)
+})
+
+And('the user repeats the password {string}', (password: string) => {
+ resetPasswordPage.repeatNewPassword(password)
+})
+
+And('the user submits the new password', () => {
+ resetPasswordPage.submitNewPassword()
+ cy.get(resetPasswordPage.resetPasswordMessageBlock).should('be.visible')
+})
+
+And('the user clicks the sign in button', () => {
+ resetPasswordPage.openSigninPage()
+ cy.url().should('contain', '/login')
+})
diff --git a/e2e-tests/cypress/cypress/support/step_definitions/user_profile_change_password_steps.ts b/e2e-tests/cypress/cypress/support/step_definitions/user_profile_change_password_steps.ts
new file mode 100644
index 000000000..1dcbe69ef
--- /dev/null
+++ b/e2e-tests/cypress/cypress/support/step_definitions/user_profile_change_password_steps.ts
@@ -0,0 +1,32 @@
+import { And, When } from '@badeball/cypress-cucumber-preprocessor'
+import { ProfilePage } from '../../e2e/models/ProfilePage'
+import { Toasts } from '../../e2e/models/Toasts'
+
+const profilePage = new ProfilePage()
+
+And('the user opens the change password menu', () => {
+ cy.get(profilePage.openChangePassword).click()
+ cy.get(profilePage.newPasswordRepeatInput).should('be.visible')
+ cy.get(profilePage.submitNewPasswordBtn).should('be.disabled')
+})
+
+When('the user fills the password form with:', (table) => {
+ let hashedTableRows = table.rowsHash()
+ profilePage.enterOldPassword(hashedTableRows['Old password'])
+ profilePage.enterNewPassword(hashedTableRows['New password'])
+ profilePage.enterRepeatPassword(hashedTableRows['Repeat new password'])
+ cy.get(profilePage.submitNewPasswordBtn).should('be.enabled')
+})
+
+And('the user submits the password form', () => {
+ profilePage.submitPasswordForm()
+})
+
+When('the user is presented a {string} message', (type: string) => {
+ const toast = new Toasts()
+ cy.get(toast.toastSlot).within(() => {
+ cy.get(toast.toastTypeSuccess)
+ cy.get(toast.toastTitle).should('be.visible')
+ cy.get(toast.toastMessage).should('be.visible')
+ })
+})
diff --git a/e2e-tests/cypress/cypress/support/step_definitions/user_registration_steps.ts b/e2e-tests/cypress/cypress/support/step_definitions/user_registration_steps.ts
new file mode 100644
index 000000000..8f12338b0
--- /dev/null
+++ b/e2e-tests/cypress/cypress/support/step_definitions/user_registration_steps.ts
@@ -0,0 +1,24 @@
+import { And, When } from '@badeball/cypress-cucumber-preprocessor'
+import { RegistrationPage } from '../../e2e/models/RegistrationPage'
+
+const registrationPage = new RegistrationPage()
+
+When(
+ 'the user fills name and email {string} {string} {string}',
+ (firstname: string, lastname: string, email: string) => {
+ const registrationPage = new RegistrationPage()
+ registrationPage.enterFirstname(firstname)
+ registrationPage.enterLastname(lastname)
+ registrationPage.enterEmail(email)
+ }
+)
+
+And('the user agrees to the privacy policy', () => {
+ registrationPage.checkPrivacyCheckbox()
+})
+
+And('the user submits the registration form', () => {
+ registrationPage.submitRegistrationPage()
+ cy.get(registrationPage.RegistrationThanxHeadline).should('be.visible')
+ cy.get(registrationPage.RegistrationThanxText).should('be.visible')
+})