Skip to content

Commit

Permalink
New Cypress test for the patient discussion notes (#8554)
Browse files Browse the repository at this point in the history
* doctor notes cypress test without tab switching

* doctor notes cypress test without tab switching

* Adds utility fn. to extract keys of obj. in type-safe manner.

* i18n for patient notes thread titles and add id for tabs

* discussion note tab switching functionality test

* made success notification as variables

* corrected the test description

---------

Co-authored-by: rithviknishad <[email protected]>
  • Loading branch information
nihal467 and rithviknishad authored Sep 17, 2024
1 parent 5287f35 commit b54bcc5
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 108 deletions.
61 changes: 61 additions & 0 deletions cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import LoginPage from "../../pageobject/Login/LoginPage";
import { PatientPage } from "../../pageobject/Patient/PatientCreation";
import { PatientDoctorNotes } from "../../pageobject/Patient/PatientDoctorNotes";

describe("Patient Discussion notes in the consultation page", () => {
const loginPage = new LoginPage();
const patientPage = new PatientPage();
const patientDoctorNotes = new PatientDoctorNotes();
const patientName = "Dummy Patient 4";
const patientNurseNote = "Test nurse Notes";
const patientNurseReplyNote = "Test nurse reply Notes";
const discussionNotesSubscribeWarning =
"Please subscribe to notifications to get live updates on discussion notes.";
const discussionNotesSuccessMessage = "Note added successfully";

before(() => {
loginPage.loginAsDisctrictAdmin();
cy.saveLocalStorage();
});

beforeEach(() => {
cy.restoreLocalStorage();
cy.clearLocalStorage(/filters--.+/);
cy.awaitUrl("/patients");
});

it("Create a nurse note for a patient and verify both ID received the messages", () => {
// Create a doctor notes a with a district admin
patientPage.visitPatient(patientName);
patientDoctorNotes.visitDiscussionNotesPage();
cy.verifyNotification(discussionNotesSubscribeWarning);
cy.closeNotification();
// switch the switch to nurse note, as the bydefault is doctornotes
patientDoctorNotes.selectNurseDiscussion();
patientDoctorNotes.addDiscussionNotes(patientNurseNote);
patientDoctorNotes.postDiscussionNotes();
cy.verifyNotification(discussionNotesSuccessMessage);
cy.closeNotification();
// verify the auto-switching of tab to nurse notes if the user is a nurse
cy.get("p").contains("Sign Out").click();
loginPage.loginManuallyAsNurse();
loginPage.ensureLoggedIn();
cy.visit("/patients");
patientPage.visitPatient(patientName);
patientDoctorNotes.visitDiscussionNotesPage();
// verify the message is received from admin
cy.verifyNotification(discussionNotesSubscribeWarning);
cy.closeNotification();
patientDoctorNotes.verifyDiscussionMessage(patientNurseNote);
// Post a reply comment to the message
patientDoctorNotes.addDiscussionNotes(patientNurseReplyNote);
patientDoctorNotes.postDiscussionNotes();
cy.verifyNotification(discussionNotesSuccessMessage);
cy.closeNotification();
patientDoctorNotes.verifyDiscussionMessage(patientNurseReplyNote);
});

afterEach(() => {
cy.saveLocalStorage();
});
});
48 changes: 0 additions & 48 deletions cypress/e2e/patient_spec/PatientManage.cy.ts

This file was deleted.

6 changes: 6 additions & 0 deletions cypress/pageobject/Login/LoginPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ class LoginPage {
cy.get("button").contains("Login").click();
}

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();
}

login(username: string, password: string): void {
cy.loginByApi(username, password);
}
Expand Down
26 changes: 0 additions & 26 deletions cypress/pageobject/Patient/PatientConsultation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,30 +110,4 @@ export class PatientConsultationPage {
);
cy.wait(3000);
}

visitShiftRequestPage() {
cy.get("#create_shift_request").click();
}

createShiftRequest() {
cy.intercept("POST", "**/api/v1/shift/").as("createShiftRequest");
cy.get("#submit").click();
cy.wait("@createShiftRequest").its("response.statusCode").should("eq", 201);
}

visitDoctorNotesPage() {
cy.get("#patient_doctor_notes").scrollIntoView();
cy.get("#patient_doctor_notes").click();
}

addDoctorsNotes(notes: string) {
cy.get("#doctor_notes_textarea").scrollIntoView();
cy.get("#doctor_notes_textarea").click().type(notes);
}

