[UI automation test] Add basic tests case for powerrename module. (#40393)

<!-- 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
1. Add command args support in ui test core
2. Add command line parse logic in powerrename
3. Add some test cases.

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

- [ ] **Closes:** #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **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

---------

Co-authored-by: Yu Leng <yuleng@microsoft.com>
This commit is contained in:
Yu Leng
2025-07-09 14:32:40 +08:00
committed by GitHub
parent c4922f1b30
commit 802bc3bd34
12 changed files with 568 additions and 138 deletions

View File

@@ -31,6 +31,7 @@ namespace Microsoft.PowerToys.UITest
Hosts,
Runner,
Workspaces,
PowerRename,
}
/// <summary>
@@ -97,6 +98,7 @@ namespace Microsoft.PowerToys.UITest
[PowerToysModule.Hosts] = "Hosts File Editor",
[PowerToysModule.Runner] = "PowerToys",
[PowerToysModule.Workspaces] = "Workspaces Editor",
[PowerToysModule.PowerRename] = "PowerRename",
};
// Exe start path for the module if it exists.
@@ -107,6 +109,7 @@ namespace Microsoft.PowerToys.UITest
[PowerToysModule.Hosts] = @"\..\..\..\WinUI3Apps\PowerToys.Hosts.exe",
[PowerToysModule.Runner] = @"\..\..\..\PowerToys.exe",
[PowerToysModule.Workspaces] = @"\..\..\..\PowerToys.WorkspacesEditor.exe",
[PowerToysModule.PowerRename] = @"\..\..\..\WinUI3Apps\PowerToys.PowerRename.exe",
};
}

View File

@@ -5,7 +5,9 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
@@ -33,11 +35,13 @@ namespace Microsoft.PowerToys.UITest
private Process? runner;
private PowerToysModule scope;
private string[]? commandLineArgs;
[UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "<Pending>")]
public SessionHelper(PowerToysModule scope)
public SessionHelper(PowerToysModule scope, string[]? commandLineArgs = null)
{
this.scope = scope;
this.commandLineArgs = commandLineArgs;
this.sessionPath = ModuleConfigData.Instance.GetModulePath(scope);
this.locationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
@@ -66,7 +70,7 @@ namespace Microsoft.PowerToys.UITest
{
this.ExitExe(this.locationPath + this.sessionPath);
this.StartExe(this.locationPath + this.sessionPath);
this.StartExe(this.locationPath + this.sessionPath, this.commandLineArgs);
Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null.");
@@ -109,18 +113,27 @@ namespace Microsoft.PowerToys.UITest
/// Starts a new exe and takes control of it.
/// </summary>
/// <param name="appPath">The path to the application executable.</param>
public void StartExe(string appPath)
/// <param name="args">Optional command line arguments to pass to the application.</param>
public void StartExe(string appPath, string[]? args = null)
{
var opts = new AppiumOptions();
opts.AddAdditionalCapability("app", appPath);
// if we want to start settings, we need to use the runner exe to open settings
if (scope == PowerToysModule.PowerToysSettings)
if (args != null && args.Length > 0)
{
TryLaunchPowerToysSettings(opts);
}
else
{
opts.AddAdditionalCapability("app", appPath);
// Build command line arguments string
string argsString = string.Join(" ", args.Select(arg =>
{
// Quote arguments that contain spaces
if (arg.Contains(' '))
{
return $"\"{arg}\"";
}
return arg;
}));
opts.AddAdditionalCapability("appArguments", argsString);
}
this.Driver = NewWindowsDriver(opts);
@@ -174,7 +187,7 @@ namespace Microsoft.PowerToys.UITest
/// <summary>
/// Starts a new exe and takes control of it.
/// </summary>
/// <param name="info">The path to the application executable.</param>
/// <param name="info">The AppiumOptions for the application.</param>
private WindowsDriver<WindowsElement> NewWindowsDriver(AppiumOptions info)
{
// Create driver with retry
@@ -229,7 +242,7 @@ namespace Microsoft.PowerToys.UITest
public void RestartScopeExe()
{
ExitScopeExe();
StartExe(locationPath + sessionPath);
StartExe(locationPath + sessionPath, this.commandLineArgs);
}
public WindowsDriver<WindowsElement> GetRoot()

View File

@@ -26,11 +26,12 @@ namespace Microsoft.PowerToys.UITest
private readonly PowerToysModule scope;
private readonly WindowSize size;
private readonly string[]? commandLineArgs;
private SessionHelper? sessionHelper;
private System.Threading.Timer? screenshotTimer;
private string? screenshotDirectory;
public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, WindowSize size = WindowSize.UnSpecified)
public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, WindowSize size = WindowSize.UnSpecified, string[]? commandLineArgs = null)
{
this.IsInPipeline = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("platform"));
Console.WriteLine($"Running tests on platform: {Environment.GetEnvironmentVariable("platform")}");
@@ -45,6 +46,7 @@ namespace Microsoft.PowerToys.UITest
this.scope = scope;
this.size = size;
this.commandLineArgs = commandLineArgs;
}
/// <summary>
@@ -66,7 +68,7 @@ namespace Microsoft.PowerToys.UITest
System.Windows.Forms.SendKeys.SendWait("{ESC}");
}
this.sessionHelper = new SessionHelper(scope).Init();
this.sessionHelper = new SessionHelper(scope, commandLineArgs).Init();
this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver(), scope, size);
}