Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue33287.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using System.Threading.Tasks;
using System.ComponentModel;

namespace Maui.Controls.Sample.Issues;

Expand All @@ -17,6 +17,12 @@ public Issue33287MainPage()
{
Title = "Issue 33287";

var statusLabel = new Label
{
Text = "Waiting for alert request",
AutomationId = "AlertStatusLabel"
};

Content = new VerticalStackLayout
{
Padding = 20,
Expand All @@ -28,23 +34,26 @@ public Issue33287MainPage()
Text = "Navigate to Second Page",
AutomationId = "NavigateButton",
Command = new Command(async () =>
await Navigation.PushAsync(new Issue33287SecondPage()))
await Navigation.PushAsync(new Issue33287SecondPage(status =>
statusLabel.Text = status)))
},
new Label
{
Text = "MainPage",
AutomationId = "MainPageLabel"
}
},
statusLabel
}
};
}
}

public class Issue33287SecondPage : ContentPage
{
public Issue33287SecondPage()
public Issue33287SecondPage(Action<string> updateStatus)
{
Title = "Second Page";
PropertyChanged += OnPropertyChanged;

Content = new VerticalStackLayout
{
Expand All @@ -59,20 +68,18 @@ public Issue33287SecondPage()
}
}
};
}

protected override async void OnAppearing()
{
base.OnAppearing();
async void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != nameof(Window) || Window is not null)
return;

// Wait long enough for the user/test to navigate back
#if MACCATALYST
await Task.Delay(4000);
#else
await Task.Delay(2000);
#endif
PropertyChanged -= OnPropertyChanged;
updateStatus("Page detached");

// Without the fix this throws NullReferenceException and crashes the app
await DisplayAlertAsync("Test Alert", "This alert was delayed", "OK");
// Request the alert before handler teardown changes IsPlatformEnabled.
await DisplayAlertAsync("Test Alert", "This alert was delayed", "OK");
updateStatus("Alert request completed");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ public void DisplayAlertAsyncShouldNotCrashWhenPageUnloaded()
App.WaitForElement("GoBackButton");
App.Tap("GoBackButton");

// Back on main pagewait for the delayed DisplayAlertAsync to fire.
// Without the fix the NRE crashes the app and this element becomes unreachable.
// Back on the main page, wait until the detached page's alert request completes.
// Without the fix the NRE crashes the app and this status is never updated.
App.WaitForElement("MainPageLabel");
System.Threading.Thread.Sleep(3000);

// Verify the app is still alive and responsive after the alert fired on the detached page.
Assert.That(
App.WaitForTextToBePresentInElement(
"AlertStatusLabel",
"Alert request completed",
timeout: TimeSpan.FromSeconds(10)),
Is.True,
"The detached page's alert request should complete");

// Verify the app is still alive and responsive after the alert request on the detached page.
// Without the fix the app process is dead and this call will throw/timeout.
Assert.That(App.FindElement("MainPageLabel").GetText(), Is.EqualTo("MainPage"),
"App should remain responsive after DisplayAlertAsync on an unloaded page");
Expand Down
Loading