UI Test Automation (#39777)

### Summary

This pull request includes the following updates:

1. Improvements and stabilization of the UI automation framework  
2. Setup of the UI automation pipeline  
3. Add UI test cases for FancyZones  
4. Add UI test cases for MouseUtils  
5. Improvements of Hosts Editor UI tests

---

### Related Links

- **Current Release checklist coverage**:  
 
https://github.com/microsoft/PowerToys/blob/feature/UITestAutomation/src/common/UITestAutomation/Doc/ui-automation-cover-list.md

- **UI Automation pipeline**:  
 
https://microsoft.visualstudio.com/Dart/_build?definitionId=161438&_a=summary

---------

Signed-off-by: Shawn Yuan <shuai.yuan.zju@gmail.com>
Signed-off-by: Shawn Yuan <shuaiyuan@microsoft.com>
Co-authored-by: Jerry Xu <n.xu@outlook.com>
Co-authored-by: Zhaopeng Wang <zhaopengwang@microsoft.com>
Co-authored-by: Xiaofeng Wang (from Dev Box) <xiaofengwang@microsoft.com>
Co-authored-by: Mengyuan <162882040+chenmy77@users.noreply.github.com>
Co-authored-by: yaqingmi <miyaqing01@gmail.com>
Co-authored-by: Clint Rutkas <clint@rutkas.com>
Co-authored-by: Yaqing Mi (from Dev Box) <yaqingmi@microsoft.com>
Co-authored-by: Kai Tao <69313318+vanzue@users.noreply.github.com>
Co-authored-by: zhaopeng wang <33367956+wang563681252@users.noreply.github.com>
Co-authored-by: Laszlo Nemeth <57342539+donlaci@users.noreply.github.com>
Co-authored-by: RokyZevon <12629919+RokyZevon@users.noreply.github.com>
Co-authored-by: Yu Leng <42196638+moooyo@users.noreply.github.com>
Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Davide Giacometti <25966642+davidegiacometti@users.noreply.github.com>
Co-authored-by: Gordon Lam <73506701+yeelam-gordon@users.noreply.github.com>
Co-authored-by: ruslanlap <106077551+ruslanlap@users.noreply.github.com>
Co-authored-by: Muhammad Danish <mdanishkhdev@gmail.com>
Co-authored-by: Bennett Blodinger <benwa@users.noreply.github.com>
Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
Co-authored-by: Ionuț Manța <ionut@janeasystems.com>
Co-authored-by: Hao Liu <liuhaobupt@163.com>
Co-authored-by: OlegHarchevkin <40352094+OlegKharchevkin@users.noreply.github.com>
Co-authored-by: dcog989 <89043002+dcog989@users.noreply.github.com>
Co-authored-by: PesBandi <127593627+PesBandi@users.noreply.github.com>
Co-authored-by: Stefan Markovic <57057282+stefansjfw@users.noreply.github.com>
Co-authored-by: vanzue <vanzue@outlook.com>
Co-authored-by: Typpi <20943337+Nick2bad4u@users.noreply.github.com>
Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Abhyudit <64366765+bitmap4@users.noreply.github.com>
Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com>
Co-authored-by: Ved Nig <vednig12@outlook.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Aung Khaing Khant <aungkhaingkhant.dev@gmail.com>
Co-authored-by: Aung Khaing Khant <aungkhaingkhant@advent-soft.com>
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
Co-authored-by: leileizhang <leilzh@microsoft.com>
Co-authored-by: Dustin L. Howett <dustin@howett.net>
Co-authored-by: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com>
Co-authored-by: Shawn Yuan <shuai.yuan.zju@gmail.com>
Co-authored-by: cryolithic <cryolithic@gmail.com>
Co-authored-by: Lemonyte <49930425+lemonyte@users.noreply.github.com>
Co-authored-by: Gordon Lam (SH) <yeelam@microsoft.com>
Co-authored-by: Corey Hayward <72159232+CoreyHayward@users.noreply.github.com>
Co-authored-by: Jerry Xu <nxu@microsoft.com>
Co-authored-by: Shawn Yuan <shuaiyuan@microsoft.com>
Co-authored-by: Kayla Cinnamon <cinnamon@microsoft.com>
Co-authored-by: Jeremy Sinclair <4016293+snickler@users.noreply.github.com>
This commit is contained in:
XiaofengWang
2025-06-17 17:56:48 +08:00
committed by GitHub
parent c487638758
commit 350b9b78fe
81 changed files with 7979 additions and 650 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -13,7 +13,7 @@ namespace Hosts.UITests
public class HostModuleTests : UITestBase
{
public HostModuleTests()
: base(PowerToysModule.Hosts)
: base(PowerToysModule.Hosts, WindowSize.Small_Vertical)
{
}
@@ -31,14 +31,17 @@ namespace Hosts.UITests
/// </item>
/// </list>
/// </summary>
[TestMethod]
[TestMethod("Hosts.Basic.EmptyViewShouldWork")]
[TestCategory("Hosts File Editor #4")]
public void TestEmptyView()
{
this.CloseWarningDialog();
this.RemoveAllEntries();
// 'Add an entry' button (only show-up when list is empty) should be visible
Assert.IsTrue(this.FindAll<HyperlinkButton>("Add an entry").Count == 1, "'Add an entry' button should be visible in the empty view");
Assert.IsTrue(this.HasOne<HyperlinkButton>("Add an entry"), "'Add an entry' button should be visible in the empty view");
VisualAssert.AreEqual(this.TestContext, this.Find("Entries"), "EmptyView");
// Click 'Add an entry' from empty-view for adding Host override rule
this.Find<HyperlinkButton>("Add an entry").Click();
@@ -46,8 +49,10 @@ namespace Hosts.UITests
this.AddEntry("192.168.0.1", "localhost", false, false);
// Should have one row now and not more empty view
Assert.IsTrue(this.FindAll<Button>("Delete").Count == 1, "Should have one row now");
Assert.IsTrue(this.FindAll<HyperlinkButton>("Add an entry").Count == 0, "'Add an entry' button should be invisible if not empty view");
Assert.IsTrue(this.Has<Button>("Delete"), "Should have one row now");
Assert.IsFalse(this.Has<HyperlinkButton>("Add an entry"), "'Add an entry' button should be invisible if not empty view");
VisualAssert.AreEqual(this.TestContext, this.Find("Entries"), "NonEmptyView");
}
/// <summary>
@@ -58,17 +63,20 @@ namespace Hosts.UITests
/// </item>
/// </list>
/// </summary>
[TestMethod]
[TestMethod("Hosts.Basic.AddEntryButtonShouldWork")]
[TestCategory("Hosts File Editor #4")]
public void TestAddingEntry()
{
this.CloseWarningDialog();
this.RemoveAllEntries();
Assert.IsTrue(this.FindAll<Button>("Delete").Count == 0, "Should have no row after removing all");
Assert.IsFalse(this.Has<Button>("Delete"), "Should have no row after removing all");
this.AddEntry("192.168.0.1", "localhost", true);
Assert.IsTrue(this.FindAll<Button>("Delete").Count == 1, "Should have one row now");
Assert.IsTrue(this.Has<Button>("Delete"), "Should have one row now");
VisualAssert.AreEqual(this.TestContext, this.Find("Entries"));
}
/// <summary>
@@ -82,7 +90,8 @@ namespace Hosts.UITests
/// </item>
/// </list>
/// </summary>
[TestMethod]
[TestMethod("Hosts.Basic.CanNotAddMoreThenNighHosts")]
[TestCategory("Hosts File Editor #5")]
public void TestTooManyHosts()
{
this.CloseWarningDialog();
@@ -116,18 +125,48 @@ namespace Hosts.UITests
/// </item>
/// </list>
/// </summary>
[TestMethod]
[TestMethod("Hosts.Basic.ErrorMessageShowupIfNotRunAsAdmin")]
[TestCategory("Hosts File Editor #8")]
public void TestErrorMessageWithNonAdminPermission()
{
this.CloseWarningDialog();
this.RemoveAllEntries();
if (this.Session.IsElevated == false)
{
this.CloseWarningDialog();
this.RemoveAllEntries();
// Add new URL override and a warning tip should be shown
this.AddEntry("192.168.0.1", "localhost", true);
// Add new URL override and a warning tip should be shown
this.AddEntry("192.168.0.1", "localhost", true);
Assert.IsTrue(
this.FindAll<TextBlock>("The hosts file cannot be saved because the program isn't running as administrator.").Count == 1,
"Should display host-file saving error if not run as administrator");
Assert.IsTrue(
this.FindAll<TextBlock>("The hosts file cannot be saved because the program isn't running as administrator.").Count == 1,
"Should display host-file saving error if not run as administrator");
}
}
/// <summary>
/// Test No Error-message in the Hosts-File-Editor
/// <list type="bullet">
/// <item>
/// <description>Validating error message should be shown if not run as admin.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("Hosts.Basic.NoErrorMessageShowupIfRunAsAdmin")]
[TestCategory("Hosts File Editor #8")]
public void TestNoErrorMessageWithNonAdminPermission()
{
if (this.Session.IsElevated == true)
{
this.CloseWarningDialog();
this.RemoveAllEntries();
// Add new URL override and a warning tip should be shown
this.AddEntry("192.168.0.1", "localhost", true);
Assert.IsFalse(
this.FindAll<TextBlock>("The hosts file cannot be saved because the program isn't running as administrator.").Count > 0,
"Should display host-file saving error if not run as administrator");
}
}
/// <summary>
@@ -144,7 +183,8 @@ namespace Hosts.UITests
/// </item>
/// </list>
/// </summary>
[TestMethod]
[TestMethod("Hosts.Basic.FiltersControlShouldWork")]
[TestCategory("Hosts File Editor #6")]
public void TestFilterControl()
{
this.CloseWarningDialog();
@@ -212,7 +252,7 @@ namespace Hosts.UITests
// Close-filter-panel
this.Find<Button>("Filters").Click();
Assert.IsFalse(this.FindAll<Button>("Clear filters").Count == 1, "Filter panel should be closed afer click Filter Button");
Assert.IsFalse(this.FindAll<Button>("Clear filters").Count == 1, "Filter panel should be closed after clicking Filter Button");
}
private void AddEntry(string ip, string host, bool active = true, bool clickAddEntryButton = true)
@@ -243,25 +283,25 @@ namespace Hosts.UITests
private void CloseWarningDialog()
{
// Find 'Accept' button which come in 'Warning' dialog
if (this.FindAll("Warning").Count > 0 &&
this.FindAll<Button>("Accept").Count > 0)
if (this.FindAll("Warning", 1000).Count > 0 &&
this.FindAll<Button>("Accept", 1000).Count > 0)
{
// Hide Warning dialog if any
this.Find<Button>("Accept").Click();
this.Find<Button>("Accept", 1000).Click();
}
}
private void RemoveAllEntries()
{
// Delete all existing host-override rules
foreach (var deleteBtn in this.FindAll<Button>("Delete"))
foreach (var deleteBtn in this.FindAll<Button>("Delete", 1000))
{
deleteBtn.Click();
this.Find<Button>("Yes").Click();
this.Find<Button>("Yes", 1000).Click();
}
// Should have no row left, and no more delete button
Assert.IsTrue(this.FindAll<Button>("Delete").Count == 0);
Assert.IsTrue(this.FindAll<Button>("Delete", 1000).Count == 0);
}
}
}

View File

@@ -17,6 +17,17 @@
<PropertyGroup>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\tests\Hosts.UITests\</OutputPath>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Baseline\HostModuleTests_TestAddingEntry_arm64.png" />
<EmbeddedResource Include="Baseline\HostModuleTests_TestEmptyView_EmptyView_arm64.png" />
<EmbeddedResource Include="Baseline\HostModuleTests_TestEmptyView_NonEmptyView_arm64.png" />
<EmbeddedResource Include="Baseline\HostModuleTests_TestAddingEntry_x64Win10.png" />
<EmbeddedResource Include="Baseline\HostModuleTests_TestEmptyView_EmptyView_x64Win10.png" />
<EmbeddedResource Include="Baseline\HostModuleTests_TestEmptyView_NonEmptyView_x64Win10.png" />
<EmbeddedResource Include="Baseline\HostModuleTests_TestAddingEntry_x64Win11.png" />
<EmbeddedResource Include="Baseline\HostModuleTests_TestEmptyView_EmptyView_x64Win11.png" />
<EmbeddedResource Include="Baseline\HostModuleTests_TestEmptyView_NonEmptyView_x64Win11.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MSTest" />

View File

@@ -12,6 +12,11 @@ namespace Hosts.UITests
[TestClass]
public class HostsSettingTests : UITestBase
{
public HostsSettingTests()
: base(PowerToysModule.PowerToysSettings, WindowSize.Medium)
{
}
/// <summary>
/// Test Warning Dialog at startup
/// <list type="bullet">
@@ -29,7 +34,9 @@ namespace Hosts.UITests
/// </item>
/// </list>
/// </summary>
[TestMethod]
[TestMethod("Hosts.Settings.ShowWarningDialogIfRunAsAdmin")]
[TestCategory("Hosts File Editor #1")]
[TestCategory("Hosts File Editor #9")]
public void TestWarningDialog()
{
this.LaunchFromSetting(showWarning: true);
@@ -51,10 +58,7 @@ namespace Hosts.UITests
this.Find<Button>("Launch Hosts File Editor").Click();
// wait for 500 ms to make sure Hosts File Editor is launched
Task.Delay(500).Wait();
this.Session.Attach(PowerToysModule.Hosts);
this.Session.Attach(PowerToysModule.Hosts, WindowSize.Small_Vertical);
// Should show warning dialog
Assert.IsTrue(this.FindAll("Warning").Count > 0, "Should show warning dialog");
@@ -68,7 +72,7 @@ namespace Hosts.UITests
Assert.IsFalse(this.IsHostsFileEditorClosed(), "Hosts File Editor should NOT be closed after click Accept button in Warning Dialog");
// Close Hosts File Editor window
this.Session.Find<Window>("Hosts File Editor").Close();
this.Session.CloseMainWindow();
// Restore back to PowerToysSettings Session
this.Session.Attach(PowerToysModule.PowerToysSettings);
@@ -82,7 +86,7 @@ namespace Hosts.UITests
Assert.IsFalse(this.IsHostsFileEditorClosed(), "Hosts File Editor should NOT be closed");
// Close Hosts File Editor window
this.Session.Find<Window>("Hosts File Editor").Close();
this.Session.CloseMainWindow();
// Restore back to PowerToysSettings Session
this.Session.Attach(PowerToysModule.PowerToysSettings);
@@ -90,14 +94,9 @@ namespace Hosts.UITests
private bool IsHostsFileEditorClosed()
{
try
if (this.Session.FindAll<Window>("Hosts File Editor").Count == 0 && this.Session.FindAll<Window>("Administrator: Hosts File Editor").Count == 0)
{
this.Session.FindAll<Window>("Hosts File Editor");
}
catch (Exception ex)
{
// Validate if editor window closed by checking exception.Message
return ex.Message.Contains("Currently selected window has been closed");
return true;
}
return false;
@@ -121,7 +120,7 @@ namespace Hosts.UITests
// launch Hosts File Editor
this.Find<Button>("Launch Hosts File Editor").Click();
Task.Delay(500).Wait();
Task.Delay(2000).Wait();
this.Session.Attach(PowerToysModule.Hosts);
}

View File

@@ -0,0 +1,640 @@
// 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.Globalization;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Windows.Devices.Printers;
namespace MouseUtils.UITests
{
[TestClass]
public class FindMyMouseTests : UITestBase
{
/// <summary>
/// Test Warning Dialog at startup
/// <list type="bullet">
/// <item>
/// <description>Validating Warning-Dialog will be shown if 'Show a warning at startup' toggle is On.</description>
/// </item>
/// <item>
/// <description>Validating Warning-Dialog will NOT be shown if 'Show a warning at startup' toggle is Off.</description>
/// </item>
/// <item>
/// <description>Validating click 'Quit' button in Warning-Dialog, the Hosts File Editor window would be closed.</description>
/// </item>
/// <item>
/// <description>Validating click 'Accept' button in Warning-Dialog, the Hosts File Editor window would NOT be closed.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("MouseUtils.FindMyMouse.EnableFindMyMouse")]
[TestCategory("Mouse Utils #1")]
[TestCategory("Mouse Utils #2")]
[TestCategory("Mouse Utils #3")]
[TestCategory("Mouse Utils #4")]
public void TestEnableFindMyMouse()
{
LaunchFromSetting();
var settings = new FindMyMouseSettings();
settings.OverlayOpacity = "100";
settings.Radius = "50";
settings.InitialZoom = "1";
settings.AnimationDuration = "0";
settings.BackgroundColor = "000000";
settings.SpotlightColor = "FFFFFF";
var foundCustom = this.Find<Custom>("Find My Mouse");
Assert.IsNotNull(foundCustom);
if (CheckAnimationEnable(ref foundCustom))
{
foundCustom = this.Find<Custom>("Find My Mouse");
}
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom, "Find My Mouse group not found.");
SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
if (excludedApps != null)
{
excludedApps.Click();
excludedApps.Click();
}
else
{
Assert.Fail("Activation method group not found.");
}
}
else
{
Assert.Fail("Find My Mouse group not found.");
}
// [Test Case]Enable FindMyMouse. Then, without moving your mouse: Press Left Ctrl twice and verify the overlay appears.
VerifySpotlightSettings(ref settings);
// [Test Case]Enable FindMyMouse. Then, without moving your mouse: Press any other key and verify the overlay disappears.
Session.SendKeys(Key.A);
VerifySpotlightDisappears(ref settings);
// [Test Case]Enable FindMyMouse. Then, without moving your mouse: Press Left Ctrl twice and verify the overlay appears.
VerifySpotlightSettings(ref settings);
// [Test Case]Enable FindMyMouse. Then, without moving your mouse: Press a mouse button and verify the overlay disappears.
Task.Delay(1000).Wait();
Session.PerformMouseAction(MouseActionType.LeftClick, 500, 1000);
VerifySpotlightDisappears(ref settings);
}
[TestMethod("MouseUtils.FindMyMouse.FindMyMouseDifferentSettings")]
[TestCategory("Mouse Utils #10")]
[TestCategory("Mouse Utils #11")]
[TestCategory("Mouse Utils #12")]
public void TestFindMyMouseDifferentSettings()
{
LaunchFromSetting();
var settings = new FindMyMouseSettings();
settings.OverlayOpacity = "100";
settings.Radius = "80";
settings.InitialZoom = "1";
settings.AnimationDuration = "0";
settings.BackgroundColor = "FF0000";
settings.SpotlightColor = "0000FF";
var foundCustom = this.Find<Custom>("Find My Mouse");
Assert.IsNotNull(foundCustom);
if (CheckAnimationEnable(ref foundCustom))
{
foundCustom = this.Find<Custom>("Find My Mouse");
}
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom, "Find My Mouse group not found.");
SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
if (excludedApps != null)
{
excludedApps.Click();
excludedApps.Click();
}
else
{
Assert.Fail("Excluded apps group not found.");
}
}
else
{
Assert.Fail("Find My Mouse group not found.");
}
// [Test Case]Test the different settings and verify they apply, Background color
// [Test Case]Test the different settings and verify they apply, Spotlight color
// [Test Case]Test the different settings and verify they apply, Spotlight radius
VerifySpotlightSettings(ref settings);
Session.SendKeys(Key.A);
VerifySpotlightDisappears(ref settings);
}
[TestMethod("MouseUtils.FindMyMouse.DisableFindMyMouse")]
[TestCategory("Mouse Utils #5")]
[TestCategory("Mouse Utils #6")]
public void TestDisableFindMyMouse()
{
LaunchFromSetting();
var settings = new FindMyMouseSettings();
settings.OverlayOpacity = "100";
settings.Radius = "50";
settings.InitialZoom = "1";
settings.AnimationDuration = "0";
settings.BackgroundColor = "000000";
settings.SpotlightColor = "FFFFFF";
var foundCustom = this.Find<Custom>("Find My Mouse");
Assert.IsNotNull(foundCustom);
if (CheckAnimationEnable(ref foundCustom))
{
foundCustom = this.Find<Custom>("Find My Mouse");
}
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom);
SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
if (excludedApps != null)
{
excludedApps.Click();
excludedApps.Click();
}
else
{
Assert.Fail("Activation method group not found.");
}
}
else
{
Assert.Fail("Find My Mouse group not found.");
}
// [Test Case]Enable FindMyMouse. Then, without moving your mouse: Press Left Ctrl twice and verify the overlay appears.
// VerifySpotlightSettings(ref settings);
ActivateSpotlight(ref settings);
VerifySpotlightAppears(ref settings);
// [Test Case] Disable FindMyMouse. Verify the overlay no longer appears when you press Left Ctrl twice
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
Task.Delay(1000).Wait();
ActivateSpotlight(ref settings);
VerifySpotlightDisappears(ref settings);
// [Test Case] Press Left Ctrl twice and verify the overlay appears
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
Task.Delay(2000).Wait();
ActivateSpotlight(ref settings);
VerifySpotlightAppears(ref settings);
Session.PerformMouseAction(MouseActionType.LeftClick);
}
[TestMethod("MouseUtils.FindMyMouse.DisableFindMyMouse3")]
[TestCategory("Mouse Utils #6")]
public void TestDisableFindMyMouse3()
{
LaunchFromSetting();
var settings = new FindMyMouseSettings();
settings.OverlayOpacity = "100";
settings.Radius = "50";
settings.InitialZoom = "1";
settings.AnimationDuration = "0";
settings.BackgroundColor = "000000";
settings.SpotlightColor = "FFFFFF";
var foundCustom = this.Find<Custom>("Find My Mouse");
Assert.IsNotNull(foundCustom);
if (CheckAnimationEnable(ref foundCustom))
{
foundCustom = this.Find<Custom>("Find My Mouse");
}
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom);
SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
if (excludedApps != null)
{
excludedApps.Click();
excludedApps.Click();
}
else
{
Assert.Fail("Activation method group not found.");
}
}
else
{
Assert.Fail("Find My Mouse group not found.");
}
// [Test Case]Enable FindMyMouse. Then, without moving your mouse: Press Left Ctrl twice and verify the overlay appears.
// VerifySpotlightSettings(ref settings);
ActivateSpotlight(ref settings);
VerifySpotlightAppears(ref settings);
// [Test Case] Disable FindMyMouse. Verify the overlay no longer appears when you press Left Ctrl twice
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
Task.Delay(1000).Wait();
ActivateSpotlight(ref settings);
VerifySpotlightDisappears(ref settings);
// [Test Case] Press Left Ctrl twice and verify the overlay appears
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
Task.Delay(2000).Wait();
ActivateSpotlight(ref settings);
VerifySpotlightAppears(ref settings);
Session.PerformMouseAction(MouseActionType.LeftClick);
}
[TestMethod("MouseUtils.FindMyMouse.DisableFindMyMouse2")]
[TestCategory("Mouse Utils #5")]
public void TestDisableFindMyMouse2()
{
LaunchFromSetting();
var settings = new FindMyMouseSettings();
settings.OverlayOpacity = "100";
settings.Radius = "50";
settings.InitialZoom = "1";
settings.AnimationDuration = "0";
settings.BackgroundColor = "000000";
settings.SpotlightColor = "FFFFFF";
var foundCustom = this.Find<Custom>("Find My Mouse");
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
// foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom, "Find My Mouse group not found.");
// SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
if (excludedApps != null)
{
excludedApps.Click();
excludedApps.Click();
}
else
{
Assert.Fail("Activation method group not found.");
}
}
else
{
Assert.Fail("Find My Mouse group not found.");
}
// [Test Case]Enable FindMyMouse. Then, without moving your mouse: Press Left Ctrl twice and verify the overlay appears.
// VerifySpotlightSettings(ref settings);
// [Test Case] Disable FindMyMouse. Verify the overlay no longer appears when you press Left Ctrl twice
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
Task.Delay(2000).Wait();
Session.SendKey(Key.LCtrl, 0, 0);
Task.Delay(100).Wait();
Session.SendKey(Key.LCtrl, 0, 0);
VerifySpotlightDisappears(ref settings);
}
private void VerifySpotlightDisappears(ref FindMyMouseSettings settings)
{
Task.Delay(2000).Wait();
var location = Session.GetMousePosition();
int radius = int.Parse(settings.Radius, CultureInfo.InvariantCulture);
var colorSpotlight = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreNotEqual("#" + settings.SpotlightColor, colorSpotlight);
var colorBackground = this.GetPixelColorString(location.Item1 + radius + 50, location.Item2 + radius + 50);
Assert.AreNotEqual("#" + settings.BackgroundColor, colorBackground);
var colorBackground2 = this.GetPixelColorString(location.Item1 + radius + 100, location.Item2 + radius + 100);
Assert.AreNotEqual("#" + settings.BackgroundColor, colorBackground2);
}
private void VerifySpotlightAppears(ref FindMyMouseSettings settings)
{
Task.Delay(2000).Wait();
var location = Session.GetMousePosition();
int radius = int.Parse(settings.Radius, CultureInfo.InvariantCulture);
var colorSpotlight = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreEqual("#" + settings.SpotlightColor, colorSpotlight);
var colorSpotlight2 = this.GetPixelColorString(location.Item1 + radius - 1, location.Item2);
// Session.MoveMouseTo(location.Item1 + radius - 10, location.Item2);
Assert.AreEqual("#" + settings.SpotlightColor, colorSpotlight2);
Task.Delay(100).Wait();
var colorBackground = this.GetPixelColorString(location.Item1 + radius + 50, location.Item2 + radius + 50);
Assert.AreEqual("#" + settings.BackgroundColor, colorBackground);
var colorBackground2 = this.GetPixelColorString(location.Item1 + radius + 100, location.Item2 + radius + 100);
Assert.AreEqual("#" + settings.BackgroundColor, colorBackground2);
}
private void ActivateSpotlight(ref FindMyMouseSettings settings)
{
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1 - 200, xy.Item2 - 100);
Task.Delay(1000).Wait();
Session.PerformMouseAction(MouseActionType.LeftClick);
Task.Delay(1000).Wait();
if (settings.SelectedActivationMethod == FindMyMouseSettings.ActivationMethod.PressLeftControlTwice)
{
Session.SendKey(Key.LCtrl, 0, 0);
Task.Delay(200).Wait();
Session.SendKey(Key.LCtrl, 0, 0);
}
else if (settings.SelectedActivationMethod == FindMyMouseSettings.ActivationMethod.PressRightControlTwice)
{
Session.SendKey(Key.RCtrl, 0, 0);
Task.Delay(200).Wait();
Session.SendKey(Key.RCtrl, 0, 0);
}
else if (settings.SelectedActivationMethod == FindMyMouseSettings.ActivationMethod.ShakeMouse)
{
// Simulate shake mouse;
}
else if (settings.SelectedActivationMethod == FindMyMouseSettings.ActivationMethod.CustomShortcut)
{
// Simulate custom shortcut
}
}
private void VerifySpotlightSettings(ref FindMyMouseSettings settings, bool equal = true)
{
ActivateSpotlight(ref settings);
VerifySpotlightAppears(ref settings);
}
private void SetFindMyMouseActivationMethod(ref Custom? foundCustom, string method)
{
Assert.IsNotNull(foundCustom);
var groupActivation = foundCustom.Find<TextBlock>("Activation method");
if (groupActivation != null)
{
groupActivation.Click();
string findMyMouseComboBoxKey = "Activation method";
var foundElements = foundCustom.FindAll<ComboBox>(findMyMouseComboBoxKey);
if (foundElements.Count != 0)
{
var myMouseComboBox = foundCustom.Find<ComboBox>(findMyMouseComboBoxKey);
Assert.IsNotNull(myMouseComboBox);
myMouseComboBox.Click();
var selectedItem = myMouseComboBox.Find<NavigationViewItem>(method);
Assert.IsNotNull(selectedItem);
selectedItem.Click();
}
else
{
Assert.IsTrue(false, "ComboBox is not found in the setting page.");
}
}
else
{
Assert.Fail("Activation method group not found.");
}
}
private void SetFindMyMouseAppearanceBehavior(ref Custom foundCustom, ref FindMyMouseSettings settings)
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
if (groupAppearanceBehavior != null)
{
// groupAppearanceBehavior.Click();
if (foundCustom.FindAll<Slider>("Overlay opacity (%)").Count == 0)
{
groupAppearanceBehavior.Click();
}
// Set the BackGround color
var backgroundColor = foundCustom.Find<Group>("Background color");
Assert.IsNotNull(backgroundColor);
var button = backgroundColor.Find<Button>(By.XPath(".//Button"));
Assert.IsNotNull(button);
button.Click();
var popupWindow = this.Find<Window>("Popup");
Assert.IsNotNull(popupWindow);
Task.Delay(1000).Wait();
var colorModelComboBox = this.Find<ComboBox>("Color model");
Assert.IsNotNull(colorModelComboBox);
colorModelComboBox.Click();
var selectedItem = colorModelComboBox.Find<NavigationViewItem>("RGB");
selectedItem.Click();
Task.Delay(500).Wait();
var rgbHexEdit = this.Find<TextBox>("RGB hex");
Assert.IsNotNull(rgbHexEdit);
Task.Delay(500).Wait();
int retry = 5;
while (retry > 0)
{
Task.Delay(500).Wait();
rgbHexEdit.SetText(settings.BackgroundColor);
Task.Delay(500).Wait();
string rgbHex = rgbHexEdit.Text;
bool isValid = rgbHex.StartsWith('#') && rgbHex.Length == 7 && rgbHex.Substring(1) == settings.BackgroundColor;
Task.Delay(500).Wait();
if (isValid)
{
break;
}
retry--;
}
button.Click();
// Set the Spotlight color
var spotlightColor = foundCustom.Find<Group>("Spotlight color");
Assert.IsNotNull(spotlightColor);
var spotlightColorButton = spotlightColor.Find<Button>(By.XPath(".//Button"));
Assert.IsNotNull(spotlightColorButton);
spotlightColorButton.Click();
var spotlightColorPopupWindow = Session.Find<Window>("Popup");
Assert.IsNotNull(spotlightColorPopupWindow);
var spotlightColorModelComboBox = this.Find<ComboBox>("Color model");
Assert.IsNotNull(spotlightColorModelComboBox);
spotlightColorModelComboBox.Click();
var selectedItem2 = spotlightColorModelComboBox.Find<NavigationViewItem>("RGB");
Assert.IsNotNull(selectedItem2);
selectedItem2.Click();
Task.Delay(500).Wait();
var rgbHexEdit2 = this.Find<TextBox>("RGB hex");
Assert.IsNotNull(rgbHexEdit2);
Task.Delay(500).Wait();
retry = 5;
while (retry > 0)
{
Task.Delay(500).Wait();
rgbHexEdit2.SetText(settings.SpotlightColor);
Task.Delay(500).Wait();
string rgbHex = rgbHexEdit2.Text;
bool isValid = rgbHex.StartsWith('#') && rgbHex.Length == 7 && rgbHex.Substring(1) == settings.SpotlightColor;
Task.Delay(500).Wait();
if (isValid)
{
break;
}
retry--;
}
Task.Delay(500).Wait();
spotlightColorButton.Click(false, 500, 1500);
// Set the overlay opacity to overlayOpacity%
var overlayOpacitySlider = foundCustom.Find<Slider>("Overlay opacity (%)");
Assert.IsNotNull(overlayOpacitySlider);
Assert.IsNotNull(settings.OverlayOpacity);
int overlayOpacityValue = int.Parse(settings.OverlayOpacity, CultureInfo.InvariantCulture);
overlayOpacitySlider.QuickSetValue(overlayOpacityValue);
Assert.AreEqual(settings.OverlayOpacity, overlayOpacitySlider.Text);
Task.Delay(1000).Wait();
// Set the Fade Initial zoom to 0
var spotlightInitialZoomSlider = foundCustom.Find<Slider>("Spotlight initial zoom");
Assert.IsNotNull(spotlightInitialZoomSlider);
Task.Delay(1000).Wait();
spotlightInitialZoomSlider.QuickSetValue(int.Parse(settings.InitialZoom, CultureInfo.InvariantCulture));
Assert.AreEqual(settings.InitialZoom, spotlightInitialZoomSlider.Text);
Task.Delay(1000).Wait();
//// Change the edit value
var spotlightRadiusEdit = foundCustom.Find<TextBox>("Spotlight radius (px) Minimum5");
Assert.IsNotNull(spotlightRadiusEdit);
Task.Delay(1000).Wait();
spotlightRadiusEdit.SetText(settings.Radius);
Assert.AreEqual(settings.Radius, spotlightRadiusEdit.Text);
Task.Delay(1000).Wait();
// Set the duration to 0 ms
var spotlightAnimationDuration = foundCustom.Find<TextBox>("Animation duration (ms) Minimum0");
Assert.IsNotNull(spotlightAnimationDuration);
Task.Delay(1000).Wait();
spotlightAnimationDuration.SetText(settings.AnimationDuration);
Assert.AreEqual(settings.AnimationDuration, spotlightAnimationDuration.Text);
Task.Delay(1000).Wait();
// groupAppearanceBehavior.Click();
}
else
{
Assert.Fail("Appearance & behavior group not found.");
}
}
private bool CheckAnimationEnable(ref Custom? foundCustom)
{
Assert.IsNotNull(foundCustom, "Find My Mouse group not found.");
var foundElements = foundCustom.FindAll<TextBlock>("Animations are disabled in your system settings.");
// Assert.IsNull(animationDisabledWarning);
if (foundElements.Count != 0)
{
var openSettingsLink = foundCustom.Find<Element>("Open settings");
Assert.IsNotNull(openSettingsLink);
openSettingsLink.Click(false, 500, 3000);
string settingsWindow = "Settings";
this.Session.Attach(settingsWindow);
var animationEffects = this.Find<ToggleSwitch>("Animation effects");
Assert.IsNotNull(animationEffects);
animationEffects.Toggle(true);
Task.Delay(2000).Wait();
Session.SendKeys(Key.Alt, Key.F4);
this.Session.Attach(PowerToysModule.PowerToysSettings);
this.LaunchFromSetting(reload: true);
}
else
{
return false;
}
return true;
}
private void LaunchFromSetting(bool reload = false, bool launchAsAdmin = false)
{
// this.Session.Attach(PowerToysModule.PowerToysSettings);
this.Session.SetMainWindowSize(WindowSize.Large);
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities", 10000).Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").Click();
}
if (reload)
{
this.Find<NavigationViewItem>("Keyboard Manager").Click();
}
Task.Delay(1000).Wait();
this.Find<NavigationViewItem>("Mouse utilities").Click();
}
}
}

