From aeeefa304df2c149aa9068801dfef696346381a0 Mon Sep 17 00:00:00 2001 From: Jerry Xu Date: Wed, 26 Feb 2025 12:59:31 +0800 Subject: [PATCH 01/10] Add more UI-Test, refactor UITestAutomation --- .../UITestAutomation/Element/Element.cs | 5 +- src/common/UITestAutomation/SessionHelper.cs | 106 ++++++++++++++++++ src/common/UITestAutomation/UITestBase.cs | 101 +---------------- .../Hosts/Hosts.UITests/HostModuleTests.cs | 18 +++ 4 files changed, 131 insertions(+), 99 deletions(-) create mode 100644 src/common/UITestAutomation/SessionHelper.cs diff --git a/src/common/UITestAutomation/Element/Element.cs b/src/common/UITestAutomation/Element/Element.cs index f2f3d4ee29bd..7d78ac5f9c4e 100644 --- a/src/common/UITestAutomation/Element/Element.cs +++ b/src/common/UITestAutomation/Element/Element.cs @@ -174,7 +174,7 @@ public T Find(By by, int timeoutMS = 3000) /// The selector to use for finding the elements. /// The timeout in milliseconds. /// A read-only collection of the found elements. - public ReadOnlyCollection? FindAll(By by, int timeoutMS = 3000) + public ReadOnlyCollection FindAll(By by, int timeoutMS = 3000) where T : Element, new() { Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method FindAll<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}"); @@ -182,13 +182,12 @@ public T Find(By by, int timeoutMS = 3000) () => { var elements = this.windowsElement.FindElements(by.ToSeleniumBy()); - Assert.IsTrue(elements.Count > 0, $"Elements not found using selector: {by}"); return elements; }, this.driver, timeoutMS); - return foundElements; + return foundElements ?? new ReadOnlyCollection(new List()); } /// diff --git a/src/common/UITestAutomation/SessionHelper.cs b/src/common/UITestAutomation/SessionHelper.cs new file mode 100644 index 000000000000..ec2e97caec76 --- /dev/null +++ b/src/common/UITestAutomation/SessionHelper.cs @@ -0,0 +1,106 @@ +// 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.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Windows; + +namespace Microsoft.PowerToys.UITest +{ + /// + /// Nested class for test initialization. + /// + internal class SessionHelper + { + // Default session path is PowerToys settings dashboard + private readonly string sessionPath = ModuleConfigData.Instance.GetModulePath(PowerToysModule.PowerToysSettings); + + private WindowsDriver Root { get; set; } + + private WindowsDriver? Driver { get; set; } + + private Process? appDriver; + + public SessionHelper(PowerToysModule scope, bool runAsAdmin) + { + this.sessionPath = ModuleConfigData.Instance.GetModulePath(scope); + + var winAppDriverProcessInfo = new ProcessStartInfo + { + FileName = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe", + }; + + if (runAsAdmin) + { + winAppDriverProcessInfo.UseShellExecute = true; + winAppDriverProcessInfo.Verb = "runas"; + } + + this.appDriver = Process.Start(winAppDriverProcessInfo); + + var desktopCapabilities = new AppiumOptions(); + desktopCapabilities.AddAdditionalCapability("app", "Root"); + this.Root = new WindowsDriver(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), desktopCapabilities); + + // Set default timeout to 5 seconds + this.Root.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5); + } + + /// + /// Initializes the test environment. + /// + /// The PowerToys module to start. + [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "")] + public SessionHelper Init() + { + string? path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + this.StartExe(path + this.sessionPath); + + Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null."); + + // Set default timeout to 5 seconds + this.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5); + + return this; + } + + /// + /// Cleans up the test environment. + /// + public void Cleanup() + { + try + { + appDriver?.Kill(); + } + catch (Exception ex) + { + // Handle exceptions if needed + Debug.WriteLine($"Exception during Cleanup: {ex.Message}"); + } + } + + /// + /// Starts a new exe and takes control of it. + /// + /// The path to the application executable. + public void StartExe(string appPath) + { + var opts = new AppiumOptions(); + opts.AddAdditionalCapability("app", appPath); + this.Driver = new WindowsDriver(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), opts); + } + + public WindowsDriver GetRoot() => this.Root; + + public WindowsDriver GetDriver() + { + Assert.IsNotNull(this.Driver, $"Failed to get driver. Driver is null."); + return this.Driver; + } + } +} diff --git a/src/common/UITestAutomation/UITestBase.cs b/src/common/UITestAutomation/UITestBase.cs index 4ce432f23a07..2fbb6cefe827 100644 --- a/src/common/UITestAutomation/UITestBase.cs +++ b/src/common/UITestAutomation/UITestBase.cs @@ -19,18 +19,17 @@ public class UITestBase { public Session Session { get; set; } - private readonly TestInit testInit = new TestInit(); + private readonly SessionHelper sessionHelper; - public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings) + public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, bool runAsAdmin = false) { - this.testInit.SetScope(scope); - this.testInit.Init(); - this.Session = new Session(this.testInit.GetRoot(), this.testInit.GetDriver()); + this.sessionHelper = new SessionHelper(scope, runAsAdmin).Init(); + this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver()); } ~UITestBase() { - this.testInit.Cleanup(); + this.sessionHelper.Cleanup(); } /// @@ -60,95 +59,5 @@ protected ReadOnlyCollection FindAll(By by, int timeoutMS = 3000) { return this.Session.FindAll(by, timeoutMS); } - - /// - /// Nested class for test initialization. - /// - private sealed class TestInit - { - private WindowsDriver Root { get; set; } - - private WindowsDriver? Driver { get; set; } - - private static Process? appDriver; - - // Default session path is PowerToys settings dashboard - private static string sessionPath = ModuleConfigData.Instance.GetModulePath(PowerToysModule.PowerToysSettings); - - public TestInit() - { - appDriver = Process.Start(new ProcessStartInfo - { - FileName = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe", - Verb = "runas", - }); - - var desktopCapabilities = new AppiumOptions(); - desktopCapabilities.AddAdditionalCapability("app", "Root"); - this.Root = new WindowsDriver(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), desktopCapabilities); - - // Set default timeout to 5 seconds - this.Root.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5); - } - - /// - /// Initializes the test environment. - /// - [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "")] - public void Init() - { - string? path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - this.StartExe(path + sessionPath); - - Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null."); - - // Set default timeout to 5 seconds - this.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5); - } - - /// - /// Cleans up the test environment. - /// - public void Cleanup() - { - try - { - appDriver?.Kill(); - } - catch (Exception ex) - { - // Handle exceptions if needed - Debug.WriteLine($"Exception during Cleanup: {ex.Message}"); - } - } - - /// - /// Starts a new exe and takes control of it. - /// - /// The path to the application executable. - public void StartExe(string appPath) - { - var opts = new AppiumOptions(); - opts.AddAdditionalCapability("app", appPath); - this.Driver = new WindowsDriver(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), opts); - } - - /// - /// Sets scope to the Test Class. - /// - /// The PowerToys module to start. - public void SetScope(PowerToysModule scope) - { - sessionPath = ModuleConfigData.Instance.GetModulePath(scope); - } - - public WindowsDriver GetRoot() => this.Root; - - public WindowsDriver GetDriver() - { - Assert.IsNotNull(this.Driver, $"Failed to get driver. Driver is null."); - return this.Driver; - } - } } } diff --git a/src/modules/Hosts/Hosts.UITests/HostModuleTests.cs b/src/modules/Hosts/Hosts.UITests/HostModuleTests.cs index 35d49a5b64cd..77b494c1673d 100644 --- a/src/modules/Hosts/Hosts.UITests/HostModuleTests.cs +++ b/src/modules/Hosts/Hosts.UITests/HostModuleTests.cs @@ -56,6 +56,24 @@ public void TestAddingEntry() Assert.IsTrue(this.FindAll public class Button : Element { + private static readonly string ExpectedControlType = "ControlType.Button"; + + /// + /// Initializes a new instance of the class. + /// + public Button() + { + this.TargetControlType = Button.ExpectedControlType; + } } } diff --git a/src/common/UITestAutomation/Element/Element.cs b/src/common/UITestAutomation/Element/Element.cs index 7d78ac5f9c4e..59c799e401dc 100644 --- a/src/common/UITestAutomation/Element/Element.cs +++ b/src/common/UITestAutomation/Element/Element.cs @@ -22,6 +22,14 @@ public class Element private WindowsDriver? driver; + protected string? TargetControlType { get; set; } + + internal bool IsMatchingTarget() + { + var ct = this.ControlType; + return string.IsNullOrEmpty(this.TargetControlType) || this.TargetControlType == this.ControlType; + } + internal void SetWindowsElement(WindowsElement windowsElement) => this.windowsElement = windowsElement; internal void SetSession(WindowsDriver driver) => this.driver = driver; @@ -91,7 +99,7 @@ public string ControlType /// Click the UI element. /// /// If true, performs a right-click; otherwise, performs a left-click. Default value is false - public void Click(bool rightClick = false) + public virtual void Click(bool rightClick = false) { PerformAction((actions, windowElement) => { @@ -116,7 +124,7 @@ public void Click(bool rightClick = false) /// /// Double Click the UI element. /// - public void DoubleClick() + public virtual void DoubleClick() { PerformAction((actions, windowElement) => { @@ -139,7 +147,6 @@ public string GetAttribute(string attributeName) { Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method GetAttribute with parameter: attributeName = {attributeName}"); var attributeValue = this.windowsElement.GetAttribute(attributeName); - Assert.IsNotNull(attributeValue, $"Attribute '{attributeName}' is null."); return attributeValue; } @@ -154,17 +161,51 @@ public T Find(By by, int timeoutMS = 3000) where T : Element, new() { Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method Find<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}"); - var foundElement = FindHelper.Find( - () => - { - var element = this.windowsElement.FindElement(by.ToSeleniumBy()); - Assert.IsNotNull(element, $"Element not found using selector: {by}"); - return element; - }, - this.driver, - timeoutMS); - return foundElement; + // leverage findAll to filter out mismatched elements + var collection = this.FindAll(by, timeoutMS); + + Assert.IsTrue(collection.Count > 0, $"Element not found using selector: {by}"); + + return collection[0]; + } + + /// + /// Finds an element by the selector. + /// Shortcut for this.Find(By.Name(name), timeoutMS) + /// + /// The class type of the element to find. + /// The name for finding the element. + /// The timeout in milliseconds. + /// The found element. + public T Find(string name, int timeoutMS = 3000) + where T : Element, new() + { + return this.Find(By.Name(name), timeoutMS); + } + + /// + /// Finds an element by the selector. + /// Shortcut for this.Find(by, timeoutMS) + /// + /// The selector to use for finding the element. + /// The timeout in milliseconds. + /// The found element. + public Element Find(By by, int timeoutMS = 3000) + { + return this.Find(by, timeoutMS); + } + + /// + /// Finds an element by the selector. + /// Shortcut for this.Find(By.Name(name), timeoutMS) + /// + /// The name for finding the element. + /// The timeout in milliseconds. + /// The found element. + public Element Find(string name, int timeoutMS = 3000) + { + return this.Find(By.Name(name), timeoutMS); } /// @@ -187,16 +228,54 @@ public ReadOnlyCollection FindAll(By by, int timeoutMS = 3000) this.driver, timeoutMS); - return foundElements ?? new ReadOnlyCollection(new List()); + return foundElements ?? new ReadOnlyCollection([]); + } + + /// + /// Finds all elements by the selector. + /// Shortcut for this.FindAll(By.Name(name), timeoutMS) + /// + /// The class type of the elements to find. + /// The name for finding the element. + /// The timeout in milliseconds. + /// A read-only collection of the found elements. + public ReadOnlyCollection FindAll(string name, int timeoutMS = 3000) + where T : Element, new() + { + return this.FindAll(By.Name(name), timeoutMS); + } + + /// + /// Finds all elements by the selector. + /// Shortcut for this.FindAll(by, timeoutMS) + /// + /// The selector to use for finding the elements. + /// The timeout in milliseconds. + /// A read-only collection of the found elements. + public ReadOnlyCollection FindAll(By by, int timeoutMS = 3000) + { + return this.FindAll(by, timeoutMS); + } + + /// + /// Finds all elements by the selector. + /// Shortcut for this.FindAll(By.Name(name), timeoutMS) + /// + /// The name for finding the element. + /// The timeout in milliseconds. + /// A read-only collection of the found elements. + public ReadOnlyCollection FindAll(string name, int timeoutMS = 3000) + { + return this.FindAll(By.Name(name), timeoutMS); } /// /// Simulates a manual operation on the element. /// /// The action to perform on the element. - /// The number of milliseconds to wait before the action. Default value is 100 ms - /// The number of milliseconds to wait after the action. Default value is 100 ms - protected void PerformAction(Action action, int msPreAction = 100, int msPostAction = 100) + /// The number of milliseconds to wait before the action. Default value is 500 ms + /// The number of milliseconds to wait after the action. Default value is 500 ms + protected void PerformAction(Action action, int msPreAction = 500, int msPostAction = 500) { if (msPreAction > 0) { diff --git a/src/common/UITestAutomation/Element/HyperlinkButton.cs b/src/common/UITestAutomation/Element/HyperlinkButton.cs new file mode 100644 index 000000000000..738414b1b508 --- /dev/null +++ b/src/common/UITestAutomation/Element/HyperlinkButton.cs @@ -0,0 +1,23 @@ +// 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. + +namespace Microsoft.PowerToys.UITest +{ + /// + /// Represents a HyperLinkButton in the UI test environment. + /// HyperLinkButton reepresents a button control that functions as a hyperlink. + /// + public class HyperlinkButton : Button + { + private static readonly string ExpectedControlType = "ControlType.HyperLink"; + + /// + /// Initializes a new instance of the class. + /// + public HyperlinkButton() + { + this.TargetControlType = HyperlinkButton.ExpectedControlType; + } + } +} diff --git a/src/common/UITestAutomation/Element/NavigationViewItem.cs b/src/common/UITestAutomation/Element/NavigationViewItem.cs new file mode 100644 index 000000000000..c23713de31a4 --- /dev/null +++ b/src/common/UITestAutomation/Element/NavigationViewItem.cs @@ -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. + +namespace Microsoft.PowerToys.UITest +{ + /// + /// Represents a NavigationViewItem in the UI test environment. + /// NavigationViewItem pepresents the container for an item in a NavigationView control. + /// + public class NavigationViewItem : Element + { + private static readonly string ExpectedControlType = "ControlType.ListItem"; + + /// + /// Initializes a new instance of the class. + /// + public NavigationViewItem() + { + this.TargetControlType = NavigationViewItem.ExpectedControlType; + } + + /// + /// Click the ListItem element. + /// + /// If true, performs a right-click; otherwise, performs a left-click. Default value is false + public override void Click(bool rightClick = false) + { + PerformAction((actions, windowElement) => + { + actions.MoveToElement(windowElement, 10, 10); + + if (rightClick) + { + actions.ContextClick(); + } + else + { + actions.Click(); + } + + actions.Build().Perform(); + }); + } + + /// + /// Double Click the ListItem element. + /// + public override void DoubleClick() + { + PerformAction((actions, windowElement) => + { + actions.MoveToElement(windowElement, 10, 10); + actions.DoubleClick(); + actions.Build().Perform(); + }); + } + } +} diff --git a/src/common/UITestAutomation/Element/TextBlock.cs b/src/common/UITestAutomation/Element/TextBlock.cs new file mode 100644 index 000000000000..883b104e2623 --- /dev/null +++ b/src/common/UITestAutomation/Element/TextBlock.cs @@ -0,0 +1,23 @@ +// 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. + +namespace Microsoft.PowerToys.UITest +{ + /// + /// Represents a TextBlock in the UI test environment. + /// TextBlock provides a lightweight control for displaying small amounts of flow content. + /// + public class TextBlock : Element + { + private static readonly string ExpectedControlType = "ControlType.Text"; + + /// + /// Initializes a new instance of the class. + /// + public TextBlock() + { + this.TargetControlType = TextBlock.ExpectedControlType; + } + } +} diff --git a/src/common/UITestAutomation/Element/TextBox.cs b/src/common/UITestAutomation/Element/TextBox.cs index e427f7c9d316..dc6d70fe38cc 100644 --- a/src/common/UITestAutomation/Element/TextBox.cs +++ b/src/common/UITestAutomation/Element/TextBox.cs @@ -7,10 +7,21 @@ namespace Microsoft.PowerToys.UITest { /// - /// Represents a textbox in the UI test environment. + /// Represents a TextBox in the UI test environment. + /// TextBox rpresents a control that can be used to display and edit plain text (single or multi-line). /// public class TextBox : Element { + private static readonly string ExpectedControlType = "ControlType.Edit"; + + /// + /// Initializes a new instance of the class. + /// + public TextBox() + { + this.TargetControlType = TextBox.ExpectedControlType; + } + /// /// Sets the text of the textbox. /// diff --git a/src/common/UITestAutomation/Element/Window.cs b/src/common/UITestAutomation/Element/Window.cs index eceb1fcf4793..5fc5fc6e266c 100644 --- a/src/common/UITestAutomation/Element/Window.cs +++ b/src/common/UITestAutomation/Element/Window.cs @@ -18,7 +18,7 @@ public Window Maximize(bool byClickButton = true) { if (byClickButton) { - Find internal static class FindHelper { - public static T Find(Func findElementFunc, WindowsDriver? driver, int timeoutMS) - where T : Element, new() - { - var item = findElementFunc() as WindowsElement; - return NewElement(item, driver, timeoutMS); - } - public static ReadOnlyCollection? FindAll(Func> findElementsFunc, WindowsDriver? driver, int timeoutMS) where T : Element, new() { @@ -32,7 +25,7 @@ public static T Find(Func findElementFunc, WindowsDriver(element, driver, timeoutMS); - }).ToList(); + }).Where(item => item.IsMatchingTarget()).ToList(); return new ReadOnlyCollection(res); } diff --git a/src/common/UITestAutomation/Session.cs b/src/common/UITestAutomation/Session.cs index 7071f6d2e236..ef0a6fff3fad 100644 --- a/src/common/UITestAutomation/Session.cs +++ b/src/common/UITestAutomation/Session.cs @@ -4,6 +4,7 @@ using System.Collections.ObjectModel; using System.Runtime.InteropServices; +using System.Xml.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; @@ -39,17 +40,48 @@ public T Find(By by, int timeoutMS = 3000) where T : Element, new() { Assert.IsNotNull(this.WindowsDriver, $"WindowsElement is null in method Find<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}"); - var foundElement = FindHelper.Find( - () => - { - var element = this.WindowsDriver.FindElement(by.ToSeleniumBy()); - Assert.IsNotNull(element, $"Element not found using selector: {by}"); - return element; - }, - this.WindowsDriver, - timeoutMS); - return foundElement; + // leverage findAll to filter out mismatched elements + var collection = this.FindAll(by, timeoutMS); + + Assert.IsTrue(collection.Count > 0, $"Element not found using selector: {by}"); + + return collection[0]; + } + + /// + /// Shortcut for this.Find(By.Name(name), timeoutMS) + /// + /// The class of the element, should be Element or its derived class. + /// The name of the element. + /// The timeout in milliseconds (default is 3000). + /// The found element. + public T Find(string name, int timeoutMS = 3000) + where T : Element, new() + { + return this.Find(By.Name(name), timeoutMS); + } + + /// + /// Shortcut for this.Find(by, timeoutMS) + /// + /// The selector to find the element. + /// The timeout in milliseconds (default is 3000). + /// The found element. + public Element Find(By by, int timeoutMS = 3000) + { + return this.Find(by, timeoutMS); + } + + /// + /// Shortcut for this.Find(By.Name(name), timeoutMS) + /// + /// The name of the element. + /// The timeout in milliseconds (default is 3000). + /// The found element. + public Element Find(string name, int timeoutMS = 3000) + { + return this.Find(By.Name(name), timeoutMS); } /// @@ -72,7 +104,45 @@ public ReadOnlyCollection FindAll(By by, int timeoutMS = 3000) this.WindowsDriver, timeoutMS); - return foundElements ?? new ReadOnlyCollection(new List()); + return foundElements ?? new ReadOnlyCollection([]); + } + + /// + /// Finds all elements by selector. + /// Shortcut for this.FindAll(By.Name(name), timeoutMS) + /// + /// The class of the elements, should be Element or its derived class. + /// The name to find the elements. + /// The timeout in milliseconds (default is 3000). + /// A read-only collection of the found elements. + public ReadOnlyCollection FindAll(string name, int timeoutMS = 3000) + where T : Element, new() + { + return this.FindAll(By.Name(name), timeoutMS); + } + + /// + /// Finds all elements by selector. + /// Shortcut for this.FindAll(by, timeoutMS) + /// + /// The selector to find the elements. + /// The timeout in milliseconds (default is 3000). + /// A read-only collection of the found elements. + public ReadOnlyCollection FindAll(By by, int timeoutMS = 3000) + { + return this.FindAll(by, timeoutMS); + } + + /// + /// Finds all elements by selector. + /// Shortcut for this.FindAll(By.Name(name), timeoutMS) + /// + /// The name to find the elements. + /// The timeout in milliseconds (default is 3000). + /// A read-only collection of the found elements. + public ReadOnlyCollection FindAll(string name, int timeoutMS = 3000) + { + return this.FindAll(By.Name(name), timeoutMS); } /// diff --git a/src/common/UITestAutomation/SessionHelper.cs b/src/common/UITestAutomation/SessionHelper.cs index ec2e97caec76..7bb1f6e7a6fd 100644 --- a/src/common/UITestAutomation/SessionHelper.cs +++ b/src/common/UITestAutomation/SessionHelper.cs @@ -25,21 +25,16 @@ internal class SessionHelper private Process? appDriver; - public SessionHelper(PowerToysModule scope, bool runAsAdmin) + public SessionHelper(PowerToysModule scope) { this.sessionPath = ModuleConfigData.Instance.GetModulePath(scope); var winAppDriverProcessInfo = new ProcessStartInfo { FileName = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe", + Verb = "runas", }; - if (runAsAdmin) - { - winAppDriverProcessInfo.UseShellExecute = true; - winAppDriverProcessInfo.Verb = "runas"; - } - this.appDriver = Process.Start(winAppDriverProcessInfo); var desktopCapabilities = new AppiumOptions(); diff --git a/src/common/UITestAutomation/UITestBase.cs b/src/common/UITestAutomation/UITestBase.cs index 2fbb6cefe827..1d6502ac5447 100644 --- a/src/common/UITestAutomation/UITestBase.cs +++ b/src/common/UITestAutomation/UITestBase.cs @@ -15,15 +15,19 @@ namespace Microsoft.PowerToys.UITest /// /// Base class that should be inherited by all Test Classes. /// + [TestClass] public class UITestBase { public Session Session { get; set; } private readonly SessionHelper sessionHelper; - public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, bool runAsAdmin = false) + private readonly PowerToysModule scope; + + public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings) { - this.sessionHelper = new SessionHelper(scope, runAsAdmin).Init(); + this.scope = scope; + this.sessionHelper = new SessionHelper(scope).Init(); this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver()); } @@ -32,6 +36,23 @@ public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, boo this.sessionHelper.Cleanup(); } + /// + /// Initializes the test. + /// + [TestInitialize] + public void TestInit() + { + if (this.scope == PowerToysModule.PowerToysSettings) + { + // close Debug warning dialog if any + // Such debug warning dialog seems only appear in PowerToys Settings + if (this.FindAll("DEBUG").Count > 0) + { + this.Find("DEBUG").Find