diff --git a/Avalonia.sln b/Avalonia.sln
index 71ed289241..551eb5925e 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -226,6 +226,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Markup.Xaml.Loader
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.ReactiveUI.Events", "src\Avalonia.ReactiveUI.Events\Avalonia.ReactiveUI.Events.csproj", "{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.ReactiveUI.Events.UnitTests", "tests\Avalonia.ReactiveUI.Events.UnitTests\Avalonia.ReactiveUI.Events.UnitTests.csproj", "{780AC0FE-8DD2-419F-A1DC-AC7E3EB393F7}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
@@ -2120,6 +2122,7 @@ Global
{351337F5-D66F-461B-A957-4EF60BDB4BA6} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{3C84E04B-36CF-4D0D-B965-C26DD649D1F3} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
+ {780AC0FE-8DD2-419F-A1DC-AC7E3EB393F7} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/dirs.proj b/dirs.proj
index 26c8f54b23..086a22a77b 100644
--- a/dirs.proj
+++ b/dirs.proj
@@ -7,6 +7,7 @@
+
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index 8c40a2c45b..a46b55f6f3 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -240,6 +240,7 @@ partial class Build : NukeBuild
RunCoreTest("Avalonia.Visuals.UnitTests");
RunCoreTest("Avalonia.Skia.UnitTests");
RunCoreTest("Avalonia.ReactiveUI.UnitTests");
+ RunCoreTest("Avalonia.ReactiveUI.Events.UnitTests");
});
Target RunRenderTests => _ => _
diff --git a/tests/Avalonia.ReactiveUI.Events.UnitTests/Avalonia.ReactiveUI.Events.UnitTests.csproj b/tests/Avalonia.ReactiveUI.Events.UnitTests/Avalonia.ReactiveUI.Events.UnitTests.csproj
new file mode 100644
index 0000000000..19a6fd138e
--- /dev/null
+++ b/tests/Avalonia.ReactiveUI.Events.UnitTests/Avalonia.ReactiveUI.Events.UnitTests.csproj
@@ -0,0 +1,15 @@
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Avalonia.ReactiveUI.Events.UnitTests/BasicControlEventsTest.cs b/tests/Avalonia.ReactiveUI.Events.UnitTests/BasicControlEventsTest.cs
new file mode 100644
index 0000000000..1092c98246
--- /dev/null
+++ b/tests/Avalonia.ReactiveUI.Events.UnitTests/BasicControlEventsTest.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Reactive.Linq;
+using Avalonia.Controls;
+using Avalonia.UnitTests;
+using Xunit;
+
+namespace Avalonia.ReactiveUI.Events.UnitTests
+{
+ public class BasicControlEventsTest
+ {
+ public class EventsControl : UserControl
+ {
+ public bool IsAttached { get; private set; }
+
+ public EventsControl()
+ {
+ var attached = this
+ .Events()
+ .AttachedToVisualTree
+ .Select(args => true);
+
+ this.Events()
+ .DetachedFromVisualTree
+ .Select(args => false)
+ .Merge(attached)
+ .Subscribe(marker => IsAttached = marker);
+ }
+ }
+
+ [Fact]
+ public void Should_Generate_Events_Wrappers()
+ {
+ var root = new TestRoot();
+ var control = new EventsControl();
+ Assert.False(control.IsAttached);
+
+ root.Child = control;
+ Assert.True(control.IsAttached);
+
+ root.Child = null;
+ Assert.False(control.IsAttached);
+ }
+ }
+}