diff --git a/.cursorrules b/.cursorrules index 2eed3afe459..94ebea1bd57 100644 --- a/.cursorrules +++ b/.cursorrules @@ -1,23 +1,35 @@ -Care is a React Typescript Project, built with Vite and styled with TailwindCSS. +You are an expert in TypeScript, React, Shadcn UI, Tailwind. -Care uses a Plugin Architecture. Apps are installed in /apps. +Key Principles -Care uses a custom useQuery hook to fetch data from the API. APIs are defined in the api.tsx file +- Write concise, technical TypeScript code with accurate examples. +- Use functional and declarative programming patterns; avoid classes. +- Prefer iteration and modularization over code duplication. +- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError). -Here's an example of how to use the useQuery hook to fetch data from the API: +Naming Conventions -``` -useQuery from "@/common/hooks/useQuery"; -const { data, loading, error } = useQuery(routes.getFacilityUsers, { - facility_id: "1", -}); +- Use lowercase with dashes for directories (e.g., components/auth-wizard). +- Favor named exports for components. -request from "@/common/utils/request"; -const { res } = await request(routes.partialUpdateAsset, { - pathParams: { external_id: assetId }, - body: data, -}); -``` +TypeScript Usage +- Use TypeScript for all code; prefer interfaces over types. +- Avoid enums; use maps instead. +- Use functional components with TypeScript interfaces. +Syntax and Formatting +- Use the "function" keyword for pure functions. +- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements. +- Use declarative JSX. + +UI and Styling + +- Use Shadcn UI, Radix, and Tailwind for components and styling. +- Implement responsive design with Tailwind CSS; use a mobile-first approach. + +General Guidelines + +- Care uses a custom useQuery hook to fetch data from the API. (Docs @ /Utils/request/useQuery) +- APIs are defined in the api.tsx file. diff --git a/.github/workflows/cypress.yaml b/.github/workflows/cypress.yaml index 506c2e56f66..3abf95cd4b0 100644 --- a/.github/workflows/cypress.yaml +++ b/.github/workflows/cypress.yaml @@ -18,8 +18,9 @@ jobs: containers: [1, 2, 3, 4] env: REACT_CARE_API_URL: http://localhost:9000 - REACT_ENABLED_APPS: "ohcnetwork/care_hcx_fe@main" + REACT_ENABLED_APPS: "ohcnetwork/care_hcx_fe@main,ohcnetwork/care_abdm_fe@main" REACT_ENABLE_HCX: true + REACT_ENABLE_ABDM: true steps: - name: Checkout 📥 uses: actions/checkout@v3 @@ -135,4 +136,4 @@ jobs: if: ${{ failure() && steps.pr_origin.outputs.is_forked == 'true' }} with: name: cypress-videos - path: cypress/videos \ No newline at end of file + path: cypress/videos diff --git a/.github/workflows/notify-non-core-qn.yml b/.github/workflows/notify-non-core-qn.yml index 7aa59e6e868..07533c320c5 100644 --- a/.github/workflows/notify-non-core-qn.yml +++ b/.github/workflows/notify-non-core-qn.yml @@ -1,37 +1,39 @@ name: Notify Core Team on Non-Core Questions + on: issue_comment: types: [created] + permissions: issues: write pull-requests: write + jobs: notify_core_team: runs-on: ubuntu-latest env: - ALLOWED_USERNAMES: ${{ vars.ALLOWED_USERNAMES }} - QUESTION_KEYWORDS: ${{ vars.QUESTION_KEYWORDS }} - QUESTION_LABELS: ${{ vars.QUESTION_LABELS }} - SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + ALLOWED_USERNAMES: ${{ vars.ALLOWED_USERNAMES || '' }} + QUESTION_KEYWORDS: ${{ vars.QUESTION_KEYWORDS || '' }} + QUESTION_LABELS: ${{ vars.QUESTION_LABELS || '' }} + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK || '' }} + steps: - name: Check and Notify - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - console.log('Script started'); - const isOrgMember = (commenter, allowedUsers) => { - return allowedUsers.split(',').map(u => u.trim()).includes(commenter); - }; - const containsQuestionKeywords = (text, keywords) => { - return keywords.split(',').map(k => k.trim()).some(keyword => + const isOrgMember = (commenter, allowedUsers) => + allowedUsers.split(',').map(u => u.trim()).includes(commenter); + + const containsQuestionKeywords = (text, keywords) => + keywords.split(',').map(k => k.trim()).some(keyword => text.toLowerCase().includes(keyword.toLowerCase()) ); - }; + const addLabelsToIssue = async (github, context, labelsString) => { - const labels = labelsString.split(',').map(label => label.trim()).filter(label => label); + const labels = labelsString.split(',').map(label => label.trim()).filter(Boolean); if (labels.length > 0) { - console.log('Adding labels:', labels); await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, @@ -40,48 +42,47 @@ jobs: }); } }; - const sendSlackNotification = async (webhook, payload) => { + + const sendSlackNotification = async (webhook, commentUrl) => { + const payload = { commentUrl }; const response = await fetch(webhook, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); + throw new Error(`Slack notification failed with status: ${response.status}`); } }; + + const isBot = async (github, commenter) => { + try { + const { data: user } = await github.rest.users.getByUsername({ username: commenter }); + return user.type === 'Bot'; + } catch { + return false; + } + }; + const commenter = context.payload.comment.user.login; - console.log('Commenter:', commenter); - if (!isOrgMember(commenter, process.env.ALLOWED_USERNAMES)) { - const commentBody = context.payload.comment.body; - const sanitizedComment = commentBody - ?.replace(/[^\w\s?]/gi, '') - .toLowerCase(); - console.log('Comment body:', sanitizedComment); - if (containsQuestionKeywords(sanitizedComment, process.env.QUESTION_KEYWORDS)) { - try { - console.log('Adding labels to the issue'); - await addLabelsToIssue(github, context, process.env.QUESTION_LABELS); - console.log('Labels added successfully'); - const issueUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/issues/${context.payload.issue.number}`; - const issueTitle = context.payload.issue.title; - const issueNumber = context.payload.issue.number; - console.log('Issue URL:', issueUrl); - console.log('Issue Title:', issueTitle); - console.log('Issue Number:', issueNumber); - const payload = { - link: issueUrl, - Question: commentBody, - "issue-number": issueNumber, - title: issueTitle, - user: commenter - }; - await sendSlackNotification(process.env.SLACK_WEBHOOK, payload); - console.log('Slack notification sent successfully'); - } catch (error) { - console.error('Workflow failed:', error.message); - core.setFailed(`Workflow failed: ${error.message}`); + const allowedUsers = process.env.ALLOWED_USERNAMES; + const keywords = process.env.QUESTION_KEYWORDS; + const labels = process.env.QUESTION_LABELS; + const webhook = process.env.SLACK_WEBHOOK; + + if (await isBot(github, commenter)) return; + + if (allowedUsers && !isOrgMember(commenter, allowedUsers)) { + const commentBody = context.payload.comment.body.trim(); + const filteredCommentBody = commentBody.split('\n').filter(line => !line.startsWith('>')).join('\n'); + + if (keywords && containsQuestionKeywords(filteredCommentBody, keywords)) { + if (labels) { + await addLabelsToIssue(github, context, labels); + } + if (webhook) { + const commentUrl = context.payload.comment.html_url; + await sendSlackNotification(webhook, commentUrl); } } } - console.log('Script ended'); diff --git a/.github/workflows/thank-you.yml b/.github/workflows/thank-you.yml index 192f71d1a64..b91642dd24f 100644 --- a/.github/workflows/thank-you.yml +++ b/.github/workflows/thank-you.yml @@ -18,26 +18,20 @@ jobs: uses: actions/github-script@v6.3.3 with: script: | - const thankyouNote = 'Your efforts have helped advance digital healthcare and TeleICU systems. :rocket: Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! :raised_hands:' + const thankyouNote = 'Your efforts have helped advance digital healthcare and TeleICU systems. :rocket: Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! :raised_hands:'; const options = { issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - } + }; - const result = await github.rest.issues.get({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - }) - - const { assignees, user } = result.data + const { data : { assignees, user } } = await github.rest.issues.get(options); - const assignees_tagged = assignees.map((user) => '@' + user.login).join(' ') - const owner_tagged = '@' + user.login + const taggedUsers = [...new Set( + assignees.map(u => "@"+u.login).concat("@"+user.login) + )].join(" ") - if (assignees.length == 0) { - await github.rest.issues.createComment({ ...options, body: `${owner_tagged} ${thankyouNote}` }) - } else { - await github.rest.issues.createComment({ ...options, body: `${assignees_tagged} ${owner_tagged} ${thankyouNote}` }) - } + await github.rest.issues.createComment({ + ...options, + body: `${taggedUsers} ${thankyouNote}` + }); diff --git a/crowdin.yml b/crowdin.yml index 0ab1a042711..fdcb6bcd32d 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,5 +1,6 @@ files: - - source: /src/Locale/en/*.json - translation: /src/Locale/%two_letters_code%/%original_file_name% + - source: /public/locale/{{lang}}.json + translation: /public/locale/%two_letters_code%/%original_file_name% bundles: - 2 + diff --git a/cypress/e2e/assets_spec/AssetHomepage.cy.ts b/cypress/e2e/assets_spec/AssetHomepage.cy.ts index dfb3249c243..e19f885db72 100644 --- a/cypress/e2e/assets_spec/AssetHomepage.cy.ts +++ b/cypress/e2e/assets_spec/AssetHomepage.cy.ts @@ -2,112 +2,128 @@ import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; import { pageNavigation } from "pageobject/utils/paginationHelpers"; import { v4 as uuidv4 } from "uuid"; -import { AssetPage } from "../../pageobject/Asset/AssetCreation"; import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; -import { AssetQRScanPage } from "../../pageobject/Asset/AssetQRScan"; -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import { AssetHome } from "../../pageobject/Asset/AssetHome"; import LoginPage from "../../pageobject/Login/LoginPage"; - -describe("Asset Tab", () => { - const assetSearchPage = new AssetSearchPage(); - const assetQRScanPage = new AssetQRScanPage(); - const assetFilters = new AssetFilters(); - const assetPage = new AssetPage(); - const loginPage = new LoginPage(); - const assetName = "Dummy Camera 10"; - const qrCode = uuidv4(); - const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); - - before(() => { - loginPage.loginAsDistrictAdmin(); - cy.saveLocalStorage(); - }); - - beforeEach(() => { - cy.restoreLocalStorage(); - cy.clearLocalStorage(/filters--.+/); - cy.awaitUrl("/assets"); - }); - - // search for a element - - it("Search Asset Name/QR_ID/Serial_number", () => { - assetSearchPage.typeSearchKeyword(assetName); - assetSearchPage.pressEnter(); - assetSearchPage.verifyBadgeContent(assetName); - assetSearchPage.clickAssetByName(assetName); - assetSearchPage.clickUpdateButton(); - assetSearchPage.clearAndTypeQRCode(qrCode); - assetSearchPage.clearAndTypeSerialNumber(serialNumber); - assetSearchPage.clickAssetSubmitButton(); - assetSearchPage.visitAssetsPage(); - assetSearchPage.typeSearchKeyword(qrCode); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetListContains(assetName); - assetSearchPage.verifyBadgeContent(qrCode); - assetSearchPage.typeSearchKeyword(serialNumber); - assetSearchPage.verifyAssetListContains(assetName); - assetSearchPage.verifyBadgeContent(serialNumber); - }); - - // scan a asset qr code - - it("Scan Asset QR", () => { - assetQRScanPage.scanAssetQR(); - }); - - // filter the asset and verify the badges are there - - it("Filter Asset", () => { - assetFilters.filterAssets( - "Dummy Facility 40", - "ACTIVE", - "ONVIF Camera", - "Camera Loc", - ); - advanceFilters.clickAdvancedFiltersButton(); - assetFilters.clickslideoverbackbutton(); // to verify the back button doesn't clear applied filters - assetFilters.assertFacilityText("Dummy Facility 40"); - assetFilters.assertAssetClassText("ONVIF"); - assetFilters.assertStatusText("ACTIVE"); - assetFilters.assertLocationText("Camera Loc"); - advanceFilters.clickAdvancedFiltersButton(); - assetFilters.clearFilters(); - }); - - // Verify the pagination in the page - - it("Next/Previous Page", () => { - pageNavigation.navigateToNextPage(); - pageNavigation.verifyCurrentPageNumber(2); - pageNavigation.navigateToPreviousPage(); - pageNavigation.verifyCurrentPageNumber(1); - }); - - it("Import new asset", () => { - assetPage.selectassetimportbutton(); - assetPage.selectImportOption(); - assetPage.selectImportFacility("Dummy Facility 40"); - assetPage.importAssetFile(); - assetPage.selectImportLocation("Camera Loc"); - assetPage.clickImportAsset(); - }); - - it("verify imported asset", () => { - assetSearchPage.typeSearchKeyword("New Test Asset"); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetIsPresent("New Test Asset"); - }); - - it("Export asset", () => { - assetPage.selectassetimportbutton(); - cy.wait(2000); - assetPage.selectJsonExportButton(); - assetPage.selectassetimportbutton(); - assetPage.selectCsvExportButton(); - }); - - afterEach(() => { - cy.saveLocalStorage(); +import { nonAdminRoles } from "../../pageobject/utils/userConfig"; + +const rolesToTest: Array<"districtAdmin" | (typeof nonAdminRoles)[number]> = [ + "districtAdmin", + ...nonAdminRoles, +]; + +rolesToTest.forEach((role) => { + describe(`Asset Tab Tests for Role: ${role}`, () => { + const assetHome = new AssetHome(); + const assetFilters = new AssetFilters(); + const loginPage = new LoginPage(); + const assetName = "Dummy Camera 10"; + const assetStatus = "ACTIVE"; + const assetClass = "ONVIF"; + const assetLocation = "Camera Loc"; + const facilityName = "Dummy Facility 40"; + const newImportAssetName = "New Test Asset"; + const qrCode = uuidv4(); + const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); + + before(() => { + loginPage.loginByRole(role); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.clearLocalStorage(/filters--.+/); + cy.awaitUrl("/assets"); + }); + + it("Search Asset Name/QR_ID/Serial_number", () => { + assetHome.typeAssetSearch(assetName); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + assetName, + true, + ); + assetHome.clickAssetByName(assetName); + assetHome.clickAssetDetailsUpdateButton(); + assetHome.clearAndTypeQRCode(qrCode); + assetHome.clearAndTypeSerialNumber(serialNumber); + assetHome.clickAssetUpdateSubmitButton(); + assetHome.navigateToAssetsPage(); + assetHome.typeAssetSearch(qrCode); + assetHome.verifyAssetListContains(assetName); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + qrCode, + true, + ); + assetHome.typeAssetSearch(serialNumber); + assetHome.verifyAssetListContains(assetName); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + serialNumber, + true, + ); + }); + + it("Scan Asset QR", () => { + assetHome.scanAssetQR(); + }); + + it("Advance Filter Asset", () => { + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.typeFacilityName(facilityName); + assetFilters.filterAssets(assetStatus, assetClass, assetLocation); + advanceFilters.applySelectedFilter(); + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.clickslideoverbackbutton(); // to verify the back button doesn't clear applied filters + advanceFilters.verifyFilterBadgePresence("Facility", facilityName, true); + advanceFilters.verifyFilterBadgePresence("Asset Class", assetClass, true); + advanceFilters.verifyFilterBadgePresence("Status", assetStatus, true); + advanceFilters.verifyFilterBadgePresence("Location", assetLocation, true); + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.clickClearAdvanceFilters(); + }); + + it("Next/Previous Page", () => { + pageNavigation.navigateToNextPage(); + pageNavigation.verifyCurrentPageNumber(2); + pageNavigation.navigateToPreviousPage(); + pageNavigation.verifyCurrentPageNumber(1); + }); + + it("Import new asset and verify its presence", () => { + if (role === "districtAdmin") { + assetHome.selectAssetImportButton("click"); + assetHome.selectImportOption(); + assetHome.selectImportFacility(facilityName); + assetHome.importAssetFile(); + assetHome.selectImportLocation(assetLocation); + assetHome.clickImportAsset(); + cy.verifyNotification("Assets imported successfully"); + cy.closeNotification(); + assetHome.navigateToAssetsPage(); + assetHome.typeAssetSearch(newImportAssetName); + assetHome.verifyAssetIsPresent(newImportAssetName); + } else { + assetHome.selectAssetImportButton("verifyNotExist"); + } + }); + + it("Export the list of assets in CSV & Json", () => { + if (role === "districtAdmin") { + assetHome.selectAssetImportButton("click"); + cy.wait(2000); + assetHome.selectJsonExportButton(); + assetHome.selectAssetImportButton("click"); + assetHome.selectCsvExportButton(); + } else { + assetHome.selectAssetImportButton("verifyNotExist"); + } + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); }); }); diff --git a/cypress/e2e/assets_spec/AssetsCreation.cy.ts b/cypress/e2e/assets_spec/AssetsCreation.cy.ts index 61c6fe9b517..76f225b03d7 100644 --- a/cypress/e2e/assets_spec/AssetsCreation.cy.ts +++ b/cypress/e2e/assets_spec/AssetsCreation.cy.ts @@ -1,18 +1,18 @@ import { v4 as uuidv4 } from "uuid"; import { AssetPage } from "../../pageobject/Asset/AssetCreation"; -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import { AssetHome } from "../../pageobject/Asset/AssetHome"; import LoginPage from "../../pageobject/Login/LoginPage"; describe("Asset", () => { const assetPage = new AssetPage(); - const assetSearchPage = new AssetSearchPage(); + const assetHome = new AssetHome(); const loginPage = new LoginPage(); const phone_number = "9999999999"; const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -87,9 +87,8 @@ describe("Asset", () => { assetPage.verifyAssetCreation(); assetPage.verifySuccessNotification("Asset created successfully"); - assetSearchPage.typeSearchKeyword("New Test Asset 2"); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetIsPresent("New Test Asset 2"); + assetHome.typeAssetSearch("New Test Asset 2"); + assetHome.verifyAssetIsPresent("New Test Asset 2"); }); it("Edit an Asset", () => { @@ -114,9 +113,8 @@ describe("Asset", () => { }); it("Verify Editted Asset", () => { - assetSearchPage.typeSearchKeyword("New Test Asset Edited"); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetIsPresent("New Test Asset Edited"); + assetHome.typeAssetSearch("New Test Asset Edited"); + assetHome.verifyAssetIsPresent("New Test Asset Edited"); }); it("Configure an asset", () => { @@ -159,8 +157,7 @@ describe("Asset", () => { assetPage.interceptAssetCreation(); assetPage.clickCreateAsset(); assetPage.verifyAssetCreation(); - assetSearchPage.typeSearchKeyword("New Test Asset Vital"); - assetSearchPage.pressEnter(); + assetHome.typeAssetSearch("New Test Asset Vital"); assetPage.openCreatedAsset(); assetPage.configureVitalAsset("Host name", "192.168.1.20"); assetPage.clickConfigureVital(); diff --git a/cypress/e2e/assets_spec/AssetsManage.cy.ts b/cypress/e2e/assets_spec/AssetsManage.cy.ts index 17ee99bdb62..32dc5791bd3 100644 --- a/cypress/e2e/assets_spec/AssetsManage.cy.ts +++ b/cypress/e2e/assets_spec/AssetsManage.cy.ts @@ -1,6 +1,8 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import { AssetPage } from "../../pageobject/Asset/AssetCreation"; -import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import { AssetHome } from "../../pageobject/Asset/AssetHome"; import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import LoginPage from "../../pageobject/Login/LoginPage"; @@ -14,15 +16,15 @@ describe("Asset", () => { const assetPage = new AssetPage(); const loginPage = new LoginPage(); const facilityPage = new FacilityPage(); - const assetSearchPage = new AssetSearchPage(); - const assetFilters = new AssetFilters(); + const assetHome = new AssetHome(); + const facilityHome = new FacilityHome(); const fillFacilityName = "Dummy Facility 40"; const assetname = "Dummy Camera"; const locationName = "Dummy Location 1"; const initiallocationName = "Camera Location"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -33,10 +35,13 @@ describe("Asset", () => { }); it("Verify Asset Warranty Expiry Label", () => { - assetSearchPage.typeSearchKeyword(assetname); - assetSearchPage.pressEnter(); - assetSearchPage.verifyBadgeContent(assetname); - assetSearchPage.clickAssetByName(assetname); + assetHome.typeAssetSearch(assetname); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + assetname, + true, + ); + assetHome.clickAssetByName(assetname); assetPage.clickupdatedetailbutton(); assetPage.scrollintoWarrantyDetails(); assetPage.enterWarrantyExpiryDate(addDaysToDate(100)); // greater than 3 months @@ -60,10 +65,13 @@ describe("Asset", () => { }); it("Create & Edit a service history and verify reflection", () => { - assetSearchPage.typeSearchKeyword(assetname); - assetSearchPage.pressEnter(); - assetSearchPage.verifyBadgeContent(assetname); - assetSearchPage.clickAssetByName(assetname); + assetHome.typeAssetSearch(assetname); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + assetname, + true, + ); + assetHome.clickAssetByName(assetname); assetPage.clickupdatedetailbutton(); assetPage.scrollintonotes(); assetPage.enterAssetNotes("Dummy Notes"); @@ -82,10 +90,13 @@ describe("Asset", () => { }); it("Create a asset transaction and verify history", () => { - assetSearchPage.typeSearchKeyword(assetname); - assetSearchPage.pressEnter(); - assetSearchPage.verifyBadgeContent(assetname); - assetSearchPage.clickAssetByName(assetname); + assetHome.typeAssetSearch(assetname); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + assetname, + true, + ); + assetHome.clickAssetByName(assetname); assetPage.clickupdatedetailbutton(); assetPage.clickassetlocation(locationName); assetPage.clickUpdateAsset(); @@ -94,10 +105,13 @@ describe("Asset", () => { }); it("Verify Facility Asset Page Redirection", () => { - cy.visit("/facility"); - assetSearchPage.typeSearchKeyword(fillFacilityName); - assetSearchPage.pressEnter(); - facilityPage.verifyFacilityBadgeContent(fillFacilityName); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(fillFacilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + fillFacilityName, + true, + ); facilityPage.visitAlreadyCreatedFacility(); facilityPage.clickManageFacilityDropdown(); facilityPage.clickCreateAssetFacilityOption(); @@ -106,7 +120,11 @@ describe("Asset", () => { facilityPage.clickManageFacilityDropdown(); facilityPage.clickviewAssetFacilityOption(); facilityPage.verifyfacilityviewassetredirection(); - assetFilters.assertFacilityText(fillFacilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility", + fillFacilityName, + true, + ); facilityPage.verifyassetfacilitybackredirection(); }); diff --git a/cypress/e2e/facility_spec/FacilityCreation.cy.ts b/cypress/e2e/facility_spec/FacilityCreation.cy.ts index 5fd988480fc..d8d73417e7e 100644 --- a/cypress/e2e/facility_spec/FacilityCreation.cy.ts +++ b/cypress/e2e/facility_spec/FacilityCreation.cy.ts @@ -1,8 +1,11 @@ +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import FacilityHome from "../../pageobject/Facility/FacilityHome"; import LoginPage from "../../pageobject/Login/LoginPage"; import ManageUserPage from "../../pageobject/Users/ManageUserPage"; import { UserCreationPage } from "../../pageobject/Users/UserCreation"; +import { nonAdminRoles } from "../../pageobject/utils/userConfig"; describe("Facility Creation", () => { let facilityUrl1: string; @@ -60,7 +63,7 @@ describe("Facility Creation", () => { const facilityType = "Primary Health Centres"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -72,9 +75,13 @@ describe("Facility Creation", () => { it("Verify Facility Triage Function", () => { // mandatory field error throw - manageUserPage.typeFacilitySearch(facilityName2); - facilityPage.verifyFacilityBadgeContent(facilityName2); - manageUserPage.assertFacilityInCard(facilityName2); + facilityHome.typeFacilitySearch(facilityName2); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName2, + true, + ); + facilityHome.assertFacilityInCard(facilityName2); facilityHome.verifyURLContains(facilityName2); facilityPage.visitAlreadyCreatedFacility(); facilityPage.scrollToFacilityTriage(); @@ -237,10 +244,14 @@ describe("Facility Creation", () => { .contains(facilityNumber) .should("be.visible"); // verify the facility homepage - cy.visit("/facility"); - manageUserPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); facilityHome.verifyURLContains(facilityName); }); @@ -335,13 +346,8 @@ describe("Facility Creation", () => { }); it("Access Restriction for Non-Admin Users to facility creation page", () => { - const nonAdminLoginMethods = [ - loginPage.loginAsDevDoctor.bind(loginPage), - loginPage.loginAsStaff.bind(loginPage), - ]; - - nonAdminLoginMethods.forEach((loginMethod) => { - loginMethod(); + nonAdminRoles.forEach((role) => { + loginPage.loginByRole(role); cy.visit("/facility/create"); facilityPage.verifyErrorNotification( "You don't have permission to perform this action. Contact the admin", diff --git a/cypress/e2e/facility_spec/FacilityHomepage.cy.ts b/cypress/e2e/facility_spec/FacilityHomepage.cy.ts index f4c7aaa90a0..7d03f7a16f0 100644 --- a/cypress/e2e/facility_spec/FacilityHomepage.cy.ts +++ b/cypress/e2e/facility_spec/FacilityHomepage.cy.ts @@ -6,7 +6,6 @@ import FacilityHome from "../../pageobject/Facility/FacilityHome"; import FacilityNotify from "../../pageobject/Facility/FacilityNotify"; import LoginPage from "../../pageobject/Login/LoginPage"; import ManageUserPage from "../../pageobject/Users/ManageUserPage"; -import { UserPage } from "../../pageobject/Users/UserSearch"; import { advanceFilters } from "../../pageobject/utils/advanceFilterHelpers"; describe("Facility Homepage Function", () => { @@ -15,7 +14,6 @@ describe("Facility Homepage Function", () => { const facilityNotify = new FacilityNotify(); const facilityPage = new FacilityPage(); const manageUserPage = new ManageUserPage(); - const userPage = new UserPage(); const facilitiesAlias = "downloadFacilitiesCSV"; const doctorsAlias = "downloadDoctorsCSV"; const triagesAlias = "downloadTriagesCSV"; @@ -29,7 +27,7 @@ describe("Facility Homepage Function", () => { const notificationMessage = "Test Notification"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -41,9 +39,13 @@ describe("Facility Homepage Function", () => { it("Verify the Facility card button redirection", () => { // view cns button - manageUserPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); facilityHome.clickViewCnsButton(); facilityHome.verifyCnsUrl(); facilityHome.navigateBack(); @@ -68,17 +70,21 @@ describe("Facility Homepage Function", () => { advanceFilters.selectLocalBody(localBody); advanceFilters.selectFacilityType(facilityType); advanceFilters.applySelectedFilter(); - facilityPage.verifyStateBadgeContent(stateName); - facilityPage.verifyDistrictBadgeContent(district); - facilityPage.verifyLocalBodyBadgeContent(localBody); - facilityPage.verifyFacilityTypeBadgeContent(facilityType); - manageUserPage.assertFacilityInCard(facilityName); + advanceFilters.verifyFilterBadgePresence("State", stateName, true); + advanceFilters.verifyFilterBadgePresence("District", district, true); + advanceFilters.verifyFilterBadgePresence( + "Facility type", + facilityType, + true, + ); + advanceFilters.verifyFilterBadgePresence("Local Body", localBody, true); + facilityHome.assertFacilityInCard(facilityName); advanceFilters.clickAdvancedFiltersButton(); advanceFilters.clickClearAdvanceFilters(); - userPage.verifyDataTestIdNotVisible("State"); - userPage.verifyDataTestIdNotVisible("District"); - userPage.verifyDataTestIdNotVisible("Facility type"); - userPage.verifyDataTestIdNotVisible("Local Body"); + advanceFilters.verifyFilterBadgePresence("State", "", false); + advanceFilters.verifyFilterBadgePresence("District", "", false); + advanceFilters.verifyFilterBadgePresence("Facility type", "", false); + advanceFilters.verifyFilterBadgePresence("Local Body", "", false); }); it("Search a facility in homepage and pagination", () => { @@ -88,9 +94,13 @@ describe("Facility Homepage Function", () => { pageNavigation.navigateToPreviousPage(); pageNavigation.verifyCurrentPageNumber(1); // search for a facility - manageUserPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); facilityHome.verifyURLContains(facilityName); }); @@ -124,9 +134,13 @@ describe("Facility Homepage Function", () => { advanceFilters.selectLocalBody(localBody); advanceFilters.applySelectedFilter(); // go to cns page in the facility details page - manageUserPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); facilityHome.clickViewFacilityDetails(); facilityHome.clickFacilityCnsButton(); facilityHome.verifyCnsUrl(); @@ -140,13 +154,17 @@ describe("Facility Homepage Function", () => { it("Verify Notice Board Functionality", () => { // search facility and verify it's loaded or not - manageUserPage.interceptFacilitySearchReq(); - manageUserPage.typeFacilitySearch(facilityName); - manageUserPage.verifyFacilitySearchReq(); + facilityHome.interceptFacilitySearchReq(); + facilityHome.typeFacilitySearch(facilityName); + facilityHome.verifyFacilitySearchReq(); // verify facility name and card reflection facilityNotify.verifyUrlContains("Dummy+Facility+40"); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); // send notification to a facility facilityHome.clickFacilityNotifyButton(); facilityNotify.verifyFacilityName(facilityName); diff --git a/cypress/e2e/facility_spec/FacilityInventory.cy.ts b/cypress/e2e/facility_spec/FacilityInventory.cy.ts index a9f32984efc..b3f77479763 100644 --- a/cypress/e2e/facility_spec/FacilityInventory.cy.ts +++ b/cypress/e2e/facility_spec/FacilityInventory.cy.ts @@ -9,7 +9,7 @@ describe("Inventory Management Section", () => { const inventoryName = "PPE"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/facility_spec/FacilityLocation.cy.ts b/cypress/e2e/facility_spec/FacilityLocation.cy.ts index 9ac85e9ba4c..b4d153b16ed 100644 --- a/cypress/e2e/facility_spec/FacilityLocation.cy.ts +++ b/cypress/e2e/facility_spec/FacilityLocation.cy.ts @@ -1,3 +1,4 @@ +import LoginPage from "pageobject/Login/LoginPage"; import { pageNavigation } from "pageobject/utils/paginationHelpers"; import { v4 as uuidv4 } from "uuid"; @@ -13,6 +14,7 @@ describe("Location Management Section", () => { const facilityPage = new FacilityPage(); const facilityLocation = new FacilityLocation(); const facilityHome = new FacilityHome(); + const loginPage = new LoginPage(); const EXPECTED_LOCATION_ERROR_MESSAGES = [ "Name is required", @@ -36,6 +38,7 @@ describe("Location Management Section", () => { const bedType = "ICU"; const bedStatus = "Vacant"; const bedModifiedName = "test modified bed"; + const duplicateBedName = "ICCU"; const bedModifiedDescrption = "test modified description"; const bedModifiedType = "Isolation"; const numberOfBeds = 10; @@ -45,7 +48,7 @@ describe("Location Management Section", () => { const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -96,12 +99,12 @@ describe("Location Management Section", () => { facilityHome.verifyAndCloseNotifyModal(); // edit the created bed facilityLocation.clickEditBedButton(); - facilityLocation.enterBedName(bedModifiedName); + facilityLocation.enterBedName(duplicateBedName); facilityLocation.enterBedDescription(bedModifiedDescrption); facilityLocation.selectBedType(bedModifiedType); assetPage.clickassetupdatebutton(); // verify the modification - facilityLocation.verifyBedNameBadge(bedModifiedName); + facilityLocation.verifyBedNameBadge(duplicateBedName); facilityLocation.verifyBedBadge(bedModifiedType); facilityLocation.verifyBedBadge(bedStatus); facilityLocation.closeNotification(); diff --git a/cypress/e2e/facility_spec/FacilityManage.cy.ts b/cypress/e2e/facility_spec/FacilityManage.cy.ts index 02c14958ccf..9f1523768c1 100644 --- a/cypress/e2e/facility_spec/FacilityManage.cy.ts +++ b/cypress/e2e/facility_spec/FacilityManage.cy.ts @@ -1,3 +1,6 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import FacilityManage from "../../pageobject/Facility/FacilityManage"; import LoginPage from "../../pageobject/Login/LoginPage"; @@ -6,16 +9,18 @@ describe("Facility Manage Functions", () => { const loginPage = new LoginPage(); const facilityManage = new FacilityManage(); const facilityPage = new FacilityPage(); + const facilityHome = new FacilityHome(); const facilityName = "Dummy Facility 40"; const facilityMiddlewareUpdateButton = "Update"; const facilityMiddleware = "dev-middleware.coronasafe.live"; const facilityUpdatedMiddleware = "updated.coronasafe.live"; const facilityMiddlewareSuccessfullNotification = "Facility middleware updated successfully"; - // const facilityHfridUpdateButton = "Link Health Facility"; - // const facilityHfridToastNotificationText = /Health Facility config updated successfully|Health ID registration failed/; - // const facilityHfrId = "IN180000018"; - // const facilityUpdatedHfrId = uuidv4(); + const facilityHfridUpdateButton = "Link Health Facility"; + const facilityHfridToastNotificationText = + /Health Facility config updated successfully|Health ID registration failed/; + const facilityHfrId = "IN180000018"; + const facilityUpdatedHfrId = "IN180000020"; const doctorCapacity = "5"; const doctorModifiedCapacity = "7"; const totalCapacity = "100"; @@ -24,7 +29,7 @@ describe("Facility Manage Functions", () => { const currentUpdatedOccupied = "100"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -33,8 +38,12 @@ describe("Facility Manage Functions", () => { cy.restoreLocalStorage(); cy.clearLocalStorage(/filters--.+/); cy.awaitUrl("/"); - facilityPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); facilityPage.visitAlreadyCreatedFacility(); }); @@ -76,37 +85,36 @@ describe("Facility Manage Functions", () => { facilityManage.verifyMiddlewareAddressValue(facilityUpdatedMiddleware); }); - // TODO: enable this test after configuring testing specs for plugs - // it("Configure Facility Health ID", () => { - // facilityPage.clickManageFacilityDropdown(); - // facilityManage.clickFacilityConfigureButton(); - // // verify mandatory field error message - // facilityManage.clearHfrId(); - // facilityManage.clickButtonWithText(facilityHfridUpdateButton); - // facilityManage.checkErrorMessageVisibility( - // "Health Facility Id is required", - // ); - // // add facility health ID and verify notification - // facilityManage.typeHfrId(facilityHfrId); - // facilityManage.clickButtonWithText(facilityHfridUpdateButton); - // facilityManage.verifySuccessMessageVisibilityAndContent( - // facilityHfridToastNotificationText, - // true, - // ); - // // update the existing middleware - // facilityPage.clickManageFacilityDropdown(); - // facilityManage.clickFacilityConfigureButton(); - // facilityManage.typeHfrId(facilityUpdatedHfrId); - // facilityManage.clickButtonWithText(facilityHfridUpdateButton); - // facilityManage.verifySuccessMessageVisibilityAndContent( - // facilityHfridToastNotificationText, - // true, - // ); - // // verify its reflection - // facilityPage.clickManageFacilityDropdown(); - // facilityManage.clickFacilityConfigureButton(); - // facilityManage.verifyHfrIdValue(facilityUpdatedHfrId); - // }); + it("Configure Facility Health ID", () => { + facilityPage.clickManageFacilityDropdown(); + facilityManage.clickFacilityConfigureButton(); + // verify mandatory field error message + facilityManage.clearHfrId(); + facilityManage.clickButtonWithText(facilityHfridUpdateButton); + facilityManage.checkErrorMessageVisibility( + "Health Facility Id is required", + ); + // add facility health ID and verify notification + facilityManage.typeHfrId(facilityHfrId); + facilityManage.clickButtonWithText(facilityHfridUpdateButton); + facilityManage.verifySuccessMessageVisibilityAndContent( + facilityHfridToastNotificationText, + true, + ); + // update the existing middleware + facilityPage.clickManageFacilityDropdown(); + facilityManage.clickFacilityConfigureButton(); + facilityManage.typeHfrId(facilityUpdatedHfrId); + facilityManage.clickButtonWithText(facilityHfridUpdateButton); + facilityManage.verifySuccessMessageVisibilityAndContent( + facilityHfridToastNotificationText, + true, + ); + // verify its reflection + facilityPage.clickManageFacilityDropdown(); + facilityManage.clickFacilityConfigureButton(); + facilityManage.verifyHfrIdValue(facilityUpdatedHfrId); + }); it("Modify doctor capacity in Facility detail page", () => { // Add a doctor capacity diff --git a/cypress/e2e/hcx_spec/HcxClaims.cy.ts b/cypress/e2e/hcx_spec/HcxClaims.cy.ts index b698bb7ffd8..ccaa628febb 100644 --- a/cypress/e2e/hcx_spec/HcxClaims.cy.ts +++ b/cypress/e2e/hcx_spec/HcxClaims.cy.ts @@ -18,7 +18,7 @@ describe("HCX Claims configuration and approval workflow", () => { const patientInsurerName = "Demo Payor"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientBedManagement.cy.ts b/cypress/e2e/patient_spec/PatientBedManagement.cy.ts index 94f0869db9b..fbc31ff9698 100644 --- a/cypress/e2e/patient_spec/PatientBedManagement.cy.ts +++ b/cypress/e2e/patient_spec/PatientBedManagement.cy.ts @@ -15,7 +15,7 @@ describe("Patient swtich bed functionality", () => { const switchPatientTwo = "Dummy Patient Seven"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts b/cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts index 3eacd9b718f..4191d63b3e2 100644 --- a/cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts +++ b/cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts @@ -38,7 +38,7 @@ describe("Patient Consultation in multiple combination", () => { const patientIpNumber = `${Math.floor(Math.random() * 90 + 10)}/${Math.floor(Math.random() * 9000 + 1000)}`; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientConsultationDischarge.cy.ts b/cypress/e2e/patient_spec/PatientConsultationDischarge.cy.ts index 9e234c860da..b7ef6936804 100644 --- a/cypress/e2e/patient_spec/PatientConsultationDischarge.cy.ts +++ b/cypress/e2e/patient_spec/PatientConsultationDischarge.cy.ts @@ -20,7 +20,7 @@ describe("Patient Discharge based on multiple reason", () => { const doctorName = "Custom Doctor"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts b/cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts index 474af286b21..9dd43da4e13 100644 --- a/cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts +++ b/cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts @@ -13,7 +13,7 @@ describe("Patient Doctor Connect in consultation page", () => { const teleIcuUser = "Tester Doctor"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts b/cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts index d227d68ddcb..4fe19329af1 100644 --- a/cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts +++ b/cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts @@ -14,7 +14,7 @@ describe("Patient Discussion notes in the consultation page", () => { const discussionNotesSuccessMessage = "Note added successfully"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientFileUpload.cy.ts b/cypress/e2e/patient_spec/PatientFileUpload.cy.ts index dd3098163ec..ebf85d2cfad 100644 --- a/cypress/e2e/patient_spec/PatientFileUpload.cy.ts +++ b/cypress/e2e/patient_spec/PatientFileUpload.cy.ts @@ -18,7 +18,7 @@ function runTests( const patientNameTwo = "Dummy Patient Four"; const patientNameThree = "Dummy Patient Five"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -63,7 +63,7 @@ function runTests( it("User-level Based Permission for File Modification", () => { // Login as Nurse 1 - loginPage.login("dummynurse1", "Coronasafe@123"); + loginPage.loginByRole("nurse"); cy.reload(); // Visit the patient details page patientPage.visitPatient(patientNameThree); @@ -85,13 +85,13 @@ function runTests( cy.closeNotification(); patientFileUpload.verifyUploadFilePresence(newFileName); // Login as Nurse 2 - loginPage.login("dummynurse2", "Coronasafe@123"); + loginPage.loginByRole("nurse2"); cy.reload(); // Verify the file edit option is not available patientFileUpload.verifyUploadFilePresence(newFileName); patientFileUpload.verifyFileRenameOption(false); // Login as District Admin - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.reload(); // Verify the file edit option is available patientFileUpload.verifyUploadFilePresence(newFileName); diff --git a/cypress/e2e/patient_spec/PatientHomepage.cy.ts b/cypress/e2e/patient_spec/PatientHomepage.cy.ts index e2c32098f1c..2d8d20572bc 100644 --- a/cypress/e2e/patient_spec/PatientHomepage.cy.ts +++ b/cypress/e2e/patient_spec/PatientHomepage.cy.ts @@ -27,7 +27,7 @@ describe("Patient Homepage present functionalities", () => { const patientToDateBadge = "2023-12-07"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientInvestigation.cy.ts b/cypress/e2e/patient_spec/PatientInvestigation.cy.ts index 350614d0c9a..27d68aa257f 100644 --- a/cypress/e2e/patient_spec/PatientInvestigation.cy.ts +++ b/cypress/e2e/patient_spec/PatientInvestigation.cy.ts @@ -10,7 +10,7 @@ describe("Patient Investigation Creation from Patient consultation page", () => const patientName = "Dummy Patient Thirteen"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts b/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts index cfb739c8343..ec5aef250dc 100644 --- a/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts +++ b/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts @@ -41,7 +41,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { const domicilaryPatient = "Dummy Patient Eleven"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientPrescription.cy.ts b/cypress/e2e/patient_spec/PatientPrescription.cy.ts index 96e6e23b1aa..61f8067eea0 100644 --- a/cypress/e2e/patient_spec/PatientPrescription.cy.ts +++ b/cypress/e2e/patient_spec/PatientPrescription.cy.ts @@ -15,7 +15,7 @@ const medicineIndicator = "Test Indicator"; describe("Patient Medicine Administration", () => { before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientRegistration.cy.ts b/cypress/e2e/patient_spec/PatientRegistration.cy.ts index 2da35c840e0..a7c869401cd 100644 --- a/cypress/e2e/patient_spec/PatientRegistration.cy.ts +++ b/cypress/e2e/patient_spec/PatientRegistration.cy.ts @@ -70,7 +70,7 @@ describe("Patient Creation with consultation", () => { const patientOccupation = "Student"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/resource_spec/ResourcesAdvanceFilters.cy.ts b/cypress/e2e/resource_spec/ResourcesAdvanceFilters.cy.ts index aafc03680ee..33e11b4987a 100644 --- a/cypress/e2e/resource_spec/ResourcesAdvanceFilters.cy.ts +++ b/cypress/e2e/resource_spec/ResourcesAdvanceFilters.cy.ts @@ -1,6 +1,10 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); + describe("Resource filter", () => { before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts b/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts index 299d753d720..23077a71ed8 100644 --- a/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts +++ b/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts @@ -1,3 +1,5 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; + import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import LoginPage from "../../pageobject/Login/LoginPage"; import ResourcePage from "../../pageobject/Resource/ResourcePage"; @@ -7,10 +9,11 @@ describe("Resource Page", () => { const loginPage = new LoginPage(); const resourcePage = new ResourcePage(); const facilityPage = new FacilityPage(); + const facilityHome = new FacilityHome(); const phone_number = "9999999999"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -39,8 +42,8 @@ describe("Resource Page", () => { }); it("Create a resource request", () => { - cy.visit("/facility"); - cy.get("#search").click().type("dummy facility 40"); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch("dummy facility 40"); cy.intercept("GET", "**/api/v1/facility/**").as("loadFacilities"); cy.get("#facility-details").click(); cy.wait("@loadFacilities").its("response.statusCode").should("eq", 200); diff --git a/cypress/e2e/sample_test_spec/SampleTestAdvanceFilters.cy.ts b/cypress/e2e/sample_test_spec/SampleTestAdvanceFilters.cy.ts index ad2e57b7433..562eb22a75e 100644 --- a/cypress/e2e/sample_test_spec/SampleTestAdvanceFilters.cy.ts +++ b/cypress/e2e/sample_test_spec/SampleTestAdvanceFilters.cy.ts @@ -1,6 +1,10 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); + describe("Sample Filter", () => { before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/sample_test_spec/SampleTestHomepage.cy.ts b/cypress/e2e/sample_test_spec/SampleTestHomepage.cy.ts index 98d69ccff41..491da5ee7ad 100644 --- a/cypress/e2e/sample_test_spec/SampleTestHomepage.cy.ts +++ b/cypress/e2e/sample_test_spec/SampleTestHomepage.cy.ts @@ -1,6 +1,10 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); + describe("Sample List", () => { before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts b/cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts index da4d8aabd20..a4b26d328e5 100644 --- a/cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts +++ b/cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts @@ -24,7 +24,7 @@ describe("Sample Test", () => { const sampleTestResult = "Awaiting"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/shifting_spec/ShiftingAdvanceFilters.cy.ts b/cypress/e2e/shifting_spec/ShiftingAdvanceFilters.cy.ts index 01c1cbebd3a..1a773350b2d 100644 --- a/cypress/e2e/shifting_spec/ShiftingAdvanceFilters.cy.ts +++ b/cypress/e2e/shifting_spec/ShiftingAdvanceFilters.cy.ts @@ -1,12 +1,14 @@ +import LoginPage from "pageobject/Login/LoginPage"; import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; import ShiftingPage from "../../pageobject/Shift/ShiftFilters"; describe("Shifting section filter", () => { const shiftingPage = new ShiftingPage(); + const loginPage = new LoginPage(); before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/shifting_spec/ShiftingHomepage.cy.ts b/cypress/e2e/shifting_spec/ShiftingHomepage.cy.ts index a0a637f97f1..a94de68591d 100644 --- a/cypress/e2e/shifting_spec/ShiftingHomepage.cy.ts +++ b/cypress/e2e/shifting_spec/ShiftingHomepage.cy.ts @@ -1,6 +1,10 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); + describe("Shifting Page", () => { before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/users_spec/UsersCreation.cy.ts b/cypress/e2e/users_spec/UsersCreation.cy.ts index f495a136d97..1c720e7df12 100644 --- a/cypress/e2e/users_spec/UsersCreation.cy.ts +++ b/cypress/e2e/users_spec/UsersCreation.cy.ts @@ -1,4 +1,8 @@ -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import FacilityHome from "pageobject/Facility/FacilityHome"; +import ManageUserPage from "pageobject/Users/ManageUserPage"; +import UserProfilePage from "pageobject/Users/UserProfilePage"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import LoginPage from "../../pageobject/Login/LoginPage"; import { UserCreationPage } from "../../pageobject/Users/UserCreation"; @@ -11,13 +15,15 @@ import { describe("User Creation", () => { const userPage = new UserPage(); const loginPage = new LoginPage(); + const userProfilePage = new UserProfilePage(); + const manageUserPage = new ManageUserPage(); const userCreationPage = new UserCreationPage(); const facilityPage = new FacilityPage(); - const assetSearchPage = new AssetSearchPage(); - const phone_number = generatePhoneNumber(); - const emergency_phone_number = generateEmergencyPhoneNumber(); + const facilityHome = new FacilityHome(); + const phoneNumber = generatePhoneNumber(); + const emergencyPhoneNumber = generateEmergencyPhoneNumber(); const fillFacilityName = "Dummy Facility 40"; - const makeid = (length: number) => { + const makeId = (length: number) => { let result = ""; const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; const charactersLength = characters.length; @@ -26,8 +32,8 @@ describe("User Creation", () => { } return result; }; - const username = makeid(8); - const alreadylinkedusersviews = [ + const username = makeId(8); + const alreadyLinkedUsersViews = [ "devdoctor", "devstaff2", "devdistrictadmin", @@ -53,9 +59,28 @@ describe("User Creation", () => { "This field is required", "Please enter valid phone number", ]; + const userName = "devdistrictadmin"; + const firstName = "District Editted"; + const lastName = "Cypress"; + const gender = "Male"; + const email = "test@test.com"; + const password = "Test@123"; + const qualification = "MBBS"; + const experience = "2"; + const regNo = "123456789"; + const newUserFirstName = "cypress test"; + const newUserLastName = "staff user"; + const state = "Kerala"; + const district = "Ernakulam"; + const role = "Doctor"; + const homeFacility = "Dummy Shifting Center"; + const weeklyWorkingHrs = "14"; + const dob = "01011998"; + const formattedDob = "01/01/1998"; + const newUserDob = "25081999"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -66,135 +91,107 @@ describe("User Creation", () => { }); it("Update the existing user profile and verify its reflection", () => { - userCreationPage.clickElementById("user-profile-name"); - userCreationPage.clickElementById("profile-button"); - userCreationPage.verifyElementContainsText( - "username-profile-details", - "devdistrictadmin", - ); - userCreationPage.clickElementById("edit-cancel-profile-button"); - userCreationPage.typeIntoElementByIdPostClear( - "firstName", - "District Editted", - ); - userCreationPage.typeIntoElementByIdPostClear("lastName", "Cypress"); - userCreationPage.selectDropdownOption("gender", "Male"); - userCreationPage.typeIntoElementByIdPostClear("phoneNumber", phone_number); - userCreationPage.typeIntoElementByIdPostClear( - "altPhoneNumber", - emergency_phone_number, - ); - userCreationPage.typeIntoElementByIdPostClear("email", "test@test.com"); - userCreationPage.typeIntoElementByIdPostClear("weekly_working_hours", "14"); - userCreationPage.typeIntoElementByIdPostClearDob( - "date_of_birth", - "01011998", - ); - userCreationPage.clickElementById("submit"); - userCreationPage.verifyElementContainsText( - "contactno-profile-details", - "+91" + phone_number, - ); - userCreationPage.verifyElementContainsText( - "whatsapp-profile-details", - "+91" + emergency_phone_number, - ); - userCreationPage.verifyElementContainsText( - "firstname-profile-details", - "District Editted", - ); - userCreationPage.verifyElementContainsText( - "lastname-profile-details", - "Cypress", - ); - userCreationPage.verifyElementContainsText( - "date_of_birth-profile-details", - "01/01/1998", - ); - userCreationPage.verifyElementContainsText( - "emailid-profile-details", - "test@test.com", - ); - userCreationPage.verifyElementContainsText( - "gender-profile-details", - "Male", - ); - userCreationPage.verifyElementContainsText( - "averageworkinghour-profile-details", - "14", - ); + manageUserPage.navigateToProfile(); + cy.verifyContentPresence("#username-profile-details", [userName]); + userProfilePage.clickEditProfileButton(); + userCreationPage.clearFirstName(); + userCreationPage.typeFirstName(firstName); + userCreationPage.clearLastName(); + userCreationPage.typeLastName(lastName); + userProfilePage.selectGender(gender); + userProfilePage.clearPhoneNumber(); + userProfilePage.typePhoneNumber(phoneNumber); + userProfilePage.clearAltPhoneNumber(); + userProfilePage.typeWhatsappNumber(emergencyPhoneNumber); + userProfilePage.clearEmail(); + userProfilePage.typeEmail(email); + userProfilePage.clearWorkingHours(); + userProfilePage.typeWorkingHours(weeklyWorkingHrs); + userProfilePage.typeDateOfBirth(dob); + cy.intercept("PATCH", "/api/v1/users/*").as("updateUser"); + userProfilePage.clickUpdateButton(); + cy.wait("@updateUser").its("response.statusCode").should("eq", 200); + cy.verifyContentPresence("#contactno-profile-details", [ + "+91" + phoneNumber, + ]); + cy.verifyContentPresence("#whatsapp-profile-details", [ + "+91" + emergencyPhoneNumber, + ]); + cy.verifyContentPresence("#firstname-profile-details", [firstName]); + cy.verifyContentPresence("#lastname-profile-details", [lastName]); + cy.verifyContentPresence("#date_of_birth-profile-details", [formattedDob]); + cy.verifyContentPresence("#emailid-profile-details", [email]); + cy.verifyContentPresence("#gender-profile-details", [gender]); + cy.verifyContentPresence("#averageworkinghour-profile-details", [ + weeklyWorkingHrs, + ]); }); it("Update the existing user profile Form Mandatory File Error", () => { - userCreationPage.clickElementById("user-profile-name"); - userCreationPage.clickElementById("profile-button"); - userCreationPage.clickElementById("edit-cancel-profile-button"); - userCreationPage.clearIntoElementById("firstName"); - userCreationPage.clearIntoElementById("lastName"); - userCreationPage.clearIntoElementById("phoneNumber"); - userCreationPage.clearIntoElementById("altPhoneNumber"); - userCreationPage.clearIntoElementById("weekly_working_hours"); - userCreationPage.clickElementById("submit"); + manageUserPage.navigateToProfile(); + userProfilePage.clickEditProfileButton(); + userCreationPage.clearFirstName(); + userCreationPage.clearLastName(); + userProfilePage.clearPhoneNumber(); + userProfilePage.clearAltPhoneNumber(); + userProfilePage.clearWorkingHours(); + userProfilePage.clickUpdateButton(); userCreationPage.verifyErrorMessages(EXPECTED_PROFILE_ERROR_MESSAGES); }); it("create new user and verify reflection", () => { - userCreationPage.clickElementById("addUserButton"); - userCreationPage.selectFacility("Dummy Shifting Center"); - userCreationPage.typeIntoElementById("username", username); - userCreationPage.typeIntoElementById("password", "Test@123"); - userCreationPage.selectHomeFacility("Dummy Shifting Center"); - userCreationPage.typeIntoElementById("phone_number", phone_number); - userCreationPage.setInputDate("date_of_birth", "25081999"); - userCreationPage.selectDropdownOption("user_type", "Doctor"); - userCreationPage.typeIntoElementById("c_password", "Test@123"); - userCreationPage.typeIntoElementById("qualification", "MBBS"); - userCreationPage.typeIntoElementById("doctor_experience_commenced_on", "2"); - userCreationPage.typeIntoElementById( - "doctor_medical_council_registration", - "123456789", - ); - userCreationPage.typeIntoElementById("first_name", "cypress test"); - userCreationPage.typeIntoElementById("last_name", "staff user"); - userCreationPage.typeIntoElementById("email", "test@test.com"); - userCreationPage.selectDropdownOption("gender", "Male"); - userCreationPage.selectDropdownOption("state", "Kerala"); - userCreationPage.selectDropdownOption("district", "Ernakulam"); - userCreationPage.clickElementById("submit"); - userCreationPage.verifyNotification("User added successfully"); + userCreationPage.clickAddUserButton(); + userCreationPage.selectFacility(homeFacility); + userCreationPage.typeUserName(username); + userCreationPage.typePassword(password); + userCreationPage.typeConfirmPassword(password); + userCreationPage.selectHomeFacility(homeFacility); + userPage.typeInPhoneNumber(phoneNumber); + userProfilePage.typeDateOfBirth(newUserDob); + userCreationPage.selectUserType(role); + userProfilePage.typeQualification(qualification); + userProfilePage.typeDoctorYoE(experience); + userProfilePage.typeMedicalCouncilRegistration(regNo); + userPage.typeInFirstName(newUserFirstName); + userPage.typeInLastName(newUserLastName); + userProfilePage.typeEmail(email); + userCreationPage.selectGender(gender); + userCreationPage.selectState(state); + userCreationPage.selectDistrict(district); + cy.intercept("POST", "/api/v1/users/add_user/").as("createUser"); + userCreationPage.clickSaveUserButton(); + cy.wait("@createUser").its("response.statusCode").should("eq", 201); + cy.verifyNotification("User added successfully"); userPage.typeInSearchInput(username); userPage.checkUsernameText(username); - userCreationPage.verifyElementContainsText("name", "cypress test"); - userCreationPage.verifyElementContainsText("role", "Doctor"); - userCreationPage.verifyElementContainsText("district", "Ernakulam"); - userCreationPage.verifyElementContainsText( - "home_facility", - "Dummy Shifting Center", - ); - userCreationPage.verifyElementContainsText("qualification", "MBBS"); - userCreationPage.verifyElementContainsText("doctor-experience", "2"); - userCreationPage.verifyElementContainsText( - "medical-council-registration", - "123456789", - ); + cy.verifyContentPresence("#name", [newUserFirstName]); + cy.verifyContentPresence("#role", [role]); + cy.verifyContentPresence("#district", [district]); + cy.verifyContentPresence("#home_facility", [homeFacility]); + cy.verifyContentPresence("#qualification", [qualification]); + cy.verifyContentPresence("#doctor-experience", [experience]); + cy.verifyContentPresence("#medical-council-registration", [regNo]); }); it("create new user form throwing mandatory field error", () => { - userCreationPage.clickElementById("addUserButton"); - userCreationPage.clickElementById("submit"); - cy.wait(2000); + userCreationPage.clickAddUserButton(); + userCreationPage.clickSaveUserButton(); + cy.get(".error-text", { timeout: 10000 }).should("be.visible"); userCreationPage.verifyErrorMessages(EXPECTED_ERROR_MESSAGES); }); it("view user redirection from facility page", () => { - cy.visit("/facility"); - assetSearchPage.typeSearchKeyword(fillFacilityName); - assetSearchPage.pressEnter(); - facilityPage.verifyFacilityBadgeContent(fillFacilityName); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(fillFacilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + fillFacilityName, + true, + ); facilityPage.visitAlreadyCreatedFacility(); facilityPage.clickManageFacilityDropdown(); facilityPage.clickViewUsersOption(); - userPage.verifyMultipleBadgesWithSameId(alreadylinkedusersviews); + userPage.verifyMultipleBadgesWithSameId(alreadyLinkedUsersViews); }); afterEach(() => { diff --git a/cypress/e2e/users_spec/UsersHomepage.cy.ts b/cypress/e2e/users_spec/UsersHomepage.cy.ts index b32bb859e4e..8d86482645b 100644 --- a/cypress/e2e/users_spec/UsersHomepage.cy.ts +++ b/cypress/e2e/users_spec/UsersHomepage.cy.ts @@ -20,7 +20,7 @@ describe("User Homepage", () => { const doctorUserName = "dev-doctor2"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -43,30 +43,28 @@ describe("User Homepage", () => { advanceFilters.applySelectedFilter(); userPage.checkUsernameText(nurseUserName); // Verify the badges related to the data - userPage.verifyDataTestIdText("First Name", `First Name: ${firstName}`); - userPage.verifyDataTestIdText("Last Name", `Last Name: ${lastName}`); - userPage.verifyDataTestIdText( - "Phone Number", - `Phone Number: +91${phoneNumber}`, - ); - userPage.verifyDataTestIdText( + advanceFilters.verifyFilterBadgePresence("First Name", firstName, true); + advanceFilters.verifyFilterBadgePresence("Last Name", lastName, true); + advanceFilters.verifyFilterBadgePresence("Phone Number", phoneNumber, true); + advanceFilters.verifyFilterBadgePresence( "WhatsApp no.", - `WhatsApp no.: +91${altPhoneNumber}`, + altPhoneNumber, + true, ); - userPage.verifyDataTestIdText("Role", `Role: ${role}`); - userPage.verifyDataTestIdText( + advanceFilters.verifyFilterBadgePresence("Role", role, true); + advanceFilters.verifyFilterBadgePresence( "Home Facility", - `Home Facility: ${homeFacility}`, + homeFacility, + true, ); advanceFilters.clickAdvancedFiltersButton(); advanceFilters.clickClearAdvanceFilters(); - userPage.verifyDataTestIdNotVisible("First Name"); - userPage.verifyDataTestIdNotVisible("Last Name"); - userPage.verifyDataTestIdNotVisible("Phone Number"); - userPage.verifyDataTestIdNotVisible("WhatsApp no."); - userPage.verifyDataTestIdNotVisible("Role"); - userPage.verifyDataTestIdNotVisible("Home Facility"); - userPage.verifyDataTestIdNotVisible("District"); + advanceFilters.verifyFilterBadgePresence("First Name", "", false); + advanceFilters.verifyFilterBadgePresence("Last Name", "", false); + advanceFilters.verifyFilterBadgePresence("Phone Number", "", false); + advanceFilters.verifyFilterBadgePresence("WhatsApp no.", "", false); + advanceFilters.verifyFilterBadgePresence("Role", "", false); + advanceFilters.verifyFilterBadgePresence("Home Facility", "", false); }); it("Search by username", () => { diff --git a/cypress/e2e/users_spec/UsersManage.cy.ts b/cypress/e2e/users_spec/UsersManage.cy.ts index 40d436be0a6..41557e87756 100644 --- a/cypress/e2e/users_spec/UsersManage.cy.ts +++ b/cypress/e2e/users_spec/UsersManage.cy.ts @@ -1,21 +1,21 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; import LoginPage from "../../pageobject/Login/LoginPage"; import ManageUserPage from "../../pageobject/Users/ManageUserPage"; -import { UserCreationPage } from "../../pageobject/Users/UserCreation"; import { UserPage } from "../../pageobject/Users/UserSearch"; describe("Manage User", () => { const loginPage = new LoginPage(); const userPage = new UserPage(); const manageUserPage = new ManageUserPage(); + const facilityHome = new FacilityHome(); const usernameToLinkFacilitydoc1 = "dummydoctor4"; const usernameToLinkFacilitydoc2 = "dummydoctor5"; const usernameToLinkFacilitydoc3 = "dummydoctor6"; const usernameToLinkSkill = "devdoctor"; const firstNameUserSkill = "Dev"; const lastNameUserSkill = "Doctor"; - const userCreationPage = new UserCreationPage(); const usernameforworkinghour = "devdistrictadmin"; const usernamerealname = "Dummy Doctor"; const facilitytolinkusername = "Dummy Shifting Center"; @@ -24,7 +24,7 @@ describe("Manage User", () => { const linkedskill = "General Medicine"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -48,10 +48,9 @@ describe("Manage User", () => { manageUserPage.clickCloseSlideOver(); cy.wait(5000); manageUserPage.navigateToProfile(); - userCreationPage.verifyElementContainsText( - "username-profile-details", + cy.verifyContentPresence("#username-profile-details", [ usernameforworkinghour, - ); + ]); manageUserPage.assertSkillInAlreadyLinkedSkills(linkedskill); }); @@ -71,9 +70,9 @@ describe("Manage User", () => { manageUserPage.assertSkillInAddedUserSkills(linkedskill); manageUserPage.clickCloseSlideOver(); // verifying the doctor connect - manageUserPage.navigateToFacility(); - manageUserPage.typeFacilitySearch(facilitytolinkskill); - manageUserPage.assertFacilityInCard(facilitytolinkskill); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(facilitytolinkskill); + facilityHome.assertFacilityInCard(facilitytolinkskill); manageUserPage.clickFacilityPatients(); manageUserPage.clickDoctorConnectButton(); manageUserPage.assertSkillIndoctorconnect(linkedskill); @@ -137,9 +136,9 @@ describe("Manage User", () => { 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); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(facilitytolinkusername); + facilityHome.assertFacilityInCard(facilitytolinkusername); manageUserPage.clickFacilityPatients(); manageUserPage.clickDoctorConnectButton(); manageUserPage.assertDoctorConnectVisibility(usernamerealname); diff --git a/cypress/e2e/users_spec/UsersProfile.cy.ts b/cypress/e2e/users_spec/UsersProfile.cy.ts index 35771024180..551fba4c0f1 100644 --- a/cypress/e2e/users_spec/UsersProfile.cy.ts +++ b/cypress/e2e/users_spec/UsersProfile.cy.ts @@ -1,3 +1,5 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; + import LoginPage from "../../pageobject/Login/LoginPage"; import ManageUserPage from "../../pageobject/Users/ManageUserPage"; import UserProfilePage from "../../pageobject/Users/UserProfilePage"; @@ -6,6 +8,7 @@ describe("Manage User Profile", () => { const loginPage = new LoginPage(); const userProfilePage = new UserProfilePage(); const manageUserPage = new ManageUserPage(); + const facilityHome = new FacilityHome(); const date_of_birth = "01011999"; const gender = "Male"; @@ -19,7 +22,7 @@ describe("Manage User Profile", () => { const facilitySearch = "Dummy Facility 40"; before(() => { - loginPage.loginAsDevDoctor(); + loginPage.loginByRole("devDoctor"); cy.saveLocalStorage(); }); @@ -32,25 +35,22 @@ describe("Manage User Profile", () => { it("Set Dob, Gender, Email, Phone and Working Hours for a user and verify its reflection in user profile", () => { userProfilePage.clickEditProfileButton(); - userProfilePage.typedate_of_birth(date_of_birth); + userProfilePage.typeDateOfBirth(date_of_birth); userProfilePage.selectGender(gender); userProfilePage.typeEmail(email); - userProfilePage.typePhone(phone); - userProfilePage.typeWhatsApp(phone); + userProfilePage.typePhoneNumber(phone); + userProfilePage.typeWhatsappNumber(phone); userProfilePage.typeWorkingHours(workinghours); userProfilePage.typeQualification(qualification); userProfilePage.typeDoctorYoE(doctorYoE); userProfilePage.typeMedicalCouncilRegistration(medicalCouncilRegistration); - userProfilePage.clickUpdateButton(); - cy.verifyNotification("Details updated successfully"); - - userProfilePage.assertdate_of_birth("01/01/1999"); + userProfilePage.assertDateOfBirth("01/01/1999"); userProfilePage.assertGender(gender); userProfilePage.assertEmail(email); - userProfilePage.assertPhone(phone); - userProfilePage.assertWhatsApp(phone); + userProfilePage.assertPhoneNumber(phone); + userProfilePage.assertAltPhoneNumber(phone); userProfilePage.assertWorkingHours(workinghours); }); @@ -68,9 +68,9 @@ describe("Manage User Profile", () => { userProfilePage.clickUpdateButton(); userProfilePage.assertVideoConnectLink("https://www.test.com"); // Go to particular facility doctor connect and verify the video connect link is present - manageUserPage.navigateToFacility(); - manageUserPage.typeFacilitySearch(facilitySearch); - manageUserPage.assertFacilityInCard(facilitySearch); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(facilitySearch); + facilityHome.assertFacilityInCard(facilitySearch); manageUserPage.clickFacilityPatients(); manageUserPage.clickDoctorConnectButton(); manageUserPage.assertVideoConnectLink("Dev Doctor", "https://www.test.com"); diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index ec631768154..5e590a0f7fd 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -208,51 +208,6 @@ export class AssetPage { ); } - selectImportFacility(facilityName: string) { - cy.get("input[name='facilities']") - .type(facilityName) - .then(() => { - cy.get("[role='option']").contains(facilityName).click(); - }); - } - - selectassetimportbutton() { - cy.get("[data-testid=import-asset-button]").click(); - } - - selectJsonExportButton() { - cy.intercept("GET", "**/api/v1/asset/?**json=true**").as("getJsonexport"); - cy.get("#export-json-option").click(); - cy.wait("@getJsonexport").its("response.statusCode").should("eq", 200); - } - - selectCsvExportButton() { - cy.intercept("GET", "**/api/v1/asset/?**csv=true**").as("getCsvexport"); - cy.get("#export-csv-option").click(); - cy.wait("@getCsvexport").its("response.statusCode").should("eq", 200); - } - - selectImportOption() { - cy.get(".import-assets-button").click(); - } - - importAssetFile() { - cy.get("[data-testid=import-file]") - .selectFile("cypress/fixtures/sample-asset.xlsx", { force: true }) - .wait(100); - } - - selectImportLocation(locationName: string) { - cy.get("[data-testid=select-import-location]").click(); - cy.get("li[role=option]").contains(locationName).click(); - } - - clickImportAsset() { - cy.intercept("POST", "**/api/v1/asset/").as("importAsset"); - cy.get("#submit").contains("Import").click(); - cy.wait("@importAsset").its("response.statusCode").should("eq", 201); - } - clickupdatedetailbutton() { cy.get("[data-testid=asset-update-button]").click(); } diff --git a/cypress/pageobject/Asset/AssetFilters.ts b/cypress/pageobject/Asset/AssetFilters.ts index 7e7b5013d5d..b562841a598 100644 --- a/cypress/pageobject/Asset/AssetFilters.ts +++ b/cypress/pageobject/Asset/AssetFilters.ts @@ -1,68 +1,7 @@ export class AssetFilters { - filterAssets( - facilityName: string, - assetStatus: string, - assetClass: string, - assetLocation: string, - ) { - cy.contains("Advanced Filters").click(); - cy.get("input[name='Facilities']") - .click() - .type(facilityName) - .then(() => { - cy.get("[role='option']").contains(facilityName).click(); - }); - cy.get("#asset-status") - .click() - .then(() => { - cy.get("[role='option']").contains(assetStatus).click(); - }); - cy.get("#asset-class") - .click() - .then(() => { - cy.get("[role='option']").contains(assetClass).click(); - }); - cy.get("#Facilities-location") - .click() - .type(assetLocation) - .then(() => { - cy.get("[role='option']").contains(assetLocation).click(); - }); - cy.contains("Apply").click(); - } - clearFilters() { - cy.intercept("GET", "**/api/v1/asset/**").as("clearAssets"); - cy.get("#clear-filter").click(); - cy.wait("@clearAssets").its("response.statusCode").should("eq", 200); - cy.location("pathname").should("match", /\/assets$/); - cy.url().then((url) => { - const queryParams = new URL(url).searchParams; - let allEmpty = true; - const blacklistedKeys = ["page", "limit", "offset"]; - - queryParams.forEach((value, key) => { - if (value !== "" && !blacklistedKeys.includes(key)) { - allEmpty = false; - } - }); - - expect(allEmpty).to.be.true; - }); - } - clickslideoverbackbutton() { - cy.get("#close-slide-over").click(); - } - // Assertions - assertFacilityText(text: string) { - cy.get("[data-testid=Facility]").should("contain", text); - } - assertAssetClassText(text: string) { - cy.get("[data-testid='Asset Class']").should("contain", text); - } - assertStatusText(text: string) { - cy.get("[data-testid=Status]").should("contain", text); - } - assertLocationText(text: string) { - cy.get("[data-testid=Location]").should("contain", text); + filterAssets(assetStatus: string, assetClass: string, assetLocation: string) { + cy.clickAndSelectOption("#asset-status", assetStatus); + cy.clickAndSelectOption("#asset-class", assetClass); + cy.typeAndSelectOption("#Facilities-location", assetLocation); } } diff --git a/cypress/pageobject/Asset/AssetHome.ts b/cypress/pageobject/Asset/AssetHome.ts new file mode 100644 index 00000000000..e127b785100 --- /dev/null +++ b/cypress/pageobject/Asset/AssetHome.ts @@ -0,0 +1,112 @@ +export class AssetHome { + clickAssetByName(assetName: string) { + cy.intercept("GET", "**/api/v1/asset/**").as("clearAssets"); + cy.get("[data-testid='created-asset-list']").contains(assetName).click(); + cy.wait("@clearAssets").its("response.statusCode").should("eq", 200); + } + + typeAssetSearch(name: string) { + cy.get("#asset-search").click().type(name); + } + + verifyAssetIsPresent(assetName: string) { + cy.get("[data-testid=created-asset-list]") + .first() + .should("contain", assetName); + } + + clickAssetDetailsUpdateButton() { + cy.verifyAndClickElement("[data-testid='asset-update-button']", "Update"); + } + + clearAndTypeQRCode(qrCode: string) { + cy.get("#qr_code_id").clear(); + cy.get("#qr_code_id").click().type(qrCode); + } + + clearAndTypeSerialNumber(serialNumber: string) { + cy.get("#serial-number").clear(); + cy.get("#serial-number").click().type(serialNumber); + } + + clickAssetSubmitButton() { + cy.intercept("GET", "**/api/v1/asset/**").as("getAssets"); + cy.get("#submit").click(); + cy.wait("@getAssets").its("response.statusCode").should("eq", 200); + } + + clickAssetUpdateSubmitButton() { + cy.intercept("GET", "**/api/v1/asset/**").as("getAssets"); + cy.clickSubmitButton("Update"); + cy.wait("@getAssets").its("response.statusCode").should("eq", 200); + } + + navigateToAssetsPage() { + cy.visit("/assets"); + } + + verifyAssetListContains(dummyCameraText: string) { + cy.get("[data-testid='created-asset-list']").should( + "contain", + dummyCameraText, + ); + } + + scanAssetQR() { + cy.contains("Scan Asset QR").click().wait(1000); + cy.get("video").should("exist"); + cy.get("button").contains("Close Scanner").should("exist").click(); + } + + selectImportFacility(facilityName: string) { + cy.get("input[name='facilities']") + .type(facilityName) + .then(() => { + cy.get("[role='option']").contains(facilityName).click(); + }); + } + + selectAssetImportButton(action: "click" | "verifyNotExist"): void { + const selector = "[data-testid=import-asset-button]"; + if (action === "click") { + cy.get(selector).click(); + } else if (action === "verifyNotExist") { + cy.get(selector).should("not.exist"); + } + } + + selectJsonExportButton() { + cy.intercept("GET", "**/api/v1/asset/?**json=true**").as("getJsonexport"); + cy.get("#export-json-option").click(); + cy.wait("@getJsonexport").its("response.statusCode").should("eq", 200); + } + + selectCsvExportButton() { + cy.intercept("GET", "**/api/v1/asset/?**csv=true**").as("getCsvexport"); + cy.get("#export-csv-option").click(); + cy.wait("@getCsvexport").its("response.statusCode").should("eq", 200); + } + + selectImportOption() { + cy.get(".import-assets-button").click(); + } + + importAssetFile() { + cy.get("[data-testid=import-file]") + .selectFile("cypress/fixtures/sample-asset.xlsx", { force: true }) + .wait(100); + } + + selectImportLocation(locationName: string) { + cy.clickAndSelectOption( + "[data-testid=select-import-location]", + locationName, + ); + } + + clickImportAsset() { + cy.intercept("POST", "**/api/v1/asset/").as("importAsset"); + cy.clickSubmitButton("Import"); + cy.wait("@importAsset").its("response.statusCode").should("eq", 201); + } +} diff --git a/cypress/pageobject/Asset/AssetPagination.ts b/cypress/pageobject/Asset/AssetPagination.ts deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/cypress/pageobject/Asset/AssetQRScan.ts b/cypress/pageobject/Asset/AssetQRScan.ts deleted file mode 100644 index a88f378f02f..00000000000 --- a/cypress/pageobject/Asset/AssetQRScan.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class AssetQRScanPage { - scanAssetQR() { - cy.contains("Scan Asset QR").click().wait(1000); - cy.get("video").should("exist"); - cy.get("button").contains("Close Scanner").should("exist").click(); - } -} diff --git a/cypress/pageobject/Asset/AssetSearch.ts b/cypress/pageobject/Asset/AssetSearch.ts deleted file mode 100644 index 653c7bdd89c..00000000000 --- a/cypress/pageobject/Asset/AssetSearch.ts +++ /dev/null @@ -1,60 +0,0 @@ -export class AssetSearchPage { - typeSearchKeyword(keyword: string) { - cy.get("#search").click().clear(); - cy.get("#search").click().type(keyword); - } - - pressEnter() { - cy.get("[name='search']").type("{enter}"); - } - - clickAssetByName(assetName: string) { - cy.intercept("GET", "**/api/v1/asset/**").as("clearAssets"); - cy.get("[data-testid='created-asset-list']").contains(assetName).click(); - cy.wait("@clearAssets").its("response.statusCode").should("eq", 200); - } - - verifyBadgeContent(expectedText: string) { - cy.get("[data-testid='Name/Serial No./QR ID']").should( - "contain", - expectedText, - ); - } - - verifyAssetIsPresent(assetName: string) { - cy.get("[data-testid=created-asset-list]") - .first() - .should("contain", assetName); - } - - clickUpdateButton() { - cy.get("[data-testid='asset-update-button']").contains("Update").click(); - } - - clearAndTypeQRCode(qrCode: string) { - cy.get("#qr_code_id").clear(); - cy.get("#qr_code_id").click().type(qrCode); - } - - clearAndTypeSerialNumber(serialNumber: string) { - cy.get("#serial-number").clear(); - cy.get("#serial-number").click().type(serialNumber); - } - - clickAssetSubmitButton() { - cy.intercept("GET", "**/api/v1/asset/**").as("getAssets"); - cy.get("#submit").click(); - cy.wait("@getAssets").its("response.statusCode").should("eq", 200); - } - - visitAssetsPage() { - cy.visit("/assets"); - } - - verifyAssetListContains(dummyCameraText: string) { - cy.get("[data-testid='created-asset-list']").should( - "contain", - dummyCameraText, - ); - } -} diff --git a/cypress/pageobject/Facility/FacilityCreation.ts b/cypress/pageobject/Facility/FacilityCreation.ts index 0fddc3f9799..4c064956fcc 100644 --- a/cypress/pageobject/Facility/FacilityCreation.ts +++ b/cypress/pageobject/Facility/FacilityCreation.ts @@ -9,11 +9,6 @@ class FacilityPage { .should("eq", 200); } - typeFacilitySearch(facilityName: string) { - cy.get("#search").click().clear(); - cy.get("#search").click().type(facilityName); - } - selectFacilityType(facility: string) { advanceFilters.selectFacilityType(facility); } @@ -313,29 +308,6 @@ class FacilityPage { cy.get("h1.text-3xl.font-bold", { timeout: 10000 }).should("be.visible"); } - verifyFacilityBadgeContent(expectedText: string) { - cy.get("[data-testid='Facility/District Name']").should( - "contain", - expectedText, - ); - } - - verifyStateBadgeContent(expectedText: string) { - cy.get("[data-testid='State']").should("contain", expectedText); - } - - verifyDistrictBadgeContent(expectedText: string) { - cy.get("[data-testid='District']").should("contain", expectedText); - } - - verifyLocalBodyBadgeContent(expectedText: string) { - cy.get("[data-testid='Local Body']").should("contain", expectedText); - } - - verifyFacilityTypeBadgeContent(expectedText: string) { - cy.get("[data-testid='Facility type']").should("contain", expectedText); - } - verifyfacilitycreateassetredirection() { cy.url().should("include", "/assets/new"); } diff --git a/cypress/pageobject/Facility/FacilityHome.ts b/cypress/pageobject/Facility/FacilityHome.ts index 30f51052370..da26cc29fc7 100644 --- a/cypress/pageobject/Facility/FacilityHome.ts +++ b/cypress/pageobject/Facility/FacilityHome.ts @@ -1,7 +1,6 @@ class FacilityHome { // Selectors exportButton = "#export-button"; - searchButton = "#search"; menuItem = "[role='menuitem']"; // Operations @@ -10,8 +9,25 @@ class FacilityHome { cy.get(this.exportButton).click(); } - clickSearchButton() { - cy.get(this.searchButton).click(); + navigateToFacilityHomepage() { + cy.visit("/facility"); + } + + assertFacilityInCard(facilityName: string) { + cy.get("#facility-name-card").should("contain", facilityName); + } + + interceptFacilitySearchReq() { + cy.intercept("GET", "**/api/v1/facility/**").as("searchFacility"); + } + + verifyFacilitySearchReq() { + cy.wait("@searchFacility").its("response.statusCode").should("eq", 200); + } + + typeFacilitySearch(facilityName: string) { + cy.get("#search-by-facility").click().clear(); + cy.get("#search-by-facility").click().type(facilityName); } clickMenuItem(itemName: string) { diff --git a/cypress/pageobject/Login/LoginPage.ts b/cypress/pageobject/Login/LoginPage.ts index 714004023f7..481c6ec3045 100644 --- a/cypress/pageobject/Login/LoginPage.ts +++ b/cypress/pageobject/Login/LoginPage.ts @@ -1,16 +1,12 @@ -// LoginPage.ts +import { users } from "../utils/userConfig"; class LoginPage { - loginAsDistrictAdmin(): void { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); - } - - loginAsDevDoctor(): void { - cy.loginByApi("devdoctor", "Coronasafe@123"); - } - - loginAsStaff(): void { - cy.loginByApi("staffdev", "Coronasafe@123"); + loginByRole(role: keyof typeof users): void { + const user = users[role]; + if (!user) { + throw new Error(`Role "${role}" is not defined in userConfig`); + } + cy.loginByApi(user.username, user.password); } loginManuallyAsDistrictAdmin(isCorrectCredentials: boolean = true): void { @@ -29,10 +25,6 @@ class LoginPage { cy.clickSubmitButton("Login"); } - login(username: string, password: string): void { - cy.loginByApi(username, password); - } - ensureLoggedIn(): void { cy.get("#user-profile-name").click(); cy.get("#sign-out-button").scrollIntoView(); diff --git a/cypress/pageobject/Users/ManageUserPage.ts b/cypress/pageobject/Users/ManageUserPage.ts index a3a6e72fbc3..01871acd97d 100644 --- a/cypress/pageobject/Users/ManageUserPage.ts +++ b/cypress/pageobject/Users/ManageUserPage.ts @@ -90,27 +90,6 @@ export class ManageUserPage { ); } - navigateToFacility() { - cy.visit("/facility"); - } - - typeFacilitySearch(facilityName: string) { - cy.get("#search").click().clear(); - cy.get("#search").click().type(facilityName); - } - - interceptFacilitySearchReq() { - cy.intercept("GET", "**/api/v1/facility/**").as("searchFacility"); - } - - verifyFacilitySearchReq() { - cy.wait("@searchFacility").its("response.statusCode").should("eq", 200); - } - - assertFacilityInCard(facilityName: string) { - cy.get("#facility-name-card").should("contain", facilityName); - } - clickFacilityPatients() { cy.get("#facility-patients").should("be.visible"); cy.get("#facility-patients").click(); diff --git a/cypress/pageobject/Users/UserCreation.ts b/cypress/pageobject/Users/UserCreation.ts index 906c07e797a..72157861f2c 100644 --- a/cypress/pageobject/Users/UserCreation.ts +++ b/cypress/pageobject/Users/UserCreation.ts @@ -1,69 +1,52 @@ // UserCreation.ts export class UserCreationPage { - clickElementById(elementId: string) { - cy.get("#" + elementId).click(); + clickAddUserButton() { + cy.verifyAndClickElement("#addUserButton", "Add New User"); } - - typeIntoElementById(elementId: string, value: string) { - cy.get("#" + elementId) - .click() - .type(value); + 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); } - - selectOptionContainingText(text: string) { - cy.get("[role='option']").contains(text).click(); + clearFirstName() { + cy.get("#firstName").click().clear(); } - - verifyNotification(message: string) { - cy.verifyNotification(message); + clearLastName() { + cy.get("#lastName").click().clear(); } - - selectFacility(name: string) { - this.typeIntoInputByName("facilities", name); - this.selectOptionContainingText(name); - cy.get("input[name='facilities'] + button") - .find("#dropdown-toggle") - .click(); + selectUserType(role: string) { + cy.clickAndSelectOption("#user_type", role); } - selectHomeFacility(name: string) { - this.clickElementById("home_facility"); - this.selectOptionContainingText(name); + cy.clickAndSelectOption("#home_facility", name); } - setInputDate(dateElementId: string, dateValue: string) { - cy.clickAndTypeDate("#" + dateElementId, dateValue); + selectGender(gender: string) { + cy.clickAndSelectOption("#gender", gender); + } + selectState(state: string) { + cy.clickAndSelectOption("#state", state); + } + selectDistrict(district: string) { + cy.clickAndSelectOption("#district", district); } - selectDropdownOption(dropdownId: string, optionText: string) { - this.clickElementById(dropdownId); - this.selectOptionContainingText(optionText); + selectFacility(name: string) { + cy.typeAndSelectOption("input[name='facilities']", name); } - verifyElementContainsText(elementId: string, expectedText: string) { - cy.get("#" + elementId).should("contain.text", expectedText); + clickSaveUserButton() { + cy.clickSubmitButton("Save User"); } verifyErrorMessages(errorMessages: string[]) { diff --git a/cypress/pageobject/Users/UserProfilePage.ts b/cypress/pageobject/Users/UserProfilePage.ts index 3744c5a5d82..882be0b7b9b 100644 --- a/cypress/pageobject/Users/UserProfilePage.ts +++ b/cypress/pageobject/Users/UserProfilePage.ts @@ -12,11 +12,24 @@ export default class UserProfilePage { } clickUpdateButton() { - cy.get("#submit").click(); + cy.clickSubmitButton("Update"); } - typedate_of_birth(date_of_birth: string) { - cy.clickAndTypeDate("#date_of_birth", date_of_birth); + typeDateOfBirth(dob: string) { + cy.clickAndTypeDate("#date_of_birth", dob); + } + + clearPhoneNumber() { + cy.get("#phoneNumber").click().clear(); + } + clearAltPhoneNumber() { + cy.get("#altPhoneNumber").click().clear(); + } + clearWorkingHours() { + cy.get("#weekly_working_hours").click().clear(); + } + clearEmail() { + cy.get("#email").click().clear(); } selectGender(gender: string) { @@ -28,16 +41,16 @@ export default class UserProfilePage { cy.get("#email").click().clear().type(email); } - typePhone(phone: string) { + typePhoneNumber(phone: string) { cy.get("#phoneNumber").click().clear().type(phone); } - typeWhatsApp(phone: string) { + typeWhatsappNumber(phone: string) { cy.get("#altPhoneNumber").click().clear().type(phone); } - typeWorkingHours(workinghours: string) { - cy.get("#weekly_working_hours").click().clear().type(workinghours); + typeWorkingHours(workingHours: string) { + cy.get("#weekly_working_hours").click().clear().type(workingHours); } typeQualification = (qualification: string) => { @@ -55,11 +68,8 @@ export default class UserProfilePage { .type(medicalCouncilRegistration); }; - assertdate_of_birth(date_of_birth: string) { - cy.get("#date_of_birth-profile-details").should( - "contain.text", - date_of_birth, - ); + assertDateOfBirth(dob: string) { + cy.get("#date_of_birth-profile-details").should("contain.text", dob); } assertGender(gender: string) { @@ -70,18 +80,18 @@ export default class UserProfilePage { cy.get("#emailid-profile-details").should("contain.text", email); } - assertPhone(phone: string) { + assertPhoneNumber(phone: string) { cy.get("#contactno-profile-details").should("contain.text", phone); } - assertWhatsApp(phone: string) { + assertAltPhoneNumber(phone: string) { cy.get("#whatsapp-profile-details").should("contain.text", phone); } - assertWorkingHours(workinghours: string) { + assertWorkingHours(workingHours: string) { cy.get("#averageworkinghour-profile-details").should( "contain.text", - workinghours, + workingHours, ); } } diff --git a/cypress/pageobject/Users/UserSearch.ts b/cypress/pageobject/Users/UserSearch.ts index 6b727aa2040..9d996abd83f 100644 --- a/cypress/pageobject/Users/UserSearch.ts +++ b/cypress/pageobject/Users/UserSearch.ts @@ -68,14 +68,6 @@ export class UserPage { cy.typeAndSelectOption("input[name='home_facility']", facility); } - verifyDataTestIdText(testId: string, text: string) { - cy.get(`[data-testid="${testId}"]`).contains(text).should("be.visible"); - } - - verifyDataTestIdNotVisible(testId: string) { - cy.get(`[data-testid="${testId}"]`).should("not.be.visible"); - } - verifyMultipleBadgesWithSameId(alreadylinkedusersviews: string[]) { cy.get("#user-view-name").then(($elements) => { const userViews = $elements diff --git a/cypress/pageobject/utils/advanceFilterHelpers.ts b/cypress/pageobject/utils/advanceFilterHelpers.ts index a624311c197..22925fc2c23 100644 --- a/cypress/pageobject/utils/advanceFilterHelpers.ts +++ b/cypress/pageobject/utils/advanceFilterHelpers.ts @@ -23,7 +23,28 @@ export const advanceFilters = { cy.clickAndSelectOption("#facility_type", facilityType); }, + typeFacilityName(facilityName: string) { + cy.typeAndSelectOption("input[name='Facilities']", facilityName); + }, + + clickslideoverbackbutton() { + cy.get("#close-slide-over").click(); + }, + clickClearAdvanceFilters() { cy.verifyAndClickElement("#clear-filter", "Clear"); }, + + verifyFilterBadgePresence( + badgeTestId: string, + text: string, + visible: boolean = true, + ) { + const badgeElement = cy.get(`[data-testid="${badgeTestId}"]`); + if (visible) { + badgeElement.contains(text).should("be.visible"); + } else { + badgeElement.should("not.be.visible"); + } + }, }; diff --git a/cypress/pageobject/utils/constants.ts b/cypress/pageobject/utils/constants.ts index 08411e84b6a..053d0561ce8 100644 --- a/cypress/pageobject/utils/constants.ts +++ b/cypress/pageobject/utils/constants.ts @@ -1,7 +1,10 @@ -export function generatePhoneNumber() { - return "9" + Math.floor(100000000 + Math.random() * 900000000).toString(); +export function generatePhoneNumber(): string { + const array = new Uint32Array(1); + window.crypto.getRandomValues(array); + const randomNum = (array[0] % 900000000) + 100000000; + return "9" + randomNum.toString(); } -export function generateEmergencyPhoneNumber() { - return "9" + Math.floor(100000000 + Math.random() * 900000000).toString(); +export function generateEmergencyPhoneNumber(): string { + return generatePhoneNumber(); } diff --git a/cypress/pageobject/utils/userConfig.ts b/cypress/pageobject/utils/userConfig.ts new file mode 100644 index 00000000000..270fbfba10a --- /dev/null +++ b/cypress/pageobject/utils/userConfig.ts @@ -0,0 +1,8 @@ +export const users = { + districtAdmin: { username: "devdistrictadmin", password: "Coronasafe@123" }, + devDoctor: { username: "devdoctor", password: "Coronasafe@123" }, + nurse: { username: "dummynurse1", password: "Coronasafe@123" }, + nurse2: { username: "dummynurse2", password: "Coronasafe@123" }, +}; + +export const nonAdminRoles = ["devDoctor", "nurse"] as const; diff --git a/package-lock.json b/package-lock.json index 5c703af8fe1..26832f0dbd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,11 +20,11 @@ "@pnotify/core": "^5.2.0", "@pnotify/mobile": "^5.2.0", "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-icons": "^1.3.1", + "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-toast": "^1.2.2", - "@radix-ui/react-tooltip": "^1.1.3", - "@sentry/browser": "^8.37.1", + "@radix-ui/react-tooltip": "^1.1.4", + "@sentry/browser": "^8.42.0", "@yudiel/react-qr-scanner": "^2.0.8", "bowser": "^2.11.0", "browser-image-compression": "^2.0.2", @@ -33,7 +33,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cross-env": "^7.0.3", - "cypress": "^13.15.2", + "cypress": "^13.16.0", "dayjs": "^1.11.13", "echarts": "^5.5.1", "echarts-for-react": "^3.0.2", @@ -54,7 +54,7 @@ "react-infinite-scroll-component": "^6.1.0", "react-pdf": "^9.1.1", "react-webcam": "^7.2.0", - "tailwind-merge": "^2.5.4", + "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "use-keyboard-shortcut": "^1.1.6", "xlsx": "^0.18.5" @@ -92,7 +92,7 @@ "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.0.0", "glob": "^11.0.0", - "husky": "^9.1.6", + "husky": "^9.1.7", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", "local-cypress": "^1.2.6", @@ -114,25 +114,6 @@ "node": ">=22.11.0" } }, - "apps/care_livekit_fe": { - "name": "care-livekit", - "version": "0.0.1", - "extraneous": true, - "license": "ISC", - "dependencies": { - "@livekit/components-react": "^2.6.2", - "@livekit/components-styles": "^1.1.3", - "livekit-client": "^2.5.5" - }, - "devDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - }, - "peerDependencies": { - "react": "18.3.1", - "react-dom": "18.3.1" - } - }, "node_modules/@actions/core": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", @@ -3838,12 +3819,12 @@ } }, "node_modules/@radix-ui/react-icons": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.1.tgz", - "integrity": "sha512-QvYompk0X+8Yjlo/Fv4McrzxohDdM5GgLHyQcPpcsPvlOSXCGFjdbuyGL5dzRbg0GpknAjQJJZzdiRK7iWVuFQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz", + "integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==", "license": "MIT", "peerDependencies": { - "react": "^16.x || ^17.x || ^18.x || ^19.x" + "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/@radix-ui/react-id": { @@ -4121,9 +4102,9 @@ } }, "node_modules/@radix-ui/react-tooltip": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.3.tgz", - "integrity": "sha512-Z4w1FIS0BqVFI2c1jZvb/uDVJijJjJ2ZMuPV81oVgTZ7g3BZxobplnMVvXtFWgtozdvYJ+MFWtwkM5S2HnAong==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.4.tgz", + "integrity": "sha512-QpObUH/ZlpaO4YgHSaYzrLO2VuO+ZBFFgGzjMUPwtiYnAzzNNDPJeEGRrT7qNOrWm/Jr08M1vlp+vTHtnSQ0Uw==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.0", @@ -4682,58 +4663,50 @@ ] }, "node_modules/@sentry-internal/browser-utils": { - "version": "8.37.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.37.1.tgz", - "integrity": "sha512-OSR/V5GCsSCG7iapWtXCT/y22uo3HlawdEgfM1NIKk1mkP15UyGQtGEzZDdih2H+SNuX1mp9jQLTjr5FFp1A5w==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.42.0.tgz", + "integrity": "sha512-xzgRI0wglKYsPrna574w1t38aftuvo44gjOKFvPNGPnYfiW9y4m+64kUz3JFbtanvOrKPcaITpdYiB4DeJXEbA==", "license": "MIT", "dependencies": { - "@sentry/core": "8.37.1", - "@sentry/types": "8.37.1", - "@sentry/utils": "8.37.1" + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/feedback": { - "version": "8.37.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.37.1.tgz", - "integrity": "sha512-Se25NXbSapgS2S+JssR5YZ48b3OY4UGmAuBOafgnMW91LXMxRNWRbehZuNUmjjHwuywABMxjgu+Yp5uJDATX+g==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.42.0.tgz", + "integrity": "sha512-dkIw5Wdukwzngg5gNJ0QcK48LyJaMAnBspqTqZ3ItR01STi6Z+6+/Bt5XgmrvDgRD+FNBinflc5zMmfdFXXhvw==", "license": "MIT", "dependencies": { - "@sentry/core": "8.37.1", - "@sentry/types": "8.37.1", - "@sentry/utils": "8.37.1" + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay": { - "version": "8.37.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.37.1.tgz", - "integrity": "sha512-E/Plhisk/pXJjOdOU12sg8m/APTXTA21iEniidP6jW3/+O0tD/H/UovEqa4odNTqxPMa798xHQSQNt5loYiaLA==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.42.0.tgz", + "integrity": "sha512-oNcJEBlDfXnRFYC5Mxj5fairyZHNqlnU4g8kPuztB9G5zlsyLgWfPxzcn1ixVQunth2/WZRklDi4o1ZfyHww7w==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.37.1", - "@sentry/core": "8.37.1", - "@sentry/types": "8.37.1", - "@sentry/utils": "8.37.1" + "@sentry-internal/browser-utils": "8.42.0", + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "8.37.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.37.1.tgz", - "integrity": "sha512-1JLAaPtn1VL5vblB0BMELFV0D+KUm/iMGsrl4/JpRm0Ws5ESzQl33DhXVv1IX/ZAbx9i14EjR7MG9+Hj70tieQ==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.42.0.tgz", + "integrity": "sha512-XrPErqVhPsPh/oFLVKvz7Wb+Fi2J1zCPLeZCxWqFuPWI2agRyLVu0KvqJyzSpSrRAEJC/XFzuSVILlYlXXSfgA==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "8.37.1", - "@sentry/core": "8.37.1", - "@sentry/types": "8.37.1", - "@sentry/utils": "8.37.1" + "@sentry-internal/replay": "8.42.0", + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" @@ -4792,32 +4765,26 @@ } }, "node_modules/@sentry/browser": { - "version": "8.37.1", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.37.1.tgz", - "integrity": "sha512-5ym+iGiIpjIKKpMWi9S3/tXh9xneS+jqxwRTJqed3cb8i4ydfMAAP8sM3U8xMCWWABpWyIUW+fpewC0tkhE1aQ==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.42.0.tgz", + "integrity": "sha512-lStrEk609KJHwXfDrOgoYVVoFFExixHywxSExk7ZDtwj2YPv6r6Y1gogvgr7dAZj7jWzadHkxZ33l9EOSJBfug==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.37.1", - "@sentry-internal/feedback": "8.37.1", - "@sentry-internal/replay": "8.37.1", - "@sentry-internal/replay-canvas": "8.37.1", - "@sentry/core": "8.37.1", - "@sentry/types": "8.37.1", - "@sentry/utils": "8.37.1" + "@sentry-internal/browser-utils": "8.42.0", + "@sentry-internal/feedback": "8.42.0", + "@sentry-internal/replay": "8.42.0", + "@sentry-internal/replay-canvas": "8.42.0", + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/core": { - "version": "8.37.1", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.37.1.tgz", - "integrity": "sha512-82csXby589iDupM3VgCHJeWZagUyEEaDnbFcoZ/Z91QX2Sjq8FcF5OsforoXjw09i0XTFqlkFAnQVpDBmMXcpQ==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.42.0.tgz", + "integrity": "sha512-ac6O3pgoIbU6rpwz6LlwW0wp3/GAHuSI0C5IsTgIY6baN8rOBnlAtG6KrHDDkGmUQ2srxkDJu9n1O6Td3cBCqw==", "license": "MIT", - "dependencies": { - "@sentry/types": "8.37.1", - "@sentry/utils": "8.37.1" - }, "engines": { "node": ">=14.18" } @@ -4929,27 +4896,6 @@ "node": ">=8" } }, - "node_modules/@sentry/types": { - "version": "8.37.1", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.37.1.tgz", - "integrity": "sha512-ryMOTROLSLINKFEbHWvi7GigNrsQhsaScw2NddybJGztJQ5UhxIGESnxGxWCufBmWFDwd7+5u0jDPCVUJybp7w==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/@sentry/utils": { - "version": "8.37.1", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.37.1.tgz", - "integrity": "sha512-Qtn2IfpII12K17txG/ZtTci35XYjYi4CxbQ3j7nXY7toGv/+MqPXwV5q2i9g94XaSXlE5Wy9/hoCZoZpZs/djA==", - "license": "MIT", - "dependencies": { - "@sentry/types": "8.37.1" - }, - "engines": { - "node": ">=14.18" - } - }, "node_modules/@surma/rollup-plugin-off-main-thread": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", @@ -7685,9 +7631,9 @@ "license": "MIT" }, "node_modules/cypress": { - "version": "13.15.2", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.15.2.tgz", - "integrity": "sha512-ARbnUorjcCM3XiPwgHKuqsyr5W9Qn+pIIBPaoilnoBkLdSC2oLQjV1BUpnmc7KR+b7Avah3Ly2RMFnfxr96E/A==", + "version": "13.16.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.16.0.tgz", + "integrity": "sha512-g6XcwqnvzXrqiBQR/5gN+QsyRmKRhls1y5E42fyOvsmU7JuY+wM6uHJWj4ZPttjabzbnRvxcik2WemR8+xT6FA==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -10449,9 +10395,9 @@ "license": "Unlicense" }, "node_modules/husky": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", - "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", "bin": { @@ -17629,9 +17575,9 @@ "license": "MIT" }, "node_modules/tailwind-merge": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz", - "integrity": "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", + "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", "license": "MIT", "funding": { "type": "github", diff --git a/package.json b/package.json index 020d73f5e65..968c4a3e95b 100644 --- a/package.json +++ b/package.json @@ -59,11 +59,11 @@ "@pnotify/core": "^5.2.0", "@pnotify/mobile": "^5.2.0", "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-icons": "^1.3.1", + "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-toast": "^1.2.2", - "@radix-ui/react-tooltip": "^1.1.3", - "@sentry/browser": "^8.37.1", + "@radix-ui/react-tooltip": "^1.1.4", + "@sentry/browser": "^8.42.0", "@yudiel/react-qr-scanner": "^2.0.8", "bowser": "^2.11.0", "browser-image-compression": "^2.0.2", @@ -72,7 +72,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cross-env": "^7.0.3", - "cypress": "^13.15.2", + "cypress": "^13.16.0", "dayjs": "^1.11.13", "echarts": "^5.5.1", "echarts-for-react": "^3.0.2", @@ -93,7 +93,7 @@ "react-infinite-scroll-component": "^6.1.0", "react-pdf": "^9.1.1", "react-webcam": "^7.2.0", - "tailwind-merge": "^2.5.4", + "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "use-keyboard-shortcut": "^1.1.6", "xlsx": "^0.18.5" @@ -131,7 +131,7 @@ "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.0.0", "glob": "^11.0.0", - "husky": "^9.1.6", + "husky": "^9.1.7", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", "local-cypress": "^1.2.6", diff --git a/public/locale/en.json b/public/locale/en.json index 56f84a1883a..b5f46dd7308 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -562,7 +562,7 @@ "date_and_time": "Date and Time", "date_declared_positive": "Date of declaring positive", "date_of_admission": "Date of Admission", - "date_of_birth": "Date of birth", + "date_of_birth": "Date of Birth", "date_of_positive_covid_19_swab": "Date of Positive Covid 19 Swab", "date_of_result": "Covid confirmation date", "date_of_return": "Date of Return", @@ -945,6 +945,7 @@ "next_sessions": "Next Sessions", "no": "No", "no_attachments_found": "This communication has no attachments.", + "no_bed_asset_linked_allocated": "No bed/asset linked allocated", "no_bed_types_found": "No Bed Types found", "no_beds_available": "No beds available", "no_changes": "No changes", @@ -1364,6 +1365,7 @@ "update_facility_middleware_success": "Facility middleware updated successfully", "update_log": "Update Log", "update_patient_details": "Update Patient Details", + "update_preset": "Update Preset", "update_preset_position_to_current": "Update preset's position to camera's current position", "update_record": "Update Record", "update_record_for_asset": "Update record for asset", @@ -1378,6 +1380,7 @@ "upload_headings__patient": "Upload New Patient File", "upload_headings__sample_report": "Upload Sample Report", "upload_headings__supporting_info": "Upload Supporting Info", + "upload_report": "Upload Report", "uploading": "Uploading", "use_existing_abha_address": "Use Existing ABHA Address", "user_deleted_successfuly": "User Deleted Successfuly", @@ -1433,6 +1436,7 @@ "why_the_asset_is_not_working": "Why the asset is not working?", "width": "Width ({{unit}})", "working_status": "Working Status", + "year_of_birth": "Year of Birth", "years": "years", "years_of_experience": "Years of Experience", "years_of_experience_of_the_doctor": "Years of Experience of the Doctor", diff --git a/src/CAREUI/misc/PrintPreview.tsx b/src/CAREUI/misc/PrintPreview.tsx index 53eda1339ac..daf79ecbb34 100644 --- a/src/CAREUI/misc/PrintPreview.tsx +++ b/src/CAREUI/misc/PrintPreview.tsx @@ -8,7 +8,8 @@ import { ZoomTransform, } from "@/CAREUI/interactive/Zoom"; -import ButtonV2 from "@/components/Common/ButtonV2"; +import { Button } from "@/components/ui/button"; + import Page from "@/components/Common/Page"; import useBreakpoints from "@/hooks/useBreakpoints"; @@ -30,10 +31,10 @@ export default function PrintPreview(props: Props) {
- +
diff --git a/src/components/Assets/AssetManage.tsx b/src/components/Assets/AssetManage.tsx index c78be71d627..b4377d2e1aa 100644 --- a/src/components/Assets/AssetManage.tsx +++ b/src/components/Assets/AssetManage.tsx @@ -69,7 +69,11 @@ const AssetManage = (props: AssetManageProps) => { >(); const [transactionFilter, setTransactionFilter] = useState({}); - const { data: asset, loading } = useQuery(routes.getAsset, { + const { + data: asset, + loading, + refetch, + } = useQuery(routes.getAsset, { pathParams: { external_id: assetId, }, @@ -594,7 +598,10 @@ const AssetManage = (props: AssetManageProps) => { handleClose={() => setServiceEditData({ ...serviceEditData, open: false }) } - handleUpdate={() => serviceRefetch()} + handleUpdate={() => { + serviceRefetch(); + refetch(); + }} show={serviceEditData.open} viewOnly={serviceEditData.viewOnly} /> diff --git a/src/components/Assets/AssetsList.tsx b/src/components/Assets/AssetsList.tsx index eceee4887e8..f48723f2784 100644 --- a/src/components/Assets/AssetsList.tsx +++ b/src/components/Assets/AssetsList.tsx @@ -377,6 +377,7 @@ const AssetsList = () => { />
updateQuery({ [e.name]: e.value })} diff --git a/src/components/CameraFeed/ConfigureCamera.tsx b/src/components/CameraFeed/ConfigureCamera.tsx index f969ed2b0ca..eec453053d6 100644 --- a/src/components/CameraFeed/ConfigureCamera.tsx +++ b/src/components/CameraFeed/ConfigureCamera.tsx @@ -89,16 +89,15 @@ export default function ConfigureCamera(props: Props) { const firstBedId = linkedAssetBeds?.[0]?.bed_object.id ?? unlinkedBeds?.[0]?.id; - useEffect(() => { - if (!query.bed && firstBedId) { - setQuery({ bed: firstBedId }); - } - }, [query.bed, firstBedId]); + + const selectedBedId = query.bed || firstBedId; const selectedAssetBed = linkedAssetBeds?.find( - (a) => a.bed_object.id === query.bed, + (a) => a.bed_object.id === selectedBedId, + ); + const selectedUnlinkedBed = unlinkedBeds?.find( + (bed) => bed.id === selectedBedId, ); - const selectedUnlinkedBed = unlinkedBeds?.find((bed) => bed.id === query.bed); const cameraPresetsQuery = useQuery(FeedRoutes.listAssetBedPresets, { pathParams: { assetbed_id: selectedAssetBed?.id ?? "" }, diff --git a/src/components/Common/FilePreviewDialog.tsx b/src/components/Common/FilePreviewDialog.tsx index 4b7a07bd0cd..fa8a333515d 100644 --- a/src/components/Common/FilePreviewDialog.tsx +++ b/src/components/Common/FilePreviewDialog.tsx @@ -4,6 +4,7 @@ import { SetStateAction, Suspense, lazy, + useEffect, useState, } from "react"; import { useTranslation } from "react-i18next"; @@ -15,6 +16,8 @@ import CircularProgress from "@/components/Common/CircularProgress"; import DialogModal from "@/components/Common/Dialog"; import { StateInterface } from "@/components/Files/FileUpload"; +import { FileUploadModel } from "../Patient/models"; + const PDFViewer = lazy(() => import("@/components/Common/PDFViewer")); export const zoom_values = [ @@ -40,6 +43,9 @@ type FilePreviewProps = { className?: string; titleAction?: ReactNode; fixedWidth?: boolean; + uploadedFiles?: FileUploadModel[]; + loadFile?: (file: FileUploadModel, associating_id: string) => void; + currentIndex: number; }; const previewExtensions = [ @@ -56,12 +62,28 @@ const previewExtensions = [ ]; const FilePreviewDialog = (props: FilePreviewProps) => { - const { show, onClose, file_state, setFileState, downloadURL, fileUrl } = - props; + const { + show, + onClose, + file_state, + setFileState, + downloadURL, + fileUrl, + uploadedFiles, + loadFile, + currentIndex, + } = props; const { t } = useTranslation(); const [page, setPage] = useState(1); const [numPages, setNumPages] = useState(1); + const [index, setIndex] = useState(currentIndex); + + useEffect(() => { + if (uploadedFiles && show) { + setIndex(currentIndex); + } + }, [uploadedFiles, show, currentIndex]); const handleZoomIn = () => { const checkFull = file_state.zoom === zoom_values.length; @@ -79,9 +101,27 @@ const FilePreviewDialog = (props: FilePreviewProps) => { }); }; + const handleNext = (newIndex: number) => { + if ( + !uploadedFiles?.length || + !loadFile || + newIndex < 0 || + newIndex >= uploadedFiles.length + ) + return; + + const nextFile = uploadedFiles[newIndex]; + if (!nextFile?.id) return; + + const associating_id = nextFile.associating_id || ""; + loadFile(nextFile, associating_id); + setIndex(newIndex); + }; + const handleClose = () => { setPage(1); setNumPages(1); + setIndex(-1); onClose?.(); }; @@ -102,6 +142,21 @@ const FilePreviewDialog = (props: FilePreviewProps) => { : `rotate-${normalizedRotation}`; } + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (!show) return; + if (e.key === "ArrowLeft" && index > 0) { + handleNext(index - 1); + } + if (e.key === "ArrowRight" && index < (uploadedFiles?.length || 0) - 1) { + handleNext(index + 1); + } + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [show, index, uploadedFiles]); + return ( { onClose={() => { handleClose(); }} - title={t("file_preview")} + title={{t("file_preview")}} show={show} > {fileUrl ? ( <> -
-

- {file_state.name}.{file_state.extension} -

-
+
+
+

+ {file_state.name}.{file_state.extension} +

+ {uploadedFiles && + uploadedFiles[index] && + uploadedFiles[index].created_date && ( +

+ Created on{" "} + {new Date( + uploadedFiles[index].created_date!, + ).toLocaleString("en-US", { + dateStyle: "long", + timeStyle: "short", + })} +

+ )} +
+
{downloadURL && downloadURL.length > 0 && ( {
+ {uploadedFiles && uploadedFiles.length > 1 && ( + handleNext(index - 1)} + disabled={index <= 0} + aria-label="Previous file" + onKeyDown={(e) => + e.key === "ArrowLeft" && handleNext(index - 1) + } + > + + + )}
{file_state.isImage ? ( {
)}
+ + {uploadedFiles && uploadedFiles.length > 1 && ( + handleNext(index + 1)} + disabled={index >= uploadedFiles.length - 1} + aria-label="Next file" + onKeyDown={(e) => + e.key === "ArrowRight" && handleNext(index + 1) + } + > + + + )}
diff --git a/src/components/Facility/ConsultationDetails/ConsultationFeedTab.tsx b/src/components/Facility/ConsultationDetails/ConsultationFeedTab.tsx index 21c6f304cb5..bc518feb02f 100644 --- a/src/components/Facility/ConsultationDetails/ConsultationFeedTab.tsx +++ b/src/components/Facility/ConsultationDetails/ConsultationFeedTab.tsx @@ -34,6 +34,7 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => { const bed = props.consultationData.current_bed?.bed_object; const feedStateSessionKey = `encounterFeedState[${props.consultationId}]`; const [preset, setPreset] = useState(); + const [selectedPreset, setSelectedPreset] = useState(); const [showPresetSaveConfirmation, setShowPresetSaveConfirmation] = useState(false); const [isUpdatingPreset, setIsUpdatingPreset] = useState(false); @@ -78,28 +79,14 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => { return presets.find((obj) => obj.id === lastState.value); } if (lastState.type === "position") { - const assetBedObj = presets.find( - (p) => p.asset_bed.id === lastState.assetBed, - )?.asset_bed; - - if (!assetBedObj) { - return; - } - - return { - ...presets[0], - id: "", - asset_bed: assetBedObj, - position: lastState.value, - } satisfies CameraPreset; + return; } } })() ?? presets[0]; - console.log({ preset, presets }); - if (preset) { setPreset(preset); + setSelectedPreset(preset); } }, }); @@ -126,6 +113,7 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => { await presetsQuery.refetch(); setPreset(updated); + setSelectedPreset(updated); setHasMoved(false); setIsUpdatingPreset(false); setShowPresetSaveConfirmation(false); @@ -154,7 +142,7 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => { } if (!bed || !asset) { - return No bed/asset linked allocated; + return {t("no_bed_asset_linked_allocated")}; } const cannotSaveToPreset = !hasMoved || !preset?.id; @@ -162,8 +150,8 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => { return ( setShowPresetSaveConfirmation(false)} @@ -180,11 +168,9 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => { { - if (!preset) { - return; - } + setSelectedPreset(undefined); setHasMoved(true); setTimeout(async () => { const { data } = await operate({ type: "get_status" }); @@ -193,7 +179,6 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => { feedStateSessionKey, JSON.stringify({ type: "position", - assetBed: preset.asset_bed.id, value: (data as GetStatusResponse).result.position, } satisfies LastAccessedPosition), ); @@ -222,16 +207,17 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => { obj.name} - value={preset} + value={selectedPreset} onChange={(value) => { triggerGoal("Camera Preset Clicked", { - presetName: preset?.name, + presetName: selectedPreset?.name, consultationId: props.consultationId, userId: authUser.id, result: "success", }); setHasMoved(false); setPreset(value); + setSelectedPreset(value); }} /> {isUpdatingPreset ? ( @@ -277,7 +263,6 @@ type LastAccessedPreset = { type LastAccessedPosition = { type: "position"; - assetBed: string; value: PTZPayload; }; diff --git a/src/components/Facility/ConsultationDetails/index.tsx b/src/components/Facility/ConsultationDetails/index.tsx index 4834ba40198..191d0156d03 100644 --- a/src/components/Facility/ConsultationDetails/index.tsx +++ b/src/components/Facility/ConsultationDetails/index.tsx @@ -213,6 +213,10 @@ export const ConsultationDetails = (props: any) => { crumbsReplacements={{ [facilityId]: { name: patientData?.facility_object?.name }, [patientId]: { name: patientData?.name }, + consultation: { + name: "Consultation", + uri: `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/update`, + }, [consultationId]: { name: consultationData.suggestion === "A" diff --git a/src/components/Facility/FacilityList.tsx b/src/components/Facility/FacilityList.tsx index 6570bf7ea58..7f40bfde5f3 100644 --- a/src/components/Facility/FacilityList.tsx +++ b/src/components/Facility/FacilityList.tsx @@ -189,6 +189,7 @@ export const FacilityList = () => { />
updateQuery({ [e.name]: e.value })} diff --git a/src/components/Files/FileUpload.tsx b/src/components/Files/FileUpload.tsx index d98df131863..50ab3ffdb01 100644 --- a/src/components/Files/FileUpload.tsx +++ b/src/components/Files/FileUpload.tsx @@ -69,6 +69,8 @@ export interface StateInterface { isZoomInDisabled: boolean; isZoomOutDisabled: boolean; rotation: number; + id?: string; + associating_id?: string; } export const FileUpload = (props: FileUploadProps) => { @@ -208,8 +210,15 @@ export const FileUpload = (props: FileUploadProps) => { type, onArchive: refetchAll, onEdit: refetchAll, + uploadedFiles: + fileQuery?.data?.results + .slice() + .reverse() + .map((file) => ({ + ...file, + associating_id: associatedId, + })) || [], }); - const dischargeSummaryFileManager = useFileManager({ type: "DISCHARGE_SUMMARY", onArchive: refetchAll, @@ -244,7 +253,6 @@ export const FileUpload = (props: FileUploadProps) => { id: "record-audio", }, ]; - return (
{fileUpload.Dialogues} diff --git a/src/components/Patient/FileUploadPage.tsx b/src/components/Patient/FileUploadPage.tsx index 518644f54d7..d38b149ebeb 100644 --- a/src/components/Patient/FileUploadPage.tsx +++ b/src/components/Patient/FileUploadPage.tsx @@ -11,12 +11,10 @@ export default function FileUploadPage(props: { type: "CONSULTATION" | "PATIENT"; }) { const { facilityId, patientId, consultationId, type } = props; - const { data: patient } = useQuery(routes.getPatient, { pathParams: { id: patientId }, prefetch: !!patientId, }); - return ( { />
- +
{managePatients}
diff --git a/src/components/Patient/PatientConsentRecords.tsx b/src/components/Patient/PatientConsentRecords.tsx index 162dcb2ff77..cbeb56b894f 100644 --- a/src/components/Patient/PatientConsentRecords.tsx +++ b/src/components/Patient/PatientConsentRecords.tsx @@ -112,6 +112,10 @@ export default function PatientConsentRecords(props: { crumbsReplacements={{ [facilityId]: { name: patient?.facility_object?.name }, [patientId]: { name: patient?.name }, + consultation: { + name: "Consultation", + uri: `/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/update`, + }, [consultationId]: { name: patient?.last_consultation?.suggestion === "A" @@ -121,7 +125,7 @@ export default function PatientConsentRecords(props: { : patient?.last_consultation?.suggestion_text, }, }} - backUrl={`/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/`} + backUrl={`/facility/${facilityId}/patient/${patientId}/consultation/${consultationId}/update`} > {fileUpload.Dialogues} {fileManager.Dialogues} diff --git a/src/components/Patient/PatientDetailsTab/Demography.tsx b/src/components/Patient/PatientDetailsTab/Demography.tsx index 7ac854b8ee6..b9d2b8fece4 100644 --- a/src/components/Patient/PatientDetailsTab/Demography.tsx +++ b/src/components/Patient/PatientDetailsTab/Demography.tsx @@ -5,8 +5,9 @@ import { useTranslation } from "react-i18next"; import Chip from "@/CAREUI/display/Chip"; import CareIcon from "@/CAREUI/icons/CareIcon"; +import AuthorizedChild from "@/CAREUI/misc/AuthorizedChild"; -import ButtonV2 from "@/components/Common/ButtonV2"; +import { Button } from "@/components/ui/button"; import useAuthUser from "@/hooks/useAuthUser"; @@ -188,12 +189,19 @@ export const Demography = (props: PatientProps) => { ), }, { - label: t("date_of_birth"), - value: ( + label: t( + patientData.date_of_birth ? "date_of_birth" : "year_of_birth", + ), + value: patientData.date_of_birth ? ( <> {dayjs(patientData.date_of_birth).format("DD MMM YYYY")} ( {formatPatientAge(patientData, true)}) + ) : ( + <> + {patientData.year_of_birth} ({formatPatientAge(patientData, true)} + ) + ), }, { @@ -305,10 +313,9 @@ export const Demography = (props: PatientProps) => { {t("no_data_found")}
)} - handleEditClick("insurance-details"), @@ -316,7 +323,7 @@ export const Demography = (props: PatientProps) => { > {t("add_insurance_details")} - +
, ], }, @@ -366,21 +373,24 @@ export const Demography = (props: PatientProps) => {
- - navigate( - `/facility/${patientData?.facility}/patient/${id}/update`, - ), + + {({ isAuthorized }) => ( + )} - > - - {t("edit_profile")} - +
{/*
@@ -408,22 +418,19 @@ export const Demography = (props: PatientProps) => { className="group mt-4 rounded-md bg-white pb-2 pl-5 pt-5 shadow" >
-
+

{t(`patient__${subtab.id}`)}

{subtab.allowEdit && ( - + )}
diff --git a/src/components/Patient/PatientDetailsTab/HealthProfileSummary.tsx b/src/components/Patient/PatientDetailsTab/HealthProfileSummary.tsx index 3fb6b60d330..374d5ede08b 100644 --- a/src/components/Patient/PatientDetailsTab/HealthProfileSummary.tsx +++ b/src/components/Patient/PatientDetailsTab/HealthProfileSummary.tsx @@ -3,6 +3,8 @@ import { useTranslation } from "react-i18next"; import CareIcon from "@/CAREUI/icons/CareIcon"; +import { Button } from "@/components/ui/button"; + import { UserModel } from "@/components/Users/models"; import useAuthUser from "@/hooks/useAuthUser"; @@ -56,12 +58,12 @@ export const HealthProfileSummary = (props: PatientProps) => {

-
+
{t("medical")}
- +
diff --git a/src/components/Patient/PatientDetailsTab/ImmunisationRecords.tsx b/src/components/Patient/PatientDetailsTab/ImmunisationRecords.tsx index eb298737f3c..7ee828868fc 100644 --- a/src/components/Patient/PatientDetailsTab/ImmunisationRecords.tsx +++ b/src/components/Patient/PatientDetailsTab/ImmunisationRecords.tsx @@ -3,6 +3,8 @@ import { useTranslation } from "react-i18next"; import CareIcon from "@/CAREUI/icons/CareIcon"; +import { Button } from "@/components/ui/button"; + import { UserModel } from "@/components/Users/models"; import useAuthUser from "@/hooks/useAuthUser"; @@ -40,10 +42,10 @@ export const ImmunisationRecords = (props: PatientProps) => {

-
+

{t("covid_details")}

- +
diff --git a/src/components/Patient/PatientHome.tsx b/src/components/Patient/PatientHome.tsx index d6b9844b699..518ac33bdf2 100644 --- a/src/components/Patient/PatientHome.tsx +++ b/src/components/Patient/PatientHome.tsx @@ -376,10 +376,22 @@ export const PatientHome = (props: { .treating_physician_object, )}

-

+ {!!skillsQuery.data?.results?.length && formatSkills(skillsQuery.data?.results)} -

+ {(skillsQuery.data?.results?.length || 0) > 3 && ( +
    + {skillsQuery.data?.results.map((skill) => ( +
  • + {skill.skill_object.name} +
  • + ))} +
+ )} +
)} diff --git a/src/components/Patient/SampleDetails.tsx b/src/components/Patient/SampleDetails.tsx index edc0b4d53a6..abf099a6e7d 100644 --- a/src/components/Patient/SampleDetails.tsx +++ b/src/components/Patient/SampleDetails.tsx @@ -300,6 +300,7 @@ export const SampleDetails = ({ id }: DetailRoute) => { return ( { return state; } }; - const UpdateStatusDialog = (props: Props) => { const { t } = useTranslation(); const { sample, handleOk, handleCancel } = props; const [state, dispatch] = useReducer(updateStatusReducer, initialState); - const [file, setfile] = useState(); - const [contentType, setcontentType] = useState(""); - const [uploadPercent, setUploadPercent] = useState(0); - const [uploadStarted, setUploadStarted] = useState(false); - const [uploadDone, setUploadDone] = useState(false); + const fileUpload = useFileUpload({ + type: "SAMPLE_MANAGEMENT", + allowedExtensions: ["pdf", "jpg", "jpeg", "png"], + allowNameFallback: true, + }); const currentStatus = SAMPLE_TEST_STATUS.find( (i) => i.text === sample.status, ); @@ -104,79 +99,26 @@ const UpdateStatusDialog = (props: Props) => { dispatch({ type: "set_form", form }); }; - const uploadfile = (data: CreateFileResponse) => { - const url = data.signed_url; - const internal_name = data.internal_name; - - const f = file; - if (f === undefined) return; - const newFile = new File([f], `${internal_name}`); - - uploadFile( - url, - newFile, - "PUT", - { - "Content-Type": contentType, - "Content-disposition": "inline", - }, - (xhr: XMLHttpRequest) => { - if (xhr.status >= 200 && xhr.status < 300) { - setUploadStarted(false); - setUploadDone(true); - request(routes.editUpload, { - pathParams: { - id: data.id, - fileType: "SAMPLE_MANAGEMENT", - associatingId: sample.id?.toString() ?? "", - }, - body: { upload_completed: true }, - }); - Notification.Success({ msg: "File Uploaded Successfully" }); + const handleUpload = async () => { + if (fileUpload.files.length > 0) { + if (!fileUpload.fileNames[0]) { + Notification.Error({ + msg: "Please enter a file name before uploading", + }); + return; + } + if (sample.id) { + await fileUpload.handleFileUpload(sample.id); + if (!fileUpload.error) { + return; } else { - setUploadStarted(false); + Notification.Error({ msg: `Upload failed: ${fileUpload.error}` }); } - }, - setUploadPercent, - () => { - setUploadStarted(false); - }, - ); - }; - - const onFileChange = (e: React.ChangeEvent) => { - if (e.target.files == null) { - throw new Error("Error finding e.target.files"); - } - setfile(e.target.files[0]); - const fileName = e.target.files[0].name; - const ext: string = fileName.split(".")[1]; - setcontentType( - HEADER_CONTENT_TYPES[ext as keyof typeof HEADER_CONTENT_TYPES], - ); - return e.target.files[0]; - }; - const handleUpload = async () => { - const f = file; - if (f === undefined) return; - const category = "UNSPECIFIED"; - const name = f.name; - setUploadStarted(true); - setUploadDone(false); - - const { data } = await request(routes.createUpload, { - body: { - original_name: name, - file_type: "SAMPLE_MANAGEMENT", - name: `${sample.patient_name} Sample Report`, - associating_id: sample.id ?? "", - file_category: category, - mime_type: contentType, - }, - }); - - if (data) { - uploadfile(data); + } else { + Notification.Error({ msg: "Sample ID is missing" }); + } + } else { + Notification.Error({ msg: "No file selected for upload" }); } }; @@ -218,32 +160,58 @@ const UpdateStatusDialog = (props: Props) => { onChange={handleChange} /> - Upload Report : + {t("upload_report")}: - {uploadStarted ? ( - - ) : ( -
-