diff --git a/cypress/e2e/users_spec/user_creation.cy.ts b/cypress/e2e/users_spec/user_creation.cy.ts index bd5002d386f..9090f72505a 100644 --- a/cypress/e2e/users_spec/user_creation.cy.ts +++ b/cypress/e2e/users_spec/user_creation.cy.ts @@ -193,18 +193,6 @@ describe("User Creation", () => { userPage.verifyMultipleBadgesWithSameId(alreadylinkedusersviews); }); - // the below commented out codes, will be used in the upcoming refactoring of this module, since it is a inter-dependent of partially converted code, currently taking it down - - // it("link facility for user", () => { - // cy.contains("Linked Facilities").click(); - // cy.intercept(/\/api\/v1\/facility/).as("getFacilities"); - // cy.get("[name='facility']") - // .click() - // .type("Dummy Facility 1") - // .wait("@getFacilities"); - // cy.get("li[role='option']").should("not.exist"); - // }); - afterEach(() => { cy.saveLocalStorage(); }); diff --git a/cypress/e2e/users_spec/user_manage.cy.ts b/cypress/e2e/users_spec/user_manage.cy.ts new file mode 100644 index 00000000000..b7e1e8b53e9 --- /dev/null +++ b/cypress/e2e/users_spec/user_manage.cy.ts @@ -0,0 +1,101 @@ +import { cy, describe, before, beforeEach, it, afterEach } from "local-cypress"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { UserPage } from "../../pageobject/Users/UserSearch"; +import ManageUserPage from "../../pageobject/Users/ManageUserPage"; + +describe("Manage User", () => { + const loginPage = new LoginPage(); + const userPage = new UserPage(); + const manageUserPage = new ManageUserPage(); + const usernametolinkfacilitydoc1 = "dummydoctor4"; + const usernametolinkfacilitydoc2 = "dummydoctor5"; + const usernametolinkfacilitydoc3 = "dummydoctor6"; + const usernametolinkskill = "devdistrictadmin"; + const usernamerealname = "Dummy Doctor"; + const facilitytolinkusername = "Dummy Shifting Center"; + const workinghour = "23"; + + before(() => { + loginPage.loginAsDisctrictAdmin(); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.awaitUrl("/users"); + }); + + it("add working hour for a user and verify its reflection in card and user profile", () => { + // verify mandatory field error and select working hour for a user + userPage.typeInSearchInput(usernametolinkskill); + userPage.checkUsernameText(usernametolinkskill); + manageUserPage.clicksetaveragehourbutton(); + manageUserPage.clearweeklyhourfield(); + manageUserPage.clickSubmit(); + manageUserPage.verifyErrorText("Value should be between 0 and 168"); + // verify the data is reflected in user card and profile page + manageUserPage.typeInWeeklyWorkingHours(workinghour); + manageUserPage.clickSubmit(); + manageUserPage.verifyWorkingHours(workinghour); + manageUserPage.navigateToProfile(); + manageUserPage.verifyProfileWorkingHours(workinghour); + }); + + it("linking and unlinking facility for multiple users, and confirm reflection in user cards and doctor connect", () => { + // verify the user doesn't have any home facility + userPage.typeInSearchInput(usernametolinkfacilitydoc1); + userPage.checkUsernameText(usernametolinkfacilitydoc1); + manageUserPage.assertHomeFacility("No Home Facility"); + // Link a new facility and ensure it is under linked facility - doctor username (1) + manageUserPage.clickFacilitiesTab(); + manageUserPage.typeFacilityName(facilitytolinkusername); + manageUserPage.selectFacilityFromDropdown(facilitytolinkusername); + manageUserPage.clickLinkFacility(); + manageUserPage.assertLinkedFacility(facilitytolinkusername); + // Verify in the already linked facility are not present in droplist + manageUserPage.assertFacilityNotInDropdown(facilitytolinkusername); + manageUserPage.clickCloseSlideOver(); + // Link a new facility and ensure it is under home facility - doctor username (2) + userPage.clearSearchInput(); + userPage.typeInSearchInput(usernametolinkfacilitydoc2); + userPage.checkUsernameText(usernametolinkfacilitydoc2); + manageUserPage.clickFacilitiesTab(); + manageUserPage.typeFacilityName(facilitytolinkusername); + manageUserPage.selectFacilityFromDropdown(facilitytolinkusername); + manageUserPage.clickLinkFacility(); + manageUserPage.clickHomeFacilityIcon(); + manageUserPage.assertnotLinkedFacility(facilitytolinkusername); + manageUserPage.assertHomeFacilitylink(facilitytolinkusername); + manageUserPage.clickCloseSlideOver(); + // verify the home facility doctor id have reflection in user card + userPage.clearSearchInput(); + userPage.typeInSearchInput(usernametolinkfacilitydoc2); + userPage.checkUsernameText(usernametolinkfacilitydoc2); + manageUserPage.assertHomeFacility(facilitytolinkusername); + // Link a new facility and unlink the facility from the doctor username (3) + userPage.clearSearchInput(); + userPage.typeInSearchInput(usernametolinkfacilitydoc3); + userPage.checkUsernameText(usernametolinkfacilitydoc3); + manageUserPage.clickFacilitiesTab(); + manageUserPage.typeFacilityName(facilitytolinkusername); + manageUserPage.selectFacilityFromDropdown(facilitytolinkusername); + manageUserPage.clickLinkFacility(); + manageUserPage.clickUnlinkFacilityButton(); + manageUserPage.clickSubmit(); + manageUserPage.assertnotLinkedFacility; + manageUserPage.linkedfacilitylistnotvisible(); + manageUserPage.clickCloseSlideOver(); + // Go to particular facility doctor connect and all user-id are reflected based on there access + // Path will be facility page to patient page then doctor connect button + manageUserPage.navigateToFacility(); + manageUserPage.typeFacilitySearch(facilitytolinkusername); + manageUserPage.assertFacilityInCard(facilitytolinkusername); + manageUserPage.clickFacilityPatients(); + manageUserPage.clickDoctorConnectButton(); + manageUserPage.assertDoctorConnectVisibility(usernamerealname); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/pageobject/Patient/PatientConsultation.ts b/cypress/pageobject/Patient/PatientConsultation.ts index bf301641898..ce1fdc1e393 100644 --- a/cypress/pageobject/Patient/PatientConsultation.ts +++ b/cypress/pageobject/Patient/PatientConsultation.ts @@ -44,23 +44,20 @@ export class PatientConsultationPage { cy.get("#height").click().type(weight); cy.get("#patient_no").type(ipNumber); cy.intercept("GET", "**/icd/**").as("getIcdResults"); - cy.get( - "#icd11_diagnoses_object input[placeholder='Select'][role='combobox']" - ) + cy.get("#icd11-search input[role='combobox']") .scrollIntoView() .click() .type("1A"); - cy.get("#icd11_diagnoses_object [role='option']") + cy.get("#icd11-search [role='option']") .contains("1A00 Cholera") .scrollIntoView() .click(); - cy.get("label[for='icd11_diagnoses_object']").click(); + cy.get("#condition-verification-status-menu").click(); + cy.get("#add-icd11-diagnosis-as-confirmed").click(); cy.wait("@getIcdResults").its("response.statusCode").should("eq", 200); - cy.get("#icd11_principal_diagnosis [role='combobox']").click().type("1A"); - cy.get("#icd11_principal_diagnosis [role='option']") - .contains("1A00 Cholera") - .click(); + cy.get("#principal-diagnosis-select").click(); + cy.get("#principal-diagnosis-select [role='option']").first().click(); cy.get("#consultation_notes").click().type(consulationNotes); cy.get("#verified_by") diff --git a/cypress/pageobject/Users/ManageUserPage.ts b/cypress/pageobject/Users/ManageUserPage.ts new file mode 100644 index 00000000000..70e617f7e35 --- /dev/null +++ b/cypress/pageobject/Users/ManageUserPage.ts @@ -0,0 +1,116 @@ +export class ManageUserPage { + assertHomeFacility(expectedText) { + cy.get("#home_facility").should("contain.text", expectedText); + } + + clickFacilitiesTab() { + cy.get("#facilities").click(); + } + + typeFacilityName(facilityName) { + cy.get("input[name='facility']").click().type(facilityName); + } + + selectFacilityFromDropdown(facilityName) { + cy.get("[role='option']").contains(facilityName).click(); + } + + clickLinkFacility() { + cy.get("#link-facility").click(); + } + + assertLinkedFacility(facilityName) { + cy.get("#linked-facility-list").should("contain.text", facilityName); + } + + assertnotLinkedFacility(facilityName) { + cy.get("#linked-facility-list").should("not.contain", facilityName); + } + + linkedfacilitylistnotvisible() { + cy.get("#linked-facility-list").should("not.exist"); + } + + assertHomeFacilitylink(facilityName) { + cy.get("#home-facility").should("contain.text", facilityName); + } + + assertFacilityNotInDropdown(facilityName) { + this.typeFacilityName(facilityName); + cy.get("[role='option']").should("not.exist"); + } + + clickCloseSlideOver() { + cy.get("#close-slide-over").click(); + } + + clickHomeFacilityIcon() { + cy.get("#home-facility-icon").click(); + } + + clickUnlinkFacilityButton() { + cy.get("#unlink-facility-button").click(); + } + + clickSubmit() { + cy.get("#submit").click(); + } + + clicksetaveragehourbutton() { + cy.get("#avg-workinghour").click(); + } + + clearweeklyhourfield() { + cy.get("#weekly_working_hours").click().clear(); + } + + verifyErrorText(expectedError: string) { + cy.get(".error-text").should("contain", expectedError).and("be.visible"); + } + + typeInWeeklyWorkingHours(hours: string) { + cy.get("#weekly_working_hours").click().type(hours); + } + + navigateToProfile() { + cy.get("#profilenamelink").click(); + } + + verifyWorkingHours(expectedHours: string) { + cy.get("#working-hours").should("contain", `${expectedHours} hours`); + } + + verifyProfileWorkingHours(expectedHours: string) { + cy.get("#averageworkinghour-profile-details").should( + "contain", + expectedHours + ); + } + + navigateToFacility() { + cy.visit("/facility"); + } + + typeFacilitySearch(facilityName) { + cy.get("#search").click().type(facilityName); + } + + assertFacilityInCard(facilityName) { + cy.get("#facility-name-card").should("contain", facilityName); + } + + clickFacilityPatients() { + cy.get("#facility-patients").click(); + } + + clickDoctorConnectButton() { + cy.get("#doctor-connect-patient-button").click(); + } + + assertDoctorConnectVisibility(realName) { + cy.get("#doctor-connect-home-doctor").should("contain.text", realName); + cy.get("#doctor-connect-remote-doctor").should("contain.text", realName); + } +} + +export default ManageUserPage; diff --git a/package-lock.json b/package-lock.json index baa3205a234..0da53d597ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23708,4 +23708,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/CAREUI/misc/PaginatedList.tsx b/src/CAREUI/misc/PaginatedList.tsx index 3521807154e..0d2445ffbc9 100644 --- a/src/CAREUI/misc/PaginatedList.tsx +++ b/src/CAREUI/misc/PaginatedList.tsx @@ -33,7 +33,10 @@ function useContextualized() { interface Props extends QueryOptions> { route: QueryRoute>; perPage?: number; - children: (ctx: PaginatedListContext) => JSX.Element | JSX.Element[]; + children: ( + ctx: PaginatedListContext, + query: ReturnType>> + ) => JSX.Element | JSX.Element[]; } export default function PaginatedList({ @@ -59,7 +62,7 @@ export default function PaginatedList({ value={{ ...query, items, perPage, currentPage, setPage }} > - {(ctx) => children(ctx as PaginatedListContext)} + {(ctx) => children(ctx as PaginatedListContext, query)} ); diff --git a/src/Common/hooks/useSlug.ts b/src/Common/hooks/useSlug.ts index 69d8f591c84..8885a074678 100644 --- a/src/Common/hooks/useSlug.ts +++ b/src/Common/hooks/useSlug.ts @@ -8,9 +8,9 @@ import { usePath } from "raviger"; * // Current path: /consultation/94b9a * const consultation = useSlug("consultation"); // consultation = "94b9a" */ -export default function useSlug(prefix: string) { +export default function useSlug(prefix: string, fallback?: string) { const path = usePath() ?? ""; - return findSlug(path.split("/"), prefix); + return findSlug(path.split("/"), prefix, fallback); } /** @@ -28,7 +28,7 @@ export const useSlugs = (...prefix: string[]) => { return prefix.map((p) => findSlug(path.split("/"), p)); }; -const findSlug = (segments: string[], prefix: string) => { +const findSlug = (segments: string[], prefix: string, fallback?: string) => { const index = segments.findIndex((segment) => segment === prefix); if (index === -1) { throw new Error( @@ -36,8 +36,8 @@ const findSlug = (segments: string[], prefix: string) => { ); } - const slug = segments[index + 1]; - if (!slug) { + const slug = segments[index + 1] ?? fallback; + if (slug === undefined) { throw new Error(`Slug not found in path "${segments.join("/")}"`); } diff --git a/src/Components/Common/DiagnosisSelectFormField.tsx b/src/Components/Common/DiagnosisSelectFormField.tsx deleted file mode 100644 index 4086664d4ba..00000000000 --- a/src/Components/Common/DiagnosisSelectFormField.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useAsyncOptions } from "../../Common/hooks/useAsyncOptions"; -import { listICD11Diagnosis } from "../../Redux/actions"; -import { ICD11DiagnosisModel } from "../Facility/models"; -import { AutocompleteMutliSelect } from "../Form/FormFields/AutocompleteMultiselect"; -import FormField from "../Form/FormFields/FormField"; -import { - FormFieldBaseProps, - useFormFieldPropsResolver, -} from "../Form/FormFields/Utils"; - -type Props = - // | ({ multiple?: false | undefined } & FormFieldBaseProps) // uncomment when single select form field is required and implemented. - { multiple: true } & FormFieldBaseProps; - -export function DiagnosisSelectFormField(props: Props) { - const field = useFormFieldPropsResolver(props); - const { fetchOptions, isLoading, options } = - useAsyncOptions("id"); - - if (!props.multiple) { - return ( -
- Component not implemented -
- ); - } - - return ( - - option.label} - optionValue={(option) => option} - onQuery={(query) => - fetchOptions(listICD11Diagnosis({ query }, field.id || "")) - } - isLoading={isLoading} - /> - - ); -} diff --git a/src/Components/Common/FacilitySelect.tsx b/src/Components/Common/FacilitySelect.tsx index 19494081aa3..1aabc36013b 100644 --- a/src/Components/Common/FacilitySelect.tsx +++ b/src/Components/Common/FacilitySelect.tsx @@ -6,7 +6,7 @@ import { FacilityModel } from "../Facility/models"; interface FacilitySelectProps { name: string; - exclude_user: string; + exclude_user?: string; errors?: string | undefined; className?: string; searchAll?: boolean; diff --git a/src/Components/Common/Sidebar/Sidebar.tsx b/src/Components/Common/Sidebar/Sidebar.tsx index b4f5155e676..10b5c6d04fa 100644 --- a/src/Components/Common/Sidebar/Sidebar.tsx +++ b/src/Components/Common/Sidebar/Sidebar.tsx @@ -116,7 +116,7 @@ const StatelessSidebar = ({ return (