diff --git a/.gitmodules b/.gitmodules index 24ccfc3259..93467688c1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ path = src/Perspex.HtmlRenderer/external url = https://github.com/Perspex/HTML-Renderer.git branch = perspex-pcl +[submodule "src/Markup/Perspex.Markup.Xaml/OmniXAML"] + path = src/Markup/Perspex.Markup.Xaml/OmniXAML + url = https://github.com/SuperJMN/OmniXAML.git diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs b/Tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs new file mode 100644 index 0000000000..3193c0d459 --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs @@ -0,0 +1,63 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using Moq; +using OmniXaml; +using OmniXaml.TypeConversion; +using OmniXaml.Typing; +using Perspex.Markup.Xaml.Converters; +using Xunit; + +namespace Perspex.Markup.Xaml.UnitTests.Converters +{ + public class PerspexPropertyConverterTest + { + public PerspexPropertyConverterTest() + { + // Ensure properties are registered. + var foo = Class1.FooProperty; + var attached = AttachedOwner.AttachedProperty; + } + + [Fact] + public void ConvertFrom_Finds_Fully_Qualified_Property() + { + var target = new PerspexPropertyConverter(); + var context = CreateContext(); + var result = target.ConvertFrom(context, null, "Class1.Foo"); + } + + [Fact] + public void ConvertFrom_Finds_Attached_Property() + { + var target = new PerspexPropertyConverter(); + var context = CreateContext(); + var result = target.ConvertFrom(context, null, "AttachedOwner.Attached"); + } + + private IXamlTypeConverterContext CreateContext() + { + var context = new Mock(); + var typeRepository = new Mock(); + var featureProvider = new Mock(); + var class1XamlType = new XamlType(typeof(Class1), typeRepository.Object, null, featureProvider.Object); + var attachedOwnerXamlType = new XamlType(typeof(AttachedOwner), typeRepository.Object, null, featureProvider.Object); + context.Setup(x => x.TypeRepository).Returns(typeRepository.Object); + typeRepository.Setup(x => x.GetByQualifiedName("Class1")).Returns(class1XamlType); + typeRepository.Setup(x => x.GetByQualifiedName("AttachedOwner")).Returns(attachedOwnerXamlType); + return context.Object; + } + + private class Class1 : PerspexObject + { + public static readonly PerspexProperty FooProperty = + PerspexProperty.Register("Foo"); + } + + private class AttachedOwner + { + public static readonly PerspexProperty AttachedProperty = + PerspexProperty.RegisterAttached("Attached"); + } + } +} diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/Parsers/SelectorGrammarTests.cs b/Tests/Perspex.Markup.Xaml.UnitTests/Parsers/SelectorGrammarTests.cs new file mode 100644 index 0000000000..58bbb465ac --- /dev/null +++ b/Tests/Perspex.Markup.Xaml.UnitTests/Parsers/SelectorGrammarTests.cs @@ -0,0 +1,189 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System.Linq; +using Perspex.Markup.Xaml.Parsers; +using Sprache; +using Xunit; + +namespace Perspex.Xaml.Base.UnitTest.Parsers +{ + public class SelectorGrammarTests + { + [Fact] + public void OfType() + { + var result = SelectorGrammar.Selector.Parse("Button").ToList(); + + Assert.Equal( + new[] { new SelectorGrammar.OfTypeSyntax { TypeName = "Button", Xmlns = null } }, + result); + } + + [Fact] + public void NamespacedOfType() + { + var result = SelectorGrammar.Selector.Parse("x|Button").ToList(); + + Assert.Equal( + new[] { new SelectorGrammar.OfTypeSyntax { TypeName = "Button", Xmlns = "x" } }, + result); + } + + [Fact] + public void Name() + { + var result = SelectorGrammar.Selector.Parse("#foo").ToList(); + + Assert.Equal( + new[] { new SelectorGrammar.NameSyntax { Name = "foo" }, }, + result); + } + + [Fact] + public void OfType_Name() + { + var result = SelectorGrammar.Selector.Parse("Button#foo").ToList(); + + Assert.Equal( + new SelectorGrammar.ISyntax[] + { + new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, + new SelectorGrammar.NameSyntax { Name = "foo" }, + }, + result); + } + + [Fact] + public void Class() + { + var result = SelectorGrammar.Selector.Parse(".foo").ToList(); + + Assert.Equal( + new[] { new SelectorGrammar.ClassSyntax { Class = "foo" } }, + result); + } + + [Fact] + public void Pseudoclass() + { + var result = SelectorGrammar.Selector.Parse(":foo").ToList(); + + Assert.Equal( + new[] { new SelectorGrammar.ClassSyntax { Class = ":foo" } }, + result); + } + + [Fact] + public void OfType_Class() + { + var result = SelectorGrammar.Selector.Parse("Button.foo").ToList(); + + Assert.Equal( + new SelectorGrammar.ISyntax[] + { + new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, + new SelectorGrammar.ClassSyntax { Class = "foo" }, + }, + result); + } + + [Fact] + public void OfType_Child_Class() + { + var result = SelectorGrammar.Selector.Parse("Button < .foo").ToList(); + + Assert.Equal( + new SelectorGrammar.ISyntax[] + { + new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, + new SelectorGrammar.ChildSyntax { }, + new SelectorGrammar.ClassSyntax { Class = "foo" }, + }, + result); + } + + [Fact] + public void OfType_Child_Class_No_Spaces() + { + var result = SelectorGrammar.Selector.Parse("Button<.foo").ToList(); + + Assert.Equal( + new SelectorGrammar.ISyntax[] + { + new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, + new SelectorGrammar.ChildSyntax { }, + new SelectorGrammar.ClassSyntax { Class = "foo" }, + }, + result); + } + + [Fact] + public void OfType_Descendent_Class() + { + var result = SelectorGrammar.Selector.Parse("Button .foo").ToList(); + + Assert.Equal( + new SelectorGrammar.ISyntax[] + { + new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, + new SelectorGrammar.DescendentSyntax { }, + new SelectorGrammar.ClassSyntax { Class = "foo" }, + }, + result); + } + + [Fact] + public void OfType_Template_Class() + { + var result = SelectorGrammar.Selector.Parse("Button /template/ .foo").ToList(); + + Assert.Equal( + new SelectorGrammar.ISyntax[] + { + new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, + new SelectorGrammar.TemplateSyntax { }, + new SelectorGrammar.ClassSyntax { Class = "foo" }, + }, + result); + } + + [Fact] + public void OfType_Property() + { + var result = SelectorGrammar.Selector.Parse("Button[Foo=bar]").ToList(); + + Assert.Equal( + new SelectorGrammar.ISyntax[] + { + new SelectorGrammar.OfTypeSyntax { TypeName = "Button" }, + new SelectorGrammar.PropertySyntax { Property = "Foo", Value = "bar" }, + }, + result); + } + + [Fact] + public void Namespace_Alone_Fails() + { + Assert.Throws(() => SelectorGrammar.Selector.Parse("ns|").ToList()); + } + + [Fact] + public void Dot_Alone_Fails() + { + Assert.Throws(() => SelectorGrammar.Selector.Parse(". dot").ToList()); + } + + [Fact] + public void Invalid_Identifier_Fails() + { + Assert.Throws(() => SelectorGrammar.Selector.Parse("%foo").ToList()); + } + + [Fact] + public void Invalid_Class_Fails() + { + Assert.Throws(() => SelectorGrammar.Selector.Parse(".%foo").ToList()); + } + } +} diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj b/Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj index 67c0aac88f..219251a7f0 100644 --- a/Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj +++ b/Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj @@ -8,8 +8,8 @@ {99135EAB-653D-47E4-A378-C96E1278CA44} Library Properties - Perspex.Xaml.Base.UnitTest - Perspex.Xaml.Base.UnitTest + Perspex.Markup.Xaml.UnitTests + Perspex.Markup.Xaml.UnitTests v4.5.1 512 10.0 @@ -43,10 +43,6 @@ 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 @@ -54,13 +50,14 @@ ..\..\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\Sprache.SuperJMN.2.0.0.50\lib\portable-net451+netcore451+wpa81\Sprache.dll + True + ..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll @@ -102,7 +99,9 @@ + + diff --git a/Tests/Perspex.Markup.Xaml.UnitTests/packages.config b/Tests/Perspex.Markup.Xaml.UnitTests/packages.config index 8268799d3b..64a2d902f9 100644 --- a/Tests/Perspex.Markup.Xaml.UnitTests/packages.config +++ b/Tests/Perspex.Markup.Xaml.UnitTests/packages.config @@ -1,6 +1,5 @@  - @@ -8,6 +7,7 @@ + diff --git a/samples/XamlTestApplication/Views/MainWindow.xaml b/samples/XamlTestApplication/Views/MainWindow.xaml index 96f4db9653..32953306f6 100644 --- a/samples/XamlTestApplication/Views/MainWindow.xaml +++ b/samples/XamlTestApplication/Views/MainWindow.xaml @@ -6,10 +6,15 @@ + + +