Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions src/CommunityToolkit.Maui.Markup.UnitTests/BindingHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Globalization;
using System.Globalization;
using System.Reflection;
using Microsoft.Maui.Controls.Internals;
using NUnit.Framework;
namespace CommunityToolkit.Maui.Markup.UnitTests;

Expand Down Expand Up @@ -79,14 +78,17 @@ internal static void AssertTypedBindingExists<TBindable, TBindingContext, TSourc
TDest? expectedFallbackValue = default,
TParam? expectedConverterParameter = default) where TBindable : BindableObject
{
var binding = GetTypedBinding(bindable, targetProperty) ?? throw new NullReferenceException();
var binding = GetBinding(bindable, targetProperty) ?? throw new NullReferenceException();

Assert.Multiple(() =>
{
Assert.That(binding, Is.Not.Null);
Assert.That(binding.Mode, Is.EqualTo(expectedBindingMode));

Assert.That(binding.Converter?.ToString(), Is.EqualTo(expectedConverter?.ToString()));
var actualConverter = binding.Converter?.GetType().Name.StartsWith("GetterValueConverter", StringComparison.Ordinal) is true && expectedConverter is null
? null
: binding.Converter;
Assert.That(actualConverter?.ToString(), Is.EqualTo(expectedConverter?.ToString()));

Assert.That(binding.ConverterParameter, Is.EqualTo(expectedConverterParameter));

Expand Down Expand Up @@ -200,8 +202,6 @@ internal static void AssertBindingExists<TDest, TParam>(

internal static Binding? GetBinding(BindableObject bindable, BindableProperty property) => GetBindingBase<Binding>(bindable, property);

internal static TypedBindingBase? GetTypedBinding(BindableObject bindable, BindableProperty property) => GetBindingBase<TypedBindingBase>(bindable, property);

internal static MultiBinding? GetMultiBinding(BindableObject bindable, BindableProperty property) => GetBindingBase<MultiBinding>(bindable, property);

/// <remarks>
Expand All @@ -213,8 +213,15 @@ internal static void AssertBindingExists<TDest, TParam>(
{
getContextMethodInfo ??= typeof(BindableObject).GetMethod("GetContext", BindingFlags.NonPublic | BindingFlags.Instance);

var context = (BindableObject.BindablePropertyContext?)getContextMethodInfo?.Invoke(bindable, [property]);
return (TBinding?)context?.Bindings.GetValue();
var context = getContextMethodInfo?.Invoke(bindable, [property]);
var contextType = context?.GetType();
var bindings = contextType?.GetProperty("Bindings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(context)
?? contextType?.GetField("Bindings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(context);
var binding = bindings?.GetType()
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.SingleOrDefault(static method => method.Name is "GetValue" && method.GetParameters().Length is 0)
?.Invoke(bindings, null);
return binding as TBinding;
}

internal static IValueConverter AssertConvert<TValue, TConvertedValue>(this IValueConverter converter, TValue value, object? parameter, TConvertedValue expectedConvertedValue, bool twoWay = false, bool backOnly = false, CultureInfo? culture = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,39 +60,39 @@ public void EffectsMultiple()

[Test]
public void FontSize()
=> TestPropertiesSet(l => l.FontSize(8), (FontElement.FontSizeProperty, 6.0, 8.0));
=> TestPropertiesSet(l => l.FontSize(8), (Label.FontSizeProperty, 6.0, 8.0));

[Test]
public void Bold()
=> TestPropertiesSet(l => l.Bold(), (FontElement.FontAttributesProperty, FontAttributes.None, FontAttributes.Bold));
=> TestPropertiesSet(l => l.Bold(), (Label.FontAttributesProperty, FontAttributes.None, FontAttributes.Bold));

[Test]
public void Italic()
=> TestPropertiesSet(l => l.Italic(), (FontElement.FontAttributesProperty, FontAttributes.None, FontAttributes.Italic));
=> TestPropertiesSet(l => l.Italic(), (Label.FontAttributesProperty, FontAttributes.None, FontAttributes.Italic));

[Test]
public void FontWithPositionalParameters()
=> TestPropertiesSet(
l => l.Font("AFontName", 8, true, true),
(FontElement.FontSizeProperty, 6.0, 8.0),
(FontElement.FontAttributesProperty, FontAttributes.None, FontAttributes.Bold | FontAttributes.Italic),
(FontElement.FontFamilyProperty, string.Empty, "AFontName"));
(Label.FontSizeProperty, 6.0, 8.0),
(Label.FontAttributesProperty, FontAttributes.None, FontAttributes.Bold | FontAttributes.Italic),
(Label.FontFamilyProperty, string.Empty, "AFontName"));

[Test]
public void FontWithSizeNamedParameter()
=> TestPropertiesSet(l => l.Font(size: 8), (FontElement.FontSizeProperty, 6.0, 8.0));
=> TestPropertiesSet(l => l.Font(size: 8), (Label.FontSizeProperty, 6.0, 8.0));

[Test]
public void FontWithBoldNamedParameter()
=> TestPropertiesSet(l => l.Font(bold: true), (FontElement.FontAttributesProperty, FontAttributes.None, FontAttributes.Bold));
=> TestPropertiesSet(l => l.Font(bold: true), (Label.FontAttributesProperty, FontAttributes.None, FontAttributes.Bold));

[Test]
public void FontWithItalicNamedParameter()
=> TestPropertiesSet(l => l.Font(italic: true), (FontElement.FontAttributesProperty, FontAttributes.None, FontAttributes.Italic));
=> TestPropertiesSet(l => l.Font(italic: true), (Label.FontAttributesProperty, FontAttributes.None, FontAttributes.Italic));

[Test]
public void FontWithFamilyNamedParameter()
=> TestPropertiesSet(l => l.Font(family: "AFontName"), (FontElement.FontFamilyProperty, string.Empty, "AFontName"));
=> TestPropertiesSet(l => l.Font(family: "AFontName"), (Label.FontFamilyProperty, string.Empty, "AFontName"));

static Label AssertDynamicResources()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public void BindTapGestureDefaults()
Assert.That(gestureElement.GestureRecognizers[0], Is.InstanceOf<TapGestureRecognizer>());
});

BindingHelpers.AssertTypedBindingExists((TapGestureRecognizer)gestureElement.GestureRecognizers[0], TapGestureRecognizer.CommandProperty, BindingMode.Default, gestureElement.BindingContext);
BindingHelpers.AssertTypedBindingExists((TapGestureRecognizer)gestureElement.GestureRecognizers[0], TapGestureRecognizer.CommandProperty, BindingMode.OneWay, gestureElement.BindingContext);
}

[Test]
Expand All @@ -232,6 +232,29 @@ public void BindTapGestureDefaultsWithNestedBindings()
});

BindingHelpers.AssertTypedBindingExists((TapGestureRecognizer)gestureElement.GestureRecognizers[0], TapGestureRecognizer.CommandProperty, BindingMode.OneTime, gestureElement.BindingContext);
Assert.That(BindingHelpers.GetBinding((TapGestureRecognizer)gestureElement.GestureRecognizers[0], TapGestureRecognizer.CommandProperty)?.Path, Is.EqualTo("NestedCommand.SetGuidCommand"));
}

[Test]
public void BindTapGestureExpressionOverloadUsesNestedBindingPaths()
{
var gestureElement = new TGestureElement
{
BindingContext = new ViewModel()
};

gestureElement.BindTapGesture(
getter: static (ViewModel vm) => vm.NestedCommand.SetGuidCommand,
commandBindingMode: BindingMode.OneTime,
parameterGetter: static (ViewModel vm) => vm.NestedCommand.Id);

var tapGestureRecognizer = (TapGestureRecognizer)gestureElement.GestureRecognizers[0];

Assert.Multiple(() =>
{
Assert.That(BindingHelpers.GetBinding(tapGestureRecognizer, TapGestureRecognizer.CommandProperty)?.Path, Is.EqualTo("NestedCommand.SetGuidCommand"));
Assert.That(BindingHelpers.GetBinding(tapGestureRecognizer, TapGestureRecognizer.CommandParameterProperty)?.Path, Is.EqualTo("NestedCommand.Id"));
});
}

[Test]
Expand Down Expand Up @@ -308,7 +331,12 @@ public void BindTapGesturePositionalParametersWithNestedBindings()
});

