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

added cypress tests for shifting request #9035

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
80 changes: 80 additions & 0 deletions cypress/e2e/shifting_spec/ShiftingRequest.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import LoginPage from "pageobject/Login/LoginPage"
import { PatientConsultationPage } from "pageobject/Patient/PatientConsultation";
import { PatientPage } from "pageobject/Patient/PatientCreation";
import ShiftCreation from "pageobject/Shift/ShiftCreation";
import { ShiftDetails } from "pageobject/Shift/ShiftDetails";
import { ShiftingBoard } from "pageobject/Shift/ShiftingBoard";
import ShiftUpdate from "pageobject/Shift/ShiftUpdate";

describe("New shifting request",() =>{
const loginPage = new LoginPage();
const shiftCreation = new ShiftCreation()
const shiftingBoard = new ShiftingBoard()
const shiftDetails = new ShiftDetails()
const shiftUpdate = new ShiftUpdate()
const patientPage = new PatientPage()
const patientConsultationPage = new PatientConsultationPage()

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

beforeEach(() => {
cy.restoreLocalStorage();
});

it("Creating and verifying new shifting request", () => {
cy.intercept("POST", "api/v1/shift").as("shiftRequest");

cy.visit('/patients')
patientPage.visitPatient("Dummy Patient 16")
patientConsultationPage.clickShiftPatientButton()

shiftCreation.typeCurrentFacilityPerson("new");
shiftCreation.typeCurrentFacilityPhone("9465666768");
shiftCreation.typeShiftReason("emmergency");
shiftCreation.typeAmbulanceDriverName("Rahul");
shiftCreation.typeAmbulancePhone("9865666768")
shiftCreation.typeAmbulanceNumber("1")
shiftCreation.typeComment("Some comment")
shiftCreation.submitShiftForm();

cy.wait("@shiftRequest").its("response.statusCode").should("eq", 201);

cy.visit("/shifting/board");
cy.contains("Dummy Patient 16").should("exist");
});

it("Editing and verifying refelctions in existing request", () => {
cy.intercept("PUT", "**/api/v1/shift/**").as("shiftUpdateRequest");
cy.visit("/shifting/board");
cy.contains("Dummy Patient 16").should("exist");

shiftingBoard.openDetails("Dummy Patient 16")
shiftDetails.clickUpdateStatusButton()

shiftUpdate.typeShiftReason("new reason");
shiftUpdate.typeAmbulanceDriverName("Ramesh");
shiftUpdate.typeAmbulancePhone("9755443232")
shiftUpdate.typeAmbulanceNumber("2")
shiftUpdate.typeComment("New comment")
shiftUpdate.submitShiftForm();

cy.wait('@shiftUpdateRequest').then((interception) => {
const responseData = interception.response.body;

expect(responseData.patient_object.name).to.eq("Dummy Patient 16");
expect(responseData.ambulance_phone_number).to.eq("+919755443232");
expect(responseData.comments).to.eq("New comment");
expect(responseData.reason).to.eq("new reason");
expect(responseData.ambulance_driver_name).to.eq("Ramesh");
expect(responseData.ambulance_number).to.eq("2");
});

});
Comment on lines +49 to +75
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix typo and enhance error handling scenarios.

  1. The test description contains a typo: "refelctions" should be "reflections"
  2. Consider adding test cases for error scenarios

Add error scenarios:

it("Should handle API errors when updating shift request", () => {
  cy.intercept("PUT", "**/api/v1/shift/**", {
    statusCode: 500,
    body: { error: "Internal Server Error" }
  }).as("failedUpdate");
  
  // Perform update operation
  // Verify error handling in UI
  cy.get('[data-testid=error-message]').should('be.visible');
});

it("Should validate required fields when updating", () => {
  shiftingBoard.openDetails("Dummy Patient 16");
  shiftDetails.clickUpdateStatusButton();
  
  // Clear required fields
  shiftUpdate.typeShiftReason("");
  shiftUpdate.submitShiftForm();
  
  // Verify validation messages
  cy.get('[data-testid=reason-error]').should('be.visible');
});


afterEach(() => {
cy.saveLocalStorage();
});
})
11 changes: 11 additions & 0 deletions cypress/pageobject/Patient/PatientConsultation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class PatientConsultationPage {
selectSymptomsDate(date: string) {
cy.clickAndTypeDate("#symptoms_onset_date", date);
}

clickAddSymptom() {
cy.get("#add-symptom").click();
}
Expand Down Expand Up @@ -111,4 +112,14 @@ export class PatientConsultationPage {
);
cy.wait(3000);
}

