From 6a76a961d938a77cd563230d845206678747ddb8 Mon Sep 17 00:00:00 2001 From: NooBat Date: Fri, 31 Jan 2025 12:27:33 +0700 Subject: [PATCH] [fix] Fix Rating return NaN when using user event --- packages/mui-material/src/Rating/Rating.js | 10 +++++++-- .../mui-material/src/Rating/Rating.test.js | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/mui-material/src/Rating/Rating.js b/packages/mui-material/src/Rating/Rating.js index d6b5f761603982..6efc9854dbe823 100644 --- a/packages/mui-material/src/Rating/Rating.js +++ b/packages/mui-material/src/Rating/Rating.js @@ -404,9 +404,17 @@ const Rating = React.forwardRef(function Rating(inProps, ref) { percent = (event.clientX - left) / containerWidth; } + setFocusVisible(false); + 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 +424,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..33f2c2f612b27f 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,27 @@ describe('', () => { expect(checked.value).to.equal('2'); }); + it('should select the rating with user clicks', async () => { + const user = userEvent.setup(); + const handleChange = spy(); + + const { container } = render(); + + const input = container.getByLabelText('3 Stars'); + // A mouse move event is required since userEvent.click triggers a mouse move event + // but clientX is always 0 in the event. + fireEvent.mouseMove(input, { + clientX: 60, + }); + await user.click(input); + + 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();