BindingHelpers.AssertTypedBindingExists(tapGestureRecognizer, TapGestureRecognizer.CommandProperty, BindingMode.OneTime, gestureElement.BindingContext);
BindingHelpers.AssertTypedBindingExists(tapGestureRecognizer, TapGestureRecognizer.CommandParameterProperty, BindingMode.Default, gestureElement.BindingContext);
BindingHelpers.AssertTypedBindingExists(tapGestureRecognizer, TapGestureRecognizer.CommandParameterProperty, BindingMode.OneWay, gestureElement.BindingContext);
Assert.Multiple(() =>
{
Assert.That(BindingHelpers.GetBinding(tapGestureRecognizer, TapGestureRecognizer.CommandProperty)?.Path, Is.EqualTo("NestedCommand.SetGuidCommand"));
Assert.That(BindingHelpers.GetBinding(tapGestureRecognizer, TapGestureRecognizer.CommandParameterProperty)?.Path, Is.EqualTo("NestedCommand.Id"));
});
}

[Test]
Expand All @@ -323,7 +351,7 @@ public void BindSwipeGestureDefaults()

Assert.That(gestureElement.GestureRecognizers, Has.Count.EqualTo(1));
Assert.That(gestureElement.GestureRecognizers[0], Is.InstanceOf<SwipeGestureRecognizer>());
BindingHelpers.AssertTypedBindingExists((SwipeGestureRecognizer)gestureElement.GestureRecognizers[0], SwipeGestureRecognizer.CommandProperty, BindingMode.Default, gestureElement.BindingContext);
BindingHelpers.AssertTypedBindingExists((SwipeGestureRecognizer)gestureElement.GestureRecognizers[0], SwipeGestureRecognizer.CommandProperty, BindingMode.OneWay, gestureElement.BindingContext);
}

