maui-linux/Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs

843 строки
19 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Threading.Tasks;
using NUnit.Framework;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Core.UnitTests
{
[TestFixture]
public class ViewUnitTests : BaseTestFixture
{
[SetUp]
public override void Setup ()
{
base.Setup ();
Device.PlatformServices = new MockPlatformServices (getNativeSizeFunc: (ve, widthConstraint, heightConstraint) => {
if (widthConstraint < 30)
return new SizeRequest (new Size (40, 50));
return new SizeRequest(new Size(20, 100));
});
}
[TearDown]
public override void TearDown ()
{
base.TearDown ();
Device.PlatformServices = null;
}
[Test]
public void TestLayout ()
{
View view = new View ();
view.Layout (new Rectangle (50, 25, 100, 200));
Assert.AreEqual (view.X, 50);
Assert.AreEqual (view.Y, 25);
Assert.AreEqual (view.Width, 100);
Assert.AreEqual (view.Height, 200);
}
[Test]
public void TestPreferredSize ()
{
View view = new View {
IsPlatformEnabled = true,
};
bool fired = false;
view.MeasureInvalidated += (sender, e) => fired = true;
view.WidthRequest = 200;
view.HeightRequest = 300;
Assert.True (fired);
var result = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
Assert.AreEqual (new Size (200, 300), result);
}
[Test]
public void TestSizeChangedEvent ()
{
View view = new View ();
bool fired = false;
view.SizeChanged += (sender, e) => fired = true;
view.Layout (new Rectangle (0, 0, 100, 100));
Assert.True (fired);
}
[Test]
public void TestOpacityClamping ()
{
var view = new View ();
view.Opacity = -1;
Assert.AreEqual (0, view.Opacity);
view.Opacity = 2;
Assert.AreEqual (1, view.Opacity);
}
[Test]
public void TestMeasureInvalidatedFiredOnVisibilityChanged ()
{
var view = new View {IsVisible = false};
bool signaled = false;
view.MeasureInvalidated += (sender, e) => {
signaled = true;
};
view.IsVisible = true;
Assert.True (signaled);
}
[Test]
public void TestOnPlatformiOS ()
{
var view = new View ();
bool ios = false;
bool android = false;
bool winphone = false;
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = Device.iOS;
Device.OnPlatform (
iOS: () => ios = true,
Android: () => android = true,
WinPhone: () => winphone = true);
Assert.True (ios);
Assert.False (android);
Assert.False (winphone);
}
[Test]
public void TestOnPlatformAndroid ()
{
var view = new View ();
bool ios = false;
bool android = false;
bool winphone = false;
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = Device.Android;
Device.OnPlatform (
iOS: () => ios = true,
Android: () => android = true,
WinPhone: () => winphone = true);
Assert.False (ios);
Assert.True (android);
Assert.False (winphone);
}
[Test]
public void TestOnPlatformDefault ()
{
var view = new View ();
bool ios = false;
bool android = false;
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = Device.Android;
Device.OnPlatform (
iOS: () => ios = false,
Default: () => android = true);
Assert.False (ios);
Assert.True (android);
}
[Test]
public void TestOnPlatformNoOpWithoutDefault ()
{
bool any = false;
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = "Other";
Device.OnPlatform (
iOS: () => any = true,
Android: () => any = true,
WinPhone: () => any = true);
Assert.False (any);
}
[Test]
public void TestDefaultOniOS ()
{
bool defaultExecuted = false;
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = Device.iOS;
Device.OnPlatform (
Android: () => { },
WinPhone: () => { },
Default:() => defaultExecuted = true);
Assert.True (defaultExecuted);
}
[Test]
public void TestDefaultOnAndroid ()
{
bool defaultExecuted = false;
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = Device.Android;
Device.OnPlatform (
iOS: () => { },
WinPhone: () => { },
Default:() => defaultExecuted = true);
Assert.True (defaultExecuted);
}
[Test]
public void TestDefaultOnOther ()
{
bool defaultExecuted = false;
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = "Other";
Device.OnPlatform (
iOS: () => { },
Android: () => { },
WinPhone: () => { },
Default:() => defaultExecuted = true);
Assert.True (defaultExecuted);
}
[Test]
public void TestNativeStateConsistent ()
{
var view = new View { IsPlatformEnabled = true };
Assert.True (view.IsNativeStateConsistent);
view.IsNativeStateConsistent = false;
Assert.False (view.IsNativeStateConsistent);
bool sizeChanged = false;
view.MeasureInvalidated += (sender, args) => {
sizeChanged = true;
};
view.IsNativeStateConsistent = true;
Assert.True (sizeChanged);
sizeChanged = false;
view.IsNativeStateConsistent = true;
Assert.False (sizeChanged);
}
[Test]
public async Task TestFadeTo ()
{
var view = new View {IsPlatformEnabled = true};
Ticker.Default = new BlockingTicker ();
await view.FadeTo (0.1);
Assert.True (Math.Abs (0.1 - view.Opacity) < 0.001);
}
[Test]
public async Task TestTranslateTo ()
{
var view = new View {IsPlatformEnabled = true};
Ticker.Default = new BlockingTicker ();
await view.TranslateTo (100, 50);
Assert.AreEqual (100, view.TranslationX);
Assert.AreEqual (50, view.TranslationY);
}
[Test]
public async Task ScaleTo ()
{
var view = new View {IsPlatformEnabled = true};
Ticker.Default = new BlockingTicker ();
await view.ScaleTo (2);
Assert.AreEqual (2, view.Scale);
}
[Test]
public void TestNativeSizeChanged ()
{
var view = new View ();
bool sizeChanged = false;
view.MeasureInvalidated += (sender, args) => sizeChanged = true;
((IVisualElementController)view).NativeSizeChanged ();
Assert.True (sizeChanged);
}
[Test]
public async Task TestRotateTo ()
{
var view = new View {IsPlatformEnabled = true};
Ticker.Default = new BlockingTicker ();
await view.RotateTo (25);
Assert.That (view.Rotation, Is.EqualTo (25).Within (0.001));
}
[Test]
public async Task TestRotateYTo ()
{
var view = new View {IsPlatformEnabled = true};
Ticker.Default = new BlockingTicker ();
await view.RotateYTo (25);
Assert.That (view.RotationY, Is.EqualTo (25).Within (0.001));
}
[Test]
public async Task TestRotateXTo ()
{
var view = new View {IsPlatformEnabled = true};
Ticker.Default = new BlockingTicker ();
await view.RotateXTo (25);
Assert.That (view.RotationX, Is.EqualTo (25).Within (0.001));
}
[Test]
public async Task TestRelRotateTo ()
{
var view = new View {Rotation = 30, IsPlatformEnabled = true};
Ticker.Default = new BlockingTicker ();
await view.RelRotateTo (20);
Assert.That (view.Rotation, Is.EqualTo (50).Within (0.001));
}
[Test]
public async Task TestRelScaleTo ()
{
var view = new View {Scale = 1, IsPlatformEnabled = true};
Ticker.Default = new BlockingTicker ();
await view.RelScaleTo (1);
Assert.That (view.Scale, Is.EqualTo (2).Within (0.001));
}
class ParentSignalView : View
{
public bool ParentSet { get; set; }
protected override void OnParentSet ()
{
ParentSet = true;
base.OnParentSet ();
}
}
[Test]
public void TestDoubleSetParent ()
{
var view = new ParentSignalView ();
var parent = new NaiveLayout {Children = {view}};
view.ParentSet = false;
view.Parent = parent;
Assert.False (view.ParentSet, "OnParentSet should not be called in the event the parent is already properly set");
}
[Test]
public void TestAncestorAdded ()
{
var child = new NaiveLayout ();
var view = new NaiveLayout {Children = {child}};
bool added = false;
view.DescendantAdded += (sender, arg) => added = true;
child.Children.Add (new View ());
Assert.True (added, "AncestorAdded must fire when adding a child to an ancestor of a view.");
}
[Test]
public void TestAncestorRemoved ()
{
var ancestor = new View ();
var child = new NaiveLayout {Children = {ancestor}};
var view = new NaiveLayout {Children = {child}};
bool removed = false;
view.DescendantRemoved += (sender, arg) => removed = true;
child.Children.Remove (ancestor);
Assert.True (removed, "AncestorRemoved must fire when removing a child from an ancestor of a view.");
}
[Test]
public void TestOnPlatformGeneric ()
{
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = Device.iOS;
Assert.AreEqual (1, Device.OnPlatform (1, 2, 3));
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = Device.Android;
Assert.AreEqual (2, Device.OnPlatform (1, 2, 3));
((MockPlatformServices)Device.PlatformServices).RuntimePlatform = "Other";
Assert.AreEqual (1, Device.OnPlatform (1, 2, 3));
}
[Test]
public void TestOnIdiomDefault()
{
Device.Idiom = TargetIdiom.Tablet;
Assert.That((int)(new OnIdiom<int> { Tablet = 12, Default = 42 }), Is.EqualTo(12));
Device.Idiom = TargetIdiom.Watch;
Assert.That((int)(new OnIdiom<int> { Tablet = 12, Default = 42 }), Is.EqualTo(42));
}
[Test]
public void TestBatching ()
{
var view = new View ();
bool committed = false;
view.BatchCommitted += (sender, arg) => committed = true;
view.BatchBegin ();
Assert.True (view.Batched);
view.BatchBegin ();
Assert.True (view.Batched);
view.BatchCommit ();
Assert.True (view.Batched);
Assert.False (committed);
view.BatchCommit ();
Assert.False (view.Batched);
Assert.True (committed);
}
[Test]
public void TestBatchRegularCase()
{
var view = new View();
var committed = false;
view.BatchCommitted += (sender, arg) => committed = true;
using (view.Batch())
{
Assert.True(view.Batched);
}
Assert.False(view.Batched);
Assert.True(committed);
}
[Test]
public void TestBatchWhenExceptionThrown()
{
var view = new View();
var committed = false;
view.BatchCommitted += (sender, arg) => committed = true;
var exceptionThrown = false;
try
{
using (view.Batch())
{
Assert.True(view.Batched);
throw new Exception();
}
}
catch
{
exceptionThrown = true;
}
Assert.True(exceptionThrown);
Assert.False(view.Batched);
Assert.True(committed);
}
[Test]
public void IsPlatformEnabled ()
{
var view = new View ();
Assert.False (view.IsPlatformEnabled);
view.IsPlatformEnabled = true;
Assert.True (view.IsPlatformEnabled);
view.IsPlatformEnabled = false;
Assert.False (view.IsPlatformEnabled);
}
[Test]
public void TestBindingContextChaining ()
{
View child;
var group = new NaiveLayout {
Children = { (child = new View ()) }
};
var context = new object ();
group.BindingContext = context;
Assert.AreEqual (context, child.BindingContext);
}
[Test]
public void FocusWithoutSubscriber ()
{
var view = new View ();
Assert.False (view.Focus ());
}
[Test]
public void FocusWithSubscriber ([Values(true, false)] bool result)
{
var view = new View ();
view.FocusChangeRequested += (sender, arg) => arg.Result = result;
Assert.True (view.Focus () == result);
}
[Test]
public void DoNotSignalWhenAlreadyFocused ()
{
var view = new View ();
view.SetValueCore (VisualElement.IsFocusedPropertyKey, true);
bool signaled = false;
view.FocusChangeRequested += (sender, args) => signaled = true;
Assert.True (view.Focus (), "View.Focus returned false");
Assert.False (signaled, "FocusRequested was raised");
}
[Test]
public void UnFocus ()
{
var view = new View ();
view.SetValueCore (VisualElement.IsFocusedPropertyKey, true);
var requested = false;
view.FocusChangeRequested += (sender, args) => {
requested = !args.Focus;
};
view.Unfocus ();
Assert.True (requested);
}
[Test]
public void UnFocusDoesNotFireWhenNotFocused ()
{
var view = new View ();
view.SetValueCore (VisualElement.IsFocusedPropertyKey, false);
var requested = false;
view.FocusChangeRequested += (sender, args) => {
requested = args.Focus;
};
view.Unfocus ();
Assert.False (requested);
}
[Test]
public void TestFocusedEvent ()
{
var view = new View ();
bool fired = false;
view.Focused += (sender, args) => fired = true;
view.SetValueCore (VisualElement.IsFocusedPropertyKey, true);
Assert.True (fired);
}
[Test]
public void TestUnFocusedEvent ()
{
var view = new View ();
view.SetValueCore (VisualElement.IsFocusedPropertyKey, true);
bool fired = false;
view.Unfocused += (sender, args) => fired = true;
view.SetValueCore (VisualElement.IsFocusedPropertyKey, false);
Assert.True (fired);
}
[Test]
public void TestOpenUriAction ()
{
var uri = new Uri ("http://www.xamarin.com/");
var invoked = false;
Device.PlatformServices = new MockPlatformServices (openUriAction: u => {
Assert.AreSame (uri, u);
invoked = true;
});
Device.OpenUri (uri);
Assert.True (invoked);
}
[Test]
public void OpenUriThrowsWhenNull ()
{
Device.PlatformServices = null;
var uri = new Uri ("http://www.xamarin.com/");
Assert.Throws<InvalidOperationException> (() => Device.OpenUri (uri));
}
[Test]
public void MinimumWidthRequest ()
{
var view = new View ();
bool signaled = false;
view.MeasureInvalidated += (sender, args) => signaled = true;
view.MinimumWidthRequest = 10;
Assert.True (signaled);
Assert.AreEqual (10, view.MinimumWidthRequest);
signaled = false;
view.MinimumWidthRequest = 10;
Assert.False (signaled);
}
[Test]
public void MinimumHeightRequest ()
{
var view = new View ();
bool signaled = false;
view.MeasureInvalidated += (sender, args) => signaled = true;
view.MinimumHeightRequest = 10;
Assert.True (signaled);
Assert.AreEqual (10, view.MinimumHeightRequest);
signaled = false;
view.MinimumHeightRequest = 10;
Assert.False (signaled);
}
[Test]
public void MinimumWidthRequestInSizeRequest ()
{
var view = new View {
IsPlatformEnabled = true
};
view.HeightRequest = 20;
view.WidthRequest = 200;
view.MinimumWidthRequest = 100;
var result = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
Assert.AreEqual (new Size (200, 20), result.Request);
Assert.AreEqual (new Size (100, 20), result.Minimum);
}
[Test]
public void MinimumHeightRequestInSizeRequest ()
{
var view = new View {
IsPlatformEnabled = true
};
view.HeightRequest = 200;
view.WidthRequest = 20;
view.MinimumHeightRequest = 100;
var result = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
Assert.AreEqual (new Size (20, 200), result.Request);
Assert.AreEqual (new Size (20, 100), result.Minimum);
}
[Test]
public void StartTimerSimple ()
{
Device.PlatformServices = new MockPlatformServices ();
var task = new TaskCompletionSource<bool> ();
Task.Factory.StartNew (() => Device.StartTimer (TimeSpan.FromMilliseconds (200), () => {
task.SetResult (false);
return false;
}));
task.Task.Wait ();
Assert.False (task.Task.Result);
Device.PlatformServices = null;
}
[Test]
public void StartTimerMultiple ()
{
Device.PlatformServices = new MockPlatformServices ();
var task = new TaskCompletionSource<int> ();
int steps = 0;
Task.Factory.StartNew (() => Device.StartTimer (TimeSpan.FromMilliseconds (200), () => {
steps++;
if (steps < 2)
return true;
task.SetResult (steps);
return false;
}));
task.Task.Wait ();
Assert.AreEqual (2, task.Task.Result);
Device.PlatformServices = null;
}
[Test]
public void BindingsApplyAfterViewAddedToParentWithContextSet()
{
var parent = new NaiveLayout();
parent.BindingContext = new MockViewModel { Text = "test" };
var child = new Entry();
child.SetBinding (Entry.TextProperty, new Binding ("Text"));
parent.Children.Add (child);
Assert.That (child.BindingContext, Is.SameAs (parent.BindingContext));
Assert.That (child.Text, Is.EqualTo ("test"));
}
[Test]
public void IdIsUnique ()
{
var view1 = new View ();
var view2 = new View ();
Assert.True (view1.Id != view2.Id);
}
[Test]
public void MockBounds ()
{
var view = new View ();
view.Layout (new Rectangle (10, 20, 30, 40));
bool changed = false;
view.PropertyChanged += (sender, args) => {
if (args.PropertyName == View.XProperty.PropertyName ||
args.PropertyName == View.YProperty.PropertyName ||
args.PropertyName == View.WidthProperty.PropertyName ||
args.PropertyName == View.HeightProperty.PropertyName)
changed = true;
};
view.SizeChanged += (sender, args) => changed = true;
view.MockBounds (new Rectangle (5, 10, 15, 20));
Assert.AreEqual (new Rectangle (5, 10, 15, 20), view.Bounds);
Assert.False (changed);
view.UnmockBounds ();
Assert.AreEqual (new Rectangle (10, 20, 30, 40), view.Bounds);
Assert.False (changed);
}
[Test]
public void AddGestureRecognizer ()
{
var view = new View ();
var gestureRecognizer = new TapGestureRecognizer ();
view.GestureRecognizers.Add (gestureRecognizer);
Assert.True (view.GestureRecognizers.Contains (gestureRecognizer));
}
[Test]
public void AddGestureRecognizerSetsParent ()
{
var view = new View ();
var gestureRecognizer = new TapGestureRecognizer ();
view.GestureRecognizers.Add (gestureRecognizer);
Assert.AreEqual (view, gestureRecognizer.Parent);
}
[Test]
public void RemoveGestureRecognizerUnsetsParent ()
{
var view = new View ();
var gestureRecognizer = new TapGestureRecognizer ();
view.GestureRecognizers.Add (gestureRecognizer);
view.GestureRecognizers.Remove (gestureRecognizer);
Assert.Null (gestureRecognizer.Parent);
}
[Test]
public void WidthRequestEffectsGetSizeRequest ()
{
var view = new View ();
view.IsPlatformEnabled = true;
view.WidthRequest = 20;
var request = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
Assert.AreEqual (new Size (20, 50), request.Request);
}
[Test]
public void HeightRequestEffectsGetSizeRequest ()
{
Device.PlatformServices = new MockPlatformServices (getNativeSizeFunc: (ve, widthConstraint, heightConstraint) => {
if (heightConstraint < 30)
return new SizeRequest (new Size (40, 50));
return new SizeRequest(new Size(20, 100));
});
var view = new View ();
view.IsPlatformEnabled = true;
view.HeightRequest = 20;
var request = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
Assert.AreEqual (new Size (40, 20), request.Request);
}
}
}