diff --git a/NOTICE.md b/NOTICE.md
index 5891f1ae7f..388d82ef74 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -1322,6 +1322,7 @@ EXHIBIT A -Mozilla Public License.
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
- Microsoft.Data.Sqlite 9.0.2
- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
+- Microsoft.DotNet.ILCompiler (A)
- Microsoft.Extensions.DependencyInjection 9.0.2
- Microsoft.Extensions.Hosting 9.0.2
- Microsoft.Extensions.Hosting.WindowsServices 9.0.2
diff --git a/PowerToys.sln b/PowerToys.sln
index c7b9d5fac2..7a5f2831d8 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -636,6 +636,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItModuleInterface", "sr
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItSettingsInterop", "src\modules\ZoomIt\ZoomItSettingsInterop\ZoomItSettingsInterop.vcxproj", "{CA7D8106-30B9-4AEC-9D05-B69B31B8C461}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITestAutomation", "src\common\UITestAutomation\UITestAutomation.csproj", "{A558C25D-2007-498E-8B6F-43405AFAE9E2}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyboardManagerEditorUI", "src\modules\keyboardmanager\KeyboardManagerEditorUI\KeyboardManagerEditorUI.csproj", "{08F9155D-B6DC-46E5-9C83-AF60B655898B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditorLibraryWrapper", "src\modules\keyboardmanager\KeyboardManagerEditorLibraryWrapper\KeyboardManagerEditorLibraryWrapper.vcxproj", "{4382A954-179A-4078-92AF-715187DFFF50}"
@@ -2250,6 +2252,20 @@ Global
{CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|ARM64.Build.0 = Release|ARM64
{CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x64.ActiveCfg = Release|x64
{CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x64.Build.0 = Release|x64
+ {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x86.ActiveCfg = Release|x64
+ {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x86.Build.0 = Release|x64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|ARM64.Build.0 = Debug|ARM64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|x64.ActiveCfg = Debug|x64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|x64.Build.0 = Debug|x64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|x86.ActiveCfg = Debug|x64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|x86.Build.0 = Debug|x64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|ARM64.ActiveCfg = Release|ARM64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|ARM64.Build.0 = Release|ARM64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|x64.ActiveCfg = Release|x64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|x64.Build.0 = Release|x64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|x86.ActiveCfg = Release|x64
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|x86.Build.0 = Release|x64
{08F9155D-B6DC-46E5-9C83-AF60B655898B}.Debug|ARM64.ActiveCfg = Debug|ARM64
{08F9155D-B6DC-46E5-9C83-AF60B655898B}.Debug|ARM64.Build.0 = Debug|ARM64
{08F9155D-B6DC-46E5-9C83-AF60B655898B}.Debug|x64.ActiveCfg = Debug|x64
@@ -2509,6 +2525,9 @@ Global
{0A84F764-3A88-44CD-AA96-41BDBD48627B} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C}
{E4585179-2AC1-4D5F-A3FF-CFC5392F694C} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C}
{CA7D8106-30B9-4AEC-9D05-B69B31B8C461} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C}
+ {A558C25D-2007-498E-8B6F-43405AFAE9E2} = {1AFB6476-670D-4E80-A464-657E01DFF482}
+ {08F9155D-B6DC-46E5-9C83-AF60B655898B} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
+ {4382A954-179A-4078-92AF-715187DFFF50} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{EBED240C-8702-452D-B764-6DB9DA9179AF} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
diff --git a/doc/devdocs/UITests.md b/doc/devdocs/UITests.md
new file mode 100644
index 0000000000..fea05f6b9e
--- /dev/null
+++ b/doc/devdocs/UITests.md
@@ -0,0 +1,91 @@
+# UI tests framework
+
+ A specialized UI test framework for PowerToys that makes it easy to write UI tests for PowerToys modules or settings. Let's start writing UI tests!
+
+## Before running tests
+
+- Install Windows Application Driver v1.2.1 from https://github.com/microsoft/WinAppDriver/releases/tag/v1.2.1 to the default directory (`C:\Program Files (x86)\Windows Application Driver`)
+
+- Enable Developer Mode in Windows settings
+
+## Running tests
+
+- Exit PowerToys if it's running.
+
+- Open `PowerToys.sln` in Visual Studio and build the solution.
+
+- Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`).
+
+
+## How to add the first UI tests for your modules
+
+- Create a new project and add the following references to the project file. Change the OutputPath to your own module's path.
+ ```
+
+ Library
+
+ false
+
+
+
+ ..\..\..\..\$(Platform)\$(Configuration)\tests\KeyboardManagerUITests\
+
+
+
+
+
+
+
+ ```
+- Inherit your test class from UITestBase.
+ >Set Scope: The default scope starts from the PowerToys settings UI. If you want to start from your own module, set the constructor as shown below:
+
+ >Specify Scope:
+ ```
+ [TestClass]
+ public class RunFancyZonesTest : UITestBase
+ {
+ public RunFancyZonesTest()
+ : base(PowerToysModule.FancyZone)
+ {
+ }
+ }
+ ```
+
+- Then you can start using session to perform the UI operations.
+
+**Example**
+```
+using Microsoft.PowerToys.UITest;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace UITests_KeyboardManager
+{
+ [TestClass]
+ public class RunKeyboardManagerUITests : UITestBase
+ {
+ [TestMethod]
+ public void OpenKeyboardManagerEditor()
+ {
+ // Open KeyboardManagerEditor
+ this.Session.Find