@@ -58,6 +58,7 @@ jest.mock('../flyout.component', () => {
5858
5959// Shared mock functions - must be defined in module scope for Jest
6060const mockCloseFlyout = jest . fn ( ) ;
61+ const mockCloseAllFlyouts = jest . fn ( ) ;
6162
6263// Create mock state and functions once at module scope to avoid redundant object creation
6364const mockState = {
@@ -70,6 +71,7 @@ const mockFunctions = {
7071 dispatch : jest . fn ( ) ,
7172 addFlyout : jest . fn ( ) ,
7273 closeFlyout : mockCloseFlyout ,
74+ closeAllFlyouts : mockCloseAllFlyouts ,
7375 setActiveFlyout : jest . fn ( ) ,
7476 setFlyoutWidth : jest . fn ( ) ,
7577 goBack : jest . fn ( ) ,
@@ -152,7 +154,7 @@ describe('EuiManagedFlyout', () => {
152154 expect ( el ) . toHaveAttribute ( PROPERTY_LEVEL , LEVEL_MAIN ) ;
153155 } ) ;
154156
155- it ( 'calls the unregister callback prop when onClose ' , ( ) => {
157+ it ( 'calls closeAllFlyouts during cleanup when main flyout unmounts ' , ( ) => {
156158 const onClose = jest . fn ( ) ;
157159
158160 const { getByTestSubject, unmount } = renderInProvider (
@@ -166,12 +168,36 @@ describe('EuiManagedFlyout', () => {
166168 // The onClose should be called when the flyout is clicked
167169 expect ( onClose ) . toHaveBeenCalled ( ) ;
168170
171+ // The closeAllFlyouts should be called when the component unmounts (cleanup)
172+ act ( ( ) => {
173+ unmount ( ) ;
174+ } ) ;
175+
176+ expect ( mockCloseAllFlyouts ) . toHaveBeenCalled ( ) ;
177+ expect ( mockCloseFlyout ) . not . toHaveBeenCalled ( ) ;
178+ } ) ;
179+
180+ it ( 'calls closeFlyout during cleanup when child flyout unmounts' , ( ) => {
181+ const onClose = jest . fn ( ) ;
182+
183+ const { getByTestSubject, unmount } = renderInProvider (
184+ < EuiManagedFlyout id = "close-me" level = { LEVEL_CHILD } onClose = { onClose } />
185+ ) ;
186+
187+ act ( ( ) => {
188+ userEvent . click ( getByTestSubject ( 'managed-flyout' ) ) ;
189+ } ) ;
190+
191+ // The onClose should be called when the flyout is clicked
192+ expect ( onClose ) . toHaveBeenCalled ( ) ;
193+
169194 // The closeFlyout should be called when the component unmounts (cleanup)
170195 act ( ( ) => {
171196 unmount ( ) ;
172197 } ) ;
173198
174199 expect ( mockCloseFlyout ) . toHaveBeenCalledWith ( 'close-me' ) ;
200+ expect ( mockCloseAllFlyouts ) . not . toHaveBeenCalled ( ) ;
175201 } ) ;
176202
177203 it ( 'registers child flyout and sets data-level child' , ( ) => {
@@ -463,7 +489,7 @@ describe('EuiManagedFlyout', () => {
463489 expect ( onClose ) . not . toHaveBeenCalled ( ) ;
464490
465491 // Clear any calls from mount
466- mockCloseFlyout . mockClear ( ) ;
492+ mockCloseAllFlyouts . mockClear ( ) ;
467493
468494 // Unmount the component to trigger cleanup
469495 act ( ( ) => {
@@ -504,13 +530,13 @@ describe('EuiManagedFlyout', () => {
504530 } ) ;
505531
506532 describe ( 'manager state update ordering' , ( ) => {
507- it ( 'calls closeFlyout before parent onClose callback' , ( ) => {
533+ it ( 'calls closeAllFlyouts before parent onClose callback' , ( ) => {
508534 const onClose = jest . fn ( ) ;
509535 const callOrder : string [ ] = [ ] ;
510536
511537 // Track call order
512- mockCloseFlyout . mockImplementation ( ( ) => {
513- callOrder . push ( 'closeFlyout ' ) ;
538+ mockCloseAllFlyouts . mockImplementation ( ( ) => {
539+ callOrder . push ( 'closeAllFlyouts ' ) ;
514540 } ) ;
515541 onClose . mockImplementation ( ( ) => {
516542 callOrder . push ( 'onClose' ) ;
@@ -530,13 +556,13 @@ describe('EuiManagedFlyout', () => {
530556 userEvent . click ( getByTestSubject ( 'managed-flyout' ) ) ;
531557 } ) ;
532558
533- // Verify closeFlyout was called BEFORE onClose
534- expect ( callOrder ) . toEqual ( [ 'closeFlyout ' , 'onClose' ] ) ;
535- expect ( mockCloseFlyout ) . toHaveBeenCalledWith ( 'ordering-test' ) ;
559+ // Verify closeAllFlyouts was called BEFORE onClose
560+ expect ( callOrder ) . toEqual ( [ 'closeAllFlyouts ' , 'onClose' ] ) ;
561+ expect ( mockCloseAllFlyouts ) . toHaveBeenCalled ( ) ;
536562 expect ( onClose ) . toHaveBeenCalled ( ) ;
537563 } ) ;
538564
539- it ( 'prevents duplicate closeFlyout calls when closing via user interaction' , ( ) => {
565+ it ( 'prevents duplicate closeAllFlyouts calls when closing via user interaction' , ( ) => {
540566 const onClose = jest . fn ( ) ;
541567
542568 const { getByTestSubject, unmount } = renderInProvider (
@@ -549,23 +575,23 @@ describe('EuiManagedFlyout', () => {
549575 ) ;
550576
551577 // Clear any setup calls
552- mockCloseFlyout . mockClear ( ) ;
578+ mockCloseAllFlyouts . mockClear ( ) ;
553579
554580 // User closes the flyout
555581 act ( ( ) => {
556582 userEvent . click ( getByTestSubject ( 'managed-flyout' ) ) ;
557583 } ) ;
558584
559- // closeFlyout should be called once from the onClose handler
560- expect ( mockCloseFlyout ) . toHaveBeenCalledTimes ( 1 ) ;
585+ // closeAllFlyouts should be called once from the onClose handler
586+ expect ( mockCloseAllFlyouts ) . toHaveBeenCalledTimes ( 1 ) ;
561587
562588 // Manual, duplicate cleanup call
563589 act ( ( ) => {
564590 unmount ( ) ;
565591 } ) ;
566592
567593 // Should still be called only once total
568- expect ( mockCloseFlyout ) . toHaveBeenCalledTimes ( 1 ) ;
594+ expect ( mockCloseAllFlyouts ) . toHaveBeenCalledTimes ( 1 ) ;
569595 } ) ;
570596
571597 it ( 'handles cascade close correctly when main flyout closes' , ( ) => {
@@ -603,10 +629,51 @@ describe('EuiManagedFlyout', () => {
603629 } ) ;
604630
605631 // Manager should be notified to handle cascade close
606- expect ( mockCloseFlyout ) . toHaveBeenCalledWith ( 'main-flyout' ) ;
632+ expect ( mockCloseAllFlyouts ) . toHaveBeenCalled ( ) ;
607633 expect ( onCloseMain ) . toHaveBeenCalled ( ) ;
608634 } ) ;
609635
636+ it ( 'calls closeFlyout when closing a child flyout' , ( ) => {
637+ const onCloseMain = jest . fn ( ) ;
638+ const onCloseChild = jest . fn ( ) ;
639+
640+ // Simulate a main flyout with child
641+ const { container } = renderInProvider (
642+ < >
643+ < EuiManagedFlyout
644+ id = "main-flyout"
645+ level = { LEVEL_MAIN }
646+ onClose = { onCloseMain }
647+ flyoutMenuProps = { { title : 'Main Flyout' } }
648+ data-test-subj = "main-flyout-element"
649+ />
650+ < EuiManagedFlyout
651+ id = "child-flyout"
652+ level = { LEVEL_CHILD }
653+ onClose = { onCloseChild }
654+ data-test-subj = "child-flyout-element"
655+ />
656+ </ >
657+ ) ;
658+
659+ // Find the child flyout specifically
660+ const childFlyout = container . querySelector ( '[id="child-flyout"]' ) ;
661+ expect ( childFlyout ) . toBeInTheDocument ( ) ;
662+
663+ // Close the child flyout
664+ act ( ( ) => {
665+ if ( childFlyout ) {
666+ userEvent . click ( childFlyout ) ;
667+ }
668+ } ) ;
669+
670+ // Child flyouts should call closeFlyout, not closeAllFlyouts
671+ expect ( mockCloseFlyout ) . toHaveBeenCalledWith ( 'child-flyout' ) ;
672+ expect ( mockCloseFlyout ) . toHaveBeenCalledTimes ( 1 ) ;
673+ expect ( mockCloseAllFlyouts ) . not . toHaveBeenCalled ( ) ;
674+ expect ( onCloseChild ) . toHaveBeenCalled ( ) ;
675+ } ) ;
676+
610677 it ( 'uses flushSync to ensure synchronous state update before DOM cleanup' , ( ) => {
611678 const onClose = jest . fn ( ) ;
612679
@@ -621,7 +688,7 @@ describe('EuiManagedFlyout', () => {
621688
622689 // Clear any setup calls
623690 mockFlushSync . mockClear ( ) ;
624- mockCloseFlyout . mockClear ( ) ;
691+ mockCloseAllFlyouts . mockClear ( ) ;
625692
626693 // Trigger close via user interaction
627694 act ( ( ) => {
@@ -632,14 +699,14 @@ describe('EuiManagedFlyout', () => {
632699 expect ( mockFlushSync ) . toHaveBeenCalledTimes ( 1 ) ;
633700 expect ( mockFlushSync ) . toHaveBeenCalledWith ( expect . any ( Function ) ) ;
634701
635- // Verify closeFlyout was called (inside flushSync)
636- expect ( mockCloseFlyout ) . toHaveBeenCalledWith ( 'flush-sync-test' ) ;
702+ // Verify closeAllFlyouts was called (inside flushSync)
703+ expect ( mockCloseAllFlyouts ) . toHaveBeenCalled ( ) ;
637704
638705 // Verify onClose was called after the synchronous state update
639706 expect ( onClose ) . toHaveBeenCalled ( ) ;
640707 } ) ;
641708
642- it ( 'calls closeFlyout inside flushSync callback' , ( ) => {
709+ it ( 'calls closeAllFlyouts inside flushSync callback' , ( ) => {
643710 const onClose = jest . fn ( ) ;
644711 const callOrder : string [ ] = [ ] ;
645712
@@ -650,8 +717,8 @@ describe('EuiManagedFlyout', () => {
650717 callOrder . push ( 'flushSync-end' ) ;
651718 } ) ;
652719
653- mockCloseFlyout . mockImplementation ( ( ) => {
654- callOrder . push ( 'closeFlyout ' ) ;
720+ mockCloseAllFlyouts . mockImplementation ( ( ) => {
721+ callOrder . push ( 'closeAllFlyouts ' ) ;
655722 } ) ;
656723
657724 onClose . mockImplementation ( ( ) => {
@@ -675,10 +742,10 @@ describe('EuiManagedFlyout', () => {
675742 userEvent . click ( getByTestSubject ( 'managed-flyout' ) ) ;
676743 } ) ;
677744
678- // Verify closeFlyout is called INSIDE flushSync, and onClose is called AFTER
745+ // Verify closeAllFlyouts is called INSIDE flushSync, and onClose is called AFTER
679746 expect ( callOrder ) . toEqual ( [
680747 'flushSync-start' ,
681- 'closeFlyout ' ,
748+ 'closeAllFlyouts ' ,
682749 'flushSync-end' ,
683750 'onClose' ,
684751 ] ) ;
0 commit comments