View File

@@ -0,0 +1,498 @@
// 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.Globalization;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Windows.Devices.Printers;
namespace MouseUtils.UITests
{
[TestClass]
public class MouseHighlighterTests : UITestBase
{
[TestMethod("MouseUtils.MouseHighlighter.EnableMouseHighlighter")]
[TestCategory("Mouse Utils #17")]
[TestCategory("Mouse Utils #18")]
[TestCategory("Mouse Utils #19")]
[TestCategory("Mouse Utils #20")]
[TestCategory("Mouse Utils #21")]
public void TestEnableMouseHighlighter()
{
LaunchFromSetting();
var foundCustom0 = this.Find<Custom>("Find My Mouse");
if (foundCustom0 != null)
{
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
}
else
{
Assert.Fail("Find My Mouse custom not found.");
}
var settings = new MouseHighlighterSettings();
settings.PrimaryButtonHighlightColor = "FFFF0000";
settings.SecondaryButtonHighlightColor = "FF00FF00";
settings.AlwaysHighlightColor = "004cFF71";
settings.Radius = "50";
settings.FadeDelay = "0";
settings.FadeDuration = "90";
var foundCustom = this.Find<Custom>("Mouse Highlighter");
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(false);
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1, xy.Item2 - 100);
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
// Change the shortcut key for MouseHighlighter
// [TestCase]Change activation shortcut and test it
var activationShortcutButton = foundCustom.Find<Button>("Activation shortcut");
Assert.IsNotNull(activationShortcutButton);
activationShortcutButton.Click();
Task.Delay(500).Wait();
var activationShortcutWindow = Session.Find<Window>("Activation shortcut");
Assert.IsNotNull(activationShortcutWindow);
// Invalid shortcut key
Session.SendKeySequence(Key.H);
// IOUtil.SimulateKeyPress(0x41);
var invalidShortcutText = activationShortcutWindow.Find<TextBlock>("Invalid shortcut");
Assert.IsNotNull(invalidShortcutText);
// IOUtil.SimulateShortcut(0x5B, 0x10, 0x45);
Session.SendKeys(Key.Win, Key.Shift, Key.H);
// Assert.IsNull(activationShortcutWindow.Find<TextBlock>("Invalid shortcut"));
var saveButton = activationShortcutWindow.Find<Button>("Save");
Assert.IsNotNull(saveButton);
saveButton.Click(false, 500, 1000);
SetMouseHighlighterAppearanceBehavior(ref foundCustom, ref settings);
var xy0 = Session.GetMousePosition();
Session.MoveMouseTo(xy0.Item1 - 100, xy0.Item2);
Session.PerformMouseAction(MouseActionType.LeftClick);
// Check the mouse highlighter is enabled
Session.SendKeys(Key.Win, Key.Shift, Key.H);
// IOUtil.SimulateShortcut(0x5B, 0x10, 0x45);
Task.Delay(1000).Wait();
// MouseSimulator.LeftClick();
// [Test Case] Press the activation shortcut and press left and right click somewhere, verifying the highlights are applied.
// [Test Case] Press the activation shortcut again and verify no highlights appear when the mouse buttons are clicked.
VerifyMouseHighlighterAppears(ref settings, "leftClick");
VerifyMouseHighlighterAppears(ref settings, "rightClick");
// Disable mouse highlighter
Session.SendKeys(Key.Win, Key.Shift, Key.H);
Task.Delay(1000).Wait();
VerifyMouseHighlighterNotAppears(ref settings, "leftClick");
VerifyMouseHighlighterNotAppears(ref settings, "rightClick");
// [Test Case] Disable Mouse Highlighter and verify that the module is not activated when you press the activation shortcut.
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(false);
xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1 - 100, xy.Item2);
Session.SendKeys(Key.Win, Key.Shift, Key.H);
Task.Delay(1000).Wait();
VerifyMouseHighlighterNotAppears(ref settings, "leftClick");
VerifyMouseHighlighterNotAppears(ref settings, "rightClick");
// [Test Case] With left mouse button pressed, drag the mouse and verify the hightlight is dragged with the pointer.
// [Test Case] With right mouse button pressed, drag the mouse and verify the hightlight is dragged with the pointer.
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1 - 100, xy.Item2);
Session.SendKeys(Key.Win, Key.Shift, Key.H);
Task.Delay(1000).Wait();
VerifyMouseHighlighterDrag(ref settings, "leftClick");
VerifyMouseHighlighterDrag(ref settings, "rightClick");
}
else
{
Assert.Fail("Mouse Highlighter Custom not found.");
}
Task.Delay(500).Wait();
}
[TestMethod("MouseUtils.MouseHighlighter.MouseHighlighterDifferentSettings")]
[TestCategory("Mouse Utils #22")]
[TestCategory("Mouse Utils #23")]
[TestCategory("Mouse Utils #24")]
public void TestMouseHighlighterDifferentSettings()
{
LaunchFromSetting();
var foundCustom0 = this.Find<Custom>("Find My Mouse");
if (foundCustom0 != null)
{
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
}
else
{
Assert.Fail("Find My Mouse custom not found.");
}
var settings = new MouseHighlighterSettings();
settings.PrimaryButtonHighlightColor = "FF000000";
settings.SecondaryButtonHighlightColor = "FFFFFFFF";
settings.AlwaysHighlightColor = "004cFF71";
settings.Radius = "70";
settings.FadeDelay = "0";
settings.FadeDuration = "90";
var foundCustom = this.Find<Custom>("Mouse Highlighter");
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(false);
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1, xy.Item2 - 100);
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
// Change the shortcut key for MouseHighlighter
// [TestCase] Test the different settings and verify they apply - Change activation shortcut and test it
// [Test Case] Test the different settings and verify they apply - Left button highlight color
// [Test Case] Test the different settings and verify they apply - Right button highlight color
// [Test Case] Test the different settings and verify they apply - Radius
var activationShortcutButton = foundCustom.Find<Button>("Activation shortcut");
Assert.IsNotNull(activationShortcutButton);
activationShortcutButton.Click();
Task.Delay(500).Wait();
var activationShortcutWindow = Session.Find<Window>("Activation shortcut");
Assert.IsNotNull(activationShortcutWindow);
// Invalid shortcut key
Session.SendKeySequence(Key.H);
// IOUtil.SimulateKeyPress(0x41);
var invalidShortcutText = activationShortcutWindow.Find<TextBlock>("Invalid shortcut");
Assert.IsNotNull(invalidShortcutText);
// IOUtil.SimulateShortcut(0x5B, 0x10, 0x45);
Session.SendKeys(Key.Win, Key.Shift, Key.O);
// Assert.IsNull(activationShortcutWindow.Find<TextBlock>("Invalid shortcut"));
var saveButton = activationShortcutWindow.Find<Button>("Save");
Assert.IsNotNull(saveButton);
saveButton.Click(false, 500, 1000);
SetMouseHighlighterAppearanceBehavior(ref foundCustom, ref settings);
var xy0 = Session.GetMousePosition();
Session.MoveMouseTo(xy0.Item1 - 100, xy0.Item2);
Session.PerformMouseAction(MouseActionType.LeftClick);
// Check the mouse highlighter is enabled
Session.SendKeys(Key.Win, Key.Shift, Key.O);
Task.Delay(1000).Wait();
VerifyMouseHighlighterAppears(ref settings, "leftClick");
VerifyMouseHighlighterAppears(ref settings, "rightClick");
}
else
{
Assert.Fail("Mouse Highlighter Custom not found.");
}
Task.Delay(500).Wait();
}
private void VerifyMouseHighlighterDrag(ref MouseHighlighterSettings settings, string action = "leftClick")
{
Task.Delay(500).Wait();
string expectedColor = string.Empty;
if (action == "leftClick")
{
IOUtil.SimulateMouseDown(true);
expectedColor = settings.PrimaryButtonHighlightColor.Substring(2);
}
else if (action == "rightClick")
{
IOUtil.SimulateMouseDown(false);
expectedColor = settings.SecondaryButtonHighlightColor.Substring(2);
}
else
{
Assert.Fail("Invalid action specified.");
}
expectedColor = "#" + expectedColor;
Task.Delay(100).Wait();
var location = Session.GetMousePosition();
int radius = int.Parse(settings.Radius, CultureInfo.InvariantCulture);
var colorLeftClick = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreEqual(expectedColor, colorLeftClick);
var colorLeftClick2 = this.GetPixelColorString(location.Item1 + radius - 1, location.Item2);
Assert.AreEqual(expectedColor, colorLeftClick2);
var colorBackground = this.GetPixelColorString(location.Item1 + radius + 50, location.Item2 + radius + 50);
Assert.AreNotEqual(expectedColor, colorBackground);
// Drag the mouse
// Session.MoveMouseTo(location.Item1 - 400, location.Item2);
for (int i = 0; i < 500; i++)
{
IOUtil.MoveMouseBy(-1, 0);
Task.Delay(10).Wait();
}
Task.Delay(2000).Wait();
location = Session.GetMousePosition();
colorLeftClick = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreEqual(expectedColor, colorLeftClick);
colorLeftClick2 = this.GetPixelColorString(location.Item1 + radius - 1, location.Item2);
Assert.AreEqual(expectedColor, colorLeftClick2);
colorBackground = this.GetPixelColorString(location.Item1 + radius + 50, location.Item2 + radius + 50);
Assert.AreNotEqual(expectedColor, colorBackground);
if (action == "leftClick")
{
IOUtil.SimulateMouseUp(true);
}
else if (action == "rightClick")
{
IOUtil.SimulateMouseUp(false);
}
int duration = int.Parse(settings.FadeDuration, CultureInfo.InvariantCulture);
Task.Delay(duration + 100).Wait();
colorLeftClick = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreNotEqual("#" + settings.PrimaryButtonHighlightColor, colorLeftClick);
}
private void VerifyMouseHighlighterNotAppears(ref MouseHighlighterSettings settings, string action = "leftClick")
{
Task.Delay(500).Wait();
string expectedColor = string.Empty;
if (action == "leftClick")
{
// MouseSimulator.LeftDown();
Session.PerformMouseAction(MouseActionType.LeftDown);
expectedColor = settings.PrimaryButtonHighlightColor.Substring(2);
}
else if (action == "rightClick")
{
// MouseSimulator.RightDown();
Session.PerformMouseAction(MouseActionType.RightDown);
expectedColor = settings.SecondaryButtonHighlightColor.Substring(2);
}
else
{
Assert.Fail("Invalid action specified.");
}
expectedColor = "#" + expectedColor;
var location = Session.GetMousePosition();
int radius = int.Parse(settings.Radius, CultureInfo.InvariantCulture);
var colorLeftClick = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreNotEqual(expectedColor, colorLeftClick);
var colorLeftClick2 = this.GetPixelColorString(location.Item1 + radius - 1, location.Item2);
Assert.AreNotEqual(expectedColor, colorLeftClick2);
if (action == "leftClick")
{
Session.PerformMouseAction(MouseActionType.LeftUp);
}
else if (action == "rightClick")
{
Session.PerformMouseAction(MouseActionType.RightUp);
}
}
private void VerifyMouseHighlighterAppears(ref MouseHighlighterSettings settings, string action = "leftClick")
{
Task.Delay(500).Wait();
string expectedColor = string.Empty;
if (action == "leftClick")
{
// MouseSimulator.LeftDown();
Session.PerformMouseAction(MouseActionType.LeftDown);
expectedColor = settings.PrimaryButtonHighlightColor.Substring(2);
}
else if (action == "rightClick")
{
// MouseSimulator.RightDown();
Session.PerformMouseAction(MouseActionType.RightDown);
expectedColor = settings.SecondaryButtonHighlightColor.Substring(2);
}
else
{
Assert.Fail("Invalid action specified.");
}
expectedColor = "#" + expectedColor;
var location = Session.GetMousePosition();
int radius = int.Parse(settings.Radius, CultureInfo.InvariantCulture);
var colorLeftClick = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreEqual(expectedColor, colorLeftClick);
var colorLeftClick2 = this.GetPixelColorString(location.Item1 + radius - 1, location.Item2);
Assert.AreEqual(expectedColor, colorLeftClick2);
Task.Delay(500).Wait();
var colorBackground = this.GetPixelColorString(location.Item1 + radius + 50, location.Item2 + radius + 50);
Assert.AreNotEqual(expectedColor, colorBackground);
if (action == "leftClick")
{
// MouseSimulator.LeftUp();
Session.PerformMouseAction(MouseActionType.LeftUp);
}
else if (action == "rightClick")
{
// MouseSimulator.RightUp();
Session.PerformMouseAction(MouseActionType.RightUp);
}
int duration = int.Parse(settings.FadeDuration, CultureInfo.InvariantCulture);
Task.Delay(duration + 100).Wait();
colorLeftClick = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreNotEqual("#" + settings.PrimaryButtonHighlightColor, colorLeftClick);
}
private void SetColor(ref Custom foundCustom, string colorName = "Primary button highlight color", string colorValue = "000000", string opacity = "0")
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
if (groupAppearanceBehavior != null)
{
if (foundCustom.FindAll<TextBox>("Fade duration (ms) Minimum0").Count == 0)
{
groupAppearanceBehavior.Click();
}
// Set primary button highlight color
var primaryButtonHighlightColor = foundCustom.Find<Group>(colorName);
Assert.IsNotNull(primaryButtonHighlightColor);
var button = primaryButtonHighlightColor.Find<Button>(By.XPath(".//Button"));
Assert.IsNotNull(button);
button.Click(false, 500, 700);
var popupWindow = Session.Find<Window>("Popup");
Assert.IsNotNull(popupWindow);
var colorModelComboBox = this.Find<ComboBox>("Color model");
Assert.IsNotNull(colorModelComboBox);
colorModelComboBox.Click(false, 500, 700);
var selectedItem = colorModelComboBox.Find<NavigationViewItem>("RGB");
selectedItem.Click();
var rgbHexEdit = this.Find<TextBox>("RGB hex");
Assert.IsNotNull(rgbHexEdit);
Task.Delay(500).Wait();
rgbHexEdit.SetText(colorValue);
int retry = 5;
while (retry > 0)
{
Task.Delay(500).Wait();
rgbHexEdit.SetText(colorValue);
Task.Delay(500).Wait();
string rgbHex = rgbHexEdit.Text;
bool isValid = rgbHex.StartsWith('#') && rgbHex.Length == 9 && rgbHex.Substring(1) == colorValue;
Task.Delay(500).Wait();
if (isValid)
{
break;
}
retry--;
}
Task.Delay(500).Wait();
button.Click();
}
}
private void SetMouseHighlighterAppearanceBehavior(ref Custom foundCustom, ref MouseHighlighterSettings settings)
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
if (groupAppearanceBehavior != null)
{
// groupAppearanceBehavior.Click();
if (foundCustom.FindAll<TextBox>(settings.GetElementName(MouseHighlighterSettings.SettingsUIElements.FadeDurationEdit)).Count == 0)
{
groupAppearanceBehavior.Click();
}
// Set primary button highlight color
SetColor(ref foundCustom, settings.GetElementName(MouseHighlighterSettings.SettingsUIElements.PrimaryButtonHighlightColorGroup), settings.PrimaryButtonHighlightColor);
// Set secondary button highlight color
SetColor(ref foundCustom, settings.GetElementName(MouseHighlighterSettings.SettingsUIElements.SecondaryButtonHighlightColorGroup), settings.SecondaryButtonHighlightColor);
// Set the duration to duration ms
var fadeDurationEdit = foundCustom.Find<TextBox>(settings.GetElementName(MouseHighlighterSettings.SettingsUIElements.FadeDurationEdit));
Assert.IsNotNull(fadeDurationEdit);
fadeDurationEdit.SetText(settings.FadeDuration);
Assert.AreEqual(settings.FadeDuration, fadeDurationEdit.Text);
// Set Fade delay(ms)
var fadeDelayEdit = foundCustom.Find<TextBox>(settings.GetElementName(MouseHighlighterSettings.SettingsUIElements.FadeDelayEdit));
Assert.IsNotNull(fadeDelayEdit);
fadeDelayEdit.SetText(settings.FadeDelay);
Assert.AreEqual(settings.FadeDelay, fadeDelayEdit.Text);
// Set the fade radius (px)
var fadeRadiusEdit = foundCustom.Find<TextBox>(settings.GetElementName(MouseHighlighterSettings.SettingsUIElements.RadiusEdit));
Assert.IsNotNull(fadeRadiusEdit);
fadeRadiusEdit.SetText(settings.Radius);
Assert.AreEqual(settings.Radius, fadeRadiusEdit.Text);
// Set always highlight color
SetColor(ref foundCustom, settings.GetElementName(MouseHighlighterSettings.SettingsUIElements.AlwaysHighlightColorGroup), settings.AlwaysHighlightColor);
}
else
{
Assert.Fail("Appearance & behavior group not found.");
}
}
private void LaunchFromSetting(bool showWarning = false, bool launchAsAdmin = false)
{
this.Session.SetMainWindowSize(WindowSize.Large);
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities").Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").Click();
}
this.Find<NavigationViewItem>("Mouse utilities").Click();
}
}
}