clickShiftPatientButton() {
cy.get("#consultation-buttons").scrollIntoView();
cy.get("button").contains("Manage Patient").click();
cy.verifyAndClickElement(
"#consultation-buttons",
"Shift Patient",
);
cy.wait(3000);
}
}
16 changes: 16 additions & 0 deletions cypress/pageobject/Shift/ShiftCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ export class ShiftCreation {
cy.get("#reason").click().type(reason);
}

typeAmbulanceDriverName(name: string) {
cy.get("#ambulance_driver_name").click().type(name);
}

typeAmbulancePhone(number: string) {
cy.get("#ambulance_phone_number").click().type(number);
}

typeAmbulanceNumber(number: string) {
cy.get("#ambulance_number").click().type(number);
}

typeComment(comment:string) {
cy.get('#comments').click().type(comment)
}

submitShiftForm() {
cy.get("#submit").contains("Submit").click();
}
Expand Down
6 changes: 6 additions & 0 deletions cypress/pageobject/Shift/ShiftDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class ShiftDetails{
clickUpdateStatusButton(){
cy.contains("Update Status/Details").click()
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use data-testid for more robust element selection

Using text content for element selection is fragile and can break if the text changes or with i18n. Use data-testid attributes instead.

-        cy.contains("Update Status/Details").click()
+        cy.get('[data-testid="shift-update-status-button"]').click()

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

}

}
Comment on lines +1 to +6
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add TypeScript types and documentation

The class should follow TypeScript best practices with proper type annotations and documentation.

