Browse Source

More ExpressionObserver tests.

pull/237/head
Steven Kirk 11 years ago
parent
commit
cf3834755d
  1. 4
      src/Markup/Perspex.Markup/Binding/ExpressionNode.cs
  2. 2
      src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs
  3. 78
      tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests.cs
  4. 8
      tests/Perspex.Markup.UnitTests/Binding/NotifyingBase.cs
  5. 1
      tests/Perspex.Markup.UnitTests/Perspex.Markup.UnitTests.csproj

4
src/Markup/Perspex.Markup/Binding/ExpressionNode.cs

@ -35,7 +35,7 @@ namespace Perspex.Markup.Binding
if (_target != null) if (_target != null)
{ {
Subscribe(_target); SubscribeAndUpdate(_target);
} }
else else
{ {
@ -95,7 +95,7 @@ namespace Perspex.Markup.Binding
} }
} }
protected abstract void Subscribe(object target); protected abstract void SubscribeAndUpdate(object target);
protected abstract void Unsubscribe(object target); protected abstract void Unsubscribe(object target);

2
src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs

@ -18,7 +18,7 @@ namespace Perspex.Markup.Binding
public string PropertyName { get; } public string PropertyName { get; }
protected override void Subscribe(object target) protected override void SubscribeAndUpdate(object target)
{ {
var result = ExpressionValue.None; var result = ExpressionValue.None;

78
tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests.cs

@ -63,66 +63,94 @@ namespace Perspex.Markup.UnitTests.Binding
[Fact] [Fact]
public void Should_Track_End_Of_Property_Chain_Changing() public void Should_Track_End_Of_Property_Chain_Changing()
{ {
var data = new Class1 { Class2 = new Class2 { Bar = "bar" } }; var data = new Class1 { Next = new Class2 { Bar = "bar" } };
var target = new ExpressionObserver(data, "Class2.Bar"); var target = new ExpressionObserver(data, "Next.Bar");
var result = new List<object>(); var result = new List<object>();
var sub = target.Subscribe(x => result.Add(x.Value)); var sub = target.Subscribe(x => result.Add(x.Value));
data.Class2.Bar = "baz"; ((Class2)data.Next).Bar = "baz";
Assert.Equal(new[] { "bar", "baz" }, result); Assert.Equal(new[] { "bar", "baz" }, result);
sub.Dispose(); sub.Dispose();
Assert.Equal(0, data.SubscriptionCount); Assert.Equal(0, data.SubscriptionCount);
Assert.Equal(0, data.Class2.SubscriptionCount); Assert.Equal(0, data.Next.SubscriptionCount);
} }
[Fact] [Fact]
public void Should_Track_Middle_Of_Property_Chain_Changing() public void Should_Track_Property_Chain_Changing()
{ {
var data = new Class1 { Class2 = new Class2 { Bar = "bar" } }; var data = new Class1 { Next = new Class2 { Bar = "bar" } };
var target = new ExpressionObserver(data, "Class2.Bar"); var target = new ExpressionObserver(data, "Next.Bar");
var result = new List<object>(); var result = new List<object>();
var sub = target.Subscribe(x => result.Add(x.Value)); var sub = target.Subscribe(x => result.Add(x.Value));
var old = data.Class2; var old = data.Next;
data.Class2 = new Class2 { Bar = "baz" }; data.Next = new Class2 { Bar = "baz" };
Assert.Equal(new[] { "bar", "baz" }, result); Assert.Equal(new[] { "bar", "baz" }, result);
sub.Dispose(); sub.Dispose();
Assert.Equal(0, data.SubscriptionCount); Assert.Equal(0, data.SubscriptionCount);
Assert.Equal(0, data.Class2.SubscriptionCount); Assert.Equal(0, data.Next.SubscriptionCount);
Assert.Equal(0, old.SubscriptionCount); Assert.Equal(0, old.SubscriptionCount);
} }
[Fact] [Fact]
public void Should_Track_Middle_Of_Property_Chain_Breaking_Then_Mending() public void Should_Track_Property_Chain_Breaking_With_Null_Then_Mending()
{ {
var data = new Class1 { Class2 = new Class2 { Bar = "bar" } }; var data = new Class1 { Next = new Class2 { Bar = "bar" } };
var target = new ExpressionObserver(data, "Class2.Bar"); var target = new ExpressionObserver(data, "Next.Bar");
var result = new List<object>(); var result = new List<object>();
var sub = target.Subscribe(x => result.Add(x.Value)); var sub = target.Subscribe(x => result.Add(x.Value));
var old = data.Class2; var old = data.Next;
data.Class2 = null; data.Next = null;
data.Class2 = new Class2 { Bar = "baz" }; data.Next = new Class2 { Bar = "baz" };
Assert.Equal(new[] { "bar", null, "baz" }, result); Assert.Equal(new[] { "bar", null, "baz" }, result);
sub.Dispose(); sub.Dispose();
Assert.Equal(0, data.SubscriptionCount); Assert.Equal(0, data.SubscriptionCount);
Assert.Equal(0, data.Class2.SubscriptionCount); Assert.Equal(0, data.Next.SubscriptionCount);
Assert.Equal(0, old.SubscriptionCount); Assert.Equal(0, old.SubscriptionCount);
} }
[Fact]
public void Should_Track_Property_Chain_Breaking_With_Object_Then_Mending()
{
var data = new Class1 { Next = new Class2 { Bar = "bar" } };
var target = new ExpressionObserver(data, "Next.Bar");
var result = new List<object>();
var sub = target.Subscribe(x => result.Add(x.Value));
var old = data.Next;
var breaking = new WithoutBar();
data.Next = breaking;
data.Next = new Class2 { Bar = "baz" };
Assert.Equal(new[] { "bar", null, "baz" }, result);
sub.Dispose();
Assert.Equal(0, data.SubscriptionCount);
Assert.Equal(0, data.Next.SubscriptionCount);
Assert.Equal(0, breaking.SubscriptionCount);
Assert.Equal(0, old.SubscriptionCount);
}
private interface INext
{
int SubscriptionCount { get; }
}
private class Class1 : NotifyingBase private class Class1 : NotifyingBase
{ {
private string _foo; private string _foo;
private Class2 _class2; private INext _next;
public string Foo public string Foo
{ {
@ -134,18 +162,18 @@ namespace Perspex.Markup.UnitTests.Binding
} }
} }
public Class2 Class2 public INext Next
{ {
get { return _class2; } get { return _next; }
set set
{ {
_class2 = value; _next = value;
RaisePropertyChanged(nameof(Class2)); RaisePropertyChanged(nameof(Next));
} }
} }
} }
private class Class2 : NotifyingBase private class Class2 : NotifyingBase, INext
{ {
private string _bar; private string _bar;
@ -159,5 +187,9 @@ namespace Perspex.Markup.UnitTests.Binding
} }
} }
} }
private class WithoutBar : NotifyingBase, INext
{
}
} }
} }

8
tests/Perspex.Markup.UnitTests/Binding/NotifyingBase.cs

@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.ComponentModel; using System.ComponentModel;
using System.Linq;
namespace Perspex.Markup.UnitTests.Binding namespace Perspex.Markup.UnitTests.Binding
{ {
@ -19,8 +20,11 @@ namespace Perspex.Markup.UnitTests.Binding
remove remove
{ {
_propertyChanged -= value; if (_propertyChanged?.GetInvocationList().Contains(value) == true)
--SubscriptionCount; {
_propertyChanged -= value;
--SubscriptionCount;
}
} }
} }

1
tests/Perspex.Markup.UnitTests/Perspex.Markup.UnitTests.csproj

@ -74,6 +74,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="Binding\ExpressionObserverTests.cs" /> <Compile Include="Binding\ExpressionObserverTests.cs" />
<Compile Include="Binding\ExpressionNodeBuilderTests.cs" /> <Compile Include="Binding\ExpressionNodeBuilderTests.cs" />
<Compile Include="Binding\NotifyingBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Loading…
Cancel
Save