From 140b53faf3701cb3646f557534f29b9a11b6c2b6 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 10 Feb 2023 10:12:44 +0100 Subject: [PATCH 1/9] Change " to ', remove ; at end of statements, try to correct IDE recognition of modul imports. --- e2e-tests/cypress/tests/.eslintrc.js | 25 ++--- e2e-tests/cypress/tests/.prettierrc.js | 9 ++ e2e-tests/cypress/tests/cypress.config.ts | 78 +++++++-------- .../cypress/e2e/models/ForgotPasswordPage.ts | 16 ++-- .../tests/cypress/e2e/models/LoginPage.ts | 32 +++---- .../tests/cypress/e2e/models/OverviewPage.ts | 8 +- .../tests/cypress/e2e/models/ProfilePage.ts | 32 +++---- .../cypress/e2e/models/RegistrationPage.ts | 38 ++++---- .../cypress/e2e/models/ResetPasswordPage.ts | 30 +++--- .../tests/cypress/e2e/models/SideNavMenu.ts | 14 +-- .../tests/cypress/e2e/models/Toasts.ts | 12 +-- .../tests/cypress/e2e/models/UserEMailSite.ts | 18 ++-- .../cypress/tests/cypress/support/e2e.ts | 30 +++--- .../cypress/tests/cypress/support/index.ts | 6 +- .../support/step_definitions/common_steps.ts | 52 +++++----- .../support/step_definitions/email_steps.ts | 56 +++++------ .../user_authentication_steps.ts | 96 +++++++++---------- .../user_profile_change_password_steps.ts | 52 +++++----- .../user_registration_steps.ts | 34 +++---- e2e-tests/cypress/tests/tsconfig.json | 2 +- 20 files changed, 325 insertions(+), 315 deletions(-) create mode 100644 e2e-tests/cypress/tests/.prettierrc.js diff --git a/e2e-tests/cypress/tests/.eslintrc.js b/e2e-tests/cypress/tests/.eslintrc.js index 157454287..9bdd630c7 100644 --- a/e2e-tests/cypress/tests/.eslintrc.js +++ b/e2e-tests/cypress/tests/.eslintrc.js @@ -3,22 +3,23 @@ module.exports = { env: { node: true, }, - parser: "@typescript-eslint/parser", - plugins: ["cypress", "prettier", "@typescript-eslint"], + parser: '@typescript-eslint/parser', + plugins: ['cypress', 'prettier', '@typescript-eslint' /*, 'jest' */], extends: [ - "standard", - "eslint:recommended", - "plugin:prettier/recommended", - "plugin:@typescript-eslint/recommended", + 'standard', + 'eslint:recommended', + 'plugin:prettier/recommended', + 'plugin:@typescript-eslint/recommended', ], + // add your custom rules here rules: { - "no-console": ["error"], - "no-debugger": "error", - "prettier/prettier": [ - "error", + 'no-console': ['error'], + 'no-debugger': 'error', + 'prettier/prettier': [ + 'error', { - htmlWhitespaceSensitivity: "ignore", + htmlWhitespaceSensitivity: 'ignore', }, ], }, -}; +} diff --git a/e2e-tests/cypress/tests/.prettierrc.js b/e2e-tests/cypress/tests/.prettierrc.js new file mode 100644 index 000000000..bc1d767d7 --- /dev/null +++ b/e2e-tests/cypress/tests/.prettierrc.js @@ -0,0 +1,9 @@ +module.exports = { + semi: false, + printWidth: 100, + singleQuote: true, + trailingComma: "all", + tabWidth: 2, + bracketSpacing: true, + endOfLine: "auto", +}; diff --git a/e2e-tests/cypress/tests/cypress.config.ts b/e2e-tests/cypress/tests/cypress.config.ts index a9627c5ae..16ebb0e97 100644 --- a/e2e-tests/cypress/tests/cypress.config.ts +++ b/e2e-tests/cypress/tests/cypress.config.ts @@ -1,51 +1,51 @@ -import { defineConfig } from "cypress"; -import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor"; -import browserify from "@badeball/cypress-cucumber-preprocessor/browserify"; +import { defineConfig } from 'cypress' +import { addCucumberPreprocessorPlugin } from '@badeball/cypress-cucumber-preprocessor' +import browserify from '@badeball/cypress-cucumber-preprocessor/browserify' -let resetPasswordLink: string; +let resetPasswordLink: string async function setupNodeEvents( on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions ): Promise { - await addCucumberPreprocessorPlugin(on, config); + await addCucumberPreprocessorPlugin(on, config) on( - "file:preprocessor", + 'file:preprocessor', browserify(config, { - typescript: require.resolve("typescript"), + typescript: require.resolve('typescript'), }) - ); + ) - on("task", { + on('task', { setResetPasswordLink: (val) => { - return (resetPasswordLink = val); + return (resetPasswordLink = val) }, getResetPasswordLink: () => { - return resetPasswordLink; + return resetPasswordLink }, - }); + }) - on("after:run", (results) => { + on('after:run', (results) => { if (results) { // results will be undefined in interactive mode // eslint-disable-next-line no-console - console.log(results.status); + console.log(results.status) } - }); + }) - return config; + return config } export default defineConfig({ e2e: { - specPattern: "**/*.feature", - excludeSpecPattern: "*.js", + specPattern: '**/*.feature', + excludeSpecPattern: '*.js', experimentalSessionAndOrigin: true, - baseUrl: "http://localhost:3000", + baseUrl: 'http://localhost:3000', chromeWebSecurity: false, defaultCommandTimeout: 10000, - supportFile: "cypress/support/index.ts", + supportFile: 'cypress/support/index.ts', viewportHeight: 720, viewportWidth: 1280, video: false, @@ -54,26 +54,26 @@ export default defineConfig({ openMode: 0, }, env: { - backendURL: "http://localhost:4000", - mailserverURL: "http://localhost:1080", + backendURL: 'http://localhost:4000', + mailserverURL: 'http://localhost:1080', loginQuery: `query ($email: String!, $password: String!, $publisherId: Int) { - login(email: $email, password: $password, publisherId: $publisherId) { - email - firstName - lastName - language - klickTipp { - newsletterState - __typename - } - hasElopage - publisherId - isAdmin - creation - __typename - } -}`, + login(email: $email, password: $password, publisherId: $publisherId) { + email + firstName + lastName + language + klickTipp { + newsletterState + __typename + } + hasElopage + publisherId + isAdmin + creation + __typename + } + }`, }, setupNodeEvents, }, -}); +}) diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/ForgotPasswordPage.ts b/e2e-tests/cypress/tests/cypress/e2e/models/ForgotPasswordPage.ts index 295bb1fda..b97bc8ee7 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/ForgotPasswordPage.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/ForgotPasswordPage.ts @@ -1,18 +1,18 @@ -/// +/// export class ForgotPasswordPage { // selectors - emailInput = "input[type=email]"; - submitBtn = "button[type=submit]"; - successComponent = "[data-test='forgot-password-success']"; + 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; + cy.get(this.emailInput).clear().type(email) + return this } submitEmail() { - cy.get(this.submitBtn).click(); - return this; + cy.get(this.submitBtn).click() + return this } } diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/LoginPage.ts b/e2e-tests/cypress/tests/cypress/e2e/models/LoginPage.ts index df91e8e14..52aa5d19b 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/LoginPage.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/LoginPage.ts @@ -1,35 +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"; + 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; + cy.visit('/') + return this } enterEmail(email: string) { - cy.get(this.emailInput).clear().type(email); - return this; + cy.get(this.emailInput).clear().type(email) + return this } enterPassword(password: string) { - cy.get(this.passwordInput).clear().type(password); - return this; + cy.get(this.passwordInput).clear().type(password) + return this } submitLogin() { - cy.get(this.submitBtn).click(); - return this; + cy.get(this.submitBtn).click() + return this } openForgotPasswordPage() { - cy.get(this.forgotPasswordLink).click(); + cy.get(this.forgotPasswordLink).click() } } diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/OverviewPage.ts b/e2e-tests/cypress/tests/cypress/e2e/models/OverviewPage.ts index 426c2b8b3..345124c66 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/OverviewPage.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/OverviewPage.ts @@ -1,10 +1,10 @@ -/// +/// export class OverviewPage { - navbarName = '[data-test="navbar-item-username"]'; + navbarName = '[data-test="navbar-item-username"]' goto() { - cy.visit("/overview"); - return this; + cy.visit('/overview') + return this } } diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/ProfilePage.ts b/e2e-tests/cypress/tests/cypress/e2e/models/ProfilePage.ts index 0532a7ff8..4d5b98a53 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/ProfilePage.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/ProfilePage.ts @@ -1,35 +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]"; + 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; + cy.visit('/profile') + return this } enterOldPassword(password: string) { - cy.get(this.oldPasswordInput).clear().type(password); - return this; + cy.get(this.oldPasswordInput).clear().type(password) + return this } enterNewPassword(password: string) { - cy.get(this.newPasswordInput).find("input").clear().type(password); - return this; + 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; + cy.get(this.newPasswordRepeatInput).find('input').clear().type(password) + return this } submitPasswordForm() { - cy.get(this.submitNewPasswordBtn).click(); - return this; + cy.get(this.submitNewPasswordBtn).click() + return this } } diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/RegistrationPage.ts b/e2e-tests/cypress/tests/cypress/e2e/models/RegistrationPage.ts index 27a9cb8cc..8cae26a26 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/RegistrationPage.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/RegistrationPage.ts @@ -1,42 +1,42 @@ -/// +/// export class RegistrationPage { // selectors - firstnameInput = "#registerFirstname"; - lastnameInput = "#registerLastname"; - emailInput = "#Email-input-field"; - checkbox = "#registerCheckbox"; - submitBtn = "[type=submit]"; + firstnameInput = '#registerFirstname' + lastnameInput = '#registerLastname' + emailInput = '#Email-input-field' + checkbox = '#registerCheckbox' + submitBtn = '[type=submit]' - RegistrationThanxHeadline = ".test-message-headline"; - RegistrationThanxText = ".test-message-subtitle"; + RegistrationThanxHeadline = '.test-message-headline' + RegistrationThanxText = '.test-message-subtitle' goto() { - cy.visit("/register"); - return this; + cy.visit('/register') + return this } enterFirstname(firstname: string) { - cy.get(this.firstnameInput).clear().type(firstname); - return this; + cy.get(this.firstnameInput).clear().type(firstname) + return this } enterLastname(lastname: string) { - cy.get(this.lastnameInput).clear().type(lastname); - return this; + cy.get(this.lastnameInput).clear().type(lastname) + return this } enterEmail(email: string) { - cy.get(this.emailInput).clear().type(email); - return this; + cy.get(this.emailInput).clear().type(email) + return this } checkPrivacyCheckbox() { - cy.get(this.checkbox).click({ force: true }); + cy.get(this.checkbox).click({ force: true }) } submitRegistrationPage() { - cy.get(this.submitBtn).should("be.enabled"); - cy.get(this.submitBtn).click(); + cy.get(this.submitBtn).should('be.enabled') + cy.get(this.submitBtn).click() } } diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/ResetPasswordPage.ts b/e2e-tests/cypress/tests/cypress/e2e/models/ResetPasswordPage.ts index 4f01d73b0..20134de6d 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/ResetPasswordPage.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/ResetPasswordPage.ts @@ -1,32 +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"; + 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; + 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; + .find('input[type=password]') + .type(password) + return this } submitNewPassword() { - cy.get(this.resetPasswordBtn).click(); - return this; + cy.get(this.resetPasswordBtn).click() + return this } openSigninPage() { - cy.get(this.signinBtn).click(); - return this; + cy.get(this.signinBtn).click() + return this } } diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/SideNavMenu.ts b/e2e-tests/cypress/tests/cypress/e2e/models/SideNavMenu.ts index 3dd9d6914..ccd177b66 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/SideNavMenu.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/SideNavMenu.ts @@ -1,17 +1,17 @@ -/// +/// export class SideNavMenu { // selectors - profileMenu = "[data-test=profile-menu]"; - logoutMenu = "[data-test=logout-menu]"; + profileMenu = '[data-test=profile-menu]' + logoutMenu = '[data-test=logout-menu]' openUserProfile() { - cy.get(this.profileMenu).click(); - return this; + cy.get(this.profileMenu).click() + return this } logout() { - cy.get(this.logoutMenu).click(); - return this; + cy.get(this.logoutMenu).click() + return this } } diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/Toasts.ts b/e2e-tests/cypress/tests/cypress/e2e/models/Toasts.ts index aabd0a45e..efd5052fb 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/Toasts.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/Toasts.ts @@ -1,10 +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"; + 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/tests/cypress/e2e/models/UserEMailSite.ts b/e2e-tests/cypress/tests/cypress/e2e/models/UserEMailSite.ts index 02207827d..f46f5677b 100644 --- a/e2e-tests/cypress/tests/cypress/e2e/models/UserEMailSite.ts +++ b/e2e-tests/cypress/tests/cypress/e2e/models/UserEMailSite.ts @@ -1,17 +1,17 @@ -/// +/// export class UserEMailSite { // selectors - emailInbox = ".sidebar-emails-container"; - emailList = ".email-list"; - emailMeta = ".email-meta"; - emailSubject = ".subject"; + 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"); + .find('email-item') + .filter(':contains(asswor)') + .click() + expect(cy.get(this.emailSubject)).to('contain', 'asswor') } } diff --git a/e2e-tests/cypress/tests/cypress/support/e2e.ts b/e2e-tests/cypress/tests/cypress/support/e2e.ts index 16cc474bf..801165a48 100644 --- a/e2e-tests/cypress/tests/cypress/support/e2e.ts +++ b/e2e-tests/cypress/tests/cypress/support/e2e.ts @@ -1,38 +1,38 @@ -import jwtDecode from "jwt-decode"; +import jwtDecode from 'jwt-decode' -Cypress.Commands.add("login", (email, password) => { - cy.clearLocalStorage("vuex"); +Cypress.Commands.add('login', (email, password) => { + cy.clearLocalStorage('vuex') cy.request({ - method: "POST", - url: Cypress.env("backendURL"), + method: 'POST', + url: Cypress.env('backendURL'), body: { operationName: null, variables: { email: email, password: password, }, - query: Cypress.env("loginQuery"), + query: Cypress.env('loginQuery'), }, }).then(async (response) => { - const token = response.headers.token; - let tokenTime; + const token = response.headers.token + let tokenTime // 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; + tokenTime = jwtDecode(token).exp } catch (tokenDecodingError) { - cy.log("JWT decoding error: ", tokenDecodingError); + cy.log('JWT decoding error: ', tokenDecodingError) } const vuexToken = { token: token, tokenTime: tokenTime, - }; + } - cy.visit("/"); - window.localStorage.setItem("vuex", JSON.stringify(vuexToken)); - }); -}); + cy.visit('/') + window.localStorage.setItem('vuex', JSON.stringify(vuexToken)) + }) +}) diff --git a/e2e-tests/cypress/tests/cypress/support/index.ts b/e2e-tests/cypress/tests/cypress/support/index.ts index 99ab0efc2..f8d1abacf 100644 --- a/e2e-tests/cypress/tests/cypress/support/index.ts +++ b/e2e-tests/cypress/tests/cypress/support/index.ts @@ -1,14 +1,14 @@ /* eslint-disable @typescript-eslint/no-namespace */ /* eslint-disable @typescript-eslint/no-explicit-any */ -/// +/// -import "./e2e"; +import './e2e' declare global { namespace Cypress { interface Chainable { - login(email: string, password: string): Chainable; + login(email: string, password: string): Chainable } } } diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/common_steps.ts b/e2e-tests/cypress/tests/cypress/support/step_definitions/common_steps.ts index e2d66f76a..c5d3004ac 100644 --- a/e2e-tests/cypress/tests/cypress/support/step_definitions/common_steps.ts +++ b/e2e-tests/cypress/tests/cypress/support/step_definitions/common_steps.ts @@ -1,39 +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"; +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); -}); +Given('the user navigates to page {string}', (page: string) => { + cy.visit(page) +}) // login related Given( - "the user is logged in as {string} {string}", + 'the user is logged in as {string} {string}', (email: string, password: string) => { - cy.login(email, password); + 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 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(); +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"); - }); -}); + 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(); -}); +Then('the user logs out', () => { + const sideNavMenu = new SideNavMenu() + sideNavMenu.logout() +}) diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/tests/cypress/support/step_definitions/email_steps.ts index 4044c3717..b313442f2 100644 --- a/e2e-tests/cypress/tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/tests/cypress/support/step_definitions/email_steps.ts @@ -1,45 +1,45 @@ -import { Then, When } from "@badeball/cypress-cucumber-preprocessor"; -import { ResetPasswordPage } from "../../e2e/models/ResetPasswordPage"; -import { UserEMailSite } from "../../e2e/models/UserEMailSite"; +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(); +const userEMailSite = new UserEMailSite() +const resetPasswordPage = new ResetPasswordPage() -Then("the user receives an e-mail containing the password reset link", () => { +Then('the user receives an e-mail containing the password reset link', () => { cy.origin( - Cypress.env("mailserverURL"), + Cypress.env('mailserverURL'), { args: userEMailSite }, (userEMailSite) => { - const linkPattern = /\/reset-password\/[0-9]+\d/; + 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.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)") + .find('.email-item') + .filter(':contains(asswor)') .first() - .click(); + .click() cy.get(userEMailSite.emailMeta) .find(userEMailSite.emailSubject) - .contains("asswor"); + .contains('asswor') - cy.get(".email-content") - .find(".plain-text") + cy.get('.email-content') + .find('.plain-text') .contains(linkPattern) - .invoke("text") + .invoke('text') .then((text) => { - const resetPasswordLink = text.match(linkPattern)[0]; - cy.task("setResetPasswordLink", resetPasswordLink); - }); + 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"); -}); +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/tests/cypress/support/step_definitions/user_authentication_steps.ts b/e2e-tests/cypress/tests/cypress/support/step_definitions/user_authentication_steps.ts index 17743ebe5..5b25f5391 100644 --- a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_authentication_steps.ts +++ b/e2e-tests/cypress/tests/cypress/support/step_definitions/user_authentication_steps.ts @@ -1,69 +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"; +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(); +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 no credentials', () => { + loginPage.submitLogin() +}) When( - "the user submits the credentials {string} {string}", + 'the user submits the credentials {string} {string}', (email: string, password: string) => { - cy.intercept("POST", "/graphql", (req) => { + cy.intercept('POST', '/graphql', (req) => { if ( - req.body.hasOwnProperty("query") && - req.body.query.includes("mutation") + req.body.hasOwnProperty('query') && + req.body.query.includes('mutation') ) { - req.alias = "login"; + req.alias = 'login' } - }); + }) - loginPage.enterEmail(email); - loginPage.enterPassword(password); - loginPage.submitLogin(); - cy.wait("@login").then((interception) => { - expect(interception.response.statusCode).equals(200); - }); + 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"); -}); +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); -}); +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 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 enters the password {string}', (password: string) => { + resetPasswordPage.enterNewPassword(password) +}) -And("the user repeats the password {string}", (password: string) => { - resetPasswordPage.repeatNewPassword(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 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"); -}); +And('the user clicks the sign in button', () => { + resetPasswordPage.openSigninPage() + cy.url().should('contain', '/login') +}) diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_profile_change_password_steps.ts b/e2e-tests/cypress/tests/cypress/support/step_definitions/user_profile_change_password_steps.ts index 5396b66bb..1dcbe69ef 100644 --- a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_profile_change_password_steps.ts +++ b/e2e-tests/cypress/tests/cypress/support/step_definitions/user_profile_change_password_steps.ts @@ -1,32 +1,32 @@ -import { And, When } from "@badeball/cypress-cucumber-preprocessor"; -import { ProfilePage } from "../../e2e/models/ProfilePage"; -import { Toasts } from "../../e2e/models/Toasts"; +import { And, When } from '@badeball/cypress-cucumber-preprocessor' +import { ProfilePage } from '../../e2e/models/ProfilePage' +import { Toasts } from '../../e2e/models/Toasts' -const profilePage = new ProfilePage(); +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"); -}); +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) => { - table = table.rowsHash(); - profilePage.enterOldPassword(table["Old password"]); - profilePage.enterNewPassword(table["New password"]); - profilePage.enterRepeatPassword(table["Repeat new password"]); - cy.get(profilePage.submitNewPasswordBtn).should("be.enabled"); -}); +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(); -}); +And('the user submits the password form', () => { + profilePage.submitPasswordForm() +}) -When("the user is presented a {string} message", (type: string) => { - const toast = new Toasts(); +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"); - }); -}); + cy.get(toast.toastTypeSuccess) + cy.get(toast.toastTitle).should('be.visible') + cy.get(toast.toastMessage).should('be.visible') + }) +}) diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_registration_steps.ts b/e2e-tests/cypress/tests/cypress/support/step_definitions/user_registration_steps.ts index 49e121fc2..8f12338b0 100644 --- a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_registration_steps.ts +++ b/e2e-tests/cypress/tests/cypress/support/step_definitions/user_registration_steps.ts @@ -1,24 +1,24 @@ -import { And, When } from "@badeball/cypress-cucumber-preprocessor"; -import { RegistrationPage } from "../../e2e/models/RegistrationPage"; +import { And, When } from '@badeball/cypress-cucumber-preprocessor' +import { RegistrationPage } from '../../e2e/models/RegistrationPage' -const registrationPage = new RegistrationPage(); +const registrationPage = new RegistrationPage() When( - "the user fills name and email {string} {string} {string}", + '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); + 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 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"); -}); +And('the user submits the registration form', () => { + registrationPage.submitRegistrationPage() + cy.get(registrationPage.RegistrationThanxHeadline).should('be.visible') + cy.get(registrationPage.RegistrationThanxText).should('be.visible') +}) diff --git a/e2e-tests/cypress/tests/tsconfig.json b/e2e-tests/cypress/tests/tsconfig.json index c031a126e..287443d46 100644 --- a/e2e-tests/cypress/tests/tsconfig.json +++ b/e2e-tests/cypress/tests/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "es2016", "lib": ["es6", "dom"], - "baseUrl": "../node_modules", + "baseUrl": ".", "types": ["cypress", "node"], "strict": true }, From 9008c96d0f0a1a72e87b87f890adb29e798848b2 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 10 Feb 2023 12:12:17 +0100 Subject: [PATCH 2/9] Move cypress/tests/cypress folder to src --- e2e-tests/cypress/{tests => }/.eslintignore | 0 e2e-tests/cypress/{tests => }/.eslintrc.js | 1 + e2e-tests/cypress/.gitignore | 8 ++++---- e2e-tests/cypress/{tests => }/.prettierrc.js | 0 e2e-tests/cypress/Dockerfile | 2 +- e2e-tests/cypress/{tests => }/cypress.config.ts | 0 e2e-tests/cypress/{tests => }/package.json | 0 .../e2e/User.Authentication.ResetPassword.feature | 0 .../e2e/User.Authentication.feature | 0 .../cypress => src}/e2e/User.Registration.feature | 0 .../e2e/UserProfile.ChangePassword.feature | 0 .../e2e/models/ForgotPasswordPage.ts | 0 .../cypress => src}/e2e/models/LoginPage.ts | 0 .../cypress => src}/e2e/models/OverviewPage.ts | 0 .../cypress => src}/e2e/models/ProfilePage.ts | 0 .../e2e/models/RegistrationPage.ts | 0 .../e2e/models/ResetPasswordPage.ts | 0 .../cypress => src}/e2e/models/SideNavMenu.ts | 0 .../{tests/cypress => src}/e2e/models/Toasts.ts | 0 .../cypress => src}/e2e/models/UserEMailSite.ts | 0 .../{tests/cypress => src}/fixtures/users.json | 0 .../cypress/{tests/cypress => src}/support/e2e.ts | 0 .../{tests/cypress => src}/support/index.ts | 0 .../support/step_definitions/common_steps.ts | 0 .../support/step_definitions/email_steps.ts | 4 ++-- .../step_definitions/user_authentication_steps.ts | 0 .../user_profile_change_password_steps.ts | 0 .../step_definitions/user_registration_steps.ts | 2 +- e2e-tests/cypress/tests/tsconfig.json | 10 ---------- e2e-tests/cypress/tsconfig.json | 15 +++++++++++++++ e2e-tests/cypress/{tests => }/yarn.lock | 0 31 files changed, 24 insertions(+), 18 deletions(-) rename e2e-tests/cypress/{tests => }/.eslintignore (100%) rename e2e-tests/cypress/{tests => }/.eslintrc.js (96%) rename e2e-tests/cypress/{tests => }/.prettierrc.js (100%) rename e2e-tests/cypress/{tests => }/cypress.config.ts (100%) rename e2e-tests/cypress/{tests => }/package.json (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/User.Authentication.ResetPassword.feature (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/User.Authentication.feature (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/User.Registration.feature (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/UserProfile.ChangePassword.feature (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/ForgotPasswordPage.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/LoginPage.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/OverviewPage.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/ProfilePage.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/RegistrationPage.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/ResetPasswordPage.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/SideNavMenu.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/Toasts.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/e2e/models/UserEMailSite.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/fixtures/users.json (100%) rename e2e-tests/cypress/{tests/cypress => src}/support/e2e.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/support/index.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/support/step_definitions/common_steps.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/support/step_definitions/email_steps.ts (90%) rename e2e-tests/cypress/{tests/cypress => src}/support/step_definitions/user_authentication_steps.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/support/step_definitions/user_profile_change_password_steps.ts (100%) rename e2e-tests/cypress/{tests/cypress => src}/support/step_definitions/user_registration_steps.ts (91%) delete mode 100644 e2e-tests/cypress/tests/tsconfig.json create mode 100644 e2e-tests/cypress/tsconfig.json rename e2e-tests/cypress/{tests => }/yarn.lock (100%) diff --git a/e2e-tests/cypress/tests/.eslintignore b/e2e-tests/cypress/.eslintignore similarity index 100% rename from e2e-tests/cypress/tests/.eslintignore rename to e2e-tests/cypress/.eslintignore diff --git a/e2e-tests/cypress/tests/.eslintrc.js b/e2e-tests/cypress/.eslintrc.js similarity index 96% rename from e2e-tests/cypress/tests/.eslintrc.js rename to e2e-tests/cypress/.eslintrc.js index 9bdd630c7..98f13d176 100644 --- a/e2e-tests/cypress/tests/.eslintrc.js +++ b/e2e-tests/cypress/.eslintrc.js @@ -2,6 +2,7 @@ module.exports = { root: true, env: { node: true, + cypress: true, }, parser: '@typescript-eslint/parser', plugins: ['cypress', 'prettier', '@typescript-eslint' /*, 'jest' */], diff --git a/e2e-tests/cypress/.gitignore b/e2e-tests/cypress/.gitignore index 7dfc547b4..1261bffa8 100644 --- a/e2e-tests/cypress/.gitignore +++ b/e2e-tests/cypress/.gitignore @@ -1,4 +1,4 @@ -tests/node_modules/ -tests/cypress/screenshots/ -tests/cypress/videos/ -tests/cucumber-messages.ndjson +node_modules/ +src/screenshots/ +src/videos/ +src/cucumber-messages.ndjson diff --git a/e2e-tests/cypress/tests/.prettierrc.js b/e2e-tests/cypress/.prettierrc.js similarity index 100% rename from e2e-tests/cypress/tests/.prettierrc.js rename to e2e-tests/cypress/.prettierrc.js diff --git a/e2e-tests/cypress/Dockerfile b/e2e-tests/cypress/Dockerfile index 8c8e00da8..7d036c613 100644 --- a/e2e-tests/cypress/Dockerfile +++ b/e2e-tests/cypress/Dockerfile @@ -11,7 +11,7 @@ ############################################################################### FROM cypress/base:16.14.2-slim -ARG DOCKER_WORKDIR=/tests/ +ARG DOCKER_WORKDIR"="/tests" WORKDIR $DOCKER_WORKDIR # install dependencies diff --git a/e2e-tests/cypress/tests/cypress.config.ts b/e2e-tests/cypress/cypress.config.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress.config.ts rename to e2e-tests/cypress/cypress.config.ts diff --git a/e2e-tests/cypress/tests/package.json b/e2e-tests/cypress/package.json similarity index 100% rename from e2e-tests/cypress/tests/package.json rename to e2e-tests/cypress/package.json diff --git a/e2e-tests/cypress/tests/cypress/e2e/User.Authentication.ResetPassword.feature b/e2e-tests/cypress/src/e2e/User.Authentication.ResetPassword.feature similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/User.Authentication.ResetPassword.feature rename to e2e-tests/cypress/src/e2e/User.Authentication.ResetPassword.feature diff --git a/e2e-tests/cypress/tests/cypress/e2e/User.Authentication.feature b/e2e-tests/cypress/src/e2e/User.Authentication.feature similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/User.Authentication.feature rename to e2e-tests/cypress/src/e2e/User.Authentication.feature diff --git a/e2e-tests/cypress/tests/cypress/e2e/User.Registration.feature b/e2e-tests/cypress/src/e2e/User.Registration.feature similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/User.Registration.feature rename to e2e-tests/cypress/src/e2e/User.Registration.feature diff --git a/e2e-tests/cypress/tests/cypress/e2e/UserProfile.ChangePassword.feature b/e2e-tests/cypress/src/e2e/UserProfile.ChangePassword.feature similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/UserProfile.ChangePassword.feature rename to e2e-tests/cypress/src/e2e/UserProfile.ChangePassword.feature diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/ForgotPasswordPage.ts b/e2e-tests/cypress/src/e2e/models/ForgotPasswordPage.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/ForgotPasswordPage.ts rename to e2e-tests/cypress/src/e2e/models/ForgotPasswordPage.ts diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/LoginPage.ts b/e2e-tests/cypress/src/e2e/models/LoginPage.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/LoginPage.ts rename to e2e-tests/cypress/src/e2e/models/LoginPage.ts diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/OverviewPage.ts b/e2e-tests/cypress/src/e2e/models/OverviewPage.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/OverviewPage.ts rename to e2e-tests/cypress/src/e2e/models/OverviewPage.ts diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/ProfilePage.ts b/e2e-tests/cypress/src/e2e/models/ProfilePage.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/ProfilePage.ts rename to e2e-tests/cypress/src/e2e/models/ProfilePage.ts diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/RegistrationPage.ts b/e2e-tests/cypress/src/e2e/models/RegistrationPage.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/RegistrationPage.ts rename to e2e-tests/cypress/src/e2e/models/RegistrationPage.ts diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/ResetPasswordPage.ts b/e2e-tests/cypress/src/e2e/models/ResetPasswordPage.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/ResetPasswordPage.ts rename to e2e-tests/cypress/src/e2e/models/ResetPasswordPage.ts diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/SideNavMenu.ts b/e2e-tests/cypress/src/e2e/models/SideNavMenu.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/SideNavMenu.ts rename to e2e-tests/cypress/src/e2e/models/SideNavMenu.ts diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/Toasts.ts b/e2e-tests/cypress/src/e2e/models/Toasts.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/Toasts.ts rename to e2e-tests/cypress/src/e2e/models/Toasts.ts diff --git a/e2e-tests/cypress/tests/cypress/e2e/models/UserEMailSite.ts b/e2e-tests/cypress/src/e2e/models/UserEMailSite.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/e2e/models/UserEMailSite.ts rename to e2e-tests/cypress/src/e2e/models/UserEMailSite.ts diff --git a/e2e-tests/cypress/tests/cypress/fixtures/users.json b/e2e-tests/cypress/src/fixtures/users.json similarity index 100% rename from e2e-tests/cypress/tests/cypress/fixtures/users.json rename to e2e-tests/cypress/src/fixtures/users.json diff --git a/e2e-tests/cypress/tests/cypress/support/e2e.ts b/e2e-tests/cypress/src/support/e2e.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/support/e2e.ts rename to e2e-tests/cypress/src/support/e2e.ts diff --git a/e2e-tests/cypress/tests/cypress/support/index.ts b/e2e-tests/cypress/src/support/index.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/support/index.ts rename to e2e-tests/cypress/src/support/index.ts diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/common_steps.ts b/e2e-tests/cypress/src/support/step_definitions/common_steps.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/support/step_definitions/common_steps.ts rename to e2e-tests/cypress/src/support/step_definitions/common_steps.ts diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/src/support/step_definitions/email_steps.ts similarity index 90% rename from e2e-tests/cypress/tests/cypress/support/step_definitions/email_steps.ts rename to e2e-tests/cypress/src/support/step_definitions/email_steps.ts index b313442f2..7d70e36bc 100644 --- a/e2e-tests/cypress/tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/src/support/step_definitions/email_steps.ts @@ -1,6 +1,6 @@ import { Then, When } from '@badeball/cypress-cucumber-preprocessor' -import { ResetPasswordPage } from '../../e2e/models/ResetPasswordPage' -import { UserEMailSite } from '../../e2e/models/UserEMailSite' +import { ResetPasswordPage } from '@models/ResetPasswordPage' +import { UserEMailSite } from '@models/UserEMailSite' const userEMailSite = new UserEMailSite() const resetPasswordPage = new ResetPasswordPage() diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_authentication_steps.ts b/e2e-tests/cypress/src/support/step_definitions/user_authentication_steps.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/support/step_definitions/user_authentication_steps.ts rename to e2e-tests/cypress/src/support/step_definitions/user_authentication_steps.ts diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_profile_change_password_steps.ts b/e2e-tests/cypress/src/support/step_definitions/user_profile_change_password_steps.ts similarity index 100% rename from e2e-tests/cypress/tests/cypress/support/step_definitions/user_profile_change_password_steps.ts rename to e2e-tests/cypress/src/support/step_definitions/user_profile_change_password_steps.ts diff --git a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_registration_steps.ts b/e2e-tests/cypress/src/support/step_definitions/user_registration_steps.ts similarity index 91% rename from e2e-tests/cypress/tests/cypress/support/step_definitions/user_registration_steps.ts rename to e2e-tests/cypress/src/support/step_definitions/user_registration_steps.ts index 8f12338b0..6f4034447 100644 --- a/e2e-tests/cypress/tests/cypress/support/step_definitions/user_registration_steps.ts +++ b/e2e-tests/cypress/src/support/step_definitions/user_registration_steps.ts @@ -1,5 +1,5 @@ import { And, When } from '@badeball/cypress-cucumber-preprocessor' -import { RegistrationPage } from '../../e2e/models/RegistrationPage' +import { RegistrationPage } from '@models/RegistrationPage' const registrationPage = new RegistrationPage() diff --git a/e2e-tests/cypress/tests/tsconfig.json b/e2e-tests/cypress/tests/tsconfig.json deleted file mode 100644 index 287443d46..000000000 --- a/e2e-tests/cypress/tests/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "target": "es2016", - "lib": ["es6", "dom"], - "baseUrl": ".", - "types": ["cypress", "node"], - "strict": true - }, - "include": ["**/*.ts"] -} diff --git a/e2e-tests/cypress/tsconfig.json b/e2e-tests/cypress/tsconfig.json new file mode 100644 index 000000000..4d863857b --- /dev/null +++ b/e2e-tests/cypress/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es2016", + "lib": ["es6", "dom"], + "baseUrl": ".", + "types": ["cypress", "node"], + "strict": true, + "esModuleInterop": true, + "moduleResolution": "node", + "paths": { + "@/*": ["src/*"], + "@models/*": ["src/e2e/models/*"], + } + }, +} diff --git a/e2e-tests/cypress/tests/yarn.lock b/e2e-tests/cypress/yarn.lock similarity index 100% rename from e2e-tests/cypress/tests/yarn.lock rename to e2e-tests/cypress/yarn.lock From 4d0d709f3fffe1be9945df4c7a6dc80ee7acc17c Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 10 Feb 2023 12:55:40 +0100 Subject: [PATCH 3/9] Changed path now cypress/src/* --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 04dbb8382..4d30cda1f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -647,9 +647,9 @@ jobs: - name: End-to-end tests | run tests id: e2e-tests run: | - cd e2e-tests/cypress/tests/ + cd e2e-tests/cypress/ yarn - yarn run cypress run --spec cypress/e2e/User.Authentication.feature,cypress/e2e/User.Authentication.ResetPassword.feature + yarn run cypress run --spec src/e2e/User.Authentication.feature,cypress/e2e/User.Authentication.ResetPassword.feature - name: End-to-end tests | if tests failed, upload screenshots if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} uses: actions/upload-artifact@v3 From 2d86cd97b0099f3e172766f0ba1bdc7b194b1182 Mon Sep 17 00:00:00 2001 From: elweyn Date: Sun, 12 Feb 2023 07:28:21 +0100 Subject: [PATCH 4/9] Delete everything under src. --- .../User.Authentication.ResetPassword.feature | 25 ------- .../src/e2e/User.Authentication.feature | 17 ----- .../cypress/src/e2e/User.Registration.feature | 13 ---- .../e2e/UserProfile.ChangePassword.feature | 27 -------- .../src/e2e/models/ForgotPasswordPage.ts | 18 ----- e2e-tests/cypress/src/e2e/models/LoginPage.ts | 35 ---------- .../cypress/src/e2e/models/OverviewPage.ts | 10 --- .../cypress/src/e2e/models/ProfilePage.ts | 35 ---------- .../src/e2e/models/RegistrationPage.ts | 42 ----------- .../src/e2e/models/ResetPasswordPage.ts | 32 --------- .../cypress/src/e2e/models/SideNavMenu.ts | 17 ----- e2e-tests/cypress/src/e2e/models/Toasts.ts | 10 --- .../cypress/src/e2e/models/UserEMailSite.ts | 17 ----- e2e-tests/cypress/src/fixtures/users.json | 7 -- e2e-tests/cypress/src/support/e2e.ts | 38 ---------- e2e-tests/cypress/src/support/index.ts | 14 ---- .../support/step_definitions/common_steps.ts | 39 ----------- .../support/step_definitions/email_steps.ts | 45 ------------ .../user_authentication_steps.ts | 69 ------------------- .../user_profile_change_password_steps.ts | 32 --------- .../user_registration_steps.ts | 24 ------- 21 files changed, 566 deletions(-) delete mode 100644 e2e-tests/cypress/src/e2e/User.Authentication.ResetPassword.feature delete mode 100644 e2e-tests/cypress/src/e2e/User.Authentication.feature delete mode 100644 e2e-tests/cypress/src/e2e/User.Registration.feature delete mode 100644 e2e-tests/cypress/src/e2e/UserProfile.ChangePassword.feature delete mode 100644 e2e-tests/cypress/src/e2e/models/ForgotPasswordPage.ts delete mode 100644 e2e-tests/cypress/src/e2e/models/LoginPage.ts delete mode 100644 e2e-tests/cypress/src/e2e/models/OverviewPage.ts delete mode 100644 e2e-tests/cypress/src/e2e/models/ProfilePage.ts delete mode 100644 e2e-tests/cypress/src/e2e/models/RegistrationPage.ts delete mode 100644 e2e-tests/cypress/src/e2e/models/ResetPasswordPage.ts delete mode 100644 e2e-tests/cypress/src/e2e/models/SideNavMenu.ts delete mode 100644 e2e-tests/cypress/src/e2e/models/Toasts.ts delete mode 100644 e2e-tests/cypress/src/e2e/models/UserEMailSite.ts delete mode 100644 e2e-tests/cypress/src/fixtures/users.json delete mode 100644 e2e-tests/cypress/src/support/e2e.ts delete mode 100644 e2e-tests/cypress/src/support/index.ts delete mode 100644 e2e-tests/cypress/src/support/step_definitions/common_steps.ts delete mode 100644 e2e-tests/cypress/src/support/step_definitions/email_steps.ts delete mode 100644 e2e-tests/cypress/src/support/step_definitions/user_authentication_steps.ts delete mode 100644 e2e-tests/cypress/src/support/step_definitions/user_profile_change_password_steps.ts delete mode 100644 e2e-tests/cypress/src/support/step_definitions/user_registration_steps.ts diff --git a/e2e-tests/cypress/src/e2e/User.Authentication.ResetPassword.feature b/e2e-tests/cypress/src/e2e/User.Authentication.ResetPassword.feature deleted file mode 100644 index 55ca87215..000000000 --- a/e2e-tests/cypress/src/e2e/User.Authentication.ResetPassword.feature +++ /dev/null @@ -1,25 +0,0 @@ -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/src/e2e/User.Authentication.feature b/e2e-tests/cypress/src/e2e/User.Authentication.feature deleted file mode 100644 index 3b460efc6..000000000 --- a/e2e-tests/cypress/src/e2e/User.Authentication.feature +++ /dev/null @@ -1,17 +0,0 @@ -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/src/e2e/User.Registration.feature b/e2e-tests/cypress/src/e2e/User.Registration.feature deleted file mode 100644 index ed53bb4b0..000000000 --- a/e2e-tests/cypress/src/e2e/User.Registration.feature +++ /dev/null @@ -1,13 +0,0 @@ -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/src/e2e/UserProfile.ChangePassword.feature b/e2e-tests/cypress/src/e2e/UserProfile.ChangePassword.feature deleted file mode 100644 index aa853f6ff..000000000 --- a/e2e-tests/cypress/src/e2e/UserProfile.ChangePassword.feature +++ /dev/null @@ -1,27 +0,0 @@ -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/src/e2e/models/ForgotPasswordPage.ts b/e2e-tests/cypress/src/e2e/models/ForgotPasswordPage.ts deleted file mode 100644 index b97bc8ee7..000000000 --- a/e2e-tests/cypress/src/e2e/models/ForgotPasswordPage.ts +++ /dev/null @@ -1,18 +0,0 @@ -/// - -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/src/e2e/models/LoginPage.ts b/e2e-tests/cypress/src/e2e/models/LoginPage.ts deleted file mode 100644 index 52aa5d19b..000000000 --- a/e2e-tests/cypress/src/e2e/models/LoginPage.ts +++ /dev/null @@ -1,35 +0,0 @@ -/// - -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/src/e2e/models/OverviewPage.ts b/e2e-tests/cypress/src/e2e/models/OverviewPage.ts deleted file mode 100644 index 345124c66..000000000 --- a/e2e-tests/cypress/src/e2e/models/OverviewPage.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - -export class OverviewPage { - navbarName = '[data-test="navbar-item-username"]' - - goto() { - cy.visit('/overview') - return this - } -} diff --git a/e2e-tests/cypress/src/e2e/models/ProfilePage.ts b/e2e-tests/cypress/src/e2e/models/ProfilePage.ts deleted file mode 100644 index 4d5b98a53..000000000 --- a/e2e-tests/cypress/src/e2e/models/ProfilePage.ts +++ /dev/null @@ -1,35 +0,0 @@ -/// - -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/src/e2e/models/RegistrationPage.ts b/e2e-tests/cypress/src/e2e/models/RegistrationPage.ts deleted file mode 100644 index 8cae26a26..000000000 --- a/e2e-tests/cypress/src/e2e/models/RegistrationPage.ts +++ /dev/null @@ -1,42 +0,0 @@ -/// - -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/src/e2e/models/ResetPasswordPage.ts b/e2e-tests/cypress/src/e2e/models/ResetPasswordPage.ts deleted file mode 100644 index 20134de6d..000000000 --- a/e2e-tests/cypress/src/e2e/models/ResetPasswordPage.ts +++ /dev/null @@ -1,32 +0,0 @@ -/// - -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/src/e2e/models/SideNavMenu.ts b/e2e-tests/cypress/src/e2e/models/SideNavMenu.ts deleted file mode 100644 index ccd177b66..000000000 --- a/e2e-tests/cypress/src/e2e/models/SideNavMenu.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// - -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/src/e2e/models/Toasts.ts b/e2e-tests/cypress/src/e2e/models/Toasts.ts deleted file mode 100644 index efd5052fb..000000000 --- a/e2e-tests/cypress/src/e2e/models/Toasts.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - -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/src/e2e/models/UserEMailSite.ts b/e2e-tests/cypress/src/e2e/models/UserEMailSite.ts deleted file mode 100644 index f46f5677b..000000000 --- a/e2e-tests/cypress/src/e2e/models/UserEMailSite.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// - -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/src/fixtures/users.json b/e2e-tests/cypress/src/fixtures/users.json deleted file mode 100644 index f13e203f0..000000000 --- a/e2e-tests/cypress/src/fixtures/users.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "user": { - "email": "bibi@bloxberg.de", - "password": "Aa12345_", - "name": "Bibi Bloxberg" - } -} diff --git a/e2e-tests/cypress/src/support/e2e.ts b/e2e-tests/cypress/src/support/e2e.ts deleted file mode 100644 index 801165a48..000000000 --- a/e2e-tests/cypress/src/support/e2e.ts +++ /dev/null @@ -1,38 +0,0 @@ -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 token = response.headers.token - let tokenTime - - // 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/src/support/index.ts b/e2e-tests/cypress/src/support/index.ts deleted file mode 100644 index f8d1abacf..000000000 --- a/e2e-tests/cypress/src/support/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* 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/src/support/step_definitions/common_steps.ts b/e2e-tests/cypress/src/support/step_definitions/common_steps.ts deleted file mode 100644 index c5d3004ac..000000000 --- a/e2e-tests/cypress/src/support/step_definitions/common_steps.ts +++ /dev/null @@ -1,39 +0,0 @@ -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/src/support/step_definitions/email_steps.ts b/e2e-tests/cypress/src/support/step_definitions/email_steps.ts deleted file mode 100644 index 7d70e36bc..000000000 --- a/e2e-tests/cypress/src/support/step_definitions/email_steps.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Then, When } from '@badeball/cypress-cucumber-preprocessor' -import { ResetPasswordPage } from '@models/ResetPasswordPage' -import { UserEMailSite } from '@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/src/support/step_definitions/user_authentication_steps.ts b/e2e-tests/cypress/src/support/step_definitions/user_authentication_steps.ts deleted file mode 100644 index 5b25f5391..000000000 --- a/e2e-tests/cypress/src/support/step_definitions/user_authentication_steps.ts +++ /dev/null @@ -1,69 +0,0 @@ -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/src/support/step_definitions/user_profile_change_password_steps.ts b/e2e-tests/cypress/src/support/step_definitions/user_profile_change_password_steps.ts deleted file mode 100644 index 1dcbe69ef..000000000 --- a/e2e-tests/cypress/src/support/step_definitions/user_profile_change_password_steps.ts +++ /dev/null @@ -1,32 +0,0 @@ -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/src/support/step_definitions/user_registration_steps.ts b/e2e-tests/cypress/src/support/step_definitions/user_registration_steps.ts deleted file mode 100644 index 6f4034447..000000000 --- a/e2e-tests/cypress/src/support/step_definitions/user_registration_steps.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { And, When } from '@badeball/cypress-cucumber-preprocessor' -import { RegistrationPage } from '@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') -}) From 227f793deccbe105833cd2558eb54d34bdc8fc83 Mon Sep 17 00:00:00 2001 From: elweyn Date: Sun, 12 Feb 2023 07:28:38 +0100 Subject: [PATCH 5/9] Move src to cypress. --- .../User.Authentication.ResetPassword.feature | 25 +++++++ .../cypress/e2e/User.Authentication.feature | 17 +++++ .../cypress/e2e/User.Registration.feature | 13 ++++ .../e2e/UserProfile.ChangePassword.feature | 27 ++++++++ .../cypress/e2e/models/ForgotPasswordPage.ts | 18 +++++ .../cypress/cypress/e2e/models/LoginPage.ts | 35 ++++++++++ .../cypress/e2e/models/OverviewPage.ts | 10 +++ .../cypress/cypress/e2e/models/ProfilePage.ts | 35 ++++++++++ .../cypress/e2e/models/RegistrationPage.ts | 42 +++++++++++ .../cypress/e2e/models/ResetPasswordPage.ts | 32 +++++++++ .../cypress/cypress/e2e/models/SideNavMenu.ts | 17 +++++ .../cypress/cypress/e2e/models/Toasts.ts | 10 +++ .../cypress/e2e/models/UserEMailSite.ts | 17 +++++ e2e-tests/cypress/cypress/fixtures/users.json | 7 ++ e2e-tests/cypress/cypress/support/e2e.ts | 40 +++++++++++ e2e-tests/cypress/cypress/support/index.ts | 14 ++++ .../support/step_definitions/common_steps.ts | 39 +++++++++++ .../support/step_definitions/email_steps.ts | 45 ++++++++++++ .../user_authentication_steps.ts | 69 +++++++++++++++++++ .../user_profile_change_password_steps.ts | 32 +++++++++ .../user_registration_steps.ts | 24 +++++++ 21 files changed, 568 insertions(+) create mode 100644 e2e-tests/cypress/cypress/e2e/User.Authentication.ResetPassword.feature create mode 100644 e2e-tests/cypress/cypress/e2e/User.Authentication.feature create mode 100644 e2e-tests/cypress/cypress/e2e/User.Registration.feature create mode 100644 e2e-tests/cypress/cypress/e2e/UserProfile.ChangePassword.feature create mode 100644 e2e-tests/cypress/cypress/e2e/models/ForgotPasswordPage.ts create mode 100644 e2e-tests/cypress/cypress/e2e/models/LoginPage.ts create mode 100644 e2e-tests/cypress/cypress/e2e/models/OverviewPage.ts create mode 100644 e2e-tests/cypress/cypress/e2e/models/ProfilePage.ts create mode 100644 e2e-tests/cypress/cypress/e2e/models/RegistrationPage.ts create mode 100644 e2e-tests/cypress/cypress/e2e/models/ResetPasswordPage.ts create mode 100644 e2e-tests/cypress/cypress/e2e/models/SideNavMenu.ts create mode 100644 e2e-tests/cypress/cypress/e2e/models/Toasts.ts create mode 100644 e2e-tests/cypress/cypress/e2e/models/UserEMailSite.ts create mode 100644 e2e-tests/cypress/cypress/fixtures/users.json create mode 100644 e2e-tests/cypress/cypress/support/e2e.ts create mode 100644 e2e-tests/cypress/cypress/support/index.ts create mode 100644 e2e-tests/cypress/cypress/support/step_definitions/common_steps.ts create mode 100644 e2e-tests/cypress/cypress/support/step_definitions/email_steps.ts create mode 100644 e2e-tests/cypress/cypress/support/step_definitions/user_authentication_steps.ts create mode 100644 e2e-tests/cypress/cypress/support/step_definitions/user_profile_change_password_steps.ts create mode 100644 e2e-tests/cypress/cypress/support/step_definitions/user_registration_steps.ts 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') +}) From eb433ba8707c135befb7e2d23be6950d1812af08 Mon Sep 17 00:00:00 2001 From: elweyn Date: Sun, 12 Feb 2023 07:29:18 +0100 Subject: [PATCH 6/9] Remove un unused ". --- e2e-tests/cypress/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/cypress/Dockerfile b/e2e-tests/cypress/Dockerfile index 7d036c613..1a520572e 100644 --- a/e2e-tests/cypress/Dockerfile +++ b/e2e-tests/cypress/Dockerfile @@ -11,7 +11,7 @@ ############################################################################### FROM cypress/base:16.14.2-slim -ARG DOCKER_WORKDIR"="/tests" +ARG DOCKER_WORKDIR="/tests" WORKDIR $DOCKER_WORKDIR # install dependencies From a63bc245f5d638f0006139ac2a757f3804fb85d7 Mon Sep 17 00:00:00 2001 From: elweyn Date: Sun, 12 Feb 2023 07:32:15 +0100 Subject: [PATCH 7/9] Small optimization. --- .github/workflows/test.yml | 4 ++-- e2e-tests/cypress/.gitignore | 6 +++--- e2e-tests/cypress/tsconfig.json | 9 +++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4d30cda1f..0d627c2be 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -649,10 +649,10 @@ jobs: run: | cd e2e-tests/cypress/ yarn - yarn run cypress run --spec src/e2e/User.Authentication.feature,cypress/e2e/User.Authentication.ResetPassword.feature + yarn run cypress run --spec cypress/e2e/User.Authentication.feature,cypress/e2e/User.Authentication.ResetPassword.feature - name: End-to-end tests | if tests failed, upload screenshots if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} uses: actions/upload-artifact@v3 with: name: cypress-screenshots - path: /home/runner/work/gradido/gradido/e2e-tests/cypress/tests/cypress/screenshots/ + path: /home/runner/work/gradido/gradido/e2e-tests/tests/screenshots/ diff --git a/e2e-tests/cypress/.gitignore b/e2e-tests/cypress/.gitignore index 1261bffa8..7ff29d6e8 100644 --- a/e2e-tests/cypress/.gitignore +++ b/e2e-tests/cypress/.gitignore @@ -1,4 +1,4 @@ node_modules/ -src/screenshots/ -src/videos/ -src/cucumber-messages.ndjson +cypress/screenshots/ +cypress/videos/ +cypress/cucumber-messages.ndjson diff --git a/e2e-tests/cypress/tsconfig.json b/e2e-tests/cypress/tsconfig.json index 4d863857b..c07e512cb 100644 --- a/e2e-tests/cypress/tsconfig.json +++ b/e2e-tests/cypress/tsconfig.json @@ -1,15 +1,16 @@ { "compilerOptions": { - "target": "es2016", + "target": "es6", "lib": ["es6", "dom"], "baseUrl": ".", "types": ["cypress", "node"], "strict": true, - "esModuleInterop": true, + "esModuleInterop": true, "moduleResolution": "node", "paths": { - "@/*": ["src/*"], - "@models/*": ["src/e2e/models/*"], + "@/*": ["cypress/*"], + "@models/*": ["cypress/e2e/models/*"], } }, + "include": ["**/*.ts"], } From 7394735fb9abd4a997577cfe6fcd61327c549234 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 13 Feb 2023 12:08:56 +0100 Subject: [PATCH 8/9] Change structure now {root}/e2e-tests/cypress/* instead of cypress/cypress --- e2e-tests/{cypress => }/.eslintignore | 0 e2e-tests/{cypress => }/.eslintrc.js | 0 e2e-tests/{cypress => }/.gitignore | 0 e2e-tests/{cypress => }/.prettierrc.js | 0 e2e-tests/{cypress => }/Dockerfile | 0 e2e-tests/README.md | 74 ++++++++++++++++++- e2e-tests/cucumber-messages.ndjson | 64 ++++++++++++++++ e2e-tests/{cypress => }/cypress.config.ts | 0 e2e-tests/cypress/README.md | 73 ------------------ .../User.Authentication.ResetPassword.feature | 0 .../e2e/User.Authentication.feature | 0 .../e2e/User.Registration.feature | 0 .../e2e/UserProfile.ChangePassword.feature | 0 .../e2e/models/ForgotPasswordPage.ts | 0 .../{cypress => }/e2e/models/LoginPage.ts | 0 .../{cypress => }/e2e/models/OverviewPage.ts | 0 .../{cypress => }/e2e/models/ProfilePage.ts | 0 .../e2e/models/RegistrationPage.ts | 0 .../e2e/models/ResetPasswordPage.ts | 0 .../{cypress => }/e2e/models/SideNavMenu.ts | 0 .../{cypress => }/e2e/models/Toasts.ts | 0 .../{cypress => }/e2e/models/UserEMailSite.ts | 0 .../cypress/{cypress => }/fixtures/users.json | 0 .../cypress/{cypress => }/support/e2e.ts | 0 .../cypress/{cypress => }/support/index.ts | 0 .../support/step_definitions/common_steps.ts | 0 .../support/step_definitions/email_steps.ts | 0 .../user_authentication_steps.ts | 0 .../user_profile_change_password_steps.ts | 0 .../user_registration_steps.ts | 0 e2e-tests/{cypress => }/package.json | 0 e2e-tests/{cypress => }/tsconfig.json | 0 e2e-tests/{cypress => }/yarn.lock | 0 33 files changed, 134 insertions(+), 77 deletions(-) rename e2e-tests/{cypress => }/.eslintignore (100%) rename e2e-tests/{cypress => }/.eslintrc.js (100%) rename e2e-tests/{cypress => }/.gitignore (100%) rename e2e-tests/{cypress => }/.prettierrc.js (100%) rename e2e-tests/{cypress => }/Dockerfile (100%) create mode 100644 e2e-tests/cucumber-messages.ndjson rename e2e-tests/{cypress => }/cypress.config.ts (100%) delete mode 100644 e2e-tests/cypress/README.md rename e2e-tests/cypress/{cypress => }/e2e/User.Authentication.ResetPassword.feature (100%) rename e2e-tests/cypress/{cypress => }/e2e/User.Authentication.feature (100%) rename e2e-tests/cypress/{cypress => }/e2e/User.Registration.feature (100%) rename e2e-tests/cypress/{cypress => }/e2e/UserProfile.ChangePassword.feature (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/ForgotPasswordPage.ts (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/LoginPage.ts (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/OverviewPage.ts (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/ProfilePage.ts (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/RegistrationPage.ts (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/ResetPasswordPage.ts (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/SideNavMenu.ts (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/Toasts.ts (100%) rename e2e-tests/cypress/{cypress => }/e2e/models/UserEMailSite.ts (100%) rename e2e-tests/cypress/{cypress => }/fixtures/users.json (100%) rename e2e-tests/cypress/{cypress => }/support/e2e.ts (100%) rename e2e-tests/cypress/{cypress => }/support/index.ts (100%) rename e2e-tests/cypress/{cypress => }/support/step_definitions/common_steps.ts (100%) rename e2e-tests/cypress/{cypress => }/support/step_definitions/email_steps.ts (100%) rename e2e-tests/cypress/{cypress => }/support/step_definitions/user_authentication_steps.ts (100%) rename e2e-tests/cypress/{cypress => }/support/step_definitions/user_profile_change_password_steps.ts (100%) rename e2e-tests/cypress/{cypress => }/support/step_definitions/user_registration_steps.ts (100%) rename e2e-tests/{cypress => }/package.json (100%) rename e2e-tests/{cypress => }/tsconfig.json (100%) rename e2e-tests/{cypress => }/yarn.lock (100%) diff --git a/e2e-tests/cypress/.eslintignore b/e2e-tests/.eslintignore similarity index 100% rename from e2e-tests/cypress/.eslintignore rename to e2e-tests/.eslintignore diff --git a/e2e-tests/cypress/.eslintrc.js b/e2e-tests/.eslintrc.js similarity index 100% rename from e2e-tests/cypress/.eslintrc.js rename to e2e-tests/.eslintrc.js diff --git a/e2e-tests/cypress/.gitignore b/e2e-tests/.gitignore similarity index 100% rename from e2e-tests/cypress/.gitignore rename to e2e-tests/.gitignore diff --git a/e2e-tests/cypress/.prettierrc.js b/e2e-tests/.prettierrc.js similarity index 100% rename from e2e-tests/cypress/.prettierrc.js rename to e2e-tests/.prettierrc.js diff --git a/e2e-tests/cypress/Dockerfile b/e2e-tests/Dockerfile similarity index 100% rename from e2e-tests/cypress/Dockerfile rename to e2e-tests/Dockerfile diff --git a/e2e-tests/README.md b/e2e-tests/README.md index f53618ab4..4ec1ebe51 100644 --- a/e2e-tests/README.md +++ b/e2e-tests/README.md @@ -1,7 +1,73 @@ -# Gradido end-to-end tests +# Gradido End-to-End Testing with [Cypress](https://www.cypress.io/) (CI-ready via Docker) -This is still WIP. +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. -For automated end-to-end testing one of the frameworks Cypress or Playwright will be utilized. -For more details on how to run them, see the subfolders' README instructions. +## 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) + + +## Precondition + +Before running the tests, change to the repo's root directory (gradido). + +### Boot up the system under test + +```bash +docker-compose up +``` + +### 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 image and execute the given tests +docker run -it --network=host gradido_e2e-tests-cypress yarn cypress-e2e +``` diff --git a/e2e-tests/cucumber-messages.ndjson b/e2e-tests/cucumber-messages.ndjson new file mode 100644 index 000000000..653948a88 --- /dev/null +++ b/e2e-tests/cucumber-messages.ndjson @@ -0,0 +1,64 @@ +{"testRunStarted":{"timestamp":{"seconds":1676286317,"nanos":602000000}}} +{"source":{"data":"Feature: User authentication\n As a user\n I want to be able to sign in - only with valid credentials\n In order to be able to posts and do other contributions as myself\n Furthermore I want to be able to stay logged in and logout again\n\n # TODO for these pre-conditions utilize seeding or API check, if user exists in test system\n # Background:\n # Given the following \"users\" are in the database:\n # | email | password | name |\n # | bibi@bloxberg.de | Aa12345_ | Bibi Bloxberg |\n\n Scenario: Log in successfully\n Given the user navigates to page \"/login\"\n When the user submits the credentials \"bibi@bloxberg.de\" \"Aa12345_\"\n Then the user is logged in with username \"Bibi Bloxberg\"\n\n","uri":"cypress/e2e/User.Authentication.feature","mediaType":"text/x.cucumber.gherkin+plain"}} +{"gherkinDocument":{"feature":{"tags":[],"location":{"line":1,"column":1},"language":"en","keyword":"Feature","name":"User authentication","description":" As a user\n I want to be able to sign in - only with valid credentials\n In order to be able to posts and do other contributions as myself\n Furthermore I want to be able to stay logged in and logout again","children":[{"scenario":{"id":"a0e60b61-d279-428a-a801-276b5142499f","tags":[],"location":{"line":13,"column":3},"keyword":"Scenario","name":"Log in successfully","description":"","steps":[{"id":"904f82d6-cd31-4b76-a43f-fb3b53cd30e1","location":{"line":14,"column":5},"keyword":"Given ","keywordType":"Context","text":"the user navigates to page \"/login\""},{"id":"f2b5ed61-f51c-4822-b086-b7ab4852ae2e","location":{"line":15,"column":5},"keyword":"When ","keywordType":"Action","text":"the user submits the credentials \"bibi@bloxberg.de\" \"Aa12345_\""},{"id":"cff1f6a9-23c7-43de-b49b-d472c47b32dc","location":{"line":16,"column":5},"keyword":"Then ","keywordType":"Outcome","text":"the user is logged in with username \"Bibi Bloxberg\""}],"examples":[]}}]},"comments":[{"location":{"line":7,"column":1},"text":" # TODO for these pre-conditions utilize seeding or API check, if user exists in test system"},{"location":{"line":8,"column":1},"text":" # Background:"},{"location":{"line":9,"column":1},"text":" # Given the following \"users\" are in the database:"},{"location":{"line":10,"column":1},"text":" # | email | password | name |"},{"location":{"line":11,"column":1},"text":" # | bibi@bloxberg.de | Aa12345_ | Bibi Bloxberg |"}],"uri":"cypress/e2e/User.Authentication.feature"}} +{"pickle":{"id":"594b4e85-f837-4444-ac71-6ac177cb10b3","uri":"cypress/e2e/User.Authentication.feature","astNodeIds":["a0e60b61-d279-428a-a801-276b5142499f"],"tags":[],"name":"Log in successfully","language":"en","steps":[{"id":"1ae06614-195e-419b-aef6-7b9fbc101dad","text":"the user navigates to page \"/login\"","type":"Context","astNodeIds":["904f82d6-cd31-4b76-a43f-fb3b53cd30e1"]},{"id":"a883467f-a8dc-41c0-82b1-e31ed6ce7996","text":"the user submits the credentials \"bibi@bloxberg.de\" \"Aa12345_\"","type":"Action","astNodeIds":["f2b5ed61-f51c-4822-b086-b7ab4852ae2e"]},{"id":"bc98b28e-ea68-4d2f-b849-f303edb219c4","text":"the user is logged in with username \"Bibi Bloxberg\"","type":"Outcome","astNodeIds":["cff1f6a9-23c7-43de-b49b-d472c47b32dc"]}]}} +{"stepDefinition":{"id":"5d4d7728-0f60-407e-9ba1-6ab14446d7b3","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"7ef374e8-2748-43c2-9d39-e254d0724de9","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"d4b6c30d-d239-44bb-9963-b273e3aba5bf","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"testCase":{"id":"df8b15f1-e497-49c4-918d-a25a71996742","pickleId":"594b4e85-f837-4444-ac71-6ac177cb10b3","testSteps":[{"id":"1ae06614-195e-419b-aef6-7b9fbc101dad","pickleStepId":"1ae06614-195e-419b-aef6-7b9fbc101dad","stepDefinitionIds":["5d4d7728-0f60-407e-9ba1-6ab14446d7b3"]},{"id":"a883467f-a8dc-41c0-82b1-e31ed6ce7996","pickleStepId":"a883467f-a8dc-41c0-82b1-e31ed6ce7996","stepDefinitionIds":["7ef374e8-2748-43c2-9d39-e254d0724de9"]},{"id":"bc98b28e-ea68-4d2f-b849-f303edb219c4","pickleStepId":"bc98b28e-ea68-4d2f-b849-f303edb219c4","stepDefinitionIds":["d4b6c30d-d239-44bb-9963-b273e3aba5bf"]}]}} +{"testCaseStarted":{"id":"0677b26e-1829-46ae-a27f-6eac9506d2fa","testCaseId":"df8b15f1-e497-49c4-918d-a25a71996742","attempt":0,"timestamp":{"seconds":1676286322,"nanos":42000000}}} +{"testStepStarted":{"testStepId":"1ae06614-195e-419b-aef6-7b9fbc101dad","testCaseStartedId":"0677b26e-1829-46ae-a27f-6eac9506d2fa","timestamp":{"seconds":1676286322,"nanos":58000000}}} +{"testStepFinished":{"testStepId":"1ae06614-195e-419b-aef6-7b9fbc101dad","testCaseStartedId":"0677b26e-1829-46ae-a27f-6eac9506d2fa","testStepResult":{"status":"PASSED","duration":{"seconds":4,"nanos":699000000}},"timestamp":{"seconds":1676286326,"nanos":757000000}}} +{"testStepStarted":{"testStepId":"a883467f-a8dc-41c0-82b1-e31ed6ce7996","testCaseStartedId":"0677b26e-1829-46ae-a27f-6eac9506d2fa","timestamp":{"seconds":1676286326,"nanos":768000000}}} +{"testStepFinished":{"testStepId":"a883467f-a8dc-41c0-82b1-e31ed6ce7996","testCaseStartedId":"0677b26e-1829-46ae-a27f-6eac9506d2fa","testStepResult":{"status":"PASSED","duration":{"seconds":2,"nanos":194000000}},"timestamp":{"seconds":1676286328,"nanos":962000000}}} +{"testStepStarted":{"testStepId":"bc98b28e-ea68-4d2f-b849-f303edb219c4","testCaseStartedId":"0677b26e-1829-46ae-a27f-6eac9506d2fa","timestamp":{"seconds":1676286328,"nanos":969000000}}} +{"testStepFinished":{"testStepId":"bc98b28e-ea68-4d2f-b849-f303edb219c4","testCaseStartedId":"0677b26e-1829-46ae-a27f-6eac9506d2fa","testStepResult":{"status":"PASSED","duration":{"seconds":2,"nanos":-179000000}},"timestamp":{"seconds":1676286330,"nanos":790000000}}} +{"testCaseFinished":{"testCaseStartedId":"0677b26e-1829-46ae-a27f-6eac9506d2fa","timestamp":{"seconds":1676286330,"nanos":806000000},"willBeRetried":false}} +{"source":{"data":"Feature: User Authentication - reset password\n As a user\n I want to reset my password from the sign in page\n\n # TODO for these pre-conditions utilize seeding or API check, if user exists in test system\n # Background:\n # Given the following \"users\" are in the database:\n # | email | password | name |\n # | bibi@bloxberg.de | Aa12345_ | Bibi Bloxberg |\n\n Scenario: Reset password from signin page successfully\n Given the user navigates to page \"/login\"\n And the user navigates to the forgot password page\n When the user enters the e-mail address \"bibi@bloxberg.de\"\n And the user submits the e-mail form\n Then the user receives an e-mail containing the password reset link\n When the user opens the password reset link in the browser\n And the user enters the password \"12345Aa_\"\n And the user repeats the password \"12345Aa_\"\n And the user submits the password form\n And the user clicks the sign in button\n Then the user submits the credentials \"bibi@bloxberg.de\" \"Aa12345_\"\n And the user cannot login\n But the user submits the credentials \"bibi@bloxberg.de\" \"12345Aa_\"\n And the user is logged in with username \"Bibi Bloxberg\"\n","uri":"cypress/e2e/User.Authentication.ResetPassword.feature","mediaType":"text/x.cucumber.gherkin+plain"}} +{"gherkinDocument":{"feature":{"tags":[],"location":{"line":1,"column":1},"language":"en","keyword":"Feature","name":"User Authentication - reset password","description":" As a user\n I want to reset my password from the sign in page","children":[{"scenario":{"id":"8e0e49f7-45ab-4a17-9504-45cff1415b1e","tags":[],"location":{"line":11,"column":3},"keyword":"Scenario","name":"Reset password from signin page successfully","description":"","steps":[{"id":"10d7ec81-19d9-4c52-9987-22d9a90b584d","location":{"line":12,"column":5},"keyword":"Given ","keywordType":"Context","text":"the user navigates to page \"/login\""},{"id":"02bf5e72-d84f-4bcf-87d8-38d5afd035c3","location":{"line":13,"column":5},"keyword":"And ","keywordType":"Conjunction","text":"the user navigates to the forgot password page"},{"id":"dfdeedc3-6b79-44f3-9673-b01071bef0b6","location":{"line":14,"column":5},"keyword":"When ","keywordType":"Action","text":"the user enters the e-mail address \"bibi@bloxberg.de\""},{"id":"5c288ecb-447f-48c8-8756-f3e218bd309b","location":{"line":15,"column":5},"keyword":"And ","keywordType":"Conjunction","text":"the user submits the e-mail form"},{"id":"ade71b55-6471-4eeb-9216-ab597963ba83","location":{"line":16,"column":5},"keyword":"Then ","keywordType":"Outcome","text":"the user receives an e-mail containing the password reset link"},{"id":"7f0ea3d7-18c8-48a6-a23c-8a0c2ab66d5e","location":{"line":17,"column":5},"keyword":"When ","keywordType":"Action","text":"the user opens the password reset link in the browser"},{"id":"01e974c7-ed2a-4fae-a30b-75bd5662a286","location":{"line":18,"column":5},"keyword":"And ","keywordType":"Conjunction","text":"the user enters the password \"12345Aa_\""},{"id":"1440ce50-80fe-4e0a-a948-66bf83867e09","location":{"line":19,"column":5},"keyword":"And ","keywordType":"Conjunction","text":"the user repeats the password \"12345Aa_\""},{"id":"d0fc532d-ab9b-4240-9d73-4ca329c3f98e","location":{"line":20,"column":5},"keyword":"And ","keywordType":"Conjunction","text":"the user submits the password form"},{"id":"9860b7f0-c08c-494b-b4dc-65c1201e6d50","location":{"line":21,"column":5},"keyword":"And ","keywordType":"Conjunction","text":"the user clicks the sign in button"},{"id":"bcc6cea7-9e05-4d9d-b9fb-bb0e78c56382","location":{"line":22,"column":5},"keyword":"Then ","keywordType":"Outcome","text":"the user submits the credentials \"bibi@bloxberg.de\" \"Aa12345_\""},{"id":"36382e35-9bdf-4780-86df-4739aa1e53a3","location":{"line":23,"column":5},"keyword":"And ","keywordType":"Conjunction","text":"the user cannot login"},{"id":"a8678804-db7f-498c-b887-b7236ac03b55","location":{"line":24,"column":5},"keyword":"But ","keywordType":"Conjunction","text":"the user submits the credentials \"bibi@bloxberg.de\" \"12345Aa_\""},{"id":"9977e940-f7fc-48eb-b13f-b7ecd2b4f55f","location":{"line":25,"column":5},"keyword":"And ","keywordType":"Conjunction","text":"the user is logged in with username \"Bibi Bloxberg\""}],"examples":[]}}]},"comments":[{"location":{"line":5,"column":1},"text":" # TODO for these pre-conditions utilize seeding or API check, if user exists in test system"},{"location":{"line":6,"column":1},"text":" # Background:"},{"location":{"line":7,"column":1},"text":" # Given the following \"users\" are in the database:"},{"location":{"line":8,"column":1},"text":" # | email | password | name |"},{"location":{"line":9,"column":1},"text":" # | bibi@bloxberg.de | Aa12345_ | Bibi Bloxberg |"}],"uri":"cypress/e2e/User.Authentication.ResetPassword.feature"}} +{"pickle":{"id":"24f9bcc4-a1d7-4181-8f8b-5f6af6d9832f","uri":"cypress/e2e/User.Authentication.ResetPassword.feature","astNodeIds":["8e0e49f7-45ab-4a17-9504-45cff1415b1e"],"tags":[],"name":"Reset password from signin page successfully","language":"en","steps":[{"id":"40973f19-55d1-4ee1-8a8e-692b39df8408","text":"the user navigates to page \"/login\"","type":"Context","astNodeIds":["10d7ec81-19d9-4c52-9987-22d9a90b584d"]},{"id":"23d91a4d-950a-4697-8fab-f503a00bdff9","text":"the user navigates to the forgot password page","type":"Context","astNodeIds":["02bf5e72-d84f-4bcf-87d8-38d5afd035c3"]},{"id":"d4a72f40-5cb3-4448-95da-3ee4b4dd3725","text":"the user enters the e-mail address \"bibi@bloxberg.de\"","type":"Action","astNodeIds":["dfdeedc3-6b79-44f3-9673-b01071bef0b6"]},{"id":"fe4a8ade-35e6-445f-8fc6-a677749c23e4","text":"the user submits the e-mail form","type":"Action","astNodeIds":["5c288ecb-447f-48c8-8756-f3e218bd309b"]},{"id":"866472af-0e12-4e16-b92a-d328250b0e32","text":"the user receives an e-mail containing the password reset link","type":"Outcome","astNodeIds":["ade71b55-6471-4eeb-9216-ab597963ba83"]},{"id":"1573af3c-39b9-4a40-94ec-2252bc543c18","text":"the user opens the password reset link in the browser","type":"Action","astNodeIds":["7f0ea3d7-18c8-48a6-a23c-8a0c2ab66d5e"]},{"id":"343457b6-37c0-4dde-baad-31271212df53","text":"the user enters the password \"12345Aa_\"","type":"Action","astNodeIds":["01e974c7-ed2a-4fae-a30b-75bd5662a286"]},{"id":"2ce2f26b-9cc0-47e9-9b3f-f8e0cff3c6c2","text":"the user repeats the password \"12345Aa_\"","type":"Action","astNodeIds":["1440ce50-80fe-4e0a-a948-66bf83867e09"]},{"id":"8ec7c2ad-ec75-42c3-b40e-6cb41b45a316","text":"the user submits the password form","type":"Action","astNodeIds":["d0fc532d-ab9b-4240-9d73-4ca329c3f98e"]},{"id":"20084ca2-45c5-4aa0-b8cc-3090421a1981","text":"the user clicks the sign in button","type":"Action","astNodeIds":["9860b7f0-c08c-494b-b4dc-65c1201e6d50"]},{"id":"318683e6-23d0-4983-8268-be0c86242e99","text":"the user submits the credentials \"bibi@bloxberg.de\" \"Aa12345_\"","type":"Outcome","astNodeIds":["bcc6cea7-9e05-4d9d-b9fb-bb0e78c56382"]},{"id":"3e46d169-05ec-49fc-b84b-02e9486cfe9d","text":"the user cannot login","type":"Outcome","astNodeIds":["36382e35-9bdf-4780-86df-4739aa1e53a3"]},{"id":"2a62df07-9fbe-44b5-b543-9990ff8b6df0","text":"the user submits the credentials \"bibi@bloxberg.de\" \"12345Aa_\"","type":"Outcome","astNodeIds":["a8678804-db7f-498c-b887-b7236ac03b55"]},{"id":"c52958a7-dfba-4e29-9844-0faf070f1b17","text":"the user is logged in with username \"Bibi Bloxberg\"","type":"Outcome","astNodeIds":["9977e940-f7fc-48eb-b13f-b7ecd2b4f55f"]}]}} +{"stepDefinition":{"id":"e5b7a6d9-792e-4cf1-9335-74ab0a548768","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"4fd7cf9c-e5c7-4c90-8e4a-01bccd8b8252","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"68741ec6-fff2-4c79-8cee-e8aa28790d99","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"f8bb3265-6e86-4a51-8c0f-cef6f8c6c419","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"b00d66f5-0efd-46b6-a3b2-8e57248e336f","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"2d1b4b54-a56f-4bfe-b52a-6e6173160da3","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"fd75a778-338e-4381-86cf-b42bfc506181","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"4e88908a-e314-4762-b235-b29b55651b78","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"512c8ff3-1bb0-4da2-adbe-f4cf6581d1a4","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"df4cfb85-1def-4b22-b067-25c775474824","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"299aec62-a03f-4f9e-8de8-d44a9c736a5c","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"9718ad70-b334-46a1-878b-96d078853162","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"9c60fe6c-8b1e-4b10-b8f6-2870f31838d9","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"stepDefinition":{"id":"255e6c36-30da-4817-8198-1f14f8813f85","pattern":{"source":"a step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"uri":"not available","location":{"line":0}}}} +{"testCase":{"id":"c84a9141-dd71-43ad-9169-7a29316dca69","pickleId":"24f9bcc4-a1d7-4181-8f8b-5f6af6d9832f","testSteps":[{"id":"40973f19-55d1-4ee1-8a8e-692b39df8408","pickleStepId":"40973f19-55d1-4ee1-8a8e-692b39df8408","stepDefinitionIds":["e5b7a6d9-792e-4cf1-9335-74ab0a548768"]},{"id":"23d91a4d-950a-4697-8fab-f503a00bdff9","pickleStepId":"23d91a4d-950a-4697-8fab-f503a00bdff9","stepDefinitionIds":["4fd7cf9c-e5c7-4c90-8e4a-01bccd8b8252"]},{"id":"d4a72f40-5cb3-4448-95da-3ee4b4dd3725","pickleStepId":"d4a72f40-5cb3-4448-95da-3ee4b4dd3725","stepDefinitionIds":["68741ec6-fff2-4c79-8cee-e8aa28790d99"]},{"id":"fe4a8ade-35e6-445f-8fc6-a677749c23e4","pickleStepId":"fe4a8ade-35e6-445f-8fc6-a677749c23e4","stepDefinitionIds":["f8bb3265-6e86-4a51-8c0f-cef6f8c6c419"]},{"id":"866472af-0e12-4e16-b92a-d328250b0e32","pickleStepId":"866472af-0e12-4e16-b92a-d328250b0e32","stepDefinitionIds":["b00d66f5-0efd-46b6-a3b2-8e57248e336f"]},{"id":"1573af3c-39b9-4a40-94ec-2252bc543c18","pickleStepId":"1573af3c-39b9-4a40-94ec-2252bc543c18","stepDefinitionIds":["2d1b4b54-a56f-4bfe-b52a-6e6173160da3"]},{"id":"343457b6-37c0-4dde-baad-31271212df53","pickleStepId":"343457b6-37c0-4dde-baad-31271212df53","stepDefinitionIds":["fd75a778-338e-4381-86cf-b42bfc506181"]},{"id":"2ce2f26b-9cc0-47e9-9b3f-f8e0cff3c6c2","pickleStepId":"2ce2f26b-9cc0-47e9-9b3f-f8e0cff3c6c2","stepDefinitionIds":["4e88908a-e314-4762-b235-b29b55651b78"]},{"id":"8ec7c2ad-ec75-42c3-b40e-6cb41b45a316","pickleStepId":"8ec7c2ad-ec75-42c3-b40e-6cb41b45a316","stepDefinitionIds":["512c8ff3-1bb0-4da2-adbe-f4cf6581d1a4"]},{"id":"20084ca2-45c5-4aa0-b8cc-3090421a1981","pickleStepId":"20084ca2-45c5-4aa0-b8cc-3090421a1981","stepDefinitionIds":["df4cfb85-1def-4b22-b067-25c775474824"]},{"id":"318683e6-23d0-4983-8268-be0c86242e99","pickleStepId":"318683e6-23d0-4983-8268-be0c86242e99","stepDefinitionIds":["299aec62-a03f-4f9e-8de8-d44a9c736a5c"]},{"id":"3e46d169-05ec-49fc-b84b-02e9486cfe9d","pickleStepId":"3e46d169-05ec-49fc-b84b-02e9486cfe9d","stepDefinitionIds":["9718ad70-b334-46a1-878b-96d078853162"]},{"id":"2a62df07-9fbe-44b5-b543-9990ff8b6df0","pickleStepId":"2a62df07-9fbe-44b5-b543-9990ff8b6df0","stepDefinitionIds":["9c60fe6c-8b1e-4b10-b8f6-2870f31838d9"]},{"id":"c52958a7-dfba-4e29-9844-0faf070f1b17","pickleStepId":"c52958a7-dfba-4e29-9844-0faf070f1b17","stepDefinitionIds":["255e6c36-30da-4817-8198-1f14f8813f85"]}]}} +{"testCaseStarted":{"id":"c71f19b8-2733-403d-a854-4c3760dd9eca","testCaseId":"c84a9141-dd71-43ad-9169-7a29316dca69","attempt":0,"timestamp":{"seconds":1676286336,"nanos":35000000}}} +{"testStepStarted":{"testStepId":"40973f19-55d1-4ee1-8a8e-692b39df8408","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286336,"nanos":53000000}}} +{"testStepFinished":{"testStepId":"40973f19-55d1-4ee1-8a8e-692b39df8408","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":3,"nanos":0}},"timestamp":{"seconds":1676286339,"nanos":53000000}}} +{"testStepStarted":{"testStepId":"23d91a4d-950a-4697-8fab-f503a00bdff9","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286339,"nanos":57000000}}} +{"testStepFinished":{"testStepId":"23d91a4d-950a-4697-8fab-f503a00bdff9","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":0,"nanos":215000000}},"timestamp":{"seconds":1676286339,"nanos":272000000}}} +{"testStepStarted":{"testStepId":"d4a72f40-5cb3-4448-95da-3ee4b4dd3725","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286339,"nanos":275000000}}} +{"testStepFinished":{"testStepId":"d4a72f40-5cb3-4448-95da-3ee4b4dd3725","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":0,"nanos":520000000}},"timestamp":{"seconds":1676286339,"nanos":795000000}}} +{"testStepStarted":{"testStepId":"fe4a8ade-35e6-445f-8fc6-a677749c23e4","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286339,"nanos":798000000}}} +{"testStepFinished":{"testStepId":"fe4a8ade-35e6-445f-8fc6-a677749c23e4","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":1,"nanos":-664000000}},"timestamp":{"seconds":1676286340,"nanos":134000000}}} +{"testStepStarted":{"testStepId":"866472af-0e12-4e16-b92a-d328250b0e32","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286340,"nanos":137000000}}} +{"testStepFinished":{"testStepId":"866472af-0e12-4e16-b92a-d328250b0e32","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":2,"nanos":411000000}},"timestamp":{"seconds":1676286342,"nanos":548000000}}} +{"testStepStarted":{"testStepId":"1573af3c-39b9-4a40-94ec-2252bc543c18","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286342,"nanos":551000000}}} +{"testStepFinished":{"testStepId":"1573af3c-39b9-4a40-94ec-2252bc543c18","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":1,"nanos":94000000}},"timestamp":{"seconds":1676286343,"nanos":645000000}}} +{"testStepStarted":{"testStepId":"343457b6-37c0-4dde-baad-31271212df53","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286343,"nanos":649000000}}} +{"testStepFinished":{"testStepId":"343457b6-37c0-4dde-baad-31271212df53","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":1,"nanos":-601000000}},"timestamp":{"seconds":1676286344,"nanos":48000000}}} +{"testStepStarted":{"testStepId":"2ce2f26b-9cc0-47e9-9b3f-f8e0cff3c6c2","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286344,"nanos":52000000}}} +{"testStepFinished":{"testStepId":"2ce2f26b-9cc0-47e9-9b3f-f8e0cff3c6c2","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":0,"nanos":313000000}},"timestamp":{"seconds":1676286344,"nanos":365000000}}} +{"testStepStarted":{"testStepId":"8ec7c2ad-ec75-42c3-b40e-6cb41b45a316","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286344,"nanos":368000000}}} +{"testStepFinished":{"testStepId":"8ec7c2ad-ec75-42c3-b40e-6cb41b45a316","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":0,"nanos":118000000}},"timestamp":{"seconds":1676286344,"nanos":486000000}}} +{"testStepStarted":{"testStepId":"20084ca2-45c5-4aa0-b8cc-3090421a1981","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286344,"nanos":489000000}}} +{"testStepFinished":{"testStepId":"20084ca2-45c5-4aa0-b8cc-3090421a1981","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":0,"nanos":377000000}},"timestamp":{"seconds":1676286344,"nanos":866000000}}} +{"testStepStarted":{"testStepId":"318683e6-23d0-4983-8268-be0c86242e99","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286344,"nanos":869000000}}} +{"testStepFinished":{"testStepId":"318683e6-23d0-4983-8268-be0c86242e99","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":2,"nanos":-643000000}},"timestamp":{"seconds":1676286346,"nanos":226000000}}} +{"testStepStarted":{"testStepId":"3e46d169-05ec-49fc-b84b-02e9486cfe9d","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286346,"nanos":228000000}}} +{"testStepFinished":{"testStepId":"3e46d169-05ec-49fc-b84b-02e9486cfe9d","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":0,"nanos":113000000}},"timestamp":{"seconds":1676286346,"nanos":341000000}}} +{"testStepStarted":{"testStepId":"2a62df07-9fbe-44b5-b543-9990ff8b6df0","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286346,"nanos":344000000}}} +{"testStepFinished":{"testStepId":"2a62df07-9fbe-44b5-b543-9990ff8b6df0","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":1,"nanos":371000000}},"timestamp":{"seconds":1676286347,"nanos":715000000}}} +{"testStepStarted":{"testStepId":"c52958a7-dfba-4e29-9844-0faf070f1b17","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286347,"nanos":718000000}}} +{"testStepFinished":{"testStepId":"c52958a7-dfba-4e29-9844-0faf070f1b17","testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","testStepResult":{"status":"PASSED","duration":{"seconds":2,"nanos":-345000000}},"timestamp":{"seconds":1676286349,"nanos":373000000}}} +{"testCaseFinished":{"testCaseStartedId":"c71f19b8-2733-403d-a854-4c3760dd9eca","timestamp":{"seconds":1676286349,"nanos":385000000},"willBeRetried":false}} diff --git a/e2e-tests/cypress/cypress.config.ts b/e2e-tests/cypress.config.ts similarity index 100% rename from e2e-tests/cypress/cypress.config.ts rename to e2e-tests/cypress.config.ts diff --git a/e2e-tests/cypress/README.md b/e2e-tests/cypress/README.md deleted file mode 100644 index 4ec1ebe51..000000000 --- a/e2e-tests/cypress/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# 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) - - -## Precondition - -Before running the tests, change to the repo's root directory (gradido). - -### Boot up the system under test - -```bash -docker-compose up -``` - -### 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 image and execute the given tests -docker run -it --network=host gradido_e2e-tests-cypress yarn cypress-e2e -``` diff --git a/e2e-tests/cypress/cypress/e2e/User.Authentication.ResetPassword.feature b/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature similarity index 100% rename from e2e-tests/cypress/cypress/e2e/User.Authentication.ResetPassword.feature rename to e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature diff --git a/e2e-tests/cypress/cypress/e2e/User.Authentication.feature b/e2e-tests/cypress/e2e/User.Authentication.feature similarity index 100% rename from e2e-tests/cypress/cypress/e2e/User.Authentication.feature rename to e2e-tests/cypress/e2e/User.Authentication.feature diff --git a/e2e-tests/cypress/cypress/e2e/User.Registration.feature b/e2e-tests/cypress/e2e/User.Registration.feature similarity index 100% rename from e2e-tests/cypress/cypress/e2e/User.Registration.feature rename to e2e-tests/cypress/e2e/User.Registration.feature diff --git a/e2e-tests/cypress/cypress/e2e/UserProfile.ChangePassword.feature b/e2e-tests/cypress/e2e/UserProfile.ChangePassword.feature similarity index 100% rename from e2e-tests/cypress/cypress/e2e/UserProfile.ChangePassword.feature rename to e2e-tests/cypress/e2e/UserProfile.ChangePassword.feature diff --git a/e2e-tests/cypress/cypress/e2e/models/ForgotPasswordPage.ts b/e2e-tests/cypress/e2e/models/ForgotPasswordPage.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/ForgotPasswordPage.ts rename to e2e-tests/cypress/e2e/models/ForgotPasswordPage.ts diff --git a/e2e-tests/cypress/cypress/e2e/models/LoginPage.ts b/e2e-tests/cypress/e2e/models/LoginPage.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/LoginPage.ts rename to e2e-tests/cypress/e2e/models/LoginPage.ts diff --git a/e2e-tests/cypress/cypress/e2e/models/OverviewPage.ts b/e2e-tests/cypress/e2e/models/OverviewPage.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/OverviewPage.ts rename to e2e-tests/cypress/e2e/models/OverviewPage.ts diff --git a/e2e-tests/cypress/cypress/e2e/models/ProfilePage.ts b/e2e-tests/cypress/e2e/models/ProfilePage.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/ProfilePage.ts rename to e2e-tests/cypress/e2e/models/ProfilePage.ts diff --git a/e2e-tests/cypress/cypress/e2e/models/RegistrationPage.ts b/e2e-tests/cypress/e2e/models/RegistrationPage.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/RegistrationPage.ts rename to e2e-tests/cypress/e2e/models/RegistrationPage.ts diff --git a/e2e-tests/cypress/cypress/e2e/models/ResetPasswordPage.ts b/e2e-tests/cypress/e2e/models/ResetPasswordPage.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/ResetPasswordPage.ts rename to e2e-tests/cypress/e2e/models/ResetPasswordPage.ts diff --git a/e2e-tests/cypress/cypress/e2e/models/SideNavMenu.ts b/e2e-tests/cypress/e2e/models/SideNavMenu.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/SideNavMenu.ts rename to e2e-tests/cypress/e2e/models/SideNavMenu.ts diff --git a/e2e-tests/cypress/cypress/e2e/models/Toasts.ts b/e2e-tests/cypress/e2e/models/Toasts.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/Toasts.ts rename to e2e-tests/cypress/e2e/models/Toasts.ts diff --git a/e2e-tests/cypress/cypress/e2e/models/UserEMailSite.ts b/e2e-tests/cypress/e2e/models/UserEMailSite.ts similarity index 100% rename from e2e-tests/cypress/cypress/e2e/models/UserEMailSite.ts rename to e2e-tests/cypress/e2e/models/UserEMailSite.ts diff --git a/e2e-tests/cypress/cypress/fixtures/users.json b/e2e-tests/cypress/fixtures/users.json similarity index 100% rename from e2e-tests/cypress/cypress/fixtures/users.json rename to e2e-tests/cypress/fixtures/users.json diff --git a/e2e-tests/cypress/cypress/support/e2e.ts b/e2e-tests/cypress/support/e2e.ts similarity index 100% rename from e2e-tests/cypress/cypress/support/e2e.ts rename to e2e-tests/cypress/support/e2e.ts diff --git a/e2e-tests/cypress/cypress/support/index.ts b/e2e-tests/cypress/support/index.ts similarity index 100% rename from e2e-tests/cypress/cypress/support/index.ts rename to e2e-tests/cypress/support/index.ts diff --git a/e2e-tests/cypress/cypress/support/step_definitions/common_steps.ts b/e2e-tests/cypress/support/step_definitions/common_steps.ts similarity index 100% rename from e2e-tests/cypress/cypress/support/step_definitions/common_steps.ts rename to e2e-tests/cypress/support/step_definitions/common_steps.ts diff --git a/e2e-tests/cypress/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts similarity index 100% rename from e2e-tests/cypress/cypress/support/step_definitions/email_steps.ts rename to e2e-tests/cypress/support/step_definitions/email_steps.ts diff --git a/e2e-tests/cypress/cypress/support/step_definitions/user_authentication_steps.ts b/e2e-tests/cypress/support/step_definitions/user_authentication_steps.ts similarity index 100% rename from e2e-tests/cypress/cypress/support/step_definitions/user_authentication_steps.ts rename to e2e-tests/cypress/support/step_definitions/user_authentication_steps.ts diff --git a/e2e-tests/cypress/cypress/support/step_definitions/user_profile_change_password_steps.ts b/e2e-tests/cypress/support/step_definitions/user_profile_change_password_steps.ts similarity index 100% rename from e2e-tests/cypress/cypress/support/step_definitions/user_profile_change_password_steps.ts rename to e2e-tests/cypress/support/step_definitions/user_profile_change_password_steps.ts diff --git a/e2e-tests/cypress/cypress/support/step_definitions/user_registration_steps.ts b/e2e-tests/cypress/support/step_definitions/user_registration_steps.ts similarity index 100% rename from e2e-tests/cypress/cypress/support/step_definitions/user_registration_steps.ts rename to e2e-tests/cypress/support/step_definitions/user_registration_steps.ts diff --git a/e2e-tests/cypress/package.json b/e2e-tests/package.json similarity index 100% rename from e2e-tests/cypress/package.json rename to e2e-tests/package.json diff --git a/e2e-tests/cypress/tsconfig.json b/e2e-tests/tsconfig.json similarity index 100% rename from e2e-tests/cypress/tsconfig.json rename to e2e-tests/tsconfig.json diff --git a/e2e-tests/cypress/yarn.lock b/e2e-tests/yarn.lock similarity index 100% rename from e2e-tests/cypress/yarn.lock rename to e2e-tests/yarn.lock From b024b15ff23d795687f8bc3b42513252443eb2a1 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 13 Feb 2023 12:09:37 +0100 Subject: [PATCH 9/9] Remove the step in cypress on the docker call. --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0d627c2be..aad723ca2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -647,7 +647,7 @@ jobs: - name: End-to-end tests | run tests id: e2e-tests run: | - cd e2e-tests/cypress/ + cd e2e-tests/ yarn yarn run cypress run --spec cypress/e2e/User.Authentication.feature,cypress/e2e/User.Authentication.ResetPassword.feature - name: End-to-end tests | if tests failed, upload screenshots @@ -655,4 +655,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: cypress-screenshots - path: /home/runner/work/gradido/gradido/e2e-tests/tests/screenshots/ + path: /home/runner/work/gradido/gradido/e2e-tests/cypress/screenshots/