+/**
+ * Page Object Model class for handling shift details operations
+ */
 export class ShiftDetails{
-    clickUpdateStatusButton(){
+    /**
+     * Clicks the update status button in the shift details view
+     * @returns {Cypress.Chainable<void>} Cypress chain
+     */
+    clickUpdateStatusButton(): Cypress.Chainable<void> {
         cy.contains("Update Status/Details").click()
     }
 }
📝 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 ShiftDetails{
clickUpdateStatusButton(){
cy.contains("Update Status/Details").click()
}
}
/**
* Page Object Model class for handling shift details operations
*/
export class ShiftDetails{
/**
* Clicks the update status button in the shift details view
* @returns {Cypress.Chainable<void>} Cypress chain
*/
clickUpdateStatusButton(): Cypress.Chainable<void> {
cy.contains("Update Status/Details").click()
}
}

27 changes: 27 additions & 0 deletions cypress/pageobject/Shift/ShiftUpdate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export class ShiftUpdate {
typeShiftReason(reason: string) {
cy.get("#reason").click().clear().type(reason);
}
Comment on lines +2 to +4
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance form interaction methods with better practices.

The input methods could be improved with:

  1. Input validation
  2. Wait assertions
  3. Better error handling
  4. JSDoc documentation

Here's a suggested implementation pattern:

/** Constants file */
export const SELECTORS = {
  REASON: '#reason',
  DRIVER_NAME: '#ambulance_driver_name',
  // ... other selectors
} as const;

/** Example improved method */
/**
 * Types the shift reason into the reason field
 * @param reason - The reason for the shift
 * @throws {Error} If the reason field is not found
 */
typeShiftReason(reason: string): void {
  if (!reason?.trim()) {
    throw new Error('Shift reason cannot be empty');
  }
  cy.get(SELECTORS.REASON)
    .should('be.visible')
    .click()
    .clear()
    .type(reason, { delay: 50 })
    .should('have.value', reason);
}

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


typeAmbulanceDriverName(name: string) {
cy.get("#ambulance_driver_name").click().clear().type(name);
}

typeAmbulancePhone(number: string) {
cy.get("#ambulance_phone_number").click().clear().type(number);
}

typeAmbulanceNumber(number: string) {
cy.get("#ambulance_number").click().clear().type(number);
}

typeComment(comment: string) {
cy.get('#comments').click().clear().type(comment);
}

submitShiftForm() {
cy.get("#submit").contains("Submit").click();
}
Comment on lines +22 to +24
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve form submission handling.

The submit method should be more robust by:

  1. Using a more specific selector
  2. Handling loading states
  3. Verifying successful submission
/**
 * Submits the shift form and verifies successful submission
 * @throws {Error} If submission fails or times out
 */
submitShiftForm(): void {
  cy.get('#submit')
    .should('be.visible')
    .and('not.be.disabled')
    .click();
  
  // Wait for loading state
  cy.get('.loading-indicator').should('exist');
  
  // Verify successful submission
  cy.get('.success-message')
    .should('be.visible')
    .and('contain', 'Shift updated successfully');
}

}
export default ShiftUpdate;

8 changes: 8 additions & 0 deletions cypress/pageobject/Shift/ShiftingBoard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class ShiftingBoard {
openDetails(patientName) {
cy.get('#patient_name').type(patientName);
cy.intercept("GET", "**/api/v1/shift/**").as("getShiftingRequest");
cy.wait("@getShiftingRequest").its("response.statusCode").should("eq", 200);
Comment on lines +4 to +5
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Make the API intercept pattern more specific to match the actual endpoint

Based on the search results, the broad pattern **/api/v1/shift/** could intercept multiple endpoints:

  • /api/v1/shift/ (GET, POST)
  • /api/v1/shift/{id}/ (GET, PUT, DELETE)
  • /api/v1/shift/{id}/comment/ (GET, POST)
  • /api/v1/shift/{externalId}/transfer/ (POST)

Since this intercept is used in the openDetails method and followed by a status check, it should specifically target the list endpoint:

cy.intercept("GET", "/api/v1/shift/").as("getShiftingRequest");
🔗 Analysis chain

Verify API endpoint pattern and response handling.

The API interception pattern **/api/v1/shift/** is quite broad. Consider making it more specific to avoid intercepting unintended requests.

Let's verify the API endpoint pattern:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for shift-related API endpoints to ensure we're using the correct pattern
rg -g '*.{ts,js,tsx,jsx}' --no-heading "api/v1/shift" -A 2 -B 2

Length of output: 3699

cy.contains("All Details").click();
}
Comment on lines +2 to +7
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add TypeScript type safety and improve error handling.

The method implementation could be more robust with the following improvements:

  1. Add type safety for the parameter
  2. Configure appropriate timeout for API wait
  3. Add error handling for failed scenarios

Consider applying these improvements:

-    openDetails(patientName) {
+    openDetails(patientName: string) {
         cy.get('#patient_name').type(patientName);
         cy.intercept("GET", "**/api/v1/shift/**").as("getShiftingRequest");
-        cy.wait("@getShiftingRequest").its("response.statusCode").should("eq", 200);
+        cy.wait("@getShiftingRequest", { timeout: 10000 })
+          .then((interception) => {
+            if (interception.response?.statusCode !== 200) {
+              throw new Error(`API request failed with status ${interception.response?.statusCode}`);
+            }
+          });
-        cy.contains("All Details").click();
+        cy.contains("All Details", { timeout: 5000 }).click();
     }
📝 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
openDetails(patientName) {
cy.get('#patient_name').type(patientName);
cy.intercept("GET", "**/api/v1/shift/**").as("getShiftingRequest");
cy.wait("@getShiftingRequest").its("response.statusCode").should("eq", 200);
cy.contains("All Details").click();
}
openDetails(patientName: string) {
cy.get('#patient_name').type(patientName);
cy.intercept("GET", "**/api/v1/shift/**").as("getShiftingRequest");
cy.wait("@getShiftingRequest", { timeout: 10000 })
.then((interception) => {
if (interception.response?.statusCode !== 200) {
throw new Error(`API request failed with status ${interception.response?.statusCode}`);
}
});
cy.contains("All Details", { timeout: 5000 }).click();
}

}
Loading