Skip to content

Commit

Permalink
Merge pull request #113 from jgiven/increase_test_coverage
Browse files Browse the repository at this point in the history
Increase test coverage + Refactoring
  • Loading branch information
fudler authored Oct 2, 2024
2 parents a50075a + c93f2c3 commit 21ef8a1
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 19 deletions.
75 changes: 59 additions & 16 deletions new/src/components/ScenarioOverview/DonutChart.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
import { ReportStatistics } from "../../reportModel";
import { ArcElement, Chart as ChartJS, Legend, Tooltip } from "chart.js";
import { ArcElement, BubbleDataPoint, Chart as ChartJS, Legend, Point, Tooltip } from "chart.js";
import { Doughnut } from "react-chartjs-2";
import { useRef } from "react";
import { ChartJSOrUndefined } from "react-chartjs-2/dist/types";
import { useFilters } from "../../hooks/useFilters";
import { ScenarioStatusFilter } from "./ScenarioCollectionHead";

export function createReportCircle(props: { statistic: ReportStatistics }) {
export interface DonutChartProps {
statistic: ReportStatistics;
}

export function DonutChart(props: DonutChartProps) {
const successLabel = "Successful:";
const failedLabel = "Failed:";
ChartJS.register(ArcElement, Tooltip, Legend);

const { statistic } = props;

const { setUrlSearchParams } = useFilters();

const chartRef =
useRef<
ChartJSOrUndefined<
"doughnut",
(number | [number, number] | Point | BubbleDataPoint | null)[],
unknown
>
>(null);

const width = 240; // set default width to 100 if none is provided via props
const height = 120; // set default height to 100 if none is provided via props

const data = {
labels: ["Successful:", "Failed:"],
labels: [successLabel, failedLabel],
datasets: [
{
data: [props.statistic.numSuccessfulScenarios, props.statistic.numFailedScenarios],
data: [statistic.numSuccessfulScenarios, statistic.numFailedScenarios],
backgroundColor: ["rgba(60, 179, 113)", "rgba(255, 0, 0)"],
borderWidth: 1,
onClick: (event: MouseEvent, elements: any[], chart: any) => {
if (elements.length === 0) {
return; // user did not click on a chart element
}
const label = chart.data.labels[elements[0].index];
if (label === "Successful") {
window.location.href = "/successful";
} else if (label === "Failed") {
window.location.href = "/failed";
}
},
hoverBackgroundColor: ["rgba(60,179,113,0.63)", "rgba(255,20,20,0.63)"]
}
]
Expand Down Expand Up @@ -53,5 +65,36 @@ export function createReportCircle(props: { statistic: ReportStatistics }) {
}
};

return <Doughnut data={data} width={width} height={height} options={options} />;
const handleClick = (event: React.MouseEvent<HTMLCanvasElement>) => {
const chart = chartRef.current;
if (chart == null) {
return;
}

const clickedElementIndex = chart.getElementsAtEventForMode(
event.nativeEvent,
"nearest",
{ intersect: true },
false
)[0].index;

const label = chart.data.labels?.at(clickedElementIndex);

if (label === successLabel) {
setUrlSearchParams({ status: ScenarioStatusFilter.SUCCESS });
} else if (label === failedLabel) {
setUrlSearchParams({ status: ScenarioStatusFilter.FAILED });
}
};

return (
<Doughnut
ref={chartRef}
data={data}
width={width}
height={height}
options={options}
onClick={handleClick}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import RemoveIcon from "@mui/icons-material/Remove";
import AddIcon from "@mui/icons-material/Add";
import PrintOutlinedIcon from "@mui/icons-material/PrintOutlined";
import BookmarkOutlinedIcon from "@mui/icons-material/BookmarkOutlined";
import { createReportCircle } from "./DonutChart";
import { DonutChart } from "./DonutChart";
import { PropsWithChildren, useMemo } from "react";
import { processWords } from "../../wordProcessor";
import {
Expand Down Expand Up @@ -50,7 +50,7 @@ export function ScenarioCollectionHead(props: ScenarioCollectionHeadProps) {
<ScenarioTitles headers={headers} />
</Grid>
<Grid item sx={{ flexGrow: 1 }} />
<Grid item>{createReportCircle({ statistic })}</Grid>
<Grid item>{DonutChart({ statistic })}</Grid>
<Grid item>
<ScenarioActionButtons {...iconClickHandlers} />
</Grid>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { createReportStatistics } from "./scenarioTestData";
import { StatisticBreadcrumbs } from "../StatisticsBreadcrumbs";
import { render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import userEvent from "@testing-library/user-event";
import * as useFilters from "../../../hooks/useFilters";
import { ScenarioStatusFilter } from "../../ScenarioOverview/ScenarioCollectionHead";

const setUrlSearchParamsMock = jest.fn();

beforeEach(() => {
jest.resetAllMocks();
jest.spyOn(useFilters, "useFilters").mockReturnValue({
filter: { status: undefined },
setUrlSearchParams: setUrlSearchParamsMock
});
});

describe("StatisticsBreadcrumbs", () => {
it("should display statistics", () => {
Expand Down Expand Up @@ -60,4 +73,29 @@ describe("StatisticsBreadcrumbs", () => {
expect(screen.queryByText(")", { exact: false })).not.toBeInTheDocument();
}
);

it.each([
["Successful", ScenarioStatusFilter.SUCCESS],
["failed", ScenarioStatusFilter.FAILED],
["pending", ScenarioStatusFilter.PENDING]
])(
"Pressing %s link should filter for status %s",
(label: string, status: ScenarioStatusFilter) => {
const statistic = createReportStatistics();

render(
<MemoryRouter>
<Routes>
<Route path="/" element={<StatisticBreadcrumbs statistic={statistic} />} />
</Routes>
</MemoryRouter>
);

userEvent.click(screen.getByText(label, { exact: false }));

expect(setUrlSearchParamsMock).toHaveBeenCalledWith({
status
});
}
);
});

0 comments on commit 21ef8a1

Please sign in to comment.