diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index b4354e2f91..7355d90790 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -192,6 +192,7 @@ CImage
cla
CLASSDC
CLASSNOTAVAILABLE
+cleanmgr
clickable
clickonce
CLIENTEDGE
@@ -276,6 +277,7 @@ currentculture
CURRENTDIR
CURSORINFO
cursorpos
+CURSORSHOWING
customaction
CUSTOMACTIONTEST
CUSTOMFORMATPLACEHOLDER
@@ -343,7 +345,9 @@ DESELECTOTHERS
DESIGNINFO
DESKTOPABSOLUTEEDITING
DESKTOPABSOLUTEPARSING
+DESKTOPHORZRES
desktopshorcutinstalled
+DESKTOPVERTRES
devblogs
devdocs
devmgmt
@@ -354,6 +358,7 @@ DFX
DIALOGEX
digicert
dimm
+DINORMAL
DISABLEASACTIONKEY
DISABLENOSCROLL
diskmgmt
@@ -397,6 +402,7 @@ DVASPECTINFO
DVD
dvr
DVTARGETDEVICE
+dwflags
dwl
dwm
dwmapi
@@ -485,6 +491,7 @@ FANCYZONESDRAWLAYOUTTEST
FANCYZONESEDITOR
FARPROC
fff
+FFFF
FILEEXPLORER
FILEFLAGS
FILEFLAGSMASK
@@ -603,6 +610,7 @@ helptext
HGFE
hglobal
hhk
+HHmmssfff
hhx
Hiber
Hiberboot
@@ -611,6 +619,7 @@ hicon
HIDEREADONLY
HIDEWINDOW
Hif
+hightlight
HIMAGELIST
himl
hinst
@@ -745,6 +754,7 @@ isocpp
iss
issecret
ISSEPARATOR
+istep
ith
ITHUMBNAIL
IUI
@@ -1275,6 +1285,7 @@ prvpane
psapi
pscid
PSECURITY
+psexec
psfgao
psfi
PSMODULEPATH
@@ -1532,6 +1543,7 @@ SLGP
sln
SMALLICON
smartphone
+smileys
SMTO
SNAPPROCESS
snk
@@ -1876,6 +1888,7 @@ WINDOWPOSCHANGING
WINDOWSBUILDNUMBER
windowssearch
windowssettings
+windowsterminal
WINDOWSTYLES
WINDOWSTYLESICON
winerror
@@ -1985,6 +1998,7 @@ Zoneszonabletester
Zoomin
zoomit
ZOOMITX
+Zorder
ZXk
ZXNs
zzz
diff --git a/.pipelines/v2/templates/job-build-project.yml b/.pipelines/v2/templates/job-build-project.yml
index 13eac3a917..c642402623 100644
--- a/.pipelines/v2/templates/job-build-project.yml
+++ b/.pipelines/v2/templates/job-build-project.yml
@@ -53,6 +53,9 @@ parameters:
- name: runTests
type: boolean
default: true
+ - name: buildTests
+ type: boolean
+ default: true
- name: useVSPreview
type: boolean
default: false
@@ -110,7 +113,7 @@ jobs:
JobOutputArtifactName: build-$(BuildPlatform)-$(BuildConfiguration)${{ parameters.artifactStem }}
NUGET_RESTORE_MSBUILD_ARGS: /p:Platform=$(BuildPlatform) # Required for nuget to work due to self contained
NODE_OPTIONS: --max_old_space_size=16384
- ${{ if eq(parameters.runTests, true) }}:
+ ${{ if or(eq(parameters.runTests, true), eq(parameters.buildTests, true)) }}:
MSBuildMainBuildTargets: Build;Test
${{ else }}:
MSBuildMainBuildTargets: Build
@@ -528,7 +531,7 @@ jobs:
displayName: Stage GPO files
# Running the tests may result in future jobs consuming artifacts out of this build
- - ${{ if eq(parameters.runTests, true) }}:
+ - ${{ if or(eq(parameters.runTests, true), eq(parameters.buildTests, true)) }}:
- task: CopyFiles@2
displayName: Stage entire build output
inputs:
diff --git a/.pipelines/v2/templates/job-test-project.yml b/.pipelines/v2/templates/job-test-project.yml
index 234f477fb6..ab682cd5a5 100644
--- a/.pipelines/v2/templates/job-test-project.yml
+++ b/.pipelines/v2/templates/job-test-project.yml
@@ -15,20 +15,29 @@ parameters:
jobs:
- job: Test${{ parameters.platform }}${{ parameters.configuration }}
displayName: Test ${{ parameters.platform }} ${{ parameters.configuration }}
+ timeoutInMinutes: 300
variables:
- BuildPlatform: ${{ parameters.platform }}
+ ${{ if or(eq(parameters.platform, 'x64Win10'), eq(parameters.platform, 'x64Win11')) }}:
+ BuildPlatform: x64
+ ${{ else }}:
+ BuildPlatform: ${{ parameters.platform }}
+ TestPlatform: ${{ parameters.platform }}
BuildConfiguration: ${{ parameters.configuration }}
SrcPath: $(Build.Repository.LocalPath)
- TestArtifactsName: build-${{ parameters.platform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}
+ TestArtifactsName: build-${{ variables.BuildPlatform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}
pool:
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
${{ if ne(parameters.platform, 'ARM64') }}:
name: SHINE-INT-Testing-x64
+ ${{ if eq(parameters.platform, 'x64Win11') }}:
+ demands: ImageOverride -equals SHINE-W11-Testing
${{ else }}:
name: SHINE-INT-Testing-arm64
${{ else }}:
${{ if ne(parameters.platform, 'ARM64') }}:
name: SHINE-OSS-Testing-x64
+ ${{ if eq(parameters.platform, 'x64Win11') }}:
+ demands: ImageOverride -equals SHINE-W11-Testing
${{ else }}:
name: SHINE-OSS-Testing-arm64
steps:
@@ -101,8 +110,13 @@ jobs:
vsTestVersion: 'toolsInstaller'
uiTests: true
rerunFailedTests: true
+ # Since UITests-FancyZonesEditor.dll is generated in both UITests-FancyZonesEditor and UITests-FancyZones, removed one to avoid duplicate test runs
testAssemblyVer2: |
- **\UITests-FancyZones.dll
- **\UITests-FancyZonesEditor.dll
+ **\*UITest*.dll
!**\obj\**
- !**\ref\**
\ No newline at end of file
+ !**\ref\**
+ !**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll
+
+
+ env:
+ platform: '$(TestPlatform)'
diff --git a/.pipelines/v2/templates/pipeline-ci-build.yml b/.pipelines/v2/templates/pipeline-ci-build.yml
index 37e06ae4f2..cc7a67e613 100644
--- a/.pipelines/v2/templates/pipeline-ci-build.yml
+++ b/.pipelines/v2/templates/pipeline-ci-build.yml
@@ -60,16 +60,4 @@ stages:
useLatestWinAppSDK: ${{ parameters.useLatestWinAppSDK }}
${{ if eq(parameters.useLatestWinAppSDK, true) }}:
winAppSDKVersionNumber: ${{ parameters.winAppSDKVersionNumber }}
- useExperimentalVersion: ${{ parameters.useExperimentalVersion }}
-
- - ${{ if and(eq(parameters.runTests, true), not(and(eq(platform, 'arm64'), eq(variables['System.PullRequest.IsFork'], true)))) }}:
- - stage: Test_${{ platform }}
- displayName: Test ${{ platform }}
- dependsOn:
- - Build_${{platform}}
- jobs:
- - template: job-test-project.yml
- parameters:
- platform: ${{ platform }}
- configuration: Release
- useLatestWebView2: ${{ parameters.useLatestWebView2 }}
+ useExperimentalVersion: ${{ parameters.useExperimentalVersion }}
\ No newline at end of file
diff --git a/.pipelines/v2/templates/pipeline-ui-tests-automation.yml b/.pipelines/v2/templates/pipeline-ui-tests-automation.yml
new file mode 100644
index 0000000000..4db1005f3b
--- /dev/null
+++ b/.pipelines/v2/templates/pipeline-ui-tests-automation.yml
@@ -0,0 +1,84 @@
+variables:
+ - name: runCodesignValidationInjectionBG
+ value: false
+ - name: EnablePipelineCache
+ value: true
+ - ${{ if eq(parameters.enableMsBuildCaching, true) }}:
+ - name: EnablePipelineCache
+ value: true
+
+parameters:
+ - name: buildPlatforms
+ type: object
+ default:
+ - x64
+ - arm64
+ - name: enableMsBuildCaching
+ type: boolean
+ default: false
+ - name: useVSPreview
+ type: boolean
+ default: false
+ - name: useLatestWebView2
+ type: boolean
+ default: false
+
+stages:
+ - ${{ each platform in parameters.buildPlatforms }}:
+ - stage: Build_${{ platform }}
+ displayName: Build ${{ platform }}
+ dependsOn: []
+ jobs:
+ - template: job-build-project.yml
+ parameters:
+ pool:
+ ${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
+ name: SHINE-INT-L
+ ${{ else }}:
+ name: SHINE-OSS-L
+ ${{ if eq(parameters.useVSPreview, true) }}:
+ demands: ImageOverride -equals SHINE-VS17-Preview
+ buildPlatforms:
+ - ${{ platform }}
+ buildConfigurations: [Release]
+ enablePackageCaching: true
+ enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
+ runTests: false
+ buildTests: true
+ useVSPreview: ${{ parameters.useVSPreview }}
+
+ - ${{ if eq(platform, 'x64') }}:
+ - stage: Test_x64Win10
+ displayName: Test x64Win10
+ dependsOn:
+ - Build_${{platform}}
+ jobs:
+ - template: job-test-project.yml
+ parameters:
+ platform: x64Win10
+ configuration: Release
+ useLatestWebView2: ${{ parameters.useLatestWebView2 }}
+
+ - ${{ if eq(platform, 'x64') }}:
+ - stage: Test_x64Win11
+ displayName: Test x64Win11
+ dependsOn:
+ - Build_${{platform}}
+ jobs:
+ - template: job-test-project.yml
+ parameters:
+ platform: x64Win11
+ configuration: Release
+ useLatestWebView2: ${{ parameters.useLatestWebView2 }}
+
+ - ${{ if ne(platform, 'x64') }}:
+ - stage: Test_${{ platform }}
+ displayName: Test ${{ platform }}
+ dependsOn:
+ - Build_${{platform}}
+ jobs:
+ - template: job-test-project.yml
+ parameters:
+ platform: ${{ platform }}
+ configuration: Release
+ useLatestWebView2: ${{ parameters.useLatestWebView2 }}
diff --git a/.pipelines/verifyDepsJsonLibraryVersions.ps1 b/.pipelines/verifyDepsJsonLibraryVersions.ps1
index e85ca1d991..085e1e439a 100644
--- a/.pipelines/verifyDepsJsonLibraryVersions.ps1
+++ b/.pipelines/verifyDepsJsonLibraryVersions.ps1
@@ -92,4 +92,3 @@ if ($totalFailures -gt 0) {
Write-Host -ForegroundColor Green "All " $referencedFileVersionsPerDll.keys.Count " libraries are mentioned with the same version across the dependencies.`r`n"
exit 0
-
diff --git a/PowerToys.sln b/PowerToys.sln
index f58aa7c077..9469ac7449 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -717,6 +717,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "sr
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzingTest", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MouseUtils.UITests", "src\modules\MouseUtils\MouseUtils.UITests\MouseUtils.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesEditorUITest", "src\modules\Workspaces\WorkspacesEditorUITest\WorkspacesEditorUITest.csproj", "{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorEngineCommon", "src\common\CalculatorEngineCommon\CalculatorEngineCommon.vcxproj", "{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}"
EndProject
Global
@@ -2599,6 +2603,22 @@ Global
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.Build.0 = Release|ARM64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.ActiveCfg = Release|x64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.Build.0 = Release|x64
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|ARM64.Build.0 = Debug|ARM64
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|x64.ActiveCfg = Debug|x64
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|x64.Build.0 = Debug|x64
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|ARM64.ActiveCfg = Release|ARM64
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|ARM64.Build.0 = Release|ARM64
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|x64.ActiveCfg = Release|x64
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|x64.Build.0 = Release|x64
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|ARM64.Build.0 = Debug|ARM64
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|x64.ActiveCfg = Debug|x64
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|x64.Build.0 = Debug|x64
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|ARM64.ActiveCfg = Release|ARM64
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|ARM64.Build.0 = Release|ARM64
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|x64.ActiveCfg = Release|x64
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|x64.Build.0 = Release|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.ActiveCfg = Debug|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.Build.0 = Debug|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.ActiveCfg = Debug|x64
@@ -2768,7 +2788,7 @@ Global
{25C91A4E-BA4E-467A-85CD-8B62545BF674} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
{212AD910-8488-4036-BE20-326931B75FB2} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
- {7AC943C9-52E8-44CF-9083-744D8049667B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
+ {7AC943C9-52E8-44CF-9083-744D8049667B} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{54A93AF7-60C7-4F6C-99D2-FBB1F75F853A} = {7AC943C9-52E8-44CF-9083-744D8049667B}
{92C39820-9F84-4529-BC7D-22AAE514D63B} = {7AC943C9-52E8-44CF-9083-744D8049667B}
{515554D1-D004-4F7F-A107-2211FC0F6B2C} = {7AC943C9-52E8-44CF-9083-744D8049667B}
@@ -2900,6 +2920,8 @@ Global
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{5702B3CC-8575-48D5-83D8-15BB42269CD3} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
{64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1} = {322566EF-20DC-43A6-B9F8-616AF942579A}
+ {43E779F3-D83C-48B1-BA8D-1912DBD76FC9} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{0217E86E-3476-9946-DE8E-9D200CEBD47A} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
diff --git a/doc/devdocs/UITests.md b/doc/devdocs/UITests.md
index b1b91a632c..d02eeb6993 100644
--- a/doc/devdocs/UITests.md
+++ b/doc/devdocs/UITests.md
@@ -21,67 +21,74 @@
- Create a new project and add the following references to the project file. Change the OutputPath to your own module's path.
```
-
- Library
-
- false
-
-
-
- ..\..\..\..\$(Platform)\$(Configuration)\tests\KeyboardManagerUITests\
-
-
-
-
-
-
-
+
+
+
+
+
+ {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}
+ PowerToys.Hosts.UITests
+ PowerToys.Hosts.UITests
+ false
+ true
+ enable
+ Library
+
+
+ false
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\tests\Hosts.UITests\
+
+
+
+
+
+
+
+
```
- Inherit your test class from UITestBase.
>Set Scope: The default scope starts from the PowerToys settings UI. If you want to start from your own module, set the constructor as shown below:
>Specify Scope:
```
- [TestClass]
- public class RunFancyZonesTest : UITestBase
- {
- public RunFancyZonesTest()
- : base(PowerToysModule.FancyZone)
- {
- }
- }
+ [TestClass]
+ public class HostModuleTests : UITestBase
+ {
+ public HostModuleTests()
+ : base(PowerToysModule.Hosts, WindowSize.Small_Vertical)
+ {
+ }
+ }
```
-- Then you can start using session to perform the UI operations.
+- Then you can start performing the UI operations.
**Example**
```
-using Microsoft.PowerToys.UITest;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace UITests_KeyboardManager
+[TestMethod("Hosts.Basic.EmptyViewShouldWork")]
+[TestCategory("Hosts File Editor #4")]
+public void TestEmptyView()
{
- [TestClass]
- public class RunKeyboardManagerUITests : UITestBase
- {
- [TestMethod]
- public void OpenKeyboardManagerEditor()
- {
- // Open KeyboardManagerEditor
- this.Session.Find