@@ -179,6 +179,81 @@ describe('Trigger.Basic', () => {
179179 trigger ( document , '.rc-trigger-popup' , 'pointerEnter' ) ;
180180 expect ( isPopupHidden ( ) ) . toBeFalsy ( ) ;
181181 } ) ;
182+
183+ it ( 'temporarily hides while disabled and restores without mouse leave' , ( ) => {
184+ const onOpenChange = jest . fn ( ) ;
185+ const Demo = ( { disabled = false } ) => (
186+ < Trigger
187+ action = { [ 'hover' ] }
188+ disabled = { disabled }
189+ onOpenChange = { onOpenChange }
190+ popup = { < strong > trigger</ strong > }
191+ >
192+ < div className = "target" > hover</ div >
193+ </ Trigger >
194+ ) ;
195+
196+ const { container, rerender } = render ( < Demo /> ) ;
197+
198+ trigger ( container , '.target' , 'mouseEnter' ) ;
199+ expect ( isPopupHidden ( ) ) . toBeFalsy ( ) ;
200+ expect ( onOpenChange ) . toHaveBeenCalledWith ( true ) ;
201+ onOpenChange . mockReset ( ) ;
202+
203+ rerender ( < Demo disabled /> ) ;
204+ expect ( isPopupHidden ( ) ) . toBeTruthy ( ) ;
205+ expect ( onOpenChange ) . not . toHaveBeenCalled ( ) ;
206+
207+ rerender ( < Demo /> ) ;
208+ expect ( isPopupHidden ( ) ) . toBeFalsy ( ) ;
209+ expect ( onOpenChange ) . not . toHaveBeenCalled ( ) ;
210+ } ) ;
211+
212+ it ( 'does not restore after mouse leave while disabled' , ( ) => {
213+ const Demo = ( { disabled = false } ) => (
214+ < Trigger
215+ action = { [ 'hover' ] }
216+ disabled = { disabled }
217+ popup = { < strong > trigger</ strong > }
218+ >
219+ < div className = "target" > hover</ div >
220+ </ Trigger >
221+ ) ;
222+
223+ const { container, rerender } = render ( < Demo /> ) ;
224+
225+ trigger ( container , '.target' , 'mouseEnter' ) ;
226+ rerender ( < Demo disabled /> ) ;
227+ trigger ( container , '.target' , 'mouseLeave' ) ;
228+ rerender ( < Demo /> ) ;
229+
230+ expect ( isPopupHidden ( ) ) . toBeTruthy ( ) ;
231+ } ) ;
232+
233+ it ( 'ignores pending and direct show actions while disabled' , ( ) => {
234+ const Demo = ( { disabled = false } ) => (
235+ < Trigger
236+ action = "hover"
237+ disabled = { disabled }
238+ mouseEnterDelay = { 1 }
239+ popup = { < strong > trigger</ strong > }
240+ >
241+ < div className = "target" > hover</ div >
242+ </ Trigger >
243+ ) ;
244+
245+ const { container, rerender } = render ( < Demo /> ) ;
246+ const target = container . querySelector ( '.target' ) ;
247+
248+ fireEvent . mouseEnter ( target ) ;
249+ rerender ( < Demo disabled /> ) ;
250+ act ( ( ) => jest . runAllTimers ( ) ) ;
251+ expect ( document . querySelector ( '.rc-trigger-popup' ) ) . toBeFalsy ( ) ;
252+
253+ fireEvent . mouseEnter ( target ) ;
254+ act ( ( ) => jest . runAllTimers ( ) ) ;
255+ expect ( document . querySelector ( '.rc-trigger-popup' ) ) . toBeFalsy ( ) ;
256+ } ) ;
182257 } ) ;
183258
184259 it ( 'contextMenu works' , ( ) => {
@@ -1009,7 +1084,62 @@ describe('Trigger.Basic', () => {
10091084 expect ( document . querySelector ( '.rc-trigger-popup' ) ) . toBeTruthy ( ) ;
10101085 } ) ;
10111086
1087+ it ( 'temporarily hides a controlled popup without changing its open state' , ( ) => {
1088+ const onOpenChange = jest . fn ( ) ;
1089+ const Demo = ( { disabled = false } ) => (
1090+ < Trigger
1091+ disabled = { disabled }
1092+ onOpenChange = { onOpenChange }
1093+ popup = { < strong > trigger</ strong > }
1094+ popupVisible
1095+ >
1096+ { ( { open } ) => < div data-open = { open } /> }
1097+ </ Trigger >
1098+ ) ;
1099+
1100+ const { container, rerender } = render ( < Demo /> ) ;
1101+
1102+ expect ( container . firstChild ) . toHaveAttribute ( 'data-open' , 'true' ) ;
1103+ expect ( isPopupHidden ( ) ) . toBeFalsy ( ) ;
1104+
1105+ rerender ( < Demo disabled /> ) ;
1106+ expect ( container . firstChild ) . toHaveAttribute ( 'data-open' , 'false' ) ;
1107+ expect ( isPopupHidden ( ) ) . toBeTruthy ( ) ;
1108+
1109+ rerender ( < Demo /> ) ;
1110+ expect ( container . firstChild ) . toHaveAttribute ( 'data-open' , 'true' ) ;
1111+ expect ( isPopupHidden ( ) ) . toBeFalsy ( ) ;
1112+ expect ( onOpenChange ) . not . toHaveBeenCalled ( ) ;
1113+ } ) ;
1114+
10121115 describe ( 'click window to hide' , ( ) => {
1116+ it ( 'clears the open state while disabled' , async ( ) => {
1117+ const Demo = ( { disabled = false } ) => (
1118+ < Trigger
1119+ action = "click"
1120+ disabled = { disabled }
1121+ popup = { < strong > trigger</ strong > }
1122+ >
1123+ < div className = "target" />
1124+ </ Trigger >
1125+ ) ;
1126+
1127+ const { container, rerender } = render ( < Demo /> ) ;
1128+
1129+ fireEvent . click ( container . querySelector ( '.target' ) ) ;
1130+ await awaitFakeTimer ( ) ;
1131+ expect ( isPopupHidden ( ) ) . toBeFalsy ( ) ;
1132+
1133+ rerender ( < Demo disabled /> ) ;
1134+ expect ( isPopupHidden ( ) ) . toBeTruthy ( ) ;
1135+
1136+ fireEvent . mouseDown ( document . body ) ;
1137+ await awaitFakeTimer ( ) ;
1138+ rerender ( < Demo /> ) ;
1139+
1140+ expect ( isPopupHidden ( ) ) . toBeTruthy ( ) ;
1141+ } ) ;
1142+
10131143 it ( 'should hide' , async ( ) => {
10141144 const onOpenChange = jest . fn ( ) ;
10151145 const onPopupVisibleChange = jest . fn ( ) ;
0 commit comments