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 Sample Test Request Workflow #8977

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from

Conversation

JavidSumra
Copy link
Contributor

@JavidSumra JavidSumra commented Nov 1, 2024

Proposed Changes

@ohcnetwork/care-fe-code-reviewers

Merge Checklist

  • Add specs that demonstrate bug / test a new feature.
  • Update product documentation.
  • Ensure that UI text is kept in I18n files.
  • Prep screenshot or demo video for changelog entry, and attach it to issue.
  • Request for Peer Reviews
  • Completion of QA

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new test suite for automated testing of the sample test functionality.
    • Added a button in the mobile view for requesting a sample test, improving user interaction.
  • Improvements

    • Enhanced accessibility with new id attributes for various form fields and components across the patient management interface.
    • Improved rendering logic for patient details and sample test information.
  • Bug Fixes

    • Improved error handling in patient transfer and volunteer assignment processes.

These updates enhance user experience and ensure robust functionality within the sample test management system.

@JavidSumra JavidSumra requested a review from a team as a code owner November 1, 2024 09:52
Copy link

netlify bot commented Nov 1, 2024

Deploy Preview for care-ohc failed.

Name Link
🔨 Latest commit 641137a
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/672c58770cd7fd0008e6b058


it("should request a new sample test", () => {
sampleTestPage.visitPatientPage();
sampleTestPage.visitPatientDashboardPage();
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sampleTestPage.visitPatientDashboardPage();
patientPage.visitPatient(patientName);
  • reuse existing component, and use them in your test by importing the function
  • always try to click on specific patient card, rather than random card
  • keep all the input const in the test file itself

it("should request a new sample test", () => {
sampleTestPage.visitPatientPage();
sampleTestPage.visitPatientDashboardPage();
sampleTestPage.visitSampleRequestPage();
Copy link
Member

@nihal467 nihal467 Nov 5, 2024

Choose a reason for hiding this comment

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

  • before this line, reuse the function to click patient details function
  • after that only add this line, where you are clicking the request sample request page button
  • make sure once the sample request page is loaded, add a cy.intercept and verify the API response to ensure the page is fully loaded before your next line of test is executed

sampleTestPage.selectSampleType(sampleTestType);
sampleTestPage.selectIcmrCategory(icmrCategory);
sampleTestPage.typeIcmrLabel(icmrLabel);

Copy link
Member

@nihal467 nihal467 Nov 5, 2024

Choose a reason for hiding this comment

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

Suggested change
  • remove unwanted spaces
  • input values to all the fields in the form not only the mandatory columns

sampleTestPage.typeIcmrLabel(icmrLabel);

// Submit the form
sampleTestPage.submitForm();
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sampleTestPage.submitForm();
cy.submitButton("Confirm your request to send sample for testing")
  • always use the reusable commands present in commands.ts file

sampleTestPage.submitForm();

// Check for sample request notification and history
sampleTestPage.clickOnNotification();
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sampleTestPage.clickOnNotification();
cy.verifyNotification("Sample test created successfully");

Copy link

coderabbitai bot commented Nov 5, 2024

Walkthrough

This pull request introduces a new Cypress test specification for requesting a sample test, encapsulated in SampleTestRequest.cy.ts. It implements a structured test suite that verifies the functionality of the sample request process. Additionally, various components related to patient management have been updated to enhance accessibility and user interaction, including new id attributes for form fields and buttons, improved error handling, and the addition of a sample request button in the PatientHome component.

Changes

File Path Change Summary
cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts New test suite and test case for requesting a sample test, including setup and verification steps.
cypress/pageobject/Sample/SampleTestCreate.ts Introduction of SampleTestPage class with methods for interacting with the sample request page.
src/components/Patient/PatientHome.tsx Added a button for requesting a sample test and improved error handling in patient transfer and volunteer assignment functions.
src/components/Patient/SampleTest.tsx Added id attributes to form fields and buttons for accessibility.
src/components/Patient/SampleTestCard.tsx Introduced id attributes to various div elements for improved accessibility.
src/components/Patient/SampleViewAdmin.tsx Added id attributes to elements for patient name and search input for better accessibility.
src/components/Patient/SampleDetails.tsx Added id attributes to patient-related information spans for enhanced accessibility.

Assessment against linked issues

Objective Addressed Explanation
Create a Cypress test to request a Sample Test and verify its reflection (8926)
Follow the Page Object Model (POM) approach in the test (8926)
Ensure the normal workflow is functional (8926)
Verify modifications are reflected properly (8926)
Verify visibility in the sample test dashboard (8926) Verification of dashboard visibility is not explicitly covered in the tests.
  • Added dynamic lock icon and strong types #9006: The changes in PatientHome.tsx involve the addition of a button for requesting a sample test, which is directly related to the new test case for requesting a sample test in SampleTestRequest.cy.ts.
  • Removed Unused cypress test files #9012: The removal of unused Cypress test files may indirectly relate to the overall organization and maintenance of the testing framework, but it does not have a direct connection to the specific changes made in the main PR regarding the sample test functionality.

Suggested labels

tested, good to merge

Suggested reviewers

  • rithviknishad

🐰 "In the meadow where bunnies play,
A new test hops in, brightening the day.
With buttons and fields, all set to go,
Sample requests now flow like a show!
Accessibility's charm, in every detail,
A joyful leap, on this coding trail!" 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (8)
cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts (1)

1-8: Consider improving test data management and type safety.

  1. Move test data to a separate fixture file for better maintainability and reusability.
  2. Add TypeScript type annotations for the constants.
 import { SampleTestPage } from "pageobject/Sample/SampleTestCreate";
+import testData from '../fixtures/sampleTest.json';
 
 describe("Sample Test", () => {
   const sampleTestPage = new SampleTestPage();
-  const sampleTestType = "BA/ETA",
-    icmrCategory = "Cat 0",
-    icmrLabel = "Test Icmr Label";
+  const sampleTestType: string = testData.sampleTestType;
+  const icmrCategory: string = testData.icmrCategory;
+  const icmrLabel: string = testData.icmrLabel;
cypress/pageobject/Sample/SampleTestCreate.ts (2)

1-4: Add TypeScript type annotations and improve documentation.

Consider adding type annotations and converting the inline comment to JSDoc format for better TypeScript integration and documentation.

 export class SampleTestPage {
-  sampleTestReportHistory = 0;
-  patientName = ""; // to search for patient in sample page
+  private sampleTestReportHistory: number = 0;
+  /** Patient name used for searching in the sample page */
+  private patientName: string = "";

1-79: Consider architectural improvements for better maintainability and debugging.

While the Page Object Model implementation is good, consider these architectural improvements:

  1. Add logging for better debugging capabilities
  2. Create custom Cypress commands for common operations
  3. Implement retry strategies for flaky operations
  4. Consider splitting into smaller, more focused classes (e.g., separate navigation, form handling, and verification)
src/components/Patient/SampleTest.tsx (3)

230-230: Consider adding validation and improving accessibility for ICMR Category.

While the id="icmr-category" addition is good for testing, consider these improvements:

  1. Add validation in validateForm() to ensure a valid category is selected.
  2. Move the ICMR categories explanation to a separate component or tooltip for better maintainability and accessibility.

256-260: Consider adding format validation for ICMR Label.

While the field has required validation, consider adding:

  1. Pattern validation to ensure the ICMR label follows the expected format
  2. Helper text to guide users on the expected format

Example implementation:

 <TextFormField
   {...field("icmr_label", "ICMR Label")}
   required
   id="icmr-label"
+  pattern="[A-Z0-9-]+"
+  helperText="Enter the ICMR label in uppercase with numbers and hyphens only"
 />

Line range hint 1-326: Consider architectural improvements for better maintainability.

While the changes for testing are good, consider these architectural improvements:

  1. Extract form validation logic into a custom hook for reusability
  2. Move ICMR categories to a configuration file
  3. Consider using a form library like React Hook Form or Formik for better form handling
src/components/Patient/SampleViewAdmin.tsx (1)

349-349: LGTM! Consider consistent ID naming.

The addition of id="search_patient_name" improves test automation capabilities. For consistency across the codebase, consider using either kebab-case (like sample-card) or snake_case (like current) for all IDs.

src/components/Patient/PatientInfoCard.tsx (1)

Line range hint 1-673: Consider breaking down the component for better maintainability.

The PatientInfoCard component handles multiple responsibilities and could benefit from being split into smaller, more focused components. Consider:

  1. Extracting modal-related logic into separate components
  2. Creating a dedicated component for the patient info section
  3. Moving the dropdown menu options into a separate component
  4. Consolidating modal state management using a reducer

This would improve code maintainability, readability, and testing.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a65d7ec and c6e12eb.

📒 Files selected for processing (7)
  • cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts (1 hunks)
  • cypress/pageobject/Sample/SampleTestCreate.ts (1 hunks)
  • src/components/Patient/PatientHome.tsx (1 hunks)
  • src/components/Patient/PatientInfoCard.tsx (1 hunks)
  • src/components/Patient/SampleTest.tsx (4 hunks)
  • src/components/Patient/SampleTestCard.tsx (1 hunks)
  • src/components/Patient/SampleViewAdmin.tsx (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/components/Patient/SampleTestCard.tsx
🔇 Additional comments (4)
src/components/Patient/SampleTest.tsx (2)

215-215: LGTM! Verify test coverage for sample type selection.

The addition of id="sample-type" enhances test targeting. The field is properly integrated with form state and validation.

Let's verify the test coverage:

✅ Verification successful

The sample-type field is properly tested in the Cypress test suite

The added id="sample-type" attribute is being utilized effectively in the test suite:

  • Implemented in the page object pattern (SampleTestCreate.ts)
  • Used in E2E test flow (SampleTestRequest.cy.ts)
  • Properly validated with visibility checks before interaction
  • Integrated into the complete form submission workflow
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for test cases targeting the sample-type field
rg -l 'sample-type' cypress/

Length of output: 585


Script:

#!/bin/bash
# Let's search more broadly for any test files related to sample testing
fd . cypress/ -e ts -e js | xargs rg -l "sample.*test" -i

# Also search specifically for the sample type selector in test files
rg -A 5 "#sample-type" cypress/

Length of output: 738


Script:

#!/bin/bash
# Let's check the actual test implementation to verify the sample type testing
rg -A 10 "selectSampleType" cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts

Length of output: 436


322-326: LGTM! Verify test coverage for form submission.

The addition of id="sample-test-submit-btn" enhances test targeting. The submission logic is comprehensive.

Let's verify the test coverage:

src/components/Patient/SampleViewAdmin.tsx (1)

149-149: LGTM! Good test automation support.

The addition of id="sample-card" improves test automation capabilities by making the sample card element easily identifiable in Cypress tests.

src/components/Patient/PatientInfoCard.tsx (1)

258-258: LGTM! Adding span wrapper improves accessibility.

The addition of a span element with id="patient-name" enhances DOM accessibility and makes it easier to target the patient's name for testing or styling purposes.

Comment on lines 37 to 41
it("should verify sample request on sample page", () => {
sampleTestPage.visitSamplePage();
sampleTestPage.searchPatientSample(sampleTestPage.patientName);
sampleTestPage.patientSampleMustExist();
});
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 test independence and add explicit assertions.

The test case appears to depend on the previous test's state and lacks proper assertions.

 it("should verify sample request on sample page", () => {
+  cy.intercept('GET', '/api/v1/sample/*').as('getSamples');
   sampleTestPage.visitSamplePage();
+  cy.wait('@getSamples');
 
+  const expectedPatient = "John Doe"; // Move to test data
-  sampleTestPage.searchPatientSample(sampleTestPage.patientName);
+  sampleTestPage.searchPatientSample(expectedPatient);
+  cy.get('[data-testid="search-results"]').should('be.visible');
 
-  sampleTestPage.patientSampleMustExist();
+  cy.get('[data-testid="patient-sample"]')
+    .should('contain', expectedPatient)
+    .and('contain', sampleTestType);
 });

Consider making this test independent by setting up its own test data, rather than relying on the previous test case.

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

Comment on lines 9 to 17
before(() => {
cy.loginByApi("devdistrictadmin", "Coronasafe@123");
cy.saveLocalStorage();
});

beforeEach(() => {
cy.restoreLocalStorage();
cy.clearLocalStorage(/filters--.+/);
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Move credentials to environment variables or test configuration.

Hardcoded credentials in test files pose a security risk and make credential rotation difficult.

 before(() => {
-  cy.loginByApi("devdistrictadmin", "Coronasafe@123");
+  cy.loginByApi(Cypress.env('ADMIN_USERNAME'), Cypress.env('ADMIN_PASSWORD'));
   cy.saveLocalStorage();
 });
📝 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
before(() => {
cy.loginByApi("devdistrictadmin", "Coronasafe@123");
cy.saveLocalStorage();
});
beforeEach(() => {
cy.restoreLocalStorage();
cy.clearLocalStorage(/filters--.+/);
});
before(() => {
cy.loginByApi(Cypress.env('ADMIN_USERNAME'), Cypress.env('ADMIN_PASSWORD'));
cy.saveLocalStorage();
});
beforeEach(() => {
cy.restoreLocalStorage();
cy.clearLocalStorage(/filters--.+/);
});

Comment on lines 19 to 35
it("should request a new sample test", () => {
sampleTestPage.visitPatientPage();
sampleTestPage.visitPatientDashboardPage();
sampleTestPage.visitSampleRequestPage();

// Fill form fields
sampleTestPage.selectSampleType(sampleTestType);
sampleTestPage.selectIcmrCategory(icmrCategory);
sampleTestPage.typeIcmrLabel(icmrLabel);

// Submit the form
sampleTestPage.submitForm();

// Check for sample request notification and history
sampleTestPage.clickOnNotification();
sampleTestPage.checkRequestHistory();
});
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 test reliability with API intercepts and assertions.

The test needs improvements in several areas:

  1. Add API intercepts to verify page loads
  2. Add assertions between steps
  3. Use specific patient selection instead of random selection
 it("should request a new sample test", () => {
+  cy.intercept('GET', '/api/v1/patient/*').as('getPatient');
   sampleTestPage.visitPatientPage();
-  sampleTestPage.visitPatientDashboardPage();
+  cy.wait('@getPatient');
+  
+  const patientName = "John Doe"; // Move to test data
+  sampleTestPage.visitPatient(patientName);
+  cy.contains(patientName).should('be.visible');
 
+  cy.intercept('GET', '/api/v1/sample_test/*').as('getSampleTest');
   sampleTestPage.visitSampleRequestPage();
+  cy.wait('@getSampleTest');
 
   // Fill form fields
   sampleTestPage.selectSampleType(sampleTestType);
+  cy.get('[data-testid="sample-type"]').should('have.value', sampleTestType);
   sampleTestPage.selectIcmrCategory(icmrCategory);
+  cy.get('[data-testid="icmr-category"]').should('have.value', icmrCategory);
   sampleTestPage.typeIcmrLabel(icmrLabel);
+  cy.get('[data-testid="icmr-label"]').should('have.value', icmrLabel);
 
   // Submit the form
-  sampleTestPage.submitForm();
+  cy.submitButton("Confirm your request to send sample for testing");
 
   // Check for sample request notification and history
-  sampleTestPage.clickOnNotification();
+  cy.verifyNotification("Sample test created successfully");
   sampleTestPage.checkRequestHistory();
 });

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

Comment on lines 37 to 54
selectSampleType(option: string) {
cy.get("#sample-type").should("be.visible").click();
cy.get("[role='option']").contains(option).click();
}

selectIcmrCategory(option: string) {
cy.get("#icmr-category").should("be.visible").click();
cy.get("[role='option']").contains(option).click();
}

typeIcmrLabel(label: string) {
cy.get("#icmr-label").should("be.visible").type(label);
}

submitForm() {
cy.get("#sample-test-submit-btn").scrollIntoView();
cy.get("#sample-test-submit-btn").should("be.visible").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

Add input validation and error handling to form interactions.

The form interaction methods need improved validation and error handling:

  1. Input parameters should be validated
  2. Form submission should verify form validity
  3. Error handling for failed interactions is missing
-  selectSampleType(option: string) {
+  selectSampleType(option: string): void {
+    if (!option) {
+      throw new Error('Sample type option is required');
+    }
     cy.get("#sample-type").should("be.visible").click();
-    cy.get("[role='option']").contains(option).click();
+    cy.get("[role='option']")
+      .contains(option)
+      .should("exist")
+      .should("be.visible")
+      .click();
   }

   submitForm() {
+    // Verify form validity before submission
+    cy.get('form')
+      .invoke('get', 0)
+      .then($form => {
+        expect($form.checkValidity()).to.be.true;
+      });
     cy.get("#sample-test-submit-btn").scrollIntoView();
     cy.get("#sample-test-submit-btn")
       .should("be.visible")
+      .should("be.enabled")
       .click();
   }

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

Comment on lines 20 to 35
visitSampleRequestPage() {
cy.get("body").then(($body) => {
if ($body.find("#sample-test-history").length > 0) {
cy.get("#sample-test-history")
.its("length")
.then((count) => {
this.sampleTestReportHistory = count;
});
} else {
// Set to 0 if the element does not exist
this.sampleTestReportHistory = 0;
}
});
cy.get("#sample-request-btn").scrollIntoView();
cy.get("#sample-request-btn").should("be.visible").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

Simplify sample history count logic and add error handling.

The current implementation of sample history counting is overly complex and could be simplified.

 visitSampleRequestPage() {
-    cy.get("body").then(($body) => {
-      if ($body.find("#sample-test-history").length > 0) {
-        cy.get("#sample-test-history")
-          .its("length")
-          .then((count) => {
-            this.sampleTestReportHistory = count;
-          });
-      } else {
-        // Set to 0 if the element does not exist
-        this.sampleTestReportHistory = 0;
-      }
-    });
+    // Get sample history count, defaulting to 0 if not found
+    cy.get("#sample-test-history")
+      .then($elements => {
+        this.sampleTestReportHistory = $elements.length;
+      })
+      .catch(() => {
+        this.sampleTestReportHistory = 0;
+      });
+
+    // Verify sample request button exists before clicking
     cy.get("#sample-request-btn").scrollIntoView();
-    cy.get("#sample-request-btn").should("be.visible").click();
+    cy.get("#sample-request-btn")
+      .should("be.visible")
+      .should("be.enabled")
+      .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
visitSampleRequestPage() {
cy.get("body").then(($body) => {
if ($body.find("#sample-test-history").length > 0) {
cy.get("#sample-test-history")
.its("length")
.then((count) => {
this.sampleTestReportHistory = count;
});
} else {
// Set to 0 if the element does not exist
this.sampleTestReportHistory = 0;
}
});
cy.get("#sample-request-btn").scrollIntoView();
cy.get("#sample-request-btn").should("be.visible").click();
}
visitSampleRequestPage() {
// Get sample history count, defaulting to 0 if not found
cy.get("#sample-test-history")
.then($elements => {
this.sampleTestReportHistory = $elements.length;
})
.catch(() => {
this.sampleTestReportHistory = 0;
});
// Verify sample request button exists before clicking
cy.get("#sample-request-btn").scrollIntoView();
cy.get("#sample-request-btn")
.should("be.visible")
.should("be.enabled")
.click();
}

Comment on lines 9 to 18
visitPatientDashboardPage() {
cy.get(".patient-stable-ring").first().scrollIntoView();
cy.get(".patient-stable-ring").should("be.visible").first().click();
cy.get("#patient-name")
.invoke("text")
.then((patientName) => {
this.patientName = patientName.trim();
});
cy.get("#patient-details").should("be.visible").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

Improve selector reliability and error handling in patient dashboard navigation.

The current implementation has potential reliability issues:

  1. The .patient-stable-ring selector is brittle and could break with UI changes
  2. No error handling for cases where patient details are not found
 visitPatientDashboardPage() {
-    cy.get(".patient-stable-ring").first().scrollIntoView();
-    cy.get(".patient-stable-ring").should("be.visible").first().click();
+    cy.get('[data-testid="patient-card"]')
+      .first()
+      .should("exist")
+      .scrollIntoView()
+      .should("be.visible")
+      .click();
     cy.get("#patient-name")
       .invoke("text")
       .then((patientName) => {
         this.patientName = patientName.trim();
+        // Verify patient name was actually extracted
+        expect(this.patientName).to.not.be.empty;
       });
     cy.get("#patient-details").should("be.visible").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
visitPatientDashboardPage() {
cy.get(".patient-stable-ring").first().scrollIntoView();
cy.get(".patient-stable-ring").should("be.visible").first().click();
cy.get("#patient-name")
.invoke("text")
.then((patientName) => {
this.patientName = patientName.trim();
});
cy.get("#patient-details").should("be.visible").click();
}
visitPatientDashboardPage() {
cy.get('[data-testid="patient-card"]')
.first()
.should("exist")
.scrollIntoView()
.should("be.visible")
.click();
cy.get("#patient-name")
.invoke("text")
.then((patientName) => {
this.patientName = patientName.trim();
// Verify patient name was actually extracted
expect(this.patientName).to.not.be.empty;
});
cy.get("#patient-details").should("be.visible").click();
}

Comment on lines 56 to 78
clickOnNotification() {
cy.get(".pnotify-container").should("be.visible").click();
}

checkRequestHistory() {
cy.get("#sample-test-history").scrollIntoView();
cy.get("#sample-test-history").should(
"have.length",
this.sampleTestReportHistory + 1,
);
}

visitSamplePage() {
cy.awaitUrl("/sample");
}

searchPatientSample() {
cy.get("#search_patient_name").should("be.visible").type(this.patientName);
}

patientSampleMustExist() {
cy.get("#sample-card").should("be.visible");
}
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 verification methods with better error handling and timeouts.

The verification methods need improvements in reliability and error handling:

  1. Notification handling should be more robust
  2. Sample history verification should handle edge cases
  3. Timeouts should be configured for async operations
   clickOnNotification() {
-    cy.get(".pnotify-container").should("be.visible").click();
+    cy.get(".pnotify-container", { timeout: 10000 })
+      .should("be.visible")
+      .should("not.be.disabled")
+      .click();
   }

   checkRequestHistory() {
     cy.get("#sample-test-history").scrollIntoView();
-    cy.get("#sample-test-history").should(
-      "have.length",
-      this.sampleTestReportHistory + 1,
-    );
+    cy.get("#sample-test-history", { timeout: 10000 })
+      .should("exist")
+      .then($elements => {
+        const currentCount = $elements.length;
+        expect(currentCount).to.equal(
+          this.sampleTestReportHistory + 1,
+          `Expected sample history count to increase by 1 from ${this.sampleTestReportHistory} to ${this.sampleTestReportHistory + 1}, but found ${currentCount}`
+        );
+      });
   }

   patientSampleMustExist() {
-    cy.get("#sample-card").should("be.visible");
+    cy.get("#sample-card", { timeout: 10000 })
+      .should("exist")
+      .should("be.visible")
+      .then($card => {
+        expect($card).to.contain(this.patientName);
+      });
   }
📝 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
clickOnNotification() {
cy.get(".pnotify-container").should("be.visible").click();
}
checkRequestHistory() {
cy.get("#sample-test-history").scrollIntoView();
cy.get("#sample-test-history").should(
"have.length",
this.sampleTestReportHistory + 1,
);
}
visitSamplePage() {
cy.awaitUrl("/sample");
}
searchPatientSample() {
cy.get("#search_patient_name").should("be.visible").type(this.patientName);
}
patientSampleMustExist() {
cy.get("#sample-card").should("be.visible");
}
clickOnNotification() {
cy.get(".pnotify-container", { timeout: 10000 })
.should("be.visible")
.should("not.be.disabled")
.click();
}
checkRequestHistory() {
cy.get("#sample-test-history").scrollIntoView();
cy.get("#sample-test-history", { timeout: 10000 })
.should("exist")
.then($elements => {
const currentCount = $elements.length;
expect(currentCount).to.equal(
this.sampleTestReportHistory + 1,
`Expected sample history count to increase by 1 from ${this.sampleTestReportHistory} to ${this.sampleTestReportHistory + 1}, but found ${currentCount}`
);
});
}
visitSamplePage() {
cy.awaitUrl("/sample");
}
searchPatientSample() {
cy.get("#search_patient_name").should("be.visible").type(this.patientName);
}
patientSampleMustExist() {
cy.get("#sample-card", { timeout: 10000 })
.should("exist")
.should("be.visible")
.then($card => {
expect($card).to.contain(this.patientName);
});
}

@@ -1370,6 +1370,7 @@ export const PatientHome = (props: any) => {
)
}
authorizeFor={NonReadOnlyUsers}
id="sample-request-btn"
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Both instances of "Request Sample Test" should have test identifiers for consistency

The codebase has two instances of "Request Sample Test":

  • One in a ButtonV2 component that correctly has the id="sample-request-btn" attribute
  • Another in a <p> tag that lacks a test identifier

For consistent test automation, consider adding a test identifier to the <p> tag instance as well.

🔗 Analysis chain

LGTM! Test identifier added for Cypress automation.

The addition of the id attribute for the sample test request button aligns well with the PR objectives and follows good testing practices.

Let's verify if similar buttons in the desktop view also need test identifiers:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other sample test related buttons in the file
rg --type tsx "Request Sample Test" -B 2 -A 2

Length of output: 75


Script:

#!/bin/bash
# Search for other sample test related buttons in the file, using ripgrep without file type filter
rg "Request Sample Test" -B 2 -A 2

Length of output: 856


Script:

#!/bin/bash
# Let's check if these other instances have test identifiers
rg -B 5 -A 5 "Request Sample Test" src/components/Patient/PatientHome.tsx

Length of output: 909


// Check for sample request notification and history
sampleTestPage.clickOnNotification();
sampleTestPage.checkRequestHistory();
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sampleTestPage.checkRequestHistory();
sampleTestPage.checkRequestHistory();
  • this should verify the content on the card present in the patient details page, where status , sample type and result is displayed.
  • we have reusable component for verifying content presence, refer to commands.ts file

sampleTestPage.checkRequestHistory();
});

it("should verify sample request on sample page", () => {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
it("should verify sample request on sample page", () => {
it("should verify sample request on sample page", () => {
  • this should be part of the first test , not a different test


it("should verify sample request on sample page", () => {
sampleTestPage.visitSamplePage();
sampleTestPage.searchPatientSample(sampleTestPage.patientName);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sampleTestPage.searchPatientSample(sampleTestPage.patientName);
sampleTestPage.searchPatientSample(sampleTestPage.patientName);
  • check for the patient card presence, and verify the patient name in the card
  • then click on the sample details button, and verify all the inputted details are properly present in the sample details page
  • add a cy.intercept to ensure that the API status to ensure the page is fully loaded

cy.awaitUrl("/patients");
}

visitPatientDashboardPage() {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
visitPatientDashboardPage() {
visitPatientDashboardPage() {
  • always try to use proper id's and not class name
  • remove all unwanted function as a lot of changes requested

cy.get("#search_patient_name").should("be.visible").type(this.patientName);
}

patientSampleMustExist() {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
patientSampleMustExist() {
patientSampleMustExist() {
  • never add random card presence check, if you want to check a card of a patient, always check for the card with patient name present in it

icmrLabel = "Test Icmr Label";

before(() => {
cy.loginByApi("devdistrictadmin", "Coronasafe@123");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
cy.loginByApi("devdistrictadmin", "Coronasafe@123");
loginPage.loginAsDisctrictAdmin();

@nihal467
Copy link
Member

nihal467 commented Nov 5, 2024

@JavidSumra

  • in general, use already existing helper function in commands.ts file and already declared reusable function
  • for any form submission or new page load, add cy. intercept to make sure the API responds properly and the page is fully loaded before your next line of test is executed
  • never use classes if there is a possibility we can add id to the elements
  • always do a manual test of the workflow you are planning to write test and plan properly before start coding

@JavidSumra
Copy link
Contributor Author

Hey @nihal467 can you please verify requested changes

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🧹 Outside diff range and nitpick comments (8)
src/components/Patient/SampleDetails.tsx (2)

359-361: LGTM! Consider extending ID coverage

The etiology_identified ID is well-implemented. For completeness, consider adding similar IDs to other test-relevant fields like sample type, SARI status, and travel history sections to maintain consistent testability across the component.


Line range hint 302-361: Well-structured implementation for test automation

The addition of ID attributes follows a consistent pattern and aligns well with the PR's objective of implementing Cypress tests. The identifiers are semantic, well-placed within their respective conditional blocks, and maintain the existing component logic.

A few suggestions for enhancing the test automation setup:

  1. Consider documenting these test IDs in a central location for better maintainability
  2. Consider adding a data-testid attribute alongside id for separation of concerns between styling/accessibility and testing
cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts (2)

61-65: Add assertions to verify the request history content.

To ensure that the sample test request is correctly reflected in the request history, add explicit assertions to verify the displayed content.

Example additions:

// Check the updated request history
  sampleTestPage.interceptSampleTestReq();
  sampleTestPage.verifySampleTestReq();
  sampleTestPage.checkRequestHistory(fastTrackReason);
+ sampleTestPage.verifyRequestHistoryContent({
+   sampleType: sampleTestType,
+   diagnosis,
+   fastTrackReason,
+ });

69-81: Enhance test reliability by adding explicit assertions for sample test details.

To improve the reliability of the test, add assertions after navigating to the sample test details page to verify that all entered details are correctly displayed.

Example additions:

  sampleTestPage.searchPatientSample(patientName);
  sampleTestPage.interceptGetSampleTestReq();
  sampleTestPage.verifyGetSampleTestReq();
  sampleTestPage.verifyPatientName(patientName);
  sampleTestPage.clickOnSampleDetailsBtn();
  sampleTestPage.verifyGetSampleTestReq();
  sampleTestPage.verifyPatientTestDetails(
    patientName,
    fastTrackReason,
    diagnosis,
    differentialDiagnosis,
    etiologyIdentified,
  );
+ // Assertions to confirm displayed details
+ cy.get('[data-testid="sample-type"]').should('contain', sampleTestType);
+ cy.get('[data-testid="diagnosis"]').should('contain', diagnosis);
+ cy.get('[data-testid="fast-track-reason"]').should('contain', fastTrackReason);
+ // Add additional assertions as necessary
cypress/pageobject/Sample/SampleTestCreate.ts (4)

56-61: Parameterize hardcoded values in checkRequestHistory for flexibility

Currently, the method uses hardcoded strings like "Request Submitted" and "ba/eta". Consider passing these as parameters to make the method more reusable and adaptable to future changes.

Apply this diff to parameterize the values:

  checkRequestHistory(fastTrack: string) {
+   const status = "Request Submitted";
+   const testType = "ba/eta";
+   const result = "Awaiting";
    cy.verifyContentPresence("#sample-test-status", [status]);
    cy.verifyContentPresence("#sample-test-type", [testType]);
    cy.verifyContentPresence("#sample-test-fast-track", [fastTrack]);
    cy.verifyContentPresence("#sample-test-result", [result]);
  }

Or update the method signature to accept these as parameters:

- checkRequestHistory(fastTrack: string) {
+ checkRequestHistory(fastTrack: string, status: string, testType: string, result: string) {
    cy.verifyContentPresence("#sample-test-status", [status]);
    cy.verifyContentPresence("#sample-test-type", [testType]);
    cy.verifyContentPresence("#sample-test-fast-track", [fastTrack]);
    cy.verifyContentPresence("#sample-test-result", [result]);
  }

75-88: Parameterize hardcoded doctor name in verifyPatientTestDetails

The doctor's name "Dr John Doe" is hardcoded. To enhance flexibility and accommodate different doctors, consider making it a parameter.

Apply this diff:

  verifyPatientTestDetails(
      patientName: string,
      fastTrackReason: string,
      diagnosis: string,
      differentialDiagnosis: string,
      etiologyIdentified: string,
+     doctorName: string,
  ) {
      cy.verifyContentPresence("#patient_name", [patientName]);
      cy.verifyContentPresence("#fast_track_reason", [fastTrackReason]);
-     cy.verifyContentPresence("#doctor_name", ["Dr John Doe"]);
+     cy.verifyContentPresence("#doctor_name", [doctorName]);
      cy.verifyContentPresence("#diagnosis", [diagnosis]);
      cy.verifyContentPresence("#diff_diagnosis", [differentialDiagnosis]);
      cy.verifyContentPresence("#etiology_identified", [etiologyIdentified]);
  }

Update the calls to this method to pass the doctorName parameter accordingly.


95-96: Add timeout to cy.wait for verifyPatientDetailsResponse

To prevent indefinite waiting in case the API response is delayed or fails, consider adding a timeout to cy.wait.

Apply this diff:

  verifyPatientDetailsResponse() {
-   cy.wait("@patientDetails").its("response.statusCode").should("eq", 200);
+   cy.wait("@patientDetails", { timeout: 10000 })
+     .its("response.statusCode")
+     .should("eq", 200);
  }

Repeat similar adjustments for other methods waiting on intercepts.


108-114: Consolidate API intercepts into a single method for maintainability

To reduce code duplication and improve maintainability, consider creating a generic method for intercepting API calls and verifying their responses.

Example implementation:

interceptAndVerifyApi(alias: string, method: string, urlPattern: string, statusCode: number = 200) {
  cy.intercept(method, urlPattern).as(alias);
  cy.wait(`@${alias}`, { timeout: 10000 })
    .its("response.statusCode")
    .should("eq", statusCode);
}

You can then replace the existing methods with calls to this generic method.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c6e12eb and 988fbb1.

📒 Files selected for processing (6)
  • cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts (1 hunks)
  • cypress/pageobject/Sample/SampleTestCreate.ts (1 hunks)
  • src/components/Patient/SampleDetails.tsx (2 hunks)
  • src/components/Patient/SampleTest.tsx (5 hunks)
  • src/components/Patient/SampleTestCard.tsx (5 hunks)
  • src/components/Patient/SampleViewAdmin.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/Patient/SampleTest.tsx
  • src/components/Patient/SampleTestCard.tsx
  • src/components/Patient/SampleViewAdmin.tsx
🔇 Additional comments (5)
src/components/Patient/SampleDetails.tsx (5)

302-302: LGTM! Semantic ID for patient name

The addition of the patient_name ID attribute follows good practices for test automation.


327-327: LGTM! Appropriate ID for fast track reason

The fast_track_reason ID is well-placed within the conditional rendering block.


335-337: LGTM! Well-structured doctor name identifier

The doctor_name ID is correctly implemented while preserving the name transformation logic.


343-343: LGTM! Clear diagnosis identifier

The diagnosis ID is appropriately placed for test automation.


351-351: LGTM! Proper differential diagnosis identifier

The diff_diagnosis ID follows the established pattern for test automation.

"The patient has a high risk of complications and requires immediate testing.";

before(() => {
loginPage.loginAsDisctrictAdmin();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix the typo in method name loginAsDisctrictAdmin.

The method name loginAsDisctrictAdmin contains a typo. It should be loginAsDistrictAdmin.

Apply this diff to correct the typo:

- loginPage.loginAsDisctrictAdmin();
+ loginPage.loginAsDistrictAdmin();
📝 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
loginPage.loginAsDisctrictAdmin();
loginPage.loginAsDistrictAdmin();

Comment on lines 67 to 68
cy.awaitUrl("/sample");

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 API intercept to ensure the sample page data is loaded before proceeding.

To make sure that the sample page data is fully loaded before performing actions like searching, add a cy.intercept and wait for the response.

Apply this diff to include the intercept:

// Ensure sample page API is loaded before proceeding
+ cy.intercept('GET', '/api/v1/sample/*').as('getSamples');
  cy.awaitUrl("/sample");
+ cy.wait('@getSamples');
📝 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
cy.awaitUrl("/sample");
// Ensure sample page API is loaded before proceeding
cy.intercept('GET', '/api/v1/sample/*').as('getSamples');
cy.awaitUrl("/sample");
cy.wait('@getSamples');

sampleTestPage.verifyPatientDetailsResponse();

// Ensure sample request API is loaded
sampleTestPage.visitSampleRequestPage();
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 API intercept to ensure the sample request page has fully loaded.

To ensure that the sample request page is fully loaded before interacting with it, consider adding a cy.intercept for the sample request API and waiting for its response.

Apply this diff to implement the intercept:

// Ensure sample request API is loaded
+ sampleTestPage.interceptSampleRequestAPI();
  sampleTestPage.visitSampleRequestPage();
+ sampleTestPage.waitForSampleRequestResponse();

If these methods are not available, you can use:

// Ensure sample request API is loaded
+ cy.intercept('GET', '/api/v1/sample/*').as('getSampleRequest');
  sampleTestPage.visitSampleRequestPage();
+ cy.wait('@getSampleRequest');

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

Comment on lines 6 to 8
selectSampleType(option: string) {
cy.clickAndSelectOption("#sample-type", option);
}
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 input validation for parameters in interaction methods

To enhance robustness, consider adding input validation to ensure that the option parameter is defined before using it in selectSampleType.

Apply this diff to add input validation:

  selectSampleType(option: string) {
+   if (!option) {
+     throw new Error('Option is required for selectSampleType');
+   }
    cy.clickAndSelectOption("#sample-type", option);
  }
📝 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
selectSampleType(option: string) {
cy.clickAndSelectOption("#sample-type", option);
}
selectSampleType(option: string) {
if (!option) {
throw new Error('Option is required for selectSampleType');
}
cy.clickAndSelectOption("#sample-type", option);
}

Comment on lines 23 to 25
fillDoctorName(value: string) {
cy.get("#doctor_name").should("be.visible").type(value);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate input in fillDoctorName

To prevent errors, check that value is provided before typing.

Apply this diff:

  fillDoctorName(value: string) {
+   if (!value) {
+     throw new Error('Doctor name is required for fillDoctorName');
+   }
    cy.get("#doctor_name").should("be.visible").type(value);
  }
📝 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
fillDoctorName(value: string) {
cy.get("#doctor_name").should("be.visible").type(value);
}
fillDoctorName(value: string) {
if (!value) {
throw new Error('Doctor name is required for fillDoctorName');
}
cy.get("#doctor_name").should("be.visible").type(value);
}

Comment on lines 32 to 34
fillDiagnosis(value: string) {
cy.get("#diagnosis").should("be.visible").type(value);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate value parameter in fillDiagnosis

Add a check to ensure value is provided.

Apply this diff:

  fillDiagnosis(value: string) {
+   if (!value) {
+     throw new Error('Diagnosis value is required for fillDiagnosis');
+   }
    cy.get("#diagnosis").should("be.visible").type(value);
  }
📝 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
fillDiagnosis(value: string) {
cy.get("#diagnosis").should("be.visible").type(value);
}
fillDiagnosis(value: string) {
if (!value) {
throw new Error('Diagnosis value is required for fillDiagnosis');
}
cy.get("#diagnosis").should("be.visible").type(value);
}

Comment on lines 14 to 16
fillIcmrLabel(label: string) {
cy.get("#icmr-label").should("be.visible").type(label);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate input parameter before using in fillIcmrLabel

Ensure the label parameter is not empty to avoid unexpected behavior.

Apply this diff:

  fillIcmrLabel(label: string) {
+   if (!label) {
+     throw new Error('Label is required for fillIcmrLabel');
+   }
    cy.get("#icmr-label").should("be.visible").type(label);
  }
📝 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
fillIcmrLabel(label: string) {
cy.get("#icmr-label").should("be.visible").type(label);
}
fillIcmrLabel(label: string) {
if (!label) {
throw new Error('Label is required for fillIcmrLabel');
}
cy.get("#icmr-label").should("be.visible").type(label);
}

Comment on lines 36 to 38
fillEtiology(value: string) {
cy.get("#etiology_identified").should("be.visible").type(value);
}
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 input validation to fillEtiology

Check that value is not empty before typing.

Apply this diff:

  fillEtiology(value: string) {
+   if (!value) {
+     throw new Error('Etiology value is required for fillEtiology');
+   }
    cy.get("#etiology_identified").should("be.visible").type(value);
  }
📝 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
fillEtiology(value: string) {
cy.get("#etiology_identified").should("be.visible").type(value);
}
fillEtiology(value: string) {
if (!value) {
throw new Error('Etiology value is required for fillEtiology');
}
cy.get("#etiology_identified").should("be.visible").type(value);
}

Comment on lines 40 to 42
fillDiffDiagnosis(value: string) {
cy.get("#diff_diagnosis").should("be.visible").type(value);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Validate value parameter in fillDiffDiagnosis

Ensure value is provided to prevent potential errors.

Apply this diff:

  fillDiffDiagnosis(value: string) {
+   if (!value) {
+     throw new Error('Differential diagnosis value is required for fillDiffDiagnosis');
+   }
    cy.get("#diff_diagnosis").should("be.visible").type(value);
  }
📝 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
fillDiffDiagnosis(value: string) {
cy.get("#diff_diagnosis").should("be.visible").type(value);
}
fillDiffDiagnosis(value: string) {
if (!value) {
throw new Error('Differential diagnosis value is required for fillDiffDiagnosis');
}
cy.get("#diff_diagnosis").should("be.visible").type(value);
}

Comment on lines 18 to 21
fillFastTrackReason(value: string) {
cy.get("#is_fast_track").should("be.visible").check();
cy.get("#fast_track").should("be.visible").type(value);
}
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 input validation to fillFastTrackReason

Validate the value parameter to ensure the method functions correctly.

Apply this diff:

  fillFastTrackReason(value: string) {
+   if (!value) {
+     throw new Error('Value is required for fillFastTrackReason');
+   }
    cy.get("#is_fast_track").should("be.visible").check();
    cy.get("#fast_track").should("be.visible").type(value);
  }
📝 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
fillFastTrackReason(value: string) {
cy.get("#is_fast_track").should("be.visible").check();
cy.get("#fast_track").should("be.visible").type(value);
}
fillFastTrackReason(value: string) {
if (!value) {
throw new Error('Value is required for fillFastTrackReason');
}
cy.get("#is_fast_track").should("be.visible").check();
cy.get("#fast_track").should("be.visible").type(value);
}

Copy link
Member

@nihal467 nihal467 left a comment

Choose a reason for hiding this comment

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

  • self evaluate you PR before asking for next review
  • make sure you cleared all requested changes
  • look through the Ai suggestion once as well

// Ensure patient list API is loaded before proceeding
cy.awaitUrl("/patients");
patientPage.visitPatient(patientName);
cy.verifyAndClickElement("#patient-details", "Patient Details");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
cy.verifyAndClickElement("#patient-details", "Patient Details");
cy.verifyAndClickElement("#patient-details", "Patient Details");
  • reusable the clickPatientDetails() function in the PatientConsultation.ts

cy.awaitUrl("/patients");
patientPage.visitPatient(patientName);
cy.verifyAndClickElement("#patient-details", "Patient Details");
sampleTestPage.interceptPatientDetailsAPI();
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sampleTestPage.interceptPatientDetailsAPI();
sampleTestPage.interceptPatientDetailsAPI();
  • what are you verifying here, in between the intercept trigger and response verification, there is no action been executed

sampleTestPage.verifyPatientDetailsResponse();

// Ensure sample request API is loaded
sampleTestPage.visitSampleRequestPage();
Copy link
Member

Choose a reason for hiding this comment

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

like the ai review suggested, there is API verification is missing


// Ensure sample request API is loaded
sampleTestPage.visitSampleRequestPage();

Copy link
Member

Choose a reason for hiding this comment

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

  • As mentioned in the last review to remove unused line, why are you still keeping the space

}

checkRequestHistory(fastTrack: string) {
cy.verifyContentPresence("#sample-test-status", ["Request Submitted"]);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
cy.verifyContentPresence("#sample-test-status", ["Request Submitted"]);
cy.verifyContentPresence("#sample-test-status", ["Request Submitted"]);
  • why are keeping these hardcoded value inside the function, keep it in the test file, make it reusable, checkrequesthistory function will not be having same content all the time

cy.verifyNotification("Sample test created successfully");

// Check the updated request history
sampleTestPage.interceptSampleTestReq();
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sampleTestPage.interceptSampleTestReq();
sampleTestPage.interceptSampleTestReq();
  • as mention on above comment, there is no action after the intercept is triggered, make necessary changes, personally understand why intercept are being used before implementing it

) {
cy.verifyContentPresence("#patient_name", [patientName]);
cy.verifyContentPresence("#fast_track_reason", [fastTrackReason]);
cy.verifyContentPresence("#doctor_name", ["Dr John Doe"]);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
cy.verifyContentPresence("#doctor_name", ["Dr John Doe"]);
cy.verifyContentPresence("#doctor_name", ["Dr John Doe"]);
  • dont use hardcoded values, its not necessary next time someone using this function will have patient card of dr john

@github-actions github-actions bot added the Deploy-Failed Deplyment is not showing preview label Nov 7, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (1)
cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts (1)

36-87: Consider breaking down the test into smaller, focused test cases.

The current test case is quite long and tests multiple aspects of the workflow. Consider splitting it into smaller, more focused test cases for better maintainability and easier debugging.

Suggested test structure:

  1. Test sample request form submission:
it("should submit sample test request form successfully", () => {
  // Navigate to form
  // Fill form
  // Submit and verify
});
  1. Test sample request history:
it("should display sample request in history", () => {
  // Create sample request in before hook
  // Verify history
});
  1. Test sample search and details:
it("should display sample details correctly", () => {
  // Create sample request in before hook
  // Search and verify details
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 988fbb1 and 641137a.

📒 Files selected for processing (2)
  • cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts (1 hunks)
  • cypress/pageobject/Sample/SampleTestCreate.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cypress/pageobject/Sample/SampleTestCreate.ts

Comment on lines +11 to +24
const patientName = "Dummy Patient 11";
const sampleTestType = "BA/ETA";
const icmrCategory = "Cat 0";
const icmrLabel = "Test Icmr Label";
const doctorName = "Dr John Doe";
const atypicalDetails = "Patient showing unusual symptoms";
const diagnosis = "Suspected respiratory infection";
const etiologyIdentified = "Bacterial infection suspected";
const differentialDiagnosis = "Possibly a viral infection";
const fastTrackReason =
"The patient has a high risk of complications and requires immediate testing.";
const sampleTestStatus = "Request Submitted";
const expectedSampleTestType = "ba/eta";
const sampleTestResult = "Awaiting";
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Move test data to fixtures for better maintainability.

Consider moving test data constants to a fixture file for better reusability and maintainability.

Create a new file cypress/fixtures/sampleTest.json:

{
  "patient": {
    "name": "Dummy Patient 11",
    "doctorName": "Dr John Doe"
  },
  "sampleTest": {
    "type": "BA/ETA",
    "icmrCategory": "Cat 0",
    "icmrLabel": "Test Icmr Label",
    "status": "Request Submitted",
    "result": "Awaiting"
  },
  "clinicalDetails": {
    "atypicalDetails": "Patient showing unusual symptoms",
    "diagnosis": "Suspected respiratory infection",
    "etiologyIdentified": "Bacterial infection suspected",
    "differentialDiagnosis": "Possibly a viral infection",
    "fastTrackReason": "The patient has a high risk of complications and requires immediate testing."
  }
}

Then import and use it in the test:

let testData: any;

before(() => {
  cy.fixture('sampleTest').then((data) => {
    testData = data;
  });
});

Comment on lines +40 to +42
sampleTestPage.interceptPatientDetailsAPI();
patientConsultationPage.clickPatientDetails();
sampleTestPage.verifyPatientDetailsResponse();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve API intercept handling for patient details.

The intercept is triggered but there's no explicit wait for the response before proceeding.

Apply this diff:

-    sampleTestPage.interceptPatientDetailsAPI();
     patientConsultationPage.clickPatientDetails();
-    sampleTestPage.verifyPatientDetailsResponse();
+    cy.intercept('GET', '/api/v1/patient/*/details').as('patientDetails');
+    patientConsultationPage.clickPatientDetails();
+    cy.wait('@patientDetails').then((interception) => {
+      expect(interception.response?.statusCode).to.equal(200);
+    });

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

Comment on lines +71 to +78
cy.awaitUrl("/sample");
sampleTestPage.interceptGetSampleTestReq();
sampleTestPage.searchPatientSample(patientName);
sampleTestPage.verifyGetSampleTestReq();
sampleTestPage.verifyPatientName(patientName);
sampleTestPage.interceptGetSampleTestReq();
sampleTestPage.clickOnSampleDetailsBtn();
sampleTestPage.verifyGetSampleTestReq();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve sample page navigation and verification.

Multiple API intercepts are used without proper waiting, which could cause race conditions.

Apply this diff:

     cy.awaitUrl("/sample");
-    sampleTestPage.interceptGetSampleTestReq();
+    cy.intercept('GET', '/api/v1/sample_test/*').as('getSampleTest');
     sampleTestPage.searchPatientSample(patientName);
-    sampleTestPage.verifyGetSampleTestReq();
+    cy.wait('@getSampleTest');
     sampleTestPage.verifyPatientName(patientName);
-    sampleTestPage.interceptGetSampleTestReq();
+    cy.intercept('GET', '/api/v1/sample_test/*/details').as('getSampleDetails');
     sampleTestPage.clickOnSampleDetailsBtn();
-    sampleTestPage.verifyGetSampleTestReq();
+    cy.wait('@getSampleDetails');
📝 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
cy.awaitUrl("/sample");
sampleTestPage.interceptGetSampleTestReq();
sampleTestPage.searchPatientSample(patientName);
sampleTestPage.verifyGetSampleTestReq();
sampleTestPage.verifyPatientName(patientName);
sampleTestPage.interceptGetSampleTestReq();
sampleTestPage.clickOnSampleDetailsBtn();
sampleTestPage.verifyGetSampleTestReq();
cy.awaitUrl("/sample");
cy.intercept('GET', '/api/v1/sample_test/*').as('getSampleTest');
sampleTestPage.searchPatientSample(patientName);
cy.wait('@getSampleTest');
sampleTestPage.verifyPatientName(patientName);
cy.intercept('GET', '/api/v1/sample_test/*/details').as('getSampleDetails');
sampleTestPage.clickOnSampleDetailsBtn();
cy.wait('@getSampleDetails');

Comment on lines +59 to +62
cy.submitButton("Confirm your request to send sample for testing");
sampleTestPage.interceptSampleTestReq();
cy.verifyNotification("Sample test created successfully");
sampleTestPage.verifySampleTestReq();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix sample test request API verification.

The intercept is placed after the action that triggers the API call, which could lead to flaky tests.

Apply this diff:

+    cy.intercept('POST', '/api/v1/sample_test/').as('createSampleTest');
     cy.submitButton("Confirm your request to send sample for testing");
-    sampleTestPage.interceptSampleTestReq();
     cy.verifyNotification("Sample test created successfully");
-    sampleTestPage.verifySampleTestReq();
+    cy.wait('@createSampleTest').then((interception) => {
+      expect(interception.response?.statusCode).to.equal(201);
+    });
📝 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
cy.submitButton("Confirm your request to send sample for testing");
sampleTestPage.interceptSampleTestReq();
cy.verifyNotification("Sample test created successfully");
sampleTestPage.verifySampleTestReq();
cy.intercept('POST', '/api/v1/sample_test/').as('createSampleTest');
cy.submitButton("Confirm your request to send sample for testing");
cy.verifyNotification("Sample test created successfully");
cy.wait('@createSampleTest').then((interception) => {
expect(interception.response?.statusCode).to.equal(201);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create a cypress test to request a Sample Test and verify its reflection
2 participants