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

Rewriting UsersCreation.cy.ts according to POM approach #8930

Merged

Conversation

AnveshNalimela
Copy link
Contributor

@AnveshNalimela AnveshNalimela commented Oct 25, 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

  • New Features

    • Introduced new methods for user profile management, enhancing the clarity of user interactions.
    • Added methods for clearing input fields, improving user experience during data entry.
  • Bug Fixes

    • Renamed methods for better clarity, ensuring users can easily understand their functionality.
  • Refactor

    • Improved organization and readability of user creation and profile update tests.
    • Enhanced method specificity and clarity in user creation and profile management.
    • Updated functions for generating phone numbers to improve randomness and security.
  • Documentation

    • Updated method names and parameters to follow consistent naming conventions for better usability.

@AnveshNalimela AnveshNalimela requested a review from a team as a code owner October 25, 2024 18:32
Copy link

netlify bot commented Oct 25, 2024

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit 5bf8c5d
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/674a483fcf546400084b9ab6
😎 Deploy Preview https://deploy-preview-8930--care-ohc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

.env Outdated Show resolved Hide resolved
cypress/e2e/users_spec/UsersCreation.cy.ts Show resolved Hide resolved
.env Outdated Show resolved Hide resolved
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.

  1. We use POM approach in cypress, so changes everything into a re-usable function Refer: PatientDoctorConnect.cy.ts test file

For example cy.get("#user-profile-name").click(); should be a function which is named clickUserProfileName()

Similarly, convert the entire test file to the POM approach

@AnveshNalimela
Copy link
Contributor Author

@nihal467
have a look at this

clickProfileName() {
    cy.get("#user-profile-name").click();
  }

Declare such indiviual functions in pageobejct of user creation.ts

@nihal467
Copy link
Member

@AnveshNalimela i have modified the issue, can you clear the rest of them ?

@AnveshNalimela
Copy link
Contributor Author

@nihal467 made the changes accordingly by refering patientDoctorConnect.cy.ts .just have look at latest commit

@AnveshNalimela AnveshNalimela changed the title removed ClickElementById function from UsersCreation.cy.ts Rewriting UsersCreation.cy.ts according to POM approach Oct 27, 2024
@github-actions github-actions bot added the merge conflict pull requests with merge conflict label Oct 28, 2024
Copy link

👋 Hi, @AnveshNalimela,
Conflicts have been detected against the base branch. Please rebase your branch against the base branch.


This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there.

@nihal467
Copy link
Member

@AnveshNalimela as per the updated issue , you need to rewrite the entire file, read it carefully, so which means that, we need to give individual function name to each operation.

image

Replace all the usage of :

  • Removed the clickelemenenbyid with individual function name following the POM
  • similar do the above process for clearintoelementbyid, typeintoelemenetbyid
  • replace the setinputdate , selectdropdownoption, verifynotification, verifyelementcontainstext,verifyerrormessage with already setup command.ts function

inshort: rewrite the entire file with new individual proper function, proper usage of command.ts functions, and keep it clean

Copy link
Contributor

@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: 1

🧹 Outside diff range and nitpick comments (9)
cypress/pageobject/Users/UserProfilePage.ts (2)

22-32: Consider reducing duplication in clear methods

While the individual clear methods are clear and focused, there's significant code duplication in the implementation pattern.

Consider refactoring to use a helper method:

+ private clearField(selector: string) {
+   cy.get(selector).click().clear();
+ }
+
  clearPhoneNumber() {
-   cy.get("#phoneNumber").click().clear();
+   this.clearField("#phoneNumber");
  }
  clearAltPhoneNumber() {
-   cy.get("#altPhoneNumber").click().clear();
+   this.clearField("#altPhoneNumber");
  }
  clearWorkingHours() {
-   cy.get("#weekly_working_hours").click().clear();
+   this.clearField("#weekly_working_hours");
  }
  clearEmail() {
-   cy.get("#email").click().clear();
+   this.clearField("#email");
  }

91-94: Improve formatting consistency

The assertWorkingHours method has inconsistent formatting with extra newlines and different parameter placement compared to other assertion methods.

Consider reformatting for consistency:

  assertWorkingHours(workingHours: string) {
-   cy.get("#averageworkinghour-profile-details").should(
-     "contain.text",
-     workingHours,
-   );
+   cy.get("#averageworkinghour-profile-details").should("contain.text", workingHours);
  }
