diff --git a/.ncrunch/Avalonia.IntegrationTests.Win32.v3.ncrunchproject b/.ncrunch/Avalonia.IntegrationTests.Win32.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.IntegrationTests.Win32.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/IntegrationTestApp.v3.ncrunchproject b/.ncrunch/IntegrationTestApp.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/IntegrationTestApp.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/Avalonia.sln b/Avalonia.sln
index 75f1dd8407..96d35e1bb9 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -226,11 +226,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI.Events"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sandbox", "samples\Sandbox\Sandbox.csproj", "{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicroComGenerator", "src\tools\MicroComGenerator\MicroComGenerator.csproj", "{AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroComGenerator", "src\tools\MicroComGenerator\MicroComGenerator.csproj", "{AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.MicroCom", "src\Avalonia.MicroCom\Avalonia.MicroCom.csproj", "{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.MicroCom", "src\Avalonia.MicroCom\Avalonia.MicroCom.csproj", "{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMvvm", "samples\MiniMvvm\MiniMvvm.csproj", "{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniMvvm", "samples\MiniMvvm\MiniMvvm.csproj", "{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTestApp", "samples\IntegrationTestApp\IntegrationTestApp.csproj", "{676D6BFD-029D-4E43-BFC7-3892265CE251}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.IntegrationTests.Win32", "tests\Avalonia.IntegrationTests.Win32\Avalonia.IntegrationTests.Win32.csproj", "{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
@@ -2142,6 +2146,54 @@ Global
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhone.Build.0 = Release|Any CPU
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|Any CPU.Build.0 = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|iPhone.Build.0 = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|iPhone.Build.0 = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2203,6 +2255,8 @@ Global
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{AEC9031E-06EA-4A9E-9E7F-7D7C719404DD} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {676D6BFD-029D-4E43-BFC7-3892265CE251} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/samples/IntegrationTestApp/App.axaml b/samples/IntegrationTestApp/App.axaml
new file mode 100644
index 0000000000..a833e096df
--- /dev/null
+++ b/samples/IntegrationTestApp/App.axaml
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/samples/IntegrationTestApp/App.axaml.cs b/samples/IntegrationTestApp/App.axaml.cs
new file mode 100644
index 0000000000..022931366d
--- /dev/null
+++ b/samples/IntegrationTestApp/App.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+
+namespace IntegrationTestApp
+{
+ public class App : Application
+ {
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ desktop.MainWindow = new MainWindow();
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+ }
+}
diff --git a/samples/IntegrationTestApp/IntegrationTestApp.csproj b/samples/IntegrationTestApp/IntegrationTestApp.csproj
new file mode 100644
index 0000000000..89e793837a
--- /dev/null
+++ b/samples/IntegrationTestApp/IntegrationTestApp.csproj
@@ -0,0 +1,10 @@
+
+
+ WinExe
+ netcoreapp3.1
+ enable
+
+
+
+
+
diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml
new file mode 100644
index 0000000000..5daa7c5c18
--- /dev/null
+++ b/samples/IntegrationTestApp/MainWindow.axaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs
new file mode 100644
index 0000000000..5a14d67aa5
--- /dev/null
+++ b/samples/IntegrationTestApp/MainWindow.axaml.cs
@@ -0,0 +1,19 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace IntegrationTestApp
+{
+ public class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/samples/IntegrationTestApp/Program.cs b/samples/IntegrationTestApp/Program.cs
new file mode 100644
index 0000000000..c09b249cfa
--- /dev/null
+++ b/samples/IntegrationTestApp/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+
+namespace IntegrationTestApp
+{
+ class Program
+ {
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ public static void Main(string[] args) => BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .LogToTrace();
+ }
+}
diff --git a/samples/IntegrationTestApp/nuget.config b/samples/IntegrationTestApp/nuget.config
new file mode 100644
index 0000000000..6c273ab3d9
--- /dev/null
+++ b/samples/IntegrationTestApp/nuget.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Controls/Automation/Peers/ButtonAutomationPeer.cs b/src/Avalonia.Controls/Automation/Peers/ButtonAutomationPeer.cs
index ded27f14bd..89c80e1144 100644
--- a/src/Avalonia.Controls/Automation/Peers/ButtonAutomationPeer.cs
+++ b/src/Avalonia.Controls/Automation/Peers/ButtonAutomationPeer.cs
@@ -24,6 +24,9 @@ namespace Avalonia.Automation.Peers
{
return AutomationControlType.Button;
}
+
+ protected override bool IsContentElementCore() => true;
+ protected override bool IsControlElementCore() => true;
}
}
diff --git a/src/Avalonia.Controls/Properties/AssemblyInfo.cs b/src/Avalonia.Controls/Properties/AssemblyInfo.cs
index 5c9017f127..5ccafb725b 100644
--- a/src/Avalonia.Controls/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Controls/Properties/AssemblyInfo.cs
@@ -9,6 +9,7 @@ using Avalonia.Metadata;
[assembly: InternalsVisibleTo("Avalonia.DesignerSupport")]
#endif
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia")]
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Automation")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Embedding")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Presenters")]
diff --git a/tests/Avalonia.IntegrationTests.Win32/Avalonia.IntegrationTests.Win32.csproj b/tests/Avalonia.IntegrationTests.Win32/Avalonia.IntegrationTests.Win32.csproj
new file mode 100644
index 0000000000..0967944e19
--- /dev/null
+++ b/tests/Avalonia.IntegrationTests.Win32/Avalonia.IntegrationTests.Win32.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netcoreapp3.1
+ enable
+
+
+
+
+
+
+
+
diff --git a/tests/Avalonia.IntegrationTests.Win32/ButtonTests.cs b/tests/Avalonia.IntegrationTests.Win32/ButtonTests.cs
new file mode 100644
index 0000000000..03a156a9e2
--- /dev/null
+++ b/tests/Avalonia.IntegrationTests.Win32/ButtonTests.cs
@@ -0,0 +1,40 @@
+using OpenQA.Selenium.Appium.Windows;
+using Xunit;
+
+namespace Avalonia.IntegrationTests.Win32
+{
+ [Collection("IntegrationTestApp collection")]
+ public class ButtonTests
+ {
+ private WindowsDriver _session;
+ public ButtonTests(TestAppFixture fixture) => _session = fixture.Session;
+
+ [Fact]
+ public void BasicButton()
+ {
+ SelectButtonTab();
+
+ var button = _session.FindElementByAccessibilityId("BasicButton");
+
+ Assert.Equal("Basic Button", button.Text);
+ }
+
+ [Fact]
+ public void ButtonWithTextBlock()
+ {
+ SelectButtonTab();
+
+ var button = _session.FindElementByAccessibilityId("ButtonWithTextBlock");
+
+ Assert.Equal("Button with TextBlock", button.Text);
+ }
+
+ private WindowsElement SelectButtonTab()
+ {
+ var tabs = _session.FindElementByAccessibilityId("MainTabs");
+ var buttonTab = tabs.FindElementByName("Button");
+ buttonTab.Click();
+ return (WindowsElement)buttonTab;
+ }
+ }
+}
diff --git a/tests/Avalonia.IntegrationTests.Win32/Properties/AssemblyInfo.cs b/tests/Avalonia.IntegrationTests.Win32/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..f9248a3152
--- /dev/null
+++ b/tests/Avalonia.IntegrationTests.Win32/Properties/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+using Xunit;
+
+// Don't run tests in parallel.
+[assembly: CollectionBehavior(DisableTestParallelization = true)]
diff --git a/tests/Avalonia.IntegrationTests.Win32/TestAppCollection.cs b/tests/Avalonia.IntegrationTests.Win32/TestAppCollection.cs
new file mode 100644
index 0000000000..6461e14596
--- /dev/null
+++ b/tests/Avalonia.IntegrationTests.Win32/TestAppCollection.cs
@@ -0,0 +1,9 @@
+using Xunit;
+
+namespace Avalonia.IntegrationTests.Win32
+{
+ [CollectionDefinition("IntegrationTestApp collection")]
+ public class TestAppCollection : ICollectionFixture
+ {
+ }
+}
diff --git a/tests/Avalonia.IntegrationTests.Win32/TestAppFixture.cs b/tests/Avalonia.IntegrationTests.Win32/TestAppFixture.cs
new file mode 100644
index 0000000000..6337ff1c6f
--- /dev/null
+++ b/tests/Avalonia.IntegrationTests.Win32/TestAppFixture.cs
@@ -0,0 +1,28 @@
+using System;
+using System.IO;
+using OpenQA.Selenium.Appium;
+using OpenQA.Selenium.Appium.Windows;
+
+namespace Avalonia.IntegrationTests.Win32
+{
+ public class TestAppFixture : IDisposable
+ {
+ private const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
+ private const string TestAppPath = @"..\..\..\..\..\samples\IntegrationTestApp\bin\Debug\netcoreapp3.1\IntegrationTestApp.exe";
+
+ public TestAppFixture()
+ {
+ var opts = new AppiumOptions();
+ var path = Path.GetFullPath(TestAppPath);
+ opts.AddAdditionalCapability("app", path);
+ opts.AddAdditionalCapability("deviceName", "WindowsPC");
+ Session = new WindowsDriver(
+ new Uri(WindowsApplicationDriverUrl),
+ opts);
+ }
+
+ public WindowsDriver Session { get; }
+
+ public void Dispose() => Session.Close();
+ }
+}
diff --git a/tests/Avalonia.IntegrationTests.Win32/xunit.runner.json b/tests/Avalonia.IntegrationTests.Win32/xunit.runner.json
new file mode 100644
index 0000000000..f78bc2f0c6
--- /dev/null
+++ b/tests/Avalonia.IntegrationTests.Win32/xunit.runner.json
@@ -0,0 +1,3 @@
+{
+ "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json"
+}
\ No newline at end of file