Skip to content
Merged
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
128 changes: 128 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue34823.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 34823, "WebView on Windows Does Not Inherit App Theme", PlatformAffected.UWP)]
public class Issue34823 : NavigationPage
{
public Issue34823() : base(new Issue34823MainPage())
{
}

class Issue34823MainPage : ContentPage
{
public Issue34823MainPage()
{
BindingContext = this;
Title = "WebView Test";

var webButton = new Button
{
Text = "Switch to web page",
AutomationId = "WebButton",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation uses spaces here while surrounding lines use tabs.

HorizontalOptions = LayoutOptions.Center,
Margin = new Thickness(10)
};
webButton.Clicked += OnWebClicked;

var themeButton = new Button
{
Text = "Toggle Theme",
AutomationId = "ThemeButton",
HorizontalOptions = LayoutOptions.Center
};
themeButton.Clicked += OnThemeButtonClicked;

Content = new ScrollView
{
Content = new VerticalStackLayout
{
Padding = 30,
Spacing = 25,
Children =
{
webButton,
new HorizontalStackLayout
{
HorizontalOptions = LayoutOptions.Center,
Children =
{
themeButton
}
}
}
}
};
}

void OnThemeButtonClicked(object sender, EventArgs e)
{
Application.Current!.UserAppTheme = Dark ? AppTheme.Light : AppTheme.Dark;
}

async void OnWebClicked(object sender, EventArgs e)
{
var webView = new WebView();

var helpPage = new ContentPage
{
Title = "Web Page",
Content = new Grid
{
Children =
{
webView
}
}
};
helpPage.SetAppThemeColor(BackgroundColorProperty, Colors.White, Colors.Black);

helpPage.NavigatedTo += async (_, __) =>
{
webView.Source = new HtmlWebViewSource
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting Source inside NavigatedTo mixes navigation and content lifecycle. Consider setting webView.Source synchronously before PushAsync and exposing an AutomationId on the WebView so the test can WaitForElement for it before screenshotting.

{
Html = """
<html>
<head>
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
<title>Preparing Help</title>
<style>
@media (prefers-color-scheme: dark) {
html, body {
color: white;
background-color: black;
}
}

@media (prefers-color-scheme: light) {
html, body {
color: black;
background-color: white;
}
}
</style>
</head>
<body>
<center><h1>Text on a web page</h1></center>
</body>
</html>
"""
};
};
Comment on lines +78 to +109
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WebView content is assigned via the NavigatedTo event handler, which introduces timing variability (and the handler is marked async but doesn't await). Consider setting webView.Source before PushAsync (or using a non-async handler) to reduce race/flakiness and remove the unnecessary async event subscription.

Copilot uses AI. Check for mistakes.

await Navigation.PushAsync(helpPage);
}

public bool Dark
{
set
{
if (value != Dark)
{
Application.Current!.UserAppTheme = value ? AppTheme.Dark : AppTheme.Light;
}
}
get =>
Application.Current?.UserAppTheme == AppTheme.Dark ||
Application.Current?.RequestedTheme == AppTheme.Dark;
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#if TEST_FAILS_ON_ANDROID // This test fails on Android because of user app theme is not responsive in Hostapp.
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue34823 : _IssuesUITest
{
public Issue34823(TestDevice device) : base(device)
{
}

protected override bool ResetAfterEachTest => true;

public override string Issue => "WebView on Windows Does Not Inherit App Theme";

[Test]
[Category(UITestCategories.WebView)]
public void WebViewWithLightTheme()
{
App.WaitForElement("WebButton");
App.Tap("WebButton");
VerifyScreenshot();
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

App.Tap("WebButton") triggers PushAsync(helpPage) and starts WebView2 + HTML parsing — both async. VerifyScreenshot() is called immediately, so the screenshot is captured before the page navigation animation finishes and before HTML rendering completes. This is the most likely cause of the gate's 55.62% snapshot diff. Add App.WaitForElement for an in-page automation hook, or wait for navigation to complete before capturing.


[Test]
[Category(UITestCategories.WebView)]
public void WebViewWithDarkTheme()
{
App.WaitForElement("WebButton");
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test taps "ThemeButton" without first waiting for it to exist. For UI test stability, add a WaitForElement("ThemeButton") before tapping it (especially on slower devices/CI).

Suggested change
App.WaitForElement("WebButton");
App.WaitForElement("WebButton");
App.WaitForElement("ThemeButton");

Copilot uses AI. Check for mistakes.
App.Tap("ThemeButton");
App.Tap("WebButton");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as WebViewWithLightTheme: tap-then-screenshot has no wait. In addition, the theme toggle in OnThemeButtonClicked is propagated asynchronously through MAUI to WinUI's RequestedTheme. Without a small wait between Tap("ThemeButton") and Tap("WebButton"), the new WebView's ActualTheme may still be Light when UpdateBackground runs.

VerifyScreenshot();
}
}
#endif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion src/Core/src/Platform/Windows/WebViewExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using Microsoft.Maui.Graphics;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Web.WebView2.Core;

Expand Down Expand Up @@ -50,7 +51,12 @@ internal static void UpdateBackground(this WebView2 platformWebView, IWebView we
{
if (platformWebView.CoreWebView2 is not null)
{
platformWebView.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Auto;
platformWebView.CoreWebView2.Profile.PreferredColorScheme = platformWebView.ActualTheme switch
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UpdateBackground only runs from MapBackground (Background changes) and OnCoreWebView2Initialized (one-shot). When Application.UserAppTheme changes after the WebView is already initialized, the mapping is never re-applied — so an existing WebView will not follow runtime theme changes. Consider subscribing to platformWebView.ActualThemeChanged (or hooking the handler's window theme) and re-running the mapping when it fires.

{
ElementTheme.Dark => CoreWebView2PreferredColorScheme.Dark,
ElementTheme.Light => CoreWebView2PreferredColorScheme.Light,
_ => CoreWebView2PreferredColorScheme.Auto
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ActualTheme returns Default until the element is loaded into the visual tree. OnCoreWebView2Initialized may fire before the WebView's Loaded event, in which case this maps to Auto and silently reverts to the OS theme — the very bug this PR is fixing. Recommend deferring this until platformWebView.IsLoaded or hooking ActualThemeChanged.

};
}
}
}
Expand Down
Loading