Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Gonorrhea support to test card #8321

Merged
merged 3 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/src/app/commonComponents/TestResultsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const diseaseResultTitlePxpMap: Record<MULTIPLEX_DISEASES, string> = {
[MULTIPLEX_DISEASES.RSV]: "constants.diseaseResultTitle.RSV",
[MULTIPLEX_DISEASES.SYPHILIS]: "constants.diseaseResultTitle.SYPHILIS",
[MULTIPLEX_DISEASES.HEPATITIS_C]: "constants.diseaseResultTitle.HEPATITIS_C",
[MULTIPLEX_DISEASES.GONORRHEA]: "constants.diseaseResultTitle.GONORRHEA",
};

const diseaseResultReportingAppMap: Record<MULTIPLEX_DISEASES, string> = {
Expand All @@ -43,6 +44,7 @@ const diseaseResultReportingAppMap: Record<MULTIPLEX_DISEASES, string> = {
[MULTIPLEX_DISEASES.RSV]: "constants.disease.RSV",
[MULTIPLEX_DISEASES.SYPHILIS]: "constants.disease.SYPHILIS",
[MULTIPLEX_DISEASES.HEPATITIS_C]: "constants.disease.HEPATITIS_C",
[MULTIPLEX_DISEASES.GONORRHEA]: "constants.disease.GONORRHEA",
};

const setResult = (result: string, t: translateFn) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const mockSupportedDiseaseTestPerformedGonorrhea = [
{
supportedDisease: {
internalId: "18948648-1780-4303-b5fe-05c1d3f34ab7",
loinc: "LP14316-1",
name: "Gonorrhea",
},
testPerformedLoincCode: "80123-6",
equipmentUid: "GonorrheaEquipmentUid123",
testkitNameId: "GonorrheaTestkitNameId123",
testOrderedLoincCode: "80123-6",
},
];

export default mockSupportedDiseaseTestPerformedGonorrhea;
136 changes: 136 additions & 0 deletions frontend/src/app/testQueue/TestCard/TestCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ import {
mutationResponse,
updateHepCAoeMocks,
baseStiAoeUpdateMock,
device10Id,
device10Name,
} from "../testCardTestConstants";
import { QueriedFacility } from "../TestCardForm/types";
import mockSupportedDiseaseMultiplex, {
Expand All @@ -78,6 +80,7 @@ import mockSupportedDiseaseTestPerformedHIV from "../../supportAdmin/DeviceType/
import mockSupportedDiseaseTestPerformedSyphilis from "../../supportAdmin/DeviceType/mocks/mockSupportedDiseaseTestPerformedSyphilis";
import { UpdateTestOrderTimerStartedAtDocument } from "../../../generated/graphql";
import mockSupportedDiseaseTestPerformedHepatitisC from "../../supportAdmin/DeviceType/mocks/mockSupportedDiseaseTestPerformedHepatitisC";
import mockSupportedDiseaseTestPerformedGonorrhea from "../../supportAdmin/DeviceType/mocks/mockSupportedDiseaseTestPerformedGonorrhea";

import { TestCard, TestCardProps } from "./TestCard";

Expand Down Expand Up @@ -277,6 +280,21 @@ const facilityInfo: QueriedFacility = {
},
],
},
{
internalId: device10Id,
name: device10Name,
testLength: 15,
supportedDiseaseTestPerformed: [
...mockSupportedDiseaseTestPerformedGonorrhea,
],
swabTypes: [
{
name: specimen3Name,
internalId: specimen3Id,
typeCode: "122555007",
},
],
},
],
};
export const devicesMap = new Map();
Expand Down Expand Up @@ -1486,6 +1504,124 @@ describe("TestCard", () => {
expect(screen.queryByText(AOE_ERROR_TEXT)).not.toBeInTheDocument();
});

it("shows radio buttons for Gonorrhea when a Gonorrhea device is chosen", async function () {
mockDiseaseEnabledFlag("gonorrhea");

const mocks = [
generateEditQueueMock(
MULTIPLEX_DISEASES.GONORRHEA,
TEST_RESULTS.POSITIVE
),
blankUpdateAoeEventMock,
];

const { user } = await renderQueueItem({ mocks });
expect(screen.queryByText("Gonorrhea result")).not.toBeInTheDocument();

const deviceDropdown = await getDeviceTypeDropdown();

await user.selectOptions(deviceDropdown, device10Name);
expect(screen.getByText("Gonorrhea result")).toBeInTheDocument();
});

