diff --git a/cypress/e2e/facility_spec/facility_creation.cy.ts b/cypress/e2e/facility_spec/facility_creation.cy.ts index 9725ed42a28..f8001584ac3 100644 --- a/cypress/e2e/facility_spec/facility_creation.cy.ts +++ b/cypress/e2e/facility_spec/facility_creation.cy.ts @@ -221,7 +221,6 @@ describe("Facility Creation", () => { .should("be.visible"); // verify the facility homepage cy.visit("/facility"); - cy.get("#removeicon").click(); manageUserPage.typeFacilitySearch(facilityName); facilityPage.verifyFacilityBadgeContent(facilityName); manageUserPage.assertFacilityInCard(facilityName); diff --git a/cypress/e2e/facility_spec/locations.cy.ts b/cypress/e2e/facility_spec/locations.cy.ts index 59651c7c7c9..26364048ca2 100644 --- a/cypress/e2e/facility_spec/locations.cy.ts +++ b/cypress/e2e/facility_spec/locations.cy.ts @@ -1,6 +1,42 @@ import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; +import { AssetPage } from "../../pageobject/Asset/AssetCreation"; +import { UserCreationPage } from "../../pageobject/Users/UserCreation"; +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; +import FacilityLocation from "../../pageobject/Facility/FacilityLocation"; +// import { AssetPagination } from "../../pageobject/Asset/AssetPagination"; describe("Location Management Section", () => { + const assetPage = new AssetPage(); + const userCreationPage = new UserCreationPage(); + const facilityPage = new FacilityPage(); + const facilityLocation = new FacilityLocation(); + // const assetPagination = new AssetPagination(); + const EXPECTED_LOCATION_ERROR_MESSAGES = [ + "Name is required", + "Location Type is required", + ]; + const EXPECTED_BED_ERROR_MESSAGES = [ + "Please enter a name", + "Please select a bed type", + ]; + const locationName = "Test-location"; + const locationDescription = "Test Description"; + const locationType = "WARD"; + const locationMiddleware = "dev_middleware.coronasafe.live"; + const locationModifiedName = "Test Modified location"; + const locationModifiedDescription = "Test Modified Description"; + const locationModifiedType = "ICU"; + const locationModifiedMiddleware = "dev-middleware.coronasafe.live"; + const bedName = "Test Bed"; + const bedDescrption = "test description"; + const bedType = "ICU"; + const bedStatus = "Vacant"; + const bedModifiedName = "test modified bed"; + const bedModifiedDescrption = "test modified description"; + const bedModifiedType = "Isolation"; + const numberOfBeds = 10; + // const numberOfModifiedBeds = 25; + before(() => { cy.loginByApi("devdistrictadmin", "Coronasafe@123"); cy.saveLocalStorage(); @@ -20,28 +56,95 @@ describe("Location Management Section", () => { cy.get("[id=location-management]").click(); }); - it("Adds Location", () => { - cy.contains("Add New Location").click(); - cy.get("[name='name']").type("Test Location"); - cy.get("textarea[name='description']").type("Test Description"); - cy.get("#location-type").click(); - cy.get("#location-type-option-ICU").click(); - cy.intercept(/\/api\/v1\/facility\/[\w-]+\/asset_location\//).as( - "addLocation" - ); - cy.get("button").contains("Add Location").click(); - cy.wait("@addLocation").then((interception) => { - switch (interception?.response?.statusCode) { - case 201: - cy.verifyNotification("Location created successfully"); - return; - case 400: - cy.verifyNotification( - "Name - Asset location with this name and facility already exists." - ); - return; - } - }); + it("Adds Location to a facility and modify it", () => { + // add a new location form mandatory error + facilityLocation.clickAddNewLocationButton(); + assetPage.clickassetupdatebutton(); + userCreationPage.verifyErrorMessages(EXPECTED_LOCATION_ERROR_MESSAGES); + // create a new location + facilityPage.fillFacilityName(locationName); + facilityLocation.fillDescription(locationDescription); + facilityLocation.selectLocationType(locationType); + facilityLocation.fillMiddlewareAddress(locationMiddleware); + assetPage.clickassetupdatebutton(); + // verify the reflection + facilityLocation.verifyLocationName(locationName); + facilityLocation.verifyLocationType(locationType); + facilityLocation.verifyLocationDescription(locationDescription); + facilityLocation.verifyLocationMiddleware(locationMiddleware); + // modify the existing data + facilityLocation.clickEditLocationButton(); + facilityPage.fillFacilityName(locationModifiedName); + facilityLocation.fillDescription(locationModifiedDescription); + facilityLocation.selectLocationType(locationModifiedType); + facilityLocation.fillMiddlewareAddress(locationModifiedMiddleware); + assetPage.clickassetupdatebutton(); + // verify the reflection + facilityLocation.verifyLocationName(locationModifiedName); + facilityLocation.verifyLocationType(locationModifiedType); + facilityLocation.verifyLocationDescription(locationModifiedDescription); + facilityLocation.verifyLocationMiddleware(locationModifiedMiddleware); + }); + + it("Add Multiple Bed to a facility location and delete a bed", () => { + // create multiple bed and verify + facilityLocation.clickManageBedButton(); + facilityLocation.clickAddBedButton(); + facilityLocation.enterBedName(bedName); + facilityLocation.enterBedDescription(bedDescrption); + facilityLocation.selectBedType(bedType); + facilityLocation.setMultipleBeds(numberOfBeds); + assetPage.clickassetupdatebutton(); + // verify the bed creation + facilityLocation.verifyBedBadge(bedType); + facilityLocation.verifyBedBadge(bedStatus); + facilityLocation.verifyIndividualBedName(bedName, numberOfBeds); + // delete a bed and verify it + facilityLocation.deleteFirstBed(); + facilityLocation.deleteBedRequest(); + assetPage.clickassetupdatebutton(); + facilityLocation.deleteBedRequest(); + }); + + // it("Add Multiple Bed to a facility location and verify pagination", () => { + // // bed creation + // facilityLocation.clickManageBedButton(); + // facilityLocation.clickAddBedButton(); + // facilityLocation.enterBedName(bedModifiedName); + // facilityLocation.enterBedDescription(bedModifiedDescrption); + // facilityLocation.selectBedType(bedModifiedType); + // facilityLocation.setMultipleBeds(numberOfModifiedBeds); + // assetPage.clickassetupdatebutton(); + // // pagination + // assetPagination.navigateToNextPage(); + // assetPagination.navigateToPreviousPage(); + // }); need to be unblocked upon issue #6906 is solved + + it("Add Single Bed to a facility location and modify it", () => { + // mandatory field verification in bed creation + facilityLocation.clickManageBedButton(); + facilityLocation.clickAddBedButton(); + assetPage.clickassetupdatebutton(); + userCreationPage.verifyErrorMessages(EXPECTED_BED_ERROR_MESSAGES); + // create a new single bed and verify + facilityLocation.enterBedName(bedName); + facilityLocation.enterBedDescription(bedDescrption); + facilityLocation.selectBedType(bedType); + assetPage.clickassetupdatebutton(); + // Verify the bed creation + facilityLocation.verifyBedNameBadge(bedName); + facilityLocation.verifyBedBadge(bedType); + facilityLocation.verifyBedBadge(bedStatus); + // edit the created bed + facilityLocation.clickEditBedButton(); + facilityLocation.enterBedName(bedModifiedName); + facilityLocation.enterBedDescription(bedModifiedDescrption); + facilityLocation.selectBedType(bedModifiedType); + assetPage.clickassetupdatebutton(); + // verify the modification + facilityLocation.verifyBedNameBadge(bedModifiedName); + facilityLocation.verifyBedBadge(bedModifiedType); + facilityLocation.verifyBedBadge(bedStatus); }); afterEach(() => { diff --git a/cypress/pageobject/Facility/FacilityLocation.ts b/cypress/pageobject/Facility/FacilityLocation.ts new file mode 100644 index 00000000000..d3eebdaf4ff --- /dev/null +++ b/cypress/pageobject/Facility/FacilityLocation.ts @@ -0,0 +1,105 @@ +class FacilityLocation { + clickAddNewLocationButton() { + cy.get("#add-new-location").click(); + } + + clickEditLocationButton() { + cy.get("#edit-location-button").click(); + } + + clickEditBedButton() { + cy.get("#edit-bed-button").click(); + } + + fillDescription(description: string) { + cy.get("#description").clear().click().type(description); + } + + selectLocationType(type: string) { + cy.get("#location-type").click(); + cy.get("li[role=option]").contains(type).click(); + } + + fillMiddlewareAddress(address: string) { + cy.get("#location-middleware-address").clear().click().type(address); + } + + verifyLocationName(name: string) { + cy.get("#view-location-name").contains(name); + } + + verifyLocationType(type: string) { + cy.get("#location-type").contains(type); + } + + verifyLocationDescription(description: string) { + cy.get("#view-location-description").contains(description); + } + + verifyLocationMiddleware(middleware: string) { + cy.get("#view-location-middleware").contains(middleware); + } + + clickManageBedButton() { + cy.get("#manage-bed-button").first().click(); + } + + clickAddBedButton() { + cy.get("#add-new-bed").click(); + } + + enterBedName(name: string) { + cy.get("#bed-name").clear().click().type(name); + } + + enterBedDescription(description: string) { + cy.get("#bed-description").clear().click().type(description); + } + + selectBedType(type: string) { + cy.get("#bed-type").click(); + cy.get("li[role=option]").contains(type).click(); + } + + setMultipleBeds(numberOfBeds: number) { + if (numberOfBeds > 1) { + cy.get("#multiplebed-checkbox").click(); + cy.get("#numberofbed") + .click() + .clear() + .click() + .type(numberOfBeds.toString()); + } + } + + verifyBedBadge(badge: string) { + cy.get("#view-bedbadges").contains(badge); + } + + verifyBedNameBadge(name: string) { + cy.get("#view-bed-name").contains(name); + } + + verifyIndividualBedName(baseName: string, totalBeds: number) { + for (let i = 1; i <= totalBeds; i++) { + const expectedName = `${baseName} ${i}`; + cy.get("p#view-bed-name.inline.break-words.text-xl.capitalize") + .should("be.visible") + .contains(expectedName); + } + } + + deleteFirstBed() { + cy.get("#delete-bed-button").first().click(); + } + + deleteBedRequest() { + cy.intercept("DELETE", "**/api/v1/bed/**").as("deleteRequest"); + } + + deleteBedResponse() { + cy.wait("@deleteRequest").its("response.statusCode").should("eq", 204); + } +} + +export default FacilityLocation; diff --git a/src/Common/hooks/useFilters.tsx b/src/Common/hooks/useFilters.tsx index a62180c8a29..5781eaca54f 100644 --- a/src/Common/hooks/useFilters.tsx +++ b/src/Common/hooks/useFilters.tsx @@ -33,28 +33,24 @@ export default function useFilters({ limit = 14 }: { limit?: number }) { if (!hasPagination) return; setQueryParams(Object.assign({}, qParams, { page }), { replace: true }); }; - const removeFilter = (param: string) => updateQuery({ [param]: "" }); - const removeFilters = (keys: string[]) => - updateQuery(keys.reduce((acc, key) => ({ ...acc, [key]: "" }), qParams)); + const removeFilters = (params: string[]) => { + setQueryParams(removeFromQuery(qParams, params)); + }; + const removeFilter = (param: string) => removeFilters([param]); - useEffect(() => { - const localFilters = JSON.parse( - localStorage.getItem("filters--" + window.location.pathname) || "{}" - ); - const blacklistLocalFilters = ["page", "limit", "offset"]; - const newFilters = { ...localFilters, ...qParams }; - const filteredNewFilters = blacklistLocalFilters.reduce( - (acc, key) => ({ ...acc, [key]: undefined }), - newFilters - ); + useEffect(() => updateFiltersCache(qParams), [qParams]); - localStorage.setItem( - "filters--" + window.location.pathname, - JSON.stringify(filteredNewFilters) + useEffect(() => { + const cache = getFiltersCache(); + const qParamKeys = Object.keys(qParams); + const canSkip = Object.keys(cache).every( + (key) => qParamKeys.includes(key) && qParams[key] === cache[key] ); - - updateQuery(newFilters); - }, [qParams]); + if (canSkip) return; + if (Object.keys(cache).length) { + setQueryParams(cache); + } + }, []); const FilterBadge = ({ name, value, paramKey }: FilterBadgeProps) => { if (Array.isArray(paramKey)) @@ -174,7 +170,8 @@ export default function useFilters({ limit = 14 }: { limit?: number }) { id="clear-all-filters" className="rounded-full border border-gray-300 bg-white px-2 py-1 text-xs text-gray-600 hover:text-gray-800" onClick={() => { - removeFilters(activeFilters); + updateFiltersCache({}); + removeFilters(Object.keys(qParams)); }} > {t("clear_all_filters")} @@ -254,3 +251,25 @@ export default function useFilters({ limit = 14 }: { limit?: number }) { }, }; } + +const removeFromQuery = (query: Record, params: string[]) => { + const result = { ...query }; + for (const param of params) { + delete result[param]; + } + return result; +}; + +const FILTERS_CACHE_BLACKLIST = ["page", "limit", "offset"]; + +const getFiltersCacheKey = () => `filters--${window.location.pathname}`; +const getFiltersCache = () => { + return JSON.parse(localStorage.getItem(getFiltersCacheKey()) || "{}"); +}; +const updateFiltersCache = (cache: Record) => { + const result = { ...cache }; + for (const param of FILTERS_CACHE_BLACKLIST) { + delete result[param]; + } + localStorage.setItem(getFiltersCacheKey(), JSON.stringify(result)); +}; diff --git a/src/Components/Facility/AddBedForm.tsx b/src/Components/Facility/AddBedForm.tsx index 2fcda7a7a54..931a95da6a2 100644 --- a/src/Components/Facility/AddBedForm.tsx +++ b/src/Components/Facility/AddBedForm.tsx @@ -183,13 +183,14 @@ export const AddBedForm = (props: BedFormProps) => { name="name" type="text" label="Name" - id="name" + id="bed-name" required value={name} onChange={(e) => setName(e.value)} error={errors.name} /> { {!bedId && ( <> { if (multipleBeds) setNumberOfBeds(1); @@ -223,6 +225,7 @@ export const AddBedForm = (props: BedFormProps) => { name={"multipleBeds"} /> {
{ >
-

{name}

{" "} +

+ {name} +

{" "}   -
+
{LOCATION_BED_TYPES.find((item) => item.id === bedType) && (

{LOCATION_BED_TYPES.find( @@ -119,6 +124,7 @@ const BedRow = (props: BedRowProps) => {

{ Edit handleDelete(name, id)} authorizeFor={NonReadOnlyUsers} variant="danger" @@ -272,6 +279,7 @@ export const BedManagement = (props: BedManagementProps) => {
diff --git a/src/Components/Facility/LocationManagement.tsx b/src/Components/Facility/LocationManagement.tsx index d378dbf9953..b7a758c5055 100644 --- a/src/Components/Facility/LocationManagement.tsx +++ b/src/Components/Facility/LocationManagement.tsx @@ -26,6 +26,7 @@ export default function LocationManagement({ facilityId }: Props) { backUrl={`/facility/${facilityId}`} options={
-

{name}

-
+

+ {name} +

+

{location_type}

-

+

{description || "-"}

Middleware Address:

-

+

{middleware_address || "-"}