From a028a6cdceb90b91682cf6b04414ca3a6b6f4d88 Mon Sep 17 00:00:00 2001 From: JavidSumra <112365664+JavidSumra@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:17:30 +0530 Subject: [PATCH 1/4] Refactor Cypress Auth Test to POM and Improve Test Stability (#9024) Co-authored-by: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> --- cypress/e2e/auth_spec/ForgotPassword.cy.ts | 17 ----- cypress/e2e/auth_spec/auth.cy.ts | 23 ------- cypress/e2e/homepage_spec/UserLogin.cy.ts | 48 ++++++++++++++ .../redirect.cy.ts | 0 cypress/pageobject/Login/LoginPage.ts | 64 +++++++++++++++++-- src/components/Auth/Login.tsx | 11 +++- 6 files changed, 117 insertions(+), 46 deletions(-) delete mode 100644 cypress/e2e/auth_spec/ForgotPassword.cy.ts delete mode 100644 cypress/e2e/auth_spec/auth.cy.ts create mode 100644 cypress/e2e/homepage_spec/UserLogin.cy.ts rename cypress/e2e/{auth_spec => homepage_spec}/redirect.cy.ts (100%) diff --git a/cypress/e2e/auth_spec/ForgotPassword.cy.ts b/cypress/e2e/auth_spec/ForgotPassword.cy.ts deleted file mode 100644 index c1b1db7ecad..00000000000 --- a/cypress/e2e/auth_spec/ForgotPassword.cy.ts +++ /dev/null @@ -1,17 +0,0 @@ -describe("Forgot Password", () => { - beforeEach(() => { - cy.awaitUrl("/", true); - cy.get("button").contains("Forgot password?").click().wait(100); - }); - - it("Send Password Reset Link", () => { - cy.get("input[id='forgot_username']").type("dummy_user_1"); - cy.contains("Send Reset Link").click().wait(1000); - cy.contains("Password Reset Email Sent").should("exist"); - }); - - it("Go to Login page", () => { - cy.get("button").contains("Back to login").click(); - cy.url().should("contain", "/"); - }); -}); diff --git a/cypress/e2e/auth_spec/auth.cy.ts b/cypress/e2e/auth_spec/auth.cy.ts deleted file mode 100644 index b2bd7b634c0..00000000000 --- a/cypress/e2e/auth_spec/auth.cy.ts +++ /dev/null @@ -1,23 +0,0 @@ -describe("Authorisation/Authentication", () => { - beforeEach(() => { - cy.awaitUrl("/", true); - }); - - it("Try login as admin with correct password", () => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); - cy.awaitUrl("/facility"); - cy.get("#user-profile-name").click(); - cy.get("#sign-out-button").contains("Sign Out").click(); - cy.url().should("include", "/"); - }); - - it("Try login as admin with incorrect password", () => { - cy.log("Logging in the user: devdistrictadmin:Coronasafe@123"); - - cy.awaitUrl("/", true); - cy.get("input[id='username']").type("devdistrictadmin"); - cy.get("input[id='password']").type("coronasafe@123"); - cy.get("button").contains("Login").click(); - cy.contains("No active account").should("exist"); - }); -}); diff --git a/cypress/e2e/homepage_spec/UserLogin.cy.ts b/cypress/e2e/homepage_spec/UserLogin.cy.ts new file mode 100644 index 00000000000..ab00bd80ff1 --- /dev/null +++ b/cypress/e2e/homepage_spec/UserLogin.cy.ts @@ -0,0 +1,48 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); +const userName = "dummy_user_1"; +const forgotPasswordHeading = "Forgot password?"; + +describe("User login workflow with correct and incorrect passwords", () => { + beforeEach(() => { + cy.awaitUrl("/", true); + }); + + it("Log in as admin with correct password", () => { + loginPage.loginManuallyAsDistrictAdmin(); + loginPage.interceptFacilityReq(); + loginPage.verifyFacilityReq(); + loginPage.ensureLoggedIn(); + loginPage.clickSignOutBtn(); + loginPage.verifyLoginPageUrl(); + }); + + it("Display an error when logging in as admin with incorrect password", () => { + loginPage.interceptLoginReq(); + loginPage.loginManuallyAsDistrictAdmin(false); + loginPage.verifyLoginReq(); + cy.verifyNotification("No active account found with the given credentials"); + cy.closeNotification(); + }); +}); + +describe("Reset user's password using email", () => { + beforeEach(() => { + cy.awaitUrl("/", true); + }); + + it("Send a password reset link and navigate back to the login page", () => { + loginPage.clickForgotPasswordButton(forgotPasswordHeading); + loginPage.verifyForgotPasswordHeading([forgotPasswordHeading]); + loginPage.fillUserNameInForgotPasswordForm(userName); + loginPage.interceptResetLinkReq(); + loginPage.clickSendResetLinkBtn(); + loginPage.verifyResetLinkReq(); + cy.verifyNotification("Password Reset Email Sent"); + cy.closeNotification(); + loginPage.clickBackButton(); + loginPage.verifyLoginPageUrl(); + loginPage.verifyLoginButtonPresence(); + }); +}); diff --git a/cypress/e2e/auth_spec/redirect.cy.ts b/cypress/e2e/homepage_spec/redirect.cy.ts similarity index 100% rename from cypress/e2e/auth_spec/redirect.cy.ts rename to cypress/e2e/homepage_spec/redirect.cy.ts diff --git a/cypress/pageobject/Login/LoginPage.ts b/cypress/pageobject/Login/LoginPage.ts index 38b8aeee2af..07eb4486d17 100644 --- a/cypress/pageobject/Login/LoginPage.ts +++ b/cypress/pageobject/Login/LoginPage.ts @@ -13,16 +13,20 @@ class LoginPage { cy.loginByApi("staffdev", "Coronasafe@123"); } - loginManuallyAsDistrictAdmin(): void { + loginManuallyAsDistrictAdmin(isCorrectCredentials: boolean = true): void { cy.get("input[id='username']").type("devdistrictadmin"); - cy.get("input[id='password']").type("Coronasafe@123"); - cy.get("button").contains("Login").click(); + if (isCorrectCredentials) { + cy.get("input[id='password']").type("Coronasafe@123"); + } else { + cy.get("input[id='password']").type("Corona"); + } + cy.submitButton("Login"); } loginManuallyAsNurse(): void { cy.get("input[id='username']").click().type("dummynurse1"); cy.get("input[id='password']").click().type("Coronasafe@123"); - cy.get("button").contains("Login").click(); + cy.submitButton("Login"); } login(username: string, password: string): void { @@ -38,6 +42,58 @@ class LoginPage { clickSignOutBtn(): void { cy.verifyAndClickElement("#sign-out-button", "Sign Out"); } + + fillUserNameInForgotPasswordForm(userName: string): void { + cy.get("#forgot_username").type(userName); + } + + clickSendResetLinkBtn(): void { + cy.verifyAndClickElement("#send-reset-link-btn", "Send Reset Link"); + } + + verifyLoginPageUrl(): void { + cy.url().should("include", "/"); + } + + clickBackButton(): void { + cy.verifyAndClickElement("#back-to-login-btn", "Back to login"); + } + + clickForgotPasswordButton(text: string): void { + cy.verifyAndClickElement("#forgot-pass-btn", text); + } + + interceptFacilityReq(): void { + cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); + } + + verifyFacilityReq(): void { + cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); + } + + interceptLoginReq(): void { + cy.intercept("POST", "**/api/v1/auth/login").as("userLogin"); + } + + verifyLoginReq(): void { + cy.wait("@userLogin").its("response.statusCode").should("eq", 401); + } + + interceptResetLinkReq(): void { + cy.intercept("POST", "**/api/v1/password_reset").as("resetLink"); + } + + verifyResetLinkReq(): void { + cy.wait("@resetLink").its("response.statusCode").should("eq", 200); + } + + verifyLoginButtonPresence(): void { + cy.verifyContentPresence("#login-button", ["Login"]); + } + + verifyForgotPasswordHeading(text: string[]): void { + cy.verifyContentPresence("#forgot-password-heading", text); + } } export default LoginPage; diff --git a/src/components/Auth/Login.tsx b/src/components/Auth/Login.tsx index bcf0d4e3415..aab5f8df179 100644 --- a/src/components/Auth/Login.tsx +++ b/src/components/Auth/Login.tsx @@ -335,6 +335,7 @@ const Login = (props: { forgot?: boolean }) => { setForgotPassword(true); }} type="button" + id="forgot-pass-btn" className="text-sm text-primary-400 hover:text-primary-500" > {t("forget_password")} @@ -347,6 +348,7 @@ const Login = (props: { forgot?: boolean }) => { ) : ( -