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

MAT-7528 Added Saved Codes UI builder for Qi Core and handled special… #430

Merged
merged 8 commits into from
Jan 13, 2025
3 changes: 2 additions & 1 deletion src/CqlBuilderPanel/codesSection/CodesSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default function CodesSection({
const codeSystemVersion = getCodeSystemVersion(matchedCodeSystem);
return {
code: parsedCode,
codeSystem: codeSystem.name,
codeSystem: codeSystem?.name,
version: codeSystemVersion,
oid: codeSystem?.oid,
suffix: getCodeSuffix(code),
Expand Down Expand Up @@ -91,6 +91,7 @@ export default function CodesSection({
{activeTab === "savedCodes" && (
<SavedCodesSubSection
measureStoreCql={measureStoreCql}
measureModel={measureModel}
canEdit={canEdit}
handleApplyCode={handleApplyCode}
handleCodeDelete={handleCodeDelete}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ const readOnly = true;
const handleFormSubmitMock = jest.fn();

describe("Code Section component", () => {
it("should display all the fields in the Code(s) section", async () => {
it("should display all the fields in the Code(s) section for QDM", async () => {
render(
<CodeSection
canEdit={readOnly}
allCodeSystems={mockedCodeSystems}
handleFormSubmit={handleFormSubmitMock}
blankResults={jest.fn()}
measureModel=""
measureModel="QDM v5.6"
/>
);

Expand All @@ -29,27 +29,19 @@ describe("Code Section component", () => {
const codeSystemSelect = screen.getByTestId(
"code-system-selector-dropdown"
);

expect(codeSystemSelect).toBeInTheDocument();
expect(codeSystemSelect).toBeEnabled();

const codeSystemSelectButton = screen.getByRole("button", {
name: "Open",
});

userEvent.click(codeSystemSelectButton);

expect(screen.getByText("System1")).toBeInTheDocument();
expect(screen.getByText("System2")).toBeInTheDocument();

userEvent.type(codeSystemSelectButton, "System1");

expect(screen.getByText("System1")).toBeInTheDocument();
expect(screen.queryByText("System2")).not.toBeInTheDocument();
expect(codeSystemSelect).toBeEnabled();
userEvent.click(codeSystemSelect);

const codeSystemOptions = await screen.findAllByRole("option");
expect(codeSystemOptions.length).toEqual(1);
expect(codeSystemOptions.length).toEqual(3);
expect(codeSystemOptions[0]).toHaveTextContent("System1");
expect(codeSystemOptions[1]).toHaveTextContent("AdministrativeGender");
expect(codeSystemOptions[2]).toHaveTextContent("SNOMEDCT");
userEvent.click(codeSystemOptions[0]);

// Selecting a Code System Version
Expand Down Expand Up @@ -90,6 +82,161 @@ describe("Code Section component", () => {
});
});

it("should display all the fields in the Code(s) section for QiCore", async () => {
render(
<CodeSection
canEdit={readOnly}
allCodeSystems={mockedCodeSystems}
handleFormSubmit={handleFormSubmitMock}
blankResults={jest.fn()}
measureModel="QiCore v5.0.0"
/>
);

const searchButton = screen.getByRole("button", { name: "Search" });
const clearButton = screen.getByRole("button", { name: "Clear" });
expect(searchButton).toBeDisabled();
expect(clearButton).toBeDisabled();

// Selecting a Code System
const codeSystemSelect = screen.getByTestId(
"code-system-selector-dropdown"
);
expect(codeSystemSelect).toBeInTheDocument();
expect(codeSystemSelect).toBeEnabled();

const codeSystemSelectButton = screen.getByRole("button", {
name: "Open",
});
userEvent.click(codeSystemSelectButton);

const codeSystemOptions = await screen.findAllByRole("option");
expect(codeSystemOptions.length).toEqual(3);
expect(codeSystemOptions[0]).toHaveTextContent("System1");
expect(codeSystemOptions[1]).toHaveTextContent("AdministrativeGender");
expect(codeSystemOptions[2]).toHaveTextContent("SNOMEDCT");
userEvent.click(codeSystemOptions[1]);

// Making sure the latest version is already selected
const comboBoxContainer = screen.getByTestId(
"code-system-version-selector"
);
const codeSystemVersionSelect =
within(comboBoxContainer).getByRole("combobox");
expect(codeSystemVersionSelect).toHaveTextContent("2016-07-01");
expect(codeSystemVersionSelect).toBeEnabled();
userEvent.click(codeSystemVersionSelect);

// Selecting a Code System Version
const codeSystemVersionOptions = await screen.findAllByRole("option");
expect(codeSystemVersionOptions.length).toEqual(2);
expect(codeSystemVersionOptions[0]).toHaveTextContent("2016-07-01");
expect(codeSystemVersionOptions[1]).toHaveTextContent("2015-07-01");
userEvent.click(codeSystemVersionOptions[1]);

expect(codeSystemVersionSelect).toHaveTextContent("2015-07-01");

// Selecting a code
const codeText = screen.getByTestId("code-text");
expect(codeText).toBeEnabled();
userEvent.click(codeText);
const codeTextInput = screen.getByTestId(
"code-text-input"
) as HTMLInputElement;
userEvent.type(codeTextInput, "Code");
expect(codeTextInput.value).toBe("Code");

await waitFor(() => {
expect(clearButton).toBeEnabled();
expect(searchButton).not.toBeDisabled();
});
userEvent.click(searchButton);
await waitFor(() => {
expect(handleFormSubmitMock).toHaveBeenCalledWith({
title: "AdministrativeGender",
version: "2015-07-01",
code: "Code",
});
});
});

it("should display accurate code system version for SNOMED CT for QiCore", async () => {
render(
<CodeSection
canEdit={readOnly}
allCodeSystems={mockedCodeSystems}
handleFormSubmit={handleFormSubmitMock}
blankResults={jest.fn()}
measureModel="QiCore v5.0.0"
/>
);

const searchButton = screen.getByRole("button", { name: "Search" });
const clearButton = screen.getByRole("button", { name: "Clear" });
expect(searchButton).toBeDisabled();
expect(clearButton).toBeDisabled();

// Selecting a Code System
const codeSystemSelect = screen.getByTestId(
"code-system-selector-dropdown"
);
expect(codeSystemSelect).toBeInTheDocument();
expect(codeSystemSelect).toBeEnabled();

const codeSystemSelectButton = screen.getByRole("button", {
name: "Open",
});
userEvent.click(codeSystemSelectButton);

const codeSystemOptions = await screen.findAllByRole("option");
expect(codeSystemOptions.length).toEqual(3);
expect(codeSystemOptions[0]).toHaveTextContent("System1");
expect(codeSystemOptions[1]).toHaveTextContent("AdministrativeGender");
expect(codeSystemOptions[2]).toHaveTextContent("SNOMEDCT");
userEvent.click(codeSystemOptions[2]);

// Making sure the latest version is already selected
const comboBoxContainer = screen.getByTestId(
"code-system-version-selector"
);
const codeSystemVersionSelect =
within(comboBoxContainer).getByRole("combobox");
expect(codeSystemVersionSelect).toHaveTextContent("20180901");
expect(codeSystemVersionSelect).toBeEnabled();
userEvent.click(codeSystemVersionSelect);

// Selecting a Code System Version
const codeSystemVersionOptions = await screen.findAllByRole("option");
expect(codeSystemVersionOptions.length).toEqual(2);
expect(codeSystemVersionOptions[0]).toHaveTextContent("20180901");
expect(codeSystemVersionOptions[1]).toHaveTextContent("20130901");
userEvent.click(codeSystemVersionOptions[1]);

expect(codeSystemVersionSelect).toHaveTextContent("20130901");

// Selecting a code
const codeText = screen.getByTestId("code-text");
expect(codeText).toBeEnabled();
const codeTextInput = screen.getByTestId(
"code-text-input"
) as HTMLInputElement;
userEvent.type(codeTextInput, "Code");
expect(codeTextInput.value).toBe("Code");

await waitFor(() => {
expect(clearButton).toBeEnabled();
expect(searchButton).toBeEnabled();
});
userEvent.click(searchButton);
await waitFor(() => {
expect(handleFormSubmitMock).toHaveBeenCalledWith({
title: "SNOMEDCT",
version: "http://snomed.info/sct/731000124108/version/20130901",
code: "Code",
});
});
});

it("clear button should be disabled until a change is made in one of the search criteria", () => {
const { getByTestId } = render(
<CodeSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import InputAdornment from "@material-ui/core/InputAdornment";
import ExpandingSection from "../../../../common/ExpandingSection";
import { useFormik } from "formik";
import { CodeSubSectionSchemaValidator } from "../../../../validations/CodeSubSectionSchemaValidator";
import { uniq } from "lodash";
import _ from "lodash";
import moment from "moment";
import { MenuItem } from "@mui/material";
import { MenuItem, Tooltip } from "@mui/material";
import { CodeSystem } from "../../../../api/useTerminologyServiceApi";
import ControlledAutoComplete from "../../../../common/ControlledAutoComplete";

Expand All @@ -28,8 +28,22 @@ interface CodeSectionProps {
interface MenuObj {
value: string;
label: string;
fullValue: string;
}

const renderMenuItems = (options) =>
options.map(({ value, label, fullValue }) => (
<MenuItem
key={`${value}-option`}
value={value}
data-testid={`${value}-option`}
>
<Tooltip key={`${label}-tooltip`} title={fullValue} arrow>
<span>{label}</span>
</Tooltip>
</MenuItem>
));

export default function CodeSection({
handleFormSubmit,
allCodeSystems,
Expand All @@ -41,7 +55,7 @@ export default function CodeSection({
// if we open tab before information has arrived, we need to trigger a useEffect
useEffect(() => {
if (allCodeSystems?.length) {
const filteredTitles = uniq(allCodeSystems.map((t) => t.name)).map(
const filteredTitles = _.uniq(allCodeSystems.map((t) => t.name)).map(
(name) => ({
value: name,
label: name,
Expand All @@ -68,33 +82,43 @@ export default function CodeSection({
const [availableVersions, setAvailableVersions] = useState([]);
useEffect(() => {
if (formik.values.title) {
const availableVersions = allCodeSystems
// filter out code entries that matches with CodeSystem Title
const matchedCodeSystems = allCodeSystems
.filter((c) => c.name === formik.values.title)
.filter((c) => c.qdmDisplayVersion !== null)
.filter((c) => c.qdmDisplayVersion !== null || c.version !== null)
.sort((a, b) => {
const dateA = new Date(a.lastUpdatedUpstream);
const dateB = new Date(b.lastUpdatedUpstream);
return dateB.getTime() - dateA.getTime();
});
setAvailableVersions(
availableVersions
.map((cs) => ({
value: cs.version,
label: cs.qdmDisplayVersion,
}))
.filter((cs) => {
if (measureModel === "QDM v5.6") {
return cs.label !== null;
}
return true;
})
);
formik.setFieldValue("version", availableVersions[0]?.version);
// creates a list of value, label obj based on model and filters out if version is null
// We want to display qdm version but when retrieving codes we have to use fhir Version
const availableVersionsList = matchedCodeSystems
.map((m) => ({
value: m.version,
label: _.includes(measureModel, "QDM")
? m.qdmDisplayVersion
: m.version,
}))
.filter((m) => m.label !== null);
// if version is URL ( ex: SNOMEDCT ) then fetch the version parameter
const updatedVersionList = availableVersionsList.map((a) => {
const isUrl = a.label.includes("http://");
const version = isUrl ? _.last(a.label.split("/")) : a.label;
return {
value: a.value,
label: version,
fullValue: a.value,
};
});
setAvailableVersions(updatedVersionList);
formik.setFieldValue("version", updatedVersionList[0]?.value);
} else {
setAvailableVersions([]);
formik.setFieldValue("version", "");
}
}, [formik.values.title]);
}, [formik.values.title, measureModel, allCodeSystems]);

const searchInputProps = {
startAdornment: (
<InputAdornment position="start">
Expand All @@ -103,20 +127,6 @@ export default function CodeSection({
),
};

const renderMenuItems = (options: MenuObj[]) => {
return [
...options.map(({ value, label }) => (
<MenuItem
key={`${label}-option`}
value={value}
data-testid={`${label}-option`}
>
{label}
</MenuItem>
)),
];
};

function trimCodeInput() {
formik.setFieldValue("code", formik.values.code.trim());
}
Expand Down
Loading
Loading