mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-08-29 10:09:43 +02:00
## Summary Adds end‑to‑end UI tests on the `Microsoft.PowerToys.UITest.Next` (winappcli) framework for three modules, grows the shared `.Next` test framework with the helpers those suites needed, and adds the CI plumbing that lets shell‑extension tests exercise the **real** Windows 11 modern context menu. Also ships two agent skills that document how to write and run these tests. Product runtime behavior is **unchanged** — the only product edits are test‑observability hooks in Peek and a unit‑test project exclude. Closes: https://github.com/microsoft/PowerToys/issues/40660 https://github.com/microsoft/PowerToys/issues/49424 https://github.com/microsoft/PowerToys/issues/40661 ## What's added ### New UI test suites - **Image Resizer** — `src/modules/imageresizer/tests/ImageResizer.UITests`: context‑menu enable/disable tracking, the resize dialog, custom presets, every fit mode, every unit, filename format, keep‑date, shrink‑only, replace‑in‑place, and orientation. - **Peek** — `src/modules/peek/Peek.UITests.Next`: file‑preview coverage across image/text/archive/ markdown types with per‑arch visual baselines. - **File Explorer add‑ons** — `src/modules/previewpane/PreviewPane.UITests`: Preview Pane handlers and thumbnail providers. ### `UITestAutomation.Next` framework - New helpers: `ExplorerShell` (Shell selection/view‑mode interop), `WaitHelper` (structured stable waits), `WindowControl` (foreground/context‑menu/process control), `VisualAssert` (image compare), `WindowHelper`. - Updates to `Session`, `UITestBase`, `SettingsConfigHelper`, `WinappCli`. - New `UITestAutomation.Next.UnitTests` project covering the new wait/settings/CLI helpers. ### CI — sign sparse MSIX so the modern menu registers - **`.pipelines/signSparsePackages.ps1`** — self‑signs each sparse context‑menu MSIX with a publisher‑matching test certificate and force‑trusts it (machine stores), so `AddPackageByUriAsync` succeeds on otherwise‑unsigned PR builds. Robust `signtool` discovery with a NuGet fallback; test‑only trust that asserts no security. - Wired into **`.pipelines/v2/templates/job-test-project.yml`** as a best‑effort step covering the run‑in‑place, machine‑install, and per‑user‑install locations. Signs nothing it can't (skips already‑signed packages) and never fails the job. ### Product changes (test observability only) - **Peek `FilePreview.xaml` / `.xaml.cs`** — a named `LoadingIndicator` and a hidden automation peer that exposes the current preview state as text, so tests can read load state deterministically. No runtime behavior change. - **`ImageResizer.UnitTests.csproj`** — exclude the sibling `ImageResizer.UITests\**` folder from the unit‑test compilation. ### Agent skills & docs - **New `ui-tests-local-vm` skill** — run `.Next` suites in persistent dockur/windows VMs: setup, agentic loop, image customization, troubleshooting, the shell‑extension **signing** reference, plus controller/guest scripts and VM templates. - **Updated `ui-tests-migration` skill** — WinAppDriver/Selenium → `.Next` porting guidance (CI stability, Explorer/shell‑extension test design, patterns & pitfalls). - **`doc/devdocs/development/ui-tests.md`** — updated for the `.Next` workflow. ## Testing - All three suites pass locally and in CI across **x64 Win10**, **x64 Win11**, and **arm64** (machine and per‑user install legs). ## Reviewer notes - No product runtime behavior changes; product edits are limited to the Peek test hooks above. - The CI signing step is a **test‑only** trust anchor (self‑signed, scoped to the agent) and is best‑effort, so it can only add modern‑menu coverage and never regress the job.
67 lines
2.9 KiB
PowerShell
67 lines
2.9 KiB
PowerShell
# Copyright (c) Microsoft Corporation
|
|
# The Microsoft Corporation licenses this file to you under the MIT license.
|
|
# See the LICENSE file in the project root for more information.
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Scaffolds a local Hyper-V UI-test VM directory for persistent PowerToys UI-test execution.
|
|
|
|
.DESCRIPTION
|
|
Copies the Hyper-V VM lifecycle scripts, the unattend template, and the OEM provisioning payload
|
|
into a working directory. Everything runs on the platform hypervisor, so no nested virtualization is
|
|
needed and the scaffold works on x64 and on Windows on ARM alike.
|
|
|
|
.EXAMPLE
|
|
pwsh ./Initialize-LocalVm.ps1 -DestinationRoot X:\PowerToysUiTestVm
|
|
#>
|
|
|
|
[CmdletBinding(SupportsShouldProcess)]
|
|
param(
|
|
[Parameter(Mandatory)]
|
|
[string]$DestinationRoot,
|
|
[switch]$Force
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
if ($PSVersionTable.PSVersion.Major -lt 7) {
|
|
throw 'Run this script with PowerShell 7 (pwsh).'
|
|
}
|
|
|
|
$templateRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\templates\vm'))
|
|
$oemTemplateRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\templates\oem'))
|
|
$destination = [IO.Path]::GetFullPath($DestinationRoot)
|
|
if (-not (Test-Path $templateRoot -PathType Container)) {
|
|
throw "VM templates were not found: $templateRoot"
|
|
}
|
|
if (-not (Test-Path $oemTemplateRoot -PathType Container)) {
|
|
throw "OEM templates were not found: $oemTemplateRoot"
|
|
}
|
|
|
|
if (Test-Path $destination -PathType Container) {
|
|
$existingItems = @(Get-ChildItem $destination -Force)
|
|
if ($existingItems.Count -gt 0 -and -not $Force) {
|
|
throw "Destination is not empty: $destination. Pass -Force to merge and overwrite template files."
|
|
}
|
|
}
|
|
|
|
if ($PSCmdlet.ShouldProcess($destination, 'Scaffold the local Hyper-V UI-test VM')) {
|
|
New-Item $destination -ItemType Directory -Force | Out-Null
|
|
Copy-Item (Join-Path $templateRoot '*') $destination -Recurse -Force
|
|
New-Item (Join-Path $destination 'oem') -ItemType Directory -Force | Out-Null
|
|
Copy-Item (Join-Path $oemTemplateRoot '*') (Join-Path $destination 'oem') -Recurse -Force
|
|
New-Item (Join-Path $destination 'shared') -ItemType Directory -Force | Out-Null
|
|
}
|
|
|
|
[pscustomobject]@{
|
|
VmRoot = $destination
|
|
ConfigurationTemplate = (Join-Path $destination 'vm.config.example.psd1')
|
|
NextSteps = @(
|
|
"Copy vm.config.example.psd1 to vm.config.psd1 and set the VM name, paths, and architecture.",
|
|
"Obtain media: pwsh $(Join-Path $PSScriptRoot 'Get-WindowsMedia.ps1') -Source Fido -Windows 11 -Architecture x64 -DestinationRoot $(Join-Path $destination 'media')",
|
|
"HUMAN-ONLY, elevated, once: pwsh $(Join-Path $PSScriptRoot 'Initialize-LocalVmHost.ps1') -VmRoot $destination -InstallMedia <windows.iso>",
|
|
"It joins Hyper-V Administrators, saves the DPAPI guest credential, and creates the guest - an agent cannot do any of these.",
|
|
"Agents: verify with -CheckOnly and stop until it reports IsReady=true."
|
|
)
|
|
} | ConvertTo-Json -Depth 4
|