diff --git a/Perspex.sln b/Perspex.sln index 4952c2b257..61fda99a60 100644 --- a/Perspex.sln +++ b/Perspex.sln @@ -90,6 +90,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Cairo", "src\Gtk\Pe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.ReactiveUI", "src\Perspex.ReactiveUI\Perspex.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Markup.Xaml.UnitTests", "Tests\Perspex.Markup.Xaml.UnitTests\Perspex.Markup.Xaml.UnitTests.csproj", "{99135EAB-653D-47E4-A378-C96E1278CA44}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -212,6 +214,10 @@ Global {6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Debug|Any CPU.Build.0 = Debug|Any CPU {6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Release|Any CPU.ActiveCfg = Release|Any CPU {6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Release|Any CPU.Build.0 = Release|Any CPU + {99135EAB-653D-47E4-A378-C96E1278CA44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99135EAB-653D-47E4-A378-C96E1278CA44}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99135EAB-653D-47E4-A378-C96E1278CA44}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99135EAB-653D-47E4-A378-C96E1278CA44}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -234,5 +240,6 @@ Global {78CAFE33-DBEB-4132-8A28-81CFE8A4933C} = {9B9E3891-2366-4253-A952-D08BCEB71098} {54F237D5-A70A-4752-9656-0C70B1A7B047} = {B9894058-278A-46B5-B6ED-AD613FCC03B3} {FB05AC90-89BA-4F2F-A924-F37875FB547C} = {B9894058-278A-46B5-B6ED-AD613FCC03B3} + {99135EAB-653D-47E4-A378-C96E1278CA44} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} EndGlobalSection EndGlobal diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/BinderTest.cs b/Tests/Perspex.Markup.Xaml.UnitTests/BinderTest.cs new file mode 100644 index 0000000000..feea7342aa --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/BinderTest.cs @@ -0,0 +1,24 @@ +namespace Perspex.Xaml.Base.UnitTest +{ + using System; + using Moq; + using Markup.Xaml.DataBinding; + using OmniXaml.TypeConversion; + using Xunit; + + public class BinderTest + { + [Fact] + public void NullTarget_Throws() + { + var typeConverter = new Mock(); + var perspexPropertyBinder = new PerspexPropertyBinder(typeConverter.Object); + var bindingDefinitionBuilder = new BindingDefinitionBuilder(); + var binding = bindingDefinitionBuilder + .WithNullTarget() + .Build(); + + var exception = Assert.Throws(() => perspexPropertyBinder.Create(binding)); + } + } +} diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/BindingDefinitionBuilder.cs b/Tests/Perspex.Markup.Xaml.UnitTests/BindingDefinitionBuilder.cs new file mode 100644 index 0000000000..08c919341d --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/BindingDefinitionBuilder.cs @@ -0,0 +1,37 @@ +using System; + +namespace Perspex.Xaml.Base.UnitTest +{ + using Controls; + using Markup.Xaml.DataBinding; + using Markup.Xaml.DataBinding.ChangeTracking; + + public class BindingDefinitionBuilder + { + private readonly BindingMode bindingMode; + private readonly PropertyPath sourcePropertyPath; + private Control target; + private PerspexProperty targetProperty; + + public BindingDefinitionBuilder() + { + bindingMode = BindingMode.Default; + sourcePropertyPath = new PropertyPath(string.Empty); + } + + public BindingDefinitionBuilder WithNullTarget() + { + target = null; + return this; + } + + public XamlBindingDefinition Build() + { + return new XamlBindingDefinition( + bindingMode: bindingMode, + sourcePropertyPath: sourcePropertyPath, + target: target, + targetProperty: targetProperty); + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/ChangeBranchTest.cs b/Tests/Perspex.Markup.Xaml.UnitTests/ChangeBranchTest.cs new file mode 100644 index 0000000000..74aa0b9db3 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/ChangeBranchTest.cs @@ -0,0 +1,69 @@ +namespace Perspex.Xaml.Base.UnitTest +{ + using System; + using Markup.Xaml.DataBinding.ChangeTracking; + using SampleModel; + using Xunit; + + public class ChangeBranchTest + { + [Fact] + public void GetValueOfMemberOfStruct() + { + var level1 = new Level1(); + level1.DateTime = new DateTime(1, 2, 3, 4, 5, 6); + + var branch = new ObservablePropertyBranch(level1, new PropertyPath("DateTime.Minute")); + + var day = branch.Value; + Assert.Equal(day, branch.Value); + } + + [Fact] + public void OnePathOnly() + { + var level1 = new Level1(); + + var branch = new ObservablePropertyBranch(level1, new PropertyPath("Text")); + var newValue = "Hey now"; + branch.Value = newValue; + + Assert.Equal(level1.Text, newValue); + } + + [Fact] + public void SettingValueToUnderlyingProperty_ChangesTheValueInBranch() + { + var level1 = new Level1(); + + level1.Level2.Level3.Property = 3; + + var branch = new ObservablePropertyBranch(level1, new PropertyPath("Level2.Level3.Property")); + Assert.Equal(3, branch.Value); + } + + [Fact] + public void SettingValueToBranch_ChangesTheUnderlyingProperty() + { + var level1 = new Level1(); + + var branch = new ObservablePropertyBranch(level1, new PropertyPath("Level2.Level3.Property")); + branch.Value = 3; + Assert.Equal(3, level1.Level2.Level3.Property); + } + + [Fact] + public void SettingValueProperty_RaisesChangeInBranch() + { + var level1 = new Level1(); + + var branch = new ObservablePropertyBranch(level1, new PropertyPath("Level2.Level3.Property")); + bool hit = false; + ObservableExtensions.Subscribe(branch.Changed, _ => hit = true); + + level1.Level2.Level3.Property = 3; + + Assert.True(hit); + } + } +} diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/DataContextChangeSynchronizerTest.cs b/Tests/Perspex.Markup.Xaml.UnitTests/DataContextChangeSynchronizerTest.cs new file mode 100644 index 0000000000..284227d0ed --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/DataContextChangeSynchronizerTest.cs @@ -0,0 +1,105 @@ +namespace Perspex.Xaml.Base.UnitTest +{ + using System; + using Controls; + using GitHubClient.ViewModels; + using Markup.Xaml.DataBinding; + using Markup.Xaml.DataBinding.ChangeTracking; + using OmniXaml.Builder; + using OmniXaml.TypeConversion; + using OmniXaml.TypeConversion.BuiltInConverters; + using SampleModel; + using Xunit; + + public class DataContextChangeSynchronizerTest + { + private TypeConverterProvider repo; + private SamplePerspexObject guiObject; + private ViewModelMock viewModel; + + public DataContextChangeSynchronizerTest() + { + repo = new TypeConverterProvider(); + guiObject = new SamplePerspexObject(); + viewModel = new ViewModelMock(); + } + + [Fact] + public void SameTypesFromUIToModel() + { + var synchronizer = new DataContextChangeSynchronizer(guiObject, SamplePerspexObject.IntProperty, new PropertyPath("IntProp"), viewModel, repo); + synchronizer.SubscribeModelToUI(); + + const int someValue = 4; + guiObject.Int = someValue; + + Assert.Equal(someValue, viewModel.IntProp); + } + + [Fact] + public void DifferentTypesFromUIToModel() + { + var synchronizer = new DataContextChangeSynchronizer(guiObject, SamplePerspexObject.StringProperty, new PropertyPath("IntProp"), viewModel, repo); + synchronizer.SubscribeModelToUI(); + + guiObject.String = "2"; + + Assert.Equal(2, viewModel.IntProp); + } + + [Fact] + public void DifferentTypesAndNonConvertibleValueFromUIToModel() + { + var synchronizer = new DataContextChangeSynchronizer(guiObject, SamplePerspexObject.StringProperty, new PropertyPath("IntProp"), viewModel, repo); + synchronizer.SubscribeModelToUI(); + + guiObject.String = ""; + + Assert.Equal(default(int), viewModel.IntProp); + } + + + [Fact] + public void DifferentTypesFromModelToUI() + { + var synchronizer = new DataContextChangeSynchronizer(guiObject, SamplePerspexObject.StringProperty, new PropertyPath("IntProp"), viewModel, repo); + synchronizer.SubscribeUIToModel(); + + viewModel.IntProp = 2; + + Assert.Equal("2", guiObject.String); + } + + [Fact] + public void SameTypesFromModelToUI() + { + var synchronizer = new DataContextChangeSynchronizer(guiObject, SamplePerspexObject.IntProperty, new PropertyPath("IntProp"), viewModel, repo); + synchronizer.SubscribeUIToModel(); + + viewModel.IntProp = 2; + + Assert.Equal(2, guiObject.Int); + } + + [Fact] + public void GrokysTest() + { + var mainWindowViewModel = new MainWindowViewModel(); + var contentControl = new ContentControl(); + + var synchronizer = new DataContextChangeSynchronizer( + contentControl, + ContentControl.ContentProperty, + new PropertyPath("Content"), + mainWindowViewModel, + repo); + + synchronizer.SubscribeUIToModel(); + + var logInViewModel = new LogInViewModel(); + mainWindowViewModel.Content = logInViewModel; + + Assert.Equal(logInViewModel, contentControl.Content); + } + } +} diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj b/Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj new file mode 100644 index 0000000000..67c0aac88f --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj @@ -0,0 +1,212 @@ + + + + + + Debug + AnyCPU + {99135EAB-653D-47E4-A378-C96E1278CA44} + Library + Properties + Perspex.Xaml.Base.UnitTest + Perspex.Xaml.Base.UnitTest + v4.5.1 + 512 + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + SAK + SAK + SAK + SAK + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\packages\Glass.0.1.0\lib\portable-net45+win+Xamarin.iOS10+MonoAndroid10+MonoTouch10\Glass.dll + True + + + ..\..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll + True + + + ..\..\packages\Octokit.0.14.0\lib\net45\Octokit.dll + + + ..\..\packages\OmniXaml.0.1.0\lib\portable-net45+win+Xamarin.iOS10+MonoAndroid10+MonoTouch10\OmniXaml.dll + + + ..\..\packages\Splat.1.6.1\lib\Net45\Splat.dll + True + + + + ..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll + True + + + ..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll + True + + + ..\..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll + True + + + ..\..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll + True + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {3E53A01A-B331-47F3-B828-4A5717E77A24} + Perspex.Markup.Xaml + + + {415e048e-4611-4815-9cf2-d774e29079ac} + NGenerics + + + {d211e587-d8bc-45b9-95a4-f297c8fa5200} + Perspex.Animation + + + {B09B78D8-9B26-48B0-9149-D64A2F120F3F} + Perspex.Base + + + {d2221c82-4a25-4583-9b43-d791e3f6820c} + Perspex.Controls + + + {62024b2d-53eb-4638-b26b-85eeaa54866e} + Perspex.Input + + + {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b} + Perspex.Interactivity + + + {42472427-4774-4c81-8aff-9f27b8e31721} + Perspex.Layout + + + {6417b24e-49c2-4985-8db2-3ab9d898ec91} + Perspex.ReactiveUI + + + {eb582467-6abb-43a1-b052-e981ba910e3a} + Perspex.SceneGraph + + + {f1baa01a-f176-4c6a-b39d-5b40bb1b148f} + Perspex.Styling + + + {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} + Perspex.Themes.Default + + + + + + + + + + + + + False + + + False + + + False + + + False + + + + + + + + + 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}. + + + + + + \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/Properties/AssemblyInfo.cs b/Tests/Perspex.Markup.Xaml.UnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..959388e56d --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Reflection; + +[assembly: AssemblyTitle("Perspex.Markup.Xaml.UnitTests")] \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/PropertyMountPointTest.cs b/Tests/Perspex.Markup.Xaml.UnitTests/PropertyMountPointTest.cs new file mode 100644 index 0000000000..c94d13037d --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/PropertyMountPointTest.cs @@ -0,0 +1,15 @@ +namespace Perspex.Xaml.Base.UnitTest +{ + using Markup.Xaml.DataBinding.ChangeTracking; + using System; + using Xunit; + + public class PropertyMountPointTest + { + [Fact] + public void SourceAndPathAreNull() + { + Assert.Throws(() => new PropertyMountPoint(null, null)); + } + } +} diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level1.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level1.cs new file mode 100644 index 0000000000..ddc41ef2a0 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level1.cs @@ -0,0 +1,41 @@ +using System; + +namespace Perspex.Xaml.Base.UnitTest.SampleModel +{ + public class Level1 : PropertyChangeNotifier + { + private Level2 level2 = new Level2(); + private DateTime dateTime; + private string text; + + public Level2 Level2 + { + get { return level2; } + set + { + level2 = value; + OnPropertyChanged(); + } + } + + public string Text + { + get { return text; } + set + { + text = value; + OnPropertyChanged(); + } + } + + public DateTime DateTime + { + get { return dateTime; } + set + { + dateTime = value; + OnPropertyChanged(); + } + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level2.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level2.cs new file mode 100644 index 0000000000..6a276dc923 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level2.cs @@ -0,0 +1,17 @@ +namespace Perspex.Xaml.Base.UnitTest.SampleModel +{ + public class Level2 : PropertyChangeNotifier + { + private Level3 level3 = new Level3(); + + public Level3 Level3 + { + get { return level3; } + set + { + level3 = value; + OnPropertyChanged(); + } + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level3.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level3.cs new file mode 100644 index 0000000000..132d33ee89 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level3.cs @@ -0,0 +1,17 @@ +namespace Perspex.Xaml.Base.UnitTest.SampleModel +{ + public class Level3 : PropertyChangeNotifier + { + private int property = 10; + + public int Property + { + get { return property; } + set + { + property = value; + OnPropertyChanged(); + } + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/LogInViewModel.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/LogInViewModel.cs new file mode 100644 index 0000000000..144d6680cd --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/LogInViewModel.cs @@ -0,0 +1,35 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2015 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Xaml.Base.UnitTest.SampleModel +{ + using ReactiveUI; + + public class LogInViewModel : ReactiveObject + { + private string username; + + public LogInViewModel() + { + this.OkCommand = ReactiveCommand.Create( + this.WhenAnyValue( + x => x.Username, + x => !string.IsNullOrWhiteSpace(x))); + } + + public string Username + { + get { return this.username; } + set { this.RaiseAndSetIfChanged(ref this.username, value); } + } + + public ReactiveCommand OkCommand + { + get; + private set; + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/MainWindowViewModel.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/MainWindowViewModel.cs new file mode 100644 index 0000000000..2323916aa4 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/MainWindowViewModel.cs @@ -0,0 +1,44 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2015 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace GitHubClient.ViewModels +{ + using System; + using Perspex.Xaml.Base.UnitTest.SampleModel; + using ReactiveUI; + + public class MainWindowViewModel : ReactiveObject + { + private object content; + + private LogInViewModel login; + + public MainWindowViewModel() + { + this.ShowLogin(); + } + + public object Content + { + get { return this.content; } + set { this.RaiseAndSetIfChanged(ref this.content, value); } + } + + private void ShowLogin() + { + this.login = new LogInViewModel(); + this.login.OkCommand.Subscribe(_ => this.ShowRepositories()); + this.Content = this.login; + } + + private void ShowRepositories() + { + var vm = new UserRepositoriesViewModel(); + var task = vm.Load(this.login.Username); + this.Content = vm; + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/PropertyChangeNotifier.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/PropertyChangeNotifier.cs new file mode 100644 index 0000000000..10a8086a8c --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/PropertyChangeNotifier.cs @@ -0,0 +1,15 @@ +namespace Perspex.Xaml.Base.UnitTest.SampleModel +{ + using System.ComponentModel; + using System.Runtime.CompilerServices; + + public abstract class PropertyChangeNotifier : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Repository.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Repository.cs new file mode 100644 index 0000000000..fda8dd3ace --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Repository.cs @@ -0,0 +1,17 @@ +namespace GitHubClient.ViewModels +{ + public class Repository + { + private readonly string name; + + public Repository(string name) + { + this.name = name; + } + + public string Name + { + get { return name; } + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/UserRepositoriesViewModel.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/UserRepositoriesViewModel.cs new file mode 100644 index 0000000000..11007edd5b --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SampleModel/UserRepositoriesViewModel.cs @@ -0,0 +1,29 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2015 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Xaml.Base.UnitTest.SampleModel +{ + using System.Collections.Generic; + using System.Threading.Tasks; + using GitHubClient.ViewModels; + using ReactiveUI; + + public class UserRepositoriesViewModel : ReactiveObject + { + private IReadOnlyList repositories; + + public async Task Load(string username) + { + this.Repositories = await new Task>(() => new List { new Repository("Blah"), new Repository("Bleh") }); + } + + public IReadOnlyList Repositories + { + get { return this.repositories; } + private set { this.RaiseAndSetIfChanged(ref this.repositories, value); } + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/SamplePerspexObject.cs b/Tests/Perspex.Markup.Xaml.UnitTests/SamplePerspexObject.cs new file mode 100644 index 0000000000..c568be6585 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/SamplePerspexObject.cs @@ -0,0 +1,25 @@ +using System; + +namespace Perspex.Xaml.Base.UnitTest +{ + internal class SamplePerspexObject : PerspexObject + { + public static readonly PerspexProperty StringProperty = + PerspexProperty.Register("StrProp", string.Empty); + + public static readonly PerspexProperty IntProperty = + PerspexProperty.Register("IntProp"); + + public int Int + { + get { return GetValue(IntProperty); } + set { this.SetValue(IntProperty, value); } + } + + public string String + { + get { return GetValue(StringProperty); } + set { this.SetValue(StringProperty, value); } + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/TypeProviderMock.cs b/Tests/Perspex.Markup.Xaml.UnitTests/TypeProviderMock.cs new file mode 100644 index 0000000000..2c0e1093cf --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/TypeProviderMock.cs @@ -0,0 +1,35 @@ +namespace Perspex.Xaml.Base.UnitTest +{ + using OmniXaml; + using System; + + class TypeProviderMock : ITypeProvider + { + private readonly string typeName; + private readonly string clrNamespace; + private readonly string assemblyName; + private readonly Type typeToReturn; + + public TypeProviderMock(string typeName, string clrNamespace, string assemblyName, Type typeToReturn) + { + this.typeName = typeName; + this.clrNamespace = clrNamespace; + this.assemblyName = assemblyName; + this.typeToReturn = typeToReturn; + } + + public TypeProviderMock() + { + } + + public Type GetType(string typeName, string clrNamespace, string assemblyName) + { + if (this.typeName == typeName && this.clrNamespace == clrNamespace && this.assemblyName == assemblyName) + { + return typeToReturn; + } + + throw new TypeNotFoundException("The Type cannot be found"); + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/ViewModelMock.cs b/Tests/Perspex.Markup.Xaml.UnitTests/ViewModelMock.cs new file mode 100644 index 0000000000..dda8111ce1 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/ViewModelMock.cs @@ -0,0 +1,38 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace Perspex.Xaml.Base.UnitTest +{ + class ViewModelMock : INotifyPropertyChanged + { + private string str; + private int intProp; + + public int IntProp + { + get { return intProp; } + set + { + intProp = value; + OnPropertyChanged(); + } + } + + public string StrProp + { + get { return str; } + set + { + str = value; + OnPropertyChanged(); + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + private void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/XamlBindingTest.cs b/Tests/Perspex.Markup.Xaml.UnitTests/XamlBindingTest.cs new file mode 100644 index 0000000000..fd92757e91 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/XamlBindingTest.cs @@ -0,0 +1,18 @@ +namespace Perspex.Xaml.Base.UnitTest +{ + using Moq; + using Markup.Xaml.DataBinding; + using OmniXaml.TypeConversion; + using Xunit; + + public class XamlBindingTest + { + [Fact] + public void TestNullDataContext() + { + var t = new Mock(); + var sut = new XamlBinding(t.Object); + sut.Bind(null); + } + } +} diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/packages.config b/Tests/Perspex.Markup.Xaml.UnitTests/packages.config new file mode 100644 index 0000000000..8268799d3b --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/packages.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Markup/Perspex.Markup.Xaml/DataBinding/ChangeTracking/PropertyPath.cs b/src/Markup/Perspex.Markup.Xaml/DataBinding/ChangeTracking/PropertyPath.cs index 73fe67f051..0fbd27ca61 100644 --- a/src/Markup/Perspex.Markup.Xaml/DataBinding/ChangeTracking/PropertyPath.cs +++ b/src/Markup/Perspex.Markup.Xaml/DataBinding/ChangeTracking/PropertyPath.cs @@ -30,5 +30,10 @@ namespace Perspex.Markup.Xaml.DataBinding.ChangeTracking { return new PropertyPath(this); } + + public override string ToString() + { + return string.Join(".", this.chunks); + } } } \ No newline at end of file