diff options
Diffstat (limited to 'Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs')
-rw-r--r-- | Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs | 868 |
1 files changed, 868 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs b/Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs new file mode 100644 index 00000000..97700ca4 --- /dev/null +++ b/Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs @@ -0,0 +1,868 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Threading.Tasks; + +using NUnit.Framework; + +namespace Xamarin.Forms.Core.UnitTests +{ + [TestFixture] + public class ViewUnitTests : BaseTestFixture + { + [SetUp] + public override void Setup () + { + base.Setup (); + Device.PlatformServices = new MockPlatformServices (); + } + + [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, + Platform = new UnitPlatform () + }; + + 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; + + Device.OS = TargetPlatform.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; + + Device.OS = TargetPlatform.Android; + + Device.OnPlatform ( + iOS: () => ios = true, + Android: () => android = true, + WinPhone: () => winphone = true); + + Assert.False (ios); + Assert.True (android); + Assert.False (winphone); + } + + [Test] + public void TestOnPlatformWinPhone () + { + var view = new View (); + + bool ios = false; + bool android = false; + bool winphone = false; + + Device.OS = TargetPlatform.WinPhone; + + Device.OnPlatform ( + iOS: () => ios = true, + Android: () => android = true, + WinPhone: () => winphone = true); + + Assert.False (ios); + Assert.False (android); + Assert.True (winphone); + } + + [Test] + public void TestOnPlatformDefault () + { + var view = new View (); + + bool ios = false; + bool android = false; + + Device.OS = TargetPlatform.Android; + + Device.OnPlatform ( + iOS: () => ios = false, + Default: () => android = true); + + Assert.False (ios); + Assert.True (android); + } + + [Test] + public void TestOnPlatformNoOpWithoutDefault () + { + bool any = false; + Device.OS = TargetPlatform.Other; + + Device.OnPlatform ( + iOS: () => any = true, + Android: () => any = true, + WinPhone: () => any = true); + + Assert.False (any); + } + + [Test] + public void TestDefaultOniOS () + { + bool defaultExecuted = false; + + Device.OS = TargetPlatform.iOS; + + Device.OnPlatform ( + Android: () => { }, + WinPhone: () => { }, + Default:() => defaultExecuted = true); + + Assert.True (defaultExecuted); + } + + [Test] + public void TestDefaultOnAndroid () + { + bool defaultExecuted = false; + + Device.OS = TargetPlatform.Android; + + Device.OnPlatform ( + iOS: () => { }, + WinPhone: () => { }, + Default:() => defaultExecuted = true); + + Assert.True (defaultExecuted); + } + + [Test] + public void TestDefaultOnWinPhone () + { + bool defaultExecuted = false; + + Device.OS = TargetPlatform.WinPhone; + + Device.OnPlatform ( + iOS: () => { }, + Android: () => { }, + Default:() => defaultExecuted = true); + + Assert.True (defaultExecuted); + } + + [Test] + public void TestDefaultOnOther () + { + bool defaultExecuted = false; + + Device.OS = TargetPlatform.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 void TestFadeTo () + { + var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()}; + Ticker.Default = new BlockingTicker (); + + view.FadeTo (0.1); + + Assert.True (Math.Abs (0.1 - view.Opacity) < 0.001); + } + + [Test] + public void TestTranslateTo () + { + var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()}; + Ticker.Default = new BlockingTicker (); + + view.TranslateTo (100, 50); + + Assert.AreEqual (100, view.TranslationX); + Assert.AreEqual (50, view.TranslationY); + } + + [Test] + public void ScaleTo () + { + var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()}; + Ticker.Default = new BlockingTicker (); + + 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 void TestRotateTo () + { + var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()}; + Ticker.Default = new BlockingTicker (); + + view.RotateTo (25); + + Assert.That (view.Rotation, Is.EqualTo (25).Within (0.001)); + } + + [Test] + public void TestRotateYTo () + { + var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()}; + Ticker.Default = new BlockingTicker (); + + view.RotateYTo (25); + + Assert.That (view.RotationY, Is.EqualTo (25).Within (0.001)); + } + + [Test] + public void TestRotateXTo () + { + var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()}; + Ticker.Default = new BlockingTicker (); + + view.RotateXTo (25); + + Assert.That (view.RotationX, Is.EqualTo (25).Within (0.001)); + } + + [Test] + public void TestRelRotateTo () + { + var view = new View {Rotation = 30, IsPlatformEnabled = true, Platform = new UnitPlatform ()}; + Ticker.Default = new BlockingTicker (); + + view.RelRotateTo (20); + + Assert.That (view.Rotation, Is.EqualTo (50).Within (0.001)); + } + + [Test] + public void TestRelScaleTo () + { + var view = new View {Scale = 1, IsPlatformEnabled = true, Platform = new UnitPlatform ()}; + Ticker.Default = new BlockingTicker (); + + 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 () + { + Device.OS = TargetPlatform.WinPhone; + Assert.AreEqual (3, Device.OnPlatform (1, 2, 3)); + + Device.OS = TargetPlatform.iOS; + Assert.AreEqual (1, Device.OnPlatform (1, 2, 3)); + + Device.OS = TargetPlatform.Android; + Assert.AreEqual (2, Device.OnPlatform (1, 2, 3)); + + Device.OS = TargetPlatform.Other; + Assert.AreEqual (1, Device.OnPlatform (1, 2, 3)); + } + + [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 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 PlatformSet () + { + var view = new View (); + bool set = false; + view.PlatformSet += (sender, args) => set = true; + + view.Platform = new UnitPlatform (); + + Assert.True (set); + } + + [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 TestBeginInvokeOnMainThread () + { + Device.PlatformServices = new MockPlatformServices (invokeOnMainThread: action => action ()); + + bool invoked = false; + Device.BeginInvokeOnMainThread (() => invoked = true); + + Assert.True (invoked); + } + + [Test] + public void InvokeOnMainThreadThrowsWhenNull () + { + Device.PlatformServices = null; + Assert.Throws<InvalidOperationException>(() => Device.BeginInvokeOnMainThread (() => { })); + } + + [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 { + Platform = new UnitPlatform (), + 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 { + Platform = new UnitPlatform (), + 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.Platform = new UnitPlatform ((ve, widthConstraint, heightConstraint) => { + if (widthConstraint < 30) + return new SizeRequest (new Size (40, 50)); + return new SizeRequest(new Size(20, 100)); + }); + + view.WidthRequest = 20; + var request = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity); + + Assert.AreEqual (new Size (20, 50), request.Request); + } + + [Test] + public void HeightRequestEffectsGetSizeRequest () + { + var view = new View (); + view.IsPlatformEnabled = true; + view.Platform = new UnitPlatform ((ve, widthConstraint, heightConstraint) => { + if (heightConstraint < 30) + return new SizeRequest (new Size (40, 50)); + return new SizeRequest(new Size(20, 100)); + }); + + view.HeightRequest = 20; + var request = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity); + + Assert.AreEqual (new Size (40, 20), request.Request); + } + } +} |