View File

@@ -0,0 +1,250 @@
// 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.Threading.Tasks;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MouseUtils.UITests
{
[TestClass]
public class MouseJumpTests : UITestBase
{
[TestMethod("MouseUtils.MouseJump.EnableMouseJump")]
[TestCategory("Mouse Utils #39")]
[TestCategory("Mouse Utils #40")]
[TestCategory("Mouse Utils #41")]
[TestCategory("Mouse Utils #45")]
public void TestEnableMouseJump()
{
LaunchFromSetting(true);
}
[TestMethod("MouseUtils.MouseJump.EnableMouseJump2")]
[TestCategory("Mouse Utils #39")]
[TestCategory("Mouse Utils #41")]
[TestCategory("Mouse Utils #45")]
public void TestEnableMouseJump2()
{
LaunchFromSetting();
var foundCustom0 = this.Find<Custom>("Find My Mouse");
if (foundCustom0 != null)
{
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
}
else
{
Assert.Fail("Find My Mouse custom not found.");
}
for (int i = 0; i < 10; i++)
{
Session.PerformMouseAction(MouseActionType.ScrollDown);
}
var foundCustom = this.Find<Custom>("Mouse Jump");
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Mouse Jump").Toggle(true);
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1, xy.Item2 - 100);
// Change the shortcut key for MouseHighlighter
// [TestCase]Change activation shortcut and test it
var activationShortcutButton = foundCustom.Find<Button>("Activation shortcut");
Assert.IsNotNull(activationShortcutButton);
activationShortcutButton.Click(false, 500, 1000);
var activationShortcutWindow = Session.Find<Window>("Activation shortcut");
Assert.IsNotNull(activationShortcutWindow);
// Invalid shortcut key
Session.SendKeySequence(Key.H);
// IOUtil.SimulateKeyPress(0x41);
var invalidShortcutText = activationShortcutWindow.Find<TextBlock>("Invalid shortcut");
Assert.IsNotNull(invalidShortcutText);
// IOUtil.SimulateShortcut(0x5B, 0x10, 0x45);
Session.SendKeys(Key.Win, Key.Shift, Key.Z);
// Assert.IsNull(activationShortcutWindow.Find<TextBlock>("Invalid shortcut"));
var saveButton = activationShortcutWindow.Find<Button>("Save");
Assert.IsNotNull(saveButton);
saveButton.Click(false, 500, 1500);
var screenCenter = this.GetScreenCenter();
Session.MoveMouseTo(screenCenter.CenterX, screenCenter.CenterY, 500, 1000);
Session.MoveMouseTo(screenCenter.CenterX, screenCenter.CenterY - 300, 500, 1000);
// [TestCase] Enable Mouse Jump. Then - Press the activation shortcut and verify the screens preview appears.
// [TestCase] Enable Mouse Jump. Then - Click around the screen preview and ensure that mouse cursor jumped to clicked location.
Session.SendKeys(Key.Win, Key.Shift, Key.Z);
VerifyWindowAppears();
Task.Delay(1000).Wait();
// [TestCase] Enable Mouse Jump. Then - Disable Mouse Jump and verify that the module is not activated when you press the activation shortcut.
foundCustom.Find<ToggleSwitch>("Enable Mouse Jump").Toggle(false);
Session.MoveMouseTo(screenCenter.CenterX, screenCenter.CenterY - 300, 500, 1000);
Session.SendKeys(Key.Win, Key.Shift, Key.Z);
Task.Delay(500).Wait();
VerifyWindowNotAppears();
}
else
{
Assert.Fail("Mouse Highlighter Custom not found.");
}
Task.Delay(500).Wait();
}
[TestMethod("MouseUtils.MouseJump.EnableMouseJump3")]
[TestCategory("Mouse Utils #40")]
public void TestEnableMouseJump3()
{
LaunchFromSetting();
var foundCustom0 = this.Find<Custom>("Find My Mouse");
if (foundCustom0 != null)
{
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
}
else
{
Assert.Fail("Find My Mouse custom not found.");
}
for (int i = 0; i < 10; i++)
{
Session.PerformMouseAction(MouseActionType.ScrollDown);
}
var foundCustom = this.Find<Custom>("Mouse Jump");
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Mouse Jump").Toggle(true);
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1, xy.Item2 - 100);
// Change the shortcut key for MouseHighlighter
// [TestCase]Change activation shortcut and test it
var activationShortcutButton = foundCustom.Find<Button>("Activation shortcut");
Assert.IsNotNull(activationShortcutButton);
activationShortcutButton.Click(false, 500, 1000);
var activationShortcutWindow = Session.Find<Window>("Activation shortcut");
Assert.IsNotNull(activationShortcutWindow);
// Invalid shortcut key
Session.SendKeySequence(Key.H);
// IOUtil.SimulateKeyPress(0x41);
var invalidShortcutText = activationShortcutWindow.Find<TextBlock>("Invalid shortcut");
Assert.IsNotNull(invalidShortcutText);
// IOUtil.SimulateShortcut(0x5B, 0x10, 0x45);
Session.SendKeys(Key.Win, Key.Shift, Key.J);
// Assert.IsNull(activationShortcutWindow.Find<TextBlock>("Invalid shortcut"));
var saveButton = activationShortcutWindow.Find<Button>("Save");
Assert.IsNotNull(saveButton);
saveButton.Click(false, 500, 1500);
var screenCenter = this.GetScreenCenter();
Session.MoveMouseTo(screenCenter.CenterX, screenCenter.CenterY, 500, 1000);
Session.MoveMouseTo(screenCenter.CenterX, screenCenter.CenterY - 300, 500, 1000);
// [TestCase] Enable Mouse Jump. Then - Change activation shortcut and verify that new shortcut triggers Mouse Jump.
Session.SendKeys(Key.Win, Key.Shift, Key.J);
VerifyWindowAppears();
}
else
{
Assert.Fail("Mouse Highlighter Custom not found.");
}
Task.Delay(500).Wait();
}
private void VerifyWindowAppears()
{
string windowName = "MouseJump";
Session.Attach(windowName);
var center = this.Session.GetMainWindowCenter();
Session.MoveMouseTo(center.CenterX, center.CenterY);
Session.PerformMouseAction(MouseActionType.LeftClick, 1000, 1000);
var screenCenter = this.GetScreenCenter();
// Get Mouse position
var xy = Session.GetMousePosition();
double distance = CalculateDistance(xy.Item1, xy.Item2, screenCenter.CenterX, screenCenter.CenterY);
Assert.IsTrue(distance <= 10, "Mouse Jump window should be opened and mouse should be moved to the center of the screen.");
}
private void VerifyWindowNotAppears()
{
string windowName = "MouseJump";
bool open = this.IsWindowOpen(windowName);
Assert.IsFalse(open, "Mouse Jump window should not be opened.");
}
/// <summary>
/// Calculate the Euclidean distance between two 2D points
/// </summary>
/// <param name="x1">X coordinate of first point</param>
/// <param name="y1">Y coordinate of first point</param>
/// <param name="x2">X coordinate of second point</param>
/// <param name="y2">Y coordinate of second point</param>
/// <returns>Distance (double)</returns>
public double CalculateDistance(int x1, int y1, int x2, int y2)
{
int dx = x2 - x1;
int dy = y2 - y1;
return Math.Sqrt((dx * dx) + (dy * dy));
}
private void LaunchFromSetting(bool firstTime = false, bool launchAsAdmin = false)
{
Session.SetMainWindowSize(WindowSize.Large);
Task.Delay(1000).Wait();
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities").Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").ClickCenter();
Task.Delay(2000).Wait();
}
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities").Count == 0)
{
RestartScopeExe();
Session.SetMainWindowSize(WindowSize.Large);
Task.Delay(1000).Wait();
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").ClickCenter();
Task.Delay(2000).Wait();
}
// Click on the Mouse utilities
// Task.Delay(2000).Wait();
if (firstTime)
{
return;
}
else
{
this.Find<NavigationViewItem>("Mouse utilities").Click();
}
}
}
}

View File