postDoctorNotes() {
cy.intercept("POST", "**/api/v1/patient/*/notes").as("postDoctorNotes");
cy.get("#add_doctor_note_button").click();
cy.wait("@postDoctorNotes").its("response.statusCode").should("eq", 201);
}
}
1 change: 1 addition & 0 deletions cypress/pageobject/Patient/PatientCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class PatientPage {
cy.get("#name").click().type(patientName);
cy.intercept("GET", "**/api/v1/consultation/**").as("getPatient");
cy.get("#patient-name-list").contains(patientName).click();
cy.wait(2000);
cy.wait("@getPatient").its("response.statusCode").should("eq", 200);
cy.get("#patient-name-consultation")
.should("be.visible")
Expand Down
29 changes: 29 additions & 0 deletions cypress/pageobject/Patient/PatientDoctorNotes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export class PatientDoctorNotes {
visitDiscussionNotesPage() {
cy.get("#patient_discussion_notes").scrollIntoView();
cy.get("#patient_discussion_notes").click();
}

addDiscussionNotes(notes: string) {
cy.wait(2000);
cy.get("#discussion_notes_textarea").scrollIntoView();
cy.get("#discussion_notes_textarea").click().type(notes);
}

selectNurseDiscussion() {
cy.get("#patient-note-tab-Nurses").scrollIntoView();
cy.get("#patient-note-tab-Nurses").click();
}

verifyDiscussionMessage(text: string) {
cy.get("#patient-notes-list").contains(text);
}

postDiscussionNotes() {
cy.intercept("POST", "**/api/v1/patient/*/notes").as("postDiscussionNotes");
cy.get("#add_doctor_note_button").click();
cy.wait("@postDiscussionNotes")
.its("response.statusCode")
.should("eq", 201);
}
}
2 changes: 1 addition & 1 deletion src/Components/Facility/ConsultationDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export const ConsultationDetails = (props: any) => {
Patient Details
</Link>
<a
id="patient_doctor_notes"
id="patient_discussion_notes"
onClick={() =>
showPatientNotesPopup
? navigate(
Expand Down
16 changes: 6 additions & 10 deletions src/Components/Facility/ConsultationDoctorNotes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import routes from "../../../Redux/api.js";
import request from "../../../Utils/request/request.js";
import useQuery from "../../../Utils/request/useQuery.js";
import useKeyboardShortcut from "use-keyboard-shortcut";
import { classNames, isAppleDevice } from "../../../Utils/utils.js";
import { classNames, isAppleDevice, keysOf } from "../../../Utils/utils.js";
import AutoExpandingTextInputFormField from "../../Form/FormFields/AutoExpandingTextInputFormField.js";
import { PATIENT_NOTES_THREADS } from "../../../Common/constants.js";
import useAuthUser from "../../../Common/hooks/useAuthUser.js";
Expand Down Expand Up @@ -123,23 +123,19 @@ const ConsultationDoctorNotes = (props: ConsultationDoctorNotesProps) => {
>
<div className="relative mx-3 my-2 flex grow flex-col overflow-hidden rounded-lg border border-secondary-300 bg-white p-2 sm:mx-10 sm:my-5 sm:p-5">
<div className="absolute inset-x-0 top-0 flex bg-secondary-200 text-sm shadow-md">
{Object.values(PATIENT_NOTES_THREADS).map((current) => (
{keysOf(PATIENT_NOTES_THREADS).map((current) => (
<button
id={`patient-note-tab-${current}`}
key={current}
className={classNames(
"flex flex-1 justify-center border-b-2 py-2",
thread === current
thread === PATIENT_NOTES_THREADS[current]
? "border-primary-500 font-bold text-secondary-800"
: "border-secondary-300 text-secondary-800",
)}
onClick={() => setThread(current)}
onClick={() => setThread(PATIENT_NOTES_THREADS[current])}
>
{
{
10: "Doctor's Discussions",
20: "Nurse's Discussions",
}[current]
}
{t(`patient_notes_thread__${current}`)}
</button>
))}
</div>
Expand Down
18 changes: 7 additions & 11 deletions src/Components/Facility/PatientNotesSlideover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState, useEffect, Dispatch, SetStateAction } from "react";
import * as Notification from "../../Utils/Notifications.js";
import { NonReadOnlyUsers } from "../../Utils/AuthorizeFor";
import CareIcon from "../../CAREUI/icons/CareIcon";
import { classNames, isAppleDevice } from "../../Utils/utils";
import { classNames, isAppleDevice, keysOf } from "../../Utils/utils";
import ButtonV2 from "../Common/components/ButtonV2";
import { useMessageListener } from "../../Common/hooks/useMessageListener";
import PatientConsultationNotesList from "./PatientConsultationNotesList";
Expand Down Expand Up @@ -193,23 +193,19 @@ export default function PatientNotesSlideover(props: PatientNotesProps) {
{notesActionIcons}
</div>
<div className="flex bg-primary-800 text-sm">
{Object.values(PATIENT_NOTES_THREADS).map((current) => (
{keysOf(PATIENT_NOTES_THREADS).map((current) => (
<button
id={`patient-note-tab-${current}`}
key={current}
className={classNames(
"flex flex-1 justify-center border-b-4 py-1",
thread === current
thread === PATIENT_NOTES_THREADS[current]
? "border-primary-500 font-medium text-white"
: "border-primary-800 text-white/70",
)}
onClick={() => setThread(current)}
onClick={() => setThread(PATIENT_NOTES_THREADS[current])}
>
{
{
10: "Doctor's Discussions",
20: "Nurse's Discussions",
}[current]
}
{t(`patient_notes_thread__${current}`)}
</button>
))}
</div>
Expand All @@ -223,7 +219,7 @@ export default function PatientNotesSlideover(props: PatientNotesProps) {
/>
<div className="relative mx-4 flex items-center">
<AutoExpandingTextInputFormField
id="doctor_notes_textarea"
id="discussion_notes_textarea"
maxHeight={160}
rows={2}
name="note"
Expand Down
16 changes: 6 additions & 10 deletions src/Components/Patient/PatientNotes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import request from "../../Utils/request/request";
import routes from "../../Redux/api";
import { PATIENT_NOTES_THREADS } from "../../Common/constants.js";
import useAuthUser from "../../Common/hooks/useAuthUser.js";
import { classNames } from "../../Utils/utils.js";
import { classNames, keysOf } from "../../Utils/utils.js";
import AutoExpandingTextInputFormField from "../Form/FormFields/AutoExpandingTextInputFormField.js";
import { t } from "i18next";

Expand Down Expand Up @@ -106,23 +106,19 @@ const PatientNotes = (props: PatientNotesProps) => {
>
<div className="relative mx-3 my-2 flex grow flex-col rounded-lg border border-secondary-300 bg-white p-2 sm:mx-10 sm:my-5 sm:p-5">
<div className="absolute inset-x-0 top-0 flex bg-secondary-200 text-sm shadow-md">
{Object.values(PATIENT_NOTES_THREADS).map((current) => (
{keysOf(PATIENT_NOTES_THREADS).map((current) => (
<button
id={`patient-note-tab-${current}`}
key={current}
className={classNames(
"flex flex-1 justify-center border-b-2 py-2",
thread === current
thread === PATIENT_NOTES_THREADS[current]
? "border-primary-500 font-bold text-secondary-800"
: "border-secondary-300 text-secondary-800",
)}
onClick={() => setThread(current)}
onClick={() => setThread(PATIENT_NOTES_THREADS[current])}
>
{
{
10: "Doctor's Discussions",
20: "Nurse's Discussions",
}[current]
}
{t(`patient_notes_thread__${current}`)}
</button>
))}
</div>
Expand Down
6 changes: 4 additions & 2 deletions src/Locale/en/Consultation.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,7 @@
"back_dated_encounter_date_caution": "You are creating an encounter for",
"encounter_duration_confirmation": "The duration of this encounter would be",
"consultation_notes": "General Instructions (Advice)",
"procedure_suggestions": "Procedure Suggestions"
}
"procedure_suggestions": "Procedure Suggestions",
"patient_notes_thread__Doctors": "Doctor's Discussions",
"patient_notes_thread__Nurses": "Nurse's Discussions"
}
7 changes: 7 additions & 0 deletions src/Utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,3 +525,10 @@ export const celsiusToFahrenheit = (celsius: number) => {
export const fahrenheitToCelsius = (fahrenheit: number) => {
return ((fahrenheit - 32) * 5) / 9;
};

/**
* Although same as `Objects.keys(...)`, this provides better type-safety.
*/
export const keysOf = <T extends object>(obj: T) => {
return Object.keys(obj) as (keyof T)[];
};

0 comments on commit b54bcc5

Please sign in to comment.