Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cypress Test Suite for Facility Notice Board Functionality Verification #9045

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
66d6ef4
Add Cypress Test Suit to Verify Notify Facility
JavidSumra Nov 7, 2024
1566910
fix addded id in SidebarItemProps type
JavidSumra Nov 7, 2024
dd38cef
fix failing test case
JavidSumra Nov 7, 2024
76dac1e
tying fix in notification test suit
JavidSumra Nov 8, 2024
db8c5ec
test fix for notification test suit
JavidSumra Nov 8, 2024
cbe768d
test fix for notification test suit
JavidSumra Nov 8, 2024
9a1ad6c
Merge branch 'develop' into issues/9041/test-verify-notice-board
JavidSumra Nov 8, 2024
d3d2034
Merge branch 'develop' of github.com:JavidSumra/care_fe into issues/9…
JavidSumra Nov 8, 2024
e6970b7
test fix for Notification test suit
JavidSumra Nov 8, 2024
73d44a1
Merge branch 'issues/9041/test-verify-notice-board' of github.com:Jav…
JavidSumra Nov 8, 2024
b800349
fix Notification Test Suit
JavidSumra Nov 8, 2024
c2069bf
Merge branch 'develop' of github.com:JavidSumra/care_fe into issues/9…
JavidSumra Nov 8, 2024
28d43b0
fix Notification test by verifying url
JavidSumra Nov 8, 2024
87196e3
fix Notification test by verifying url
JavidSumra Nov 8, 2024
1d187b2
trying test fix for Notification test Suit
JavidSumra Nov 8, 2024
b7bed31
trying test fix for Notification test Suit
JavidSumra Nov 8, 2024
4c84e13
Test fix for Notification Board test Suit
JavidSumra Nov 9, 2024
ec37084
fix adding cy function to check visiblity of button
JavidSumra Nov 9, 2024
f196fbe
merge conflict fixed
JavidSumra Nov 9, 2024
958f148
Remove unused functions
JavidSumra Nov 9, 2024
f030749
debug notify button
nihal467 Nov 9, 2024
0fb706c
handle the cache and element focus
nihal467 Nov 9, 2024
7fa0842
fixed the cache
nihal467 Nov 9, 2024
e076c3e
reorder the process to adjust with message delay
nihal467 Nov 9, 2024
461dc91
implement manual reload
nihal467 Nov 10, 2024
9f80448
Merge branch 'develop' into issues/9041/test-verify-notice-board
JavidSumra Nov 10, 2024
07b9d8b
Merge branch 'develop' of github.com:JavidSumra/care_fe into issues/9…
JavidSumra Nov 10, 2024
0690862
Add Changes Made by Nihal
JavidSumra Nov 10, 2024
c306fce
fix merge conflicts
JavidSumra Nov 10, 2024
93924c6
Remove Unused Functions
JavidSumra Nov 10, 2024
edc48d2
Add Network Call Intercept to fix Test Failure Issue
JavidSumra Nov 10, 2024
1ff02f8
added a hard wait to handle celery delay
nihal467 Nov 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 44 additions & 8 deletions cypress/e2e/facility_spec/FacilityHomepage.cy.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
// FacilityCreation

import LoginPage from "../../pageobject/Login/LoginPage";
import { AssetPagination } from "../../pageobject/Asset/AssetPagination";
import FacilityPage from "../../pageobject/Facility/FacilityCreation";
import FacilityHome from "../../pageobject/Facility/FacilityHome";
import { FacilityNotify } from "../../pageobject/Facility/FacilityNotify";
import LoginPage from "../../pageobject/Login/LoginPage";
import ManageUserPage from "../../pageobject/Users/ManageUserPage";
import FacilityPage from "../../pageobject/Facility/FacilityCreation";
import { UserPage } from "../../pageobject/Users/UserSearch";
import { AssetPagination } from "../../pageobject/Asset/AssetPagination";

