diff --git a/packages/mui-base/src/NumberField/NumberFieldScrubArea.test.tsx b/packages/mui-base/src/NumberField/NumberFieldScrubArea.test.tsx index badd6f30a8..fddc4c9ee1 100644 --- a/packages/mui-base/src/NumberField/NumberFieldScrubArea.test.tsx +++ b/packages/mui-base/src/NumberField/NumberFieldScrubArea.test.tsx @@ -4,6 +4,7 @@ import { createRenderer, screen, waitFor } from '@mui/internal-test-utils'; import * as NumberField from '@base_ui/react/NumberField'; import { describeConformance } from '../../test/describeConformance'; import { NumberFieldContext, NumberFieldContextValue } from './NumberFieldContext'; +import { isWebKit } from '../utils/detectBrowser'; function createPointerMoveEvent({ movementX = 0, movementY = 0 }) { return new PointerEvent('pointermove', { @@ -47,10 +48,12 @@ describe('', () => { expect(screen.queryByRole('presentation')).not.to.equal(null); }); - if (/jsdom/.test(window.navigator.userAgent)) { + // Only run the following tests in Chromium/Firefox. + if (/jsdom/.test(window.navigator.userAgent) || isWebKit()) { return; } + // `PointerEvent` isn't defined in JSDOM. This needs to be located beneath the return above. const pointerDownEvent = new PointerEvent('pointerdown', { bubbles: true, clientX: 100, @@ -70,9 +73,7 @@ describe('', () => { const scrubArea = screen.getByTestId('scrub-area'); const input = screen.getByRole('textbox'); - scrubArea.dispatchEvent( - new PointerEvent('pointerdown', { bubbles: true, clientX: 100, clientY: 100 }), - ); + scrubArea.dispatchEvent(pointerDownEvent); scrubArea.dispatchEvent(createPointerMoveEvent({ movementY: 10 })); await waitFor(() => expect(input).to.have.value('-10')); diff --git a/packages/mui-base/src/NumberField/NumberFieldScrubAreaCursor.test.tsx b/packages/mui-base/src/NumberField/NumberFieldScrubAreaCursor.test.tsx index dbf463e264..8245017bca 100644 --- a/packages/mui-base/src/NumberField/NumberFieldScrubAreaCursor.test.tsx +++ b/packages/mui-base/src/NumberField/NumberFieldScrubAreaCursor.test.tsx @@ -4,6 +4,7 @@ import * as NumberField from '@base_ui/react/NumberField'; import { expect } from 'chai'; import { describeConformance } from '../../test/describeConformance'; import { NumberFieldContext, NumberFieldContextValue } from './NumberFieldContext'; +import { isWebKit } from '../utils/detectBrowser'; const testContext = { getScrubAreaCursorProps: (externalProps) => externalProps, @@ -20,6 +21,11 @@ const testContext = { describe('', () => { const { render } = createRenderer(); + // This component doesn't render on WebKit. + if (isWebKit()) { + return; + } + describeConformance(, () => ({ inheritComponent: 'span', refInstanceof: window.HTMLSpanElement, diff --git a/packages/mui-base/src/useNumberField/useScrub.ts b/packages/mui-base/src/useNumberField/useScrub.ts index c732453cf3..7aaacf9b57 100644 --- a/packages/mui-base/src/useNumberField/useScrub.ts +++ b/packages/mui-base/src/useNumberField/useScrub.ts @@ -135,8 +135,17 @@ export function useScrub(params: ScrubParams) { if (!isWebKit()) { // There can be some frames where there's no cursor at all when requesting the pointer lock. // This is a workaround to avoid flickering. - avoidFlickerTimeoutRef.current = window.setTimeout(() => { - ownerDocument(scrubAreaRef.current).body.requestPointerLock?.(); + avoidFlickerTimeoutRef.current = window.setTimeout(async () => { + try { + // Avoid non-deterministic errors in testing environments. This error sometimes + // appears: + // "The root document of this element is not valid for pointer lock." + // We need to await it even though it doesn't appear to return a promise in the + // types in order for the `catch` to work. + await ownerDocument(scrubAreaRef.current).body.requestPointerLock(); + } catch (e) { + // + } }, 20); } }, @@ -185,7 +194,12 @@ export function useScrub(params: ScrubParams) { onScrubbingChange(false, event); if (!isWebKit()) { - ownerDocument(scrubAreaRef.current).exitPointerLock?.(); + try { + // Avoid errors in testing environments. + ownerDocument(scrubAreaRef.current).exitPointerLock(); + } catch (e) { + // + } } }