@@ -0,0 +1,404 @@
// 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.Globalization;
using System.Reflection;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Windows.Devices.Printers;
namespace MouseUtils.UITests
{
[TestClass]
public class MousePointerCrosshairsTests : UITestBase
{
[TestMethod("MouseUtils.MousePointerCrosshairs.EnableMousePointerCrosshairs")]
[TestCategory("Mouse Utils #29")]
[TestCategory("Mouse Utils #30")]
[TestCategory("Mouse Utils #31")]
public void TestEnableMousePointerCrosshairs()
{
LaunchFromSetting();
var settings = new MousePointerCrosshairsSettings();
settings.CrosshairsColor = "FF0000";
settings.CrosshairsBorderColor = "FF0000";
settings.Opacity = "100";
settings.CenterRadius = "0";
settings.Thickness = "20";
settings.BorderSize = "0";
settings.IsFixLength = false;
settings.FixedLength = "1";
var foundCustom = FindMouseUtilElement(MouseUtilsSettings.MouseUtils.FindMyMouse);
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.FindMyMouse, false);
foundCustom = FindMouseUtilElement(MouseUtilsSettings.MouseUtils.MouseHighlighter);
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MouseHighlighter, true);
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MouseHighlighter, false);
for (int i = 0; i < 10; i++)
{
Session.PerformMouseAction(MouseActionType.ScrollDown);
}
foundCustom = FindMouseUtilElement(MouseUtilsSettings.MouseUtils.MousePointerCrosshairs);
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MousePointerCrosshairs, false);
Task.Delay(500).Wait();
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MousePointerCrosshairs, true);
Assert.IsNotNull(foundCustom);
// [Test Case] Change activation shortcut and test it.
var activationShortcutButton = foundCustom.Find<Button>("Activation shortcut");
Assert.IsNotNull(activationShortcutButton);
activationShortcutButton.Click(false, 500, 1000);
var activationShortcutWindow = Session.Find<Window>("Activation shortcut");
Assert.IsNotNull(activationShortcutWindow);
// Invalid shortcut key
Session.SendKeySequence(Key.H);
var invalidShortcutText = activationShortcutWindow.Find<TextBlock>("Invalid shortcut");
Assert.IsNotNull(invalidShortcutText);
Session.SendKeys(Key.Win, Key.Alt, Key.A);
var saveButton = activationShortcutWindow.Find<Button>("Save");
Assert.IsNotNull(saveButton);
saveButton.Click(false, 500, 1000);
SetMousePointerCrosshairsAppearanceBehavior(ref foundCustom, ref settings);
Task.Delay(500).Wait();
// [Test Case] Press the activation shortcut and verify the crosshairs appear, and that they follow the mouse around.
var xy0 = Session.GetMousePosition();
Session.MoveMouseTo(xy0.Item1 - 100, xy0.Item2);
IOUtil.MouseClick();
Task.Delay(500).Wait();
Session.SendKeys(Key.Win, Key.Alt, Key.A);
Task.Delay(1000).Wait();
xy0 = Session.GetMousePosition();
VerifyMousePointerCrosshairsAppears(ref settings);
Task.Delay(500).Wait();
for (int i = 0; i < 100; i++)
{
IOUtil.MoveMouseBy(-1, 0);
Task.Delay(10).Wait();
}
VerifyMousePointerCrosshairsAppears(ref settings);
// [Test Case] Press the activation shortcut again and verify the crosshairs disappear.
Session.SendKeys(Key.Win, Key.Alt, Key.A);
Task.Delay(1000).Wait();
VerifyMousePointerCrosshairsNotAppears(ref settings);
Task.Delay(500).Wait();
// [Test Case] Disable Mouse Pointer Crosshairs and verify that the module is not activated when you press the activation shortcut.
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MousePointerCrosshairs, false);
xy0 = Session.GetMousePosition();
Session.MoveMouseTo(xy0.Item1 - 100, xy0.Item2);
Session.PerformMouseAction(MouseActionType.LeftClick);
Session.SendKeys(Key.Win, Key.Alt, Key.A);
Task.Delay(1000).Wait();
VerifyMousePointerCrosshairsNotAppears(ref settings);
}
[TestMethod("MouseUtils.MousePointerCrosshairs.MousePointerCrosshairsDifferentSettings")]
[TestCategory("Mouse Utils #32")]
[TestCategory("Mouse Utils #33")]
public void TestMousePointerCrosshairsDifferentSettings()
{
LaunchFromSetting();
var settings = new MousePointerCrosshairsSettings();
settings.CrosshairsColor = "00FF00";
settings.CrosshairsBorderColor = "00FF00";
settings.Opacity = "100";
settings.CenterRadius = "0";
settings.Thickness = "20";
settings.BorderSize = "0";
settings.IsFixLength = false;
settings.FixedLength = "1";
var foundCustom = FindMouseUtilElement(MouseUtilsSettings.MouseUtils.FindMyMouse);
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.FindMyMouse, false);
foundCustom = FindMouseUtilElement(MouseUtilsSettings.MouseUtils.MouseHighlighter);
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MouseHighlighter, true);
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MouseHighlighter, false);
for (int i = 0; i < 10; i++)
{
Session.PerformMouseAction(MouseActionType.ScrollDown);
}
foundCustom = FindMouseUtilElement(MouseUtilsSettings.MouseUtils.MousePointerCrosshairs);
// this.FindGroup("Enable Mouse Pointer Crosshairs");
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MousePointerCrosshairs, false);
Task.Delay(500).Wait();
MouseUtilsSettings.SetMouseUtilEnabled(foundCustom, MouseUtilsSettings.MouseUtils.MousePointerCrosshairs, true);
Assert.IsNotNull(foundCustom);
// [Test Case] Change activation shortcut and test it.
var activationShortcutButton = foundCustom.Find<Button>("Activation shortcut");
Assert.IsNotNull(activationShortcutButton);
activationShortcutButton.Click(false, 500, 1000);
var activationShortcutWindow = Session.Find<Window>("Activation shortcut");
Assert.IsNotNull(activationShortcutWindow);
// Invalid shortcut key
Session.SendKeySequence(Key.H);
var invalidShortcutText = activationShortcutWindow.Find<TextBlock>("Invalid shortcut");
Assert.IsNotNull(invalidShortcutText);
Session.SendKeys(Key.Win, Key.Alt, Key.P);
var saveButton = activationShortcutWindow.Find<Button>("Save");
Assert.IsNotNull(saveButton);
saveButton.Click(false, 500, 1000);
SetMousePointerCrosshairsAppearanceBehavior(ref foundCustom, ref settings);
Task.Delay(500).Wait();
// [Test Case] Test the different settings and verify they apply - Change activation shortcut and test it.
// [Test Case] Test the different settings and verify they apply - Crosshairs color.
var xy0 = Session.GetMousePosition();
Session.MoveMouseTo(xy0.Item1 - 100, xy0.Item2);
IOUtil.MouseClick();
Task.Delay(500).Wait();
Session.SendKeys(Key.Win, Key.Alt, Key.P);
Task.Delay(1000).Wait();
xy0 = Session.GetMousePosition();
VerifyMousePointerCrosshairsAppears(ref settings);
Task.Delay(500).Wait();
for (int i = 0; i < 100; i++)
{
IOUtil.MoveMouseBy(-1, 0);
Task.Delay(10).Wait();
}
VerifyMousePointerCrosshairsAppears(ref settings);
// Press the activation shortcut again and verify the crosshairs disappear.
Session.SendKeys(Key.Win, Key.Alt, Key.P);
Task.Delay(1000).Wait();
VerifyMousePointerCrosshairsNotAppears(ref settings);
}
private void VerifyMousePointerCrosshairsNotAppears(ref MousePointerCrosshairsSettings settings)
{
Task.Delay(500).Wait();
string expectedColor = string.Empty;
expectedColor = "#" + settings.CrosshairsColor;
var location = Session.GetMousePosition();
int radius = int.Parse(settings.CenterRadius, CultureInfo.InvariantCulture);
var color = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreNotEqual(expectedColor, color);
}
private void VerifyMousePointerCrosshairsAppears(ref MousePointerCrosshairsSettings settings)
{
Task.Delay(1000).Wait();
string expectedColor = string.Empty;
expectedColor = "#" + settings.CrosshairsColor;
var location = Session.GetMousePosition();
int radius = int.Parse(settings.CenterRadius, CultureInfo.InvariantCulture);
var color = this.GetPixelColorString(location.Item1, location.Item2);
Assert.AreEqual(expectedColor, color, "Center color check failed");
var colorX = this.GetPixelColorString(location.Item1 + 50, location.Item2);
Assert.AreEqual(expectedColor, colorX, "Center x + 50 color check failed");
colorX = this.GetPixelColorString(location.Item1 - 50, location.Item2);
Assert.AreEqual(expectedColor, colorX, "Center x - 50 color check failed");
var colorY = this.GetPixelColorString(location.Item1, location.Item2 + 50);
Assert.AreEqual(expectedColor, colorY, "Center y + 50 color check failed");
colorY = this.GetPixelColorString(location.Item1, location.Item2 - 50);
Assert.AreEqual(expectedColor, colorY, "Center y + 50 color check failed");
}
private void SetColor(ref Custom foundCustom, string colorName, string colorValue = "000000")
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
if (groupAppearanceBehavior != null)
{
// Set primary button highlight color
var primaryButtonHighlightColor = foundCustom.Find<Group>(colorName);
Assert.IsNotNull(primaryButtonHighlightColor);
var button = primaryButtonHighlightColor.Find<Button>(By.XPath(".//Button"));
Assert.IsNotNull(button);
button.Click(false);
var popupWindow = Session.Find<Window>("Popup");
Assert.IsNotNull(popupWindow);
var colorModelComboBox = this.Find<ComboBox>("Color model");
Assert.IsNotNull(colorModelComboBox);
colorModelComboBox.Click();
var selectedItem = colorModelComboBox.Find<NavigationViewItem>("RGB");
selectedItem.Click();
var rgbHexEdit = this.Find<TextBox>("RGB hex");
Assert.IsNotNull(rgbHexEdit);
rgbHexEdit.SetText(colorValue);
button.Click();
}
}
private void SetMousePointerCrosshairsAppearanceBehavior(ref Custom foundCustom, ref MousePointerCrosshairsSettings settings)
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
if (groupAppearanceBehavior != null)
{
// groupAppearanceBehavior.Click();
if (foundCustom.FindAll<TextBox>(settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.ThicknessEdit)).Count == 0)
{
groupAppearanceBehavior.Click();
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
}
// Set the crosshairs color
SetColor(ref foundCustom, settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.CrosshairsColorGroup), settings.CrosshairsColor);
// Set the crosshairs border color
SetColor(ref foundCustom, settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.CrosshairsBorderColorGroup), settings.CrosshairsBorderColor);
// Set the duration to duration ms
var opacitySlider = foundCustom.Find<Slider>(settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.OpacitySlider));
Assert.IsNotNull(opacitySlider);
Assert.IsNotNull(settings.Opacity);
int opacityValue = int.Parse(settings.Opacity, CultureInfo.InvariantCulture);
opacitySlider.QuickSetValue(opacityValue);
Assert.AreEqual(settings.Opacity, opacitySlider.Text);
Task.Delay(500).Wait();
// Set the center radius (px)
var centerRadiusEdit = foundCustom.Find<TextBox>(settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.CenterRadiusEdit));
Assert.IsNotNull(centerRadiusEdit);
centerRadiusEdit.SetText(settings.CenterRadius);
Assert.AreEqual(settings.CenterRadius, centerRadiusEdit.Text);
// Set the thickness (px)
var thicknessEdit = foundCustom.Find<TextBox>(settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.ThicknessEdit));
Assert.IsNotNull(thicknessEdit);
thicknessEdit.SetText(settings.Thickness);
Assert.AreEqual(settings.Thickness, thicknessEdit.Text);
// Set the border size (px)
var borderSizeEdit = foundCustom.Find<TextBox>(settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.BorderSizeEdit));
Assert.IsNotNull(borderSizeEdit);
borderSizeEdit.SetText(settings.BorderSize);
Assert.AreEqual(settings.BorderSize, borderSizeEdit.Text);
// Set the fixed length (px)
var isFixedLength = foundCustom.Find<ToggleSwitch>(settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.IsFixLengthToggle));
Assert.IsNotNull(isFixedLength);
isFixedLength.Toggle(settings.IsFixLength);
Assert.AreEqual(settings.IsFixLength, isFixedLength.IsOn);
if (settings.IsFixLength)
{
var fixedLengthEdit = foundCustom.Find<TextBox>(settings.GetElementName(MousePointerCrosshairsSettings.SettingsUIElements.FixedLengthEdit));
Assert.IsNotNull(fixedLengthEdit);
fixedLengthEdit.SetText(settings.FixedLength);
Assert.AreEqual(settings.FixedLength, fixedLengthEdit.Text);
}
}
else
{
Assert.Fail("Appearance & behavior group not found.");
}
}
private bool FindGroup(string groupName)
{
try
{
var foundElements = this.FindAll<Element>(groupName);
foreach (var element in foundElements)
{
string className = element.ClassName;
string name = element.Name;
string text = element.Text;
string helptext = element.HelpText;
string controlType = element.ControlType;
}
if (foundElements.Count == 0)
{
return false;
}
}
catch (Exception ex)
{
// Validate if group is not found by checking exception.Message
return ex.Message.Contains("No element found");
}
return true;
}
public Custom? FindMouseUtilElement(MouseUtilsSettings.MouseUtils element)
{
var elementName = MouseUtilsSettings.GetMouseUtilUIName(element);
var foundCustom = this.Find<Custom>(elementName);
for (int i = 0; i < 20; i++)
{
if (foundCustom != null)
{
break;
}
Session.PerformMouseAction(MouseActionType.ScrollDown);
foundCustom = this.Find<Custom>(elementName);
}
return foundCustom;
}
private void LaunchFromSetting(bool showWarning = false, bool launchAsAdmin = false)
{
Session.SetMainWindowSize(WindowSize.Large);
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities").Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").Click();
}
this.Find<NavigationViewItem>("Mouse utilities").Click();
}
}
}

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Look at Directory.Build.props in root for common stuff as well -->
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<ProjectGuid>{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}</ProjectGuid>
<RootNamespace>PowerToys.MouseUtils.UITests</RootNamespace>
<AssemblyName>PowerToys.MouseUtils.UITests</AssemblyName>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<!-- This is a UI test, so don't run as part of MSBuild -->
<RunVSTest>false</RunVSTest>
</PropertyGroup>
<PropertyGroup>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\tests\MouseUtils.UITests\</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MSTest" />
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,64 @@
## [Mouse Utils](tests-checklist-template-mouse-utils-section.md)
Find My Mouse:
* Enable FindMyMouse. Then, without moving your mouse:
- [x] Press Left Ctrl twice and verify the overlay appears.
- [x] Press any other key and verify the overlay disappears.
- [x] Press Left Ctrl twice and verify the overlay appears.
- [x] Press a mouse button and verify the overlay disappears.
* Disable FindMyMouse. Verify the overlay no longer appears when you press Left Ctrl twice.
* Enable FindMyMouse. Then, without moving your mouse:
- [x] Press Left Ctrl twice and verify the overlay appears.
* Enable the "Do not activate on game mode" option. Start playing a game that uses CG native full screen.
- [ ] Verify the overlay no longer appears when you press Left Ctrl twice.
* Disable the "Do not activate on game mode" option. Start playing the same game.
- [ ] Verify the overlay appears when you press Left Ctrl twice. (though it'll likely minimize the game)
* Test the different settings and verify they apply:
- [ ] Overlay opacity
- [x] Background color
- [x] Spotlight color
- [x] Spotlight radius
- [ ] Spotlight initial zoom (1x vs 9x will show the difference)
- [ ] Animation duration
- [ ] Change activation method to shake and activate by shaking your mouse pointer
- [ ] Excluded apps
Mouse Highlighter:
* Enable Mouse Highlighter. Then:
- [x] Press the activation shortcut and press left and right click somewhere, verifying the hightlights are applied.
- [x] With left mouse button pressed, drag the mouse and verify the hightlight is dragged with the pointer.
- [x] With right mouse button pressed, drag the mouse and verify the hightlight is dragged with the pointer.
- [x] Press the activation shortcut again and verify no highlights appear when the mouse buttons are clicked.
- [x] Disable Mouse Highlighter and verify that the module is not activated when you press the activation shortcut.
* Test the different settings and verify they apply:
- [x] Change activation shortcut and test it
- [x] Left button highlight color
- [x] Right button highlight color
- [ ] Opacity
- [ ] Radius
- [ ] Fade delay
- [ ] Fade duration
Mouse Pointer Crosshairs:
* Enable Mouse Pointer Crosshairs. Then:
- [x] Press the activation shortcut and verify the crosshairs appear, and that they follow the mouse around.
- [x] Press the activation shortcut again and verify the crosshairs disappear.
- [x] Disable Mouse Pointer Crosshairs and verify that the module is not activated when you press the activation shortcut.
* Test the different settings and verify they apply:
- [x] Change activation shortcut and test it
- [x] Crosshairs color
- [ ] Crosshairs opacity
- [ ] Crosshairs center radius
- [ ] Crosshairs thickness
- [ ] Crosshairs border color
- [ ] Crosshairs border size
Mouse Jump:
* Enable Mouse Jump. Then:
- [x] Press the activation shortcut and verify the screens preview appears.
- [x] Change activation shortcut and verify that new shortcut triggers Mouse Jump.
- [x] Click around the screen preview and ensure that mouse cursor jumped to clicked location.
- [ ] Reorder screens in Display settings and confirm that Mouse Jump reflects the change and still works correctly.
- [ ] Change scaling of screens and confirm that Mouse Jump still works correctly.
- [ ] Unplug additional monitors and confirm that Mouse Jump still works correctly.
- [x] Disable Mouse Jump and verify that the module is not activated when you press the activation shortcut.

View File

@@ -0,0 +1,58 @@
// 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;
namespace MouseUtils.UITests
{
public class FindMyMouseSettings
{
// Appearance settings
public string OverlayOpacity { get; set; }
public string Radius { get; set; }
public string InitialZoom { get; set; }
public string AnimationDuration { get; set; }
// Color settings
public string BackgroundColor { get; set; }
public string SpotlightColor { get; set; }
// Activation method settings
public enum ActivationMethod
{
PressLeftControlTwice,
PressRightControlTwice,
ShakeMouse,
CustomShortcut,
}
public ActivationMethod SelectedActivationMethod { get; set; }
// Optional constructor to initialize properties
public FindMyMouseSettings(
string overlayOpacity = "",
string radius = "",
string initialZoom = "",
string animationDuration = "",
string backgroundColor = "",
string spotlightColor = "")
{
OverlayOpacity = overlayOpacity;
Radius = radius;
InitialZoom = initialZoom;
AnimationDuration = animationDuration;
BackgroundColor = backgroundColor;
SpotlightColor = spotlightColor;
SelectedActivationMethod = ActivationMethod.PressLeftControlTwice; // Default value
}
}
}

View File

@@ -0,0 +1,291 @@
// 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.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
// The MouseUtils module relies on simulating system-level input events (such as mouse movement or key presses) to test visual or behavioral responses.
// The UI Test framework provides built-in methods for simulating mouse movement and clicks, which work for MouseUtils reliably on high-performance dev boxes.
// However, on low-performance environments such as CI/CD pipelines or virtual machines, these simulated input events are not always correctly recognized by the operating system.
// IOUtils class is added specifically for MouseUtils tests.
// For any test scenario that involves simulating continuous mouse movement (e.g., detecting crosshair changes while moving the cursor),
// input simulation methods in IOUtils class should be used.
namespace MouseUtils.UITests
{
public class IOUtil
{
private readonly UIntPtr ignoreKeyEventFlag = 0x5555;
[DllImport("user32.dll")]
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct INPUT
{
internal INPUTTYPE type;
internal InputUnion data;
internal static int Size
{
get { return Marshal.SizeOf<INPUT>(); }
}
}
[StructLayout(LayoutKind.Explicit)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct InputUnion
{
[FieldOffset(0)]
internal MOUSEINPUT mi;
[FieldOffset(0)]
internal KEYBDINPUT ki;
[FieldOffset(0)]
internal HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct MOUSEINPUT
{
internal int dx;
internal int dy;
internal int mouseData;
internal uint dwFlags;
internal uint time;
internal UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct KEYBDINPUT
{
internal short wVk;
internal short wScan;
internal uint dwFlags;
internal int time;
internal UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct HARDWAREINPUT
{
internal int uMsg;
internal short wParamL;
internal short wParamH;
}
internal enum INPUTTYPE : uint
{
INPUT_MOUSE = 0,
INPUT_KEYBOARD = 1,
INPUT_HARDWARE = 2,
}
[Flags]
internal enum KeyEventF
{
KeyDown = 0x0000,
ExtendedKey = 0x0001,
KeyUp = 0x0002,
Unicode = 0x0004,
Scancode = 0x0008,
}
[Flags]
internal enum MouseEventF : uint
{
MOVE = 0x0001,
LEFTDOWN = 0x0002,
LEFTUP = 0x0004,
RIGHTDOWN = 0x0008,
RIGHTUP = 0x0010,
ABSOLUTE = 0x8000,
MIDDLEDOWN = 0x0020,
MIDDLEUP = 0x0040,
}
public static void SimulateMouseDown(bool leftButton = true)
{
SendMouseInput(leftButton ? MouseEventF.LEFTDOWN : MouseEventF.RIGHTDOWN);
}
public static void SimulateMouseUp(bool leftButton = true)
{
SendMouseInput(leftButton ? MouseEventF.LEFTUP : MouseEventF.RIGHTUP);
}
public static void MouseClick(bool leftButton = true)
{
SendMouseInput(leftButton ? MouseEventF.LEFTDOWN : MouseEventF.RIGHTDOWN);
SendMouseInput(leftButton ? MouseEventF.LEFTUP : MouseEventF.RIGHTUP);
}
private static void SendMouseInput(MouseEventF mouseFlags)
{
var input = new INPUT
{
type = INPUTTYPE.INPUT_MOUSE,
data = new InputUnion
{
mi = new MOUSEINPUT
{
dx = 0,
dy = 0,
mouseData = 0,
dwFlags = (uint)mouseFlags,
time = 0,
dwExtraInfo = UIntPtr.Zero,
},
},
};
INPUT[] inputs = [input];
_ = SendInput(1, inputs, INPUT.Size);
}
[DllImport("user32.dll")]
private static extern IntPtr GetMessageExtraInfo();
public static void MoveMouseBy(int dx, int dy)
{
var input = new INPUT
{
type = INPUTTYPE.INPUT_MOUSE,
data = new InputUnion
{
mi = new MOUSEINPUT
{
dx = dx,
dy = dy,
mouseData = 0,
dwFlags = (uint)MouseEventF.MOVE,
time = 0,
dwExtraInfo = (nuint)GetMessageExtraInfo(),
},
},
};
INPUT[] inputs = [input];
_ = SendInput(1, inputs, INPUT.Size);
}
[DllImport("user32.dll")]
private static extern int GetSystemMetrics(int nIndex);
public static void MoveMouseTo(int x, int y)
{
int screenWidth = GetSystemMetrics(0);
int screenHeight = GetSystemMetrics(1);
int normalizedX = (int)(x * 65535 / screenWidth);
int normalizedY = (int)(y * 65535 / screenHeight);
var input = new INPUT
{
type = INPUTTYPE.INPUT_MOUSE,
data = new InputUnion
{
mi = new MOUSEINPUT
{
dx = normalizedX,
dy = normalizedY,
mouseData = 0,
dwFlags = (uint)(MouseEventF.MOVE | MouseEventF.ABSOLUTE),
time = 0,
dwExtraInfo = UIntPtr.Zero,
},
},
};
INPUT[] inputs = [input];
_ = SendInput(1, inputs, INPUT.Size);
}
private void SendSingleKeyboardInput(short keyCode, uint keyStatus)
{
var inputShift = new INPUT
{
type = INPUTTYPE.INPUT_KEYBOARD,
data = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = keyCode,
dwFlags = keyStatus,
// Any keyevent with the extraInfo set to this value will be ignored by the keyboard hook and sent to the system instead.
dwExtraInfo = ignoreKeyEventFlag,
},
},
};
INPUT[] inputs = [inputShift];
_ = SendInput(1, inputs, INPUT.Size);
}
public static void SimulateKeyDown(ushort keyCode)
{
SendKey(keyCode, false);
}
public static void SimulateKeyUp(ushort keyCode)
{
SendKey(keyCode, true);
}
public static void SimulateKeyPress(ushort keyCode)
{
SendKey(keyCode, false);
SendKey(keyCode, true);
}
public static void SimulateShortcut(params ushort[] keyCodes)
{
foreach (var key in keyCodes)
{
SimulateKeyDown(key);
}
for (int i = keyCodes.Length - 1; i >= 0; i--)
{
SimulateKeyUp(keyCodes[i]);
}
}
public static void SendKey(ushort keyCode, bool keyUp)
{
var inputShift = new INPUT
{
type = INPUTTYPE.INPUT_KEYBOARD,
data = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = (short)keyCode,
dwFlags = (uint)(keyUp ? KeyEventF.KeyUp : 0),
dwExtraInfo = (uint)IntPtr.Zero,
},
},
};
INPUT[] inputs = [inputShift];
_ = SendInput(1, inputs, INPUT.Size);
}
}
}

View File

@@ -0,0 +1,74 @@
// 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;
namespace MouseUtils.UITests
{
public class MouseHighlighterSettings
{
// Appearance settings
public string Radius { get; set; }
public string FadeDelay { get; set; }
public string FadeDuration { get; set; }
// Color settings
public string PrimaryButtonHighlightColor { get; set; }
public string SecondaryButtonHighlightColor { get; set; }
public string AlwaysHighlightColor { get; set; }
// Settings UI Elements
public enum SettingsUIElements
{
PrimaryButtonHighlightColorGroup,
SecondaryButtonHighlightColorGroup,
AlwaysHighlightColorGroup,
RadiusEdit,
FadeDelayEdit,
FadeDurationEdit,
}
private Dictionary<SettingsUIElements, string> ElementNameMap { get; }
// Optional constructor to initialize properties
public MouseHighlighterSettings(
string radius = "",
string fadeDelay = "",
string fadeDuration = "",
string primaryButtonHighlightColor = "",
string secondaryButtonHighlightColor = "",
string alwaysHighlightColor = "")
{
this.Radius = radius;
this.FadeDelay = fadeDelay;
this.FadeDuration = fadeDuration;
this.PrimaryButtonHighlightColor = primaryButtonHighlightColor;
this.SecondaryButtonHighlightColor = secondaryButtonHighlightColor;
this.AlwaysHighlightColor = alwaysHighlightColor;
ElementNameMap = new Dictionary<SettingsUIElements, string>
{
[SettingsUIElements.PrimaryButtonHighlightColorGroup] = @"Primary button highlight color",
[SettingsUIElements.SecondaryButtonHighlightColorGroup] = @"Secondary button highlight color",
[SettingsUIElements.AlwaysHighlightColorGroup] = @"Always highlight color",
[SettingsUIElements.RadiusEdit] = @"Radius (px) Minimum5",
[SettingsUIElements.FadeDelayEdit] = @"Fade delay (ms) Minimum0",
[SettingsUIElements.FadeDurationEdit] = @"Fade duration (ms) Minimum0",
};
}
public string GetElementName(SettingsUIElements element)
{
return ElementNameMap[element];
}
}
}

View File

@@ -0,0 +1,86 @@
// 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 Windows.UI.Core.AnimationMetrics;
namespace MouseUtils.UITests
{
public class MousePointerCrosshairsSettings
{
// Appearance settings
public string Opacity { get; set; }
public string CenterRadius { get; set; }
public string Thickness { get; set; }
public string BorderSize { get; set; }
public bool IsFixLength { get; set; }
public string FixedLength { get; set; }
// Color settings
public string CrosshairsColor { get; set; }
public string CrosshairsBorderColor { get; set; }
// Settings UI Elements
public enum SettingsUIElements
{
CrosshairsColorGroup,
CrosshairsBorderColorGroup,
OpacitySlider,
CenterRadiusEdit,
ThicknessEdit,
BorderSizeEdit,
FixedLengthEdit,
IsFixLengthToggle,
}
private Dictionary<SettingsUIElements, string> ElementNameMap { get; }
// Optional constructor to initialize properties
public MousePointerCrosshairsSettings(
string opacity = "",
string centerRadius = "",
string thickness = "",
string borderSize = "",
bool isFixLength = false,
string fixedLength = "",
string crosshairsColor = "",
string crosshairsBorderColor = "")
{
this.Opacity = opacity;
this.CenterRadius = centerRadius;
this.Thickness = thickness;
this.BorderSize = borderSize;
this.IsFixLength = isFixLength;
this.FixedLength = fixedLength;
this.CrosshairsColor = crosshairsColor;
this.CrosshairsBorderColor = crosshairsBorderColor;
ElementNameMap = new Dictionary<SettingsUIElements, string>
{
[SettingsUIElements.CrosshairsColorGroup] = @"Crosshairs color",
[SettingsUIElements.CrosshairsBorderColorGroup] = @"Crosshairs border color",
[SettingsUIElements.OpacitySlider] = @"Crosshairs opacity (%)",
[SettingsUIElements.CenterRadiusEdit] = @"Crosshairs center radius (px) Minimum0 Maximum500",
[SettingsUIElements.ThicknessEdit] = @"Crosshairs thickness (px) Minimum1 Maximum50",
[SettingsUIElements.BorderSizeEdit] = @"Crosshairs border size (px) Minimum0 Maximum50",
[SettingsUIElements.FixedLengthEdit] = @"Crosshairs fixed length (px) Minimum1",
[SettingsUIElements.IsFixLengthToggle] = @"Fix crosshairs length",
};
}
public string GetElementName(SettingsUIElements element)
{
return ElementNameMap[element];
}
}
}

View File

@@ -0,0 +1,59 @@
// 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.Collections.Generic;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
namespace MouseUtils.UITests
{
public class MouseUtilsSettings
{
// Mouse Utils Modules
public enum MouseUtils
{
MouseHighlighter,
FindMyMouse,
MousePointerCrosshairs,
MouseJump,
}
private static readonly Dictionary<MouseUtils, string> MouseUtilUINameMap = new()
{
[MouseUtils.MouseHighlighter] = @"Mouse Highlighter",
[MouseUtils.FindMyMouse] = @"Find My Mouse",
[MouseUtils.MousePointerCrosshairs] = @"Mouse Pointer Crosshairs",
[MouseUtils.MouseJump] = @"Mouse Jump",
};
private static readonly Dictionary<MouseUtils, string> MouseUtilUIToggleMap = new()
{
[MouseUtils.MouseHighlighter] = @"Enable Mouse Highlighter",
[MouseUtils.FindMyMouse] = @"Enable Find My Mouse",
[MouseUtils.MousePointerCrosshairs] = @"Enable Mouse Pointer Crosshairs",
[MouseUtils.MouseJump] = @"Enable Mouse Jump",
};
public static string GetMouseUtilUIName(MouseUtils element)
{
return MouseUtilUINameMap[element];
}
public static void SetMouseUtilEnabled(Custom? custom, MouseUtils element, bool isEnable = true)
{
if (custom != null)
{
string toggleName = MouseUtilUIToggleMap[element];
var toggle = custom.Find<ToggleSwitch>(toggleName);
toggle.Toggle(isEnable);
}
else
{
Assert.Fail(element + " custom not found.");
}
}
}
}

View File

@@ -0,0 +1,24 @@
// 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 Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace WorkspacesEditorUITest;
[TestClass]
public class WorkspacesEditorTests : UITestBase
{
public WorkspacesEditorTests()
: base(PowerToysModule.Workspaces, WindowSize.Medium)
{
}
[TestMethod("WorkspacesEditor.Items.Present")]
[TestCategory("Workspaces UI")]
public void TestItemsPresents()
{
Assert.IsTrue(this.Has<Button>("Create Workspace"), "Should have create workspace button");
}
}

View File

@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<RunVSTest>false</RunVSTest>
<IsTestProject>true</IsTestProject>
<IsPackable>false</IsPackable>
<AssemblyName>PowerToys.Workspaces.UITests</AssemblyName>
</PropertyGroup>
<PropertyGroup>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\Workspaces.UITests\</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Appium.WebDriver" />
<PackageReference Include="MSTest" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
</ItemGroup>
</Project>

View File

@@ -23,6 +23,7 @@
namespace NonLocalizable
{
const wchar_t ToolWindowClassName[] = L"FancyZones_ZonesOverlay";
const wchar_t ToolWindowName[] = L"FancyZones_ZonesOverlay";
}
using namespace FancyZonesUtils;
@@ -59,7 +60,7 @@ namespace
HWND windowFromPool = ExtractWindow();
if (windowFromPool == NULL)
{
HWND window = CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, L"", WS_POPUP, position.left(), position.top(), position.width(), position.height(), nullptr, nullptr, hinstance, owner);
HWND window = CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, NonLocalizable::ToolWindowName, WS_POPUP, position.left(), position.top(), position.width(), position.height(), nullptr, nullptr, hinstance, owner);
Logger::info("Creating new ZonesOverlay window, hWnd = {}", (void*)window);
FancyZonesWindowUtils::MakeWindowTransparent(window);

View File

