Skip to content

Commit

Permalink
Merge branch '3.1.0' into CRDCDH-1428
Browse files Browse the repository at this point in the history
  • Loading branch information
Alejandro-Vega authored Nov 8, 2024
2 parents b8cd159 + aa06d99 commit c706dcd
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 17 deletions.
84 changes: 74 additions & 10 deletions src/components/NodeChart/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,80 @@
import { axe } from "jest-axe";
import { render } from "@testing-library/react";
import { render, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import NodeChart from "./index";

it("should not have any accessibility violations", async () => {
const data = [
{ label: "New" as SeriesLabel, value: 50, color: "#000000" },
{ label: "Passed" as SeriesLabel, value: 25, color: "#ffffff" },
{ label: "Error" as SeriesLabel, value: 25, color: "#3b3b3b" },
];
const { container } = render(<NodeChart label="Test Chart" centerCount={3} data={data} />);
const mockData: PieSectorDataItem[] = [
{ label: "New", value: 50, color: "#000000" },
{ label: "Passed", value: 25, color: "#ffffff" },
{ label: "Error", value: 25, color: "#3b3b3b" },
];

const results = await axe(container);
describe("Accessibility", () => {
it("should not have any accessibility violations", async () => {
const { container } = render(<NodeChart label="Test Chart" centerCount={3} data={mockData} />);

expect(results).toHaveNoViolations();
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});

describe("Basic Functionality", () => {
it("should trim the chart label if it exceeds 14 characters", () => {
const { getByText, rerender } = render(
<NodeChart label="This Is A Very Long Label" centerCount={3} data={mockData} />
);

expect(getByText("This Is A Very...")).toBeInTheDocument();

rerender(<NodeChart label="Short Label" centerCount={3} data={mockData} />);

expect(getByText("Short Label")).toBeInTheDocument();
});

it("should replace underscores with spaces in the chart label", () => {
const { getByText } = render(
<NodeChart label="Test_Label_1" centerCount={3} data={mockData} />
);

expect(getByText("Test Label 1")).toBeInTheDocument();
});

it("should perform a title case transformation on the chart label if it contains spaces", async () => {
const { getByText, getByRole } = render(
<NodeChart label="principal investigator" centerCount={3} data={mockData} />
);

expect(getByText("Principal Inve...")).toBeInTheDocument();

userEvent.hover(getByText("Principal Inve..."));

await waitFor(() => {
expect(getByRole("tooltip")).toBeVisible();
});

// NOTE: We're asserting that the same transformation is applied to the tooltip
expect(within(getByRole("tooltip")).getByText("Principal Investigator")).toBeInTheDocument();
});

// NOTE: Since we're splitting at underscores, let's individually test this too
it("should perform title case transformation on the chart label if it would contain spaces", () => {
const { getByText } = render(
<NodeChart label="principal_investigator" centerCount={3} data={mockData} />
);

expect(getByText("Principal Inve...")).toBeInTheDocument();
});

it("should persist existing casing if the label does not contain spaces", () => {
const { getByText } = render(
<NodeChart label="NonDICOMCTimages" centerCount={3} data={mockData} />
);

expect(getByText("NonDICOMCTimag...")).toBeInTheDocument();
});

it.each([null, "", undefined])("should not crash if the label is %s", (value) => {
expect(() => render(<NodeChart label={value} centerCount={3} data={mockData} />)).not.toThrow();
});
});
34 changes: 27 additions & 7 deletions src/components/NodeChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Box, Typography, styled } from "@mui/material";
import { PieChart, Pie, Label, Cell } from "recharts";
import { isEqual } from "lodash";
import PieChartCenter from "./PieChartCenter";
import TruncatedText from "../TruncatedText";
import { capitalizeFirstLetter, titleCase } from "../../utils";

type Props = {
/**
Expand All @@ -21,14 +23,10 @@ type Props = {

const StyledPieChartLabel = styled(Typography)({
color: "#3D4551",
fontFamily: "'Nunito Sans', 'Rubik', sans-serif",
fontSize: "20px",
fontWeight: 600,
lineHeight: "21px",
textTransform: "capitalize",
marginBottom: "12px",
textAlign: "center",
alignSelf: "center",
userSelect: "none",
});

Expand All @@ -53,16 +51,38 @@ const NodeChart: FC<Props> = ({ label, centerCount, data }: Props) => {
const [hoveredSlice, setHoveredSlice] = useState<PieSectorDataItem>(null);

const dataset: PieSectorDataItem[] = useMemo(() => data.filter(({ value }) => value > 0), [data]);
const onMouseOver = useCallback((data) => setHoveredSlice(data), []);
const onMouseLeave = useCallback(() => setHoveredSlice(null), []);

const showDefaultCenter: boolean = useMemo(
() => (dataset.length === 0 && hoveredSlice === null) || hoveredSlice?.value === 0,
[dataset, hoveredSlice]
);

const reformattedLabel = useMemo<string>(() => {
const replacedLabel = label?.replace(/_/g, " ") || "";

// If the label has no spaces, capitalize the first letter to avoid
// titleCase from performing a full title case conversion
if (replacedLabel?.indexOf(" ") === -1) {
return capitalizeFirstLetter(replacedLabel);
}

return titleCase(replacedLabel);
}, [label]);

const onMouseOver = useCallback((data) => setHoveredSlice(data), []);
const onMouseLeave = useCallback(() => setHoveredSlice(null), []);

return (
<StyledChartContainer>
{label && <StyledPieChartLabel>{label.replace(/_/g, " ")}</StyledPieChartLabel>}
{reformattedLabel && (
<StyledPieChartLabel>
<TruncatedText
text={reformattedLabel}
wrapperStyles={{ margin: "0 auto" }}
maxCharacters={14}
/>
</StyledPieChartLabel>
)}
<PieChart width={150} height={150}>
<Pie
data={[{ value: 100 }]}
Expand Down

0 comments on commit c706dcd

Please sign in to comment.