Compare commits

..

10 Commits

Author SHA1 Message Date
Leilei Zhang
bfa490cfde use variable 2025-07-31 11:07:46 +08:00
Leilei Zhang
b99e62af48 Merge branch 'main' of https://github.com/microsoft/PowerToys into leilzh/pathissue 2025-07-30 18:30:32 +08:00
Leilei Zhang
18b926c41d update md 2025-07-30 18:18:00 +08:00
Leilei Zhang
2eb99f96a3 remove choose install mode 2025-07-30 18:10:02 +08:00
Leilei Zhang
fb260bd098 update now 2025-07-30 18:02:59 +08:00
Leilei Zhang
f35f94bbaa update 2025-07-30 17:40:02 +08:00
Leilei Zhang
873a7a2bbe test update 2025-07-30 17:33:01 +08:00
Leilei Zhang
0a8b83e528 test default value 2025-07-30 17:04:09 +08:00
Leilei Zhang
7849079de4 update pipeline 2025-07-30 15:31:50 +08:00
Leilei Zhang
1a303301bb fix comments 2025-07-30 15:19:56 +08:00
17 changed files with 158 additions and 949 deletions

View File

@@ -1440,7 +1440,6 @@ secpol
securestring
SEEMASKINVOKEIDLIST
SELCHANGE
selfhost
SENDCHANGE
sendvirtualinput
serverside
@@ -1880,7 +1879,6 @@ winexe
winforms
winget
wingetcreate
wingetpkgs
Winhook
WINL
winlogon

View File

