1- import { test , expect } from 'vitest' ;
1+ import { test , expect , vi } from 'vitest' ;
22import * as React from 'react' ;
33import type { Coords } from '@floating-ui/react-dom' ;
44import { flushMicrotasks } from '@mui/internal-test-utils' ;
55import { fireEvent , render , screen } from '@testing-library/react' ;
66import { createChangeEventDetails } from '../../internals/createBaseUIEventDetails' ;
77import { REASONS } from '../../internals/reasons' ;
8+ import { PopupTriggerMap } from '../../utils/popups' ;
9+ import { FloatingRootStore } from '../components/FloatingRootStore' ;
810import { useClientPoint , useFloating , useInteractions } from '../index' ;
911
1012function expectLocation ( { x, y } : Coords ) {
@@ -21,6 +23,20 @@ function expectRect({ x, y, width, height }: DOMRectInit) {
2123 expect ( Number ( screen . getByTestId ( 'height' ) ?. textContent ) ) . toBe ( height ) ;
2224}
2325
26+ function createRootStore ( referenceElement : HTMLElement ) {
27+ return new FloatingRootStore ( {
28+ open : false ,
29+ transitionStatus : undefined ,
30+ referenceElement,
31+ floatingElement : document . createElement ( 'div' ) ,
32+ triggerElements : new PopupTriggerMap ( ) ,
33+ floatingId : undefined ,
34+ syncOnly : false ,
35+ nested : false ,
36+ onOpenChange : vi . fn ( ) ,
37+ } ) ;
38+ }
39+
2440function App ( {
2541 enabled = true ,
2642 axis,
@@ -86,6 +102,17 @@ function App({
86102 ) ;
87103}
88104
105+ function ClientPointStoreTest ( {
106+ store,
107+ enabled = true ,
108+ } : {
109+ store : FloatingRootStore ;
110+ enabled ?: boolean ;
111+ } ) {
112+ useClientPoint ( store , { enabled } ) ;
113+ return null ;
114+ }
115+
89116test ( 'updates position from trigger props' , async ( ) => {
90117 render ( < App useTriggerProps /> ) ;
91118
@@ -264,6 +291,28 @@ test('cleans up window listener when closing or disabling', async () => {
264291 expectRect ( { x : 0 , y : 0 , width : 0 , height : 0 } ) ;
265292} ) ;
266293
294+ test ( 'clears virtual references on unmount without retaining a stale DOM reference' , async ( ) => {
295+ const reference = document . createElement ( 'button' ) ;
296+ const store = createRootStore ( reference ) ;
297+ const virtualReference = {
298+ getBoundingClientRect : ( ) => reference . getBoundingClientRect ( ) ,
299+ } ;
300+
301+ store . set ( 'positionReference' , virtualReference ) ;
302+
303+ const { rerender, unmount } = render ( < ClientPointStoreTest store = { store } /> ) ;
304+
305+ rerender ( < ClientPointStoreTest store = { store } enabled = { false } /> ) ;
306+ await flushMicrotasks ( ) ;
307+
308+ expect ( store . state . positionReference ) . toBe ( reference ) ;
309+
310+ store . set ( 'positionReference' , virtualReference ) ;
311+ unmount ( ) ;
312+
313+ expect ( store . state . positionReference ) . toBe ( null ) ;
314+ } ) ;
315+
267316test ( 'axis x' , async ( ) => {
268317 render ( < App axis = "x" /> ) ;
269318
0 commit comments