@@ -0,0 +1,673 @@
// 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.Threading.Tasks;
using System.Windows.Forms;
using FancyZonesEditor.Models;
using FancyZonesEditorCommon.Data;
using Microsoft.FancyZones.UITests.Utils;
using Microsoft.FancyZonesEditor.UITests.Utils;
using Microsoft.FancyZonesEditor.UnitTests.Utils;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualBasic.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
using static FancyZonesEditorCommon.Data.CustomLayouts;
namespace UITests_FancyZones
{
[TestClass]
public class DragWindowTests : UITestBase
{
private static readonly IOTestHelper AppZoneHistory = new FancyZonesEditorFiles().AppZoneHistoryIOHelper;
private static string nonPrimaryMouseButton = "Right";
private static string highlightColor = "#008CFF"; // set highlight color
private static string inactivateColor = "#AACDFF"; // set inactivate zone color
// set screen margin
private static int screenMarginTop;
private static int screenMarginLeft;
private static int screenMarginRight;
private static int screenMarginBottom;
// set 1/4 margin
private static int quarterX;
private static int quarterY;
private static string powertoysWindowName = "PowerToys Settings"; // set powertoys settings window name
public DragWindowTests()
: base(PowerToysModule.PowerToysSettings, WindowSize.Medium)
{
}
[TestInitialize]
public void TestInitialize()
{
// ClearOpenWindows
ClearOpenWindows();
// kill all processes related to FancyZones Editor to ensure a clean state
Session.KillAllProcessesByName("PowerToys.FancyZonesEditor");
AppZoneHistory.DeleteFile();
this.RestartScopeExe();
FancyZonesEditorHelper.Files.Restore();
// Set a custom layout with 1 subzones and clear app zone history
SetupCustomLayouts();
// Get the current mouse button setting
nonPrimaryMouseButton = SystemInformation.MouseButtonsSwapped ? "Left" : "Right";
// get PowerToys window Name
powertoysWindowName = ZoneSwitchHelper.GetActiveWindowTitle();
// Ensure FancyZones settings page is visible and enable FancyZones
LaunchFancyZones();
}
/// <summary>
/// Test Use Shift key to activate zones while dragging a window in FancyZones Zone Behaviour Settings
/// <list type="bullet">
/// <item>
/// <description>Verifies that holding Shift while dragging shows all zones as expected.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("FancyZones.Settings.TestShowZonesOnShiftDuringDrag")]
[TestCategory("FancyZones_Dragging #1")]
public void TestShowZonesOnShiftDuringDrag()
{
string testCaseName = nameof(TestShowZonesOnShiftDuringDrag);
Pane dragElement = Find<Pane>(By.Name("Non Client Input Sink Window")); // element to drag
var offSet = ZoneSwitchHelper.GetOffset(dragElement, quarterX, quarterY);
var (initialColor, withShiftColor) = RunDragInteractions(
preAction: () =>
{
dragElement.DragAndHold(offSet.Dx, offSet.Dy);
},
postAction: () =>
{
Session.PressKey(Key.Shift);
Task.Delay(500).Wait();
},
releaseAction: () =>
{
Session.ReleaseKey(Key.Shift);
Task.Delay(5000).Wait(); // Optional: Wait for a moment to ensure window switch
},
testCaseName: testCaseName);
string zoneColorWithoutShift = GetOutWindowPixelColor(30);
Assert.AreNotEqual(initialColor, withShiftColor, $"[{testCaseName}] Zone display failed.");
Assert.IsTrue(
withShiftColor == inactivateColor || withShiftColor == highlightColor,
$"[{testCaseName}] Zone display failed: withShiftColor was {withShiftColor}, expected {inactivateColor} or {highlightColor}.");
Assert.AreEqual(inactivateColor, withShiftColor, $"[{testCaseName}] Zone display failed.");
Assert.AreEqual(zoneColorWithoutShift, initialColor, $"[{testCaseName}] Zone deactivated failed.");
dragElement.ReleaseDrag();
Clean();
}
/// <summary>
/// Test dragging a window during Shift key press in FancyZones Zone Behaviour Settings
/// <list type="bullet">
/// <item>
/// <description>Verifies that dragging activates zones as expected.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("FancyZones.Settings.TestShowZonesOnDragDuringShift")]
[TestCategory("FancyZones_Dragging #2")]
public void TestShowZonesOnDragDuringShift()
{
string testCaseName = nameof(TestShowZonesOnDragDuringShift);
var dragElement = Find<Pane>(By.Name("Non Client Input Sink Window"));
var offSet = ZoneSwitchHelper.GetOffset(dragElement, quarterX, quarterY);
var (initialColor, withDragColor) = RunDragInteractions(
preAction: () =>
{
dragElement.Drag(offSet.Dx, offSet.Dy);
Session.PressKey(Key.Shift);
},
postAction: () =>
{
dragElement.DragAndHold(0, 0);
Task.Delay(5000).Wait();
},
releaseAction: () =>
{
dragElement.ReleaseDrag();
Session.ReleaseKey(Key.Shift);
},
testCaseName: testCaseName);
Assert.AreNotEqual(initialColor, withDragColor, $"[{testCaseName}] Zone color did not change; zone activation failed.");
Assert.AreEqual(highlightColor, withDragColor, $"[{testCaseName}] Zone color did not match the highlight color; activation failed.");
// double check by app-zone-history.json
string appZoneHistoryJson = AppZoneHistory.GetData();
string? zoneNumber = ZoneSwitchHelper.GetZoneIndexSetByAppName(powertoysWindowName, appZoneHistoryJson);
Assert.IsNull(zoneNumber, $"[{testCaseName}] AppZoneHistory layout was unexpectedly set.");
Clean();
}
/// <summary>
/// Test toggling zones using a non-primary mouse click during window dragging.
/// <list type="bullet">
/// <item>
/// <description>Verifies that clicking a non-primary mouse button deactivates zones while dragging a window.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("FancyZones.Settings.TestToggleZonesWithNonPrimaryMouseClick")]
[TestCategory("FancyZones_Dragging #3")]
public void TestToggleZonesWithNonPrimaryMouseClick()
{
string testCaseName = nameof(TestToggleZonesWithNonPrimaryMouseClick);
var dragElement = Find<Pane>(By.Name("Non Client Input Sink Window"));
var offSet = ZoneSwitchHelper.GetOffset(dragElement, quarterX, quarterY);
var (initialColor, withMouseColor) = RunDragInteractions(
preAction: () =>
{
// activate zone
dragElement.DragAndHold(offSet.Dx, offSet.Dy);
},
postAction: () =>
{
// press non-primary mouse button to toggle zones
Session.PerformMouseAction(
nonPrimaryMouseButton == "Right" ? MouseActionType.RightClick : MouseActionType.LeftClick);
},
releaseAction: () =>
{
dragElement.ReleaseDrag();
},
testCaseName: testCaseName);
// check the zone color is deactivated
Assert.AreNotEqual(highlightColor, withMouseColor, $"[{testCaseName}] Zone deactivation failed.");
// check the zone color is activated
Assert.AreEqual(highlightColor, initialColor, $"[{testCaseName}] Zone activation failed.");
Clean();
}
/// <summary>
/// Test both use Shift and non primary mouse off settings.
/// <list type="bullet">
/// <item>
/// <description>Verifies that pressing the Shift key deactivates zones during a window drag-and-hold action.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("FancyZones.Settings.TestShowZonesWhenShiftAndMouseOff")]
[TestCategory("FancyZones_Dragging #4")]
public void TestShowZonesWhenShiftAndMouseOff()
{
string testCaseName = nameof(TestShowZonesWhenShiftAndMouseOff);
Pane dragElement = Find<Pane>(By.Name("Non Client Input Sink Window"));
var offSet = ZoneSwitchHelper.GetOffset(dragElement, quarterX, quarterY);
var (initialColor, withShiftColor) = RunDragInteractions(
preAction: () =>
{
// activate zone
dragElement.DragAndHold(offSet.Dx, offSet.Dy);
},
postAction: () =>
{
// press Shift Key to deactivate zones
Session.PressKey(Key.Shift);
Task.Delay(500).Wait();
},
releaseAction: () =>
{
dragElement.ReleaseDrag();
Session.ReleaseKey(Key.Shift);
},
testCaseName: testCaseName);
Assert.AreEqual(highlightColor, initialColor, $"[{testCaseName}] Zone activation failed.");
Assert.AreNotEqual(highlightColor, withShiftColor, $"[{testCaseName}] Zone deactivation failed.");
Clean();
}
/// <summary>
/// Test zone visibility when both Shift key and mouse settings are involved.
/// <list type="bullet">
/// <item>
/// <description>Verifies that zones are activated when Shift is pressed during drag, and deactivated by a non-primary mouse click.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("FancyZones.Settings.TestShowZonesWhenShiftAndMouseOn")]
[TestCategory("FancyZones_Dragging #5")]
public void TestShowZonesWhenShiftAndMouseOn()
{
string testCaseName = nameof(TestShowZonesWhenShiftAndMouseOn);
var dragElement = Find<Pane>(By.Name("Non Client Input Sink Window"));
var offSet = ZoneSwitchHelper.GetOffset(dragElement, quarterX, quarterY);
var (initialColor, withShiftColor) = RunDragInteractions(
preAction: () =>
{
dragElement.DragAndHold(offSet.Dx, offSet.Dy);
},
postAction: () =>
{
Session.PressKey(Key.Shift);
},
releaseAction: () =>
{
},
testCaseName: testCaseName);
Assert.AreEqual(inactivateColor, withShiftColor, $"[{testCaseName}] show zone failed.");
Session.PerformMouseAction(
nonPrimaryMouseButton == "Right" ? MouseActionType.RightClick : MouseActionType.LeftClick);
string zoneColorWithMouse = GetOutWindowPixelColor(30);
Assert.AreEqual(initialColor, zoneColorWithMouse, $"[{nameof(TestShowZonesWhenShiftAndMouseOff)}] Zone deactivate failed.");
Session.ReleaseKey(Key.Shift);
dragElement.ReleaseDrag();
Clean();
}
/// <summary>
/// Test that a window becomes transparent during dragging when the transparent window setting is enabled.
/// <list type="bullet">
/// <item>
/// <description>Verifies that the window appears transparent while being dragged.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("FancyZones.Settings.TestMakeDraggedWindowTransparentOn")]
[TestCategory("FancyZones_Dragging #8")]
public void TestMakeDraggedWindowTransparentOn()
{
var pixel = GetPixelWhenMakeDraggedWindow();
Assert.AreNotEqual(pixel.PixelInWindow, pixel.TransPixel, $"[{nameof(TestMakeDraggedWindowTransparentOn)}] Window transparency failed.");
Clean();
}
/// <summary>
/// Test that a window remains opaque during dragging when the transparent window setting is disabled.
/// <list type="bullet">
/// <item>
/// <description>Verifies that the window is not transparent while being dragged.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("FancyZones.Settings.TestMakeDraggedWindowTransparentOff")]
[TestCategory("FancyZones_Dragging #8")]
public void TestMakeDraggedWindowTransparentOff()
{
var pixel = GetPixelWhenMakeDraggedWindow();
Assert.AreEqual(pixel.PixelInWindow, pixel.TransPixel, $"[{nameof(TestMakeDraggedWindowTransparentOff)}] Window without transparency failed.");
Clean();
}
private void Clean()
{
// clean app zone history file
AppZoneHistory.DeleteFile();
}
// Helper method to ensure the desktop has no open windows by clicking the "Show Desktop" button
private void ClearOpenWindows()
{
string desktopButtonName;
// Check for both possible button names (Win10/Win11)
if (this.FindAll<Microsoft.PowerToys.UITest.Button>("Show Desktop", 5000, true).Count == 0)
{
// win10
desktopButtonName = "Show desktop";
}
else
{
// win11
desktopButtonName = "Show Desktop";
}
this.Find<Microsoft.PowerToys.UITest.Button>(By.Name(desktopButtonName), 5000, true).Click(false, 500, 2000);
}
// Setup custom layout with 1 subzones
private void SetupCustomLayouts()
{
var customLayouts = new CustomLayouts();
var customLayoutListWrapper = CustomLayoutsList;
if (TestContext.TestName == "TestMakeDraggedWindowTransparentOff")
{
customLayoutListWrapper = CustomLayoutsListWithTwo;
}
FancyZonesEditorHelper.Files.CustomLayoutsIOHelper.WriteData(customLayouts.Serialize(customLayoutListWrapper));
}
// launch FancyZones settings page
private void LaunchFancyZones()
{
if (this.FindAll<NavigationViewItem>("FancyZones").Count == 0)
{
this.Find<NavigationViewItem>("Windowing & Layouts").Click();
}
this.Find<NavigationViewItem>("FancyZones").Click();
this.Find<ToggleSwitch>("Enable FancyZones").Toggle(true);
this.Session.SetMainWindowSize(WindowSize.Large);
Find<Element>(By.AccessibilityId("HeaderPresenter")).Click();
this.Scroll(6, "Down"); // Pull the settings page up to make sure the settings are visible
ZoneBehaviourSettings(TestContext.TestName);
this.Find<Microsoft.PowerToys.UITest.Button>("Launch layout editor").Click(false, 500, 10000);
this.Session.Attach(PowerToysModule.FancyZone);
// pipeline machine may have an unstable delays, causing the custom layout to be unavailable as we set. then A retry is required.
// Console.WriteLine($"after launch, Custom layout data: {customLayoutData}");
try
{
this.Find<Microsoft.PowerToys.UITest.Button>("Maximize").Click();
// Set the FancyZones layout to a custom layout
this.Find<Element>(By.Name("Custom Column")).Click();
}
catch (Exception)
{
// Console.WriteLine($"[Exception] Failed to attach to FancyZones window. Retrying...{ex.Message}");
this.Find<Microsoft.PowerToys.UITest.Button>("Close").Click();
this.Session.Attach(PowerToysModule.PowerToysSettings);
SetupCustomLayouts();
this.Find<Microsoft.PowerToys.UITest.Button>("Launch layout editor").Click(false, 5000, 5000);
this.Session.Attach(PowerToysModule.FancyZone);
this.Find<Microsoft.PowerToys.UITest.Button>("Maximize").Click();
// customLayoutData = FancyZonesEditorHelper.Files.CustomLayoutsIOHelper.GetData();
// Console.WriteLine($"after retry, Custom layout data: {customLayoutData}");
// Set the FancyZones layout to a custom layout
this.Find<Element>(By.Name("Custom Column")).Click();
}
// Get screen margins for positioning checks
GetScreenMargins();
// Close layout editor window
SendKeys(Key.Alt, Key.F4);
// make window small to detect zone easily
Session.Attach(powertoysWindowName, WindowSize.Small);
}
// Get the screen margins to calculate the dragged window position
private void GetScreenMargins()
{
var rect = Session.GetMainWindowRect();
screenMarginTop = rect.Top;
screenMarginLeft = rect.Left;
screenMarginRight = rect.Right;
screenMarginBottom = rect.Bottom;
(quarterX, quarterY) = ZoneSwitchHelper.GetScreenMargins(rect, 4);
}
// Get the mouse color of the pixel when make dragged window
private (string PixelInWindow, string TransPixel) GetPixelWhenMakeDraggedWindow()
{
var dragElement = Find<Pane>(By.Name("Non Client Input Sink Window"));
// maximize the window to make sure get pixel color more accurate
dragElement.DoubleClick();
var offSet = ZoneSwitchHelper.GetOffset(dragElement, quarterX, quarterY);
Session.PressKey(Key.Shift);
dragElement.DragAndHold(offSet.Dx, offSet.Dy);
Task.Delay(1000).Wait(); // Optional: Wait for a moment to ensure the window is in position
Tuple<int, int> pos = GetMousePosition();
string pixelInWindow = this.GetPixelColorString(pos.Item1, pos.Item2);
Session.ReleaseKey(Key.Shift);
Task.Delay(1000).Wait(); // Optional: Wait for a moment to ensure the window is in position
string transPixel = this.GetPixelColorString(pos.Item1, pos.Item2);
dragElement.ReleaseDrag();
return (pixelInWindow, transPixel);
}
/// <summary>
/// Gets the color of a pixel located just outside the application's window.
/// </summary>
/// <param name="spacing">
/// The minimum spacing (in pixels) required between the window edge and screen margin
/// to determine a safe pixel sampling area outside the window.
/// </param>
/// <returns>
/// A string representing the color of the pixel at the computed location outside the window,
/// </returns>
private string GetOutWindowPixelColor(int spacing)
{
var rect = Session.GetMainWindowRect();
int checkX, checkY;
if ((rect.Top - screenMarginTop) >= spacing)
{
checkX = rect.Left;
checkY = screenMarginTop + (spacing / 2);
}
else if ((screenMarginBottom - rect.Bottom) >= spacing)
{
checkX = rect.Left;
checkY = rect.Bottom + (spacing / 2);
}
else if ((rect.Left - screenMarginLeft) >= spacing)
{
checkX = rect.Left - (spacing / 2);
checkY = rect.Top;
}
else if ((screenMarginRight - rect.Right) >= spacing)
{
checkX = rect.Right + (spacing / 2);
checkY = rect.Top;
}
else
{
throw new ArgumentOutOfRangeException(nameof(spacing), "No sufficient margin to sample outside the window.");
}
Task.Delay(1000).Wait(); // Optional: Wait for a moment to ensure the mouse is in position
string zoneColor = this.GetPixelColorString(checkX, checkY);
return zoneColor;
}
/// <summary>
/// Runs drag interactions during a FancyZones test and returns the initial and final zone highlight colors.
/// </summary>
/// <param name="preAction">An optional action to execute before the drag starts (e.g., setup or key press).</param>
/// <param name="postAction">An optional action to execute after the drag is initiated but before it's released.</param>
/// <param name="releaseAction">An optional action to execute when releasing the dragged window (e.g., mouse up).</param>
/// <param name="testCaseName">The name of the test case for logging or diagnostics.</param>
/// <returns>
/// A tuple containing:
/// <list type="bullet">
/// <item><description><c>InitialZoneColor</c>: The zone highlight color before interaction completes.</description></item>
/// <item><description><c>FinalZoneColor</c>: The zone highlight color after interaction completes.</description></item>
/// </list>
/// </returns>
private (string InitialZoneColor, string FinalZoneColor) RunDragInteractions(
Action? preAction,
Action? postAction,
Action? releaseAction,
string testCaseName)
{
// Invoke the pre-action
preAction?.Invoke();
// Capture initial window state and zone color
var initialWindowRect = Session.GetMainWindowRect();
string initialZoneColor = GetOutWindowPixelColor(30);
// Invoke the post-action
postAction?.Invoke();
// Capture final zone color after the interaction
string finalZoneColor = GetOutWindowPixelColor(30);
releaseAction?.Invoke();
// Return initial and final zone colors
return (initialZoneColor, finalZoneColor);
}
// set the custom layout
private static readonly CustomLayouts.CustomLayoutListWrapper CustomLayoutsList = new CustomLayouts.CustomLayoutListWrapper
{
CustomLayouts = new List<CustomLayouts.CustomLayoutWrapper>
{
new CustomLayouts.CustomLayoutWrapper
{
Uuid = "{63F09977-D327-4DAC-98F4-0C886CAE9517}",
Type = CustomLayout.Grid.TypeToString(),
Name = "Custom Column",
Info = new CustomLayouts().ToJsonElement(new CustomLayouts.GridInfoWrapper
{
Rows = 1,
Columns = 1,
RowsPercentage = new List<int> { 10000 },
ColumnsPercentage = new List<int> { 10000 },
CellChildMap = new int[][] { [0] },
SensitivityRadius = 20,
ShowSpacing = true,
Spacing = 10, // set spacing to 0 make sure the zone is full of the screen
}),
},
},
};
// set the custom layout with 1 subzones
private static readonly CustomLayouts.CustomLayoutListWrapper CustomLayoutsListWithTwo = new CustomLayouts.CustomLayoutListWrapper
{
CustomLayouts = new List<CustomLayouts.CustomLayoutWrapper>
{
new CustomLayouts.CustomLayoutWrapper
{
Uuid = "{63F09977-D327-4DAC-98F4-0C886CAE9517}",
Type = CustomLayout.Grid.TypeToString(),
Name = "Custom Column",
Info = new CustomLayouts().ToJsonElement(new CustomLayouts.GridInfoWrapper
{
Rows = 1,
Columns = 2,
RowsPercentage = new List<int> { 10000 },
ColumnsPercentage = new List<int> { 5000, 5000 },
CellChildMap = new int[][] { [0, 1] },
SensitivityRadius = 20,
ShowSpacing = true,
Spacing = 10,
}),
},
},
};
private string GetZoneColor(string color)
{
// Click on the "Highlight color" group
Find<Group>(color).Click();
// Optional: Ensure the hex textbox is found (to wait until the UI loads)
var hexBox = Find<Element>(By.AccessibilityId("HexTextBox"));
Task.Delay(500).Wait(); // Optional: Wait for the UI to update
// Get and return the RGB hex value text
var hexColorElement = Find<Element>("RGB hex");
// return mouse to color set position
Find<Group>(color).Click();
return hexColorElement.Text;
}
// set the zone behaviour settings
private void ZoneBehaviourSettings(string? testName)
{
// test settings
Microsoft.PowerToys.UITest.CheckBox useShiftCheckBox = this.Find<Microsoft.PowerToys.UITest.CheckBox>("Hold Shift key to activate zones while dragging a window");
Microsoft.PowerToys.UITest.CheckBox useNonPrimaryMouseCheckBox = this.Find<Microsoft.PowerToys.UITest.CheckBox>("Use a non-primary mouse button to toggle zone activation");
Microsoft.PowerToys.UITest.CheckBox makeDraggedWindowTransparent = this.Find<Microsoft.PowerToys.UITest.CheckBox>("Make dragged window transparent");
Find<Microsoft.PowerToys.UITest.CheckBox>("Show zone number").SetCheck(false, 100);
Find<Slider>("Opacity (%)").QuickSetValue(100); // make highlight color visible with opacity 100
// Get the highlight and inactivate color from appearance settings
Find<Microsoft.PowerToys.UITest.ComboBox>("Zone appearance").Click();
Find<Element>("Custom colors").Click();
// get the highlight (activated) and inactivate zone color
highlightColor = GetZoneColor("Highlight color");
inactivateColor = GetZoneColor("Inactive color");
this.Scroll(2, "Down");
makeDraggedWindowTransparent.SetCheck(false, 500); // set make dragged window transparent to false or will influence the color comparison
this.Scroll(6, "Up");
switch (testName)
{
case "TestShowZonesOnShiftDuringDrag":
useShiftCheckBox.SetCheck(true, 500);
useNonPrimaryMouseCheckBox.SetCheck(false, 500);
break;
case "TestShowZonesOnDragDuringShift":
useShiftCheckBox.SetCheck(true, 500);
useNonPrimaryMouseCheckBox.SetCheck(false, 500);
break;
case "TestToggleZonesWithNonPrimaryMouseClick":
useShiftCheckBox.SetCheck(false, 500);
useNonPrimaryMouseCheckBox.SetCheck(true, 500);
break;
case "TestShowZonesWhenShiftAndMouseOff":
useShiftCheckBox.SetCheck(false, 500);
useNonPrimaryMouseCheckBox.SetCheck(false, 500);
break;
case "TestShowZonesWhenShiftAndMouseOn":
useShiftCheckBox.SetCheck(true, 500);
useNonPrimaryMouseCheckBox.SetCheck(true, 500);
break;
case "TestMakeDraggedWindowTransparentOff":
useShiftCheckBox.SetCheck(true, 500);
useNonPrimaryMouseCheckBox.SetCheck(false, 500);
break; // Added break to prevent fall-through
case "TestMakeDraggedWindowTransparentOn":
useNonPrimaryMouseCheckBox.SetCheck(false, 500);
useShiftCheckBox.SetCheck(true, 500);
this.Scroll(5, "Down"); // Pull the settings page up to make sure the settings are visible
makeDraggedWindowTransparent.SetCheck(true, 500);
this.Scroll(5, "Up");
break; // Added break to prevent fall-through
default:
throw new ArgumentException("Unsupported Test Case.", testName);
}
}
}
}

View File

