Skip to content

Commit 778ac31

Browse files
StephaneDelcroixPureWeen
authored andcommitted
Add Device Tests for BlazorWebView OnBackPressed handler registration
Tests verify that BlazorWebViewHandler on Android: 1. Registers OnBackPressed lifecycle event handler in ConnectHandler 2. Properly cleans up the handler in DisconnectHandler Related to: #32767
1 parent 14d7d07 commit 778ac31

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Microsoft.AspNetCore.Components.WebView.Maui;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Microsoft.Maui.LifecycleEvents;
6+
using Xunit;
7+
8+
namespace Microsoft.Maui.MauiBlazorWebView.DeviceTests.Elements;
9+
10+
public partial class BlazorWebViewTests
11+
{
12+
#if ANDROID
13+
/// <summary>
14+
/// Verifies that BlazorWebViewHandler registers an OnBackPressed lifecycle event handler
15+
/// when connected on Android. This handler is essential for proper back navigation within
16+
/// the BlazorWebView on Android 13+ with predictive back gestures.
17+
/// See: https://github.com/dotnet/maui/issues/32767
18+
/// </summary>
19+
[Fact]
20+
public async Task BlazorWebViewRegistersOnBackPressedHandler()
21+
{
22+
EnsureHandlerCreated(additionalCreationActions: appBuilder =>
23+
{
24+
appBuilder.Services.AddMauiBlazorWebView();
25+
});
26+
27+
var bwv = new BlazorWebViewWithCustomFiles
28+
{
29+
HostPage = "wwwroot/index.html",
30+
CustomFiles = new Dictionary<string, string>
31+
{
32+
{ "index.html", TestStaticFilesContents.DefaultMauiIndexHtmlContent },
33+
},
34+
};
35+
bwv.RootComponents.Add(new RootComponent { ComponentType = typeof(MauiBlazorWebView.DeviceTests.Components.NoOpComponent), Selector = "#app", });
36+
37+
await InvokeOnMainThreadAsync(async () =>
38+
{
39+
var bwvHandler = CreateHandler<BlazorWebViewHandler>(bwv);
40+
var platformWebView = bwvHandler.PlatformView;
41+
await WebViewHelpers.WaitForWebViewReady(platformWebView);
42+
43+
// Get the lifecycle event service and verify OnBackPressed handler is registered
44+
var lifecycleService = MauiContext.Services.GetService<ILifecycleEventService>() as LifecycleEventService;
45+
Assert.NotNull(lifecycleService);
46+
47+
// Verify the OnBackPressed event has been registered
48+
Assert.True(lifecycleService.ContainsEvent(nameof(AndroidLifecycle.OnBackPressed)),
49+
"BlazorWebViewHandler should register an OnBackPressed lifecycle event handler on Android");
50+
});
51+
}
52+
53+
/// <summary>
54+
/// Verifies that BlazorWebViewHandler properly cleans up the OnBackPressed lifecycle event handler
55+
/// when disconnected. This prevents memory leaks and ensures proper cleanup.
56+
/// See: https://github.com/dotnet/maui/issues/32767
57+
/// </summary>
58+
[Fact]
59+
public async Task BlazorWebViewCleansUpOnBackPressedHandlerOnDisconnect()
60+
{
61+
EnsureHandlerCreated(additionalCreationActions: appBuilder =>
62+
{
63+
appBuilder.Services.AddMauiBlazorWebView();
64+
});
65+
66+
var bwv = new BlazorWebViewWithCustomFiles
67+
{
68+
HostPage = "wwwroot/index.html",
69+
CustomFiles = new Dictionary<string, string>
70+
{
71+
{ "index.html", TestStaticFilesContents.DefaultMauiIndexHtmlContent },
72+
},
73+
};
74+
bwv.RootComponents.Add(new RootComponent { ComponentType = typeof(MauiBlazorWebView.DeviceTests.Components.NoOpComponent), Selector = "#app", });
75+
76+
await InvokeOnMainThreadAsync(async () =>
77+
{
78+
var bwvHandler = CreateHandler<BlazorWebViewHandler>(bwv);
79+
var platformWebView = bwvHandler.PlatformView;
80+
await WebViewHelpers.WaitForWebViewReady(platformWebView);
81+
82+
var lifecycleService = MauiContext.Services.GetService<ILifecycleEventService>() as LifecycleEventService;
83+
Assert.NotNull(lifecycleService);
84+
85+
// Verify handler is registered after connect
86+
Assert.True(lifecycleService.ContainsEvent(nameof(AndroidLifecycle.OnBackPressed)),
87+
"OnBackPressed handler should be registered after ConnectHandler");
88+
89+
// Count the handlers before disconnect
90+
var handlersBefore = lifecycleService.GetEventDelegates<AndroidLifecycle.OnBackPressed>(nameof(AndroidLifecycle.OnBackPressed));
91+
int countBefore = 0;
92+
foreach (var _ in handlersBefore)
93+
countBefore++;
94+
95+
// Disconnect the handler by setting the BlazorWebView's Handler to null
96+
// This triggers DisconnectHandler internally
97+
bwv.Handler = null;
98+
99+
// Count the handlers after disconnect
100+
var handlersAfter = lifecycleService.GetEventDelegates<AndroidLifecycle.OnBackPressed>(nameof(AndroidLifecycle.OnBackPressed));
101+
int countAfter = 0;
102+
foreach (var _ in handlersAfter)
103+
countAfter++;
104+
105+
// Verify the handler count decreased (cleanup happened)
106+
Assert.True(countAfter < countBefore,
107+
$"OnBackPressed handler should be removed after DisconnectHandler. Before: {countBefore}, After: {countAfter}");
108+
});
109+
}
110+
#endif
111+
}

0 commit comments

Comments
 (0)