diff --git a/.github/workflows/cypress.yaml b/.github/workflows/cypress.yaml index f66f9a37bd8..130f360d2ef 100644 --- a/.github/workflows/cypress.yaml +++ b/.github/workflows/cypress.yaml @@ -24,14 +24,22 @@ jobs: repository: coronasafe/care path: care - - name: Run docker compose up on care 🐳 + - name: Start care docker containers 🐳 run: | - cd care + cd care make docker_config_file=docker-compose.pre-built.yaml up - sleep 60s + 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: | + cd care docker compose exec backend bash -c "python manage.py load_dummy_data" cd .. - # Voluntarily kept 60 seconds delay to wait for migrations to complete. - name: Check care is up ♻ run: curl -o /dev/null -s -w "%{http_code}\n" http://localhost:9000 @@ -93,10 +101,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/cypress/e2e/assets_spec/asset_homepage.cy.ts b/cypress/e2e/assets_spec/asset_homepage.cy.ts index 6e9ceb9676b..fa24adf5b21 100644 --- a/cypress/e2e/assets_spec/asset_homepage.cy.ts +++ b/cypress/e2e/assets_spec/asset_homepage.cy.ts @@ -62,8 +62,18 @@ describe("Asset Tab", () => { "Dummy Facility 1", "INTERNAL", "ACTIVE", - "ONVIF Camera" + "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 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 fea6a975983..b1ccb2f71c9 100644 --- a/cypress/pageobject/Asset/AssetSearch.ts +++ b/cypress/pageobject/Asset/AssetSearch.ts @@ -1,6 +1,6 @@ export class AssetSearchPage { typeSearchKeyword(keyword: string) { - cy.get("#search").clear(); + cy.get("#search").click().clear(); cy.get("#search").click().type(keyword); } @@ -9,7 +9,9 @@ export class AssetSearchPage { } 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) { 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({ >
diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx index 012ca1d68b2..cc34140e7a9 100644 --- a/src/Components/Facility/models.tsx +++ b/src/Components/Facility/models.tsx @@ -142,6 +142,7 @@ export interface ConsultationModel { cause_of_death?: string; death_datetime?: string; death_confirmed_doctor?: string; + is_readmission?: boolean; } export interface PatientStatsModel { id?: number; diff --git a/src/Components/Patient/ManagePatients.tsx b/src/Components/Patient/ManagePatients.tsx index b29c112c5a1..54d22b5f54c 100644 --- a/src/Components/Patient/ManagePatients.tsx +++ b/src/Components/Patient/ManagePatients.tsx @@ -603,6 +603,15 @@ export const PatientManager = () => { text="Review Missed" /> )} + {patient.last_consultation?.is_readmission && ( + + )} {patient.disease_status === "POSITIVE" && ( { ); }; + const isPatientEligibleForNewConsultation = (patientData: PatientModel) => { + return !patientData.last_consultation || + patientData.last_consultation?.discharge_date + ? true + : false; + }; + return ( {
- patientData.is_active && - (!patientData?.last_consultation || - patientData?.last_consultation?.discharge_date) && + isPatientEligibleForNewConsultation(patientData) && navigate( `/facility/${patientData?.facility}/patient/${id}/consultation` ) } > -
-
+
+
diff --git a/src/Components/Patient/PatientInfoCard.tsx b/src/Components/Patient/PatientInfoCard.tsx index 9df4c93051a..dbb4aac34ce 100644 --- a/src/Components/Patient/PatientInfoCard.tsx +++ b/src/Components/Patient/PatientInfoCard.tsx @@ -143,7 +143,7 @@ export default function PatientInfoCard(props: {
)}
-
+
- - Domiciliary Care{" "} - + + + Domiciliary Care + + + )} + {consultation?.is_readmission && ( + <> + + + + Readmitted )} diff --git a/src/Components/VitalsMonitor/HL7DeviceClient.ts b/src/Components/VitalsMonitor/HL7DeviceClient.ts index 72f6406193a..7e13622b31f 100644 --- a/src/Components/VitalsMonitor/HL7DeviceClient.ts +++ b/src/Components/VitalsMonitor/HL7DeviceClient.ts @@ -1,11 +1,31 @@ import { EventEmitter } from "events"; import { VitalsDataBase, VitalsValueBase, VitalsWaveformBase } from "./types"; -const WAVEFORM_KEY_MAP: Record = { - II: "ecg-waveform", - Pleth: "pleth-waveform", - Respiration: "spo2-waveform", -}; +const ECG_WAVENAME_KEYS = [ + "I", + "II", + "III", + "aVR", + "aVL", + "aVF", + "V1", + "V2", + "V3", + "V4", + "V5", + "V6", +] as const; + +const WAVEFORM_KEY_MAP: Record = + { + Pleth: "pleth-waveform", + Respiration: "spo2-waveform", + + // Maps each ECG wave name to the event "ecg-waveform" + ...(Object.fromEntries( + ECG_WAVENAME_KEYS.map((key) => [key, "ecg-waveform"]) + ) as Record), + }; /** * Provides the API for connecting to the Vitals Monitor WebSocket and emitting @@ -74,8 +94,10 @@ export interface HL7VitalsValueData extends VitalsDataBase, VitalsValueBase { | "body-temperature2"; } +type EcgWaveName = (typeof ECG_WAVENAME_KEYS)[number]; + export interface HL7VitalsWaveformData extends VitalsWaveformBase { - "wave-name": "II" | "Pleth" | "Respiration"; + "wave-name": EcgWaveName | "Pleth" | "Respiration"; } export interface HL7VitalsBloodPressureData extends VitalsDataBase { diff --git a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx index a340c21e28b..c0b089df8b0 100644 --- a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx +++ b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx @@ -88,7 +88,7 @@ export default function HL7PatientVitalsMonitor(props: IVitalsComponentProps) { {/* Pulse Rate */} ❤️