@@ -0,0 +1,673 @@
// 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.Threading;
using System.Threading.Tasks;
using System.Windows.Automation;
using FancyZonesEditor.Models;
using FancyZonesEditorCommon.Data;
using Microsoft.FancyZonesEditor.UITests;
using Microsoft.FancyZonesEditor.UnitTests.Utils;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using static FancyZonesEditorCommon.Data.CustomLayouts;
using static Microsoft.FancyZonesEditor.UnitTests.Utils.FancyZonesEditorHelper;
namespace UITests_FancyZones
{
[TestClass]
public class LayoutApplyHotKeyTests : UITestBase
{
public LayoutApplyHotKeyTests()
: base(PowerToysModule.PowerToysSettings, WindowSize.Large)
{
}
private static readonly EditorParameters.ParamsWrapper Parameters = new EditorParameters.ParamsWrapper
{
ProcessId = 1,
SpanZonesAcrossMonitors = false,
Monitors = new List<EditorParameters.NativeMonitorDataWrapper>
{
new EditorParameters.NativeMonitorDataWrapper
{
Monitor = "monitor-1",
MonitorInstanceId = "instance-id-1",
MonitorSerialNumber = "serial-number-1",
MonitorNumber = 1,
VirtualDesktop = "{FF34D993-73F3-4B8C-AA03-73730A01D6A8}",
Dpi = 96,
LeftCoordinate = 0,
TopCoordinate = 0,
WorkAreaHeight = 1040,
WorkAreaWidth = 1920,
MonitorHeight = 1080,
MonitorWidth = 1920,
IsSelected = true,
},
new EditorParameters.NativeMonitorDataWrapper
{
Monitor = "monitor-2",
MonitorInstanceId = "instance-id-2",
MonitorSerialNumber = "serial-number-2",
MonitorNumber = 2,
VirtualDesktop = "{FF34D993-73F3-4B8C-AA03-73730A01D6A8}",
Dpi = 96,
LeftCoordinate = 1920,
TopCoordinate = 0,
WorkAreaHeight = 1040,
WorkAreaWidth = 1920,
MonitorHeight = 1080,
MonitorWidth = 1920,
IsSelected = false,
},
},
};
private static readonly CustomLayouts.CustomLayoutListWrapper CustomLayoutsList = new CustomLayouts.CustomLayoutListWrapper
{
CustomLayouts = new List<CustomLayouts.CustomLayoutWrapper>
{
new CustomLayoutWrapper
{
Uuid = "{0D6D2F58-9184-4804-81E4-4E4CC3476DC1}",
Type = CustomLayout.Grid.TypeToString(),
Name = "Grid custom layout",
Info = new CustomLayouts().ToJsonElement(new GridInfoWrapper
{
Rows = 2,
Columns = 2,
RowsPercentage = new List<int> { 5000, 5000 },
ColumnsPercentage = new List<int> { 5000, 5000 },
CellChildMap = new int[][] { [0, 1], [2, 3] },
SensitivityRadius = 30,
Spacing = 26,
ShowSpacing = false,
}),
},
new CustomLayoutWrapper
{
Uuid = "{0EB9BF3E-010E-46D7-8681-1879D1E111E1}",
Type = CustomLayout.Grid.TypeToString(),
Name = "Grid-9",
Info = new CustomLayouts().ToJsonElement(new GridInfoWrapper
{
Rows = 3,
Columns = 3,
RowsPercentage = new List<int> { 2333, 3333, 4334 },
ColumnsPercentage = new List<int> { 2333, 3333, 4334 },
CellChildMap = new int[][] { [0, 1, 2], [3, 4, 5], [6, 7, 8] },
SensitivityRadius = 20,
Spacing = 3,
ShowSpacing = false,
}),
},
new CustomLayoutWrapper
{
Uuid = "{E7807D0D-6223-4883-B15B-1F3883944C09}",
Type = CustomLayout.Canvas.TypeToString(),
Name = "Canvas custom layout",
Info = new CustomLayouts().ToJsonElement(new CanvasInfoWrapper
{
RefHeight = 1040,
RefWidth = 1920,
SensitivityRadius = 10,
Zones = new List<CanvasInfoWrapper.CanvasZoneWrapper>
{
new CanvasInfoWrapper.CanvasZoneWrapper
{
X = 0,
Y = 0,
Width = 500,
Height = 250,
},
new CanvasInfoWrapper.CanvasZoneWrapper
{
X = 500,
Y = 0,
Width = 1420,
Height = 500,
},
new CanvasInfoWrapper.CanvasZoneWrapper
{
X = 0,
Y = 250,
Width = 1920,
Height = 500,
},
},
}),
},
},
};
private static readonly LayoutHotkeys.LayoutHotkeysWrapper LayoutHotkeysList = new LayoutHotkeys.LayoutHotkeysWrapper
{
LayoutHotkeys = new List<LayoutHotkeys.LayoutHotkeyWrapper>
{
new LayoutHotkeys.LayoutHotkeyWrapper
{
Key = 0,
LayoutId = "{0D6D2F58-9184-4804-81E4-4E4CC3476DC1}",
},
new LayoutHotkeys.LayoutHotkeyWrapper
{
Key = 1,
LayoutId = "{0EB9BF3E-010E-46D7-8681-1879D1E111E1}",
},
new LayoutHotkeys.LayoutHotkeyWrapper
{
Key = 2,
LayoutId = "{E7807D0D-6223-4883-B15B-1F3883944C09}",
},
},
};
private static readonly LayoutTemplates.TemplateLayoutsListWrapper TemplateLayoutsList = new LayoutTemplates.TemplateLayoutsListWrapper
{
LayoutTemplates = new List<LayoutTemplates.TemplateLayoutWrapper>
{
new LayoutTemplates.TemplateLayoutWrapper
{
Type = LayoutType.Blank.TypeToString(),
},
new LayoutTemplates.TemplateLayoutWrapper
{
Type = LayoutType.Focus.TypeToString(),
ZoneCount = 10,
},
new LayoutTemplates.TemplateLayoutWrapper
{
Type = LayoutType.Rows.TypeToString(),
ZoneCount = 2,
ShowSpacing = true,
Spacing = 10,
SensitivityRadius = 10,
},
new LayoutTemplates.TemplateLayoutWrapper
{
Type = LayoutType.Columns.TypeToString(),
ZoneCount = 2,
ShowSpacing = true,
Spacing = 20,
SensitivityRadius = 20,
},
new LayoutTemplates.TemplateLayoutWrapper
{
Type = LayoutType.Grid.TypeToString(),
ZoneCount = 4,
ShowSpacing = false,
Spacing = 10,
SensitivityRadius = 30,
},
new LayoutTemplates.TemplateLayoutWrapper
{
Type = LayoutType.PriorityGrid.TypeToString(),
ZoneCount = 3,
ShowSpacing = true,
Spacing = 1,
SensitivityRadius = 40,
},
},
};
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
FancyZonesEditorHelper.Files.ParamsIOHelper.WriteData(editorParameters.Serialize(Parameters));
LayoutTemplates layoutTemplates = new LayoutTemplates();
FancyZonesEditorHelper.Files.LayoutTemplatesIOHelper.WriteData(layoutTemplates.Serialize(TemplateLayoutsList));
CustomLayouts customLayouts = new CustomLayouts();
FancyZonesEditorHelper.Files.CustomLayoutsIOHelper.WriteData(customLayouts.Serialize(CustomLayoutsList));
DefaultLayouts defaultLayouts = new DefaultLayouts();
DefaultLayouts.DefaultLayoutsListWrapper defaultLayoutsListWrapper = new DefaultLayouts.DefaultLayoutsListWrapper
{
DefaultLayouts = new List<DefaultLayouts.DefaultLayoutWrapper>
{
new DefaultLayouts.DefaultLayoutWrapper
{
MonitorConfiguration = MonitorConfigurationType.Horizontal.TypeToString(),
Layout = new DefaultLayouts.DefaultLayoutWrapper.LayoutWrapper
{
Type = LayoutType.Focus.TypeToString(),
ZoneCount = 4,
ShowSpacing = true,
Spacing = 5,
SensitivityRadius = 20,
},
},
new DefaultLayouts.DefaultLayoutWrapper
{
MonitorConfiguration = MonitorConfigurationType.Vertical.TypeToString(),
Layout = new DefaultLayouts.DefaultLayoutWrapper.LayoutWrapper
{
Type = LayoutType.Custom.TypeToString(),
Uuid = "{0D6D2F58-9184-4804-81E4-4E4CC3476DC1}",
ZoneCount = 0,
ShowSpacing = false,
Spacing = 0,
SensitivityRadius = 0,
},
},
},
};
FancyZonesEditorHelper.Files.DefaultLayoutsIOHelper.WriteData(defaultLayouts.Serialize(defaultLayoutsListWrapper));
LayoutHotkeys layoutHotkeys = new LayoutHotkeys();
FancyZonesEditorHelper.Files.LayoutHotkeysIOHelper.WriteData(layoutHotkeys.Serialize(LayoutHotkeysList));
AppliedLayouts appliedLayouts = new AppliedLayouts();
AppliedLayouts.AppliedLayoutsListWrapper appliedLayoutsWrapper = new AppliedLayouts.AppliedLayoutsListWrapper
{
AppliedLayouts = new List<AppliedLayouts.AppliedLayoutWrapper> { },
};
FancyZonesEditorHelper.Files.AppliedLayoutsIOHelper.WriteData(appliedLayouts.Serialize(appliedLayoutsWrapper));
this.RestartScopeExe();
}
[TestMethod("FancyZones.Settings.TestApplyHotKey")]
[TestCategory("FancyZones #1")]
public void TestApplyHotKey()
{
this.OpenFancyZonesPanel();
this.ControlQuickLayoutSwitch(true);
// Set Hotkey
this.AttachFancyZonesEditor();
var layout = "Grid custom layout";
Session.Find<Element>(layout).Find<Button>(By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
const string key = "0";
var hotkeyComboBox = Session.Find<Element>(By.AccessibilityId(AccessibilityId.HotkeyComboBox));
Assert.IsNotNull(hotkeyComboBox);
hotkeyComboBox.Click();
var popup = Session.Find<Element>(By.ClassName(ClassName.Popup));
Assert.IsNotNull(popup);
popup.Find<Element>($"{key}").Click(); // assign a free hotkey
Task.Delay(3000).Wait();
this.CloseFancyZonesEditor();
this.AttachPowertoySetting();
SendKeys(Key.Win, Key.Ctrl, Key.Alt, Key.Num0);
Task.Delay(3000).Wait();
this.AttachFancyZonesEditor();
var element = this.Find<Element>(layout);
Assert.IsTrue(element.Selected, $"{element.Selected} Grid custom layout is not visible");
this.CloseFancyZonesEditor();
this.AttachPowertoySetting();
SendKeys(Key.Win, Key.Ctrl, Key.Alt, Key.Num1);
Task.Delay(3000).Wait();
this.AttachFancyZonesEditor();
element = this.Find<Element>("Grid-9");
Assert.IsTrue(element.Selected, $"{element.Selected} Grid-9 is not visible");
this.CloseFancyZonesEditor();
this.AttachPowertoySetting();
SendKeys(Key.Win, Key.Ctrl, Key.Alt, Key.Num2);
Task.Delay(3000).Wait();
this.AttachFancyZonesEditor();
element = this.Find<Element>("Canvas custom layout");
Assert.IsTrue(element.Selected, $"{element.Selected} Canvas custom layout is not visible");
this.CloseFancyZonesEditor();
this.AttachPowertoySetting();
}
/*
[TestMethod]
[TestCategory("FancyZones #2")]
public void TestDragShiftHotKey()
{
this.OpenFancyZonesPanel();
this.ControlQuickLayoutSwitch(true);
int screenWidth = 1920; // default 1920
int targetX = screenWidth / 2 / 3;
int targetY = screenWidth / 2 / 2;
LaunchHostFromSetting();
this.Session.Attach(PowerToysModule.Hosts, WindowSize.Large_Vertical);
var hostsView = Find<Pane>(By.Name("Non Client Input Sink Window"));
hostsView.DoubleClick(); // maximize the window
hostsView.HoldShiftToDrag(Key.Shift, targetX, targetY);
SendKeys(Key.Num0);
hostsView.ReleaseAction();
hostsView.ReleaseKey(Key.Shift);
SendKeys(Key.Alt, Key.F4);
// Attach FancyZones Editor
this.AttachPowertoySetting();
this.Find<Pane>(By.ClassName("InputNonClientPointerSource")).Click();
this.OpenFancyZonesPanel(isMax: false);
this.AttachFancyZonesEditor();
var elements = this.FindAll<Element>("Grid custom layout");
if (elements.Count == 0)
{
this.Session.Attach(PowerToysModule.Hosts, WindowSize.Large_Vertical);
hostsView = Find<Pane>(By.Name("Non Client Input Sink Window"));
hostsView.DoubleClick(); // maximize the window
hostsView.HoldShiftToDrag(Key.Shift, targetX, targetY);
SendKeys(Key.Num0);
hostsView.ReleaseAction();
hostsView.ReleaseKey(Key.Shift);
SendKeys(Key.Alt, Key.F4);
this.AttachPowertoySetting();
this.Find<Pane>(By.ClassName("InputNonClientPointerSource")).Click();
this.OpenFancyZonesPanel(isMax: false);
this.AttachFancyZonesEditor();
elements = this.FindAll<Element>("Grid custom layout");
}
Assert.IsTrue(elements[0].Selected, "Grid custom layout is not visible");
this.CloseFancyZonesEditor();
Clean();
}
*/
[TestMethod("FancyZones.Settings.HotKeyWindowFlashTest")]
[TestCategory("FancyZones #3")]
public void HotKeyWindowFlashTest()
{
this.OpenFancyZonesPanel();
this.ControlQuickLayoutSwitch(true);
this.TryReaction();
int tries = 24;
Pull(tries, "down");
var switchGroup = this.Find<Group>("Enable quick layout switch");
switchGroup.Click();
var checkbox1 = switchGroup.Find<Element>("Flash zones when switching layout");
if (checkbox1.GetAttribute("Toggle.ToggleState") == "0")
{
checkbox1.Click();
}
this.Session.PressKey(Key.Win);
this.Session.PressKey(Key.Ctrl);
this.Session.PressKey(Key.Alt);
this.Session.PressKey(Key.Num0);
bool res = this.IsWindowOpen("FancyZones_ZonesOverlay");
Assert.IsTrue(res, $" HotKeyWindowFlash Test error: FancyZones_ZonesOverlay is not open");
this.Session.ReleaseKey(Key.Win);
this.Session.ReleaseKey(Key.Ctrl);
this.Session.ReleaseKey(Key.Alt);
this.Session.ReleaseKey(Key.Num0);
var checkbox2 = this.Find<CheckBox>("Flash zones when switching layout");
if (checkbox2.GetAttribute("Toggle.ToggleState") == "1")
{
checkbox2.Click();
}
// this.CloseFancyZonesEditor();
Clean();
}
[TestMethod("FancyZones.Settings.TestDisableApplyHotKey")]
[TestCategory("FancyZones #4")]
public void TestDisableApplyHotKey()
{
this.OpenFancyZonesPanel();
this.ControlQuickLayoutSwitch(false);
SendKeys(Key.Win, Key.Ctrl, Key.Alt, Key.Num0);
this.AttachFancyZonesEditor();
var element = this.Find<Element>("Grid custom layout");
Assert.IsFalse(element.Selected, $"{element.Selected} Grid custom layout is not visible");
this.CloseFancyZonesEditor();
this.AttachPowertoySetting();
SendKeys(Key.Win, Key.Ctrl, Key.Alt, Key.Num1);
this.AttachFancyZonesEditor();
element = this.Find<Element>("Grid-9");
Assert.IsFalse(element.Selected, $"{element.Selected} Grid-9 is not visible");
this.CloseFancyZonesEditor();
this.AttachPowertoySetting();
SendKeys(Key.Win, Key.Ctrl, Key.Alt, Key.Num2);
this.AttachFancyZonesEditor();
element = this.Find<Element>("Canvas custom layout");
Assert.IsFalse(element.Selected, $"{element.Selected} Canvas custom layout is not visible");
this.CloseFancyZonesEditor();
this.AttachPowertoySetting();
Clean();
}
[TestMethod("FancyZones.Settings.TestVirtualDesktopLayout")]
[TestCategory("FancyZones #6")]
public void TestVirtualDesktopLayout()
{
this.OpenFancyZonesPanel();
this.AttachFancyZonesEditor();
var element = this.Find<Element>("Grid custom layout");
element.Click();
this.CloseFancyZonesEditor();
this.ExitScopeExe();
// Add virtual desktop
SendKeys(Key.Ctrl, Key.Win, Key.D);
this.RestartScopeExe();
this.OpenFancyZonesPanel();
this.AttachFancyZonesEditor();
element = this.Find<Element>("Grid custom layout");
Assert.IsTrue(element.Selected, $"{element.Selected} Canvas custom layout is not visible");
this.CloseFancyZonesEditor();
// close the virtual desktop
SendKeys(Key.Ctrl, Key.Win, Key.Right);
Task.Delay(500).Wait(); // Optional: Wait for a moment to ensure window switch
SendKeys(Key.Ctrl, Key.Win, Key.F4);
Task.Delay(500).Wait(); // Optional: Wait for a moment to ensure window switch
Clean();
}
[TestMethod("FancyZones.Settings.TestVirtualDesktopLayoutExt")]
[TestCategory("FancyZones #7")]
public void TestVirtualDesktopLayoutExt()
{
this.OpenFancyZonesPanel();
this.AttachFancyZonesEditor();
var element = this.Find<Element>("Grid custom layout");
element.Click();
this.CloseFancyZonesEditor();
this.ExitScopeExe();
// Add virtual desktop
SendKeys(Key.Ctrl, Key.Win, Key.D);
this.RestartScopeExe();
this.OpenFancyZonesPanel();
this.AttachFancyZonesEditor();
element = this.Find<Element>("Grid-9");
element.Click();
this.CloseFancyZonesEditor();
this.ExitScopeExe();
SendKeys(Key.Ctrl, Key.Win, Key.Left);
this.RestartScopeExe();
this.OpenFancyZonesPanel();
this.AttachFancyZonesEditor();
element = this.Find<Element>("Grid custom layout");
Assert.IsTrue(element.Selected, $"{element.Selected} Grid custom layout is not visible");
this.CloseFancyZonesEditor();
this.ExitScopeExe();
// close the virtual desktop
SendKeys(Key.Ctrl, Key.Win, Key.Right);
Task.Delay(500).Wait(); // Optional: Wait for a moment to ensure window switch
SendKeys(Key.Ctrl, Key.Win, Key.F4);
Task.Delay(500).Wait(); // Optional: Wait for a moment to ensure window switch
Clean();
}
[TestMethod("FancyZones.Settings.TestDeleteCustomLayoutBehavior")]
[TestCategory("FancyZones #8")]
public void TestDeleteCustomLayoutBehavior()
{
this.OpenFancyZonesPanel();
this.AttachFancyZonesEditor();
this.Find<Element>("Grid custom layout").Click();
this.Find<Element>("Grid custom layout").Find<Button>(By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
Session.Find<Button>(By.AccessibilityId(AccessibilityId.DeleteLayoutButton)).Click();
Session.SendKeySequence(Key.Tab, Key.Enter);
// verify the empty layout is selected
Assert.IsTrue(Session.Find<Element>(TestConstants.TemplateLayoutNames[LayoutType.Blank])!.Selected);
Clean();
}
[TestMethod("FancyZones.Settings.TestCreateGridLayoutChangeMonitorSetting")]
[TestCategory("FancyZones #9")]
public void TestCreateGridLayoutChangeMonitorSetting()
{
this.OpenFancyZonesPanel();
this.AttachFancyZonesEditor();
string name = "Custom layout 1";
this.Session.Find<Element>(By.AccessibilityId(AccessibilityId.NewLayoutButton)).Click();
this.Session.Find<Element>(By.AccessibilityId(AccessibilityId.PrimaryButton)).Click();
this.Session.Find<Button>(ElementName.Save).Click();
// verify new layout presented
Assert.IsNotNull(Session.Find<Element>(name));
this.CloseFancyZonesEditor();
int nowHeight = UITestBase.MonitorInfoData.Monitors[UITestBase.MonitorInfoData.Monitors.Count - 1].PelsHeight;
int nowWidth = UITestBase.MonitorInfoData.Monitors[UITestBase.MonitorInfoData.Monitors.Count - 1].PelsWidth;
int height = UITestBase.MonitorInfoData.Monitors[0].PelsHeight;
int width = UITestBase.MonitorInfoData.Monitors[0].PelsWidth;
UITestBase.NativeMethods.ChangeDisplayResolution(width, height);
this.AttachPowertoySetting();
this.AttachFancyZonesEditor();
var maxButton = this.Find<Button>("Maximize");
maxButton.Click(); // maximize the window
var resolution = this.Session.Find<Element>(By.AccessibilityId("Monitors")).Find<Element>("Monitor 1").Find<Element>(By.AccessibilityId("ResolutionText"));
if (resolution.Text != "640 × 480")
{
this.CloseFancyZonesEditor();
UITestBase.NativeMethods.ChangeDisplayResolution(nowWidth, nowHeight);
Assert.AreEqual("640 × 480", resolution.Text);
}
this.CloseFancyZonesEditor();
UITestBase.NativeMethods.ChangeDisplayResolution(nowWidth, nowHeight);
Clean();
}
private void OpenFancyZonesPanel(bool launchAsAdmin = false, bool isMax = false)
{
var windowingElement = this.Find<NavigationViewItem>("Windowing & Layouts");
// Goto FancyZones Editor setting page
if (this.FindAll<NavigationViewItem>("FancyZones").Count == 0)
{
// Expand Advanced list-group if needed
windowingElement.Click();
}
windowingElement.Find<Element>("FancyZones").Click();
this.Find<ToggleSwitch>("Enable FancyZones").Toggle(true);
if (isMax == true)
{
this.Find<Button>("Maximize").Click(); // maximize the window
}
this.Find<Custom>("Editor").Find<TextBlock>(By.AccessibilityId("HeaderPresenter")).Click();
}
private void ControlQuickLayoutSwitch(bool flag)
{
this.TryReaction();
int tries = 24;
Pull(tries, "down"); // Pull the setting page up to make sure the setting is visible
this.Find<ToggleSwitch>("Enable quick layout switch").Toggle(flag);
tries = 24;
Pull(tries, "up");
}
private void TryReaction()
{
this.Find<Custom>("Editor").Find<TextBlock>(By.AccessibilityId("HeaderPresenter")).Click();
}
private void AttachPowertoySetting()
{
Task.Delay(200).Wait();
this.Session.Attach(PowerToysModule.PowerToysSettings);
}
private void AttachFancyZonesEditor()
{
Task.Delay(4000).Wait();
this.Find<Button>("Launch layout editor").Click();
Task.Delay(3000).Wait();
this.Session.Attach(PowerToysModule.FancyZone);
Task.Delay(3000).Wait();
}
private void CloseFancyZonesEditor()
{
this.Session.Find<Button>("Close").Click();
}
private void Clean()
{
// clean app zone history file
FancyZonesEditorHelper.Files.CustomLayoutsIOHelper.DeleteFile();
FancyZonesEditorHelper.Files.LayoutHotkeysIOHelper.DeleteFile();
FancyZonesEditorHelper.Files.LayoutTemplatesIOHelper.DeleteFile();
}
private void Pull(int tries = 5, string direction = "up")
{
Key keyToSend = direction == "up" ? Key.Up : Key.Down;
for (int i = 0; i < tries; i++)
{
SendKeys(keyToSend);
}
}
private void LaunchHostFromSetting(bool showWarning = false, bool launchAsAdmin = false)
{
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Hosts File Editor").Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Advanced").Click();
}
this.Find<NavigationViewItem>("Hosts File Editor").Click();
Task.Delay(1000).Wait();
this.Find<ToggleSwitch>("Enable Hosts File Editor").Toggle(true);
this.Find<ToggleSwitch>("Launch as administrator").Toggle(launchAsAdmin);
this.Find<ToggleSwitch>("Show a warning at startup").Toggle(showWarning);
// launch Hosts File Editor
this.Find<Button>("Launch Hosts File Editor").Click();
Task.Delay(5000).Wait();
}
}
}

View File

