[Settings] Add navigation smoke test using winapp CLI (no WinAppDriver)#48414
[Settings] Add navigation smoke test using winapp CLI (no WinAppDriver)#48414crutkas wants to merge 2 commits into
Conversation
Adds a brand-new test project (src/settings-ui/WinAppCli.UITest-Settings/) that drives the Settings shell through the Windows App Development CLI's UI Automation surface (winapp ui invoke / wait-for / etc.). One TestMethod row per NavigationViewItem covers every shell entry; assertion is that PowerToys.Settings.exe stays alive after each click. This is the runtime counterpart to the unit tests on ShellViewModel.HandleNavigationFailure (microsoft#48410). The unit tests cannot reach the FailFast path because NavigationFailedEventArgs is a sealed WinRT type; this smoke test is what would catch a regression that re-introduces 'throw from Frame_NavigationFailed' or any module page whose constructor throws. Deliberately does NOT use Appium.WebDriver / WinAppDriver - exists as a standalone project alongside the existing UITest-Settings project. Supersedes the closed microsoft#48411 which used the older stack. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
- Add 'winapp' and 'winappcli' to .github/actions/spell-check/expect.txt (the project and CLI name; preserves alphabetical order alongside the existing 'winappsdk' entry). - Reword the comment above the post-invoke Thread.Sleep in NavigationSmokeTests.cs so it no longer matches the line_forbidden.patterns rule about consecutive articles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Pushed a follow-up commit (12c3a78) addressing the spelling check:
|
|
Pushed a follow-up commit (12c3a78) addressing the spelling check:
|
|
closing out as this work was absorbed into #48467 |
Why this exists
ShellViewModel.HandleNavigationFailureandShellViewModel.GetPageDisplayName(the helpers introduced/expanded in #48409 / #48410) cover the pure-logic half of the navigation-failure regression. They cannot reach the original FailFast path:NavigationFailedEventArgsis a sealed WinRT projection that can't be constructed from MSTest, so any regression that re-introduces "page constructor throws → unhandled inFrame_NavigationFailed→RoFailFast" sails right past the unit tests.This PR adds the runtime counterpart: a smoke test that drives a real Settings shell and asserts the process is still alive after clicking every NavigationViewItem.
Framework
This test deliberately does not use
Appium.WebDriver/ WinAppDriver — the existingsrc\settings-ui\UITest-Settingsproject's stack. Instead it drives the running Settings shell through the Windows App Development CLI (winapp), which exposes a UI Automation surface (winapp ui invoke|wait-for|screenshot|inspect|search|get-property|click|set-value|...) against any running app — WinUI 3, WPF, WinForms, Win32, Electron. No daemon, no driver process, no Appium server.winget install Microsoft.winappcli(or thesetup-WinAppClipipeline task)winappis currently in public preview; this PR introduces it as an opt-in test dependency in a brand-new project so it does not affect the existing Appium-based tests or anything else. If the maintainers would rather keep WinAppDriver as the only sanctioned UI test path, this PR can be closed without touching anything else in the repo.Project layout
New project:
src/settings-ui/WinAppCli.UITest-Settings/WinAppCli.UITest-Settings.csproj— plain MSTest. NoAppium.WebDriverreference. Mirrors the existing UI test csproj conventions (<RunVSTest>false</RunVSTest>,<OutputPath>$(RepoRoot)$(Platform)\$(Configuration)\tests\WinAppCli.UITests-Settings\</OutputPath>).WinAppCli.cs— thin wrapper aroundProcess.Start("winapp", "ui …")withInvoke,WaitFor,Screenshot, andIsAvailable. Returns a record with exit code + stdout/stderr + aDescribeFailure()helper for clean assertion messages.SettingsHost.cs— owns thePowerToys.Settings.exeprocess for the class. Locates the exe in either an installed PowerToys path or alongside the test assembly (dev build), and waits forMainWindowHandlebefore returning.NavigationSmokeTests.cs— one[TestMethod](parameterized via[DynamicData]) that produces a discrete test result per nav item. Each row clicks one item viawinapp ui invoke <AutomationId> -a <pid>(parent groups are expanded on first encounter), and then assertsPowerToys.Settings.exehas not exited.Splitting the helper into one file each keeps the test source itself small — the alternative reference shape (one long PowerShell script that pipes
winapp ui …calls together) doesn't fit cleanly into how PowerToys discovers and runs its existing MSTest UI test projects.Why one
[TestMethod]per nav item, parameterized via[DynamicData]MeasureToolNavItemregresses, the report says so by name.[ClassInitialize]/[ClassCleanup]launches Settings exactly once and tears it down at the end — every row exercises navigation against the same process so the "did the process die" check is meaningful.AutomationId-based selectors
Every selector is the AutomationId already attached in
ShellPage.xaml(e.g.DashboardNavItem,FancyZonesNavItem,SystemToolsNavItem). This keeps the test localization-independent — display strings change with the user's MUI language but AutomationIds do not.Parent group items (
SystemToolsNavItem,WindowingAndLayoutsNavItem,InputOutputNavItem,FileManagementNavItem,AdvancedNavItem) haveSelectsOnInvoked="False"and only expand on click.winapp ui invoketriesInvokePattern,TogglePattern,SelectionItemPattern, thenExpandCollapsePatternin order, so the sameInvokecall works for both navigation-y leaves and expand-y groups.Pipeline notes
/settings-ui/Tests/slnx folder alongsideSettings.UI.UnitTests.csproj.<RunVSTest>false</RunVSTest>matches every other UI test project in the repo — the test doesn't run in a regularMSBuildand only fires in the UI test pipeline.doc/devdocs/development/ui-tests.md) selects projects via theuiTestModulesparameter — this csproj's assembly name isWinAppCli.UITests-Settings, which is what would go in that list to opt in.winapponPATH. The pipeline can install it withwinget install Microsoft.winappclior thesetup-WinAppCliaction.[ClassInitialize]callsWinAppCli.IsAvailable()and fails the whole class with a useful error message (rather than producing 30 opaque per-test failures) if the CLI is missing.How this was validated locally
0 Warning(s), 0 Error(s)) againstnet10.0-windowsMSTest. The PowerToys-side restore is currently failing on my dev box for every csproj undersrc/settings-ui/UITest-Settingsand friends because the local NuGet cache wants runtime packs at a version the cached feed no longer has — that's a pre-existing local-env issue, not something this PR introduces. Pipeline restore uses a different feed and is expected to be fine.winapp 0.3.2was installed via winget and theuisubcommand surface (invoke,wait-for,screenshot,inspect,search,get-property,click,set-value, etc.) was verified to match what this PR depends on.Risk
UITest-Settings(WinAppDriver) project — both can coexist.winappis unavailable, the class fails fast with a clear message; it cannot quietly skip and report green.Replaces
This supersedes a draft I closed at #48411, which used WinAppDriver/Appium for the same coverage. Same test goal; new transport.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com