diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000000..4fe94183a2f --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,40 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node +{ + "name": "care_fe", + "image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bullseye", + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "moby": true, + "installDockerBuildx": true, + "version": "latest", + "dockerDashComposeVersion": "v2" + } + }, + "customizations": { + "vscode": { + "settings": {}, + "extensions": [ + "esbenp.prettier-vscode", + "bradlc.vscode-tailwindcss", + "yoavbls.pretty-ts-errors", + "chenglou92.rescript-vscode" + ] + } + }, + "hostRequirements": { + "cpus": 4 + }, + "waitFor": "onCreateCommand", + "postCreateCommand": "npm install", + "postAttachCommand": { + "server": "npm run dev" + }, + "portsAttributes": { + "4000": { + "label": "Application", + "onAutoForward": "openPreview" + } + }, + "forwardPorts": [4000] +} diff --git a/.env b/.env index fcabed6db34..38fd950b0d8 100644 --- a/.env +++ b/.env @@ -1,11 +1,10 @@ # Whitelabelling envs -REACT_APP_TITLE="CARE" -REACT_APP_META_DESCRIPTION="CoronaSafe Network is an open-source public utility designed by a multi-disciplinary team of innovators and volunteers. CoronaSafe Care is a Digital Public Good recognised by United Nations." +REACT_APP_TITLE=CARE +REACT_APP_META_DESCRIPTION=CoronaSafe Network is an open-source public utility designed by a multi-disciplinary team of innovators and volunteers. CoronaSafe Care is a Digital Public Good recognised by United Nations. REACT_APP_COVER_IMAGE=https://cdn.coronasafe.network/care_logo.svg REACT_APP_COVER_IMAGE_ALT=https://cdn.coronasafe.network/care_logo.svg -REACT_APP_CONFIG="" -REACT_PUBLIC_URL="https://care.coronasafe.in" +REACT_PUBLIC_URL=https://care.coronasafe.in # Dev envs ESLINT_NO_DEV_ERRORS=true diff --git a/.envrc b/.envrc new file mode 100644 index 00000000000..fc7d890f90a --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +test -f .env.local && dotenv .env.local \ No newline at end of file diff --git a/.github/workflows/cypress.yaml b/.github/workflows/cypress.yaml index 7c160ce029b..f04045d0c72 100644 --- a/.github/workflows/cypress.yaml +++ b/.github/workflows/cypress.yaml @@ -14,6 +14,10 @@ jobs: permissions: write-all if: github.repository == 'coronasafe/care_fe' runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + containers: [1,2,3,4,5,6,7,8] steps: - name: Checkout 📥 uses: actions/checkout@v3 @@ -24,20 +28,26 @@ jobs: repository: coronasafe/care path: care - - name: Run docker compose up on care 🐳 - run: cd care && touch .env && make docker_config_file=docker-compose.pre-built.yaml up && cd .. && sleep 60s - # Voluntarily kept 60 seconds delay to wait for migrations to complete. - - - name: Run Django collectstatic and load dummy data on care 🐍 + - name: Start care docker containers 🐳 + run: | + cd care + make docker_config_file=docker-compose.pre-built.yaml up + while docker compose exec backend bash -c "python manage.py showmigrations 2>/dev/null | cat | grep -q '\[ \]'"; do + >&2 echo "Migrations are not yet applied - sleeping" + sleep 5 + done + echo "Migrations are applied" + cd .. + + - name: Load dummy data into care backend 📂 run: | - docker exec care python manage.py load_dummy_data + cd care + docker compose exec backend bash -c "python manage.py load_dummy_data" + cd .. - name: Check care is up ♻ run: curl -o /dev/null -s -w "%{http_code}\n" http://localhost:9000 - - name: Change api proxy url 📝 - run: 'sed --in-place "s^target: .*,^target: \"http://localhost:9000\",^g" vite.config.ts' - - name: Install dependencies 📦 run: npm install @@ -52,40 +62,16 @@ jobs: start: "npx vite preview --host" wait-on: "http://localhost:4000" wait-on-timeout: 300 - browser: electron + browser: chrome record: true + parallel: true env: + CARE_API: http://localhost:9000 CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_OPTIONS: --max_old_space_size=4096 - - - name: Remove cypress passed label on failure 🏷️ - uses: actions-ecosystem/action-remove-labels@v1 - if: failure() - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: cypress passed - - - name: Add cypress passed label on success 🏷️ - uses: actions-ecosystem/action-add-labels@v1 - if: success() - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: cypress passed - - - name: Remove cypress failed label on success 🏷️ - uses: actions-ecosystem/action-remove-labels@v1 - if: success() - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: cypress failed - - - name: Add cypress failed label on failure 🏷️ - uses: actions-ecosystem/action-add-labels@v1 - if: failure() - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: cypress failed + COMMIT_INFO_MESSAGE: ${{github.event.pull_request.title}} + COMMIT_INFO_SHA: ${{github.event.pull_request.head.sha}} - name: Upload cypress screenshots on failure 📸 uses: actions/upload-artifact@v3 @@ -94,10 +80,3 @@ jobs: name: cypress-screenshots path: cypress/screenshots - # Test run video was always captured, so this action uses "always()" condition - - name: Upload cypress videos 📹 - uses: actions/upload-artifact@v3 - if: always() - with: - name: cypress-videos - path: cypress/videos diff --git a/.gitignore b/.gitignore index 8b0b6a10d3c..4ca589aab39 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,8 @@ storybook-static .swp stats.json public/build-meta.json -.vscode +.vscode/* +!.vscode/launch.json # Reason React @@ -53,6 +54,7 @@ public/build-meta.json # Using NPM yarn.lock pnpm-lock.yaml +bun.lockb # Cypress cypress/downloads diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000000..d512e87ec49 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Run application", + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "runtimeExecutable": "npm", + "runtimeArgs": [ + "run-script", + "dev" + ], + "skipFiles": [ + "/**" + ] + } + ] +} \ No newline at end of file diff --git a/cypress.config.ts b/cypress.config.ts index 014eb1f4d07..66915f8a11b 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -19,7 +19,6 @@ export default defineConfig({ return null; }, }); - return config; }, baseUrl: "http://localhost:4000", diff --git a/cypress/e2e/assets_spec/asset_homepage.cy.ts b/cypress/e2e/assets_spec/asset_homepage.cy.ts new file mode 100644 index 00000000000..8bc24c7370f --- /dev/null +++ b/cypress/e2e/assets_spec/asset_homepage.cy.ts @@ -0,0 +1,114 @@ +/// + +import { cy, describe, before, beforeEach, it, afterEach } from "local-cypress"; +import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import { AssetQRScanPage } from "../../pageobject/Asset/AssetQRScan"; +import { AssetPagination } from "../../pageobject/Asset/AssetPagination"; +import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; +import { AssetPage } from "../../pageobject/Asset/AssetCreation"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { v4 as uuidv4 } from "uuid"; + +describe("Asset Tab", () => { + const assetSearchPage = new AssetSearchPage(); + const assetQRScanPage = new AssetQRScanPage(); + const assetPagination = new AssetPagination(); + 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.loginAsDisctrictAdmin(); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + 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 1", + "INTERNAL", + "ACTIVE", + "ONVIF Camera", + "Camera Loc" + ); + assetFilters.clickadvancefilter(); + assetFilters.clickslideoverbackbutton(); // to verify the back button doesn't clear applied filters + assetFilters.assertFacilityText("Dummy Facility 1"); + assetFilters.assertAssetTypeText("INTERNAL"); + assetFilters.assertAssetClassText("ONVIF"); + assetFilters.assertStatusText("ACTIVE"); + assetFilters.assertLocationText("Camera Locations"); + assetFilters.clickadvancefilter(); + assetFilters.clearFilters(); + }); + + // Verify the pagination in the page + + it("Next/Previous Page", () => { + assetPagination.navigateToNextPage(); + assetPagination.navigateToPreviousPage(); + }); + + it("Import new asset", () => { + assetPage.selectassetimportbutton(); + assetPage.selectImportOption(); + assetPage.selectImportFacility("Dummy Facility 1"); + assetPage.importAssetFile(); + assetPage.selectImportLocation("Camera Locations"); + assetPage.clickImportAsset(); + assetPage.verifySuccessNotification("Assets imported successfully"); + }); + + it("verify imported asset", () => { + assetSearchPage.typeSearchKeyword("New Test Asset"); + assetSearchPage.pressEnter(); + assetSearchPage.verifyAssetIsPresent("New Test Asset"); + }); + + it("Export asset", () => { + assetPage.selectassetimportbutton(); + assetPage.selectjsonexportbutton(); + assetPage.selectassetimportbutton(); + assetPage.selectcsvexportbutton(); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/e2e/assets_spec/asset_tab.cy.ts b/cypress/e2e/assets_spec/asset_tab.cy.ts deleted file mode 100644 index 0abf11fcaf0..00000000000 --- a/cypress/e2e/assets_spec/asset_tab.cy.ts +++ /dev/null @@ -1,61 +0,0 @@ -/// - -import { cy, describe, before, beforeEach, it, afterEach } from "local-cypress"; -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; -import { AssetQRScanPage } from "../../pageobject/Asset/AssetQRScan"; -import { AssetPagination } from "../../pageobject/Asset/AssetPagination"; -import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; - -describe("Asset Tab", () => { - const assetSearchPage = new AssetSearchPage(); - const assetQRScanPage = new AssetQRScanPage(); - const assetPagination = new AssetPagination(); - const assetFilters = new AssetFilters(); - - before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); - cy.saveLocalStorage(); - }); - - beforeEach(() => { - cy.restoreLocalStorage(); - cy.awaitUrl("/assets"); - }); - - // search for a element - - it("Search Asset Name", () => { - const initialUrl = cy.url(); - assetSearchPage.typeSearchKeyword("dummy camera 30"); - assetSearchPage.pressEnter(); - assetSearchPage.verifyUrlChanged(initialUrl); - }); - - // 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 1", - "INTERNAL", - "ACTIVE", - "ONVIF Camera" - ); - }); - - // Verify the pagination in the page - - it("Next/Previous Page", () => { - assetPagination.navigateToNextPage(); - assetPagination.navigateToPreviousPage(); - }); - - afterEach(() => { - cy.saveLocalStorage(); - }); -}); diff --git a/cypress/e2e/assets_spec/assets_creation.cy.ts b/cypress/e2e/assets_spec/assets_creation.cy.ts new file mode 100644 index 00000000000..3e7b24eeca6 --- /dev/null +++ b/cypress/e2e/assets_spec/assets_creation.cy.ts @@ -0,0 +1,178 @@ +/// +import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; +import { AssetPage } from "../../pageobject/Asset/AssetCreation"; +import { v4 as uuidv4 } from "uuid"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; + +describe("Asset", () => { + const assetPage = new AssetPage(); + const assetSearchPage = new AssetSearchPage(); + const loginPage = new LoginPage(); + const phone_number = "9999999999"; + const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); + + before(() => { + loginPage.loginAsDisctrictAdmin(); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.awaitUrl("/assets"); + }); + + it("Verify asset creation fields throws error if empty", () => { + assetPage.createAsset(); + assetPage.selectFacility("Dummy Facility 1"); + assetPage.clickCreateAsset(); + + assetPage.verifyEmptyAssetNameError(); + assetPage.verifyEmptyAssetTypeError(); + assetPage.verifyEmptyLocationError(); + assetPage.verifyEmptyStatusError(); + assetPage.verifyEmptyPhoneError(); + }); + + //Create an asset + + it("Create an Asset", () => { + assetPage.createAsset(); + assetPage.selectFacility("Dummy Facility 1"); + assetPage.selectLocation("Camera Loc"); + assetPage.selectAssetType("Internal"); + assetPage.selectAssetClass("ONVIF Camera"); + + const qr_id_1 = uuidv4(); + + assetPage.enterAssetDetails( + "New Test Asset 1", + "Test Description", + "Working", + qr_id_1, + "Manufacturer's Name", + "2025-12-25", + "Customer Support's Name", + phone_number, + "email@support.com", + "Vendor's Name", + serialNumber, + "25122021", + "Test note for asset creation!" + ); + + assetPage.clickCreateAddMore(); + assetPage.verifySuccessNotification("Asset created successfully"); + + const qr_id_2 = uuidv4(); + + assetPage.selectLocation("Camera Loc"); + assetPage.selectAssetType("Internal"); + assetPage.selectAssetClass("ONVIF Camera"); + assetPage.enterAssetDetails( + "New Test Asset 2", + "Test Description", + "Working", + qr_id_2, + "Manufacturer's Name", + "2025-12-25", + "Customer Support's Name", + phone_number, + "email@support.com", + "Vendor's Name", + serialNumber, + "25122021", + "Test note for asset creation!" + ); + + assetPage.interceptAssetCreation(); + assetPage.clickCreateAsset(); + assetPage.verifyAssetCreation(); + assetPage.verifySuccessNotification("Asset created successfully"); + + assetSearchPage.typeSearchKeyword("New Test Asset 2"); + assetSearchPage.pressEnter(); + assetSearchPage.verifyAssetIsPresent("New Test Asset 2"); + }); + + it("Edit an Asset", () => { + assetPage.openCreatedAsset(); + + const qr_id = uuidv4(); + + assetPage.editAssetDetails( + "New Test Asset Edited", + "Test Description Edited", + qr_id, + "Manufacturer's Name Edited", + "Customer Support's Name Edited", + "Vendor's Name Edited", + "Test note for asset creation edited!", + "25122021" + ); + + assetPage.clickUpdateAsset(); + + assetPage.verifySuccessNotification("Asset updated successfully"); + }); + + it("Verify Editted Asset", () => { + assetSearchPage.typeSearchKeyword("New Test Asset Edited"); + assetSearchPage.pressEnter(); + assetSearchPage.verifyAssetIsPresent("New Test Asset Edited"); + }); + + it("Configure an asset", () => { + assetPage.openCreatedAsset(); + assetPage.spyAssetConfigureApi(); + assetPage.configureAsset( + "Host name", + "192.168.1.64", + "remote_user", + "2jCkrCRSeahzKEU", + "d5694af2-21e2-4a39-9bad-2fb98d9818bd" + ); + assetPage.clickConfigureAsset(); + assetPage.verifyAssetConfiguration(200); + }); + + it("Add an vital monitor asset and configure it", () => { + assetPage.createAsset(); + assetPage.selectFacility("Dummy Facility 1"); + assetPage.selectLocation("Camera Loc"); + assetPage.selectAssetType("Internal"); + assetPage.selectAssetClass("HL7 Vitals Monitor"); + + const qr_id_1 = uuidv4(); + + assetPage.enterAssetDetails( + "New Test Asset Vital", + "Test Description", + "Working", + qr_id_1, + "Manufacturer's Name", + "2025-12-25", + "Customer Support's Name", + phone_number, + "email@support.com", + "Vendor's Name", + serialNumber, + "25122021", + "Test note for asset creation!" + ); + assetPage.interceptAssetCreation(); + assetPage.clickCreateAsset(); + assetPage.verifyAssetCreation(); + + assetSearchPage.typeSearchKeyword("New Test Asset Vital"); + assetSearchPage.pressEnter(); + + assetPage.openCreatedAsset(); + assetPage.configureVitalAsset("Host name", "192.168.1.64"); + assetPage.clickConfigureVital(); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/e2e/assets_spec/assets_manage.cy.ts b/cypress/e2e/assets_spec/assets_manage.cy.ts index 27843d7fa85..34c554b374e 100644 --- a/cypress/e2e/assets_spec/assets_manage.cy.ts +++ b/cypress/e2e/assets_spec/assets_manage.cy.ts @@ -1,15 +1,20 @@ -/// +import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; import { AssetPage } from "../../pageobject/Asset/AssetCreation"; -import { v4 as uuidv4 } from "uuid"; import LoginPage from "../../pageobject/Login/LoginPage"; import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; +import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; describe("Asset", () => { const assetPage = new AssetPage(); - const assetSearchPage = new AssetSearchPage(); const loginPage = new LoginPage(); - const phone_number = "9999999999"; - const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); + const facilityPage = new FacilityPage(); + const assetSearchPage = new AssetSearchPage(); + const assetFilters = new AssetFilters(); + const fillFacilityName = "Dummy Facility 1"; + const assetname = "Dummy Camera"; + const locationName = "Dummy Location 1"; + const initiallocationName = "Camera Location"; before(() => { loginPage.loginAsDisctrictAdmin(); @@ -21,102 +26,79 @@ describe("Asset", () => { cy.awaitUrl("/assets"); }); - it("Verify asset creation fields throws error if empty", () => { - assetPage.createAsset(); - assetPage.selectFacility("Dummy Facility 1"); - assetPage.clickCreateAsset(); - - assetPage.verifyEmptyAssetNameError(); - assetPage.verifyEmptyAssetTypeError(); - assetPage.verifyEmptyLocationError(); - assetPage.verifyEmptyStatusError(); - assetPage.verifyEmptyPhoneError(); - }); - - //Create an asset - - it("Create an Asset", () => { - assetPage.createAsset(); - assetPage.selectFacility("Dummy Facility 1"); - assetPage.selectLocation("Camera Loc"); - assetPage.selectAssetType("Internal"); - assetPage.selectAssetClass("ONVIF Camera"); - - const qr_id_1 = uuidv4(); - - assetPage.enterAssetDetails( - "New Test Asset 1", - "Test Description", - "Working", - qr_id_1, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "2021-12-25", - "Test note for asset creation!" - ); - - assetPage.clickCreateAddMore(); - assetPage.verifySuccessNotification("Asset created successfully"); - - const qr_id_2 = uuidv4(); - - assetPage.selectLocation("Camera Loc"); - assetPage.selectAssetType("Internal"); - assetPage.selectAssetClass("ONVIF Camera"); - assetPage.enterAssetDetails( - "New Test Asset 2", - "Test Description", - "Working", - qr_id_2, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "2021-12-25", - "Test note for asset creation!" - ); - - assetPage.clickCreateAsset(); - assetPage.verifySuccessNotification("Asset created successfully"); - - assetSearchPage.typeSearchKeyword("New Test Asset 2"); + it("Create & Edit a service history and verify reflection", () => { + assetSearchPage.typeSearchKeyword(assetname); assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetIsPresent("New Test Asset 2"); + assetSearchPage.verifyBadgeContent(assetname); + assetSearchPage.clickAssetByName(assetname); + assetPage.clickupdatedetailbutton(); + assetPage.scrollintonotes(); + assetPage.enterAssetNotes("Dummy Notes"); + assetPage.enterAssetservicedate("01092023"); + assetPage.clickassetupdatebutton(); + assetPage.scrollintoservicehistory(); + assetPage.clickedithistorybutton(); + assetPage.scrollintonotes(); + assetPage.enterAssetNotes("Dummy Notes Editted"); + assetPage.clickassetupdatebutton(); + assetPage.scrollintoservicehistory(); + assetPage.viewassetservicehistorybutton(); + assetPage.openassetservicehistory(); + assetPage.verifyassetupdateservicehistory(); + assetPage.viewassetservicehistorybutton(); }); - it("Edit an Asset", () => { - assetPage.openCreatedAsset(); - - const qr_id = uuidv4(); - - assetPage.editAssetDetails( - "New Test Asset Edited", - "Test Description Edited", - qr_id, - "Manufacturer's Name Edited", - "Customer Support's Name Edited", - "Vendor's Name Edited", - "Test note for asset creation edited!" - ); - + it("Create a asset transaction and verify history", () => { + assetSearchPage.typeSearchKeyword(assetname); + assetSearchPage.pressEnter(); + assetSearchPage.verifyBadgeContent(assetname); + assetSearchPage.clickAssetByName(assetname); + assetPage.clickupdatedetailbutton(); + assetPage.clickassetlocation(locationName); assetPage.clickUpdateAsset(); + assetPage.verifyassetlocation(locationName); + assetPage.verifytransactionStatus(initiallocationName, locationName); + }); - assetPage.verifySuccessNotification("Asset updated successfully"); + it("Verify Facility Asset Page Redirection", () => { + cy.visit("/facility"); + assetSearchPage.typeSearchKeyword(fillFacilityName); + assetSearchPage.pressEnter(); + facilityPage.verifyFacilityBadgeContent(fillFacilityName); + facilityPage.visitAlreadyCreatedFacility(); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickCreateAssetFacilityOption(); + facilityPage.verifyfacilitycreateassetredirection(); + facilityPage.verifyassetfacilitybackredirection(); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickviewAssetFacilityOption(); + facilityPage.verifyfacilityviewassetredirection(); + assetFilters.assertFacilityText(fillFacilityName); + facilityPage.verifyassetfacilitybackredirection(); }); it("Delete an Asset", () => { assetPage.openCreatedAsset(); + assetPage.interceptDeleteAssetApi(); assetPage.deleteAsset(); + assetPage.verifyDeleteStatus(); + }); - assetPage.verifySuccessNotification("Asset deleted successfully"); + it("Verify Facility Asset Page Redirection", () => { + cy.visit("/facility"); + assetSearchPage.typeSearchKeyword(fillFacilityName); + assetSearchPage.pressEnter(); + facilityPage.verifyFacilityBadgeContent(fillFacilityName); + facilityPage.visitAlreadyCreatedFacility(); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickCreateAssetFacilityOption(); + facilityPage.verifyfacilitycreateassetredirection(); + facilityPage.verifyassetfacilitybackredirection(); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickviewAssetFacilityOption(); + facilityPage.verifyfacilityviewassetredirection(); + assetFilters.assertFacilityText(fillFacilityName); + facilityPage.verifyassetfacilitybackredirection(); }); afterEach(() => { diff --git a/cypress/e2e/facility_spec/facility.cy.ts b/cypress/e2e/facility_spec/facility.cy.ts index 668b596f870..f2ff847c9d9 100644 --- a/cypress/e2e/facility_spec/facility.cy.ts +++ b/cypress/e2e/facility_spec/facility.cy.ts @@ -1,16 +1,20 @@ // FacilityCreation +import { cy, describe, before, beforeEach, it, afterEach } from "local-cypress"; import FacilityPage from "../../pageobject/Facility/FacilityCreation"; +import LoginPage from "../../pageobject/Login/LoginPage"; describe("Facility Creation", () => { let facilityUrl: string; const facilityPage = new FacilityPage(); + const loginPage = new LoginPage(); before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginAsDisctrictAdmin(); cy.saveLocalStorage(); }); beforeEach(() => { + cy.viewport(1280, 720); cy.restoreLocalStorage(); cy.awaitUrl("/facility"); }); @@ -35,14 +39,9 @@ describe("Facility Creation", () => { facilityPage.selectAreaOfSpecialization("General Medicine"); facilityPage.fillDoctorCount("5"); facilityPage.saveAndExitDoctorForm(); - - cy.url().then((initialUrl) => { - cy.get("button#save-and-exit").should("not.exist"); - cy.url() - .should("not.equal", initialUrl) - .then((newUrl) => { - facilityUrl = newUrl; - }); + facilityPage.verifyfacilitynewurl(); + cy.url().then((newUrl) => { + facilityUrl = newUrl; }); }); @@ -50,6 +49,7 @@ describe("Facility Creation", () => { facilityPage.visitUpdateFacilityPage(facilityUrl); facilityPage.clickManageFacilityDropdown(); facilityPage.clickUpdateFacilityOption(); + facilityPage.clickUpdateFacilityType(); facilityPage.fillFacilityName("cypress facility updated"); facilityPage.fillAddress("Cypress Facility Updated Address"); facilityPage.fillOxygenCapacity("100"); @@ -60,6 +60,22 @@ describe("Facility Creation", () => { cy.url().should("not.include", "/update"); }); + it("Configure the existing facility", () => { + facilityPage.visitUpdateFacilityPage(facilityUrl); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickConfigureFacilityOption(); + facilityPage.fillMiddleWareAddress("dev_middleware.coronasafe.live"); + facilityPage.clickupdateMiddleWare(); + facilityPage.verifySuccessNotification("Facility updated successfully"); + }); + + it("Delete a facility", () => { + facilityPage.visitUpdateFacilityPage(facilityUrl); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickDeleteFacilityOption(); + facilityPage.confirmDeleteFacility(); + }); + afterEach(() => { cy.saveLocalStorage(); }); diff --git a/cypress/e2e/facility_spec/inventory.cy.ts b/cypress/e2e/facility_spec/inventory.cy.ts index 6f19c6c0138..c28035dd885 100644 --- a/cypress/e2e/facility_spec/inventory.cy.ts +++ b/cypress/e2e/facility_spec/inventory.cy.ts @@ -1,28 +1,30 @@ import { cy, describe, before, beforeEach, it, afterEach } from "local-cypress"; +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; +import LoginPage from "../../pageobject/Login/LoginPage"; describe("Inventory Management Section", () => { + const facilityPage = new FacilityPage(); + const loginPage = new LoginPage(); + before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginAsDisctrictAdmin(); cy.saveLocalStorage(); }); beforeEach(() => { cy.restoreLocalStorage(); cy.awaitUrl("/"); - cy.get("[id='facility-details']").first().click(); - cy.get("[id=manage-facility-dropdown]").should("exist").click(); - cy.get("[id=inventory-management]").click(); + cy.viewport(1280, 720); }); it("Adds Inventory", () => { - cy.contains("Manage Inventory").click(); - cy.get("div#id").click(); - cy.get("div#id ul li").contains("Liquid Oxygen").click(); - cy.get("div#isIncoming").click(); - cy.get("div#isIncoming ul li").contains("Add Stock").click(); - cy.get("[name='quantity']").type("120"); - cy.get("button").contains("Add/Update Inventory").click(); - cy.verifyNotification("Inventory created successfully"); + facilityPage.visitAlreadyCreatedFacility(); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickInventoryManagementOption(); + facilityPage.clickManageInventory(); + facilityPage.fillInventoryDetails("Liquid Oxygen", "Add Stock", "120"); + facilityPage.clickAddInventory(); + facilityPage.verifySuccessNotification("Inventory created successfully"); }); afterEach(() => { diff --git a/cypress/e2e/facility_spec/locations.cy.ts b/cypress/e2e/facility_spec/locations.cy.ts index 783fe99a56c..d5b3cc9990f 100644 --- a/cypress/e2e/facility_spec/locations.cy.ts +++ b/cypress/e2e/facility_spec/locations.cy.ts @@ -7,10 +7,14 @@ describe("Location Management Section", () => { }); beforeEach(() => { + cy.viewport(1280, 720); cy.restoreLocalStorage(); cy.awaitUrl("/"); + cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); cy.get("[id='facility-details']").first().click(); - cy.get("[id=manage-facility-dropdown]").should("exist").click(); + cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); + cy.get("#manage-facility-dropdown button").should("be.visible"); + cy.get("[id='manage-facility-dropdown']").scrollIntoView().click(); cy.get("[id=location-management]").click(); }); diff --git a/cypress/e2e/patient_spec/patient_crud.cy.ts b/cypress/e2e/patient_spec/patient_crud.cy.ts index 69af8695ad6..b22ccdbce13 100644 --- a/cypress/e2e/patient_spec/patient_crud.cy.ts +++ b/cypress/e2e/patient_spec/patient_crud.cy.ts @@ -1,11 +1,13 @@ import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; - -const username = "devdistrictadmin"; -const password = "Coronasafe@123"; -const phone_number = "9" + Math.floor(100000000 + Math.random() * 900000000); -const emergency_phone_number = "9430123487"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { PatientPage } from "../../pageobject/Patient/PatientCreation"; +import { UpdatePatientPage } from "../../pageobject/Patient/PatientUpdate"; +import { PatientConsultationPage } from "../../pageobject/Patient/PatientConsultation"; +import { + emergency_phone_number, + phone_number, +} from "../../pageobject/constants"; const yearOfBirth = "2023"; -let patient_url = ""; const calculateAge = () => { const currentYear = new Date().getFullYear(); @@ -13,8 +15,13 @@ const calculateAge = () => { }; describe("Patient Creation with consultation", () => { + const loginPage = new LoginPage(); + const patientPage = new PatientPage(); + const updatePatientPage = new UpdatePatientPage(); + const patientConsultationPage = new PatientConsultationPage(); + before(() => { - cy.loginByApi(username, password); + loginPage.loginAsDisctrictAdmin(); cy.saveLocalStorage(); }); @@ -24,183 +31,108 @@ describe("Patient Creation with consultation", () => { }); it("Create a new patient with no consultation", () => { - cy.get("button").should("contain", "Add Patient Details"); - cy.get("#add-patient-div").click(); - cy.get("input[name='facilities']") - .type("cypress facility") - .then(() => { - cy.get("[role='option']").first().click(); - }); - cy.get("button").should("contain", "Select"); - cy.get("button").get("#submit").click(); - cy.get("#phone_number-div").type(phone_number); - cy.get("#emergency_phone_number-div").type(emergency_phone_number); - cy.get("[data-testid=date-of-birth] button").click(); - cy.get("#date-1").click(); - cy.get("[data-testid=name] input").type("Test E2E User"); - cy.get("[data-testid=Gender] button") - .click() - .then(() => { - cy.get("[role='option']").contains("Male").click(); - }); - cy.get("[data-testid=current-address] textarea").type( - "Test Patient Address" + patientPage.createPatient(); + patientPage.selectFacility("dummy facility"); + patientPage.patientformvisibility(); + patientPage.enterPatientDetails( + phone_number, + emergency_phone_number, + "Test E2E User", + "Male", + "Test Patient Address", + "682001", + "1: PAZHAMTHOTTAM", + "O+", + "01012001" ); - cy.get("[data-testid=permanent-address] input").check(); - cy.get("#pincode").type("682001"); - cy.get("[data-testid=localbody] button") - .click() - .then(() => { - cy.get("[role='option']").first().click(); - }); - cy.get("[data-testid=ward-respective-lsgi] button") - .click() - .then(() => { - cy.get("[role='option']").contains("1: PAZHAMTHOTTAM").click(); - }); - cy.get("[name=medical_history_check_1]").check(); - cy.get("[data-testid=blood-group] button") - .click() - .then(() => { - cy.get("[role='option']").contains("O+").click(); - }); - cy.get("button[data-testid='submit-button']").click(); + patientPage.clickCreatePatient(); - cy.get("h2").should("contain", "Create Consultation"); - cy.url().should("include", "/patient"); - cy.url().then((url) => { - cy.log(url); - patient_url = url.split("/").slice(0, -1).join("/"); - cy.log(patient_url); - }); + patientPage.verifyPatientIsCreated(); + patientPage.saveCreatedPatientUrl(); }); it("Patient Detail verification post registration", () => { - cy.log(patient_url); - cy.awaitUrl(patient_url); - cy.url().should("include", "/facility/"); - cy.get("[data-testid=patient-dashboard]").should("contain", calculateAge()); - cy.get("[data-testid=patient-dashboard]").should( - "contain", - "Test E2E User" - ); - cy.get("[data-testid=patient-dashboard]").should("contain", phone_number); - cy.get("[data-testid=patient-dashboard]").should( - "contain", - emergency_phone_number + patientPage.interceptFacilities(); + patientPage.visitCreatedPatient(); + patientPage.verifyStatusCode(); + const age = calculateAge(); + patientPage.verifyPatientDetails( + age, + "Test E2E User", + phone_number, + emergency_phone_number, + yearOfBirth, + "O+" ); - cy.get("[data-testid=patient-dashboard]").should("contain", yearOfBirth); - cy.get("[data-testid=patient-dashboard]").should("contain", "O+"); }); it("Edit the patient details", () => { - cy.awaitUrl(patient_url + "/update"); - cy.get("[data-testid=name] input").clear(); - cy.get("[data-testid=name] input").type("Test E2E User Edited"); - cy.get("#emergency_phone_number-div") - .clear() - .then(() => { - cy.get("#emergency_phone_number__country").select("IN"); - }); - cy.get("#emergency_phone_number-div").type("9120330220"); - cy.get("#address").clear().type("Test Patient Address Edited"); - cy.get("#present_health").type("Severe Cough"); - cy.get("#ongoing_medication").type("Paracetamol"); - cy.get("#allergies").type("Dust"); - cy.get("[name=medical_history_check_1]").uncheck(); - cy.get("[name=medical_history_check_2]").check(); - cy.get("#medical_history_2").type("2 months ago"); - cy.get("[name=medical_history_check_3]").check(); - cy.get("#medical_history_3").type("1 month ago"); - cy.get("button").get("[data-testid=add-insurance-button]").click(); - cy.get("#subscriber_id").type("SUB123"); - cy.get("#policy_id").type("P123"); - cy.get("#insurer_id").type("GICOFINDIA"); - cy.get("#insurer_name").type("GICOFINDIA"); - cy.get("button").get("[data-testid=submit-button]").click(); - cy.url().should("include", "/patient"); - cy.url().then((url) => { - cy.log(url); - patient_url = url.split("/").slice(0, -1).join("/"); - cy.log(patient_url); - }); - }); - - it("Patient Detail verification post edit", () => { - cy.log(patient_url); - cy.awaitUrl(patient_url); - cy.url().should("include", "/facility/"); - cy.get("[data-testid=patient-dashboard]").should( - "contain", - "Test E2E User Edited" - ); - cy.get("[data-testid=patient-dashboard]").should( - "contain", - "+919120330220" - ); - const patientDetails_values: string[] = [ + patientPage.interceptFacilities(); + patientPage.visitUpdatePatientUrl(); + patientPage.verifyStatusCode(); + patientPage.patientformvisibility(); + updatePatientPage.enterPatientDetails( + "Test E2E User Edited", + "O+", + phone_number, + emergency_phone_number, "Test Patient Address Edited", "Severe Cough", "Paracetamol", "Dust", - "Diabetes", - "2 months ago", - "Heart Disease", - "1 month ago", - ]; + ["2 months ago", "1 month ago"], + "SUB123", + "P123", + "GICOFINDIA", + "GICOFINDIA" + ); + updatePatientPage.clickUpdatePatient(); - patientDetails_values.forEach((value) => { - cy.get("[data-testid=patient-details]").should("contain", value); - }); + updatePatientPage.verifyPatientUpdated(); + updatePatientPage.saveUpdatedPatientUrl(); + }); + + it("Patient Detail verification post edit", () => { + patientPage.interceptFacilities(); + updatePatientPage.visitUpdatedPatient(); + patientPage.verifyStatusCode(); + + updatePatientPage.verifyPatientDetails( + "Test E2E User Edited", + phone_number, + "Severe Cough", + "Paracetamol", + "Dust" + ); }); it("Create a New consultation to existing patient", () => { - cy.visit(patient_url + "/consultation"); - cy.get("#consultation_status") - .click() - .then(() => { - cy.get("[role='option']").contains("Out-patient (walk in)").click(); - }); - cy.get("#symptoms") - .click() - .then(() => { - cy.get("[role='option']").contains("ASYMPTOMATIC").click(); - }); - cy.get("#symptoms").click(); - cy.get("#history_of_present_illness").click().type("histroy"); - cy.get("#examination_details") - .click() - .type("Examination details and Clinical conditions"); - cy.get("#weight").click().type("70"); - cy.get("#height").click().type("170"); - cy.get("#ip_no").type("192.168.1.11"); - cy.get( - "#icd11_diagnoses_object input[placeholder='Select'][role='combobox']" - ) - .click() - .type("1A"); - cy.wait(1000); - cy.get("#icd11_diagnoses_object [role='option']") - .contains("1A03 Intestinal infections due to Escherichia coli") - .click(); - cy.get("#consultation_notes").click().type("generalnote"); - cy.get("#verified_by").click().type("generalnote"); - cy.get("#submit").click(); + patientPage.interceptFacilities(); + updatePatientPage.visitConsultationPage(); + patientPage.verifyStatusCode(); + patientConsultationPage.fillIllnessHistory("history"); + patientConsultationPage.selectConsultationStatus("Out-patient (walk in)"); + patientConsultationPage.selectSymptoms("ASYMPTOMATIC"); + + patientConsultationPage.enterConsultationDetails( + "Examination details and Clinical conditions", + "70", + "170", + "IP007", + "generalnote", + "Dev Doctor" + ); + patientConsultationPage.submitConsultation(); + // Below code for the prescription module only present while creating a new consultation - cy.contains("button", "Add Prescription Medication") - .should("be.visible") - .click(); - cy.get("div#medicine_object input[placeholder='Select'][role='combobox']") - .click() - .type("dolo{enter}"); - cy.get("#dosage").type("3", { force: true }); - cy.get("#frequency") - .click() - .then(() => { - cy.get("div#frequency [role='option']").contains("Twice daily").click(); - }); - cy.get("button#submit").should("be.visible").click(); - cy.get("[data-testid='return-to-patient-dashboard']").click(); + patientConsultationPage.clickAddPrescription(); + patientConsultationPage.interceptMediaBase(); + patientConsultationPage.selectMedicinebox(); + patientConsultationPage.waitForMediabaseStatusCode(); + patientConsultationPage.prescribeMedicine(); + patientConsultationPage.enterDosage("3"); + patientConsultationPage.selectDosageFrequency("Twice daily"); + patientConsultationPage.submitPrescriptionAndReturn(); }); afterEach(() => { diff --git a/cypress/e2e/resource_spec/resources.cy.ts b/cypress/e2e/resource_spec/resources.cy.ts index 099e782277a..acf179db120 100644 --- a/cypress/e2e/resource_spec/resources.cy.ts +++ b/cypress/e2e/resource_spec/resources.cy.ts @@ -1,8 +1,17 @@ import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import ResourcePage from "../../pageobject/Resource/ResourcePage"; +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; describe("Resource Page", () => { + let createdResource: string; + const loginPage = new LoginPage(); + const resourcePage = new ResourcePage(); + const facilityPage = new FacilityPage(); + const phone_number = "9999999999"; + before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginAsDisctrictAdmin(); cy.saveLocalStorage(); }); @@ -11,36 +20,65 @@ describe("Resource Page", () => { cy.awaitUrl("/resource"); }); - it("checks if all download button works", () => { - cy.get("svg.care-svg-icon__baseline.care-l-export").each(($button) => { - cy.intercept(/\/api\/v1\/resource/).as("resource_download"); - cy.wrap($button).click({ force: true }); - cy.wait("@resource_download").then((interception) => { - expect(interception.response.statusCode).to.equal(200); - }); - }); + it("Checks if all download button works", () => { + resourcePage.verifyDownloadButtonWorks(); }); - it("switch between active/completed", () => { - cy.intercept(/\/api\/v1\/resource/).as("resource"); - cy.contains("Completed").click(); - cy.wait("@resource").then((interception) => { - expect(interception.response.statusCode).to.equal(200); - }); - cy.contains("Active").should("have.class", "text-primary-500"); - cy.contains("Completed").should("have.class", "text-white"); - cy.intercept(/\/api\/v1\/resource/).as("resource"); - cy.contains("Active").click(); - cy.wait("@resource").then((interception) => { - expect(interception.response.statusCode).to.equal(200); + it("Switch between active/completed", () => { + resourcePage.spyResourceApi(); + resourcePage.clickCompletedResources(); + resourcePage.verifyCompletedResources(); + resourcePage.spyResourceApi(); + resourcePage.clickActiveResources(); + resourcePage.verifyActiveResources(); + }); + + it("Switch between list view and board view", () => { + resourcePage.clickListViewButton(); + resourcePage.clickBoardViewButton(); + }); + + it("Create a resource request", () => { + cy.visit("/facility"); + cy.get("#search").click().type("dummy facility 1"); + cy.intercept("GET", "**/api/v1/facility/**").as("loadFacilities"); + cy.get("#facility-details").click(); + cy.wait("@loadFacilities").its("response.statusCode").should("eq", 200); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickResourceRequestOption(); + facilityPage.fillResourceRequestDetails( + "Test User", + phone_number, + "Dummy", + "Test title", + "10", + "Test description" + ); + facilityPage.clickSubmitRequestButton(); + facilityPage.verifySuccessNotification( + "Resource request created successfully" + ); + facilityPage.verifyresourcenewurl(); + cy.url().then((url) => { + createdResource = url; }); - cy.contains("Active").should("have.class", "text-white"); - cy.contains("Completed").should("have.class", "text-primary-500"); }); - it("switch between list view and board view", () => { - cy.contains("List View").click(); - cy.contains("Board View").click(); + it("Update the status of resource", () => { + cy.visit(createdResource); + resourcePage.clickUpdateStatus(); + resourcePage.updateStatus("APPROVED"); + resourcePage.clickSubmitButton(); + resourcePage.verifySuccessNotification( + "Resource request updated successfully" + ); + }); + + it("Post comment for a resource", () => { + cy.visit(createdResource); + resourcePage.addCommentForResource("Test comment"); + resourcePage.clickPostCommentButton(); + resourcePage.verifySuccessNotification("Comment added successfully"); }); afterEach(() => { diff --git a/cypress/e2e/users_spec/user_crud.cy.ts b/cypress/e2e/users_spec/user_crud.cy.ts index 24dcb91de33..41a12a891a8 100644 --- a/cypress/e2e/users_spec/user_crud.cy.ts +++ b/cypress/e2e/users_spec/user_crud.cy.ts @@ -38,17 +38,15 @@ describe("User management", () => { cy.intercept(/\/api\/v1\/facility/).as("facility"); cy.get("[name='facilities']") .click() - .type("cypress facility") + .type("Dummy Facility 1") .wait("@facility"); cy.get("li[role='option']").first().click(); cy.get("input[type='checkbox']").click(); cy.get("[name='phone_number']").type(phone_number); cy.get("[name='alt_phone_number']").type(alt_phone_number); cy.intercept(/users/).as("check_availability"); - cy.get("[id='date_of_birth']").click(); - cy.get("div").contains("20").click(); - cy.get("[id='year-0']").click(); - cy.get("[id='date-1']").click(); + cy.get("#date_of_birth").should("be.visible").click(); + cy.get("#date-input").click().type("25081999"); cy.get("[name='username']").type(username); cy.wait("@check_availability").its("response.statusCode").should("eq", 200); cy.get("[name='password']").type("#@Cypress_test123"); @@ -95,7 +93,7 @@ describe("User management", () => { cy.get("button[id='facilities']").click(); cy.wait("@userFacility") .getAttached("div[id=facility_0] > div > span") - .contains("cypress facility"); + .contains("Dummy Facility 1"); }); }); @@ -104,7 +102,7 @@ describe("User management", () => { cy.intercept(/\/api\/v1\/facility/).as("getFacilities"); cy.get("[name='facility']") .click() - .type("cypress facility") + .type("Dummy Facility 1") .wait("@getFacilities"); cy.get("li[role='option']").first().click(); cy.intercept(/\/api\/v1\/users\/\w+\/add_facility\//).as("addFacility"); diff --git a/cypress/fixtures/sampleAsset.xlsx b/cypress/fixtures/sampleAsset.xlsx new file mode 100644 index 00000000000..f8e234ce447 Binary files /dev/null and b/cypress/fixtures/sampleAsset.xlsx differ diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index 44841a34a65..45356a1a4e7 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -1,4 +1,5 @@ // assetPage.ts +import { cy, expect } from "local-cypress"; export class AssetPage { createAsset() { @@ -67,12 +68,21 @@ export class AssetPage { cy.get("[data-testid=asset-support-email-input] input").type(supportEmail); cy.get("[data-testid=asset-vendor-name-input] input").type(vendorName); cy.get("[data-testid=asset-serial-number-input] input").type(serialNumber); - cy.get("[data-testid=asset-last-serviced-on-input] input").type( - lastServicedOn - ); + cy.get( + "[data-testid=asset-last-serviced-on-input] input[type='text']" + ).click(); + cy.get("#date-input").click().type(lastServicedOn); cy.get("[data-testid=asset-notes-input] textarea").type(notes); } + interceptAssetCreation() { + cy.intercept("POST", "**/api/v1/asset/").as("createAsset"); + } + + verifyAssetCreation() { + cy.wait("@createAsset").its("response.statusCode").should("eq", 201); + } + clickCreateAsset() { cy.get("#submit").contains("Create Asset").click(); } @@ -86,7 +96,9 @@ export class AssetPage { } openCreatedAsset() { + cy.intercept("GET", "**/api/v1/asset/**").as("getAsset"); cy.get("[data-testid=created-asset-list]").first().click(); + cy.wait("@getAsset").its("response.statusCode").should("eq", 200); } editAssetDetails( @@ -96,7 +108,8 @@ export class AssetPage { manufacturer: string, supportName: string, vendorName: string, - notes: string + notes: string, + lastServicedOn: string ) { cy.get("[data-testid=asset-update-button]").click(); cy.get("[data-testid=asset-name-input] input").clear().type(name); @@ -113,18 +126,71 @@ export class AssetPage { cy.get("[data-testid=asset-vendor-name-input] input") .clear() .type(vendorName); + cy.get( + "[data-testid=asset-last-serviced-on-input] input[type='text']" + ).click(); + cy.get("#date-input").click().type(lastServicedOn); cy.get("[data-testid=asset-notes-input] textarea").clear().type(notes); } + configureAsset( + hostName: string, + localIp: string, + userName: string, + password: string, + streamUuid: string + ) { + cy.get("[data-testid=asset-configure-button]").click(); + cy.get("[name=middleware_hostname]").type(hostName); + cy.get("[name=camera_address]").type(localIp); + cy.get("[name=username]").type(userName); + cy.get("[name=password]").type(password); + cy.get("[name=stream_uuid]").type(streamUuid); + } + + configureVitalAsset(hostName: string, localIp: string) { + cy.get("[data-testid=asset-configure-button]").click(); + cy.get("#middlewareHostname").type(hostName); + cy.get("#localipAddress").type(localIp); + } + + spyAssetConfigureApi() { + cy.intercept(/\/api\/v1\/asset/).as("asset"); + } + + verifyAssetConfiguration(statusCode: number) { + cy.wait("@asset").then((interception) => { + expect(interception.response.statusCode).to.equal(statusCode); + }); + } + + clickConfigureAsset() { + cy.get("#submit").contains("Set Configuration").click(); + } + + clickConfigureVital() { + cy.intercept("PATCH", "**/api/v1/asset/**").as("postConfiguration"); + cy.get("#submit").contains("Save Configuration").click(); + cy.wait("@postConfiguration").its("response.statusCode").should("eq", 200); + } + clickUpdateAsset() { cy.get("#submit").contains("Update").click(); } + interceptDeleteAssetApi() { + cy.intercept("DELETE", "**/api/v1/asset/**").as("deleteAsset"); + } + deleteAsset() { cy.get("[data-testid=asset-delete-button]").click(); cy.get("#submit").contains("Confirm").click(); } + verifyDeleteStatus() { + cy.wait("@deleteAsset").its("response.statusCode").should("eq", 204); + } + verifyEmptyAssetNameError() { cy.get("[data-testid=asset-name-input] span").should( "contain", @@ -159,4 +225,129 @@ export class AssetPage { "Please enter valid phone number" ); } + + 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").then(({ request, response }) => { + expect(response.statusCode).to.eq(200); + expect(request.url).to.include("json=true"); + }); + } + + selectcsvexportbutton() { + cy.intercept("GET", "**/api/v1/asset/?csv=true**").as("getCsvexport"); + cy.get("#export-csv-option").click(); + cy.wait("@getCsvexport").then(({ request, response }) => { + expect(response.statusCode).to.eq(200); + expect(request.url).to.include("csv=true"); + }); + } + + selectImportOption() { + cy.get(".import-assets-button").click(); + } + + importAssetFile() { + cy.get("[data-testid=import-asset-file]") + .selectFile("cypress/fixtures/sampleAsset.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(); + } + + scrollintonotes() { + cy.get("#notes").scrollIntoView(); + } + + enterAssetNotes(text) { + cy.get("#notes").click().clear(); + cy.get("#notes").click().type(text); + } + + enterAssetservicedate(text) { + cy.get("input[name='last_serviced_on']").click(); + cy.get("#date-input").click().type(text); + } + + clickassetupdatebutton() { + cy.get("#submit").click(); + } + + viewassetservicehistorybutton() { + cy.get("#view-service-history").should("be.visible"); + } + + openassetservicehistory() { + cy.get("#view-service-history").click(); + cy.get("#view-asset-edit-history").first().click(); + } + + verifyassetupdateservicehistory() { + cy.get("#edit-history-asset-servicedon").should("have.text", "01/09/2023"); + cy.get("#edit-history-asset-note").should( + "have.text", + "Dummy Notes Editted" + ); + cy.get("#view-history-back-button").contains("Back").click(); + cy.get("#view-history-back-button").contains("Close").click(); + } + + scrollintoservicehistory() { + cy.get("#service-history").scrollIntoView(); + } + + clickedithistorybutton() { + cy.get("#edit-service-history").click(); + } + + verifytransactionStatus(initiallocationName: string, locationName: string) { + cy.get("#transaction-history").scrollIntoView(); + cy.get("#transaction-history table tbody tr:first-child td:eq(0)").should( + "contain", + initiallocationName + ); + cy.get("#transaction-history table tbody tr:first-child td:eq(1)").should( + "contain", + locationName + ); + } + + verifyassetlocation(locationName: string) { + cy.get("#asset-current-location").should("contain", locationName); + } + + clickassetlocation(locationName: string) { + cy.get("#clear-button").click(); + cy.get("[data-testid=asset-location-input] button").click(); + cy.get("[data-testid=asset-location-input] button") + .click() + .type(locationName); + cy.get("[role='option']").contains(locationName).click(); + } } diff --git a/cypress/pageobject/Asset/AssetFilters.ts b/cypress/pageobject/Asset/AssetFilters.ts index 57cc893bdb7..a16b61f4fc5 100644 --- a/cypress/pageobject/Asset/AssetFilters.ts +++ b/cypress/pageobject/Asset/AssetFilters.ts @@ -3,7 +3,8 @@ export class AssetFilters { facilityName: string, assetType: string, assetStatus: string, - assetClass: string + assetClass: string, + assetLocation: string ) { cy.contains("Advanced Filters").click(); cy.get("input[name='Facilities']") @@ -27,6 +28,42 @@ export class AssetFilters { .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.url().should("match", /\/assets$/); + } + clickadvancefilter() { + cy.intercept("GET", "**/api/v1/getallfacilities/**").as("advancefilter"); + cy.get("#advanced-filter").click(); + cy.wait("@advancefilter").its("response.statusCode").should("eq", 200); + } + clickslideoverbackbutton() { + cy.get("#close-slide-over").click(); + } + // Assertions + assertFacilityText(text) { + cy.get("[data-testid=Facility]").should("contain", text); + } + assertAssetTypeText(text) { + cy.get("[data-testid='Asset Type']").should("contain", text); + } + assertAssetClassText(text) { + cy.get("[data-testid='Asset Class']").should("contain", text); + } + assertStatusText(text) { + cy.get("[data-testid=Status]").should("contain", text); + } + assertLocationText(text) { + cy.get("[data-testid=Location]").should("contain", text); + } } diff --git a/cypress/pageobject/Asset/AssetSearch.ts b/cypress/pageobject/Asset/AssetSearch.ts index 315a414a62b..b1ccb2f71c9 100644 --- a/cypress/pageobject/Asset/AssetSearch.ts +++ b/cypress/pageobject/Asset/AssetSearch.ts @@ -1,16 +1,24 @@ export class AssetSearchPage { typeSearchKeyword(keyword: string) { - cy.get("[name='search']").type(keyword); + cy.get("#search").click().clear(); + cy.get("#search").click().type(keyword); } pressEnter() { cy.get("[name='search']").type("{enter}"); } - verifyUrlChanged(initialUrl: string) { - cy.url().should((currentUrl) => { - expect(currentUrl).not.to.equal(initialUrl); - }); + 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) { @@ -18,4 +26,35 @@ export class AssetSearchPage { .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 f5b4f2fcb9a..42ec6d8fd7c 100644 --- a/cypress/pageobject/Facility/FacilityCreation.ts +++ b/cypress/pageobject/Facility/FacilityCreation.ts @@ -1,11 +1,28 @@ // FacilityPage.ts +import { cy } from "local-cypress"; + class FacilityPage { visitCreateFacilityPage() { + cy.intercept("GET", "**/facility/create").as("getCreateFacilities"); cy.visit("/facility/create"); + cy.wait("@getCreateFacilities") + .its("response.statusCode") + .should("eq", 200); } visitUpdateFacilityPage(url: string) { + cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); cy.visit(url); + cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); + cy.get("#manage-facility-dropdown button").should("be.visible"); + } + + clickUpdateFacilityType() { + cy.get("#facility_type") + .click() + .then(() => { + cy.get("[role='option']").contains("Request Approving Center").click(); + }); } fillFacilityName(name: string) { @@ -83,17 +100,61 @@ class FacilityPage { } saveAndExitDoctorForm() { + cy.intercept("GET", "**/api/v1/facility/**").as("createFacilities"); cy.get("button#save-and-exit").click(); + cy.wait("@createFacilities").its("response.statusCode").should("eq", 200); } clickManageFacilityDropdown() { - cy.get("#manage-facility-dropdown").click(); + cy.get("#manage-facility-dropdown button").scrollIntoView(); + cy.get("#manage-facility-dropdown button") + .contains("Manage Facility") + .click(); } clickUpdateFacilityOption() { cy.get("#update-facility").contains("Update Facility").click(); } + clickConfigureFacilityOption() { + cy.get("#configure-facility").contains("Configure Facility").click(); + } + + clickCreateAssetFacilityOption() { + cy.get("#create-assets").contains("Create Asset").click(); + } + + clickviewAssetFacilityOption() { + cy.get("#view-assets").contains("View Assets").click(); + } + + clickInventoryManagementOption() { + cy.get("#inventory-management", { timeout: 10000 }).should("be.visible"); + cy.get("#inventory-management").click(); + } + + clickResourceRequestOption() { + cy.get("#resource-request").contains("Resource Request").click(); + } + + clickDeleteFacilityOption() { + cy.get("#delete-facility").contains("Delete Facility").click(); + } + + verifyfacilitynewurl() { + cy.url().should("match", /facility\/[a-z\d-]+/); + } + + verifyresourcenewurl() { + cy.url().should("match", /resource\/[a-z\d-]+/); + } + + confirmDeleteFacility() { + cy.intercept("DELETE", "**/api/v1/facility/**").as("deleteFacility"); + cy.get("#submit").contains("Delete").click(); + cy.wait("@deleteFacility").its("response.statusCode").should("eq", 403); + } + selectLocation(location: string) { cy.get("span > svg.care-svg-icon__baseline.care-l-map-marker").click(); cy.intercept("https://maps.googleapis.com/maps/api/mapsjs/*").as("mapApi"); @@ -101,6 +162,97 @@ class FacilityPage { cy.get("input#pac-input").type(location).type("{enter}"); cy.get("div#map-close").click(); } + + fillMiddleWareAddress(url: string) { + cy.get("#middleware_address").type(url); + } + + clickupdateMiddleWare() { + cy.intercept("PATCH", "**/api/v1/facility/**").as("updateMiddleWare"); + cy.get("button#submit").first().click(); + cy.wait("@updateMiddleWare").its("response.statusCode").should("eq", 200); + } + + verifySuccessNotification(message: string) { + cy.verifyNotification(message); + } + + visitAlreadyCreatedFacility() { + cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); + cy.get("[id='facility-details']").first().click(); + cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); + } + + verifyFacilityBadgeContent(expectedText: string) { + cy.get("[data-testid='Facility/District Name']").should( + "contain", + expectedText + ); + } + + verifyfacilitycreateassetredirection() { + cy.url().should("include", "/assets/new"); + } + + verifyassetfacilitybackredirection() { + cy.intercept("GET", "**/api/v1/facility/**").as("getManagePage"); + cy.go("back"); + cy.wait("@getManagePage").its("response.statusCode").should("eq", 200); + cy.get("#manage-facility-dropdown").scrollIntoView(); + cy.get("#manage-facility-dropdown").should("exist"); + } + + verifyfacilityviewassetredirection() { + cy.url().should("include", "/assets?facility="); + } + + clickManageInventory() { + cy.contains("Manage Inventory").click(); + } + + fillInventoryDetails(name: string, status: string, quantity: string) { + cy.get("div#id").click(); + cy.get("div#id ul li").contains(name).click(); + cy.get("div#isIncoming").click(); + cy.get("div#isIncoming ul li").contains(status).click(); + cy.get("[name='quantity']").type(quantity); + } + + clickAddInventory() { + cy.intercept("POST", "**/api/v1/facility/*/inventory/").as( + "createInventory" + ); + cy.get("button").contains("Add/Update Inventory").click(); + cy.wait("@createInventory").its("response.statusCode").should("eq", 201); + } + + fillResourceRequestDetails( + name: string, + phone_number: string, + facility: string, + title: string, + quantity: string, + description: string + ) { + cy.get("#refering_facility_contact_name").type(name); + cy.get("#refering_facility_contact_number").type(phone_number); + cy.get("[name='approving_facility']") + .type(facility) + .then(() => { + cy.get("[role='option']").first().click(); + }); + cy.get("#title").type(title); + cy.get("#requested_quantity").type(quantity); + cy.get("#reason").type(description); + } + + clickSubmitRequestButton() { + cy.intercept("POST", "**/api/v1/resource/").as("createResourceRequest"); + cy.get("button").contains("Submit").click(); + cy.wait("@createResourceRequest") + .its("response.statusCode") + .should("eq", 201); + } } export default FacilityPage; diff --git a/cypress/pageobject/Login/LoginPage.ts b/cypress/pageobject/Login/LoginPage.ts index e75524ad3f4..f691d5f9e15 100644 --- a/cypress/pageobject/Login/LoginPage.ts +++ b/cypress/pageobject/Login/LoginPage.ts @@ -1,4 +1,6 @@ // LoginPage.ts +import { cy } from "local-cypress"; + class LoginPage { loginAsDisctrictAdmin(): void { cy.loginByApi("devdistrictadmin", "Coronasafe@123"); diff --git a/cypress/pageobject/Patient/PatientConsultation.ts b/cypress/pageobject/Patient/PatientConsultation.ts new file mode 100644 index 00000000000..b1c95d19140 --- /dev/null +++ b/cypress/pageobject/Patient/PatientConsultation.ts @@ -0,0 +1,114 @@ +export class PatientConsultationPage { + selectConsultationStatus(status: string) { + cy.get("#consultation_status") + .click() + .then(() => { + cy.get("[role='option']").contains(status).click(); + }); + } + + selectSymptoms(symptoms: string) { + cy.get("#symptoms") + .click() + .then(() => { + cy.get("[role='option']").contains(symptoms).click(); + }); + } + + fillIllnessHistory(history: string) { + cy.wait(5000); + cy.get("#history_of_present_illness").scrollIntoView(); + cy.get("#history_of_present_illness").should("be.visible"); + cy.get("#history_of_present_illness").click().type(history); + } + + enterConsultationDetails( + examinationDetails: string, + weight: string, + height: string, + ipNumber: string, + consulationNotes: string, + verificationBy: string + ) { + cy.get("#symptoms").click(); + cy.get("#examination_details").click().type(examinationDetails); + cy.get("#weight").click().type(height); + cy.get("#height").click().type(weight); + cy.get("#patient_no").type(ipNumber); + cy.intercept("GET", "**/icd/**").as("getIcdResults"); + cy.get( + "#icd11_diagnoses_object input[placeholder='Select'][role='combobox']" + ) + .click() + .type("1A"); + cy.get("#icd11_diagnoses_object [role='option']") + .contains("1A03 Intestinal infections due to Escherichia coli") + .click(); + cy.get("label[for='icd11_diagnoses_object']").click(); + cy.wait("@getIcdResults").its("response.statusCode").should("eq", 200); + + cy.get("#icd11_principal_diagnosis [role='combobox']").click().type("1A"); + cy.get("#icd11_principal_diagnosis [role='option']") + .contains("1A03 Intestinal infections due to Escherichia coli") + .click(); + + cy.get("#consultation_notes").click().type(consulationNotes); + cy.get("#verified_by") + .click() + .type(verificationBy) + .then(() => { + cy.get("[role='option']").contains("Dev Doctor").click(); + }); + } + + submitConsultation() { + cy.get("#submit").click(); + } + + clickAddPrescription() { + cy.contains("button", "Add Prescription Medication") + .should("be.visible") + .click(); + } + + interceptMediaBase() { + cy.intercept("GET", "**/api/v1/medibase/**").as("getMediaBase"); + } + + prescribeMedicine() { + cy.get("div#medicine_object input[placeholder='Select'][role='combobox']") + .click() + .type("dolo{enter}"); + } + + selectMedicinebox() { + cy.get( + "div#medicine_object input[placeholder='Select'][role='combobox']" + ).click(); + } + + waitForMediabaseStatusCode() { + cy.wait("@getMediaBase").its("response.statusCode").should("eq", 200); + } + + enterDosage(doseAmount: string) { + cy.get("#dosage").type(doseAmount, { force: true }); + } + + selectDosageFrequency(frequency: string) { + cy.get("#frequency") + .click() + .then(() => { + cy.get("div#frequency [role='option']").contains(frequency).click(); + }); + } + + submitPrescriptionAndReturn() { + cy.intercept("POST", "**/api/v1/consultation/*/prescriptions/").as( + "submitPrescription" + ); + cy.get("button#submit").should("be.visible").click(); + cy.get("[data-testid='return-to-patient-dashboard']").click(); + cy.wait("@submitPrescription").its("response.statusCode").should("eq", 201); + } +} diff --git a/cypress/pageobject/Patient/PatientCreation.ts b/cypress/pageobject/Patient/PatientCreation.ts new file mode 100644 index 00000000000..4fcd43dc490 --- /dev/null +++ b/cypress/pageobject/Patient/PatientCreation.ts @@ -0,0 +1,131 @@ +// PatientPage.ts + +let patient_url = ""; + +export class PatientPage { + createPatient() { + cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); + cy.get("#add-patient-details").should("be.visible"); + cy.get("#add-patient-details").click(); + cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); + } + + selectFacility(facilityName: string) { + cy.get("input[name='facilities']") + .type(facilityName) + .then(() => { + cy.get("[role='option']").first().click(); + }); + cy.get("button").should("contain", "Select"); + cy.get("button").get("#submit").click(); + } + + interceptCreatePatientAPI() { + cy.intercept("GET", "**/facility/*/patient/**").as("createPatient"); + } + + verifyCreatedPatientResponse() { + cy.wait("@createPatient").its("response.statusCode").should("eq", 200); + } + + enterPatientDetails( + phoneNumber: string, + emergencyPhoneNumber: string, + patientName: string, + gender: string, + address: string, + pincode: string, + wardName: string, + bloodGroup: string, + dateOfBirth: string + ) { + cy.get("#phone_number-div").type(phoneNumber); + cy.get("#emergency_phone_number-div").type(emergencyPhoneNumber); + cy.get("#date_of_birth").should("be.visible").click(); + cy.get("#date-input").click().type(dateOfBirth); + cy.get("[data-testid=name] input").type(patientName); + cy.get("[data-testid=Gender] button") + .click() + .then(() => { + cy.get("[role='option']").contains(gender).click(); + }); + cy.get("[data-testid=current-address] textarea").type(address); + cy.get("[data-testid=permanent-address] input").check(); + cy.get("#pincode").type(pincode); + cy.get("[data-testid=localbody] button") + .click() + .then(() => { + cy.get("[role='option']").first().click(); + }); + cy.get("[data-testid=ward-respective-lsgi] button") + .click() + .then(() => { + cy.get("[role='option']").contains(wardName).click(); + }); + cy.get("[name=medical_history_check_1]").check(); + cy.get("[data-testid=blood-group] button") + .click() + .then(() => { + cy.get("[role='option']").contains(bloodGroup).click(); + }); + } + + clickCreatePatient() { + cy.intercept("POST", "**/api/v1/patient/").as("createPatient"); + cy.get("button[data-testid='submit-button']").click(); + cy.wait("@createPatient").its("response.statusCode").should("eq", 201); + } + + verifyPatientIsCreated() { + cy.get("h2").should("contain", "Create Consultation"); + cy.url().should("include", "/patient"); + } + + saveCreatedPatientUrl() { + cy.url().then((url) => { + cy.log(url); + patient_url = url.split("/").slice(0, -1).join("/"); + cy.log(patient_url); + }); + } + + visitCreatedPatient() { + cy.awaitUrl(patient_url); + } + + verifyPatientDetails( + age: number, + patientName: string, + phoneNumber: string, + emergencyPhoneNumber: string, + yearOfBirth: string, + bloodGroup: string + ) { + cy.url().should("include", "/facility/"); + cy.get("[data-testid=patient-dashboard]").should("contain", age); + cy.get("[data-testid=patient-dashboard]").should("contain", patientName); + cy.get("[data-testid=patient-dashboard]").should("contain", phoneNumber); + cy.get("[data-testid=patient-dashboard]").should( + "contain", + emergencyPhoneNumber + ); + cy.get("[data-testid=patient-dashboard]").should("contain", yearOfBirth); + cy.get("[data-testid=patient-dashboard]").should("contain", bloodGroup); + } + + visitUpdatePatientUrl() { + cy.awaitUrl(patient_url + "/update"); + } + + interceptFacilities() { + cy.intercept("GET", "**/facility/*/patient/**").as("getFacilities"); + } + + verifyStatusCode() { + cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); + } + + patientformvisibility() { + cy.get("[data-testid='current-address']").scrollIntoView(); + } +} diff --git a/cypress/pageobject/Patient/PatientUpdate.ts b/cypress/pageobject/Patient/PatientUpdate.ts new file mode 100644 index 00000000000..b26ef678679 --- /dev/null +++ b/cypress/pageobject/Patient/PatientUpdate.ts @@ -0,0 +1,97 @@ +let patient_url = ""; + +export class UpdatePatientPage { + enterPatientDetails( + patientName: string, + bloodGroup: string, + phoneNumber: string, + emergencyPhoneNumber: string, + address: string, + currentHealthCondition: string, + ongoingMedication: string, + allergies: string, + medicalHistory: string[], + subscriberId: string, + policyId: string, + insuranceId: string, + insuranceName: string + ) { + cy.wait(10000); + cy.get("#address").scrollIntoView(); + cy.get("#address").should("be.visible"); + cy.get("#address").type(address); + cy.get("[data-testid=name] input").clear(); + cy.get("[data-testid=name] input").type(patientName); + cy.get("#phone_number-div").clear(); + cy.get("#phone_number-div").type("+91").type(phoneNumber); + cy.get("#emergency_phone_number-div").clear(); + cy.get("#emergency_phone_number-div") + .type("+91") + .type(emergencyPhoneNumber); + cy.get("#present_health").type(currentHealthCondition); + cy.get("#ongoing_medication").type(ongoingMedication); + cy.get("#allergies").type(allergies); + cy.get("[name=medical_history_check_1]").uncheck(); + cy.get("[name=medical_history_check_2]").check(); + cy.get("#medical_history_2").type(medicalHistory[0]); + cy.get("[name=medical_history_check_3]").check(); + cy.get("#medical_history_3").type(medicalHistory[1]); + cy.get("button").get("[data-testid=add-insurance-button]").click(); + cy.get("#subscriber_id").type(subscriberId); + cy.get("#policy_id").type(policyId); + cy.get("#insurer_id").type(insuranceId); + cy.get("#insurer_name").type(insuranceName); + cy.get("[data-testid=blood-group] button") + .click() + .then(() => { + cy.get("[role='option']").contains(bloodGroup).click(); + }); + } + + clickUpdatePatient() { + cy.intercept("PUT", "**/api/v1/patient/**").as("updatePatient"); + cy.get("button").get("[data-testid=submit-button]").click(); + cy.wait("@updatePatient").its("response.statusCode").should("eq", 200); + } + + verifyPatientUpdated() { + cy.url().should("include", "/patient"); + } + + saveUpdatedPatientUrl() { + cy.url().then((url) => { + cy.log(url); + patient_url = url.split("/").slice(0, -1).join("/"); + cy.log(patient_url); + }); + } + + visitUpdatedPatient() { + cy.awaitUrl(patient_url); + } + + verifyPatientDetails( + patientName: string, + phoneNumber: string, + presentHealth: string, + ongoingMedication: string, + allergies: string + ) { + cy.url().should("include", "/facility/"); + cy.get("[data-testid=patient-dashboard]").should("contain", patientName); + cy.get("[data-testid=patient-dashboard]").should("contain", phoneNumber); + cy.get("[data-testid=patient-present-health]").should( + "contain", + presentHealth + ); + cy.get("[data-testid=patient-ongoing-medication]").should( + "contain", + ongoingMedication + ); + cy.get("[data-testid=patient-allergies]").should("contain", allergies); + } + + visitConsultationPage() { + cy.visit(patient_url + "/consultation"); + } +} diff --git a/cypress/pageobject/Resource/ResourcePage.ts b/cypress/pageobject/Resource/ResourcePage.ts new file mode 100644 index 00000000000..f7feac925bf --- /dev/null +++ b/cypress/pageobject/Resource/ResourcePage.ts @@ -0,0 +1,79 @@ +// ResoucrePage.ts +class ResourcePage { + verifyDownloadButtonWorks() { + cy.get("svg.care-svg-icon__baseline.care-l-export").each(($button) => { + cy.intercept(/\/api\/v1\/resource/).as("resource_download"); + cy.wrap($button).click({ force: true }); + cy.wait("@resource_download").then((interception) => { + expect(interception.response.statusCode).to.equal(200); + }); + }); + } + + spyResourceApi() { + cy.intercept(/\/api\/v1\/resource/).as("resource"); + } + + clickCompletedResources() { + cy.contains("Completed").click(); + } + + verifyCompletedResources() { + cy.wait("@resource").then((interception) => { + expect(interception.response.statusCode).to.equal(200); + }); + cy.contains("Active").should("have.class", "text-primary-500"); + cy.contains("Completed").should("have.class", "text-white"); + } + + clickActiveResources() { + cy.contains("Active").click(); + } + + verifyActiveResources() { + cy.wait("@resource").then((interception) => { + expect(interception.response.statusCode).to.equal(200); + }); + cy.contains("Active").should("have.class", "text-white"); + cy.contains("Completed").should("have.class", "text-primary-500"); + } + + clickListViewButton() { + cy.contains("List View").click(); + } + + clickBoardViewButton() { + cy.contains("Board View").click(); + } + + clickUpdateStatus() { + cy.get("[data-testid='update-status']").click(); + } + + updateStatus(status: string) { + cy.get("#status").click(); + cy.get("[role='option']").contains(status).click(); + } + + clickSubmitButton() { + cy.intercept("PUT", "**/api/v1/resource/**/").as("updateResource"); + cy.get("#submit").contains("Submit").click(); + cy.wait("@updateResource").its("response.statusCode").should("eq", 200); + } + + verifySuccessNotification(message: string) { + cy.verifyNotification(message); + } + + addCommentForResource(comment: string) { + cy.get("#comment").type(comment); + } + + clickPostCommentButton() { + cy.intercept("POST", "**/api/v1/resource/*/comment/").as("postComment"); + cy.contains("Post Your Comment").click(); + cy.wait("@postComment").its("response.statusCode").should("eq", 201); + } +} + +export default ResourcePage; diff --git a/cypress/pageobject/constants.ts b/cypress/pageobject/constants.ts new file mode 100644 index 00000000000..72e0d31c662 --- /dev/null +++ b/cypress/pageobject/constants.ts @@ -0,0 +1,4 @@ +export const phone_number = + "9" + Math.floor(100000000 + Math.random() * 900000000); +export const emergency_phone_number = + "9" + Math.floor(100000000 + Math.random() * 900000000); diff --git a/package-lock.json b/package-lock.json index 07637b5e0a3..6f9fd1ee31a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "@googlemaps/react-wrapper": "^1.1.35", "@googlemaps/typescript-guards": "^2.0.3", "@headlessui/react": "^1.7.15", - "@loadable/component": "^5.15.3", "@pnotify/core": "^5.2.0", "@pnotify/mobile": "^5.2.0", "@react-spring/web": "^9.7.3", @@ -30,10 +29,8 @@ "echarts": "^5.4.2", "echarts-for-react": "^3.0.2", "events": "^3.3.0", - "html2canvas": "^1.4.1", "i18next": "^23.2.7", "i18next-browser-languagedetector": "^7.1.0", - "libphonenumber-js": "^1.10.37", "lodash": "^4.17.21", "postcss-loader": "^7.3.3", "qrcode.react": "^3.1.0", @@ -51,7 +48,6 @@ "react-player": "^2.12.0", "react-qr-reader": "^2.2.1", "react-redux": "^8.1.1", - "react-swipeable-views": "^0.14.0", "react-transition-group": "^4.4.5", "react-webcam": "^7.1.1", "read-excel-file": "^5.6.1", @@ -59,7 +55,6 @@ "redux-thunk": "^2.4.2", "rehype-raw": "^6.1.1", "rescript-webapi": "^0.8.0", - "screenfull": "^6.0.2", "use-keyboard-shortcut": "^1.1.6", "uuid": "^9.0.0" }, @@ -71,13 +66,12 @@ "@storybook/react": "^7.0.26", "@storybook/react-vite": "^7.0.26", "@storybook/testing-library": "^0.2.0", - "@tailwindcss/aspect-ratio": "^0.4.2", + "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/typography": "^0.5.9", "@types/cypress": "^1.1.3", "@types/echarts": "^4.9.18", "@types/google.maps": "^3.53.4", - "@types/loadable__component": "^5.13.4", "@types/lodash": "^4.14.195", "@types/lodash.get": "^4.4.7", "@types/node": "^20.4.0", @@ -89,13 +83,12 @@ "@types/react-dom": "^18.2.6", "@types/react-google-recaptcha": "^2.1.5", "@types/react-qr-reader": "^2.1.4", - "@types/react-swipeable-views": "^0.13.2", "@types/react-transition-group": "^4.4.6", "@typescript-eslint/eslint-plugin": "^5.61.0", "@typescript-eslint/parser": "^5.61.0", "@vitejs/plugin-react-swc": "^3.3.2", "autoprefixer": "^10.4.14", - "cypress": "^12.14.0", + "cypress": "^13.1.0", "cypress-localstorage-commands": "^2.2.3", "eslint": "^8.44.0", "eslint-config-prettier": "^8.8.0", @@ -124,7 +117,7 @@ "rescript": "^10.1.4", "snyk": "^1.1187.0", "storybook": "^7.0.26", - "tailwindcss": "^3.3.2", + "tailwindcss": "^3.3.3", "typescript": "^5.1.6", "vite": "^4.4.0", "vite-plugin-pwa": "^0.16.4" @@ -2264,9 +2257,9 @@ } }, "node_modules/@cypress/request": { - "version": "2.88.11", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", - "integrity": "sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.0.tgz", + "integrity": "sha512-GKFCqwZwMYmL3IBoNeR2MM1SnxRIGERsQOTWeQKoYBt2JLqcqiy7JXqO894FLrpjZYqGxW92MNwRH2BN56obdQ==", "dev": true, "dependencies": { "aws-sign2": "~0.7.0", @@ -2284,7 +2277,7 @@ "performance-now": "^2.1.0", "qs": "~6.10.3", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", + "tough-cookie": "^4.1.3", "tunnel-agent": "^0.6.0", "uuid": "^8.3.2" }, @@ -3208,26 +3201,6 @@ "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", "dev": true }, - "node_modules/@loadable/component": { - "version": "5.15.3", - "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.3.tgz", - "integrity": "sha512-VOgYgCABn6+/7aGIpg7m0Ruj34tGetaJzt4bQ345FwEovDQZ+dua+NWLmuJKv8rWZyxOUSfoJkmGnzyDXH2BAQ==", - "dependencies": { - "@babel/runtime": "^7.7.7", - "hoist-non-react-statics": "^3.3.1", - "react-is": "^16.12.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/@mdx-js/react": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", @@ -5193,13 +5166,13 @@ "node": ">=10" } }, - "node_modules/@tailwindcss/aspect-ratio": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz", - "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==", + "node_modules/@tailwindcss/container-queries": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/container-queries/-/container-queries-0.1.1.tgz", + "integrity": "sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==", "dev": true, "peerDependencies": { - "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + "tailwindcss": ">=3.2.0" } }, "node_modules/@tailwindcss/forms": { @@ -5503,15 +5476,6 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/loadable__component": { - "version": "5.13.4", - "resolved": "https://registry.npmjs.org/@types/loadable__component/-/loadable__component-5.13.4.tgz", - "integrity": "sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/lodash": { "version": "4.14.196", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.196.tgz", @@ -5672,15 +5636,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-swipeable-views": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@types/react-swipeable-views/-/react-swipeable-views-0.13.2.tgz", - "integrity": "sha512-FiszBm9M0JicAgzO/IwDqpfHQRUEjPZA88UexYsVD6qHJBf5LrbGjR5Mw4+yZbf8ZxJneNqOsZbe4WGjOYG7iQ==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react-transition-group": { "version": "4.4.6", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz", @@ -6753,14 +6708,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -7788,14 +7735,6 @@ "node": ">=8" } }, - "node_modules/css-line-break": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", - "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", - "dependencies": { - "utrie": "^1.0.2" - } - }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -7814,15 +7753,15 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "node_modules/cypress": { - "version": "12.17.2", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.2.tgz", - "integrity": "sha512-hxWAaWbqQBzzMuadSGSuQg5PDvIGOovm6xm0hIfpCVcORsCAj/gF2p0EvfnJ4f+jK2PCiDgP6D2eeE9/FK4Mjg==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.1.0.tgz", + "integrity": "sha512-LUKxCYlB973QBFls1Up4FAE9QIYobT+2I8NvvAwMfQS2YwsWbr6yx7y9hmsk97iqbHkKwZW3MRjoK1RToBFVdQ==", "dev": true, "hasInstallScript": true, "dependencies": { - "@cypress/request": "^2.88.11", + "@cypress/request": "^3.0.0", "@cypress/xvfb": "^1.2.4", - "@types/node": "^14.14.31", + "@types/node": "^16.18.39", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "arch": "^2.2.0", @@ -7855,6 +7794,7 @@ "minimist": "^1.2.8", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", + "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", "semver": "^7.5.3", @@ -7867,7 +7807,7 @@ "cypress": "bin/cypress" }, "engines": { - "node": "^14.0.0 || ^16.0.0 || >=18.0.0" + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" } }, "node_modules/cypress-localstorage-commands": { @@ -7883,9 +7823,9 @@ } }, "node_modules/cypress/node_modules/@types/node": { - "version": "14.18.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz", - "integrity": "sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==", + "version": "16.18.42", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.42.tgz", + "integrity": "sha512-IrFfX/1oxDFQNpQzgt/BoP/hbMuQT68DPsNwzJmw8y3K8lfnPp0XymVN9GLFz+LobFmJGZ/peRzq+9wXYfCCtw==", "dev": true }, "node_modules/cypress/node_modules/fs-extra": { @@ -10757,18 +10697,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/html2canvas": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", - "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", - "dependencies": { - "css-line-break": "^2.1.0", - "text-segmentation": "^1.0.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -11144,9 +11072,9 @@ } }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -12014,11 +11942,6 @@ "node": ">=4.0" } }, - "node_modules/keycode": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz", - "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==" - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -12096,11 +12019,6 @@ "node": ">= 0.8.0" } }, - "node_modules/libphonenumber-js": { - "version": "1.10.37", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.37.tgz", - "integrity": "sha512-Z10PCaOCiAxbUxLyR31DNeeNugSVP6iv/m7UrSKS5JHziEMApJtgku4e9Q69pzzSC9LnQiM09sqsGf2ticZnMw==" - }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -14535,6 +14453,8 @@ }, "node_modules/npm/node_modules/cross-spawn/node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "inBundle": true, "license": "ISC", @@ -15291,6 +15211,8 @@ }, "node_modules/npm/node_modules/minipass": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "inBundle": true, "license": "ISC", @@ -16433,6 +16355,8 @@ }, "node_modules/npm/node_modules/tar": { "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "dev": true, "inBundle": true, "license": "ISC", @@ -16533,6 +16457,8 @@ }, "node_modules/npm/node_modules/util-deprecate": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, "inBundle": true, "license": "MIT" @@ -16600,6 +16526,8 @@ }, "node_modules/npm/node_modules/wrap-ansi": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "inBundle": true, "license": "MIT", @@ -16618,6 +16546,8 @@ "node_modules/npm/node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "inBundle": true, "license": "MIT", @@ -16697,6 +16627,8 @@ }, "node_modules/npm/node_modules/wrappy": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "inBundle": true, "license": "ISC" @@ -16716,6 +16648,8 @@ }, "node_modules/npm/node_modules/yallist": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "inBundle": true, "license": "ISC" @@ -17856,6 +17790,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -18119,19 +18059,6 @@ "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", "dev": true }, - "node_modules/react-event-listener": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.6.6.tgz", - "integrity": "sha512-+hCNqfy7o9wvO6UgjqFmBzARJS7qrNoda0VqzvOuioEpoEXKutiKuv92dSz6kP7rYLmyHPyYNLesi5t/aH1gfw==", - "dependencies": { - "@babel/runtime": "^7.2.0", - "prop-types": "^15.6.0", - "warning": "^4.0.1" - }, - "peerDependencies": { - "react": "^16.3.0" - } - }, "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", @@ -18300,91 +18227,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-swipeable-views": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-swipeable-views/-/react-swipeable-views-0.14.0.tgz", - "integrity": "sha512-wrTT6bi2nC3JbmyNAsPXffUXLn0DVT9SbbcFr36gKpbaCgEp7rX/OFxsu5hPc/NBsUhHyoSRGvwqJNNrWTwCww==", - "dependencies": { - "@babel/runtime": "7.0.0", - "prop-types": "^15.5.4", - "react-swipeable-views-core": "^0.14.0", - "react-swipeable-views-utils": "^0.14.0", - "warning": "^4.0.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "react": "^15.3.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/react-swipeable-views-core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-swipeable-views-core/-/react-swipeable-views-core-0.14.0.tgz", - "integrity": "sha512-0W/e9uPweNEOSPjmYtuKSC/SvKKg1sfo+WtPdnxeLF3t2L82h7jjszuOHz9C23fzkvLfdgkaOmcbAxE9w2GEjA==", - "dependencies": { - "@babel/runtime": "7.0.0", - "warning": "^4.0.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/react-swipeable-views-core/node_modules/@babel/runtime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", - "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", - "dependencies": { - "regenerator-runtime": "^0.12.0" - } - }, - "node_modules/react-swipeable-views-core/node_modules/regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" - }, - "node_modules/react-swipeable-views-utils": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-swipeable-views-utils/-/react-swipeable-views-utils-0.14.0.tgz", - "integrity": "sha512-W+fXBOsDqgFK1/g7MzRMVcDurp3LqO3ksC8UgInh2P/tKgb5DusuuB1geKHFc6o1wKl+4oyER4Zh3Lxmr8xbXA==", - "dependencies": { - "@babel/runtime": "7.0.0", - "keycode": "^2.1.7", - "prop-types": "^15.6.0", - "react-event-listener": "^0.6.0", - "react-swipeable-views-core": "^0.14.0", - "shallow-equal": "^1.2.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/react-swipeable-views-utils/node_modules/@babel/runtime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", - "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", - "dependencies": { - "regenerator-runtime": "^0.12.0" - } - }, - "node_modules/react-swipeable-views-utils/node_modules/regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" - }, - "node_modules/react-swipeable-views/node_modules/@babel/runtime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", - "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", - "dependencies": { - "regenerator-runtime": "^0.12.0" - } - }, - "node_modules/react-swipeable-views/node_modules/regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" - }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -18905,6 +18747,12 @@ "node": ">=0.10.5" } }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "node_modules/rescript": { "version": "10.1.4", "resolved": "https://registry.npmjs.org/rescript/-/rescript-10.1.4.tgz", @@ -18924,12 +18772,12 @@ "integrity": "sha512-PdjHqho8+kI7AIC3DlLgD99H8zzHphzpIhyv2skVtWaSJGK819+ZqWMC3mHEtSjlcFoYaLXliNt8sb6Taa2Mpg==" }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -19199,17 +19047,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/screenfull": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-6.0.2.tgz", - "integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==", - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/sdp": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz", @@ -19370,11 +19207,6 @@ "node": ">=8" } }, - "node_modules/shallow-equal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", - "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -20242,14 +20074,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/text-segmentation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", - "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", - "dependencies": { - "utrie": "^1.0.2" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -20397,16 +20221,27 @@ } }, "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { - "node": ">=0.8" + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" } }, "node_modules/tr46": { @@ -20960,6 +20795,16 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/use-keyboard-shortcut": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/use-keyboard-shortcut/-/use-keyboard-shortcut-1.1.6.tgz", @@ -21015,14 +20860,6 @@ "node": ">= 0.4.0" } }, - "node_modules/utrie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", - "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", - "dependencies": { - "base64-arraybuffer": "^1.0.2" - } - }, "node_modules/uuid": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", @@ -21262,14 +21099,6 @@ "makeerror": "1.0.12" } }, - "node_modules/warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/package.json b/package.json index 0684f9a316d..f7c0556a6b2 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "@googlemaps/react-wrapper": "^1.1.35", "@googlemaps/typescript-guards": "^2.0.3", "@headlessui/react": "^1.7.15", - "@loadable/component": "^5.15.3", "@pnotify/core": "^5.2.0", "@pnotify/mobile": "^5.2.0", "@react-spring/web": "^9.7.3", @@ -70,10 +69,8 @@ "echarts": "^5.4.2", "echarts-for-react": "^3.0.2", "events": "^3.3.0", - "html2canvas": "^1.4.1", "i18next": "^23.2.7", "i18next-browser-languagedetector": "^7.1.0", - "libphonenumber-js": "^1.10.37", "lodash": "^4.17.21", "postcss-loader": "^7.3.3", "qrcode.react": "^3.1.0", @@ -91,7 +88,6 @@ "react-player": "^2.12.0", "react-qr-reader": "^2.2.1", "react-redux": "^8.1.1", - "react-swipeable-views": "^0.14.0", "react-transition-group": "^4.4.5", "react-webcam": "^7.1.1", "read-excel-file": "^5.6.1", @@ -99,7 +95,6 @@ "redux-thunk": "^2.4.2", "rehype-raw": "^6.1.1", "rescript-webapi": "^0.8.0", - "screenfull": "^6.0.2", "use-keyboard-shortcut": "^1.1.6", "uuid": "^9.0.0" }, @@ -111,13 +106,12 @@ "@storybook/react": "^7.0.26", "@storybook/react-vite": "^7.0.26", "@storybook/testing-library": "^0.2.0", - "@tailwindcss/aspect-ratio": "^0.4.2", + "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/typography": "^0.5.9", "@types/cypress": "^1.1.3", "@types/echarts": "^4.9.18", "@types/google.maps": "^3.53.4", - "@types/loadable__component": "^5.13.4", "@types/lodash": "^4.14.195", "@types/lodash.get": "^4.4.7", "@types/node": "^20.4.0", @@ -129,13 +123,12 @@ "@types/react-dom": "^18.2.6", "@types/react-google-recaptcha": "^2.1.5", "@types/react-qr-reader": "^2.1.4", - "@types/react-swipeable-views": "^0.13.2", "@types/react-transition-group": "^4.4.6", "@typescript-eslint/eslint-plugin": "^5.61.0", "@typescript-eslint/parser": "^5.61.0", "@vitejs/plugin-react-swc": "^3.3.2", "autoprefixer": "^10.4.14", - "cypress": "^12.14.0", + "cypress": "^13.1.0", "cypress-localstorage-commands": "^2.2.3", "eslint": "^8.44.0", "eslint-config-prettier": "^8.8.0", @@ -164,7 +157,7 @@ "rescript": "^10.1.4", "snyk": "^1.1187.0", "storybook": "^7.0.26", - "tailwindcss": "^3.3.2", + "tailwindcss": "^3.3.3", "typescript": "^5.1.6", "vite": "^4.4.0", "vite-plugin-pwa": "^0.16.4" diff --git a/src/App.tsx b/src/App.tsx index 0b0f3740e05..f89dfd11e74 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,100 +1,30 @@ -import * as Sentry from "@sentry/browser"; - -import React, { useEffect, useState } from "react"; -import { getConfig, getCurrentUser } from "./Redux/actions"; -import { statusType, useAbortableEffect } from "./Common/utils"; -import { useDispatch, useSelector } from "react-redux"; - -import AppRouter from "./Router/AppRouter"; -import { HistoryAPIProvider } from "./CAREUI/misc/HistoryAPIProvider"; -import { IConfig } from "./Common/hooks/useConfig"; -import { LocalStorageKeys } from "./Common/constants"; -import Plausible from "./Components/Common/Plausible"; -import SessionRouter from "./Router/SessionRouter"; -import loadable from "@loadable/component"; - -const Loading = loadable(() => import("./Components/Common/Loading")); - -const App: React.FC = () => { - const dispatch: any = useDispatch(); - const state: any = useSelector((state) => state); - const { currentUser, config } = state; - const [user, setUser] = useState(null); - - useAbortableEffect(async () => { - const res = await dispatch(getConfig()); - if (res.data && res.status < 400) { - const config = res.data as IConfig; - - if (config?.sentry_dsn && import.meta.env.PROD) { - Sentry.init({ - environment: config.sentry_environment, - dsn: config.sentry_dsn, - }); - } - - localStorage.setItem("config", JSON.stringify(config)); - } - }, [dispatch]); - - const updateRefreshToken = () => { - const refresh = localStorage.getItem(LocalStorageKeys.refreshToken); - if (refresh) { - fetch("/api/v1/auth/token/refresh/", { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify({ refresh }), - }) - .then((res) => res.json()) - .then((resp) => { - localStorage.setItem(LocalStorageKeys.accessToken, resp.access); - localStorage.setItem(LocalStorageKeys.refreshToken, resp.refresh); - }); - } - }; - useEffect(() => { - updateRefreshToken(); - setInterval(updateRefreshToken, 5 * 60 * 1000); - }, [user]); - - useAbortableEffect( - async (status: statusType) => { - const res = await dispatch(getCurrentUser()); - if (!status.aborted && res && res.statusCode === 200) { - setUser(res.data); - } - }, - [dispatch] - ); - - useEffect(() => { - const darkThemeMq = window.matchMedia("(prefers-color-scheme: dark)"); - const favicon: any = document.querySelector("link[rel~='icon']"); - if (darkThemeMq.matches) { - favicon.href = "/favicon-light.ico"; - } else { - favicon.href = "/favicon.ico"; - } - }, []); - - if ( - !currentUser || - currentUser.isFetching || - !config || - config.isFetching || - !config.data - ) { - return ; - } - +import { Suspense } from "react"; +import Routers from "./Routers"; +import { + AppConfigProvider, + AuthUserProvider, + HistoryAPIProvider, +} from "./Providers"; +import ThemedFavicon from "./CAREUI/misc/ThemedFavicon"; +import Intergrations from "./Integrations"; +import Loading from "./Components/Common/Loading"; + +const App = () => { return ( - - {currentUser?.data ? : } - - + }> + + + + }> + + + + {/* Integrations */} + + + + + ); }; diff --git a/src/CAREUI/display/Card.tsx b/src/CAREUI/display/Card.tsx index f5630cd1753..82d535a5a0a 100644 --- a/src/CAREUI/display/Card.tsx +++ b/src/CAREUI/display/Card.tsx @@ -1,7 +1,9 @@ +import { HTMLAttributes, ReactNode } from "react"; + export default function Card( props: { - children?: React.ReactNode; - } & React.HTMLAttributes + children?: ReactNode; + } & HTMLAttributes ) { const { children, ...rest } = props; return ( diff --git a/src/CAREUI/display/Chip.tsx b/src/CAREUI/display/Chip.tsx index 1b2c4c91041..abc21711551 100644 --- a/src/CAREUI/display/Chip.tsx +++ b/src/CAREUI/display/Chip.tsx @@ -1,84 +1,53 @@ -import { MouseEventHandler, useEffect, useState } from "react"; +import CareIcon, { IconName } from "../icons/CareIcon"; +import { ButtonVariant } from "../../Components/Common/components/ButtonV2"; +import { classNames } from "../../Utils/utils"; -type iconType = "uil" | "fa"; interface Props { size?: "small" | "medium" | "large"; hideBorder?: boolean; - color?: string; - startIcon?: string | JSX.Element; - startIconType?: iconType; - endIcon?: string | JSX.Element; - endIconType?: iconType; + variant?: ButtonVariant | "custom"; + startIcon?: IconName; + endIcon?: IconName; text: string; - onStartIconClick?: MouseEventHandler; - onEndIconClick?: MouseEventHandler; + tooltip?: string; + className?: string; } -export default function Chip(props: Props) { - const [chipStyle, setChipStyle] = useState(""); - - useEffect(() => { - switch (props.size) { - case "small": - setChipStyle("px-2 py-1 rounded text-xs"); - break; +export default function Chip({ + size = "medium", + hideBorder = false, + variant = "primary", + ...props +}: Props) { + return ( + - {props.startIcon && ( - - )} - {props.text} - {props.endIcon && ( - + props.className )} + title={props.tooltip} + > + {props.startIcon && } + {props.text} + {props.endIcon && } ); } diff --git a/src/CAREUI/display/Count.tsx b/src/CAREUI/display/Count.tsx index ca9f60b1bf9..3b889b10e9b 100644 --- a/src/CAREUI/display/Count.tsx +++ b/src/CAREUI/display/Count.tsx @@ -1,39 +1,32 @@ -import CareIcon from "../icons/CareIcon"; +import { classNames } from "../../Utils/utils"; +import CareIcon, { IconName } from "../icons/CareIcon"; -export default function CountBlock(props: { +interface Props { count: number; text: string; loading: boolean; - icon: string; - color?: string; - containerClass?: string; -}) { - const { - count, - text, - loading, - icon, - color = "primary", - containerClass, - } = props; + icon: IconName; + className?: string; +} +export default function CountBlock(props: Props) { return ( -
-
-
- +
+
+
+
- {text} + {props.text}
- {loading ? ( + {props.loading ? (
) : (
- {count} + {props.count}
)}
diff --git a/src/CAREUI/display/RecordMeta.tsx b/src/CAREUI/display/RecordMeta.tsx index a6a04cf5305..83928f1f23a 100644 --- a/src/CAREUI/display/RecordMeta.tsx +++ b/src/CAREUI/display/RecordMeta.tsx @@ -1,9 +1,10 @@ import CareIcon from "../icons/CareIcon"; import { formatDateTime, isUserOnline, relativeTime } from "../../Utils/utils"; +import { ReactNode } from "react"; interface Props { time?: string; - prefix?: React.ReactNode; + prefix?: ReactNode; className?: string; user?: { first_name: string; @@ -22,7 +23,7 @@ const RecordMeta = ({ time, user, prefix, className }: Props) => { let child = (
{relativeTime(time)} - + {formatDateTime(time)} {user && ( <> diff --git a/src/CAREUI/display/SubHeading.tsx b/src/CAREUI/display/SubHeading.tsx new file mode 100644 index 00000000000..75d8710fdef --- /dev/null +++ b/src/CAREUI/display/SubHeading.tsx @@ -0,0 +1,33 @@ +import { ReactNode } from "react"; +import CareIcon from "../icons/CareIcon"; +import RecordMeta from "./RecordMeta"; + +interface Props { + title: ReactNode; + lastModified?: string; + className?: string; + options?: ReactNode; +} + +export default function SubHeading(props: Props) { + return ( +
+
+ + {props.title} + + {props.lastModified && ( +
+ + +
+ )} +
+ {props.options && ( +
+ {props.options} +
+ )} +
+ ); +} diff --git a/src/CAREUI/icons/CareIcon.tsx b/src/CAREUI/icons/CareIcon.tsx index b3a6d33c895..0c70fbfe298 100644 --- a/src/CAREUI/icons/CareIcon.tsx +++ b/src/CAREUI/icons/CareIcon.tsx @@ -1,7 +1,12 @@ import { transformIcons } from "./icon"; import { useEffect } from "react"; +import iconData from "./UniconPaths.json"; + +export type IconName = keyof typeof iconData; + export interface CareIconProps { + icon?: IconName; className?: string | undefined; onClick?: React.MouseEventHandler | undefined; } @@ -14,11 +19,15 @@ export interface CareIconProps { * * @see [icon library](https://iconscout.com/unicons/) */ -export default function CareIcon({ className, onClick }: CareIconProps) { - useEffect(() => transformIcons(), [className]); +export default function CareIcon({ icon, className, onClick }: CareIconProps) { + const effectiveClassName = icon + ? `care-${icon} ${className ?? ""}` + : className; + + useEffect(() => transformIcons(), [effectiveClassName]); return ( - - + + ); } diff --git a/src/CAREUI/interactive/SlideOver.tsx b/src/CAREUI/interactive/SlideOver.tsx index 3eae13869cb..34e1c615f94 100644 --- a/src/CAREUI/interactive/SlideOver.tsx +++ b/src/CAREUI/interactive/SlideOver.tsx @@ -109,6 +109,7 @@ export default function SlideOver({ >