@@ -0,0 +1,313 @@
// 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.Threading.Tasks;
using FancyZonesEditor.Models;
using FancyZonesEditorCommon.Data;
using Microsoft.FancyZones.UITests.Utils;
using Microsoft.FancyZonesEditor.UITests.Utils;
using Microsoft.FancyZonesEditor.UnitTests.Utils;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UITests_FancyZones
{
[TestClass]
public class OneZoneSwitchTests : UITestBase
{
private static readonly int SubZones = 2;
private static readonly IOTestHelper AppZoneHistory = new FancyZonesEditorFiles().AppZoneHistoryIOHelper;
private static string powertoysWindowName = "PowerToys Settings"; // set powertoys settings window name
public OneZoneSwitchTests()
: base(PowerToysModule.PowerToysSettings, WindowSize.Medium)
{
}
[TestInitialize]
public void TestInitialize()
{
// kill all processes related to FancyZones Editor to ensure a clean state
Session.KillAllProcessesByName("PowerToys.FancyZonesEditor");
AppZoneHistory.DeleteFile();
this.RestartScopeExe();
FancyZonesEditorHelper.Files.Restore();
// Set a custom layout with 1 subzones and clear app zone history
SetupCustomLayouts();
// get PowerToys window Name
powertoysWindowName = ZoneSwitchHelper.GetActiveWindowTitle();
// Launch FancyZones
LaunchFancyZones();
// Launch the Hosts File Editor
LaunchFromSetting();
}
/// <summary>
/// Test switching between two snapped windows using keyboard shortcuts in FancyZones
/// <list type="bullet">
/// <item>
/// <description>Verifies that after snapping two windows, the active window switches correctly using Win+PageDown.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod]
[TestCategory("FancyZones #Switch between windows in the current zone #1")]
public void TestSwitchWindow()
{
var (preWindow, postWindow) = SnapToOneZone();
string? activeWindowTitle = ZoneSwitchHelper.GetActiveWindowTitle();
Assert.AreEqual(postWindow, activeWindowTitle);
// switch to the previous window by shortcut win+page down
SendKeys(Key.Win, Key.PageDown);
activeWindowTitle = ZoneSwitchHelper.GetActiveWindowTitle();
Assert.AreEqual(preWindow, activeWindowTitle);
Clean(); // close the windows
}
/// <summary>
/// Test window switch behavior across virtual desktops in FancyZones
/// <list type="bullet">
/// <item>
/// <description>Verifies that a window remains correctly snapped after switching desktops and can be switched using Win+PageDown.</description>
/// </item>
/// </summary>
[TestMethod("FancyZones.Settings.TestSwitchAfterDesktopChange")]
[TestCategory("FancyZones #Switch between windows in the current zone #2")]
public void TestSwitchAfterDesktopChange()
{
var (preWindow, postWindow) = SnapToOneZone();
string? windowTitle = ZoneSwitchHelper.GetActiveWindowTitle();
Assert.AreEqual(postWindow, windowTitle);
// Add virtual desktop
SendKeys(Key.Ctrl, Key.Win, Key.D);
// return back
SendKeys(Key.Ctrl, Key.Win, Key.Left);
Task.Delay(500).Wait(); // Optional: Wait for a moment to ensure window switch
string? returnWindowTitle = ZoneSwitchHelper.GetActiveWindowTitle();
Assert.AreEqual(postWindow, returnWindowTitle);
// check shortcut
SendKeys(Key.Win, Key.PageDown);
string? activeWindowTitle = ZoneSwitchHelper.GetActiveWindowTitle();
Assert.AreEqual(preWindow, activeWindowTitle);
// close the virtual desktop
SendKeys(Key.Ctrl, Key.Win, Key.Right);
Task.Delay(500).Wait(); // Optional: Wait for a moment to ensure window switch
SendKeys(Key.Ctrl, Key.Win, Key.F4);
Task.Delay(500).Wait(); // Optional: Wait for a moment to ensure window switch
Clean(); // close the windows
}
/// <summary>
/// Test window switching shortcut behavior when the shortcut is disabled in FancyZones settings
/// <list type="bullet">
/// <item>
/// <description>Verifies that pressing Win+PageDown does not switch to the previously snapped window when the shortcut is disabled.</description>
/// </item>
/// </list>
/// </summary>
[TestMethod("FancyZones.Settings.TestSwitchShortCutDisable")]
[TestCategory("FancyZones #Switch between windows in the current zone #3")]
public void TestSwitchShortCutDisable()
{
var (preWindow, postWindow) = SnapToOneZone();
string? activeWindowTitle = ZoneSwitchHelper.GetActiveWindowTitle();
Assert.AreEqual(postWindow, activeWindowTitle);
// switch to the previous window by shortcut win+page down
SendKeys(Key.Win, Key.PageDown);
Task.Delay(500).Wait(); // Optional: Wait for a moment to ensure window switch
activeWindowTitle = ZoneSwitchHelper.GetActiveWindowTitle();
Assert.AreNotEqual(preWindow, activeWindowTitle);
Clean(); // close the windows
}
private (string PreWindow, string PostWindow) SnapToOneZone()
{
this.Session.Attach(PowerToysModule.Hosts, WindowSize.Large_Vertical);
var hostsView = Find<Pane>(By.Name("Non Client Input Sink Window"));
hostsView.DoubleClick(); // maximize the window
var rect = Session.GetMainWindowRect();
var (targetX, targetY) = ZoneSwitchHelper.GetScreenMargins(rect, 4);
var offSet = ZoneSwitchHelper.GetOffset(hostsView, targetX, targetY);
DragWithShift(hostsView, offSet);
string preWindow = ZoneSwitchHelper.GetActiveWindowTitle();
// Attach the PowerToys settings window to the front
Session.Attach(powertoysWindowName, WindowSize.UnSpecified);
string windowNameFront = ZoneSwitchHelper.GetActiveWindowTitle();
Pane settingsView = Find<Pane>(By.Name("Non Client Input Sink Window"));
settingsView.DoubleClick(); // maximize the window
DragWithShift(settingsView, offSet);
string appZoneHistoryJson = AppZoneHistory.GetData();
string? zoneIndexOfFileWindow = ZoneSwitchHelper.GetZoneIndexSetByAppName("PowerToys.Hosts.exe", appZoneHistoryJson); // explorer.exe
string? zoneIndexOfPowertoys = ZoneSwitchHelper.GetZoneIndexSetByAppName("PowerToys.Settings.exe", appZoneHistoryJson);
// check the AppZoneHistory layout is set and in the same zone
Assert.AreEqual(zoneIndexOfPowertoys, zoneIndexOfFileWindow);
return (preWindow, powertoysWindowName);
}
private void DragWithShift(Pane settingsView, (int Dx, int Dy) offSet)
{
Session.PressKey(Key.Shift);
settingsView.DragAndHold(offSet.Dx, offSet.Dy);
Task.Delay(1000).Wait(); // Wait for drag to start (optional)
settingsView.ReleaseDrag();
Task.Delay(1000).Wait(); // Wait after drag (optional)
Session.ReleaseKey(Key.Shift);
}
private static readonly CustomLayouts.CustomLayoutListWrapper CustomLayoutsList = new CustomLayouts.CustomLayoutListWrapper
{
CustomLayouts = new List<CustomLayouts.CustomLayoutWrapper>
{
new CustomLayouts.CustomLayoutWrapper
{
Uuid = "{63F09977-D327-4DAC-98F4-0C886CAE9517}",
Type = CustomLayout.Grid.TypeToString(),
Name = "Custom Column",
Info = new CustomLayouts().ToJsonElement(new CustomLayouts.GridInfoWrapper
{
Rows = 1,
Columns = SubZones,
RowsPercentage = new List<int> { 10000 },
ColumnsPercentage = new List<int> { 5000, 5000 },
CellChildMap = new int[][] { [0, 1] },
SensitivityRadius = 20,
ShowSpacing = true,
Spacing = 10,
}),
},
},
};
// clean window
private void Clean()
{
// Close First window
SendKeys(Key.Alt, Key.F4);
// Close Second window
SendKeys(Key.Alt, Key.F4);
// clean app zone history file
AppZoneHistory.DeleteFile();
}
// Setup custom layout with 1 subzones
private void SetupCustomLayouts()
{
var customLayouts = new CustomLayouts();
var customLayoutListWrapper = CustomLayoutsList;
FancyZonesEditorHelper.Files.CustomLayoutsIOHelper.WriteData(customLayouts.Serialize(customLayoutListWrapper));
}
// launch FancyZones settings page
private void LaunchFancyZones()
{
// Goto FancyZones setting page
if (this.FindAll<NavigationViewItem>("FancyZones").Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Windowing & Layouts").Click();
}
this.Find<NavigationViewItem>("FancyZones").Click();
this.Find<ToggleSwitch>("Enable FancyZones").Toggle(true);
this.Session.SetMainWindowSize(WindowSize.Large);
// fixed settings
this.Find<CheckBox>("Hold Shift key to activate zones while dragging a window").SetCheck(true, 500);
// should bind mouse to suitable zone for scrolling
Find<Element>(By.AccessibilityId("HeaderPresenter")).Click();
this.Scroll(9, "Down"); // Pull the setting page up to make sure the setting is visible
bool switchWindowEnable = TestContext.TestName == "TestSwitchShortCutDisable" ? false : true;
this.Find<ToggleSwitch>("Switch between windows in the current zone").Toggle(switchWindowEnable);
Task.Delay(500).Wait(); // Wait for the setting to be applied
this.Scroll(9, "Up"); // Pull the setting page down to make sure the setting is visible
this.Find<Button>("Launch layout editor").Click(false, 500, 5000);
this.Session.Attach(PowerToysModule.FancyZone);
// pipeline machine may have an unstable delays, causing the custom layout to be unavailable as we set. then A retry is required.
// Console.WriteLine($"after launch, Custom layout data: {customLayoutData}");
try
{
// Set the FancyZones layout to a custom layout
this.Find<Element>(By.Name("Custom Column")).Click();
}
catch (Exception)
{
// Console.WriteLine($"[Exception] Failed to attach to FancyZones window. Retrying...{ex.Message}");
this.Find<Microsoft.PowerToys.UITest.Button>("Close").Click();
this.Session.Attach(PowerToysModule.PowerToysSettings);
SetupCustomLayouts();
this.Find<Microsoft.PowerToys.UITest.Button>("Launch layout editor").Click(false, 5000, 5000);
this.Session.Attach(PowerToysModule.FancyZone);
// customLayoutData = FancyZonesEditorHelper.Files.CustomLayoutsIOHelper.GetData();
// Console.WriteLine($"after retry, Custom layout data: {customLayoutData}");
// Set the FancyZones layout to a custom layout
this.Find<Element>(By.Name("Custom Column")).Click();
}
// Close layout editor window
SendKeys(Key.Alt, Key.F4);
this.Session.Attach(powertoysWindowName);
}
private void LaunchFromSetting(bool showWarning = false, bool launchAsAdmin = false)
{
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Hosts File Editor").Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Advanced").Click();
}
this.Find<NavigationViewItem>("Hosts File Editor").Click();
Task.Delay(1000).Wait();
this.Find<ToggleSwitch>("Enable Hosts File Editor").Toggle(true);
this.Find<ToggleSwitch>("Launch as administrator").Toggle(launchAsAdmin);
this.Find<ToggleSwitch>("Show a warning at startup").Toggle(showWarning);
// launch Hosts File Editor
this.Find<Button>("Launch Hosts File Editor").Click();
Task.Delay(5000).Wait();
}
}
}

View File

@@ -27,5 +27,15 @@
<ItemGroup>
<Folder Include="Properties\" />
<ProjectReference Include="..\editor\FancyZonesEditor\FancyZonesEditor.csproj" />
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
<ProjectReference Include="..\UITests-FancyZonesEditor\UITests-FancyZonesEditor.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\editor\FancyZonesEditor\FancyZonesEditor.csproj" />
<ProjectReference Include="..\UITests-FancyZonesEditor\UITests-FancyZonesEditor.csproj" />
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,98 @@
// 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.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Internal;
namespace Microsoft.FancyZones.UITests.Utils
{
public class ZoneSwitchHelper
{
public static string? GetZoneIndexSetByAppName(string exeName, string json)
{
if (string.IsNullOrEmpty(exeName) || string.IsNullOrEmpty(json))
{
return null;
}
try
{
using var doc = JsonDocument.Parse(json);
var historyArray = doc.RootElement.GetProperty("app-zone-history");
foreach (var item in historyArray.EnumerateArray())
{
if (item.TryGetProperty("app-path", out var appPathElement) &&
appPathElement.GetString() is string path &&
path.EndsWith(exeName, StringComparison.OrdinalIgnoreCase))
{
var history = item.GetProperty("history");
if (history.GetArrayLength() > 0)
{
return history[0].GetProperty("zone-index-set")[0].GetRawText();
}
}
}
}
catch (JsonException ex)
{
throw new InvalidOperationException("JSON parse error: " + ex.Message, ex);
}
return null;
}
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
public static string GetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, buff, nChars) > 0)
{
return buff.ToString();
}
else
{
// Handle the error if needed
throw new InvalidOperationException("Failed to get window title.");
}
}
public static (int Dx, int Dy) GetOffset(Element element, int targetX, int targetY)
{
Assert.IsNotNull(element.Rect, "element is null");
var rect = element.Rect.Value;
return (targetX - rect.X, targetY - rect.Y);
}
public static (int X, int Y) GetScreenMargins((int Left, int Top, int Right, int Bottom) rect, int quantile = 4)
{
if (quantile == 0)
{
throw new ArgumentException("Quantile cannot be zero.", nameof(quantile));
}
int x = (rect.Left + rect.Right) / quantile;
int y = (rect.Top + rect.Bottom) / quantile;
return (x, y);
}
}
}

View File

@@ -19,7 +19,7 @@ namespace Microsoft.FancyZonesEditor.UITests
public class ApplyLayoutTests : UITestBase
{
public ApplyLayoutTests()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
@@ -135,6 +135,7 @@ namespace Microsoft.FancyZonesEditor.UITests
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
FancyZonesEditorHelper.Files.ParamsIOHelper.WriteData(editorParameters.Serialize(Parameters));
@@ -195,12 +196,6 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
public void ApplyCustomLayout()
{
@@ -234,7 +229,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(Parameters.Monitors[0].MonitorNumber, data.AppliedLayouts[0].Device.MonitorNumber);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.ApplyLayoutsOnEachMonitor")]
[TestCategory("FancyZones Editor #10")]
public void ApplyLayoutsOnEachMonitor()
{
// apply the layout on the first monitor
@@ -261,7 +257,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(secondLayout.Uuid, data.AppliedLayouts.Find(x => x.Device.MonitorNumber == 2).AppliedLayout.Uuid);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.ApplyTemplateWithDifferentParametersOnEachMonitor")]
[TestCategory("FancyZones Editor #10")]
public void ApplyTemplateWithDifferentParametersOnEachMonitor()
{
var layoutType = LayoutType.Columns;
@@ -270,10 +267,10 @@ namespace Microsoft.FancyZonesEditor.UITests
// apply the layout on the first monitor, set parameters
Session.Find<Element>(layoutName).Click();
Session.Find<Element>(layoutName).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.TemplateZoneSlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.TemplateZoneSlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
slider.SendKeys(Keys.Right);
slider.SendKeys(Key.Right);
slider.SendKeys(Key.Right);
var expectedFirstLayoutZoneCount = int.Parse(slider.Text!, CultureInfo.InvariantCulture);
Session.Find<Button>(ElementName.Save).Click();
@@ -281,16 +278,16 @@ namespace Microsoft.FancyZonesEditor.UITests
Session.Find<Element>(PowerToys.UITest.By.AccessibilityId("Monitors")).Find<Element>("Monitor 2").Click();
Session.Find<Element>(layoutName).Click();
Session.Find<Element>(layoutName).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.TemplateZoneSlider));
slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.TemplateZoneSlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Left);
slider.SendKeys(Key.Left);
var expectedSecondLayoutZoneCount = int.Parse(slider.Text!, CultureInfo.InvariantCulture);
Session.Find<Button>(ElementName.Save).Click();
// verify the layout on the first monitor wasn't changed
Session.Find<Element>(PowerToys.UITest.By.AccessibilityId("Monitors")).Find<Element>("Monitor 1").Click();
Session.Find<Element>(layoutName).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.TemplateZoneSlider));
slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.TemplateZoneSlider));
Assert.IsNotNull(slider);
Assert.AreEqual(expectedFirstLayoutZoneCount, int.Parse(slider.Text!, CultureInfo.InvariantCulture));
Session.Find<Button>(ElementName.Cancel).Click();

View File

