Files
PowerToys/doc
Gleb KhmyznikovandCopilot 1c39ab3492 [UI tests] Alt Windows new UI tests (#51552)
<!--
HARD RULE: You (the human contributor) must write this PR description in
your own words.
AI tools and agents: Do NOT write the Summary, Detailed Description, or
Validation Steps sections.
Leave them for the human. You may put AI-generated text ONLY inside an
"AI-generated summary" <details> block at the bottom.
Maintainers will close PRs whose description they think was not written
by a human.
See
https://github.com/microsoft/PowerToys/blob/main/CONTRIBUTING.md#pull-request-descriptions-must-be-written-by-a-human
-->

<!-- 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

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

- [ ] Closes: #51548
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [x] **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

<details>
<summary>AI-generated summary</summary>

### Implementation

Adds a greenfield `AltWindowCycle.UITests` suite using
`Microsoft.PowerToys.UITest.Next` for **Window Hopper**, the Settings
name of Alt Window Cycle. Addresses the sanity checks in #51548 without
changing product behavior.

The 13 cases cover:

- Same-application filtering with three separate same-image processes
and an interleaved different-image application.
- Forward and reverse cycling with one through four held-Alt key
presses, exact selected-window activation, and wraparound.
- Direction changes while the switcher is open; releasing Shift alone
must not commit the selection.
- Escape cancellation, subsequent activation, and the single-window
application case.
- Editing both shortcuts through the real Settings UI, using the new
Ctrl-based chords without restarting the Runner, and verifying the old
chords are unregistered.
- Disabling through Settings, verifying immediate module HWND
destruction and inactive shortcuts, then re-enabling and cycling again.

A small WinForms fixture supplies deterministic window titles and
distinct preview colors rather than depending on an installed
application's version or tab behavior. Tests inspect composed preview
pixels and actual foreground HWNDs because the GDI-painted switcher does
not expose a UIA card tree. They preserve module settings, release held
modifiers, clean up owned fixture processes, and remove abandoned
fixture processes before each test. The immutable different-image
fixture payload is copied once per class, while windows and processes
remain isolated per test.

Both projects are registered in `PowerToys.slnx`. The existing UI-test
pipeline now includes this suite in standard-user dispatch and
authenticated Runner/Settings companion signing, with positive and
negative Pester regression cases. The fixture and runner are test-only
binaries, not new product installer payloads. Developer documentation is
added at `doc/devdocs/modules/alt_window_cycle.md` and linked from the
module index.

### Main integration and warning policy

Merge commit `ba77aad6d0807b4874b8bb9be5e4922e29230d6b` includes
`main@e393ce2c23e5b29e6fc45fd01c5d3ecad8488023` and its stricter UI-test
warning policy. `AltWindowCycle.UITests`, `AltWindowCycle.TestApp`, and
their shared `UITestAutomation.Next` dependency already inherit
`TreatWarningsAsErrors=True`; none overrides it to `false`, adds blanket
project-local warning exclusions, or duplicates the shared
`GlobalSuppressions.cs` include. MSBuild evaluation confirmed nullable
analysis enabled, .NET analyzers enabled, and exactly one linked
global-suppression file for each project in all three configurations. No
additional suppressions were necessary.

Forced rebuilds from
`src\modules\AltWindowCycle\Tests\AltWindowCycle.UITests` each exited 0
with **0 warnings and 0 errors**:

```powershell
X:\Develop\PowerToys-alt-window\tools\build\build.cmd -Platform x64 -Configuration Debug -ExtraArgs '/t:Rebuild'
X:\Develop\PowerToys-alt-window\tools\build\build.cmd -Platform x64 -Configuration Release -ExtraArgs '/t:Rebuild'
X:\Develop\PowerToys-alt-window\tools\build\build.cmd -Platform ARM64 -Configuration Release -ExtraArgs '/t:Rebuild'
```

The merge does not change the AltWindowCycle test source, fixture,
shared test harness, or their root build/dependency properties. [Public
PR CI
391794](https://dev.azure.com/shine-oss/62769a65-d989-45e3-803c-9ad21fcf2ea2/_build/results?buildId=391794)
**succeeded** for this merge revision: x64 and ARM64 builds passed, all
13 PR checks passed, and the AltWindowCycle suite passed **39/39**
(13/13 on ARM64, Windows 10 x64, and Windows 11 x64), with no
non-passing selected UI results. The older validation details below
remain explicitly associated with the pre-merge revision.

### Claude Opus 5.5 review

Claude Opus 5.5 reviewed the initial revision using
`.claude/commands/review-pr.prompt.md`. All five findings were addressed
in `f3b39b03484bae099722404eb1b5d41726efed7c`:

| Finding | Resolution |
|---|---|
| Shift-release assertion could miss a premature commit | Select a
non-anchor window before releasing Shift; observe exact-HWND hide events
for one second; verify the same observer detects the later real
Alt-release commit |
| Aborted runs could leave same-image fixture processes in the cycle set
| Extend pre-test stale-process hygiene; explicitly validate with a
seeded, live standard-user fixture window before the full Windows 10
suite |
| Pipeline opt-ins lacked regression coverage | Add exact-suite and
lookalike-negative signing cases plus normal-user dispatch coverage |
| Developer documentation was not discoverable from its index | Add the
Window Hopper entry to the module documentation index |
| Each case copied the entire fixture payload | Cache the immutable copy
per class and remove it at class cleanup; verify one copied path across
all 13 cases and its absence afterward |

### Validation evidence

Previously validated suite source:
`f3b39b03484bae099722404eb1b5d41726efed7c` (the current merge revision
is documented above).

**CI:** [UI Test Automation 20261024.5 /
161586359](https://dev.azure.com/microsoft/Dart/_build/results?buildId=161586359),
pipeline 161438, attempt 2, `buildSource=buildNow`,
`uiTestModules=[AltWindowCycle.UITests]`, **succeeded** at the exact
reviewed-fix source above. Both full product builds succeeded, and
Runner/Settings companion signing was verified in all three test jobs.
The x64 build stage was retried once at the same SHA after an unrelated
Mouse Without Borders unit-test command timeout; no unrelated code was
changed.

| CI target | Result |
|---|---|
| Windows 10 x64 | 13/13 passed |
| Windows 11 x64 | 13/13 passed |
| Windows 11 ARM64 | 13/13 passed |

All **39/39** selected UI results passed; no selected tests were
skipped, inconclusive, or unexecuted.
The public [PowerToys PR CI run
391769](https://dev.azure.com/shine-oss/62769a65-d989-45e3-803c-9ad21fcf2ea2/_build/results?buildId=391769)
and every PR check for that pre-merge revision also succeeded.

**Local VMs:** the reviewed unfiltered Release suite passed on Windows
10 and Windows 11 under both Default (4 vCPU / 8 GB) and Constrained (1
vCPU / 4 GB): **52/52 passed**, with zero evidence-export errors. These
runs used a retained `0.0.1.0` runtime with the current-source
AltWindowCycle Release DLL and test-signed Runner/Settings companions;
CI rebuilds the full pushed source revision. One initial Windows 11
constrained run was interrupted by a OneDrive backup prompt taking
foreground. The PNG/MP4 evidence confirmed that desktop interference;
dismissing the prompt in the disposable guest restored the focused cases
and full suite without changing code or weakening assertions.

The successful build commands, run from
`src\modules\AltWindowCycle\Tests\AltWindowCycle.UITests`, were:

```powershell
X:\Develop\PowerToys-alt-window\tools\build\build.cmd -Platform x64 -Configuration Release
X:\Develop\PowerToys-alt-window\tools\build\build.cmd -Platform ARM64 -Configuration Release
```

Both exited 0. The x64 and ARM64 test and fixture apphosts were also
checked for the correct PE architecture.

The exact successful local suite invocations were:

```powershell
# Windows 10 Default: PASS, 13/13.
pwsh -NoProfile -File X:\Develop\PowerToys-alt-window\.github\skills\ui-tests-local-vm\scripts\Invoke-LocalVmUiTest.ps1 -VmName PowerToysUiTest-Win10 -VmRoot X:\PowerToysUiTestVm\Win10 -ExchangeRoot X:\PowerToysUiTestVm\Win10\shared\PowerToysUiTests\AltWindowCycle -TestExecutable AltWindowCycle.UITests.exe -ProductOverlayArchive product-overlay.zip -Platform x64Win10 -BuildLabel a32e3b6f6c-review-fixes -SuiteTimeout 15m -TimeoutMinutes 25 -ReuseStagedPayload

# Windows 11 Default: PASS, 13/13.
pwsh -NoProfile -File X:\Develop\PowerToys-alt-window\.github\skills\ui-tests-local-vm\scripts\Invoke-LocalVmUiTest.ps1 -VmName PowerToysUiTest-Win11 -VmRoot X:\PowerToysUiTestVm\Win11 -ExchangeRoot X:\PowerToysUiTestVm\Win11\shared\PowerToysUiTests\AltWindowCycle -TestExecutable AltWindowCycle.UITests.exe -ProductOverlayArchive product-overlay.zip -Platform x64Win11 -BuildLabel a32e3b6f6c-review-fixes -SuiteTimeout 15m -TimeoutMinutes 25 -ReuseStagedPayload

# Windows 10 Constrained, after stopping the guest: PASS, 13/13.
pwsh -NoProfile -File X:\Develop\PowerToys-alt-window\.github\skills\ui-tests-local-vm\scripts\Invoke-LocalVmUiTest.ps1 -VmName PowerToysUiTest-Win10 -VmRoot X:\PowerToysUiTestVm\Win10 -ConfigurationPath X:\PowerToysUiTestVm\Win10\vm.config.psd1 -ResourceProfile Constrained -ExchangeRoot X:\PowerToysUiTestVm\Win10\shared\PowerToysUiTests\AltWindowCycle -TestExecutable AltWindowCycle.UITests.exe -ProductOverlayArchive product-overlay.zip -Platform x64Win10 -BuildLabel a32e3b6f6c-review-fixes -SuiteTimeout 20m -TimeoutMinutes 30 -ReuseStagedPayload

# Windows 11 Constrained, after stopping the guest: PASS, 13/13.
pwsh -NoProfile -File X:\Develop\PowerToys-alt-window\.github\skills\ui-tests-local-vm\scripts\Invoke-LocalVmUiTest.ps1 -VmName PowerToysUiTest-Win11 -VmRoot X:\PowerToysUiTestVm\Win11 -ConfigurationPath X:\PowerToysUiTestVm\Win11\vm.config.psd1 -ResourceProfile Constrained -ExchangeRoot X:\PowerToysUiTestVm\Win11\shared\PowerToysUiTests\AltWindowCycle -TestExecutable AltWindowCycle.UITests.exe -ProductOverlayArchive product-overlay.zip -Platform x64Win11 -BuildLabel a32e3b6f6c-review-fixes -SuiteTimeout 20m -TimeoutMinutes 30 -ReuseStagedPayload
```

Additional checks, run from the worktree root:

```powershell
# PASS, exit 0.
pwsh -NoProfile -File .pipelines\verifyCommonProps.ps1 -sourceDir src\modules\AltWindowCycle\Tests

# PASS, exit 0.
dotnet format whitespace .\src\modules\AltWindowCycle\Tests\AltWindowCycle.UITests\AltWindowCycle.UITests.csproj --no-restore --verify-no-changes --include src\modules\AltWindowCycle\Tests\AltWindowCycle.UITests\AltWindowCycleTests.cs src\modules\AltWindowCycle\Tests\AltWindowCycle.UITests\WindowFixture.cs --verbosity quiet

# PASS, 135/135; zero failed or skipped.
Import-Module Pester -RequiredVersion 3.4.0
$result=Invoke-Pester -Script @('.pipelines\tests\uiTestSigningSelection.Tests.ps1','.pipelines\tests\runUiTestAsUser.Tests.ps1') -PassThru -Quiet
```

</details>

<img width="641" height="349" alt="image"
src="https://github.com/user-attachments/assets/6644dc5b-1bb6-4de1-a942-16fbb304edbc"
/>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-26 07:15:23 +01:00
..