Browse Source

Added failing unit tests for #3590.

Steven Kirk 5 years ago
parent
commit
7345336b9a

+ 131 - 0
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs

@@ -627,6 +627,137 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
             Assert.Equal(0xff506070, brush.Color.ToUint32());
         }
 
+        [Fact]
+        public void Resource_With_DynamicResource_Is_Updated_When_Added_To_Parent()
+        {
+            var xaml = @"
+<UserControl xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
+    <UserControl.Resources>
+        <SolidColorBrush x:Key='brush' Color='{DynamicResource color}'/>
+    </UserControl.Resources>
+
+    <Border Name='border' Background='{DynamicResource brush}'/>
+</UserControl>";
+
+            var loader = new AvaloniaXamlLoader();
+            var userControl = (UserControl)loader.Load(xaml);
+            var border = userControl.FindControl<Border>("border");
+
+            DelayedBinding.ApplyBindings(border);
+
+            var brush = (SolidColorBrush)border.Background;
+            Assert.Equal(0u, brush.Color.ToUint32());
+
+            brush.GetObservable(SolidColorBrush.ColorProperty).Subscribe(_ => { });
+
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var window = new Window
+                {
+                    Resources =
+                    {
+                        { "color", Colors.Red }
+                    },
+                    Content = userControl,
+                };
+
+                window.Show();
+
+                Assert.Equal(Colors.Red, brush.Color);
+            }
+        }
+
+        [Fact]
+        public void MergedDictionary_Resource_With_DynamicResource_Is_Updated_When_Added_To_Parent()
+        {
+            var xaml = @"
+<UserControl xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary>
+                    <SolidColorBrush x:Key='brush' Color='{DynamicResource color}'/>
+                </ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+        </ResourceDictionary>
+    </UserControl.Resources>
+
+    <Border Name='border' Background='{DynamicResource brush}'/>
+</UserControl>";
+
+            var loader = new AvaloniaXamlLoader();
+            var userControl = (UserControl)loader.Load(xaml);
+            var border = userControl.FindControl<Border>("border");
+
+            DelayedBinding.ApplyBindings(border);
+
+            var brush = (SolidColorBrush)border.Background;
+            Assert.Equal(0u, brush.Color.ToUint32());
+
+            brush.GetObservable(SolidColorBrush.ColorProperty).Subscribe(_ => { });
+
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var window = new Window
+                {
+                    Resources =
+                    {
+                        { "color", Colors.Red }
+                    },
+                    Content = userControl,
+                };
+
+                window.Show();
+
+                Assert.Equal(Colors.Red, brush.Color);
+            }
+        }
+
+        [Fact]
+        public void Style_Resource_With_DynamicResource_Is_Updated_When_Added_To_Parent()
+        {
+            var xaml = @"
+<UserControl xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
+    <UserControl.Styles>
+        <Style>
+            <Style.Resources>
+                <SolidColorBrush x:Key='brush' Color='{DynamicResource color}'/>
+            </Style.Resources>
+        </Style>
+    </UserControl.Styles>
+
+    <Border Name='border' Background='{DynamicResource brush}'/>
+</UserControl>";
+
+            var loader = new AvaloniaXamlLoader();
+            var userControl = (UserControl)loader.Load(xaml);
+            var border = userControl.FindControl<Border>("border");
+
+            DelayedBinding.ApplyBindings(border);
+
+            var brush = (SolidColorBrush)border.Background;
+            Assert.Equal(0u, brush.Color.ToUint32());
+
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var window = new Window
+                {
+                    Resources =
+                    {
+                        { "color", Colors.Red }
+                    },
+                    Content = userControl,
+                };
+
+                window.Show();
+
+                Assert.Equal(Colors.Red, brush.Color);
+            }
+        }
+
         private IDisposable StyledWindow(params (string, string)[] assets)
         {
             var services = TestServices.StyledWindow.With(

+ 47 - 0
tests/Avalonia.Styling.UnitTests/StyledElementTests.cs

@@ -489,6 +489,53 @@ namespace Avalonia.Styling.UnitTests
                 called);
         }
 
+        [Fact]
+        public void Changing_Parent_Notifies_Resources_ParentResourcesChanged()
+        {
+            var resources = new Mock<IResourceDictionary>();
+            var setResourceParent = resources.As<ISetResourceParent>();
+            var target = new TestControl { Resources = resources.Object };
+            var parent = new Decorator { Resources = { { "foo", "bar" } } };
+
+            setResourceParent.ResetCalls();
+            parent.Child = target;
+
+            setResourceParent.Verify(x =>
+                x.ParentResourcesChanged(It.IsAny<ResourcesChangedEventArgs>()),
+                Times.Once);
+        }
+
+        [Fact]
+        public void Changing_Parent_Notifies_Styles_ParentResourcesChanged()
+        {
+            var style = new Mock<IStyle>();
+            var setResourceParent = style.As<ISetResourceParent>();
+            var target = new TestControl { Styles = { style.Object } };
+            var parent = new Decorator { Resources = { { "foo", "bar" } } };
+
+            setResourceParent.ResetCalls();
+            parent.Child = target;
+
+            setResourceParent.Verify(x =>
+                x.ParentResourcesChanged(It.IsAny<ResourcesChangedEventArgs>()),
+                Times.Once);
+        }
+
+        [Fact]
+        public void Changing_Resources_Notifies_Styles()
+        {
+            var style = new Mock<IStyle>();
+            var setResourceParent = style.As<ISetResourceParent>();
+            var target = new TestControl { Styles = { style.Object } };
+
+            setResourceParent.ResetCalls();
+            target.Resources.Add("foo", "bar");
+
+            setResourceParent.Verify(x =>
+                x.ParentResourcesChanged(It.IsAny<ResourcesChangedEventArgs>()),
+                Times.Once);
+        }
+
         private interface IDataContextEvents
         {
             event EventHandler DataContextBeginUpdate;

+ 18 - 1
tests/Avalonia.Styling.UnitTests/StyledElementTests_Resources.cs

@@ -205,7 +205,7 @@ namespace Avalonia.Controls.UnitTests
         }
 
         [Fact]
-        public void Setting_Logical_Parent_Subscribes_To_Parents_ResourceChanged_Event()
+        public void Setting_Logical_Parent_Raises_Child_ResourcesChanged()
         {
             var parent = new ContentControl();
             var child = new StyledElement();
@@ -220,6 +220,23 @@ namespace Avalonia.Controls.UnitTests
             Assert.True(raisedOnChild);
         }
 
+        [Fact]
+        public void Setting_Logical_Parent_Raises_Style_ResourcesChanged()
+        {
+            var style = new Style(x => x.OfType<Canvas>());
+            var parent = new ContentControl();
+            var child = new StyledElement { Styles = { style } };
+
+            ((ISetLogicalParent)child).SetParent(parent);
+            var raised = false;
+
+            style.ResourcesChanged += (_, __) => raised = true;
+
+            parent.Resources.Add("foo", "bar");
+
+            Assert.True(raised);
+        }
+
         private IControlTemplate ContentControlTemplate()
         {
             return new FuncControlTemplate<ContentControl>((x, scope) =>