@@ -17,7 +17,7 @@ namespace Microsoft.FancyZonesEditor.UITests
public class CopyLayoutTests : UITestBase
{
public CopyLayoutTests()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
@@ -76,6 +76,7 @@ namespace Microsoft.FancyZonesEditor.UITests
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
ParamsWrapper parameters = new ParamsWrapper
{
@@ -172,13 +173,8 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CopyTemplate_FromEditLayoutWindow")]
[TestCategory("FancyZones Editor #4")]
public void CopyTemplate_FromEditLayoutWindow()
{
string copiedLayoutName = TestConstants.TemplateLayoutNames[LayoutType.Focus] + " (1)";
@@ -195,7 +191,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Name == copiedLayoutName));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CopyTemplate_FromEditLayoutWindow")]
[TestCategory("FancyZones Editor #4")]
public void CopyTemplate_FromContextMenu()
{
string copiedLayoutName = TestConstants.TemplateLayoutNames[LayoutType.Rows] + " (1)";
@@ -211,7 +208,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Name == copiedLayoutName));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CopyTemplate_DefaultLayout")]
[TestCategory("FancyZones Editor #13")]
public void CopyTemplate_DefaultLayout()
{
string copiedLayoutName = TestConstants.TemplateLayoutNames[LayoutType.PriorityGrid] + " (1)";
@@ -243,7 +241,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(defaultLayouts.Serialize(DefaultLayouts), defaultLayouts.Serialize(defaultLayoutData));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CopyCustomLayout_FromEditLayoutWindow")]
[TestCategory("FancyZones Editor #4")]
public void CopyCustomLayout_FromEditLayoutWindow()
{
string copiedLayoutName = CustomLayouts.CustomLayouts[0].Name + " (1)";
@@ -260,7 +259,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Name == copiedLayoutName));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CopyCustomLayout_FromContextMenu")]
[TestCategory("FancyZones Editor #4")]
public void CopyCustomLayout_FromContextMenu()
{
string copiedLayoutName = CustomLayouts.CustomLayouts[0].Name + " (1)";
@@ -276,7 +276,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Name == copiedLayoutName));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CopyCustomLayout_DefaultLayout")]
[TestCategory("FancyZones Editor #13")]
public void CopyCustomLayout_DefaultLayout()
{
string copiedLayoutName = CustomLayouts.CustomLayouts[0].Name + " (1)";
@@ -308,7 +309,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(defaultLayouts.Serialize(DefaultLayouts), defaultLayouts.Serialize(defaultLayoutData));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CopyCustomLayout_Hotkey")]
[TestCategory("FancyZones Editor #4")]
public void CopyCustomLayout_Hotkey()
{
string copiedLayoutName = CustomLayouts.CustomLayouts[0].Name + " (1)";

View File

@@ -16,13 +16,15 @@ namespace Microsoft.FancyZonesEditor.UITests
public class CreateLayoutTests : UITestBase
{
public CreateLayoutTests()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
// prepare test editor parameters with 2 monitors before launching the editor
EditorParameters editorParameters = new EditorParameters();
EditorParameters.ParamsWrapper parameters = new EditorParameters.ParamsWrapper
@@ -132,12 +134,6 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
public void CreateWithDefaultName()
{
@@ -156,7 +152,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Name == name));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CreateWithCustomName")]
[TestCategory("FancyZones Editor #3")]
public void CreateWithCustomName()
{
string name = "Layout Name";
@@ -177,7 +174,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Name == name));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CreateGrid")]
[TestCategory("FancyZones Editor #3")]
public void CreateGrid()
{
CustomLayout type = CustomLayout.Grid;
@@ -193,7 +191,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Type == type.TypeToString()));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CreateCanvas")]
[TestCategory("FancyZones Editor #3")]
public void CreateCanvas()
{
CustomLayout type = CustomLayout.Canvas;
@@ -209,7 +208,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Type == type.TypeToString()));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CancelGridCreation")]
[TestCategory("FancyZones Editor #3")]
public void CancelGridCreation()
{
Session.Find<Element>(By.AccessibilityId(AccessibilityId.NewLayoutButton)).Click();
@@ -223,7 +223,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(0, data.CustomLayouts.Count);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CancelCanvasCreation")]
[TestCategory("FancyZones Editor #3")]
public void CancelCanvasCreation()
{
Session.Find<Element>(By.AccessibilityId(AccessibilityId.NewLayoutButton)).Click();

View File

@@ -20,7 +20,7 @@ namespace Microsoft.FancyZonesEditor.UITests
public class CustomLayoutsTests : UITestBase
{
public CustomLayoutsTests()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
@@ -104,6 +104,7 @@ namespace Microsoft.FancyZonesEditor.UITests
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
CustomLayouts customLayouts = new CustomLayouts();
FancyZonesEditorHelper.Files.CustomLayoutsIOHelper.WriteData(customLayouts.Serialize(Layouts));
@@ -208,12 +209,6 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
public void Name_Initialize()
{
@@ -292,14 +287,14 @@ namespace Microsoft.FancyZonesEditor.UITests
var type = layout.Type;
Session.Find<Element>(layout.Name).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SensitivitySlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SensitivitySlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
slider.SendKeys(Key.Right);
var value = type == CustomLayout.Canvas.TypeToString() ?
new CustomLayouts().CanvasFromJsonElement(layout.Info.GetRawText()).SensitivityRadius :
new CustomLayouts().GridFromJsonElement(layout.Info.GetRawText()).SensitivityRadius;
var expected = value + 1; // one step right
var expected = value; // if have one step right please + 1
Assert.AreEqual($"{expected}", slider.Text);
@@ -321,9 +316,9 @@ namespace Microsoft.FancyZonesEditor.UITests
var type = layout.Type;
Session.Find<Element>(layout.Name).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SensitivitySlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SensitivitySlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
slider.SendKeys(Key.Right);
var expected = type == CustomLayout.Canvas.TypeToString() ?
new CustomLayouts().CanvasFromJsonElement(layout.Info.GetRawText()).SensitivityRadius :
@@ -373,15 +368,15 @@ namespace Microsoft.FancyZonesEditor.UITests
public void SpaceAroundZones_Slider_Save()
{
var layout = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Grid.TypeToString() && new CustomLayouts().GridFromJsonElement(x.Info.GetRawText()).ShowSpacing);
var expected = new CustomLayouts().GridFromJsonElement(layout.Info.GetRawText()).Spacing + 1; // one step right
var expected = new CustomLayouts().GridFromJsonElement(layout.Info.GetRawText()).Spacing; // one step right
Session.Find<Element>(layout.Name).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SpacingSlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SpacingSlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
slider.SendKeys(Key.Right);
Assert.AreEqual($"{expected}", slider.Text);
Session.Find<Button>(ElementName.Save).Click();
Session.Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.PrimaryButton)).Click();
// verify the file
var customLayouts = new CustomLayouts();
@@ -397,9 +392,9 @@ namespace Microsoft.FancyZonesEditor.UITests
Session.Find<Element>(layout.Name).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
var expected = new CustomLayouts().GridFromJsonElement(layout.Info.GetRawText()).Spacing;
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SpacingSlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SpacingSlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
slider.SendKeys(Key.Right);
Session.Find<Button>(ElementName.Cancel).Click();
// verify the file

View File

@@ -20,7 +20,7 @@ namespace Microsoft.FancyZonesEditor.UITests
public class DefaultLayoutsTest : UITestBase
{
public DefaultLayoutsTest()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
@@ -121,6 +121,7 @@ namespace Microsoft.FancyZonesEditor.UITests
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
var defaultLayouts = new DefaultLayouts();
FancyZonesEditorHelper.Files.DefaultLayoutsIOHelper.WriteData(defaultLayouts.Serialize(Layouts));
@@ -237,20 +238,16 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Default_Initialize")]
[TestCategory("FancyZones Editor #12")]
public void Initialize()
{
CheckTemplateLayouts(LayoutType.Grid, null);
CheckCustomLayouts(string.Empty, CustomLayouts.CustomLayouts[0].Uuid);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Default_Assign_Cancel")]
[TestCategory("FancyZones Editor #12")]
public void Assign_Cancel()
{
// assign Focus as a default horizontal and vertical layout
@@ -266,7 +263,8 @@ namespace Microsoft.FancyZonesEditor.UITests
CheckCustomLayouts(string.Empty, CustomLayouts.CustomLayouts[0].Uuid);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Default_Assign_Save")]
[TestCategory("FancyZones Editor #12")]
public void Assign_Save()
{
// assign Focus as a default horizontal and vertical layout

View File

@@ -22,7 +22,7 @@ namespace Microsoft.FancyZonesEditor.UITests
public class DeleteLayoutTests : UITestBase
{
public DeleteLayoutTests()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
@@ -142,6 +142,7 @@ namespace Microsoft.FancyZonesEditor.UITests
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
FancyZonesEditorHelper.Files.ParamsIOHelper.WriteData(editorParameters.Serialize(Parameters));
@@ -215,19 +216,14 @@ namespace Microsoft.FancyZonesEditor.UITests
Session.Find<Element>(CustomLayouts.CustomLayouts[0].Name).Click();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.DeleteNotAppliedLayout")]
[TestCategory("FancyZones Editor #5")]
public void DeleteNotAppliedLayout()
{
var deletedLayout = CustomLayouts.CustomLayouts[1].Name;
Session.Find<Element>(deletedLayout).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
Session.Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.DeleteLayoutButton)).Click();
Session.KeyboardAction(Keys.Tab, Keys.Enter);
Session.SendKeySequence(Key.Tab, Key.Enter);
// verify the layout is removed
Assert.IsTrue(Session.FindAll<Element>(deletedLayout).Count == 0);
@@ -239,13 +235,15 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsFalse(data.CustomLayouts.Exists(x => x.Name == deletedLayout));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.DeleteAppliedLayout")]
[TestCategory("FancyZones Editor #5")]
public void DeleteAppliedLayout()
{
var deletedLayout = CustomLayouts.CustomLayouts[0].Name;
Session.Find<Element>(deletedLayout).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
Session.Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.DeleteLayoutButton)).Click();
Session.KeyboardAction(Keys.Tab, Keys.Enter);
Session.SendKeySequence(Key.Tab, Key.Enter);
// verify the layout is removed
Assert.IsTrue(Session.FindAll<Element>(deletedLayout).Count == 0);
@@ -264,13 +262,14 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(LayoutType.Blank.TypeToString(), appliedLayoutsData.AppliedLayouts.Find(x => x.Device.Monitor == Parameters.Monitors[0].Monitor).AppliedLayout.Type);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.CancelDeletion")]
[TestCategory("FancyZones Editor #5")]
public void CancelDeletion()
{
var deletedLayout = CustomLayouts.CustomLayouts[1].Name;
Session.Find<Element>(deletedLayout).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
Session.Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.DeleteLayoutButton)).Click();
Session.KeyboardAction(Keys.Tab, Keys.Tab, Keys.Enter);
Session.SendKeySequence(Key.Tab, Key.Tab, Key.Enter);
// verify the layout is not removed
Assert.IsNotNull(Session.Find<Element>(deletedLayout));
@@ -282,12 +281,13 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(data.CustomLayouts.Exists(x => x.Name == deletedLayout));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.DeleteFromContextMenu")]
[TestCategory("FancyZones Editor #5")]
public void DeleteFromContextMenu()
{
var deletedLayout = CustomLayouts.CustomLayouts[1].Name;
FancyZonesEditorHelper.ClickContextMenuItem(Session, deletedLayout, FancyZonesEditorHelper.ElementName.Delete);
Session.KeyboardAction(Keys.Tab, Keys.Enter);
Session.SendKeySequence(Key.Tab, Key.Enter);
// verify the layout is removed
Assert.IsTrue(Session.FindAll<Element>(deletedLayout).Count == 0);
@@ -299,12 +299,13 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsFalse(data.CustomLayouts.Exists(x => x.Name == deletedLayout));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.DeleteDefaultLayout")]
[TestCategory("FancyZones Editor #5")]
public void DeleteDefaultLayout()
{
var deletedLayout = CustomLayouts.CustomLayouts[1].Name;
FancyZonesEditorHelper.ClickContextMenuItem(Session, deletedLayout, FancyZonesEditorHelper.ElementName.Delete);
Session.KeyboardAction(Keys.Tab, Keys.Enter);
Session.SendKeySequence(Key.Tab, Key.Enter);
// verify the default layout is reset to the "default" default
Session.Find<Element>(TestConstants.TemplateLayoutNames[LayoutType.PriorityGrid]).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
@@ -318,12 +319,13 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(LayoutType.PriorityGrid.TypeToString(), data.DefaultLayouts.Find(x => x.MonitorConfiguration == configuration).Layout.Type);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.DeleteLayoutWithHotkey")]
[TestCategory("FancyZones Editor #5")]
public void DeleteLayoutWithHotkey()
{
var deletedLayout = CustomLayouts.CustomLayouts[1].Name;
FancyZonesEditorHelper.ClickContextMenuItem(Session, deletedLayout, FancyZonesEditorHelper.ElementName.Delete);
Session.KeyboardAction(Keys.Tab, Keys.Enter);
Session.SendKeySequence(Key.Tab, Key.Enter);
// verify the hotkey is available
Session.Find<Element>(CustomLayouts.CustomLayouts[0].Name).Find<Button>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();

View File

@@ -21,7 +21,7 @@ namespace Microsoft.FancyZonesEditor.UITests
public class EditLayoutTests : UITestBase
{
public EditLayoutTests()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
@@ -105,6 +105,7 @@ namespace Microsoft.FancyZonesEditor.UITests
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
ParamsWrapper parameters = new ParamsWrapper
{
@@ -209,13 +210,8 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.OpenEditMode")]
[TestCategory("FancyZones Editor #7")]
public void OpenEditMode()
{
Session.Find<Element>(Layouts.CustomLayouts[0].Name).Find<Button>(By.AccessibilityId(AccessibilityId.EditLayoutButton)).Click();
@@ -224,7 +220,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Session.Find<Button>(ElementName.Cancel).Click();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.OpenEditModeFromContextMenu")]
[TestCategory("FancyZones Editor #7")]
public void OpenEditModeFromContextMenu()
{
FancyZonesEditorHelper.ClickContextMenuItem(Session, Layouts.CustomLayouts[0].Name, FancyZonesEditorHelper.ElementName.EditZones);
@@ -232,7 +229,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Session.Find<Button>(ElementName.Cancel).Click();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Canvas_AddZone_Save")]
[TestCategory("FancyZones Editor #7")]
public void Canvas_AddZone_Save()
{
var canvas = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Canvas.TypeToString());
@@ -248,7 +246,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected.Zones.Count + 1, actual.Zones.Count);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Canvas_AddZone_Cancel")]
[TestCategory("FancyZones Editor #7")]
public void Canvas_AddZone_Cancel()
{
var canvas = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Canvas.TypeToString());
@@ -264,7 +263,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected.Zones.Count, actual.Zones.Count);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Canvas_DeleteZone_Save")]
[TestCategory("FancyZones Editor #7")]
public void Canvas_DeleteZone_Save()
{
var canvas = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Canvas.TypeToString());
@@ -280,7 +280,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected.Zones.Count - 1, actual.Zones.Count);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Canvas_DeleteZone_Cancel")]
[TestCategory("FancyZones Editor #7")]
public void Canvas_DeleteZone_Cancel()
{
var canvas = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Canvas.TypeToString());
@@ -296,7 +297,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected.Zones.Count, actual.Zones.Count);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Canvas_MoveZone_Save")]
[TestCategory("FancyZones Editor #7")]
public void Canvas_MoveZone_Save()
{
int zoneNumber = 1;
@@ -333,7 +335,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Canvas_MoveZone_Cancel")]
[TestCategory("FancyZones Editor #7")]
public void Canvas_MoveZone_Cancel()
{
int zoneNumber = 1;
@@ -357,7 +360,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Canvas_ResizeZone_Save")]
[TestCategory("FancyZones Editor #7")]
public void Canvas_ResizeZone_Save()
{
int zoneNumber = 1;
@@ -366,7 +370,7 @@ namespace Microsoft.FancyZonesEditor.UITests
var canvas = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Canvas.TypeToString());
FancyZonesEditorHelper.ClickContextMenuItem(Session, canvas.Name, FancyZonesEditorHelper.ElementName.EditZones);
FancyZonesEditorHelper.GetZone(Session, zoneNumber, FancyZonesEditorHelper.ClassName.CanvasZone)?.Find<Element>(By.AccessibilityId(FancyZonesEditorHelper.AccessibilityId.TopRightCorner)).Drag(xOffset, yOffset);
FancyZonesEditorHelper.GetZone(Session, zoneNumber, FancyZonesEditorHelper.ClassName.CanvasZone)?.Find<Thumb>(By.AccessibilityId(FancyZonesEditorHelper.AccessibilityId.TopRightCorner)).Drag(xOffset, yOffset);
Session.Find<Button>(ElementName.Save).Click();
// check the file
@@ -394,7 +398,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Canvas_ResizeZone_Cancel")]
[TestCategory("FancyZones Editor #7")]
public void Canvas_ResizeZone_Cancel()
{
int zoneNumber = 1;
@@ -403,7 +408,7 @@ namespace Microsoft.FancyZonesEditor.UITests
var canvas = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Canvas.TypeToString());
FancyZonesEditorHelper.ClickContextMenuItem(Session, canvas.Name, FancyZonesEditorHelper.ElementName.EditZones);
FancyZonesEditorHelper.GetZone(Session, zoneNumber, FancyZonesEditorHelper.ClassName.CanvasZone)?.Find<Element>(By.AccessibilityId(FancyZonesEditorHelper.AccessibilityId.TopRightCorner)).Drag(xOffset, yOffset);
FancyZonesEditorHelper.GetZone(Session, zoneNumber, FancyZonesEditorHelper.ClassName.CanvasZone)?.Find<Thumb>(By.AccessibilityId(FancyZonesEditorHelper.AccessibilityId.TopRightCorner)).Drag(xOffset, yOffset);
Session.Find<Button>(ElementName.Cancel).Click();
// check the file
@@ -421,7 +426,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Grid_SplitZone_Save")]
[TestCategory("FancyZones Editor #8")]
public void Grid_SplitZone_Save()
{
int zoneNumber = 1;
@@ -450,7 +456,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Grid_SplitZone_Cancel")]
[TestCategory("FancyZones Editor #8")]
public void Grid_SplitZone_Cancel()
{
int zoneNumber = 1;
@@ -481,7 +488,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Grid_MergeZones_Save")]
[TestCategory("FancyZones Editor #8")]
public void Grid_MergeZones_Save()
{
var grid = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Grid.TypeToString());
@@ -515,7 +523,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.IsTrue(actual.CellChildMap[1].SequenceEqual([1, 2]));
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Grid_MergeZones_Cancel")]
[TestCategory("FancyZones Editor #8")]
public void Grid_MergeZones_Cancel()
{
var grid = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Grid.TypeToString());
@@ -551,7 +560,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Grid_MoveSplitter_Save")]
[TestCategory("FancyZones Editor #8")]
public void Grid_MoveSplitter_Save()
{
EditorParameters editorParameters = new EditorParameters();
@@ -614,7 +624,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.Grid_MoveSplitter_Cancel")]
[TestCategory("FancyZones Editor #8")]
public void Grid_MoveSplitter_Cancel()
{
var grid = Layouts.CustomLayouts.Find(x => x.Type == CustomLayout.Grid.TypeToString() && x.Name == "Grid-9");

View File

@@ -25,13 +25,14 @@ namespace Microsoft.FancyZonesEditor.UITests
public class FirstLunchTest : UITestBase
{
public FirstLunchTest()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
ParamsWrapper parameters = new ParamsWrapper
{
@@ -141,12 +142,6 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
public void FirstLaunch()
{

View File

@@ -23,7 +23,7 @@ namespace Microsoft.FancyZonesEditor.UITests
public class LayoutHotkeysTests : UITestBase
{
public LayoutHotkeysTests()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
@@ -106,6 +106,7 @@ namespace Microsoft.FancyZonesEditor.UITests
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
ParamsWrapper parameters = new ParamsWrapper
{
@@ -206,13 +207,8 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HotKey_Initialize")]
[TestCategory("FancyZones Editor #11")]
public void Initialize()
{
foreach (var layout in CustomLayouts.CustomLayouts)
@@ -256,7 +252,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HotKey_Assign_Save")]
[TestCategory("FancyZones Editor #11")]
public void Assign_Save()
{
var layout = CustomLayouts.CustomLayouts[2]; // a layout without assigned hotkey
@@ -299,7 +296,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HotKey_Assign_Cancel")]
[TestCategory("FancyZones Editor #11")]
public void Assign_Cancel()
{
var layout = CustomLayouts.CustomLayouts[2]; // a layout without assigned hotkey
@@ -338,7 +336,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HotKey_Assign_AllPossibleValues")]
[TestCategory("FancyZones Editor #11")]
public void Assign_AllPossibleValues()
{
for (int i = 0; i < 4; i++)
@@ -384,7 +383,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HotKey_Reset_Save")]
[TestCategory("FancyZones Editor #11")]
public void Reset_Save()
{
var layout = CustomLayouts.CustomLayouts[0]; // a layout with assigned hotkey
@@ -424,7 +424,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HotKey_Reset_Cancel")]
[TestCategory("FancyZones Editor #11")]
public void Reset_Cancel()
{
var layout = CustomLayouts.CustomLayouts[0]; // a layout with assigned hotkey

View File

@@ -26,7 +26,7 @@ namespace Microsoft.FancyZonesEditor.UITests
public class TestCaseFirstLaunch : UITestBase
{
public TestCaseFirstLaunch()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}

View File

@@ -18,12 +18,12 @@ namespace Microsoft.FancyZonesEditor.UITests
public class RunFancyZonesEditorTest : UITestBase
{
public RunFancyZonesEditorTest()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
@@ -163,12 +163,8 @@ namespace Microsoft.FancyZonesEditor.UITests
AppliedLayouts = new List<AppliedLayouts.AppliedLayoutWrapper> { },
};
FancyZonesEditorHelper.Files.AppliedLayoutsIOHelper.WriteData(appliedLayouts.Serialize(appliedLayoutsWrapper));
}
[ClassCleanup]
public static void ClassCleanup()
{
FancyZonesEditorHelper.Files.Restore();
this.RestartScopeExe();
}
[TestMethod]

View File

@@ -73,13 +73,14 @@ namespace Microsoft.FancyZonesEditor.UITests
};
public TemplateLayoutsTests()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
[TestInitialize]
public void TestInitialize()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
ParamsWrapper parameters = new ParamsWrapper
{
@@ -191,13 +192,8 @@ namespace Microsoft.FancyZonesEditor.UITests
this.RestartScopeExe();
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.ZoneNumber_Cancel")]
[TestCategory("FancyZones Editor #6")]
public void ZoneNumber_Cancel()
{
var type = LayoutType.Rows;
@@ -205,9 +201,9 @@ namespace Microsoft.FancyZonesEditor.UITests
var expected = layout.ZoneCount;
Session.Find<Button>(TestConstants.TemplateLayoutNames[type]).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.TemplateZoneSlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.TemplateZoneSlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Left);
slider.SendKeys(Key.Left);
Session.Find<Button>(ElementName.Cancel).Click();
@@ -218,7 +214,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected, actual);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HighlightDistance_Initialize")]
[TestCategory("FancyZones Editor #6")]
public void HighlightDistance_Initialize()
{
foreach (var (type, name) in TestConstants.TemplateLayoutNames)
@@ -239,7 +236,8 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HighlightDistance_Save")]
[TestCategory("FancyZones Editor #6")]
public void HighlightDistance_Save()
{
var type = LayoutType.Focus;
@@ -247,11 +245,11 @@ namespace Microsoft.FancyZonesEditor.UITests
var value = layout.SensitivityRadius;
Session.Find<Button>(TestConstants.TemplateLayoutNames[type]).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SensitivitySlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SensitivitySlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
slider.SendKeys(Key.Right);
var expected = value + 1; // one step right
var expected = value; // one step right
Assert.AreEqual($"{expected}", slider.Text);
Session.Find<Button>(ElementName.Save).Click();
@@ -263,7 +261,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected, actual);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.HighlightDistance_Cancel")]
[TestCategory("FancyZones Editor #6")]
public void HighlightDistance_Cancel()
{
var type = LayoutType.Focus;
@@ -271,9 +270,9 @@ namespace Microsoft.FancyZonesEditor.UITests
var expected = layout.SensitivityRadius;
Session.Find<Button>(TestConstants.TemplateLayoutNames[type]).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SensitivitySlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SensitivitySlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
slider.SendKeys(Key.Right);
Session.Find<Button>(ElementName.Cancel).Click();
// verify the file
@@ -283,7 +282,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected, actual);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.SpaceAroundZones_Initialize")]
[TestCategory("FancyZones Editor #6")]
public void SpaceAroundZones_Initialize()
{
foreach (var (type, name) in TestConstants.TemplateLayoutNames)
@@ -309,17 +309,18 @@ namespace Microsoft.FancyZonesEditor.UITests
}
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.SpaceAroundZones_Slider_Save")]
[TestCategory("FancyZones Editor #6")]
public void SpaceAroundZones_Slider_Save()
{
var type = LayoutType.PriorityGrid;
var layout = Layouts.LayoutTemplates.Find(x => x.Type == type.TypeToString());
var expected = layout.Spacing + 1;
var expected = layout.Spacing;
Session.Find<Button>(TestConstants.TemplateLayoutNames[type]).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SpacingSlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SpacingSlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
slider.SendKeys(Key.Right);
Assert.AreEqual($"{expected}", slider.Text);
Session.Find<Button>(ElementName.Save).Click();
@@ -331,7 +332,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected, actual);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.SpaceAroundZones_Slider_Cancel")]
[TestCategory("FancyZones Editor #6")]
public void SpaceAroundZones_Slider_Cancel()
{
var type = LayoutType.PriorityGrid;
@@ -339,10 +341,10 @@ namespace Microsoft.FancyZonesEditor.UITests
var expected = layout.Spacing;
Session.Find<Button>(TestConstants.TemplateLayoutNames[type]).Click();
var slider = Session.Find<Element>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SpacingSlider));
var slider = Session.Find<Custom>(PowerToys.UITest.By.AccessibilityId(AccessibilityId.SpacingSlider));
Assert.IsNotNull(slider);
slider.SendKeys(Keys.Right);
Assert.AreEqual($"{expected + 1}", slider.Text);
slider.SendKeys(Key.Right);
Assert.AreEqual($"{expected}", slider.Text);
Session.Find<Button>(ElementName.Cancel).Click();
@@ -353,7 +355,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected, actual);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.SpaceAroundZones_Toggle_Save")]
[TestCategory("FancyZones Editor #6")]
public void SpaceAroundZones_Toggle_Save()
{
var type = LayoutType.PriorityGrid;
@@ -376,7 +379,8 @@ namespace Microsoft.FancyZonesEditor.UITests
Assert.AreEqual(expected, actual);
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.SpaceAroundZones_Toggle_Cancel")]
[TestCategory("FancyZones Editor #6")]
public void SpaceAroundZones_Toggle_Cancel()
{
var type = LayoutType.PriorityGrid;

View File

@@ -23,17 +23,12 @@ namespace Microsoft.FancyZonesEditor.UITests
public class UIInitializeTest : UITestBase
{
public UIInitializeTest()
: base(PowerToysModule.FancyZone)
: base(PowerToysModule.FancyZone, WindowSize.UnSpecified)
{
}
[TestCleanup]
public void TestCleanup()
{
FancyZonesEditorHelper.Files.Restore();
}
[TestMethod]
[TestMethod("FancyZonesEditor.Basic.EditorParams_VerifySelectedMonitor")]
[TestCategory("FancyZones Editor #10")]
public void EditorParams_VerifySelectedMonitor()
{
InitFileData();
@@ -737,6 +732,7 @@ namespace Microsoft.FancyZonesEditor.UITests
private void InitFileData()
{
FancyZonesEditorHelper.Files.Restore();
EditorParameters editorParameters = new EditorParameters();
ParamsWrapper parameters = new ParamsWrapper
{

View File

@@ -0,0 +1,78 @@
// 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.Collections.Generic;
using System.Text.Json;
using static FancyZonesEditorCommon.Data.AppZoneHistory.AppZoneHistoryWrapper;
using static FancyZonesEditorCommon.Data.CustomLayouts;
namespace FancyZonesEditorCommon.Data
{
public class AppZoneHistory : EditorData<AppZoneHistory.AppZoneHistoryListWrapper>
{
public string File
{
get
{
return GetDataFolder() + "\\Microsoft\\PowerToys\\FancyZones\\app-zone-history.json";
}
}
public struct AppZoneHistoryWrapper
{
public struct ZoneHistoryWrapper
{
public int[][] ZoneIndexSet { get; set; }
public DeviceIdWrapper Device { get; set; }
public string ZonesetUuid { get; set; }
}
public struct DeviceIdWrapper
{
public string Monitor { get; set; }
public string MonitorInstance { get; set; }
public int MonitorNumber { get; set; }
public string SerialNumber { get; set; }
public string VirtualDesktop { get; set; }
}
public string AppPath { get; set; }
public List<ZoneHistoryWrapper> History { get; set; }
}
public struct AppZoneHistoryListWrapper
{
public List<AppZoneHistoryWrapper> AppZoneHistory { get; set; }
}
public JsonElement ToJsonElement(ZoneHistoryWrapper info)
{
string json = JsonSerializer.Serialize(info, this.JsonOptions);
return JsonSerializer.Deserialize<JsonElement>(json);
}
public JsonElement ToJsonElement(DeviceIdWrapper info)
{
string json = JsonSerializer.Serialize(info, this.JsonOptions);
return JsonSerializer.Deserialize<JsonElement>(json);
}
public ZoneHistoryWrapper ZoneHistoryFromJsonElement(string json)
{
return JsonSerializer.Deserialize<ZoneHistoryWrapper>(json, this.JsonOptions);
}
public DeviceIdWrapper GridFromJsonElement(string json)
{
return JsonSerializer.Deserialize<DeviceIdWrapper>(json, this.JsonOptions);
}
}
}

View File

@@ -20,6 +20,8 @@ namespace Microsoft.FancyZonesEditor.UITests.Utils
public IOTestHelper LayoutTemplatesIOHelper { get; }
public IOTestHelper AppZoneHistoryIOHelper { get; }
public FancyZonesEditorFiles()
{
ParamsIOHelper = new IOTestHelper(new EditorParameters().File);
@@ -28,6 +30,7 @@ namespace Microsoft.FancyZonesEditor.UITests.Utils
DefaultLayoutsIOHelper = new IOTestHelper(new DefaultLayouts().File);
LayoutHotkeysIOHelper = new IOTestHelper(new LayoutHotkeys().File);
LayoutTemplatesIOHelper = new IOTestHelper(new LayoutTemplates().File);
AppZoneHistoryIOHelper = new IOTestHelper(new AppZoneHistory().File);
}
public void Restore()
@@ -38,6 +41,7 @@ namespace Microsoft.FancyZonesEditor.UITests.Utils
DefaultLayoutsIOHelper.RestoreData();
LayoutHotkeysIOHelper.RestoreData();
LayoutTemplatesIOHelper.RestoreData();
AppZoneHistoryIOHelper.RestoreData();
}
}
}

View File

@@ -117,9 +117,9 @@ namespace Microsoft.FancyZonesEditor.UnitTests.Utils
session.Find<Element>(By.ClassName(ClassName.ContextMenu)).Find<Element>(menuItem).Click();
}
public static Element? GetZone(Session session, int zoneNumber, string zoneClassName)
public static Custom? GetZone(Session session, int zoneNumber, string zoneClassName)
{
var zones = session.FindAll<Element>(By.ClassName(zoneClassName));
var zones = session.FindAll<Custom>(By.ClassName(zoneClassName));
foreach (var zone in zones)
{
try
@@ -157,7 +157,7 @@ namespace Microsoft.FancyZonesEditor.UnitTests.Utils
public static void MoveSplitter(Session session, int index, int xOffset, int yOffset)
{
var thumbs = session.FindAll<Element>(By.ClassName(ClassName.Thumb));
var thumbs = session.FindAll<Thumb>(By.ClassName(ClassName.Thumb));
if (thumbs.Count == 0 || index >= thumbs.Count)
{
return;

View File

@@ -1,138 +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.IO;
using System.Reflection;
using Microsoft.FancyZonesEditor.UITests.Utils;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Interactions;
namespace Microsoft.FancyZonesEditor.UnitTests.Utils
{
public class FancyZonesEditorSession
{
protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
private const string FancyZonesEditorPath = @"\..\..\..\PowerToys.FancyZonesEditor.exe";
private static FancyZonesEditorFiles? _files;
public static FancyZonesEditorFiles Files
{
get
{
if (_files == null)
{
_files = new FancyZonesEditorFiles();
}
return _files;
}
}
public WindowsDriver<WindowsElement>? Session { get; }
public WindowsElement? MainEditorWindow { get; }
public FancyZonesEditorSession(TestContext testContext)
{
try
{
// Launch FancyZonesEditor
string? path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
path += FancyZonesEditorPath;
AppiumOptions opts = new AppiumOptions();
opts.AddAdditionalCapability("app", path);
Session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), opts);
}
catch (Exception ex)
{
testContext.WriteLine(ex.Message);
}
Assert.IsNotNull(Session, "Session not initialized");
testContext.WriteLine("Session: " + Session.SessionId.ToString());
testContext.WriteLine("Title: " + Session.Title);
// Set implicit timeout to make element search to retry every 500 ms
Session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(3);
// Find main editor window
try
{
MainEditorWindow = Session.FindElementByAccessibilityId("MainWindow1");
}
catch
{
Assert.IsNotNull(MainEditorWindow, "Main editor window not found");
}
}
public void Close(TestContext testContext)
{
// Close the session
if (Session != null)
{
try
{
// FZEditor application can be closed by explicitly closing main editor window
MainEditorWindow?.SendKeys(Keys.Alt + Keys.F4);
}
catch (Exception ex)
{
testContext.WriteLine(ex.Message);
}
Session.Quit();
Session.Dispose();
}
}
private WindowsElement? GetLayout(string layoutName)
{
var listItem = Session?.FindElementByName(layoutName);
Assert.IsNotNull(listItem, "Layout " + layoutName + " not found");
return listItem;
}
public WindowsElement? OpenContextMenu(string layoutName)
{
RightClick_Layout(layoutName);
var menu = Session?.FindElementByClassName("ContextMenu");
Assert.IsNotNull(menu, "Context menu not found");
return menu;
}
public void Click_CreateNewLayout()
{
var button = Session?.FindElementByAccessibilityId("NewLayoutButton");
Assert.IsNotNull(button, "Create new layout button not found");
button?.Click();
}
public void Click_EditLayout(string layoutName)
{
var layout = GetLayout(layoutName);
var editButton = layout?.FindElementByAccessibilityId("EditLayoutButton");
Assert.IsNotNull(editButton, "Edit button not found");
editButton.Click();
}
public void RightClick_Layout(string layoutName)
{
var layout = GetLayout(layoutName);
Actions actions = new Actions(Session);
actions.MoveToElement(layout);
actions.MoveByOffset(30, 30);
actions.ContextClick();
actions.Build().Perform();
}
}
}

View File

@@ -70,6 +70,12 @@ namespace Microsoft.FancyZonesEditor.UITests.Utils
}
}
// For get app zone history data
public string GetData()
{
return ReadFile(_file);
}
private string ReadFile(string fileName)
{
var attempts = 0;