Browse Source

Add theme variants specific tests

pull/8166/head
Max Katz 3 years ago
parent
commit
be22b361c8
  1. 8
      tests/Avalonia.Base.UnitTests/Styling/ResourceDictionaryTests.cs
  2. 2
      tests/Avalonia.Base.UnitTests/Styling/StylesTests.cs
  3. 2
      tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs
  4. 19
      tests/Avalonia.Benchmarks/TestStyles.cs
  5. 6
      tests/Avalonia.Markup.Xaml.UnitTests/Converters/AvaloniaPropertyConverterTest.cs
  6. 2
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs
  7. 444
      tests/Avalonia.Markup.Xaml.UnitTests/ThemeDictionariesTests.cs
  8. 4
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs
  9. 103
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/MergeResourceIncludeTests.cs
  10. 32
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ResourceDictionaryTests.cs
  11. 2
      tests/Avalonia.UnitTests/TestServices.cs

8
tests/Avalonia.Base.UnitTests/Styling/ResourceDictionaryTests.cs

@ -29,7 +29,7 @@ namespace Avalonia.Base.UnitTests.Styling
{ "foo", "bar" },
};
Assert.True(target.TryGetResource("foo", out var result));
Assert.True(target.TryGetResource("foo", null, out var result));
Assert.Equal("bar", result);
}
@ -47,7 +47,7 @@ namespace Avalonia.Base.UnitTests.Styling
}
};
Assert.True(target.TryGetResource("foo", out var result));
Assert.True(target.TryGetResource("foo", null, out var result));
Assert.Equal("bar", result);
}
@ -64,7 +64,7 @@ namespace Avalonia.Base.UnitTests.Styling
{ "foo", "baz" },
});
Assert.True(target.TryGetResource("foo", out var result));
Assert.True(target.TryGetResource("foo", null, out var result));
Assert.Equal("bar", result);
}
@ -86,7 +86,7 @@ namespace Avalonia.Base.UnitTests.Styling
}
};
Assert.True(target.TryGetResource("foo", out var result));
Assert.True(target.TryGetResource("foo", null, out var result));
Assert.Equal("baz", result);
}

2
tests/Avalonia.Base.UnitTests/Styling/StylesTests.cs

@ -108,7 +108,7 @@ namespace Avalonia.Base.UnitTests.Styling
}
};
Assert.True(target.TryGetResource("foo", out var result));
Assert.True(target.TryGetResource("foo", ThemeVariant.Dark, out var result));
Assert.Equal("bar", result);
}
}

2
tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs

@ -44,7 +44,7 @@ namespace Avalonia.Benchmarks.Styling
return new Styles
{
preHost,
new TestStyles(50, 3, 5),
new TestStyles(50, 3, 5, 0),
postHost
};
}

19
tests/Avalonia.Benchmarks/TestStyles.cs