it("shows required Gonorrhea AOE questions when a positive Gonorrhea result is present", async function () {
mockDiseaseEnabledFlag("gonorrhea");

const mocks = [
generateEditQueueMock(
MULTIPLEX_DISEASES.GONORRHEA,
TEST_RESULTS.POSITIVE
),
blankUpdateAoeEventMock,
{
...baseStiAoeUpdateMock({
...NO_SYMPTOMS_FALSE_OVERRIDE,
}),
...mutationResponse,
},
];

const { user } = await renderQueueItem({ mocks });
const deviceDropdown = await getDeviceTypeDropdown();
expect(deviceDropdown.options.length).toEqual(
DEFAULT_DEVICE_OPTIONS_LENGTH + 1
);

await user.selectOptions(deviceDropdown, device10Name);
expect(screen.getByText("Gonorrhea result")).toBeInTheDocument();

await user.click(
screen.getByLabelText("Positive", {
exact: false,
})
);

expect(screen.getByText("Is the patient pregnant?")).toBeInTheDocument();
expect(
screen.getByText(
"Is the patient currently experiencing or showing signs of symptoms?"
)
).toBeInTheDocument();
expect(
screen.getByText("What is the gender of their sexual partners?")
).toBeInTheDocument();

const symptomFieldSet = screen.getByTestId(
`has-any-symptoms-${sharedTestOrderInfo.internalId}`
);
await user.click(within(symptomFieldSet).getByLabelText("Yes"));

expect(
screen.getByText("Select any symptoms the patient is experiencing")
).toBeInTheDocument();
});

it("hides AOE questions when there is no positive Gonorrhea result", async function () {
mockDiseaseEnabledFlag("gonorrhea");

const mocks = [
generateEditQueueMock(
MULTIPLEX_DISEASES.GONORRHEA,
TEST_RESULTS.POSITIVE
),
blankUpdateAoeEventMock,
];

const { user } = await renderQueueItem({ mocks });
const deviceDropdown = await getDeviceTypeDropdown();

await user.selectOptions(deviceDropdown, device10Name);
expect(screen.getByText("Gonorrhea result")).toBeInTheDocument();
expect(
screen.queryByText("Is the patient pregnant?")
).not.toBeInTheDocument();
expect(
screen.queryByText(
"Is the patient currently experiencing or showing signs of symptoms?"
)
).not.toBeInTheDocument();
expect(
screen.queryByText("What is the gender of their sexual partners?")
).not.toBeInTheDocument();

await user.click(
screen.getByLabelText("Inconclusive", {
exact: false,
})
);
expect(
screen.queryByText("Is the patient pregnant?")
).not.toBeInTheDocument();
expect(
screen.queryByText(
"Is the patient currently experiencing or showing signs of symptoms?"
)
).not.toBeInTheDocument();
expect(
screen.queryByText("What is the gender of their sexual partners?")
).not.toBeInTheDocument();
});

it("checks that submission only works if AOE questions are valid", async function () {
mockDiseaseEnabledFlag("syphilis");

Expand Down
20 changes: 20 additions & 0 deletions frontend/src/app/testQueue/TestCardForm/TestCardForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
fluDeviceId,
fluDeviceName,
generateSubmitQueueMock,
gonorrheaDeviceId,
gonorrheaDeviceName,
hepatitisCDeviceId,
hepatitisCDeviceName,
hivDeviceId,
Expand Down Expand Up @@ -205,6 +207,24 @@ describe("TestCardForm", () => {

expect(await renderTestCardForm({ props })).toMatchSnapshot();
});

it("matches snapshot for gonorrhea device", async () => {
const props = {
...testProps,
testOrder: {
...testProps.testOrder,
results: [{ testResult: "POSITIVE", disease: { name: "GONORRHEA" } }],
deviceType: {
internalId: gonorrheaDeviceId,
name: gonorrheaDeviceName,
model: gonorrheaDeviceName,
testLength: 15,
},
},
};

expect(await renderTestCardForm({ props })).toMatchSnapshot();
});
});

describe("error handling", () => {
Expand Down
25 changes: 23 additions & 2 deletions frontend/src/app/testQueue/TestCardForm/TestCardForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
TestCorrectionReasons,
} from "../../testResults/viewResults/actionMenuModals/TestResultCorrectionModal";
import {
gonorrheaSymptomDefinitions,
hepatitisCSymptomDefinitions,
PregnancyCode,
SyphilisHistoryCode,
} from "../../../patientApp/timeOfTest/constants";
Expand Down Expand Up @@ -58,7 +60,7 @@ import { HIVAoEForm } from "./diseaseSpecificComponents/HIVAoEForm";
import { stringifySymptomJsonForAoeUpdate } from "./diseaseSpecificComponents/aoeUtils";
import { SyphilisAoEForm } from "./diseaseSpecificComponents/SyphilisAoEForm";
import { WhereResultsAreSentModal } from "./WhereResultsAreSentModal";
import { HepatitisCAoeForm } from "./diseaseSpecificComponents/HepatitisCAoeForm";
import { STIGenericAOEForm } from "./diseaseSpecificComponents/STIGenericAOEForm";

const DEBOUNCE_TIME = 300;

Expand Down Expand Up @@ -606,7 +608,7 @@ const TestCardForm = ({
)}
{whichAoeFormOption === AOEFormOption.HEPATITIS_C && (
<div className="grid-row grid-gap">
<HepatitisCAoeForm
<STIGenericAOEForm
testOrder={testOrder}
responses={state.aoeResponses}
hasAttemptedSubmit={hasAttemptedSubmit}
Expand All @@ -616,6 +618,25 @@ const TestCardForm = ({
payload: responses,
});
}}
diseaseSymptomDefinitions={hepatitisCSymptomDefinitions}
diseaseNameForFormIds={"hepatitis-c"}
/>
</div>
)}
{whichAoeFormOption === AOEFormOption.GONORRHEA && (
<div className="grid-row grid-gap">
<STIGenericAOEForm
testOrder={testOrder}
responses={state.aoeResponses}
hasAttemptedSubmit={hasAttemptedSubmit}
onResponseChange={(responses) => {
dispatch({
type: TestFormActionCase.UPDATE_AOE_RESPONSES,
payload: responses,
});
}}
diseaseSymptomDefinitions={gonorrheaSymptomDefinitions}
diseaseNameForFormIds={"gonorrhea"}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,28 @@ describe("TestCardForm.utils", () => {
)
).toEqual(AoeValidationErrorMessages.COMPLETE);
});