describe("Facility Homepage Function", () => {
const loginPage = new LoginPage();
const facilityHome = new FacilityHome();
const facilityNotify = new FacilityNotify();
const facilityPage = new FacilityPage();
const manageUserPage = new ManageUserPage();
const userPage = new UserPage();
Expand All @@ -23,7 +24,9 @@ describe("Facility Homepage Function", () => {
const district = "Ernakulam";
const localBody = "Aikaranad";
const facilityType = "Private Hospital";

const notificationErrorMsg = "Message cannot be empty";
const noitificationMessage =
"Reminder: The monthly report submission deadline is on 15th Nov. Ensure all entries are updated.";
JavidSumra marked this conversation as resolved.
Show resolved Hide resolved
before(() => {
loginPage.loginAsDistrictAdmin();
cy.saveLocalStorage();
Expand All @@ -42,9 +45,6 @@ describe("Facility Homepage Function", () => {
facilityHome.clickViewCnsButton();
facilityHome.verifyCnsUrl();
facilityHome.navigateBack();
// view notify button
facilityHome.clickFacilityNotifyButton();
facilityHome.verifyAndCloseNotifyModal();
// view facility button
facilityHome.clickViewFacilityDetails();
facilityPage.getFacilityName().should("be.visible");
Expand Down Expand Up @@ -135,6 +135,42 @@ describe("Facility Homepage Function", () => {
facilityHome.verifyLiveMonitorUrl();
});

it("Verify Notice Board Functionality", () => {
// search facility and verify it's loaded or not
facilityNotify.interceptFacilitySearchReq();
manageUserPage.typeFacilitySearch(facilityName);
facilityNotify.verifyFacilitySearchReq();
// verify facility name and notify button and click it
manageUserPage.assertFacilityInCard(facilityName);
facilityHome.clickFacilityNotifyButton();
// check visiblity of pop-up and frontend error on empty message
cy.verifyContentPresence("#notify-facility-name", [facilityName]);
cy.submitButton("Notify");
cy.verifyContentPresence(".error-text", [notificationErrorMsg]);
// close pop-up and verify
facilityHome.verifyAndCloseNotifyModal();
// send notification
facilityHome.clickFacilityNotifyButton();
facilityNotify.fillNotifyText(noitificationMessage);
facilityNotify.interceptPostNotificationReq();
cy.submitButton("Notify");
cy.verifyNotification("Facility Notified");
facilityNotify.verifyPostNotificationReq();
// signout as district admin and login as a Nurse
loginPage.ensureLoggedIn();
loginPage.clickSignOutBtn();
loginPage.loginManuallyAsNurse();
// Visit Notification Sidebar
facilityNotify.interceptGetNotificationReq();
facilityNotify.visitNoticeBoard();
facilityNotify.verifyGetNotificationReq();
cy.verifyContentPresence("#notification-message", [noitificationMessage]);
facilityNotify.interceptGetNotificationReq();
facilityNotify.openNotificationSlide();
facilityNotify.verifyGetNotificationReq();
cy.verifyContentPresence("#notification-slide-msg", [noitificationMessage]);
});

afterEach(() => {
cy.saveLocalStorage();
});
Expand Down
40 changes: 40 additions & 0 deletions cypress/pageobject/Facility/FacilityNotify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export class FacilityNotify {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance class structure with TypeScript best practices.

Add type definitions and constants to improve maintainability and type safety.

+interface NotificationResponse {
+  message: string;
+  status: string;
+}
+
 export class FacilityNotify {
+  private readonly SELECTORS = {
+    NOTIFY_INPUT: '#NotifyModalMessageInput',
+    NOTIFICATION_SLIDE_BTN: '#notification-slide-btn',
+    CLOSE_SLIDE_BTN: '#close-slide-over',
+    NOTICE_BOARD_LINK: 'a[href="/notice_board"]'
+  } as const;
+
+  private readonly API_PATHS = {
+    FACILITY: '**/api/v1/facility',
+    NOTIFICATION: '**/api/v1/notification'
+  } as const;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export class FacilityNotify {
interface NotificationResponse {
message: string;
status: string;
}
export class FacilityNotify {
private readonly SELECTORS = {
NOTIFY_INPUT: '#NotifyModalMessageInput',
NOTIFICATION_SLIDE_BTN: '#notification-slide-btn',
CLOSE_SLIDE_BTN: '#close-slide-over',
NOTICE_BOARD_LINK: 'a[href="/notice_board"]'
} as const;
private readonly API_PATHS = {
FACILITY: '**/api/v1/facility',
NOTIFICATION: '**/api/v1/notification'
} as const;

fillNotifyText(message: string): void {
cy.get("#NotifyModalMessageInput").should("be.visible").type(message);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve UI interaction reliability.

Add proper error handling, timeouts, and assertions for UI interactions.

   fillNotifyText(message: string): void {
-    cy.get("#NotifyModalMessageInput").should("be.visible").type(message);
+    cy.get(this.SELECTORS.NOTIFY_INPUT, { timeout: 10000 })
+      .should('be.visible')
+      .should('be.enabled')
+      .clear()
+      .type(message, { delay: 100 })
+      .should('have.value', message);
   }

   openNotificationSlide(): void {
-    cy.get("#notification-slide-btn").should("be.visible").click();
+    cy.get(this.SELECTORS.NOTIFICATION_SLIDE_BTN, { timeout: 10000 })
+      .should('be.visible')
+      .should('be.enabled')
+      .click()
+      .should('not.be.enabled');
   }

   closeNotificationSlide(): void {
-    cy.get("#close-slide-over").should("be.visible").click();
+    cy.get(this.SELECTORS.CLOSE_SLIDE_BTN, { timeout: 10000 })
+      .should('be.visible')
+      .should('be.enabled')
+      .click()
+      .should('not.exist');
   }

   visitNoticeBoard(): void {
-    cy.get("a[href='/notice_board']").should("be.visible").click();
+    cy.get(this.SELECTORS.NOTICE_BOARD_LINK, { timeout: 10000 })
+      .should('be.visible')
+      .should('not.be.disabled')
+      .click();
   }

Also applies to: 6-8, 10-12, 14-16


openNotificationSlide(): void {
cy.get("#notification-slide-btn").should("be.visible").click();
}

visitNoticeBoard(): void {
cy.get("a[href='/notice_board']").should("be.visible").click();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add timeout and error handling for link interaction.

The notice board link interaction could be more robust with proper timeout and error handling.

-    cy.get("a[href='/notice_board']").should("be.visible").click();
+    cy.get('[data-testid="notice-board-link"]', { timeout: 10000 })
+      .should("be.visible")
+      .should("not.be.disabled")
+      .click();

Committable suggestion skipped: line range outside the PR's diff.


visitNotificationSideBar(): void {
cy.get("#notification-slide-btn").should("be.visible").click();
}
JavidSumra marked this conversation as resolved.
Show resolved Hide resolved

interceptFacilitySearchReq(): void {
cy.intercept("GET", "**/api/v1/facility/**").as("searchFacility");
}
verifyFacilitySearchReq(): void {
cy.wait("@searchFacility").its("response.statusCode").should("eq", 200);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance API interception and verification.

Add proper response validation, error handling, and use API path constants.

   interceptFacilitySearchReq(): void {
-    cy.intercept("GET", "**/api/v1/facility/**").as("searchFacility");
+    cy.intercept("GET", `${this.API_PATHS.FACILITY}/**`).as("searchFacility");
   }

   verifyFacilitySearchReq(): void {
-    cy.wait("@searchFacility").its("response.statusCode").should("eq", 200);
+    cy.wait("@searchFacility").then((interception) => {
+      if (!interception.response) {
+        throw new Error('No response received from facility search');
+      }
+      expect(interception.response.statusCode).to.equal(200);
+      expect(interception.response.body).to.have.property('data');
+    });
   }

   interceptPostNotificationReq(): void {
-    cy.intercept("POST", "**/api/v1/notification/notify").as("notifyFacility");
+    cy.intercept("POST", `${this.API_PATHS.NOTIFICATION}/notify`).as("notifyFacility");
   }

   verifyPostNotificationReq(): void {
-    cy.wait("@notifyFacility").its("response.statusCode").should("eq", 204);
+    cy.wait("@notifyFacility").then((interception) => {
+      if (!interception.response) {
+        throw new Error('No response received from notification post');
+      }
+      expect(interception.request.body).to.have.property('message');
+      expect(interception.response.statusCode).to.equal(204);
+    });
   }

   interceptGetNotificationReq(): void {
-    cy.intercept("GET", "**/api/v1/notification/**").as("getNotifications");
+    cy.intercept("GET", `${this.API_PATHS.NOTIFICATION}/**`).as("getNotifications");
   }

   verifyGetNotificationReq(): void {
-    cy.wait("@getNotifications").its("response.statusCode").should("eq", 200);
+    cy.wait("@getNotifications").then((interception) => {
+      if (!interception.response) {
+        throw new Error('No response received from get notifications');
+      }
+      const response = interception.response;
+      expect(response.statusCode).to.equal(200);
+      
+      const body = response.body as NotificationResponse;
+      expect(body).to.have.property('message');
+      expect(body).to.have.property('status');
+    });
   }

Also applies to: 29-35, 37-43


interceptPostNotificationReq(): void {
cy.intercept("POST", "**/api/v1/notification/notify").as("notifyFacility");
}

verifyPostNotificationReq(): void {
cy.wait("@notifyFacility").its("response.statusCode").should("eq", 204);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for notification POST requests.

The notification POST verification should handle error cases and validate request payload.

   interceptPostNotificationReq(): void {
-    cy.intercept("POST", "**/api/v1/notification/notify").as("notifyFacility");
+    cy.intercept("POST", this.API_PATHS.NOTIFICATION + '/notify').as("notifyFacility");
   }

   verifyPostNotificationReq(): void {
-    cy.wait("@notifyFacility").its("response.statusCode").should("eq", 204);
+    cy.wait("@notifyFacility").then((interception) => {
+      // Verify request payload
+      expect(interception.request.body).to.have.property('message');
+      // Verify response
+      expect(interception.response?.statusCode).to.equal(204);
+      // Handle potential error responses
+      if (interception.response?.statusCode !== 204) {
+        throw new Error(`Notification failed: ${interception.response?.body}`);
+      }
+    });
   }

Committable suggestion skipped: line range outside the PR's diff.


interceptGetNotificationReq(): void {
cy.intercept("GET", "**/api/v1/notification/**").as("getNotifications");
}

verifyGetNotificationReq(): void {
cy.wait("@getNotifications").its("response.statusCode").should("eq", 200);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance GET notification verification.

Add proper response validation for the get notifications endpoint.

   interceptGetNotificationReq(): void {
-    cy.intercept("GET", "**/api/v1/notification/**").as("getNotifications");
+    cy.intercept("GET", `${this.API_PATHS.NOTIFICATION}/**`).as("getNotifications");
   }

   verifyGetNotificationReq(): void {
-    cy.wait("@getNotifications").its("response.statusCode").should("eq", 200);
+    cy.wait("@getNotifications").then((interception) => {
+      const response = interception.response;
+      expect(response?.statusCode).to.equal(200);
+      
+      const body = response?.body as NotificationResponse;
+      expect(body).to.have.property('message');
+      expect(body).to.have.property('status');
+    });
   }

Committable suggestion skipped: line range outside the PR's diff.

JavidSumra marked this conversation as resolved.
Show resolved Hide resolved
}
4 changes: 4 additions & 0 deletions cypress/pageobject/Login/LoginPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class LoginPage {
cy.get("#sign-out-button").scrollIntoView();
cy.get("#sign-out-button").contains("Sign Out").should("exist");
}

clickSignOutBtn(): void {
cy.verifyAndClickElement("#sign-out-button", "Sign Out");
}
}

export default LoginPage;
2 changes: 2 additions & 0 deletions src/components/Common/Sidebar/SidebarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useAppHistory from "@/hooks/useAppHistory";
export type SidebarIcon = React.ReactNode;

type SidebarItemProps = {
id?: string;
ref?: React.Ref<HTMLAnchorElement>;
text: string;
icon: SidebarIcon;
Expand All @@ -31,6 +32,7 @@ const SidebarItemBase = forwardRef<HTMLAnchorElement, SidebarItemBaseProps>(
return (
<Link
ref={ref}
id={props?.id}
className={`tooltip relative ml-1 mr-2 h-12 flex-1 cursor-pointer rounded-md py-1 font-medium text-gray-600 transition md:flex-none ${
props.selected
? "bg-white text-green-800 shadow"
Expand Down
5 changes: 4 additions & 1 deletion src/components/Facility/FacilityCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,10 @@ export const FacilityCard = (props: {
<DialogModal
show={notifyModalFor === facility.id}
title={
<span className="flex justify-center text-2xl">
<span
className="flex justify-center text-2xl"
id="notify-facility-name"
>
Notify: {facility.name}
</span>
}
Expand Down
4 changes: 3 additions & 1 deletion src/components/Notifications/NoticeBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export const NoticeBoard = () => {
className="overflow-hidden rounded shadow-md"
>
<div className="px-6 py-4">
<div className="text-justify text-lg">{item.message}</div>
<div className="text-justify text-lg" id="notification-message">
{item.message}
</div>
<div className="text-md my-2 text-secondary-700">
{formatName(item.caused_by)} -{" "}
<span className="font-bold text-primary-700">
Expand Down
5 changes: 4 additions & 1 deletion src/components/Notifications/NotificationsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ const NotificationTile = ({
/>
</div>
</div>
<div className="py-1 text-sm">{result.message}</div>
<div className="py-1 text-sm" id="notification-slide-msg">
{result.message}
</div>
<div className="flex flex-col justify-end gap-2">
<div className="py-1 text-right text-xs text-secondary-700">
{formatDateTime(result.created_date)}
Expand Down Expand Up @@ -474,6 +476,7 @@ export default function NotificationsList({
<>
<Item
text={t("Notifications")}
id="notification-slide-btn"
do={() => setOpen(!open)}
icon={<CareIcon icon="l-bell" className="h-5" />}
badgeCount={unreadCount}
Expand Down
Loading