[Test]
Expand All @@ -349,6 +377,29 @@ public void BindSwipeGestureWithNestedBindings()
});

BindingHelpers.AssertTypedBindingExists((SwipeGestureRecognizer)gestureElement.GestureRecognizers[0], SwipeGestureRecognizer.CommandProperty, BindingMode.OneTime, gestureElement.BindingContext);
Assert.That(BindingHelpers.GetBinding((SwipeGestureRecognizer)gestureElement.GestureRecognizers[0], SwipeGestureRecognizer.CommandProperty)?.Path, Is.EqualTo("NestedCommand.SetGuidCommand"));
}

[Test]
public void BindSwipeGestureExpressionOverloadUsesNestedBindingPaths()
{
var gestureElement = new TGestureElement
{
BindingContext = new ViewModel()
};

gestureElement.BindSwipeGesture(
getter: static (ViewModel vm) => vm.NestedCommand.SetGuidCommand,
commandBindingMode: BindingMode.OneTime,
parameterGetter: static (ViewModel vm) => vm.NestedCommand.Id);

var swipeGestureRecognizer = (SwipeGestureRecognizer)gestureElement.GestureRecognizers[0];

Assert.Multiple(() =>
{
Assert.That(BindingHelpers.GetBinding(swipeGestureRecognizer, SwipeGestureRecognizer.CommandProperty)?.Path, Is.EqualTo("NestedCommand.SetGuidCommand"));
Assert.That(BindingHelpers.GetBinding(swipeGestureRecognizer, SwipeGestureRecognizer.CommandParameterProperty)?.Path, Is.EqualTo("NestedCommand.Id"));
});
}

[Test]
Expand Down Expand Up @@ -429,7 +480,13 @@ public void BindSwipeGesturePositionalParametersWithNestedBindings()
});

BindingHelpers.AssertTypedBindingExists((SwipeGestureRecognizer)gestureElement.GestureRecognizers[0], SwipeGestureRecognizer.CommandProperty, BindingMode.OneTime, gestureElement.BindingContext);
BindingHelpers.AssertTypedBindingExists((SwipeGestureRecognizer)gestureElement.GestureRecognizers[0], SwipeGestureRecognizer.CommandParameterProperty, BindingMode.Default, gestureElement.BindingContext);
BindingHelpers.AssertTypedBindingExists((SwipeGestureRecognizer)gestureElement.GestureRecognizers[0], SwipeGestureRecognizer.CommandParameterProperty, BindingMode.OneWay, gestureElement.BindingContext);
Assert.Multiple(() =>
{
var swipeGestureRecognizer = (SwipeGestureRecognizer)gestureElement.GestureRecognizers[0];
Assert.That(BindingHelpers.GetBinding(swipeGestureRecognizer, SwipeGestureRecognizer.CommandProperty)?.Path, Is.EqualTo("NestedCommand.SetGuidCommand"));
Assert.That(BindingHelpers.GetBinding(swipeGestureRecognizer, SwipeGestureRecognizer.CommandParameterProperty)?.Path, Is.EqualTo("NestedCommand.Id"));
});
}

