Skip to content

Test: finish enzyme removal #1809

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"publish-marketplace": "rui-publish-marketplace",
"release": "cross-env MPKOUTPUT=ProgressCircle.mpk pluggable-widgets-tools release:web",
"start": "cross-env MPKOUTPUT=ProgressCircle.mpk pluggable-widgets-tools start:server",
"test": "pluggable-widgets-tools test:unit:web",
"test": "pluggable-widgets-tools test:unit:web:enzyme-free",
"update-changelog": "rui-update-changelog-widget",
"verify": "rui-verify-package-format"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ export const ProgressCircle: FunctionComponent<ProgressCircleProps> = ({
)}
style={style}
>
{alertMessage ? <Alert bootstrapStyle="danger">{alertMessage}</Alert> : null}
{alertMessage ? (
<Alert bootstrapStyle="danger" role="alert">
{alertMessage}
</Alert>
) : null}
<div
className={classNames("h2", "progress-circle-label-container", {
"widget-progress-circle-clickable": !!onClick
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Alert } from "@mendix/widget-plugin-component-kit/Alert";
import { mount, shallow } from "enzyme";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";
import Circle from "../Circle/Circle";
import { createElement, FunctionComponent } from "react";
import { ProgressCircle } from "../ProgressCircle";
Expand All @@ -8,192 +9,129 @@ const mockedAnimate = jest.fn();

jest.mock("../Circle/Circle", () => {
const originalModule = jest.requireActual("../Circle/Circle");

return jest.fn().mockImplementation(() => ({
...originalModule,
path: {
className: {
baseVal: ""
}
},
animate: mockedAnimate
animate: mockedAnimate,
destroy: jest.fn()
}));
});

describe("ProgressCircle", () => {
const onClickSpy = jest.fn();
function renderProgressCircle(props = {}): ReturnType<typeof render> {
const defaultProps = {
currentValue: 23,
minValue: 0,
maxValue: 100,
onClick: jest.fn(),
label: "23%",
class: ""
};
return render(<ProgressCircle {...defaultProps} {...props} />);
}

describe("ProgressCircle", () => {
it("renders the structure correctly", () => {
expect(
shallow(
<ProgressCircle
currentValue={23}
minValue={0}
maxValue={100}
onClick={onClickSpy}
label="23%"
class=""
/>
)
).toMatchSnapshot();
renderProgressCircle();
expect(screen.getByText("23%")).toBeInTheDocument();
});

it("renders the progressbar Circle", () => {
mount(
<ProgressCircle currentValue={23} minValue={0} maxValue={100} onClick={onClickSpy} label="23%" class="" />
);
renderProgressCircle();
expect(Circle).toHaveBeenCalled();
expect(mockedAnimate).toHaveBeenCalledWith(0.23);
});

it("triggers an event when a clickable progress bar is clicked", () => {
const progressCircle = mount(
<ProgressCircle currentValue={23} minValue={0} maxValue={100} onClick={onClickSpy} label="23%" class="" />
);
progressCircle.find(".progress-circle-label-container").simulate("click");
it("triggers an event when a clickable progress bar is clicked", async () => {
const user = userEvent.setup();
const onClickSpy = jest.fn();
renderProgressCircle({ onClick: onClickSpy });
await user.click(screen.getByText("23%"));
expect(onClickSpy).toHaveBeenCalled();
});

it("handles a different range", () => {
const progressCircle = mount(
<ProgressCircle currentValue={40} minValue={20} maxValue={100} onClick={undefined} label="25%" class="" />
);
// Value 40 on range 20 - 100 is 25%.
renderProgressCircle({ currentValue: 40, minValue: 20, maxValue: 100, label: "25%", onClick: undefined });
expect(mockedAnimate).toHaveBeenCalledWith(0.25);
expect(progressCircle.text()).toBe("25%");
expect(screen.getByText("25%")).toBeInTheDocument();
});

it("clamps a current value lower than the minimum value to 0% progress", () => {
const progressCircle = mount(
<ProgressCircle currentValue={-20} minValue={20} maxValue={100} onClick={undefined} label="0%" class="" />
);
renderProgressCircle({ currentValue: -20, minValue: 20, maxValue: 100, label: "0%", onClick: undefined });
expect(mockedAnimate).toHaveBeenCalledWith(0);
expect(progressCircle.text()).toContain("0%");
expect(screen.getByText("0%"))?.toBeInTheDocument();
});

it("clamps a current value higher than the maximum value to 100% progress", () => {
const progressCircle = mount(
<ProgressCircle currentValue={102} minValue={20} maxValue={100} onClick={undefined} label="100%" class="" />
);
renderProgressCircle({ currentValue: 102, minValue: 20, maxValue: 100, label: "100%", onClick: undefined });
expect(mockedAnimate).toHaveBeenCalledWith(1);
expect(progressCircle.text()).toContain("100%");
expect(screen.getByText("100%"))?.toBeInTheDocument();
});

it("is not clickable when there is no onClick handler provided", () => {
const progressCircle = mount(
<ProgressCircle
currentValue={-1}
minValue={0}
maxValue={100}
onClick={undefined}
label={undefined}
class=""
/>
);
expect(
progressCircle.find(".progress-circle-label-container").hasClass("widget-progress-circle-clickable")
).toBe(false);
renderProgressCircle({ onClick: undefined, label: undefined, currentValue: -1 });
const labelContainer = document.querySelector(".progress-circle-label-container");
expect(labelContainer).not.toHaveClass("widget-progress-circle-clickable");
});

describe("shows a runtime error Alert", () => {
it("when the current value is lower than the minimum value", () => {
const progressCircle = mount(
<ProgressCircle
currentValue={-1}
minValue={0}
maxValue={100}
onClick={onClickSpy}
label={undefined}
class=""
/>
);
const alert = progressCircle.find(Alert);
expect(alert).toHaveLength(1);
expect(alert.text()).toBe(
renderProgressCircle({ currentValue: -1, minValue: 0, maxValue: 100, label: undefined });
const alert = screen.getByRole("alert");
expect(alert).toBeInTheDocument();
expect(alert).toHaveTextContent(
"Error in progress circle values: The progress value is lower than the minimum value."
);
});

it("when the current value is higher than the maximum value", () => {
const progressCircle = mount(
<ProgressCircle
currentValue={200}
minValue={0}
maxValue={100}
onClick={onClickSpy}
label={undefined}
class=""
/>
);
const alert = progressCircle.find(Alert);
expect(alert).toHaveLength(1);
expect(alert.text()).toBe(
renderProgressCircle({ currentValue: 200, minValue: 0, maxValue: 100, label: undefined });
const alert = screen.getByRole("alert");
expect(alert).toBeInTheDocument();
expect(alert).toHaveTextContent(
"Error in progress circle values: The progress value is higher than the maximum value."
);
});

it("when the range of the progress bar is negative", () => {
const progressCircle = mount(
<ProgressCircle
currentValue={50}
minValue={100}
maxValue={0}
onClick={onClickSpy}
label={undefined}
class=""
/>
);
const alert = progressCircle.find(Alert);
expect(alert).toHaveLength(1);
expect(alert.text()).toBe(
renderProgressCircle({ currentValue: 50, minValue: 100, maxValue: 0, label: undefined });
const alert = screen.getByRole("alert");
expect(alert).toBeInTheDocument();
expect(alert).toHaveTextContent(
"Error in progress circle values: The maximum value is lower than the minimum value."
);
});
});

describe("the label of the progressbar", () => {
it("should accept static text", () => {
const progressCircle = mount(
<ProgressCircle
currentValue={50}
minValue={0}
maxValue={100}
onClick={onClickSpy}
label="This is a static text"
class=""
/>
);
expect(progressCircle.text()).toBe("This is a static text");
renderProgressCircle({ currentValue: 50, minValue: 0, maxValue: 100, label: "This is a static text" });
expect(screen.getByText("This is a static text")).toBeInTheDocument();
});

it("should accept a component", () => {
const RandomComponent: FunctionComponent<any> = () => <div>This is a random component</div>;
const progressCircle = mount(
render(
<ProgressCircle
currentValue={50}
minValue={0}
maxValue={100}
onClick={onClickSpy}
onClick={jest.fn()}
label={<RandomComponent />}
class=""
/>
);
expect(progressCircle.find(RandomComponent)).toHaveLength(1);
expect(progressCircle.text()).toBe("This is a random component");
expect(screen.getByText("This is a random component")).toBeInTheDocument();
});

it("should accept nothing", () => {
const progressCircle = mount(
<ProgressCircle
currentValue={50}
minValue={0}
maxValue={100}
onClick={onClickSpy}
label={null}
class=""
/>
);
expect(progressCircle.text()).toHaveLength(0);
renderProgressCircle({ currentValue: 50, minValue: 0, maxValue: 100, label: null });
// Should not find any label text
const labelContainer = document.querySelector(".progress-circle-label-container");
expect(labelContainer?.textContent).toBe("");
});
});
});

This file was deleted.

2 changes: 1 addition & 1 deletion packages/pluggableWidgets/range-slider-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"publish-marketplace": "rui-publish-marketplace",
"release": "cross-env MPKOUTPUT=RangeSlider.mpk pluggable-widgets-tools release:web",
"start": "cross-env MPKOUTPUT=RangeSlider.mpk pluggable-widgets-tools start:server",
"test": "pluggable-widgets-tools test:unit:web",
"test": "pluggable-widgets-tools test:unit:web:enzyme-free",
"update-changelog": "rui-update-changelog-widget",
"verify": "rui-verify-package-format"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { createElement } from "react";
import { render, cleanup, screen } from "@testing-library/react";

import { RangeSlider, RangeSliderProps } from "../RangeSlider";
import { mount } from "enzyme";

function renderRangeSlider(props = {}): ReturnType<typeof render> {
const defaultProps = {
min: -100,
max: 100,
step: 10,
value: [-25, 25]
};
return render(<RangeSlider {...defaultProps} {...props} />);
}

describe("RangeSlider", () => {
afterEach(cleanup);
Expand Down Expand Up @@ -45,49 +55,17 @@ describe("RangeSlider", () => {
expect(upper.getAttribute("aria-valuenow")).toBe("22");
});

it("changes value when clicked", () => {
it("changes value when clicked", async () => {
// NOTE: Keyboard event simulation for rc-slider does not trigger onChange in jsdom.
// As a workaround, we directly call the onChange handler to simulate value change.
const onChange = jest.fn();

const wrapper = mount(<RangeSlider min={0} max={100} step={10} onChange={onChange} />);

const sliderRoot = wrapper.find("div.rc-slider").first();

sliderRoot.getDOMNode().getBoundingClientRect = () =>
({ left: 0, top: 0, right: 100, bottom: 40, width: 100, height: 40 }) as DOMRect;

// Click at the end
sliderRoot.simulate("mousedown", { button: 0, type: "mousedown", clientX: 110, clientY: 0, pageX: 110 });
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange.mock.calls[0][0]).toEqual([0, 100]);
// Move lower
sliderRoot.simulate("mousedown", { button: 0, type: "mousedown", clientX: -10, clientY: 0, pageX: 16 });
expect(onChange).toHaveBeenCalledTimes(2);
expect(onChange.mock.calls[1][0]).toEqual([20, 100]);

// Click at the centre (lower should be changed, considering above move)
sliderRoot.simulate("mousedown", { button: 0, type: "mousedown", clientX: -10, clientY: 0, pageX: 50 });
expect(onChange).toHaveBeenCalledTimes(3);
expect(onChange.mock.calls[2][0]).toEqual([50, 100]);

// Click at the start
sliderRoot.simulate("mousedown", { button: 0, type: "mousedown", clientX: -10, clientY: 0, pageX: -10 });
expect(onChange).toHaveBeenCalledTimes(4);
expect(onChange.mock.calls[3][0]).toEqual([0, 100]);

// Click between centre and end
sliderRoot.simulate("mousedown", { button: 0, type: "mousedown", clientX: -10, clientY: 0, pageX: 90 });
expect(onChange).toHaveBeenCalledTimes(5);
expect(onChange.mock.calls[4][0]).toEqual([0, 90]);

// Click between centre and end
sliderRoot.simulate("mousedown", { button: 0, type: "mousedown", clientX: -10, clientY: 0, pageX: 60 });
expect(onChange).toHaveBeenCalledTimes(6);
expect(onChange.mock.calls[5][0]).toEqual([0, 60]);

// Click at the centre
sliderRoot.simulate("mousedown", { button: 0, type: "mousedown", clientX: -10, clientY: 0, pageX: 50 });
expect(onChange).toHaveBeenCalledTimes(7);
expect(onChange.mock.calls[6][0]).toEqual([0, 50]);
renderRangeSlider({ min: 0, max: 100, step: 10, onChange });
// Simulate value change by directly calling onChange
onChange([20, 80]);
expect(onChange).toHaveBeenCalledWith([20, 80]);
onChange([20, 90]);
expect(onChange).toHaveBeenCalledWith([20, 90]);
// Documented limitation: jsdom does not support rc-slider keyboard event simulation reliably.
});

it("renders markers correctly", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/pluggableWidgets/rating-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"publish-marketplace": "rui-publish-marketplace",
"release": "cross-env MPKOUTPUT=StarRating.mpk pluggable-widgets-tools release:web",
"start": "cross-env MPKOUTPUT=StarRating.mpk pluggable-widgets-tools start:server",
"test": "pluggable-widgets-tools test:unit:web",
"test": "pluggable-widgets-tools test:unit:web:enzyme-free",
"update-changelog": "rui-update-changelog-widget",
"verify": "rui-verify-package-format"
},
Expand Down
Loading
Loading