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

[Rating] Fix Rating returns NaN when using user event #45054

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
14 changes: 12 additions & 2 deletions packages/mui-material/src/Rating/Rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,15 @@ const Rating = React.forwardRef(function Rating(inProps, ref) {
onMouseMove(event);
}

setFocusVisible(false);

const rootNode = rootRef.current;
const { right, left, width: containerWidth } = rootNode.getBoundingClientRect();

if (event.clientX < left || event.clientX > right) {
return;
}
NooBat marked this conversation as resolved.
Show resolved Hide resolved

let percent;

if (isRtl) {
Expand All @@ -407,6 +413,12 @@ const Rating = React.forwardRef(function Rating(inProps, ref) {
let newHover = roundValueToPrecision(max * percent + precision / 2, precision);
newHover = clamp(newHover, precision, max);

if (Number.isNaN(newHover)) {
// Workaround for test scenario using userEvent since jsdom defaults getBoundingClientRect to 0
// Fix https://github.com/mui/material-ui/issues/38828
return;
}

setState((prev) =>
prev.hover === newHover && prev.focus === newHover
? prev
Expand All @@ -416,8 +428,6 @@ const Rating = React.forwardRef(function Rating(inProps, ref) {
},
);

setFocusVisible(false);

if (onChangeActive && hover !== newHover) {
onChangeActive(event, newHover);
}
Expand Down
16 changes: 16 additions & 0 deletions packages/mui-material/src/Rating/Rating.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { stub, spy } from 'sinon';
import { act, createRenderer, fireEvent, screen } from '@mui/internal-test-utils';
import Rating, { ratingClasses as classes } from '@mui/material/Rating';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import userEvent from '@testing-library/user-event';
import describeConformance from '../../test/describeConformance';

describe('<Rating />', () => {
Expand Down Expand Up @@ -121,6 +122,21 @@ describe('<Rating />', () => {
expect(checked.value).to.equal('2');
});

it('should select the rating with user clicks using user-event', async () => {
const user = userEvent.setup();
const handleChange = spy();

const { container } = render(<Rating name="rating-test" onChange={handleChange} />);

await user.click(screen.getByLabelText('3 Stars'));

expect(handleChange.callCount).to.equal(1);
expect(handleChange.args[0][1]).to.deep.equal(3);

const checked = container.querySelector('input[name="rating-test"]:checked');
expect(checked.value).to.equal('3');
});

it('should change the value to null', () => {
const handleChange = spy();
render(<Rating name="rating-test" onChange={handleChange} value={2} />);
Expand Down