From 13e025bb64b2c6f535d8cd559e22983c09278e8d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 13:27:19 +0000 Subject: [PATCH 01/12] Initial plan From 83ffd68fb771dc303a2d14f3a7390711df1b84a3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 13:32:28 +0000 Subject: [PATCH 02/12] Fix MariaDB container name mismatch in GitHub Actions workflows Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- .github/workflows/dotnet-core-master.yml | 2 +- .github/workflows/dotnet-core-pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet-core-master.yml b/.github/workflows/dotnet-core-master.yml index 11badeba02..9ee92fe848 100644 --- a/.github/workflows/dotnet-core-master.yml +++ b/.github/workflows/dotnet-core-master.yml @@ -54,7 +54,7 @@ jobs: - name: Wait for MariaDB run: | for i in {1..30}; do - if docker exec mariadb-test mysql -uroot -psecretpassword -e "SELECT 1" &>/dev/null; then + if docker exec mariadbtest mysql -uroot -psecretpassword -e "SELECT 1" &>/dev/null; then echo "MariaDB is ready!" break fi diff --git a/.github/workflows/dotnet-core-pr.yml b/.github/workflows/dotnet-core-pr.yml index ac988de6f6..5b7bdcf562 100644 --- a/.github/workflows/dotnet-core-pr.yml +++ b/.github/workflows/dotnet-core-pr.yml @@ -55,7 +55,7 @@ jobs: - name: Wait for MariaDB run: | for i in {1..30}; do - if docker exec mariadb-test mysql -uroot -psecretpassword -e "SELECT 1" &>/dev/null; then + if docker exec mariadbtest mysql -uroot -psecretpassword -e "SELECT 1" &>/dev/null; then echo "MariaDB is ready!" break fi From 0c19ce758da238786d9c988bd751d6a58571982b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 14:11:10 +0000 Subject: [PATCH 03/12] Add application readiness check before WDIO tests Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- .github/workflows/dotnet-core-master.yml | 16 ++++++++++++++++ .github/workflows/dotnet-core-pr.yml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/.github/workflows/dotnet-core-master.yml b/.github/workflows/dotnet-core-master.yml index 9ee92fe848..8a123243eb 100644 --- a/.github/workflows/dotnet-core-master.yml +++ b/.github/workflows/dotnet-core-master.yml @@ -95,6 +95,22 @@ jobs: config-file: cypress.config.ts working-directory: eform-client command-prefix: "--" + - name: Wait for application to be ready + run: | + echo "Waiting for application at http://localhost:4200 to be ready..." + for i in {1..60}; do + if curl -f -s http://localhost:4200 >/dev/null; then + echo "Application is ready!" + break + fi + echo "Waiting for application... ($i/60)" + sleep 2 + done + # Final check + if ! curl -f -s http://localhost:4200 >/dev/null; then + echo "Application failed to start within 120 seconds" + exit 1 + fi - name: testheadless2${{matrix.test}} run: cd eform-client && npm run testheadless2${{matrix.test}} - name: Stop the newly build Docker container diff --git a/.github/workflows/dotnet-core-pr.yml b/.github/workflows/dotnet-core-pr.yml index 5b7bdcf562..d96de1282b 100644 --- a/.github/workflows/dotnet-core-pr.yml +++ b/.github/workflows/dotnet-core-pr.yml @@ -96,6 +96,22 @@ jobs: config-file: cypress.config.ts working-directory: eform-client command-prefix: "--" + - name: Wait for application to be ready + run: | + echo "Waiting for application at http://localhost:4200 to be ready..." + for i in {1..60}; do + if curl -f -s http://localhost:4200 >/dev/null; then + echo "Application is ready!" + break + fi + echo "Waiting for application... ($i/60)" + sleep 2 + done + # Final check + if ! curl -f -s http://localhost:4200 >/dev/null; then + echo "Application failed to start within 120 seconds" + exit 1 + fi - name: testheadless2${{matrix.test}} run: cd eform-client && npm run testheadless2${{matrix.test}} - name: Stop the newly build Docker container From 2457c1a137e46b943b3ec5fd259205c628bd6bc9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 14:23:46 +0000 Subject: [PATCH 04/12] Fix mocha timeout in wdio-headless-step2e.conf.ts from 90s to 240s Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- eform-client/wdio-headless-step2e.conf.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eform-client/wdio-headless-step2e.conf.ts b/eform-client/wdio-headless-step2e.conf.ts index 8e087e1676..da6f377880 100644 --- a/eform-client/wdio-headless-step2e.conf.ts +++ b/eform-client/wdio-headless-step2e.conf.ts @@ -176,7 +176,7 @@ export const config: WebdriverIO.Config = { ui: 'bdd', //require: 'ts-node/register', //compilers: ['tsconfig-paths/register'], - timeout: 90000 + timeout: 240000 }, // // ===== From 0cf4e8219982b97c55b8f519191726216cd69834 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 16:07:40 +0000 Subject: [PATCH 05/12] Force sequential execution in step2e to avoid race conditions with shared settings Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- eform-client/wdio-headless-step2e.conf.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eform-client/wdio-headless-step2e.conf.ts b/eform-client/wdio-headless-step2e.conf.ts index da6f377880..afc2c813e2 100644 --- a/eform-client/wdio-headless-step2e.conf.ts +++ b/eform-client/wdio-headless-step2e.conf.ts @@ -73,7 +73,9 @@ export const config: WebdriverIO.Config = { // maxInstances can get overwritten per capability. So if you have an in-house Selenium // grid with only 5 firefox instances available you can make sure that not more than // 5 instances get started at a time. - maxInstances: 5, + // NOTE: Set to 1 for step2e because these tests modify shared application settings + // and must run sequentially to avoid race conditions + maxInstances: 1, // browserName: 'chrome', 'goog:chromeOptions': { From eeb05efc9394b7b15473b013ef845f58b96ff127 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 16:52:43 +0000 Subject: [PATCH 06/12] Fix duplicate describe block name in application-settings.login-page.spec.ts Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- .../application-settings.login-page.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eform-client/e2e/Tests/application-settings/application-settings.login-page.spec.ts b/eform-client/e2e/Tests/application-settings/application-settings.login-page.spec.ts index 3272cca8a6..67bb8a7290 100644 --- a/eform-client/e2e/Tests/application-settings/application-settings.login-page.spec.ts +++ b/eform-client/e2e/Tests/application-settings/application-settings.login-page.spec.ts @@ -4,7 +4,7 @@ import applicationSettingsPage from '../../Page objects/ApplicationSettings.page import ApplicationSettingsConstants from '../../Constants/ApplicationSettingsConstants'; import { expect } from 'chai'; -describe('Application settings page - site header section', function () { +describe('Application settings page - login page section', function () { before(async () => { await loginPage.open('/auth'); await loginPage.login(); From bdfc4689e22fd2e3544bf76e096480138ae66093 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 17:48:34 +0000 Subject: [PATCH 07/12] Add comprehensive debugging to diagnose step2e login failures Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- eform-client/e2e/Page objects/Login.page.ts | 30 +++++++++ eform-client/wdio-headless-step2e.conf.ts | 70 +++++++++++++++++++-- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/eform-client/e2e/Page objects/Login.page.ts b/eform-client/e2e/Page objects/Login.page.ts index 7987df01bd..a7a37b5caa 100644 --- a/eform-client/e2e/Page objects/Login.page.ts +++ b/eform-client/e2e/Page objects/Login.page.ts @@ -41,17 +41,47 @@ class LoginPage extends Page { } public async login(): Promise { + console.log('[LOGIN DEBUG] Starting login process...'); + console.log('[LOGIN DEBUG] Current URL:', await browser.getUrl()); + await (await this.loginBtn()).waitForDisplayed({ timeout: 60000 }); + console.log('[LOGIN DEBUG] Login button is displayed'); + // await (await this.usernameInput()).waitForDisplayed({ timeout: 60000 }); await (await this.usernameInput()).setValue(LoginConstants.username); + console.log('[LOGIN DEBUG] Username set'); + await (await this.passwordInput()).setValue(LoginConstants.password); + console.log('[LOGIN DEBUG] Password set'); + await (await this.loginBtn()).click(); + console.log('[LOGIN DEBUG] Login button clicked'); + console.log('[LOGIN DEBUG] URL after click:', await browser.getUrl()); + // Add pause after login click to allow application to start loading on slow environments await browser.pause(2000); + console.log('[LOGIN DEBUG] Waited 2 seconds, now looking for newEFormBtn...'); + console.log('[LOGIN DEBUG] Current URL:', await browser.getUrl()); + + // Take screenshot before waiting for newEFormBtn to help debug + try { + const screenshotPath = './errorShots/before-newEFormBtn-wait.png'; + await browser.saveScreenshot(screenshotPath); + console.log('[LOGIN DEBUG] Screenshot saved to:', screenshotPath); + } catch (e) { + console.log('[LOGIN DEBUG] Could not save screenshot:', e.message); + } + const newEFormBtn = await $('#newEFormBtn'); // Increased timeout for slow environments - application may take longer to initialize + console.log('[LOGIN DEBUG] Waiting for newEFormBtn to be displayed (120s timeout)...'); await newEFormBtn.waitForDisplayed({timeout: 120000}); + console.log('[LOGIN DEBUG] newEFormBtn is displayed'); + + console.log('[LOGIN DEBUG] Waiting for newEFormBtn to be clickable (120s timeout)...'); await newEFormBtn.waitForClickable({timeout: 120000}); + console.log('[LOGIN DEBUG] newEFormBtn is clickable - login complete!'); + console.log('[LOGIN DEBUG] Final URL:', await browser.getUrl()); } public async loginWithNewPassword(): Promise { await (await this.usernameInput()).waitForDisplayed({ timeout: 60000 }); diff --git a/eform-client/wdio-headless-step2e.conf.ts b/eform-client/wdio-headless-step2e.conf.ts index afc2c813e2..a8752c50f8 100644 --- a/eform-client/wdio-headless-step2e.conf.ts +++ b/eform-client/wdio-headless-step2e.conf.ts @@ -232,20 +232,55 @@ export const config: WebdriverIO.Config = { * Function to be executed before a test (in Mocha/Jasmine) or a step (in Cucumber) starts. * @param {Object} test test details */ - // beforeTest: function (test) { - // }, + beforeTest: function (test) { + console.log('[DEBUG] Starting test:', test.title); + console.log('[DEBUG] Test file:', test.file); + try { + const url = browser.getUrl(); + console.log('[DEBUG] Initial URL:', url); + } catch (e) { + console.log('[DEBUG] Could not retrieve initial URL:', e.message); + } + }, /** * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling * beforeEach in Mocha) */ - // beforeHook: function () { - // }, + beforeHook: function (test, context, hookName) { + console.log('[DEBUG] Before hook:', hookName); + if (hookName && hookName.includes('before all')) { + console.log('[DEBUG] This is the "before all" hook - where login happens'); + } + }, /** * Hook that gets executed _after_ a hook within the suite ends (e.g. runs after calling * afterEach in Mocha) */ - // afterHook: function () { - // }, + afterHook: function (test, context, { error, result, duration, passed }, hookName) { + if (error) { + console.log('[DEBUG] Hook failed:', hookName); + console.log('[DEBUG] Hook error:', error.message); + console.log('[DEBUG] Hook duration:', duration); + + // Take screenshot on hook failure + try { + const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); + const screenshotPath = `./errorShots/hook-failure-${timestamp}.png`; + browser.saveScreenshot(screenshotPath); + console.log('[DEBUG] Hook failure screenshot saved to:', screenshotPath); + } catch (e) { + console.log('[DEBUG] Could not save hook failure screenshot:', e.message); + } + + // Try to get current URL + try { + const url = browser.getUrl(); + console.log('[DEBUG] URL at hook failure:', url); + } catch (e) { + console.log('[DEBUG] Could not retrieve URL:', e.message); + } + } + }, /** * Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) ends. * @param {Object} test test details @@ -258,6 +293,29 @@ export const config: WebdriverIO.Config = { return; } + console.log('[DEBUG] Test failed:', test.title); + console.log('[DEBUG] Error:', error ? error.message : 'No error message'); + console.log('[DEBUG] Duration:', duration); + + // Capture browser console logs + try { + const logs = browser.getLogs('browser'); + console.log('[DEBUG] Browser console logs:'); + logs.forEach(log => { + console.log(` [${log.level}] ${log.message}`); + }); + } catch (e) { + console.log('[DEBUG] Could not retrieve browser logs:', e.message); + } + + // Capture current URL + try { + const url = browser.getUrl(); + console.log('[DEBUG] Current URL:', url); + } catch (e) { + console.log('[DEBUG] Could not retrieve URL:', e.message); + } + /* * get the current date and clean it * const date = (new Date()).toString().replace(/\s/g, '-').replace(/-\(\w+\)/, ''); From f370e48d57e66a668250a882176bb27287c36f5d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 17:50:32 +0000 Subject: [PATCH 08/12] Fix async/await issues in wdio hooks for proper debugging Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- eform-client/wdio-headless-step2e.conf.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/eform-client/wdio-headless-step2e.conf.ts b/eform-client/wdio-headless-step2e.conf.ts index a8752c50f8..c70dc7895a 100644 --- a/eform-client/wdio-headless-step2e.conf.ts +++ b/eform-client/wdio-headless-step2e.conf.ts @@ -232,11 +232,11 @@ export const config: WebdriverIO.Config = { * Function to be executed before a test (in Mocha/Jasmine) or a step (in Cucumber) starts. * @param {Object} test test details */ - beforeTest: function (test) { + beforeTest: async function (test) { console.log('[DEBUG] Starting test:', test.title); console.log('[DEBUG] Test file:', test.file); try { - const url = browser.getUrl(); + const url = await browser.getUrl(); console.log('[DEBUG] Initial URL:', url); } catch (e) { console.log('[DEBUG] Could not retrieve initial URL:', e.message); @@ -256,7 +256,7 @@ export const config: WebdriverIO.Config = { * Hook that gets executed _after_ a hook within the suite ends (e.g. runs after calling * afterEach in Mocha) */ - afterHook: function (test, context, { error, result, duration, passed }, hookName) { + afterHook: async function (test, context, { error, result, duration, passed }, hookName) { if (error) { console.log('[DEBUG] Hook failed:', hookName); console.log('[DEBUG] Hook error:', error.message); @@ -266,7 +266,7 @@ export const config: WebdriverIO.Config = { try { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const screenshotPath = `./errorShots/hook-failure-${timestamp}.png`; - browser.saveScreenshot(screenshotPath); + await browser.saveScreenshot(screenshotPath); console.log('[DEBUG] Hook failure screenshot saved to:', screenshotPath); } catch (e) { console.log('[DEBUG] Could not save hook failure screenshot:', e.message); @@ -274,7 +274,7 @@ export const config: WebdriverIO.Config = { // Try to get current URL try { - const url = browser.getUrl(); + const url = await browser.getUrl(); console.log('[DEBUG] URL at hook failure:', url); } catch (e) { console.log('[DEBUG] Could not retrieve URL:', e.message); @@ -285,7 +285,7 @@ export const config: WebdriverIO.Config = { * Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) ends. * @param {Object} test test details */ - afterTest(test, context, { error, result, duration, passed, retries }) { + afterTest: async function (test, context, { error, result, duration, passed, retries }) { const path = require('path'); // if test passed, ignore, else take and save screenshot. @@ -299,7 +299,7 @@ export const config: WebdriverIO.Config = { // Capture browser console logs try { - const logs = browser.getLogs('browser'); + const logs = await browser.getLogs('browser'); console.log('[DEBUG] Browser console logs:'); logs.forEach(log => { console.log(` [${log.level}] ${log.message}`); @@ -310,7 +310,7 @@ export const config: WebdriverIO.Config = { // Capture current URL try { - const url = browser.getUrl(); + const url = await browser.getUrl(); console.log('[DEBUG] Current URL:', url); } catch (e) { console.log('[DEBUG] Could not retrieve URL:', e.message); @@ -339,7 +339,7 @@ export const config: WebdriverIO.Config = { const filePath = path.resolve(this.screenshotPath, `${filename}.png`); console.log('Saving screenshot to:', filePath); - browser.saveScreenshot(filePath); + await browser.saveScreenshot(filePath); console.log('Saved screenshot to:', filePath); }, /** From a7718c7486019bc98fbff8583308cf2cea6bdc6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 18:22:49 +0000 Subject: [PATCH 09/12] Fix Cypress password test to ensure password is always reverted Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- ...ssword-settings.change-password.spec.cy.ts | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/eform-client/cypress/e2e/e/password-settings.change-password.spec.cy.ts b/eform-client/cypress/e2e/e/password-settings.change-password.spec.cy.ts index 233e8d632a..0daa100b14 100644 --- a/eform-client/cypress/e2e/e/password-settings.change-password.spec.cy.ts +++ b/eform-client/cypress/e2e/e/password-settings.change-password.spec.cy.ts @@ -5,47 +5,43 @@ describe('Password settings - Change password', function () { before(() => { cy.visit('http://localhost:4200'); loginPage.login(); - passwordSettingsPage.Navbar.goToPasswordSettings(); - cy.get('#oldPassword', { timeout: 10000 }).should('be.visible'); }); - it('should change password to new password', () => { + it('should change password and revert it back', () => { + // Navigate to password settings + passwordSettingsPage.Navbar.goToPasswordSettings(); + cy.get('#oldPassword', { timeout: 10000 }).should('be.visible'); + // Change password to new password passwordSettingsPage.setNewPassword(); // Logout passwordSettingsPage.Navbar.logout(); - cy.get('#loginBtn').should('be.visible'); + cy.get('#loginBtn', { timeout: 10000 }).should('be.visible'); - // Login with new password + // Login with new password to verify change worked cy.visit('http://localhost:4200'); loginPage.loginWithNewPassword(); // Verify we're logged in by checking for the new eForm button - cy.get('#newEFormBtn').should('be.visible'); + cy.get('#newEFormBtn', { timeout: 10000 }).should('be.visible'); - // Navigate to password settings + // Navigate to password settings to revert passwordSettingsPage.Navbar.goToPasswordSettings(); - cy.get('#oldPassword').should('be.visible'); - }); - - it('should revert password back to original', () => { + cy.get('#oldPassword', { timeout: 10000 }).should('be.visible'); + // Revert password back to original passwordSettingsPage.revertToOldPassword(); // Logout passwordSettingsPage.Navbar.logout(); - cy.get('#loginBtn').should('be.visible'); + cy.get('#loginBtn', { timeout: 10000 }).should('be.visible'); - // Login with original password + // Login with original password to verify revert worked cy.visit('http://localhost:4200'); loginPage.login(); // Verify we're logged in - cy.get('#newEFormBtn').should('be.visible'); - - // Navigate to password settings to verify we can access it - passwordSettingsPage.Navbar.goToPasswordSettings(); - cy.get('#oldPassword').should('be.visible'); + cy.get('#newEFormBtn', { timeout: 10000 }).should('be.visible'); }); }); From 9c5c831066f0b83ebf9d1ec2dfcbc3a4ca6a9a6d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 04:49:24 +0000 Subject: [PATCH 10/12] Remove spinner waits from Cypress password test and make WDIO test atomic Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- .../cypress/e2e/PasswordSettings.page.ts | 4 --- .../password-settings.change-password.spec.ts | 29 ++++++++++++------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/eform-client/cypress/e2e/PasswordSettings.page.ts b/eform-client/cypress/e2e/PasswordSettings.page.ts index 27bf5a9260..33e65dfc99 100644 --- a/eform-client/cypress/e2e/PasswordSettings.page.ts +++ b/eform-client/cypress/e2e/PasswordSettings.page.ts @@ -28,8 +28,6 @@ class PasswordSettingsPage extends PageWithNavbarPage { cy.intercept('PUT', '**/api/auth/change-password').as('changePassword'); this.saveBtn().should('be.visible').should('be.enabled').click(); cy.wait('@changePassword', { timeout: 10000 }); - cy.get('#spinner-animation').should('not.exist'); - cy.wait(500); } revertToOldPassword(oldPassword = loginConstants.newPassword, newPassword = loginConstants.password) { @@ -42,8 +40,6 @@ class PasswordSettingsPage extends PageWithNavbarPage { cy.intercept('PUT', '**/api/auth/change-password').as('changePassword'); this.saveBtn().should('be.visible').should('be.enabled').click(); cy.wait('@changePassword', { timeout: 10000 }); - cy.get('#spinner-animation').should('not.exist'); - cy.wait(500); } } diff --git a/eform-client/e2e/Tests/password-settings/password-settings.change-password.spec.ts b/eform-client/e2e/Tests/password-settings/password-settings.change-password.spec.ts index 2e079fde84..d527fbe77c 100644 --- a/eform-client/e2e/Tests/password-settings/password-settings.change-password.spec.ts +++ b/eform-client/e2e/Tests/password-settings/password-settings.change-password.spec.ts @@ -8,27 +8,36 @@ describe('Password settings', function () { before(async () => { loginPage.open('/'); loginPage.login(); - myEformsPage.Navbar.goToPasswordSettings(); }); - it('should set password to 2Times2WillDo', async () => { + it('should change password and revert it back', async () => { + // Navigate to password settings + myEformsPage.Navbar.goToPasswordSettings(); + + // Change password to new password passwordSettings.setNewPassword(); + + // Logout passwordSettings.Navbar.logout(); + + // Login with new password to verify change worked loginPage.open('/'); loginPage.loginWithNewPassword(); + + // Navigate to password settings to revert myEformsPage.Navbar.goToPasswordSettings(); - // expect(myEformsPage.Navbar.verifyHeaderMenuItem('My eForms')).equal('My eForms'); - // expect(myEformsPage.Navbar.verifyHeaderMenuItem('Device Users')).equal('Device Users'); - // expect(myEformsPage.Navbar.verifyHeaderMenuItem('Advanced')).equal('Advanced'); - }); - it('should revert to old password', async () => { + + // Revert password back to original passwordSettings.revertToOldPassword(); + + // Logout passwordSettings.Navbar.logout(); + + // Login with original password to verify revert worked loginPage.open('/'); loginPage.login(); + + // Verify we can access password settings again myEformsPage.Navbar.goToPasswordSettings(); - // expect(myEformsPage.Navbar.verifyHeaderMenuItem('Meine eForms')).equal('Meine eForms'); - // expect(myEformsPage.Navbar.verifyHeaderMenuItem('Gerätebenutzer')).equal('Gerätebenutzer'); - // expect(myEformsPage.Navbar.verifyHeaderMenuItem('Fortgeschritten')).equal('Fortgeschritten'); }); }); From b08d5566321f3f42c1f7a6e9e32052730597d4be Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 04:52:02 +0000 Subject: [PATCH 11/12] Fix Cypress password test to use correct HTTP method (POST) and endpoint Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- eform-client/cypress/e2e/PasswordSettings.page.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eform-client/cypress/e2e/PasswordSettings.page.ts b/eform-client/cypress/e2e/PasswordSettings.page.ts index 33e65dfc99..b6c86bd49d 100644 --- a/eform-client/cypress/e2e/PasswordSettings.page.ts +++ b/eform-client/cypress/e2e/PasswordSettings.page.ts @@ -25,7 +25,7 @@ class PasswordSettingsPage extends PageWithNavbarPage { cy.wait(500); this.newPasswordConfirmationField().should('be.visible').clear().type(newPassword); cy.wait(500); - cy.intercept('PUT', '**/api/auth/change-password').as('changePassword'); + cy.intercept('POST', '**/api/account/change-password').as('changePassword'); this.saveBtn().should('be.visible').should('be.enabled').click(); cy.wait('@changePassword', { timeout: 10000 }); } @@ -37,7 +37,7 @@ class PasswordSettingsPage extends PageWithNavbarPage { cy.wait(500); this.newPasswordConfirmationField().should('be.visible').clear().type(newPassword); cy.wait(500); - cy.intercept('PUT', '**/api/auth/change-password').as('changePassword'); + cy.intercept('POST', '**/api/account/change-password').as('changePassword'); this.saveBtn().should('be.visible').should('be.enabled').click(); cy.wait('@changePassword', { timeout: 10000 }); } From f4e687c5b3a557d84e795d3ea3ffaec2cd754bb1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Dec 2025 05:29:54 +0000 Subject: [PATCH 12/12] Add login page wait to logout and intercept to loginWithNewPassword Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- eform-client/cypress/e2e/Login.page.ts | 2 ++ eform-client/cypress/e2e/Navbar.page.ts | 3 ++- .../e2e/e/password-settings.change-password.spec.cy.ts | 6 ++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/eform-client/cypress/e2e/Login.page.ts b/eform-client/cypress/e2e/Login.page.ts index 599cc45fdf..6a85abfbbd 100644 --- a/eform-client/cypress/e2e/Login.page.ts +++ b/eform-client/cypress/e2e/Login.page.ts @@ -39,7 +39,9 @@ class LoginPage { loginWithNewPassword() { this.getUsernameInput().type(loginConstants.username); this.getPasswordInput().type(loginConstants.newPassword); + cy.intercept('POST', '**/api/templates/index').as('login'); this.getLoginButton().click(); + cy.wait('@login', { timeout: 60000 }); cy.get('#newEFormBtn').should('be.visible'); } diff --git a/eform-client/cypress/e2e/Navbar.page.ts b/eform-client/cypress/e2e/Navbar.page.ts index 660cc795c2..6c17f3c557 100644 --- a/eform-client/cypress/e2e/Navbar.page.ts +++ b/eform-client/cypress/e2e/Navbar.page.ts @@ -91,7 +91,8 @@ export class Navbar { this.signOutDropdown().click(); cy.wait(500); this.logoutBtn().click(); - cy.wait(500); + // Wait for login page to be fully loaded + cy.get('#loginBtn', { timeout: 10000 }).should('be.visible'); } public goToProfileSettings() { diff --git a/eform-client/cypress/e2e/e/password-settings.change-password.spec.cy.ts b/eform-client/cypress/e2e/e/password-settings.change-password.spec.cy.ts index 0daa100b14..32f6b8e582 100644 --- a/eform-client/cypress/e2e/e/password-settings.change-password.spec.cy.ts +++ b/eform-client/cypress/e2e/e/password-settings.change-password.spec.cy.ts @@ -15,9 +15,8 @@ describe('Password settings - Change password', function () { // Change password to new password passwordSettingsPage.setNewPassword(); - // Logout + // Logout (waits for login page to load) passwordSettingsPage.Navbar.logout(); - cy.get('#loginBtn', { timeout: 10000 }).should('be.visible'); // Login with new password to verify change worked cy.visit('http://localhost:4200'); @@ -33,9 +32,8 @@ describe('Password settings - Change password', function () { // Revert password back to original passwordSettingsPage.revertToOldPassword(); - // Logout + // Logout (waits for login page to load) passwordSettingsPage.Navbar.logout(); - cy.get('#loginBtn', { timeout: 10000 }).should('be.visible'); // Login with original password to verify revert worked cy.visit('http://localhost:4200');