diff --git a/packages/mui-material/src/Rating/Rating.js b/packages/mui-material/src/Rating/Rating.js
index d6b5f761603982..8609b297cf3eaa 100644
--- a/packages/mui-material/src/Rating/Rating.js
+++ b/packages/mui-material/src/Rating/Rating.js
@@ -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;
+ }
+
let percent;
if (isRtl) {
@@ -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
@@ -416,8 +428,6 @@ const Rating = React.forwardRef(function Rating(inProps, ref) {
},
);
- setFocusVisible(false);
-
if (onChangeActive && hover !== newHover) {
onChangeActive(event, newHover);
}
diff --git a/packages/mui-material/src/Rating/Rating.test.js b/packages/mui-material/src/Rating/Rating.test.js
index 7c84b7e72ce4fb..59d1214ce81c4b 100644
--- a/packages/mui-material/src/Rating/Rating.test.js
+++ b/packages/mui-material/src/Rating/Rating.test.js
@@ -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('', () => {
@@ -121,6 +122,21 @@ describe('', () => {
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();
+
+ 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();