@@ -45,6 +45,7 @@ jobs:
BuildConfiguration: ${{ parameters.configuration }}
SrcPath: $(Build.Repository.LocalPath)
TestArtifactsName: build-${{ variables.BuildPlatform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}
isBuildNow: ${{ eq(parameters.buildSource, 'buildNow') }}
pool:
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
${{ if ne(parameters.platform, 'ARM64') }}:
@@ -115,7 +116,7 @@ jobs:
& '$(build.sourcesdirectory)\.pipelines\InstallWinAppDriver.ps1'
displayName: Download and install WinAppDriver
- ${{ if ne(parameters.buildSource, 'buildNow') }}:
- ${{ if not(variables.isBuildNow) }}:
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'specific'
@@ -136,7 +137,7 @@ jobs:
patterns: |
**/PowerToysSetup*.exe
- ${{ if ne(parameters.buildSource, 'buildNow') }}:
- ${{ if not(variables.isBuildNow) }}:
- ${{ if eq(parameters.installMode, 'peruser') }}:
- pwsh: |-
& "$(build.sourcesdirectory)\.pipelines\installPowerToys.ps1" -InstallMode "PerUser"
@@ -172,7 +173,7 @@ jobs:
!**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll
env:
platform: '$(TestPlatform)'
useInstallerForTest: ${{ ne(parameters.buildSource, 'buildNow') }}
useInstallerForTest: ${{ not(variables.isBuildNow) }}
- ${{ if ne(length(parameters.uiTestModules), 0) }}:
- ${{ each module in parameters.uiTestModules }}:
@@ -194,4 +195,4 @@ jobs:
!**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll
env:
platform: '$(TestPlatform)'
useInstallerForTest: ${{ ne(parameters.buildSource, 'buildNow') }}
useInstallerForTest: ${{ not(variables.isBuildNow) }}

View File

@@ -3,6 +3,8 @@ variables:
value: false
- name: EnablePipelineCache
value: true
- name: isBuildNow
value: ${{ eq(parameters.buildSource, 'buildNow') }}
parameters:
- name: buildPlatforms
@@ -37,22 +39,140 @@ parameters:
stages:
- ${{ each platform in parameters.buildPlatforms }}:
# Full build path: build PowerToys + UI tests + run tests
- ${{ if eq(parameters.buildSource, 'buildNow') }}:
- template: pipeline-ui-tests-full-build.yml
parameters:
platform: ${{ platform }}
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
useVSPreview: ${{ parameters.useVSPreview }}
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
uiTestModules: ${{ parameters.uiTestModules }}
- ${{ if variables.isBuildNow }}:
- 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 }}
timeoutInMinutes: 90
# Official build path: build UI tests only + download official build + run tests
- ${{ if ne(parameters.buildSource, 'buildNow') }}:
- template: pipeline-ui-tests-official-build.yml
parameters:
platform: ${{ platform }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
uiTestModules: ${{ parameters.uiTestModules }}
- ${{ if not(variables.isBuildNow) }}:
- stage: BuildUITests_${{ platform }}
displayName: Build UI Tests Only
dependsOn: []
jobs:
- template: job-build-ui-tests.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 }}
uiTestModules: ${{ parameters.uiTestModules }}
- ${{ if eq(platform, 'x64') }}:
- stage: Test_x64Win10
displayName: Test x64Win10
${{ if not(variables.isBuildNow) }}:
dependsOn:
- BuildUITests_${{ platform }}
${{ else }}:
dependsOn:
- Build_${{ platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: x64Win10
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
# Additional per-user installation test
- ${{ if not(variables.isBuildNow) }}:
- template: job-test-project.yml
parameters:
platform: x64Win10
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
installMode: 'peruser'
jobSuffix: '_PerUser'
- ${{ if eq(platform, 'x64') }}:
- stage: Test_x64Win11
displayName: Test x64Win11
${{ if not(variables.isBuildNow) }}:
dependsOn:
- BuildUITests_${{ platform }}
${{ else }}:
dependsOn:
- Build_${{ platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: x64Win11
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
# Additional per-user installation test
- ${{ if not(variables.isBuildNow) }}:
- template: job-test-project.yml
parameters:
platform: x64Win11
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
installMode: 'peruser'
jobSuffix: '_PerUser'
- ${{ if ne(platform, 'x64') }}:
- stage: Test_${{ platform }}
displayName: Test ${{ platform }}
${{ if not(variables.isBuildNow) }}:
dependsOn:
- BuildUITests_${{ platform }}
${{ else }}:
dependsOn:
- Build_${{ platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: ${{ platform }}
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
# Additional per-user installation test
- ${{ if not(variables.isBuildNow) }}:
- template: job-test-project.yml
parameters:
platform: ${{ platform }}
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
installMode: 'peruser'
jobSuffix: '_PerUser'

View File

@@ -1,80 +0,0 @@
# Template for full build path: Build PowerToys + Build UI Tests + Run Tests
parameters:
- name: platform
type: string
- name: enableMsBuildCaching
type: boolean
default: false
- name: useVSPreview
type: boolean
default: false
- name: useLatestWebView2
type: boolean
default: false
- name: uiTestModules
type: object
default: []
stages:
# Stage 1: Build full PowerToys project
- stage: Build_${{ parameters.platform }}
displayName: Build PowerToys ${{ parameters.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:
- ${{ parameters.platform }}
buildConfigurations: [Release]
enablePackageCaching: true
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
runTests: false
buildTests: true
useVSPreview: ${{ parameters.useVSPreview }}
timeoutInMinutes: 90
# Stage 2: Run UI Tests
- ${{ if eq(parameters.platform, 'x64') }}:
- stage: Test_x64Win10_FullBuild
displayName: Test x64Win10 (Full Build)
dependsOn: Build_${{ parameters.platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: x64Win10
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: 'buildNow'
uiTestModules: ${{ parameters.uiTestModules }}
- stage: Test_x64Win11_FullBuild
displayName: Test x64Win11 (Full Build)
dependsOn: Build_${{ parameters.platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: x64Win11
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: 'buildNow'
uiTestModules: ${{ parameters.uiTestModules }}
- ${{ if ne(parameters.platform, 'x64') }}:
- stage: Test_${{ parameters.platform }}_FullBuild
displayName: Test ${{ parameters.platform }} (Full Build)
dependsOn: Build_${{ parameters.platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: ${{ parameters.platform }}
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: 'buildNow'
uiTestModules: ${{ parameters.uiTestModules }}

View File

@@ -1,110 +0,0 @@
# Template for official build path: Download Official Build + Build UI Tests Only + Run Tests
parameters:
- name: platform
type: string
- name: buildSource
type: string
- name: specificBuildId
type: string
default: 'xxxx'
- name: useLatestWebView2
type: boolean
default: false
- name: uiTestModules
type: object
default: []
stages:
# Stage 1: Build UI Tests Only
- stage: BuildUITests_${{ parameters.platform }}
displayName: Build UI Tests Only ${{ parameters.platform }}
dependsOn: []
jobs:
- template: job-build-ui-tests.yml
parameters:
pool:
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
name: SHINE-INT-L
${{ else }}:
name: SHINE-OSS-L
buildPlatforms:
- ${{ parameters.platform }}
uiTestModules: ${{ parameters.uiTestModules }}
# Stage 2: Run UI Tests with Official Build
- ${{ if eq(parameters.platform, 'x64') }}:
- stage: Test_x64Win10_OfficialBuild
displayName: Test x64Win10 (Official Build)
dependsOn: BuildUITests_${{ parameters.platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: x64Win10
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
# Additional per-user installation test
- template: job-test-project.yml
parameters:
platform: x64Win10
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
installMode: 'peruser'
jobSuffix: '_PerUser'
- stage: Test_x64Win11_OfficialBuild
displayName: Test x64Win11 (Official Build)
dependsOn: BuildUITests_${{ parameters.platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: x64Win11
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
# Additional per-user installation test
- template: job-test-project.yml
parameters:
platform: x64Win11
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
installMode: 'peruser'
jobSuffix: '_PerUser'
- ${{ if ne(parameters.platform, 'x64') }}:
- stage: Test_${{ parameters.platform }}_OfficialBuild
displayName: Test ${{ parameters.platform }} (Official Build)
dependsOn: BuildUITests_${{ parameters.platform }}
jobs:
- template: job-test-project.yml
parameters:
platform: ${{ parameters.platform }}
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
# Additional per-user installation test
- template: job-test-project.yml
parameters:
platform: ${{ parameters.platform }}
configuration: Release
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
buildSource: ${{ parameters.buildSource }}
specificBuildId: ${{ parameters.specificBuildId }}
uiTestModules: ${{ parameters.uiTestModules }}
installMode: 'peruser'
jobSuffix: '_PerUser'

View File

@@ -87,13 +87,6 @@
### Building PowerToys Locally
#### One stop script for building installer
1. Open developer powershell for vs 2022
2. Run tools\build\build-installer.ps1
> For the first-time setup, please run the installer as an administrator. This ensures that the Wix tool can move wix.target to the desired location and trust the certificate used to sign the MSIX packages.
The following manual steps will not install the MSIX apps (such as Command Palette) on your local installer.
#### Prerequisites for building the MSI installer
1. Install the [WiX Toolset Visual Studio 2022 Extension](https://marketplace.visualstudio.com/items?itemName=WixToolset.WixToolsetVisualStudio2022Extension).

View File

@@ -1,33 +0,0 @@
## If for any reason, you'd like to test winget install scenario, you can follow this doc:
### Powertoys winget manifest definition:
[winget repository](https://github.com/microsoft/winget-pkgs/tree/master/manifests/m/Microsoft/PowerToys)
### How to test a winget installation locally:
1. Get artifacts from release CI pipeline Pipelines - Runs for PowerToys Signed YAML Release Build, or you can build one yourself by execute the
'tools\build\build-installer.ps1' script
2. Get the artifact hash, this is required to define winget manifest
```powershell
cd /path/to/your/directory/contains/installer
Get-FileHash -Path ".\<Installer-name>.exe" -Algorithm SHA256
```
3. Host your installer.exe - Attention: staged github release artifacts or artifacts in release pipeline is not OK in this step
You can self-host it or you can upload to a publicly available endpoint
**How to selfhost it** (A extremely simple way):
```powershell
python -m http.server 8000
```
4. Download a version folder from wingetpkgs like: [version 0.92.1](https://github.com/microsoft/winget-pkgs/tree/master/manifests/m/Microsoft/PowerToys/0.92.1)
and you get **a folder contains 3 yml files**
>note: Do not put any files other than these three in this folder
5. Modify the yml files based on your version and the self hosted artifact link, and modify the sha256 hash for the installer you'd like to use
6. Start winget install:
```powershell
#execute as admin
winget settings --enable LocalManifestFiles
winget install --manifest "<folder_path_of_manifest_files>" --architecture x64 --scope user
```

View File

@@ -33,11 +33,10 @@ namespace Microsoft.PowerToys.UITest
private readonly PowerToysModule scope;
private readonly WindowSize size;
private readonly string[]? commandLineArgs;
private readonly bool hideAllWindowBeforeStart;
private SessionHelper? sessionHelper;
private System.Threading.Timer? screenshotTimer;
public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, WindowSize size = WindowSize.UnSpecified, string[]? commandLineArgs = null, bool hideAllWindowBeforeStart = false)
public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, WindowSize size = WindowSize.UnSpecified, string[]? commandLineArgs = null)
{
this.IsInPipeline = EnvironmentConfig.IsInPipeline;
Console.WriteLine($"Running tests on platform: {EnvironmentConfig.Platform}");
@@ -53,7 +52,6 @@ namespace Microsoft.PowerToys.UITest
this.scope = scope;
this.size = size;
this.commandLineArgs = commandLineArgs;
this.hideAllWindowBeforeStart = hideAllWindowBeforeStart;
}
/// <summary>
@@ -76,12 +74,6 @@ namespace Microsoft.PowerToys.UITest
System.Windows.Forms.SendKeys.SendWait("{ESC}");
}
if (hideAllWindowBeforeStart)
{
KeyboardHelper.SendKeys([Key.Win, Key.M]);
Task.Delay(2000).Wait(); // Wait for a second to ensure all windows are minimized
}
this.sessionHelper = new SessionHelper(scope, commandLineArgs).Init();
this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver(), scope, size);
}
@@ -586,31 +578,13 @@ namespace Microsoft.PowerToys.UITest
}
/// <summary>
/// Moves the mouse cursor to the specified screen coordinates.
/// </summary>
/// <param name="x">The new x-coordinate of the cursor.</param>
/// <param name="y">The new y-coordinate of the cursor.</param>
    /// Moves the mouse cursor to the specified screen coordinates.
    /// </summary>
    /// <param name="x">The new x-coordinate of the cursor.</param>
    /// <param name="y">The new y-coordinate of the cursor.</param
public void MoveMouseTo(int x, int y)
{
this.Session.MoveMouseTo(x, y);
}
/// <summary>
/// Moves the mouse cursor to the center of the screen.
/// </summary>
public void MoveMouseToCenter()
{
var (centerX, centerY) = this.GetScreenCenter();
this.MoveMouseTo(centerX, centerY);
}
/// <summary>
/// Moves the mouse cursor to the center of the screen and performs a left click.
/// </summary>
public void FocusOnCenter()
{
this.MoveMouseToCenter();
this.Session.PerformMouseAction(MouseActionType.LeftClick);
        this.Session.MoveMouseTo(x, y);
}
protected void AddScreenShotsToTestResultsDirectory()

View File

@@ -32,7 +32,6 @@ public partial class MainListPage : DynamicListPage,
public MainListPage(IServiceProvider serviceProvider)
{
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png");
PlaceholderText = Properties.Resources.builtin_main_list_page_searchbar_placeholder;
_serviceProvider = serviceProvider;
_tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;

View File

@@ -321,15 +321,6 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Search for apps, files and commands....
/// </summary>
public static string builtin_main_list_page_searchbar_placeholder {
get {
return ResourceManager.GetString("builtin_main_list_page_searchbar_placeholder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Creates a project for a new Command Palette extension.
/// </summary>

View File

@@ -227,7 +227,4 @@
<data name="builtin_disabled_extension" xml:space="preserve">
<value>Disabled</value>
</data>
<data name="builtin_main_list_page_searchbar_placeholder" xml:space="preserve">
<value>Search for apps, files and commands...</value>
</data>
</root>

View File

@@ -1,264 +0,0 @@
// 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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.CmdPal.UITests;
[TestClass]
public class AppsTests : CommandPaletteTestBase
{
public void EnterAppsExtension()
{
SetSearchBox("All Apps");
var searchFileItem = this.Find<NavigationViewItem>("All Apps");
Assert.AreEqual(searchFileItem.Name, "All Apps");
searchFileItem.DoubleClick();
}
public NavigationViewItem SearchAppByName(string name)
{
EnterAppsExtension();
SetAppsExtensionSearchBox(name);
var item = this.Find<NavigationViewItem>(name);
Assert.IsNotNull(item, $"{name} app not found.");
return item;
}
[TestMethod]
public void OpenWin32AppTest()
{
const string appName = "Notepad";
var notepadItem = SearchAppByName(appName);
notepadItem.DoubleClick();
var commandPromptWindow = FindWindowsTerminalWindow();
Assert.IsNotNull(commandPromptWindow, "Command Prompt window not found.");
}
[TestMethod]
public void OpenUWPAppTest()
{
const string appName = "Calculator";
var calculatorItem = SearchAppByName(appName);
calculatorItem.DoubleClick();
var calculatorWindow = this.Find<Window>("Calculator", global: true);
Assert.IsNotNull(calculatorWindow, "Calculator window not found.");
}
[TestMethod]
public void ClickPrimaryButtonTest()
{
const string appName = "Notepad";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
var primaryButton = this.Find<Button>("Run");
Assert.IsNotNull(primaryButton, "Primary button not found.");
primaryButton.Click();
var calculatorWindow = this.Find<Window>(By.ClassName("Notepad"), global: true, timeoutMS: 10000);
Assert.IsNotNull(calculatorWindow, "Notepad window not found.");
}
[STATestMethod]
[TestMethod]
public void ClickSecondaryButtonUWPAppTest()
{
const string appName = "Calculator";
var calculatorItem = SearchAppByName(appName);
calculatorItem.Click();
var secondaryButton = this.Find<Button>("Copy path");
Assert.IsNotNull(secondaryButton, "Secondary button not found.");
secondaryButton.Click();
var clipboardContent = System.Windows.Forms.Clipboard.GetText();
Assert.IsTrue(clipboardContent.Contains("Calculator"), $"Clipboard content does not contain the expected file name. clipboard: {clipboardContent}");
}
/*
[TestMethod]
public void ClickSecondaryButtonWin32AppTest()
{
const string appName = "Registry Editor";
var calculatorItem = SearchAppByName(appName);
calculatorItem.Click();
var secondaryButton = this.Find<Button>("Run as administrator");
Assert.IsNotNull(secondaryButton, "Secondary button not found.");
secondaryButton.Click();
UACConfirm();
var fileExplorerWindow = this.Find<Window>(By.ClassName("RegEdit_RegEdit"), global: true);
Assert.IsNotNull(fileExplorerWindow, "Registry Editor window not found.");
}*/
[TestMethod]
public void OpenContextMenuTest()
{
const string appName = "Notepad";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var pinButton = this.Find<NavigationViewItem>("Pin");
Assert.IsNotNull(pinButton);
}
[TestMethod]
public void ContextMenuRunButtonTest()
{
const string appName = "Notepad";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var runButton = this.Find<NavigationViewItem>("Run");
Assert.IsNotNull(runButton);
runButton.Click();
var notepadWindow = this.Find<Window>(By.ClassName("Notepad"), global: true);
Assert.IsNotNull(notepadWindow, "Notepad window not found.");
}
/*
[TestMethod]
public void ContextMenuRunAsAdminButtonTest()
{
const string appName = "Notepad";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var runButton = this.Find<NavigationViewItem>("Run as administrator");
Assert.IsNotNull(runButton);
runButton.Click();
UACConfirm();
var notepadWindow = this.Find<Window>(By.ClassName("Notepad"), global: true);
Assert.IsNotNull(notepadWindow, "Notepad window not found.");
}*/
[STATestMethod]
[TestMethod]
public void ContextMenuCopyPathButtonTest()
{
const string appName = "Notepad";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var copyPathButton = this.Find<NavigationViewItem>("Copy path");
Assert.IsNotNull(copyPathButton);
copyPathButton.Click();
var clipboardContent = System.Windows.Forms.Clipboard.GetText();
Assert.IsTrue(clipboardContent.Contains("Notepad"), $"Clipboard content does not contain the expected file name. clipboard: {clipboardContent}");
}
[TestMethod]
public void ContextMenuPinTest()
{
const string appName = "Notepad";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var pinButton = this.Find<NavigationViewItem>("Pin");
Assert.IsNotNull(pinButton);
pinButton.Click();
SetAppsExtensionSearchBox(string.Empty);
var item = this.Find<NavigationViewItem>(appName);
Assert.IsNotNull(item, $"{appName} app not found.");
OpenContextMenu();
var unPinButton = this.Find<NavigationViewItem>("Unpin");
Assert.IsNotNull(unPinButton);
unPinButton.Click();
SetAppsExtensionSearchBox(string.Empty);
}
[TestMethod]
public void ContextMenuOpenContainingFolderTest()
{
const string appName = "Calculator";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var openContainingFolderButton = this.Find<NavigationViewItem>("Open containing folder");
Assert.IsNotNull(openContainingFolderButton);
openContainingFolderButton.Click();
var fileExplorerWindow = FindFileExplorerWindow();
Assert.IsNotNull(fileExplorerWindow);
}
[TestMethod]
public void ContextMenuOpenPathInConsoleTest()
{
const string appName = "Notepad";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var openInConsoleButton = this.Find<NavigationViewItem>("Open path in console");
Assert.IsNotNull(openInConsoleButton);
openInConsoleButton.Click();
Task.Delay(2000).Wait(); // Wait for the console to open
var commandPromptWindow = FindWindowsTerminalWindow();
Assert.IsNotNull(commandPromptWindow, "Command Prompt window not found.");
}
[TestMethod]
public void ContextMenuOpenLocationTest()
{
const string appName = "Command Prompt";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var openLocationButton = this.Find<NavigationViewItem>("Open location");
Assert.IsNotNull(openLocationButton, "Open location button not found.");
openLocationButton.Click();
var fileExplorerWindow = FindFileExplorerWindow();
Assert.IsNotNull(fileExplorerWindow, "File Explorer window not found.");
}
[TestMethod]
public void ContextMenuSearchTest()
{
const string appName = "Command Prompt";
var notepadItem = SearchAppByName(appName);
notepadItem.Click();
OpenContextMenu();
var contextMenuSearchBox = this.Find<TextBox>("Search commands...");
Assert.IsNotNull(contextMenuSearchBox, "Context menu search box not found.");
Assert.AreEqual(contextMenuSearchBox.SetText("Open location", true).Text, "Open location");
var openLocationButton = this.Find<NavigationViewItem>("Open location");
Assert.IsNotNull(openLocationButton, "Open location button not found.");
openLocationButton.Click();
var fileExplore = FindFileExplorerWindow();
Assert.IsNotNull(fileExplore, "File Explorer window not found.");
}
}

View File

@@ -1,167 +0,0 @@
// 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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.CmdPal.UITests;
[TestClass]
public class CalculatorTests : CommandPaletteTestBase
{
public CalculatorTests()
: base()
{
}
public void EnterCalculatorExtension()
{
SetSearchBox("Calculator");
var calculatorItem = this.Find<NavigationViewItem>("Calculator");
Assert.AreEqual(calculatorItem.Name, "Calculator");
calculatorItem.DoubleClick();
}
private string ConvertResult(string originalResult, int originalBase, int convertToBase)
{
Assert.IsNotEmpty(originalResult, "Original result cannot be empty.");
Assert.IsTrue(originalBase is 2 or 10 or 16, "Original base must be one of the following: 2, 8, 10, or 16.");
Assert.IsTrue(convertToBase is 2 or 10 or 16, "Convert to base must be one of the following: 2, 8, 10, or 16.");
var originalDecimal = Convert.ToInt32(originalResult, originalBase);
// support base two, decimal, hexadecimal, and octal
return convertToBase switch
{
2 => $"0b{Convert.ToString(originalDecimal, 2)}",
10 => Convert.ToString(originalDecimal, 10),
16 => $"0x{Convert.ToString(originalDecimal, 16).ToUpper(System.Globalization.CultureInfo.CurrentCulture)}",
_ => throw new ArgumentOutOfRangeException(nameof(convertToBase), "Unsupported base conversion"),
};
}
[TestMethod]
[DataRow("2+2", "4")]
[DataRow("2*3", "6")]
[DataRow("2^3", "8")]
public void CalculatorBasicTests(string expression, string expectation)
{
EnterCalculatorExtension();
SetCalculatorExtensionSearchBox(expression);
var resultItem = this.Find<NavigationViewItem>(expectation);
Assert.IsNotNull(resultItem);
Assert.AreEqual(resultItem.Name, expectation, $"Expected result '{expectation}' not found for expression '{expression}'.");
}
[TestMethod]
[DataRow("2+2", "4")]
public void CalculatorResultDoubleClickTests(string expression, string expectation)
{
EnterCalculatorExtension();
SetCalculatorExtensionSearchBox(expression);
var resultItem = this.Find<NavigationViewItem>(expectation);
Assert.IsNotNull(resultItem);
Assert.AreEqual(resultItem.Name, expectation, $"Expected result '{expectation}' not found for expression '{expression}'.");
resultItem.DoubleClick();
var resultItems = this.FindAll<NavigationViewItem>(expectation);
Assert.AreEqual(2, resultItems.Count, $"Expected exactly two result item for '{expectation}' after double-clicking, but found {resultItems.Count}.");
}
[TestMethod]
[DataRow("2+2", "4")]
public void CalculatorPrimaryButtonTests(string expression, string expectation)
{
EnterCalculatorExtension();
SetCalculatorExtensionSearchBox(expression);
var resultItem = this.Find<NavigationViewItem>(expectation);
Assert.IsNotNull(resultItem);
Assert.AreEqual(resultItem.Name, expectation, $"Expected result '{expectation}' not found for expression '{expression}'.");
var primaryButton = this.Find<Button>("Save");
primaryButton.Click();
var resultItems = this.FindAll<NavigationViewItem>(expectation);
Assert.AreEqual(2, resultItems.Count, $"Expected exactly two result item for '{expectation}' after click primary button, but found {resultItems.Count}.");
}
[STATestMethod]
[TestMethod]
[DataRow("2+2", "4")]
public void CalculatorSecondaryButtonTests(string expression, string expectation)
{
EnterCalculatorExtension();
SetCalculatorExtensionSearchBox(expression);
var resultItem = this.Find<NavigationViewItem>(expectation);
Assert.IsNotNull(resultItem);
Assert.AreEqual(resultItem.Name, expectation, $"Expected result '{expectation}' not found for expression '{expression}'.");
var secondaryButton = this.Find<Button>("Copy");
secondaryButton.Click();
var clipboardContent = System.Windows.Forms.Clipboard.GetText();
Assert.IsTrue(clipboardContent.Equals(expectation, StringComparison.Ordinal), $"Clipboard content does not equal the expected result. clipboard: {clipboardContent}");
}
[STATestMethod]
[TestMethod]
[DataRow("2+2", "4")]
public void CalculatorContextMenuSaveTests(string expression, string expectation)
{
EnterCalculatorExtension();
SetCalculatorExtensionSearchBox(expression);
var resultItem = this.Find<NavigationViewItem>(expectation);
Assert.IsNotNull(resultItem);
Assert.AreEqual(resultItem.Name, expectation, $"Expected result '{expectation}' not found for expression '{expression}'.");
OpenContextMenu();
var saveItem = this.Find<NavigationViewItem>("Save");
saveItem.Click();
var clipboardContent = System.Windows.Forms.Clipboard.GetText();
Assert.IsTrue(clipboardContent.Equals(expectation, StringComparison.Ordinal), $"Clipboard content does not equal the expected result. clipboard: {clipboardContent}");
}
[STATestMethod]
[TestMethod]
[DataRow("2+2", "4", 10)]
[DataRow("0b10 * 0b10", "4", 2)]
[DataRow("0xa * 0xa", "100", 16)]
public void CalculatorContextMenuBaseConvertTests(string expression, string expectation, int originalBase)
{
EnterCalculatorExtension();
SetCalculatorExtensionSearchBox(expression);
var resultItem = this.Find<NavigationViewItem>(expectation);
Assert.IsNotNull(resultItem);
Assert.AreEqual(resultItem.Name, expectation, $"Expected result '{expectation}' not found for expression '{expression}'.");
OpenContextMenu();
var testBaseList = new List<int> { 2, 10, 16 };
foreach (var convertToBase in testBaseList)
{
var convertedResult = ConvertResult(expectation, 10, convertToBase);
var convertedItem = this.Find<NavigationViewItem>(convertedResult);
Assert.IsNotNull(convertedItem, $"Convert to base {convertToBase} item not found.");
}
var binaryResult = ConvertResult(expectation, 10, 2);
var binaryItem = this.Find<NavigationViewItem>(binaryResult);
binaryItem.Click();
var clipboardContent = System.Windows.Forms.Clipboard.GetText();
Assert.IsTrue(clipboardContent.Equals(binaryResult, StringComparison.Ordinal), $"Clipboard content does not equal the expected result. clipboard: {clipboardContent}");
}
}

View File

@@ -12,11 +12,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.CmdPal.UITests;
[TestClass]
public class CommandPaletteTestBase : UITestBase
{
public CommandPaletteTestBase()
: base(PowerToysModule.CommandPalette, hideAllWindowBeforeStart: true)
: base(PowerToysModule.CommandPalette)
{
}
@@ -40,21 +39,6 @@ public class CommandPaletteTestBase : UITestBase
Assert.AreEqual(this.Find<TextBox>("Search values or type a custom time stamp...").SetText(text, true).Text, text);
}
protected void SetAppsExtensionSearchBox(string text)
{
Assert.AreEqual(this.Find<TextBox>("Search installed apps...").SetText(text, true).Text, text);
}
protected void SetWindowsTerminalExtensionSearchBox(string text)
{
Assert.AreEqual(this.Find<TextBox>("Type here to search...").SetText(text, true).Text, text);
}
protected void SetWindowsSettingsExtensionSearchBox(string text)
{
Assert.AreEqual(this.Find<TextBox>("Type here to search...").SetText(text, true).Text, text);
}
protected void OpenContextMenu()
{
var contextMenuButton = this.Find<Button>("More");
@@ -62,24 +46,6 @@ public class CommandPaletteTestBase : UITestBase
contextMenuButton.Click();
}
protected Window FindFileExplorerWindow()
{
var fileExplorerWindow = this.Find<Window>(By.ClassName("CabinetWClass"), global: true, timeoutMS: 5000);
return fileExplorerWindow;
}
protected Window FindWindowsTerminalWindow()
{
var terminalWindow = this.Find<Window>(By.ClassName("CASCADIA_HOSTING_WINDOW_CLASS"), global: true, timeoutMS: 5000);
return terminalWindow;
}
protected Window FindWindowsSettingsWindow()
{
var settingsWindow = this.Find<Window>("Settings", global: true, timeoutMS: 5000);
return settingsWindow;
}
protected void FindDefaultAppDialogAndClickButton()
{
try

View File

@@ -114,10 +114,9 @@ public class IndexerTests : CommandPaletteTestBase
Assert.IsNotNull(openButton);
openButton.Click();
var fileExplorer = FindExplorerWindow(TestFolderName, global: true);
var fileExplorerWindow = FindFileExplorerWindow();
Assert.IsNotNull(fileExplorerWindow);
Assert.IsNotNull(fileExplorer);
}
[TestMethod]
@@ -130,9 +129,9 @@ public class IndexerTests : CommandPaletteTestBase
Assert.IsNotNull(searchItem);
searchItem.DoubleClick();
var fileExplorerWindow = FindFileExplorerWindow();
var fileExplorer = FindExplorerWindow(TestFolderName, global: true);
Assert.IsNotNull(fileExplorerWindow);
Assert.IsNotNull(fileExplorer);
}
[TestMethod]
@@ -189,9 +188,9 @@ public class IndexerTests : CommandPaletteTestBase
Assert.IsNotNull(showInFolderButton);
showInFolderButton.Click();
var fileExplorerWindow = FindFileExplorerWindow();
var fileExplorer = FindExplorerWindow(TestFolderName, global: true, timeoutMS: 20000);
Assert.IsNotNull(fileExplorerWindow);
Assert.IsNotNull(fileExplorer);
}
[TestMethod]
@@ -209,8 +208,8 @@ public class IndexerTests : CommandPaletteTestBase
Assert.IsNotNull(copyPathButton);
copyPathButton.Click();
var terminalWindow = FindWindowsTerminalWindow();
Assert.IsNotNull(terminalWindow, "The console did not open with the expected path.");
var textItem = FindByPartialName("C:\\Windows\\system32\\cmd.exe", global: true);
Assert.IsNotNull(textItem, "The console did not open with the expected path.");
}
[TestMethod]

View File

@@ -1,76 +0,0 @@
// 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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Windows.Graphics;
namespace Microsoft.CmdPal.UITests;
public class WindowsSettingsTests : CommandPaletteTestBase
{
public void EnterWindowsSettingsExtension()
{
SetSearchBox("Windows Settings");
var searchFileItem = this.Find<NavigationViewItem>("Windows Settings");
Assert.AreEqual(searchFileItem.Name, "Windows Settings");
searchFileItem.DoubleClick();
}
public NavigationViewItem SearchWindowsSettingsByName(string name)
{
EnterWindowsSettingsExtension();
SetWindowsSettingsExtensionSearchBox(name);
var item = this.Find<NavigationViewItem>(name);
Assert.IsNotNull(item, $"{name} setting not found.");
return item;
}
[TestMethod]
public void OpenDisplaySettingsTest()
{
const string settingName = "Display";
var displaySettingItem = SearchWindowsSettingsByName(settingName);
displaySettingItem.DoubleClick();
var settings = FindWindowsSettingsWindow();
Assert.IsNotNull(settings, "Display settings window not found.");
}
[TestMethod]
public void OpenDisplaySettingsByPrimaryButtonTest()
{
const string settingName = "Display";
var displaySettingItem = SearchWindowsSettingsByName(settingName);
displaySettingItem.Click();
var primaryButton = this.Find<Button>("Open Settings");
Assert.IsNotNull(primaryButton, "Primary button not found.");
primaryButton.Click();
var settings = FindWindowsSettingsWindow();
Assert.IsNotNull(settings, "Display settings window not found.");
}
[TestMethod]
[STATestMethod]
public void OpenDisplaySettingsSecondaryButtonTest()
{
const string settingName = "Display";
var displaySettingItem = SearchWindowsSettingsByName(settingName);
displaySettingItem.Click();
var secondaryButton = this.Find<Button>("Copy command");
Assert.IsNotNull(secondaryButton, "Secondary button not found.");
secondaryButton.Click();
var clipboardContent = System.Windows.Forms.Clipboard.GetText();
Assert.IsTrue(clipboardContent.Contains("ms - settings:easeofaccess - display"), $"Clipboard content does not contain the expected command. clipboard: {clipboardContent}");
}
}

View File

@@ -1,99 +0,0 @@
// 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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.CmdPal.UITests;
[TestClass]
public class WindowsTerminalTests : CommandPaletteTestBase
{
public void EnterWindowsTerminalExtension()
{
SetSearchBox("Open Windows Terminal Profiles");
var searchFileItem = this.Find<NavigationViewItem>("Open Windows Terminal Profiles");
Assert.AreEqual(searchFileItem.Name, "Open Windows Terminal Profiles");
searchFileItem.DoubleClick();
}
public NavigationViewItem SearchTerminalProfileName(string name)
{
EnterWindowsTerminalExtension();
SetWindowsTerminalExtensionSearchBox(name);
var item = this.Find<NavigationViewItem>(name);
Assert.IsNotNull(item, $"{name} profile not found.");
return item;
}
[TestMethod]
public void OpenCommandPromptTest()
{
const string profileName = "Command Prompt";
var terminalProfileItem = SearchTerminalProfileName(profileName);
terminalProfileItem.DoubleClick();
var commandPromptWindow = FindWindowsTerminalWindow();
Assert.IsNotNull(commandPromptWindow, "Command Prompt window not found.");
}
[TestMethod]
public void OpenCommandPromptByPrimaryButtonTest()
{
const string profileName = "Command Prompt";
var terminalProfileItem = SearchTerminalProfileName(profileName);
terminalProfileItem.Click();
var primaryButton = this.Find<Button>("Launch profile");
Assert.IsNotNull(primaryButton, "Primary button not found.");
primaryButton.Click();
var commandPromptWindow = FindWindowsTerminalWindow();
Assert.IsNotNull(commandPromptWindow, "Command Prompt window not found.");
}
/*
[TestMethod]
public void OpenCommandPromptBySecondaryButtonTest()
{
const string profileName = "Command Prompt";
var terminalProfileItem = SearchTerminalProfileName(profileName);
terminalProfileItem.Click();
var secondaryButton = this.Find<Button>("Launch profile as administrator");
Assert.IsNotNull(secondaryButton, "Secondary button not found.");
secondaryButton.Click();
UACConfirm();
var commandPromptWindow = FindWindowsTerminalWindow();
Assert.IsNotNull(commandPromptWindow, "Command Prompt window not found.");
}*/
[TestMethod]
public void OpenDeveloperCommandPromptTest()
{
const string profileName = "Developer Command Prompt for VS 2022";
var terminalProfileItem = SearchTerminalProfileName(profileName);
terminalProfileItem.DoubleClick();
var commandPromptWindow = FindWindowsTerminalWindow();
Assert.IsNotNull(commandPromptWindow, "Command Prompt window not found.");
}
[TestMethod]
public void OpenGitBashTest()
{
const string profileName = "Git Bash";
var terminalProfileItem = SearchTerminalProfileName(profileName);
terminalProfileItem.DoubleClick();
var commandPromptWindow = FindWindowsTerminalWindow();
Assert.IsNotNull(commandPromptWindow, "Command Prompt window not found.");
}
}