@@ -57,7 +57,7 @@ public void ShowPopupAsync_UsingNavigation_WithViewType_ShowsPopup()
5757 var popupService = ServiceProvider . GetRequiredService < IPopupService > ( ) ;
5858
5959 // Act
60- popupService . ShowPopup < ShortLivedMockPageViewModel > ( navigation ) ;
60+ popupService . ShowPopup < MockPageViewModel > ( navigation ) ;
6161
6262 // Assert
6363 Assert . Single ( navigation . ModalStack ) ;
@@ -76,22 +76,22 @@ public void ShowPopupAsync_UsingPage_WithViewType_ShowsPopup()
7676 }
7777
7878 // Act
79- popupService . ShowPopup < ShortLivedSelfClosingPopup > ( page ) ;
79+ popupService . ShowPopup < MockPopup > ( page ) ;
8080
8181 // Assert
8282 Assert . Single ( navigation . ModalStack ) ;
8383 Assert . IsType < PopupPage > ( navigation . ModalStack [ 0 ] ) ;
8484 }
8585
86- [ Fact ( Timeout = ( int ) TestDuration . Short ) ]
86+ [ Fact ( Timeout = ( int ) TestDuration . Long ) ]
8787 public async Task ShowPopupAsync_AwaitingShowPopupAsync_EnsurePreviousPopupClosed ( )
8888 {
8989 // Arrange
9090 var popupService = ServiceProvider . GetRequiredService < IPopupService > ( ) ;
9191
9292 // Act
9393 await popupService . ShowPopupAsync < ShortLivedSelfClosingPopup > ( navigation , PopupOptions . Empty , TestContext . Current . CancellationToken ) ;
94- await popupService . ShowPopupAsync < ShortLivedSelfClosingPopup > ( navigation , PopupOptions . Empty , TestContext . Current . CancellationToken ) ;
94+ await popupService . ShowPopupAsync < LongLivedSelfClosingPopup > ( navigation , PopupOptions . Empty , TestContext . Current . CancellationToken ) ;
9595
9696 // Assert
9797 Assert . Empty ( navigation . ModalStack ) ;
@@ -110,7 +110,7 @@ public async Task ShowPopupAsync_UsingPage_AwaitingShowPopupAsync_EnsurePrevious
110110
111111 // Act
112112 await popupService . ShowPopupAsync < ShortLivedMockPageViewModel > ( page , PopupOptions . Empty , TestContext . Current . CancellationToken ) ;
113- await popupService . ShowPopupAsync < ShortLivedMockPageViewModel > ( page , PopupOptions . Empty , TestContext . Current . CancellationToken ) ;
113+ await popupService . ShowPopupAsync < LongLivedMockPageViewModel > ( page , PopupOptions . Empty , TestContext . Current . CancellationToken ) ;
114114
115115 // Assert
116116 Assert . Empty ( navigation . ModalStack ) ;
@@ -124,7 +124,7 @@ public void ShowPopup_NavigationModalStackCountIncreases()
124124 Assert . Empty ( navigation . ModalStack ) ;
125125
126126 // Act
127- popupService . ShowPopup < ShortLivedMockPageViewModel > ( navigation , PopupOptions . Empty ) ;
127+ popupService . ShowPopup < MockPopup > ( navigation , PopupOptions . Empty ) ;
128128
129129 // Assert
130130 Assert . Single ( navigation . ModalStack ) ;
@@ -137,8 +137,8 @@ public void ShowPopup_MultiplePopupsDisplayed()
137137 var popupService = ServiceProvider . GetRequiredService < IPopupService > ( ) ;
138138
139139 // Act
140- popupService . ShowPopup < LongLivedMockPageViewModel > ( navigation , PopupOptions . Empty ) ;
141- popupService . ShowPopup < ShortLivedMockPageViewModel > ( navigation , PopupOptions . Empty ) ;
140+ popupService . ShowPopup < MockPopup > ( navigation , PopupOptions . Empty ) ;
141+ popupService . ShowPopup < MockPopup > ( navigation , PopupOptions . Empty ) ;
142142
143143 // Assert
144144 Assert . Equal ( 2 , navigation . ModalStack . Count ) ;
@@ -160,7 +160,7 @@ public void ShowPopupAsync_WithCustomOptions_AppliesOptions()
160160 } ;
161161
162162 // Act
163- popupService . ShowPopup < ShortLivedSelfClosingPopup > ( navigation , options ) ;
163+ popupService . ShowPopup < MockPopup > ( navigation , options ) ;
164164
165165 var popupPage = ( PopupPage ) navigation . ModalStack [ 0 ] ;
166166 var popupPageLayout = popupPage . Content ;
@@ -243,7 +243,6 @@ public async Task ShowPopupAsyncShouldValidateProperBindingContext()
243243 // Act
244244 await popupService . ShowPopupAsync < LongLivedMockPageViewModel , object ? > ( page . Navigation , PopupOptions . Empty , TestContext . Current . CancellationToken ) ;
245245
246-
247246 // Assert
248247 Assert . NotNull ( popupInstance . BindingContext ) ;
249248 Assert . IsType < LongLivedMockPageViewModel > ( popupInstance . BindingContext ) ;
@@ -534,40 +533,42 @@ protected override void HandlePopupClosed(object? sender, EventArgs e)
534533 }
535534}
536535
537- class LongLivedSelfClosingPopup : MockSelfClosingPopup
538- {
539- public LongLivedSelfClosingPopup ( LongLivedMockPageViewModel viewModel )
540- : base ( viewModel , TimeSpan . FromMilliseconds ( 1500 ) , "Long Lived" )
541- {
542- }
543- }
536+ sealed class LongLivedSelfClosingPopup ( LongLivedMockPageViewModel viewModel ) : MockSelfClosingPopup ( viewModel , TimeSpan . FromMilliseconds ( 1500 ) , "Long Lived" ) ;
544537
545- class ShortLivedSelfClosingPopup : MockSelfClosingPopup
546- {
547- public ShortLivedSelfClosingPopup ( ShortLivedMockPageViewModel viewModel )
548- : base ( viewModel , TimeSpan . FromMilliseconds ( 500 ) , "Short Lived" )
549- {
550- }
551- }
538+ sealed class ShortLivedSelfClosingPopup( ShortLivedMockPageViewModel viewModel ) : MockSelfClosingPopup ( viewModel , TimeSpan . FromMilliseconds ( 500 ) , "Short Lived" ) ;
552539
553- #pragma warning disable CA1001
554- class MockSelfClosingPopup : Popup < object ? > , IQueryAttributable
555- #pragma warning restore CA1001
540+ class MockSelfClosingPopup : Popup < object ? > , IQueryAttributable , IDisposable
556541{
557- readonly TimeSpan displayDuration ;
542+ readonly TaskCompletionSource popupClosedTCS = new ( ) ;
543+
558544 CancellationTokenSource ? cancellationTokenSource ;
559545
560- public MockSelfClosingPopup ( MockPageViewModel viewModel , TimeSpan displayDuration , object ? result = null )
546+ protected MockSelfClosingPopup ( MockPageViewModel viewModel , TimeSpan displayDuration , object ? result = null )
561547 {
562- this . displayDuration = displayDuration ;
563548 BackgroundColor = DefaultBackgroundColor ;
549+ DisplayDuration = displayDuration ;
564550 BindingContext = viewModel ;
565551 Result = result ;
566552 Opened += HandlePopupOpened ;
567553 Closed += HandlePopupClosed ;
568554 }
555+
556+ ~ MockSelfClosingPopup ( )
557+ {
558+ Dispose ( false ) ;
559+ }
560+
561+ public object ? Result { get ; }
562+
563+ public TimeSpan DisplayDuration { get ; }
569564
570565 public static Color DefaultBackgroundColor { get ; } = Colors . White ;
566+
567+ public void Dispose ( )
568+ {
569+ Dispose ( true ) ;
570+ GC . SuppressFinalize ( this ) ;
571+ }
571572
572573 protected virtual void HandlePopupClosed ( object ? sender , EventArgs e )
573574 {
@@ -585,7 +586,7 @@ protected virtual async void HandlePopupOpened(object? sender, EventArgs e)
585586
586587 Console . WriteLine ( $@ "{ DateTime . Now : O} HandlePopupOpened { BindingContext . GetType ( ) . Name } ") ;
587588
588- await Task . Delay ( displayDuration ) ;
589+ await Task . Delay ( DisplayDuration ) ;
589590
590591 if ( cancellationTokenSource ? . IsCancellationRequested is true )
591592 {
@@ -599,9 +600,17 @@ protected virtual async void HandlePopupOpened(object? sender, EventArgs e)
599600
600601 Console . WriteLine (
601602 $@ "{ DateTime . Now : O} Closed { BindingContext . GetType ( ) . Name } - { Application . Current ? . Windows [ 0 ] . Page ? . Navigation . ModalStack . Count } ") ;
603+
604+ popupClosedTCS . SetResult ( ) ;
605+ }
606+
607+ protected virtual void Dispose ( bool disposing )
608+ {
609+ if ( disposing )
610+ {
611+ cancellationTokenSource ? . Dispose ( ) ;
612+ }
602613 }
603-
604- public object ? Result { get ; }
605614
606615 void IQueryAttributable . ApplyQueryAttributes ( IDictionary < string , object > query )
607616 {
0 commit comments