[Test]
Expand Down
23 changes: 19 additions & 4 deletions src/CommunityToolkit.Maui.Markup.UnitTests/ImageExtensionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,29 @@ public void SetSourceTest()
[Test]
public void SetAspectTest()
{
TestPropertiesSet(i => i.Aspect(Aspect.AspectFill), (ImageElement.AspectProperty, Aspect.AspectFill));
TestPropertiesSet(i => i.Aspect(Aspect.Center), (ImageElement.AspectProperty, Aspect.Center));
TestPropertiesSet(i => i.Aspect(Aspect.Fill), (ImageElement.AspectProperty, Aspect.Fill));
TestPropertiesSet(i => i.Aspect(Aspect.AspectFill), (Image.AspectProperty, Aspect.AspectFill));
TestPropertiesSet(i => i.Aspect(Aspect.Center), (Image.AspectProperty, Aspect.Center));
TestPropertiesSet(i => i.Aspect(Aspect.Fill), (Image.AspectProperty, Aspect.Fill));
}

[Test]
public void SetIsOpaqueTest()
=> TestPropertiesSet(i => i.IsOpaque(true), (ImageElement.IsOpaqueProperty, true));
=> TestPropertiesSet(i => i.IsOpaque(true), (Image.IsOpaqueProperty, true));

[Test]
public void SupportsImageButton()
{
var imageButton = new ImageButton().Source(resourceToLoad);

Assert.Multiple(() =>
{
Assert.That(imageButton.Source, Is.InstanceOf<FileImageSource>());
Assert.That(((FileImageSource)imageButton.Source).File, Is.EqualTo(resourceToLoad));
});

TestPropertiesSet(new ImageButton(), imageButton => imageButton.Aspect(Aspect.Center), (ImageButton.AspectProperty, Aspect.Center));
TestPropertiesSet(new ImageButton(), imageButton => imageButton.IsOpaque(true), (ImageButton.IsOpaqueProperty, true));
}

[Test]
public void SupportDerivedFromImage()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Handlers;
namespace CommunityToolkit.Maui.Markup.UnitTests.Mocks;

Expand All @@ -9,9 +8,6 @@ public MockApplication(IServiceProvider serviceProvider)
Resources = new MockResourceDictionary();

Services = serviceProvider;
#pragma warning disable CS0612 // Type or member is obsolete
DependencyService.Register<ISystemResourcesProvider, MockResourcesProvider>();
#pragma warning restore CS0612 // Type or member is obsolete
}

public IApplication Application => this;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,30 @@ class PaceholderExtensionsTests : BaseMarkupTestFixture<Entry>
{
[Test]
public void SetPlaceholderTest()
=> TestPropertiesSet(e => e.Placeholder("Hello World"), (PlaceholderElement.PlaceholderProperty, "Hello World"));
=> TestPropertiesSet(e => e.Placeholder("Hello World"), (Entry.PlaceholderProperty, "Hello World"));

[Test]
public void SetPlaceholderAndColorTest()
=> TestPropertiesSet(e => e.Placeholder("Hello World", Colors.Red), (PlaceholderElement.PlaceholderProperty, "Hello World"), (PlaceholderElement.PlaceholderColorProperty, Colors.Red));
=> TestPropertiesSet(e => e.Placeholder("Hello World", Colors.Red), (Entry.PlaceholderProperty, "Hello World"), (Entry.PlaceholderColorProperty, Colors.Red));

[Test]
public void SetPlaceholderColorTest()
=> TestPropertiesSet(e => e.PlaceholderColor(Colors.Red), (PlaceholderElement.PlaceholderColorProperty, Colors.Red));
=> TestPropertiesSet(e => e.PlaceholderColor(Colors.Red), (Entry.PlaceholderColorProperty, Colors.Red));

[Test]
public void SupportsSearchBar()
{
var searchBar = new SearchBar()
.Placeholder("Hello World")
.PlaceholderColor(Colors.Blue)
.Placeholder("Hello World 2", Colors.Red);

Assert.Multiple(() =>
{
Assert.That(searchBar.Placeholder, Is.EqualTo("Hello World 2"));
Assert.That(searchBar.PlaceholderColor, Is.EqualTo(Colors.Red));
});
}

[Test]
public void SupportDerivedFromEditor()
Expand Down
Loading
Loading