@ -1,10 +1,11 @@
using Avalonia.Styling;
using Avalonia.Controls;
using Avalonia.Styling;
namespace Avalonia.Benchmarks
{
public class TestStyles : Styles
{
public TestStyles(int childStylesCount, int childInnerStyleCount, int childResourceCount)
public TestStyles(int childStylesCount, int childInnerStyleCount, int childResourceCount, int childThemeResourcesCount)
{
for (int i = 0; i < childStylesCount; i++)
{
@ -18,7 +19,19 @@ namespace Avalonia.Benchmarks
{
childStyle.Resources.Add($"resource.{i}.{j}.{k}", null);
}
if (childThemeResourcesCount > 0)
{
ResourceDictionary darkTheme, lightTheme;
childStyle.Resources.ThemeDictionaries[ThemeVariant.Dark] = darkTheme = new ResourceDictionary();
childStyle.Resources.ThemeDictionaries[ThemeVariant.Light] = lightTheme = new ResourceDictionary();
for (int k = 0; k < childThemeResourcesCount; k++)
{
darkTheme.Add($"resource.theme.{i}.{j}.{k}", null);
lightTheme.Add($"resource.theme.{i}.{j}.{k}", null);
}
}
childStyles.Add(childStyle);
}

6
tests/Avalonia.Markup.Xaml.UnitTests/Converters/AvaloniaPropertyConverterTest.cs

@ -142,6 +142,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.Converters
throw new NotImplementedException();
}
public ThemeVariant ThemeVariant
{
get { throw new NotImplementedException(); }
}
public event EventHandler ThemeVariantChanged;
public void DetachStyles()
{
throw new NotImplementedException();

2
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs

@ -938,7 +938,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
public void AddOwner(IResourceHost owner) => Owner = owner;
public void RemoveOwner(IResourceHost owner) => Owner = null;
public bool TryGetResource(object key, out object value)
public bool TryGetResource(object key, ThemeVariant themeVariant, out object value)
{
RequestedResources.Add(key);
value = key;

444
tests/Avalonia.Markup.Xaml.UnitTests/ThemeDictionariesTests.cs

@ -0,0 +1,444 @@
using Avalonia.Controls;
using Avalonia.Markup.Data;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Media;
using Avalonia.Styling;
using Moq;
using Xunit;
namespace Avalonia.Markup.Xaml.UnitTests;
public class ThemeDictionariesTests : XamlTestBase
{
[Fact]
public void DynamicResource_Updated_When_Control_Theme_Changed()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='DemoBackground'>Black</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='DemoBackground'>White</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{DynamicResource DemoBackground}'/>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void DynamicResource_Updated_When_Control_Theme_Changed_No_Xaml()
{
var themeVariantScope = new ThemeVariantScope
{
RequestedThemeVariant = ThemeVariant.Light,
Resources = new ResourceDictionary
{
ThemeDictionaries =
{
[ThemeVariant.Dark] = new ResourceDictionary { ["DemoBackground"] = Brushes.Black },
[ThemeVariant.Light] = new ResourceDictionary { ["DemoBackground"] = Brushes.White }
}
},
Child = new Border()
};
var border = (Border)themeVariantScope.Child!;
border[!Border.BackgroundProperty] = new DynamicResourceExtension("DemoBackground");
DelayedBinding.ApplyBindings(border);
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void Intermediate_DynamicResource_Updated_When_Control_Theme_Changed()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<Color x:Key='TestColor'>Black</Color>
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<Color x:Key='TestColor'>White</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<SolidColorBrush x:Key='DemoBackground' Color='{DynamicResource TestColor}' />
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{DynamicResource DemoBackground}'/>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void Intermediate_StaticResource_Can_Be_Reached_From_ThemeDictionaries()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<Color x:Key='TestColor'>Black</Color>
<StaticResource x:Key='DemoBackground' ResourceKey='TestColor' />
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<Color x:Key='TestColor'>White</Color>
<StaticResource x:Key='DemoBackground' ResourceKey='TestColor' />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{DynamicResource DemoBackground}'/>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact(Skip = "Not implemented")]
public void StaticResource_Inside_Of_ThemeDictionaries_Should_Use_Same_Theme_Key()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<Color x:Key='TestColor'>Black</Color>
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<Color x:Key='TestColor'>White</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{DynamicResource DemoBackground}'>
<Border.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<StaticResource x:Key='DemoBackground' ResourceKey='TestColor' />
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<StaticResource x:Key='DemoBackground' ResourceKey='TestColor' />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Border.Resources>
</Border>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void StaticResource_Outside_Of_Dictionaries_Should_Use_Control_ThemeVariant()
{
using (AvaloniaLocator.EnterScope())
{
var applicationThemeHost = new Mock<IGlobalThemeVariantProvider>();
applicationThemeHost.SetupGet(h => h.ActualThemeVariant).Returns(ThemeVariant.Dark);
AvaloniaLocator.CurrentMutable.Bind<IGlobalThemeVariantProvider>().ToConstant(applicationThemeHost.Object);
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='DemoBackground'>Black</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='DemoBackground'>White</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{StaticResource DemoBackground}'/>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
themeVariantScope.RequestedThemeVariant = ThemeVariant.Light;
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
}
}
[Fact]
public void Inner_ThemeDictionaries_Works_Properly()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<Border Name='border' Background='{DynamicResource DemoBackground}'>
<Border.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='DemoBackground'>Black</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='DemoBackground'>White</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Border.Resources>
</Border>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void Inner_Resource_Can_Reference_Parent_ThemeDictionaries()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<Color x:Key='TestColor'>Black</Color>
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<Color x:Key='TestColor'>White</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{DynamicResource DemoBackground}'>
<Border.Resources>
<ResourceDictionary>
<SolidColorBrush x:Key='DemoBackground' Color='{DynamicResource TestColor}' />
</ResourceDictionary>
</Border.Resources>
</Border>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void DynamicResource_Can_Access_Resources_Outside_Of_ThemeDictionaries()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='DemoBackground' Color='{DynamicResource TestColor1}' />
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='DemoBackground' Color='{DynamicResource TestColor2}' />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<Color x:Key='TestColor1'>Black</Color>
<Color x:Key='TestColor2'>White</Color>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{DynamicResource DemoBackground}' />
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.White, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void Inner_Dictionary_Does_Not_Affect_Parent_Resources()
{
// It might be a nice feature, but neither Avalonia nor UWP supports it.
// Better to expect this limitation with a unit test.
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<Color x:Key='TestColor'>Red</Color>
<SolidColorBrush x:Key='DemoBackground' Color='{DynamicResource TestColor}' />
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{DynamicResource DemoBackground}'>
<Border.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<Color x:Key='TestColor'>Black</Color>
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<Color x:Key='TestColor'>White</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Border.Resources>
</Border>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.Red, ((ISolidColorBrush)border.Background)!.Color);
themeVariantScope.RequestedThemeVariant = ThemeVariant.Dark;
Assert.Equal(Colors.Red, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void Custom_Theme_Can_Be_Defined_In_ThemeDictionaries()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='DemoBackground'>Black</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='DemoBackground'>White</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key='Custom'>
<SolidColorBrush x:Key='DemoBackground'>Pink</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Name='border' Background='{DynamicResource DemoBackground}'/>
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
themeVariantScope.RequestedThemeVariant = new ThemeVariant("Custom");
Assert.Equal(Colors.Pink, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void Custom_Theme_Fallbacks_To_Inherit_Theme_DynamicResource()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
RequestedThemeVariant='Light'>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='DemoBackground'>Black</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Background='{DynamicResource DemoBackground}' />
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
themeVariantScope.RequestedThemeVariant = new ThemeVariant("Custom", ThemeVariant.Dark);
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
[Fact]
public void Custom_Theme_Fallbacks_To_Inherit_Theme_StaticResource()
{
var themeVariantScope = (ThemeVariantScope)AvaloniaRuntimeXamlLoader.Load(@"
<ThemeVariantScope xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<ThemeVariantScope.RequestedThemeVariant>
<ThemeVariant>
<x:Arguments>
<x:String>Custom</x:String>
<ThemeVariant>Dark</ThemeVariant>
</x:Arguments>
</ThemeVariant>
</ThemeVariantScope.RequestedThemeVariant>
<ThemeVariantScope.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='DemoBackground'>Black</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ThemeVariantScope.Resources>
<Border Background='{StaticResource DemoBackground}' />
</ThemeVariantScope>");
var border = (Border)themeVariantScope.Child!;
Assert.Equal(Colors.Black, ((ISolidColorBrush)border.Background)!.Color);
}
}

4
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

@ -448,13 +448,13 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.True(style.Resources.Count > 0);
style.TryGetResource("Brush", out var brush);
style.TryGetResource("Brush", null, out var brush);
Assert.NotNull(brush);
Assert.IsAssignableFrom<ISolidColorBrush>(brush);
Assert.Equal(Colors.White, ((ISolidColorBrush)brush).Color);
style.TryGetResource("Double", out var d);
style.TryGetResource("Double", null, out var d);
Assert.Equal(10.0, d);
}

103
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/MergeResourceIncludeTests.cs

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Xml;
using Avalonia.Controls;
@ -128,4 +130,105 @@ public class MergeResourceIncludeTests
Assert.Equal(Colors.Black, ((ISolidColorBrush)resources["brush5"]!).Color);
Assert.Equal(Colors.White, ((ISolidColorBrush)resources["brush6"]!).Color);
}
[Fact]
public void MergeResourceInclude_Works_With_ThemeDictionaries()
{
var documents = new[]
{
new RuntimeXamlLoaderDocument(new Uri("avares://Tests/Resources1.xaml"), @"
<ResourceDictionary xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='brush1'>White</SolidColorBrush>
<SolidColorBrush x:Key='brush2'>Black</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='brush1'>Black</SolidColorBrush>
<SolidColorBrush x:Key='brush2'>White</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>"),
new RuntimeXamlLoaderDocument(new Uri("avares://Tests/Resources2.xaml"), @"
<ResourceDictionary xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='brush3'>Red</SolidColorBrush>
<SolidColorBrush x:Key='brush4'>Blue</SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key='Dark'>
<SolidColorBrush x:Key='brush3'>Blue</SolidColorBrush>
<SolidColorBrush x:Key='brush4'>Red</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>"),
new RuntimeXamlLoaderDocument(@"
<ResourceDictionary xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<ResourceDictionary.MergedDictionaries>
<MergeResourceInclude Source='avares://Tests/Resources1.xaml'/>
<MergeResourceInclude Source='avares://Tests/Resources2.xaml'/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>"),
};
var objects = AvaloniaRuntimeXamlLoader.LoadGroup(documents);
var resources = Assert.IsType<ResourceDictionary>(objects[2]);
Assert.Empty(resources.MergedDictionaries);
Assert.Equal(Colors.White, Get("brush1", ThemeVariant.Light).Color);
Assert.Equal(Colors.Black, Get("brush2", ThemeVariant.Light).Color);
Assert.Equal(Colors.Black, Get("brush1", ThemeVariant.Dark).Color);
Assert.Equal(Colors.White, Get("brush2", ThemeVariant.Dark).Color);
Assert.Equal(Colors.Red, Get("brush3", ThemeVariant.Light).Color);
Assert.Equal(Colors.Blue, Get("brush4", ThemeVariant.Light).Color);
Assert.Equal(Colors.Blue, Get("brush3", ThemeVariant.Dark).Color);
Assert.Equal(Colors.Red, Get("brush4", ThemeVariant.Dark).Color);
ISolidColorBrush Get(string key, ThemeVariant themeVariant)
{
return resources.TryGetResource(key, themeVariant, out var res) ?
(ISolidColorBrush)res! :
throw new KeyNotFoundException();
}
}
[Fact]
public void MergeResourceInclude_Fails_With_ThemeDictionaries_Duplicate_Resources()
{
var documents = new[]
{
new RuntimeXamlLoaderDocument(new Uri("avares://Tests/Resources1.xaml"), @"
<ResourceDictionary xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='brush1'>White</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>"),
new RuntimeXamlLoaderDocument(new Uri("avares://Tests/Resources2.xaml"), @"
<ResourceDictionary xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key='Light'>
<SolidColorBrush x:Key='brush1'>Black</SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>"),
new RuntimeXamlLoaderDocument(@"
<ResourceDictionary xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<ResourceDictionary.MergedDictionaries>
<MergeResourceInclude Source='avares://Tests/Resources1.xaml'/>
<MergeResourceInclude Source='avares://Tests/Resources2.xaml'/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>"),
};
Assert.ThrowsAny<ArgumentException>(() => AvaloniaRuntimeXamlLoader.LoadGroup(documents));
}
}

32
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ResourceDictionaryTests.cs

@ -276,6 +276,38 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
}
}
[Fact]
public void Closest_Resource_Should_Be_Referenced()
{
using (StyledWindow())
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Window.Resources>
<SolidColorBrush x:Key='Red' Color='Red' />
<StaticResource x:Key='Red2' ResourceKey='Red' />
</Window.Resources>
<Button>
<Button.Resources>
<SolidColorBrush x:Key='Red' Color='Blue' />
</Button.Resources>
</Button>
</Window>";
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var windowResources = (ResourceDictionary)window.Resources;
var buttonResources = (ResourceDictionary)((Button)window.Content!).Resources;
var brush = Assert.IsType<SolidColorBrush>(windowResources["Red2"]);
Assert.Equal(Colors.Red, brush.Color);
Assert.False(windowResources.ContainsDeferredKey("Red"));
Assert.False(windowResources.ContainsDeferredKey("Red2"));
Assert.True(buttonResources.ContainsDeferredKey("Red"));
}
}
private IDisposable StyledWindow(params (string, string)[] assets)
{
var services = TestServices.StyledWindow.With(

2
tests/Avalonia.UnitTests/TestServices.cs

@ -155,7 +155,7 @@ namespace Avalonia.UnitTests
private static IStyle CreateSimpleTheme()
{
return new SimpleTheme { Mode = SimpleThemeMode.Light };
return new SimpleTheme();
}
private static IPlatformRenderInterface CreateRenderInterfaceMock()

Loading…
Cancel
Save