Browse Source
Tunnelled and bubbling events can now be represented by a single RoutedEvent. Next need to implement 'handledEventsToo'.pull/39/head
13 changed files with 509 additions and 54 deletions
@ -0,0 +1,251 @@ |
|||||
|
// -----------------------------------------------------------------------
|
||||
|
// <copyright file="InteractiveTests.cs" company="Steven Kirk">
|
||||
|
// Copyright 2014 MIT Licence. See licence.md for more information.
|
||||
|
// </copyright>
|
||||
|
// -----------------------------------------------------------------------
|
||||
|
|
||||
|
namespace Perspex.Interactive.UnitTests |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Perspex.Collections; |
||||
|
using Perspex.Interactivity; |
||||
|
using Perspex.VisualTree; |
||||
|
using Xunit; |
||||
|
|
||||
|
public class InteractiveTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Direct_Event_Should_Go_Straight_To_Source() |
||||
|
{ |
||||
|
var ev = new RoutedEvent("test", RoutingStrategies.Direct, typeof(RoutedEventArgs), typeof(TestInteractive)); |
||||
|
var invoked = new List<string>(); |
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Id); |
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Direct); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.Equal(new[] { "2b" }, invoked); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Direct_Event_Should_Have_Route_Set_To_Direct() |
||||
|
{ |
||||
|
var ev = new RoutedEvent("test", RoutingStrategies.Direct, typeof(RoutedEventArgs), typeof(TestInteractive)); |
||||
|
bool called = false; |
||||
|
|
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => |
||||
|
{ |
||||
|
Assert.Equal(RoutingStrategies.Direct, e.Route); |
||||
|
called = true; |
||||
|
}; |
||||
|
|
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Direct); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.True(called); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Bubbling_Event_Should_Bubble_Up() |
||||
|
{ |
||||
|
var ev = new RoutedEvent("test", RoutingStrategies.Bubble, typeof(RoutedEventArgs), typeof(TestInteractive)); |
||||
|
var invoked = new List<string>(); |
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Id); |
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.Equal(new[] { "2b", "1" }, invoked); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Tunneling_Event_Should_Tunnel() |
||||
|
{ |
||||
|
var ev = new RoutedEvent("test", RoutingStrategies.Tunnel, typeof(RoutedEventArgs), typeof(TestInteractive)); |
||||
|
var invoked = new List<string>(); |
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Id); |
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.Equal(new[] { "1", "2b" }, invoked); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Tunneling_Bubbling_Event_Should_Tunnel_Then_Bubble_Up() |
||||
|
{ |
||||
|
var ev = new RoutedEvent( |
||||
|
"test", |
||||
|
RoutingStrategies.Bubble | RoutingStrategies.Tunnel, |
||||
|
typeof(RoutedEventArgs), |
||||
|
typeof(TestInteractive)); |
||||
|
var invoked = new List<string>(); |
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(((TestInteractive)s).Id); |
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.Equal(new[] { "1", "2b", "2b", "1" }, invoked); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Events_Should_Have_Route_Set() |
||||
|
{ |
||||
|
var ev = new RoutedEvent( |
||||
|
"test", |
||||
|
RoutingStrategies.Bubble | RoutingStrategies.Tunnel, |
||||
|
typeof(RoutedEventArgs), |
||||
|
typeof(TestInteractive)); |
||||
|
var invoked = new List<RoutingStrategies>(); |
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => invoked.Add(e.Route); |
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.Equal(new[] |
||||
|
{ |
||||
|
RoutingStrategies.Tunnel, |
||||
|
RoutingStrategies.Tunnel, |
||||
|
RoutingStrategies.Bubble, |
||||
|
RoutingStrategies.Bubble, |
||||
|
}, |
||||
|
invoked); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Direct_Subscription_Should_Not_Catch_Tunneling_Or_Bubbling() |
||||
|
{ |
||||
|
var ev = new RoutedEvent( |
||||
|
"test", |
||||
|
RoutingStrategies.Bubble | RoutingStrategies.Tunnel, |
||||
|
typeof(RoutedEventArgs), |
||||
|
typeof(TestInteractive)); |
||||
|
var count = 0; |
||||
|
|
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => |
||||
|
{ |
||||
|
++count; |
||||
|
}; |
||||
|
|
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Direct); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.Equal(0, count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Bubbling_Subscription_Should_Not_Catch_Tunneling() |
||||
|
{ |
||||
|
var ev = new RoutedEvent( |
||||
|
"test", |
||||
|
RoutingStrategies.Bubble | RoutingStrategies.Tunnel, |
||||
|
typeof(RoutedEventArgs), |
||||
|
typeof(TestInteractive)); |
||||
|
var count = 0; |
||||
|
|
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => |
||||
|
{ |
||||
|
Assert.Equal(RoutingStrategies.Bubble, e.Route); |
||||
|
++count; |
||||
|
}; |
||||
|
|
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Bubble); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.Equal(2, count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Tunneling_Subscription_Should_Not_Catch_Bubbling() |
||||
|
{ |
||||
|
var ev = new RoutedEvent( |
||||
|
"test", |
||||
|
RoutingStrategies.Bubble | RoutingStrategies.Tunnel, |
||||
|
typeof(RoutedEventArgs), |
||||
|
typeof(TestInteractive)); |
||||
|
var count = 0; |
||||
|
|
||||
|
EventHandler<RoutedEventArgs> handler = (s, e) => |
||||
|
{ |
||||
|
Assert.Equal(RoutingStrategies.Tunnel, e.Route); |
||||
|
++count; |
||||
|
}; |
||||
|
|
||||
|
var target = this.CreateTree(ev, handler, RoutingStrategies.Tunnel); |
||||
|
|
||||
|
var args = new RoutedEventArgs(ev, target); |
||||
|
target.RaiseEvent(args); |
||||
|
|
||||
|
Assert.Equal(2, count); |
||||
|
} |
||||
|
|
||||
|
private TestInteractive CreateTree( |
||||
|
RoutedEvent ev, |
||||
|
EventHandler<RoutedEventArgs> handler, |
||||
|
RoutingStrategies handlerRoutes) |
||||
|
{ |
||||
|
TestInteractive target; |
||||
|
|
||||
|
var tree = new TestInteractive |
||||
|
{ |
||||
|
Id = "1", |
||||
|
Children = new[] |
||||
|
{ |
||||
|
new TestInteractive |
||||
|
{ |
||||
|
Id = "2a", |
||||
|
}, |
||||
|
(target = new TestInteractive |
||||
|
{ |
||||
|
Id = "2b", |
||||
|
Children = new[] |
||||
|
{ |
||||
|
new TestInteractive |
||||
|
{ |
||||
|
Id = "3", |
||||
|
}, |
||||
|
}, |
||||
|
}), |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
foreach (var i in tree.GetSelfAndVisualDescendents().Cast<Interactive>()) |
||||
|
{ |
||||
|
i.AddHandler(ev, handler, handlerRoutes, false); |
||||
|
} |
||||
|
|
||||
|
return target; |
||||
|
} |
||||
|
|
||||
|
private class TestInteractive : Interactive |
||||
|
{ |
||||
|
public string Id { get; set; } |
||||
|
|
||||
|
public IEnumerable<IVisual> Children |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return ((IVisual)this).VisualChildren.AsEnumerable(); |
||||
|
} |
||||
|
|
||||
|
set |
||||
|
{ |
||||
|
this.AddVisualChildren(value.Cast<Visual>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,99 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<Import Project="..\packages\xunit.runner.visualstudio.2.0.0-rc1-build1030\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\packages\xunit.runner.visualstudio.2.0.0-rc1-build1030\build\net20\xunit.runner.visualstudio.props')" /> |
||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
||||
|
<PropertyGroup> |
||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||
|
<ProjectGuid>{08478EF5-44E8-42E9-92D6-15E00EC038D8}</ProjectGuid> |
||||
|
<OutputType>Library</OutputType> |
||||
|
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||
|
<RootNamespace>Perspex.Interactive.UnitTests</RootNamespace> |
||||
|
<AssemblyName>Perspex.Interactive.UnitTests</AssemblyName> |
||||
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
||||
|
<FileAlignment>512</FileAlignment> |
||||
|
<NuGetPackageImportStamp>ff1a0665</NuGetPackageImportStamp> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||
|
<DebugSymbols>true</DebugSymbols> |
||||
|
<DebugType>full</DebugType> |
||||
|
<Optimize>false</Optimize> |
||||
|
<OutputPath>bin\Debug\</OutputPath> |
||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
|
<ErrorReport>prompt</ErrorReport> |
||||
|
<WarningLevel>4</WarningLevel> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||
|
<DebugType>pdbonly</DebugType> |
||||
|
<Optimize>true</Optimize> |
||||
|
<OutputPath>bin\Release\</OutputPath> |
||||
|
<DefineConstants>TRACE</DefineConstants> |
||||
|
<ErrorReport>prompt</ErrorReport> |
||||
|
<WarningLevel>4</WarningLevel> |
||||
|
</PropertyGroup> |
||||
|
<ItemGroup> |
||||
|
<Reference Include="Splat"> |
||||
|
<HintPath>..\packages\Splat.1.6.0\lib\Net45\Splat.dll</HintPath> |
||||
|
</Reference> |
||||
|
<Reference Include="System" /> |
||||
|
<Reference Include="System.Core" /> |
||||
|
<Reference Include="System.Xml.Linq" /> |
||||
|
<Reference Include="System.Data.DataSetExtensions" /> |
||||
|
<Reference Include="Microsoft.CSharp" /> |
||||
|
<Reference Include="System.Data" /> |
||||
|
<Reference Include="System.Xml" /> |
||||
|
<Reference Include="xunit"> |
||||
|
<HintPath>..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath> |
||||
|
</Reference> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<Compile Include="InteractiveTests.cs" /> |
||||
|
<Compile Include="Properties\AssemblyInfo.cs" /> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<None Include="packages.config" /> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\NGenerics\NGenerics.csproj"> |
||||
|
<Project>{415e048e-4611-4815-9cf2-d774e29079ac}</Project> |
||||
|
<Name>NGenerics</Name> |
||||
|
</ProjectReference> |
||||
|
<ProjectReference Include="..\Perspex.Animation\Perspex.Animation.csproj"> |
||||
|
<Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project> |
||||
|
<Name>Perspex.Animation</Name> |
||||
|
</ProjectReference> |
||||
|
<ProjectReference Include="..\Perspex.Base\Perspex.Base.csproj"> |
||||
|
<Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project> |
||||
|
<Name>Perspex.Base</Name> |
||||
|
</ProjectReference> |
||||
|
<ProjectReference Include="..\Perspex.Interactivity\Perspex.Interactivity.csproj"> |
||||
|
<Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project> |
||||
|
<Name>Perspex.Interactivity</Name> |
||||
|
</ProjectReference> |
||||
|
<ProjectReference Include="..\Perspex.Layout\Perspex.Layout.csproj"> |
||||
|
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project> |
||||
|
<Name>Perspex.Layout</Name> |
||||
|
</ProjectReference> |
||||
|
<ProjectReference Include="..\Perspex.SceneGraph\Perspex.SceneGraph.csproj"> |
||||
|
<Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project> |
||||
|
<Name>Perspex.SceneGraph</Name> |
||||
|
</ProjectReference> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> |
||||
|
</ItemGroup> |
||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> |
||||
|
<PropertyGroup> |
||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> |
||||
|
</PropertyGroup> |
||||
|
<Error Condition="!Exists('..\packages\xunit.runner.visualstudio.2.0.0-rc1-build1030\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.runner.visualstudio.2.0.0-rc1-build1030\build\net20\xunit.runner.visualstudio.props'))" /> |
||||
|
</Target> |
||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
||||
|
Other similar extension points exist, see Microsoft.Common.targets. |
||||
|
<Target Name="BeforeBuild"> |
||||
|
</Target> |
||||
|
<Target Name="AfterBuild"> |
||||
|
</Target> |
||||
|
--> |
||||
|
</Project> |
||||
@ -0,0 +1,36 @@ |
|||||
|
using System.Reflection; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
// General Information about an assembly is controlled through the following
|
||||
|
// set of attributes. Change these attribute values to modify the information
|
||||
|
// associated with an assembly.
|
||||
|
[assembly: AssemblyTitle("Perspex.Interactive.UnitTests")] |
||||
|
[assembly: AssemblyDescription("")] |
||||
|
[assembly: AssemblyConfiguration("")] |
||||
|
[assembly: AssemblyCompany("")] |
||||
|
[assembly: AssemblyProduct("Perspex.Interactive.UnitTests")] |
||||
|
[assembly: AssemblyCopyright("Copyright © 2015")] |
||||
|
[assembly: AssemblyTrademark("")] |
||||
|
[assembly: AssemblyCulture("")] |
||||
|
|
||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
|
// to COM components. If you need to access a type in this assembly from
|
||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||
|
[assembly: ComVisible(false)] |
||||
|
|
||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
|
[assembly: Guid("08478ef5-44e8-42e9-92d6-15e00ec038d8")] |
||||
|
|
||||
|
// Version information for an assembly consists of the following four values:
|
||||
|
//
|
||||
|
// Major Version
|
||||
|
// Minor Version
|
||||
|
// Build Number
|
||||
|
// Revision
|
||||
|
//
|
||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
|
// by using the '*' as shown below:
|
||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||
|
[assembly: AssemblyVersion("1.0.0.0")] |
||||
|
[assembly: AssemblyFileVersion("1.0.0.0")] |
||||
@ -0,0 +1,6 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<packages> |
||||
|
<package id="Splat" version="1.6.0" targetFramework="net45" /> |
||||
|
<package id="xunit" version="1.9.2" targetFramework="net45" /> |
||||
|
<package id="xunit.runner.visualstudio" version="2.0.0-rc1-build1030" targetFramework="net45" /> |
||||
|
</packages> |
||||
Loading…
Reference in new issue