diff --git a/cypress/e2e/facility_spec/facility_creation.cy.ts b/cypress/e2e/facility_spec/facility_creation.cy.ts new file mode 100644 index 00000000000..a62f4ec77c5 --- /dev/null +++ b/cypress/e2e/facility_spec/facility_creation.cy.ts @@ -0,0 +1,67 @@ +import { LoginPage } from "../../pageObject/auth/LoginPage"; +import { FacilityCreation } from "../../pageObject/facility/FacilityCreation"; +import { generatePhoneNumber } from "../../utils/commonUtils"; +import { generateFacilityData } from "../../utils/facilityData"; + +describe("Facility Management", () => { + const loginPage = new LoginPage(); + const facilityPage = new FacilityCreation(); + const testFacility = generateFacilityData(); + const phoneNumber = generatePhoneNumber(); + + beforeEach(() => { + cy.clearLocalStorage(); + cy.saveLocalStorage(); + cy.visit("/login"); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); + + it("Create a new facility using the admin role", () => { + // Login + loginPage.loginByRole("admin"); + // Navigate to facility creation + facilityPage.navigateToFacilities(); + facilityPage.clickAddFacility(); + + // Fill form + facilityPage.fillBasicDetails( + testFacility.name, + testFacility.type, + testFacility.description, + ); + + facilityPage.selectFeatures(testFacility.features); + + facilityPage.fillContactDetails( + phoneNumber, + testFacility.pincode, + testFacility.address, + ); + + facilityPage.fillLocationDetails( + testFacility.coordinates.latitude, + testFacility.coordinates.longitude, + ); + + // Submit and verify + facilityPage.makePublicFacility(); + facilityPage.submitFacilityCreationForm(); + facilityPage.verifySuccessMessage(); + + // Search for the facility and verify in card + facilityPage.searchFacility(testFacility.name); + facilityPage.verifyFacilityNameInCard(testFacility.name); + }); + + it("Should show validation errors for required fields", () => { + loginPage.loginByRole("nurse"); + + facilityPage.navigateToFacilities(); + facilityPage.clickAddFacility(); + facilityPage.submitFacilityCreationForm(); + facilityPage.verifyValidationErrors(); + }); +}); diff --git a/cypress/pageObject/auth/LoginPage.ts b/cypress/pageObject/auth/LoginPage.ts index ada53b61d3a..8509b2b448a 100644 --- a/cypress/pageObject/auth/LoginPage.ts +++ b/cypress/pageObject/auth/LoginPage.ts @@ -7,13 +7,6 @@ export class LoginPage { return cy.intercept("POST", this.routes.login).as("loginRequest"); } - verifyLoginResponse() { - return cy - .wait("@loginRequest") - .its("response.statusCode") - .should("eq", 200); - } - // Add selectors for existing elements private readonly usernameInput = "[data-cy=username]"; private readonly passwordInput = "[data-cy=password]"; diff --git a/cypress/pageObject/facility/FacilityCreation.ts b/cypress/pageObject/facility/FacilityCreation.ts new file mode 100644 index 00000000000..ec7863834bf --- /dev/null +++ b/cypress/pageObject/facility/FacilityCreation.ts @@ -0,0 +1,100 @@ +export class FacilityCreation { + // Navigation + navigateToFacilities() { + cy.get('[data-cy="organization-list"]').should("be.visible"); + cy.verifyAndClickElement('[data-cy="organization-list"]', "Kerala"); + cy.get('[data-testid="org-nav-facilities"]').should("be.visible").click(); + } + + clickAddFacility() { + cy.get('[data-cy="add-facility-button"]').should("be.visible").click(); + } + + // Individual field methods + enterFacilityName(name: string) { + cy.get('[data-cy="facility-name"]').type(name); + } + + selectFacilityType() { + cy.clickAndSelectOption( + '[data-cy="facility-type"]', + "Primary Health Centres", + ); + } + + enterDescription(description: string) { + cy.get('[data-cy="facility-description"]').type(description); + } + + enterPhoneNumber(phone: string) { + cy.get('[data-cy="facility-phone"]').type(phone); + } + + enterPincode(pincode: string) { + cy.get('[data-cy="facility-pincode"]').type(pincode); + } + + enterAddress(address: string) { + cy.get('[data-cy="facility-address"]').type(address); + } + + enterLatitude(latitude: string) { + cy.get('[data-cy="facility-latitude"]').type(latitude); + } + + enterLongitude(longitude: string) { + cy.get('[data-cy="facility-longitude"]').type(longitude); + } + + // Combined methods using individual functions + fillBasicDetails(name: string, _facilityType: string, description: string) { + this.enterFacilityName(name); + this.selectFacilityType(); + this.enterDescription(description); + } + + selectFeatures(features: string[]) { + cy.clickAndMultiSelectOption("#facility-features", features); + } + + fillContactDetails(phone: string, pincode: string, address: string) { + this.enterPhoneNumber(phone); + this.enterPincode(pincode); + this.enterAddress(address); + } + + fillLocationDetails(latitude: string, longitude: string) { + this.enterLatitude(latitude); + this.enterLongitude(longitude); + } + + makePublicFacility() { + cy.get('[data-cy="make-facility-public"]').click(); + } + + submitFacilityCreationForm() { + cy.clickSubmitButton("Create Facility"); + } + + // Verification Methods + verifySuccessMessage() { + cy.verifyNotification("Facility created successfully"); + } + + verifyValidationErrors() { + cy.verifyErrorMessage("Name is required"); + cy.verifyErrorMessage("Facility type is required"); + cy.verifyErrorMessage("Address is required"); + cy.verifyErrorMessage( + "Phone number must start with +91 followed by 10 digits", + ); + } + + searchFacility(facilityName: string) { + cy.get('[data-cy="search-facility"]').type(facilityName); + } + + verifyFacilityNameInCard(facilityName: string) { + cy.get('[data-cy="facility-cards"]').should("contain", facilityName); + } +} diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 54bc3be2666..d4098de2fac 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -113,8 +113,11 @@ Cypress.Commands.add( }, ); -Cypress.Commands.add("verifyNotification", (text) => { - return cy.get(".pnotify-container").should("exist").contains(text); +Cypress.Commands.add("verifyNotification", (text: string) => { + return cy + .get("li[data-sonner-toast] div[data-title]") + .should("exist") + .contains(text); }); Cypress.Commands.add("clearAllFilters", () => { diff --git a/cypress/utils/commonUtils.ts b/cypress/utils/commonUtils.ts new file mode 100644 index 00000000000..5e2037dc123 --- /dev/null +++ b/cypress/utils/commonUtils.ts @@ -0,0 +1,11 @@ +export function generatePhoneNumber(): string { + // First digit should be 6, 7, 8, or 9 for Indian mobile numbers + const validFirstDigits = [6, 7, 8, 9]; + const firstDigit = + validFirstDigits[Math.floor(Math.random() * validFirstDigits.length)]; + + // Generate remaining 9 digits + const remainingDigits = Math.random().toString().slice(2, 11); + + return `${firstDigit}${remainingDigits}`; +} diff --git a/cypress/utils/facilityData.ts b/cypress/utils/facilityData.ts new file mode 100644 index 00000000000..9f1463ffd6e --- /dev/null +++ b/cypress/utils/facilityData.ts @@ -0,0 +1,180 @@ +interface FacilityTestData { + name: string; + type: string; + description: string; + address: string; + pincode: string; + coordinates: { + latitude: string; + longitude: string; + }; + features: string[]; +} + +const FACILITY_FEATURES = [ + "CT Scan", + "Maternity Care", + "X-Ray", + "Neonatal Care", + "Operation Theater", + "Blood Bank", + "Emergency Services", +]; + +// Facility type prefixes +const facilityPrefixes = [ + "GHC", // Government Hospital + "PHC", // Primary Health Center + "CHC", // Community Health Center + "THC", // Taluk Hospital + "DH", // District Hospital +]; + +// Special institution prefixes +const specialPrefixes = [ + "Saint Maria", + "Holy Cross", + "Little Flower", + "Mar Sleeva", + "Saint Thomas", +]; + +// Ernakulam district locations with real coordinates +const locations = [ + { + name: "Aluva", + pincode: "683101", + coordinates: { latitude: "10.1004", longitude: "76.3570" }, + }, + { + name: "Angamaly", + pincode: "683572", + coordinates: { latitude: "10.1960", longitude: "76.3860" }, + }, + { + name: "Kalady", + pincode: "683574", + coordinates: { latitude: "10.1682", longitude: "76.4410" }, + }, + { + name: "Perumbavoor", + pincode: "683542", + coordinates: { latitude: "10.1071", longitude: "76.4750" }, + }, + { + name: "Kothamangalam", + pincode: "686691", + coordinates: { latitude: "10.0558", longitude: "76.6280" }, + }, + { + name: "Muvattupuzha", + pincode: "686661", + coordinates: { latitude: "9.9894", longitude: "76.5790" }, + }, + { + name: "Piravom", + pincode: "686664", + coordinates: { latitude: "9.8730", longitude: "76.4920" }, + }, + { + name: "Kolenchery", + pincode: "682311", + coordinates: { latitude: "9.9811", longitude: "76.4007" }, + }, + { + name: "Tripunithura", + pincode: "682301", + coordinates: { latitude: "9.9486", longitude: "76.3289" }, + }, + { + name: "Kakkanad", + pincode: "682030", + coordinates: { latitude: "10.0158", longitude: "76.3419" }, + }, + { + name: "Edappally", + pincode: "682024", + coordinates: { latitude: "10.0236", longitude: "76.3097" }, + }, + { + name: "Kaloor", + pincode: "682017", + coordinates: { latitude: "9.9894", longitude: "76.2998" }, + }, + { + name: "Fort Kochi", + pincode: "682001", + coordinates: { latitude: "9.9639", longitude: "76.2432" }, + }, + { + name: "Mattancherry", + pincode: "682002", + coordinates: { latitude: "9.9585", longitude: "76.2574" }, + }, + { + name: "Vytilla", + pincode: "682019", + coordinates: { latitude: "9.9712", longitude: "76.3186" }, + }, + { + name: "Palarivattom", + pincode: "682025", + coordinates: { latitude: "10.0070", longitude: "76.3050" }, + }, + { + name: "Thevara", + pincode: "682013", + coordinates: { latitude: "9.9312", longitude: "76.2891" }, + }, + { + name: "Thrikkakara", + pincode: "682021", + coordinates: { latitude: "10.0316", longitude: "76.3421" }, + }, + { + name: "Kalamassery", + pincode: "683104", + coordinates: { latitude: "10.0558", longitude: "76.3213" }, + }, + { + name: "Eloor", + pincode: "683501", + coordinates: { latitude: "10.0583", longitude: "76.2833" }, + }, +]; + +function generateFacilityName(): string { + const useSpecialPrefix = Math.random() < 0.2; // 20% chance for special prefix + const location = locations[Math.floor(Math.random() * locations.length)]; + + if (useSpecialPrefix) { + const specialPrefix = + specialPrefixes[Math.floor(Math.random() * specialPrefixes.length)]; + return `${specialPrefix} GHC ${location.name}`; + } else { + const prefix = + facilityPrefixes[Math.floor(Math.random() * facilityPrefixes.length)]; + return `${prefix} ${location.name}`; + } +} + +export function generateFacilityData(): FacilityTestData { + const location = locations[Math.floor(Math.random() * locations.length)]; + const name = generateFacilityName(); + + // Randomly select 2-4 features from the available options + const shuffledFeatures = [...FACILITY_FEATURES].sort( + () => Math.random() - 0.5, + ); + const numberOfFeatures = Math.floor(Math.random() * 3) + 2; // Random number between 2 and 4 + + return { + name, + type: "General Hospital", + description: `Healthcare facility serving the ${location.name} region with modern medical facilities and experienced staff`, + address: `${name} Building, Main Road, ${location.name}`, + pincode: location.pincode, + coordinates: location.coordinates, + features: shuffledFeatures.slice(0, numberOfFeatures), + }; +} diff --git a/public/locale/en.json b/public/locale/en.json index 5008b13f928..d5498dbe0f6 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -923,6 +923,7 @@ "external_identifier": "External Identifier", "facilities": "Facilities", "facility": "Facility", + "facility_added_successfully": "Facility created successfully", "facility_consent_requests_page_title": "Patient Consent List", "facility_district_name": "Facility/District Name", "facility_district_pincode": "Facility/District/Pincode", diff --git a/src/components/Facility/CreateFacilityForm.tsx b/src/components/Facility/CreateFacilityForm.tsx index 8ad9887d2ef..ed5c87caabc 100644 --- a/src/components/Facility/CreateFacilityForm.tsx +++ b/src/components/Facility/CreateFacilityForm.tsx @@ -177,13 +177,17 @@ export default function CreateFacilityForm({ Facility Type + @@ -218,6 +226,7 @@ export default function CreateFacilityForm({