cypress/e2e/users_spec/UsersCreation.cy.ts (4)

Line range hint 25-33: Replace Math.random() with a cryptographically secure alternative.

The current implementation using Math.random() is not cryptographically secure and could potentially generate predictable or duplicate usernames.

Consider using crypto.getRandomValues() for better security:

 const makeId = (length: number) => {
   let result = "";
   const characters = "abcdefghijklmnopqrstuvwxyz0123456789";
-  const charactersLength = characters.length;
-  for (let i = 0; i < length; i++) {
-    result += characters.charAt(Math.floor(Math.random() * charactersLength));
+  const values = new Uint32Array(length);
+  crypto.getRandomValues(values);
+  for (let i = 0; i < length; i++) {
+    result += characters[values[i] % characters.length];
   }
   return result;
 };
🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 17-17: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


[failure] 18-18: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


62-62: Fix typo in firstName constant value.

The value "District Editted" contains a typo.

-const firstName = "District Editted";
+const firstName = "District Edited";

112-114: Enhance API response verification.

While status code verification is good, consider also validating the response body structure and content.

 cy.intercept("PATCH", "/api/v1/users/*").as("updateUser");
 cy.clickSubmitButton(updateBtn);
-cy.wait("@updateUser").its("response.statusCode").should("eq", 200);
+cy.wait("@updateUser").then((interception) => {
+  expect(interception.response?.statusCode).to.eq(200);
+  expect(interception.response?.body).to.have.property("data");
+  expect(interception.response?.body.data).to.include({
+    first_name: firstName,
+    last_name: lastName,
+    email: email
+  });
+});

180-182: Enhance error message validation.

Consider validating the format and content of error messages more specifically.

 cy.clickSubmitButton(saveBtn);
 cy.get(".error-text", { timeout: 10000 }).should("be.visible");
-userCreationPage.verifyErrorMessages(EXPECTED_ERROR_MESSAGES);
+cy.get(".error-text").each(($el, index) => {
+  expect($el.text().trim()).to.equal(EXPECTED_ERROR_MESSAGES[index]);
+  expect($el).to.have.css("color", "rgb(220, 38, 38)"); // Verify error styling
+});
cypress/pageobject/Users/UserCreation.ts (3)

3-4: Consider reducing duplication by creating a generic click method

The clickAddUserButton method directly uses cy.verifyAndClickElement. If you have multiple methods performing similar click actions, consider creating a generic method to handle clicks and reduce code duplication.

For example:

private clickElement(elementId: string, elementText: string) {
  cy.verifyAndClickElement(elementId, elementText);
}

clickAddUserButton() {
  this.clickElement("#addUserButton", "Add New User");
}

6-19: Extract common code in type methods to a reusable function

The methods typeUserName, typeFirstName, typeLastName, typePassword, and typeConfirmPassword all follow the pattern of clicking an element and typing into it. To improve maintainability and reduce repetition, consider extracting this pattern into a reusable method.

Apply this refactor:

private typeIntoField(elementId: string, value: string) {
  cy.get(elementId).click().type(value);
}

typeUserName(username: string) {
  this.typeIntoField("#username", username);
}

typeFirstName(firstName: string) {
  this.typeIntoField("#firstName", firstName);
}

typeLastName(lastName: string) {
  this.typeIntoField("#lastName", lastName);
}

typePassword(password: string) {
  this.typeIntoField("#password", password);
}

typeConfirmPassword(password: string) {
  this.typeIntoField("#c_password", password);
}

21-25: Extract common code in clear methods to a reusable function

The methods clearFirstName and clearLastName both click and clear input fields. To enhance code reusability, consider creating a generic method for clearing fields.

Apply this refactor:

private clearField(elementId: string) {
  cy.get(elementId).click().clear();
}

clearFirstName() {
  this.clearField("#firstName");
}

clearLastName() {
  this.clearField("#lastName");
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5329457 and ad5da79.

📒 Files selected for processing (4)
  • cypress/e2e/users_spec/UsersCreation.cy.ts (6 hunks)
  • cypress/e2e/users_spec/UsersProfile.cy.ts (2 hunks)
  • cypress/pageobject/Users/UserCreation.ts (1 hunks)
  • cypress/pageobject/Users/UserProfilePage.ts (4 hunks)
🧰 Additional context used
📓 Learnings (2)
cypress/e2e/users_spec/UsersCreation.cy.ts (3)
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:16-59
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In the `cypress/pageobject/Users/UserCreation.ts` file, method parameter names may use a mix of `snake_case` and `camelCase` naming conventions, and this is acceptable in the codebase.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:31-42
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In `UserCreationPage` of `UserCreation.ts`, methods like `typePhoneNumber` and `typeUserPhoneNumber` target different input fields and are both necessary.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:3-5
Timestamp: 2024-11-15T05:22:27.913Z
Learning: In the `clickProfileName()` method of the `UserCreationPage` class, the profile name is dynamic and cannot be verified using a static text. Therefore, `cy.get("#user-profile-name").click();` should be used instead of `cy.verifyAndClickElement`.
cypress/pageobject/Users/UserCreation.ts (3)
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:31-42
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In `UserCreationPage` of `UserCreation.ts`, methods like `typePhoneNumber` and `typeUserPhoneNumber` target different input fields and are both necessary.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:3-5
Timestamp: 2024-11-15T05:22:27.913Z
Learning: In the `clickProfileName()` method of the `UserCreationPage` class, the profile name is dynamic and cannot be verified using a static text. Therefore, `cy.get("#user-profile-name").click();` should be used instead of `cy.verifyAndClickElement`.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:16-59
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In the `cypress/pageobject/Users/UserCreation.ts` file, method parameter names may use a mix of `snake_case` and `camelCase` naming conventions, and this is acceptable in the codebase.
🪛 GitHub Check: CodeQL
cypress/e2e/users_spec/UsersCreation.cy.ts

[failure] 17-17: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


[failure] 18-18: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.

🔇 Additional comments (10)
cypress/pageobject/Users/UserProfilePage.ts (4)

18-20: LGTM! Good improvements to method naming

The changes follow proper camelCase naming conventions and make good use of reusable commands.


48-49: Maintain WhatsApp terminology for consistency

The rename from WhatsApp to altPhoneNumber breaks consistency with UI labels and existing tests.

Previous review already highlighted this issue. Please keep the WhatsApp-specific naming as it's used consistently throughout the codebase in UI components and tests.


52-53: LGTM! Good parameter naming improvement

The change to camelCase for the workingHours parameter improves consistency.


87-89: Maintain WhatsApp terminology in assertion methods

Similar to the input methods, the assertion method should maintain WhatsApp terminology.

cypress/e2e/users_spec/UsersProfile.cy.ts (2)

35-39: LGTM! Method names now follow consistent naming conventions.

The renaming of methods improves code clarity:

  • typeDateOfBirth clearly indicates its purpose
  • typePhoneNumber and typeAltPhoneNumber are more descriptive than the previous typePhone and typeWhatsApp

49-53: LGTM! Assert methods now match their corresponding type methods.

The assertion methods have been properly renamed to maintain consistency with their corresponding input methods:

  • assertDateOfBirth matches typeDateOfBirth
  • assertPhoneNumber matches typePhoneNumber
  • assertAltPhoneNumber matches typeAltPhoneNumber

Let's verify that these changes are consistently implemented in the page object:

✅ Verification successful

Verified: Type and assert methods are consistently implemented and properly paired

The codebase analysis confirms that the UserProfilePage class in cypress/pageobject/Users/UserProfilePage.ts has properly implemented pairs of type and assert methods:

  • typeDateOfBirth() with assertDateOfBirth()
  • typePhoneNumber() with assertPhoneNumber()
  • typeAltPhoneNumber() with assertAltPhoneNumber()

Each method pair uses consistent naming and follows the same pattern, with type methods handling input and assert methods verifying the displayed values.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify method implementations in UserProfilePage
# Expect to find both type and assert methods with consistent naming

ast-grep --pattern 'class UserProfilePage {
  $$$
  typeDateOfBirth($_) {
    $$$
  }
  assertDateOfBirth($_) {
    $$$
  }
  typePhoneNumber($_) {
    $$$
  }
  assertPhoneNumber($_) {
    $$$
  }
  typeAltPhoneNumber($_) {
    $$$
  }
  assertAltPhoneNumber($_) {
    $$$
  }
  $$$
}'

Length of output: 288


Script:

#!/bin/bash
# Let's try a different approach to find the UserProfilePage class implementation
# First, locate the file containing UserProfilePage
fd "UserProfilePage" --type f

# Then examine its content
rg "class UserProfilePage" -A 5 -B 5

# Also search for the specific methods mentioned
rg "(typeDateOfBirth|assertDateOfBirth|typePhoneNumber|assertPhoneNumber|typeAltPhoneNumber|assertAltPhoneNumber)" -A 2 -B 2

Length of output: 5167

cypress/e2e/users_spec/UsersCreation.cy.ts (2)

Line range hint 1-24: LGTM! Clean imports and proper initialization.

The imports are well-organized and the page objects are properly instantiated.

🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 17-17: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


[failure] 18-18: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


Line range hint 83-93: LGTM! Proper test setup.

The test setup follows Cypress best practices with proper login handling and local storage management.

cypress/pageobject/Users/UserCreation.ts (2)

27-28: Ensure consistent use of reusable commands for selection methods

While selectUserType, selectGender, selectState, and selectDistrict all use cy.clickAndSelectOption, the selectFacility method uses cy.typeAndSelectOption. Verify if this difference is intentional or if a consistent command should be used across all selection methods.

You can run the following script to check the usages of these commands in the codebase:

This will help you determine if the commands are used appropriately based on the context.

Also applies to: 31-31

✅ Verification successful

Different selection commands serve distinct UI interaction patterns

Based on the codebase analysis, the distinction between cy.clickAndSelectOption and cy.typeAndSelectOption is intentional and follows a consistent pattern:

  • cy.clickAndSelectOption is used for dropdown menus with predefined options (e.g., user types, gender, states, districts)
  • cy.typeAndSelectOption is used for searchable/autocomplete fields where users need to type and select from filtered results (e.g., facility search, bed selection, doctor selection)

In the UserCreation.ts file:

  • selectUserType, selectGender, selectState, and selectDistrict correctly use clickAndSelectOption for fixed dropdown options
  • selectFacility correctly uses typeAndSelectOption as it's a searchable facility field
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check usage of selection commands for consistency.

# Find usages of cy.clickAndSelectOption
rg "cy\.clickAndSelectOption"

# Find usages of cy.typeAndSelectOption
rg "cy\.typeAndSelectOption"

Length of output: 5816


44-45: Confirm the correct usage of cy.typeAndSelectOption in selectFacility

The selectFacility method uses cy.typeAndSelectOption with the selector "input[name='facilities']". Ensure that this is the appropriate command and selector for selecting facilities, and that it aligns with the behavior of similar selection methods.

Run the following script to verify the selector and usage:

This will help confirm that the selector targets the correct element and the method is used correctly elsewhere.

✅ Verification successful

Let me analyze the usage of cy.typeAndSelectOption to ensure it's consistent.


The usage of cy.typeAndSelectOption in selectFacility is correct and consistent

The verification shows that:

  • The custom command typeAndSelectOption is properly defined in cypress/support/commands.ts
  • The selector input[name='facilities'] is consistently used across multiple files including PatientCreation.ts and AssetCreation.ts
  • The implementation in UserCreation.ts follows the same pattern as other similar facility selection methods in the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the facilities input field.

# Search for the input field with name 'facilities' in the codebase
rg 'input[^>]*name=["'\'']facilities["'\'']'

# Check for usages of selectFacility method
rg 'selectFacility'

Length of output: 3516


Script:

#!/bin/bash
# Search for all usages of typeAndSelectOption to verify consistency
rg "typeAndSelectOption" -A 1

# Check if there's a custom command definition for typeAndSelectOption
fd -e ts -e js "commands" --exec cat {} \;

Length of output: 10659

Copy link
Contributor

@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: 3

🧹 Outside diff range and nitpick comments (4)
cypress/e2e/users_spec/UsersManage.cy.ts (1)

Line range hint 1-168: Consider enhancing test maintainability with these suggestions.

While the overall test structure is good, here are some suggestions to improve maintainability:

  1. Consider moving test data (usernames, facility names) to a separate fixture file
  2. Group related constants using interfaces/types
  3. Add more descriptive comments for each test case's purpose

Example structure for test data:

// cypress/fixtures/users.json
{
  "doctors": {
    "linkFacility": {
      "doc1": "dummydoctor4",
      "doc2": "dummydoctor5",
      "doc3": "dummydoctor6"
    },
    "linkSkill": {
      "username": "devdoctor",
      "firstName": "Dev",
      "lastName": "Doctor"
    }
  },
  "facilities": {
    "shiftingCenter": "Dummy Shifting Center",
    "skillFacility": "Dummy Facility 40"
  }
}
cypress/e2e/users_spec/UsersCreation.cy.ts (3)

Line range hint 25-33: Replace Math.random() with a cryptographically secure alternative.

Using Math.random() for generating usernames could be predictable and potentially exploitable. Consider using crypto.getRandomValues() for better security.

 const makeId = (length: number) => {
   let result = "";
   const characters = "abcdefghijklmnopqrstuvwxyz0123456789";
-  const charactersLength = characters.length;
-  for (let i = 0; i < length; i++) {
-    result += characters.charAt(Math.floor(Math.random() * charactersLength));
-  }
+  const array = new Uint32Array(length);
+  crypto.getRandomValues(array);
+  for (let i = 0; i < length; i++) {
+    result += characters.charAt(array[i] % characters.length);
+  }
   return result;
 };
🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 17-17: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


[failure] 18-18: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


62-62: Fix typo in firstName constant value.

The word "Editted" is misspelled. It should be "Edited".

-const firstName = "District Editted";
+const firstName = "District Edited";

176-179: Improve error message verification reliability.

The error message verification could be more reliable by adding an explicit wait for the error messages to be visible before verifying them.

 userCreationPage.clickAddUserButton();
 userCreationPage.clickSaveUserButton();
-cy.get(".error-text", { timeout: 10000 }).should("be.visible");
+// Wait for all error messages to be visible
+cy.get(".error-text").should("have.length", EXPECTED_ERROR_MESSAGES.length).and("be.visible");
 userCreationPage.verifyErrorMessages(EXPECTED_ERROR_MESSAGES);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 66c8064 and cd7c551.

📒 Files selected for processing (5)
  • cypress/e2e/users_spec/UsersCreation.cy.ts (6 hunks)
  • cypress/e2e/users_spec/UsersManage.cy.ts (1 hunks)
  • cypress/e2e/users_spec/UsersProfile.cy.ts (1 hunks)
  • cypress/pageobject/Users/UserCreation.ts (1 hunks)
  • cypress/pageobject/Users/UserProfilePage.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • cypress/e2e/users_spec/UsersProfile.cy.ts
  • cypress/pageobject/Users/UserProfilePage.ts
🧰 Additional context used
📓 Learnings (3)
cypress/e2e/users_spec/UsersCreation.cy.ts (3)
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:16-59
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In the `cypress/pageobject/Users/UserCreation.ts` file, method parameter names may use a mix of `snake_case` and `camelCase` naming conventions, and this is acceptable in the codebase.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:31-42
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In `UserCreationPage` of `UserCreation.ts`, methods like `typePhoneNumber` and `typeUserPhoneNumber` target different input fields and are both necessary.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:3-5
Timestamp: 2024-11-15T05:22:27.913Z
Learning: In the `clickProfileName()` method of the `UserCreationPage` class, the profile name is dynamic and cannot be verified using a static text. Therefore, `cy.get("#user-profile-name").click();` should be used instead of `cy.verifyAndClickElement`.
cypress/e2e/users_spec/UsersManage.cy.ts (2)
Learnt from: Jacobjeevan
PR: ohcnetwork/care_fe#9080
File: cypress/pageobject/Users/ManageUserPage.ts:67-97
Timestamp: 2024-11-14T08:09:58.453Z
Learning: In Cypress test files (`cypress/pageobject/Users/ManageUserPage.ts`), when methods are called to check input provided earlier in the test, adding TypeScript interfaces, input validation, and custom error messages is unnecessary.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:3-5
Timestamp: 2024-11-15T05:22:27.913Z
Learning: In the `clickProfileName()` method of the `UserCreationPage` class, the profile name is dynamic and cannot be verified using a static text. Therefore, `cy.get("#user-profile-name").click();` should be used instead of `cy.verifyAndClickElement`.
cypress/pageobject/Users/UserCreation.ts (3)
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:31-42
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In `UserCreationPage` of `UserCreation.ts`, methods like `typePhoneNumber` and `typeUserPhoneNumber` target different input fields and are both necessary.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:3-5
Timestamp: 2024-11-15T05:22:27.913Z
Learning: In the `clickProfileName()` method of the `UserCreationPage` class, the profile name is dynamic and cannot be verified using a static text. Therefore, `cy.get("#user-profile-name").click();` should be used instead of `cy.verifyAndClickElement`.
Learnt from: AnveshNalimela
PR: ohcnetwork/care_fe#8930
File: cypress/pageobject/Users/UserCreation.ts:16-59
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In the `cypress/pageobject/Users/UserCreation.ts` file, method parameter names may use a mix of `snake_case` and `camelCase` naming conventions, and this is acceptable in the codebase.
🪛 GitHub Check: CodeQL
cypress/e2e/users_spec/UsersCreation.cy.ts

[failure] 17-17: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


[failure] 18-18: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.

🔇 Additional comments (8)
cypress/pageobject/Users/UserCreation.ts (2)

3-4: LGTM! Click methods use appropriate reusable commands.

The click methods correctly utilize reusable commands from commands.ts:

  • verifyAndClickElement for Add User button
  • clickSubmitButton for Save User button

Also applies to: 48-49


21-25: 🛠️ Refactor suggestion

Use cy.clearInput from commands.ts for consistency.

The clear methods should use the reusable command for better maintainability.

Apply this pattern to both clear methods:

  clearFirstName() {
-   cy.get("#firstName").click().clear();
+   cy.clearInput("#firstName");
  }

Likely invalid or redundant comment.

cypress/e2e/users_spec/UsersManage.cy.ts (2)

49-51: LGTM! Good use of reusable component.

The change from userCreationPage.verifyElementContainsText to cy.verifyContentPresence aligns well with the PR's objective of utilizing reusable components from commands.ts.


49-51: Verify the custom command implementation.

Let's ensure the verifyContentPresence command is properly implemented in commands.ts.

✅ Verification successful

Custom command verifyContentPresence is properly implemented

The command is correctly implemented in cypress/support/commands.ts with proper TypeScript support. It:

  • Takes a selector and an array of texts as parameters
  • Uses cy.get() to find elements by selector
  • Verifies each text in the array is present within the found element
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if verifyContentPresence is properly implemented in commands.ts
# Expected: Should find the command definition with proper TypeScript types

# Search for verifyContentPresence command definition
echo "Searching for verifyContentPresence command definition..."
rg -A 5 "verifyContentPresence" "cypress/support/commands.ts"

# Search for any direct usage of cy.get with username-profile-details
echo "Checking for any direct DOM queries that could be consolidated..."
rg "cy\.get.*username-profile-details"

Length of output: 558

cypress/e2e/users_spec/UsersCreation.cy.ts (4)

Line range hint 1-21: LGTM! Clean setup with proper page object instantiation.

The imports are well-organized and the page objects are correctly instantiated following the Page Object Model pattern.

🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 17-17: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


[failure] 18-18: Insecure randomness
This uses a cryptographically insecure random number generated at Math.random() in a security context.


Line range hint 81-92: LGTM! Well-structured test lifecycle hooks.

The hooks properly handle authentication and local storage management.


110-112: LGTM! Proper API interception implementation.

The API calls are properly intercepted and verified, following Cypress best practices for handling asynchronous operations.


142-172: LGTM! Well-structured user creation test.

The test follows a clear arrangement of actions and assertions, with proper API interception and comprehensive verification of the created user's details.

Comment on lines +44 to +45
selectFacility(name: string) {
cy.typeAndSelectOption("input[name='facilities']", name);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use typeAndMultiSelectOption for facility selection.

As suggested in the past reviews, facility selection should use the multi-select option command.

  selectFacility(name: string) {
-   cy.typeAndSelectOption("input[name='facilities']", name);
+   cy.typeAndMultiSelectOption("input[name='facilities']", name);
  }
📝 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
selectFacility(name: string) {
cy.typeAndSelectOption("input[name='facilities']", name);
selectFacility(name: string) {
cy.typeAndMultiSelectOption("input[name='facilities']", name);

Comment on lines +37 to +41
selectState(state: string) {
cy.clickAndSelectOption("#state", state);
}
selectDistrict(district: string) {
cy.clickAndSelectOption("#district", district);
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Based on the search results, I can generate the final response:

Update selectors to match the actual DOM elements

The current selectors #state and #district need to be updated. From the codebase search results, particularly in cypress/pageobject/Users/UserSearch.ts, the correct selectors are:

  • #state input for state selection
  • #district input for district selection

These elements appear to be autocomplete inputs rather than simple dropdowns.

🔗 Analysis chain

Verify state and district element IDs.

The selectors #state and #district might need to be updated to match the actual element IDs in the DOM.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the correct element IDs for state and district dropdowns
echo "Searching for state and district element IDs..."
rg -A 2 'id=["\'](state|district)["\']' src/

Length of output: 332


Script:

#!/bin/bash
# Search for state and district element IDs in all files
rg -A 2 'id=["\'']?(state|district)["\'']?' 

# Search for any React/JSX components that might contain state or district dropdowns
ast-grep --pattern 'Select id="$_" $$$'

# Search for any form fields or components with state or district in their name
rg -i "(state|district).*(select|dropdown|field|input)"

Length of output: 14898

Comment on lines +6 to +19
typeUserName(username: string) {
cy.get("#username").click().type(username);
}

typeIntoElementByIdPostClear(elementId: string, value: string) {
cy.get("#" + elementId)
.click()
.clear()
.click()
.type(value);
typeFirstName(firstName: string) {
cy.get("#firstName").click().type(firstName);
}
typeIntoElementByIdPostClearDob(elementId: string, value: string) {
cy.clickAndTypeDate("#" + elementId, value);
typeLastName(lastName: string) {
cy.get("#lastName").click().type(lastName);
}
clearIntoElementById(elementId: string) {
cy.get("#" + elementId)
.click()
.clear();
typePassword(password: string) {
cy.get("#password").click().type(password);
}

typeIntoInputByName(inputName: string, value: string) {
cy.get("input[name='" + inputName + "']")
.click()
.type(value);
typeConfirmPassword(password: string) {
cy.get("#c_password").click().type(password);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use cy.typeIntoInput from commands.ts for consistency.

The type methods should use the reusable command for better maintainability.

Apply this pattern to all type methods:

  typeUserName(username: string) {
-   cy.get("#username").click().type(username);
+   cy.typeIntoInput("#username", username);
  }

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

Copy link
Contributor

@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: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between cd7c551 and 360c540.

📒 Files selected for processing (1)
  • cypress/pageobject/utils/constants.ts (1 hunks)
🔇 Additional comments (1)
cypress/pageobject/utils/constants.ts (1)

8-9: Consider the necessity of a separate emergency phone function

The current implementation doesn't differentiate emergency numbers from regular phone numbers. Consider either:

  1. Adding distinct validation/formatting for emergency contacts, or
  2. Removing this wrapper function if no special handling is needed

Comment on lines +1 to +5
export function generatePhoneNumber(): string {
const array = new Uint32Array(1);
window.crypto.getRandomValues(array);
const randomNum = (array[0] % 900000000) + 100000000;
return "9" + randomNum.toString();
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling and improve code clarity

While the switch to crypto.getRandomValues() is a good security improvement, consider these enhancements:

+const PHONE_PREFIX = '9';
+const MIN_PHONE_LENGTH = 9;
+
 export function generatePhoneNumber(): string {
+  try {
+    if (!window.crypto || !window.crypto.getRandomValues) {
+      throw new Error('Crypto API not supported');
+    }
     const array = new Uint32Array(1);
     window.crypto.getRandomValues(array);
-    const randomNum = (array[0] % 900000000) + 100000000;
-    return "9" + randomNum.toString();
+    // Ensure exactly 9 digits (excluding prefix)
+    const randomNum = (array[0] % 900000000) + 100000000;
+    return PHONE_PREFIX + randomNum.toString();
+  } catch (error) {
+    Cypress.log({
+      name: 'Phone Generation Error',
+      message: error.message
+    });
+    throw error;
+  }
 }
📝 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 function generatePhoneNumber(): string {
const array = new Uint32Array(1);
window.crypto.getRandomValues(array);
const randomNum = (array[0] % 900000000) + 100000000;
return "9" + randomNum.toString();
const PHONE_PREFIX = '9';
const MIN_PHONE_LENGTH = 9;
export function generatePhoneNumber(): string {
try {
if (!window.crypto || !window.crypto.getRandomValues) {
throw new Error('Crypto API not supported');
}
const array = new Uint32Array(1);
window.crypto.getRandomValues(array);
// Ensure exactly 9 digits (excluding prefix)
const randomNum = (array[0] % 900000000) + 100000000;
return PHONE_PREFIX + randomNum.toString();
} catch (error) {
Cypress.log({
name: 'Phone Generation Error',
message: error.message
});
throw error;
}
}

Copy link
Contributor

@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: 0

🧹 Outside diff range and nitpick comments (2)
cypress/e2e/facility_spec/FacilityLocation.cy.ts (2)

39-39: Consider using a more descriptive constant name

The constant name duplicateBedName implies it's used for testing duplicate bed scenarios, but it's actually used for bed modification testing. Consider renaming it to modifiedBedName or updatedBedName to better reflect its purpose.


Line range hint 71-109: Consider breaking down the large test case into smaller, focused tests

The test case "Add a Bed to facility location along with duplication and deleting a bed" combines multiple scenarios:

  1. Mandatory field validation
  2. Single bed creation
  3. Duplicate bed validation
  4. Bed modification

Consider splitting these into separate test cases for better maintainability and clearer failure isolation. This aligns with testing best practices where each test should verify a single piece of functionality.

Example structure:

it("should validate mandatory fields for bed creation")
it("should successfully create a single bed")
it("should prevent creation of duplicate beds")
it("should successfully modify existing bed details")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e24c032 and 5bf8c5d.

📒 Files selected for processing (1)
  • cypress/e2e/facility_spec/FacilityLocation.cy.ts (2 hunks)
🧰 Additional context used
📓 Learnings (1)
cypress/e2e/facility_spec/FacilityLocation.cy.ts (2)
Learnt from: Jacobjeevan
PR: ohcnetwork/care_fe#9145
File: cypress/e2e/facility_spec/FacilityHomepage.cy.ts:229-317
Timestamp: 2024-11-18T10:46:56.271Z
Learning: In `cypress/e2e/facility_spec/FacilityHomepage.cy.ts`, when verifying the bed capacity badge reflection, the badge remains the same during multiple actions and only updates after a bed is attached to a patient during consultation. Therefore, it's appropriate to keep the test case consolidated rather than splitting it into smaller tests.
Learnt from: Jacobjeevan
PR: ohcnetwork/care_fe#9145
File: cypress/e2e/facility_spec/FacilityCreation.cy.ts:177-180
Timestamp: 2024-11-18T10:44:30.303Z
Learning: In `cypress/e2e/facility_spec/FacilityCreation.cy.ts`, when testing bed and staff capacity individually for additional error verification, we prefer to use separate method calls to handle bed and staff capacity, rather than using `facilityPage.createNewFacility(testFacilityData)` which also handles bed management.
🔇 Additional comments (2)
cypress/e2e/facility_spec/FacilityLocation.cy.ts (2)

Line range hint 1-277: Implementation looks good overall!

The changes maintain the existing test coverage while updating the bed modification scenario. The code follows good testing practices with proper use of Page Object Model, appropriate assertions, and comprehensive error handling.


100-107: Verify the test coverage for bed name modification

The test case modifies a bed's name to "ICCU" but doesn't explicitly verify that this isn't a duplicate name in the system. Consider adding a verification step to ensure the bed name modification succeeds without any duplicate name conflicts.

Additionally, consider adding the following test scenarios:

  1. Attempt to modify a bed name to an existing name
  2. Verify appropriate error messages for duplicate bed names during modification

@nihal467 nihal467 added tested reviewed reviewed by a core member and removed needs review labels Nov 29, 2024
@khavinshankar khavinshankar merged commit 59cc025 into ohcnetwork:develop Nov 30, 2024
21 checks passed
Copy link

@AnveshNalimela Your efforts have helped advance digital healthcare and TeleICU systems. 🚀 Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
reviewed reviewed by a core member tested
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor Phone number generation logic in cypress to handle security concern raised by codeQL
6 participants