it("should return false if Gonorrhea questions are unanswered", () => {
const positive: TestFormState = {
...incompleteState,
};
expect(
generateAoeValidationState(positive, AOEFormOption.GONORRHEA)
).toEqual(AoeValidationErrorMessages.INCOMPLETE);
});

it("should return true when Gonorrhea positive is selected and questions are answered", () => {
const positiveGonorrheaStateCompleteAOE: TestFormState = {
...completeStateWithSymptoms,
};
positiveGonorrheaStateCompleteAOE.aoeResponses.symptoms =
'{"49650001":true,"289560001":false,"399131003":false,"249661007":false,"90446007":false,"71393004":false,"131148009":false,"225595004":false}';
expect(
generateAoeValidationState(
positiveGonorrheaStateCompleteAOE,
AOEFormOption.GONORRHEA
)
).toEqual(AoeValidationErrorMessages.COMPLETE);
});
});
});
23 changes: 22 additions & 1 deletion frontend/src/app/testQueue/TestCardForm/TestCardForm.utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export enum AOEFormOption {
HIV = "HIV",
SYPHILIS = "SYPHILIS",
HEPATITIS_C = "HEPATITIS_C",
GONORRHEA = "GONORRHEA",
NONE = "NONE",
}

Expand Down Expand Up @@ -65,6 +66,7 @@ export function useFilteredDeviceTypes(facility: QueriedFacility) {
const hivEnabled = useFeature("hivEnabled");
const syphilisEnabled = useFeature("syphilisEnabled");
const hepatitisCEnabled = useFeature("hepatitisCEnabled");
const gonorrheaEnabled = useFeature("gonorrheaEnabled");

let deviceTypes = [...facility!.deviceTypes];

Expand All @@ -74,7 +76,6 @@ export function useFilteredDeviceTypes(facility: QueriedFacility) {
MULTIPLEX_DISEASES.HIV
);
}

if (!syphilisEnabled) {
deviceTypes = filterDiseaseFromAllDevices(
deviceTypes,
Expand All @@ -87,6 +88,12 @@ export function useFilteredDeviceTypes(facility: QueriedFacility) {
MULTIPLEX_DISEASES.HEPATITIS_C
);
}
if (!gonorrheaEnabled) {
deviceTypes = filterDiseaseFromAllDevices(
deviceTypes,
MULTIPLEX_DISEASES.GONORRHEA
);
}
return deviceTypes;
}

Expand Down Expand Up @@ -204,6 +211,15 @@ export const useAOEFormOption = (
if (!hasAnySupportedDiseaseTests(testFormState.deviceId, devicesMap)) {
return AOEFormOption.COVID;
}
if (
devicesMap
.get(testFormState.deviceId)
?.supportedDiseaseTestPerformed.filter(
(x) => x.supportedDisease.name === MULTIPLEX_DISEASES.GONORRHEA
).length === 1
) {
return resultHasPositive ? AOEFormOption.GONORRHEA : AOEFormOption.NONE;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tangentially related to this change: do you think we need to make it known somewhere (e.g. warn Jayna, add a validation to add device page?) that we can't support devices that test for multiple STIs currently without changing this part of the code? it's technically possible to create that device in SR so I can see it happening where Jayna creates a ticket to add a device, we refine it and don't think about it, and then end up creating it and the AOE don't work properly. but maybe I'm being paranoid about my memory

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm good point, we should make sure everyone on the team knows we can't support multi-STI devices yet. I don't think we necessarily need to add separate validation since the multiple device test card redesign is one of the big upcoming features that will likely require us to deal with those AOE questions in a more comprehensive manner

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree! seems like this won't be the case for long

}
if (
devicesMap
.get(testFormState.deviceId)
Expand Down Expand Up @@ -288,6 +304,11 @@ export const REQUIRED_AOE_QUESTIONS_BY_DISEASE: {
AoeQuestionName.GENDER_OF_SEXUAL_PARTNERS,
AoeQuestionName.NO_SYMPTOMS,
],
[AOEFormOption.GONORRHEA]: [
AoeQuestionName.PREGNANCY,
AoeQuestionName.GENDER_OF_SEXUAL_PARTNERS,
AoeQuestionName.NO_SYMPTOMS,
],
[AOEFormOption.NONE]: [],
};

Expand Down
Loading
Loading