[UI Tests] Fix incorrect Settings Page launch method in UI test framework (#40367)

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
### Root Cause
The UI test framework previously attempted to launch
PowerToys.Settings.exe directly.
However, this bypasses the PowerToys Runner, which is required for
proper interaction
and communication between runner.

### Fix
1. This change updates the launch mechanism to start PowerToys through
the Runner
with the appropriate argument ("--open-settings").
2. Prevents the Debug dialog from appearing in test runs

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] **Closes:** #xxx
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
This commit is contained in:
leileizhang 2025-07-07 12:58:49 +08:00 committed by GitHub
parent 7772bfb777
commit a64de74f3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 36 deletions

View File

@ -9,6 +9,7 @@ using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows; using OpenQA.Selenium.Appium.Windows;
using static Microsoft.PowerToys.UITest.WindowHelper;
namespace Microsoft.PowerToys.UITest namespace Microsoft.PowerToys.UITest
{ {
@ -41,18 +42,6 @@ namespace Microsoft.PowerToys.UITest
this.locationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); this.locationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
CheckWinAppDriverAndRoot(); CheckWinAppDriverAndRoot();
var runnerProcessInfo = new ProcessStartInfo
{
FileName = locationPath + this.runnerPath,
Verb = "runas",
};
if (scope == PowerToysModule.PowerToysSettings)
{
this.ExitExe(runnerProcessInfo.FileName);
this.runner = Process.Start(runnerProcessInfo);
}
} }
/// <summary> /// <summary>
@ -76,6 +65,7 @@ namespace Microsoft.PowerToys.UITest
public SessionHelper Init() public SessionHelper Init()
{ {
this.ExitExe(this.locationPath + this.sessionPath); this.ExitExe(this.locationPath + this.sessionPath);
this.StartExe(this.locationPath + this.sessionPath); this.StartExe(this.locationPath + this.sessionPath);
Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null."); Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null.");
@ -89,19 +79,6 @@ namespace Microsoft.PowerToys.UITest
public void Cleanup() public void Cleanup()
{ {
ExitScopeExe(); ExitScopeExe();
try
{
if (this.scope == PowerToysModule.PowerToysSettings)
{
runner?.Kill();
runner?.WaitForExit(); // Optional: Wait for the process to exit
}
}
catch (Exception ex)
{
// Handle exceptions if needed
Debug.WriteLine($"Exception during Cleanup: {ex.Message}");
}
} }
/// <summary> /// <summary>
@ -135,10 +112,65 @@ namespace Microsoft.PowerToys.UITest
public void StartExe(string appPath) public void StartExe(string appPath)
{ {
var opts = new AppiumOptions(); var opts = new AppiumOptions();
// if we want to start settings, we need to use the runner exe to open settings
if (scope == PowerToysModule.PowerToysSettings)
{
TryLaunchPowerToysSettings(opts);
}
else
{
opts.AddAdditionalCapability("app", appPath); opts.AddAdditionalCapability("app", appPath);
}
this.Driver = NewWindowsDriver(opts); this.Driver = NewWindowsDriver(opts);
} }
private void TryLaunchPowerToysSettings(AppiumOptions opts)
{
CheckWinAppDriverAndRoot();
var runnerProcessInfo = new ProcessStartInfo
{
FileName = locationPath + this.runnerPath,
Verb = "runas",
Arguments = "--open-settings",
};
this.ExitExe(runnerProcessInfo.FileName);
this.runner = Process.Start(runnerProcessInfo);
Thread.Sleep(5000);
if (root != null)
{
const int maxRetries = 3;
const int delayMs = 5000;
var windowName = "PowerToys Settings";
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
var settingsWindow = ApiHelper.FindDesktopWindowHandler(
new[] { windowName, AdministratorPrefix + windowName });
if (settingsWindow.Count > 0)
{
var hexHwnd = settingsWindow[0].HWnd.ToString("x");
opts.AddAdditionalCapability("appTopLevelWindow", hexHwnd);
return;
}
if (attempt < maxRetries)
{
Thread.Sleep(delayMs);
}
else
{
throw new TimeoutException("Failed to find PowerToys Settings window after multiple attempts.");
}
}
}
}
/// <summary> /// <summary>
/// Starts a new exe and takes control of it. /// Starts a new exe and takes control of it.
/// </summary> /// </summary>
@ -176,6 +208,19 @@ namespace Microsoft.PowerToys.UITest
public void ExitScopeExe() public void ExitScopeExe()
{ {
ExitExe(sessionPath); ExitExe(sessionPath);
try
{
if (this.scope == PowerToysModule.PowerToysSettings)
{
runner?.Kill();
runner?.WaitForExit(); // Optional: Wait for the process to exit
}
}
catch (Exception ex)
{
// Handle exceptions if needed
Debug.WriteLine($"Exception during Cleanup: {ex.Message}");
}
} }
/// <summary> /// <summary>

View File

@ -68,16 +68,6 @@ namespace Microsoft.PowerToys.UITest
this.sessionHelper = new SessionHelper(scope).Init(); this.sessionHelper = new SessionHelper(scope).Init();
this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver(), scope, size); this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver(), scope, size);
if (this.scope == PowerToysModule.PowerToysSettings)
{
// close Debug warning dialog if any
// Such debug warning dialog seems only appear in PowerToys Settings
if (this.FindAll("DEBUG").Count > 0)
{
this.Find("DEBUG").Find<Button>("Close").Click();
}
}
} }
/// <summary> /// <summary>