using System; using NUnit.Framework; using System.ComponentModel; using Xamarin.Forms.Maps; using System.Windows.Input; namespace Xamarin.Forms.Core.UnitTests { [TestFixture] public class NotifiedPropertiesTests : BaseTestFixture { public abstract class PropertyTestCase { public string Name { get; set;} public Func PropertyGetter { get; set; } public Action PropertySetter { get; set; } public object ExpectedDefaultValue { get; set; } public object TestValue { get; set; } public abstract INotifyPropertyChanged CreateView (); public virtual string DebugName { get { return Name; } } } public class PropertyTestCase:PropertyTestCase where TView : INotifyPropertyChanged { Func init; Func expectedValueCreator; public PropertyTestCase (string name, Func propertyGetter, Action propertySetter, Func expectedDefaultValue, TProperty testValue, Func init = null) { Name = name; PropertyGetter = v => propertyGetter((TView)v); PropertySetter = (v,o)=> propertySetter ((TView)v, (TProperty)o); expectedValueCreator = expectedDefaultValue; TestValue = testValue; this.init = init; } public override INotifyPropertyChanged CreateView () { ExpectedDefaultValue = expectedValueCreator (); if (init != null) return init (); if (typeof(TView) == typeof(View)) return new View (); return (TView)Activator.CreateInstance (typeof(TView), new object[]{ }); } public override string DebugName { get { return typeof(TView).Name + "." + Name; } } } static PropertyTestCase[] Properties = { new PropertyTestCase ("Resources", v => v.Resources, (v, o) => v.Resources = o, () => null, new ResourceDictionary ()), new PropertyTestCase ("InputTransparent", v => v.InputTransparent, (v, o) => v.InputTransparent = o, () => false, true), new PropertyTestCase ("Scale", v => v.Scale, (v, o) => v.Scale = o, () => 1d, 2d), new PropertyTestCase ("Rotation", v => v.Rotation, (v, o) => v.Rotation = o, () => 0d, 90d), new PropertyTestCase ("RotationX", v => v.RotationX, (v, o) => v.RotationX = o, () => 0d, 90d), new PropertyTestCase ("RotationY", v => v.RotationY, (v, o) => v.RotationY = o, () => 0d, 90d), new PropertyTestCase ("AnchorX", v => v.AnchorX, (v, o) => v.AnchorX = o, () => 0.5d, 0d), new PropertyTestCase ("AnchorY", v => v.AnchorY, (v, o) => v.AnchorY = o, () => 0.5d, 0d), new PropertyTestCase ("TranslationX", v => v.TranslationX, (v, o) => v.TranslationX = o, () => 0d, 20d), new PropertyTestCase ("TranslationY", v => v.TranslationY, (v, o) => v.TranslationY = o, () => 0d, 20d), new PropertyTestCase ("Opacity", v => v.Opacity, (v, o) => v.Opacity = o, () => 1d, 0.5d), new PropertyTestCase ("IsEnabled", v => v.IsEnabled, (v, o) => v.IsEnabled = o, () => true, false), new PropertyTestCase ("IsVisible", v => v.IsVisible, (v, o) => v.IsVisible = o, () => true, false), new PropertyTestCase ("ClassId", v => v.ClassId, (v, o) => v.ClassId = o, () => null, "Foo"), new PropertyTestCase ("IsRunning", v => v.IsRunning, (v, o) => v.IsRunning = o, () => false, true), new PropertyTestCase ("Color", v => v.Color, (v, o) => v.Color = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"), new PropertyTestCase ("TextColor", v => v.TextColor, (v, o) => v.TextColor = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("Font", v => v.Font, (v, o) => v.Font = o, () => default (Font), Font.SystemFontOfSize (20)), new PropertyTestCase ("BorderWidth", v => v.BorderWidth, (v, o) => v.BorderWidth = o, () => 0d, 16d), new PropertyTestCase ("BorderRadius", v => v.BorderRadius, (v, o) => v.BorderRadius = o, () => 5, 12), new PropertyTestCase ("BorderColor", v => v.BorderColor, (v, o) => v.BorderColor = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("FontFamily", v => v.FontFamily, (v, o) => v.FontFamily = o, () => null, "TestingFace"), new PropertyTestCase ("FontSize", v => v.FontSize, (v, o) => v.FontSize = o, () => Device.GetNamedSize (NamedSize.Default, typeof (Button), true), 123.0), new PropertyTestCase ("FontAttributes", v => v.FontAttributes, (v, o) => v.FontAttributes = o, () => FontAttributes.None, FontAttributes.Italic), new PropertyTestCase ("Height", v => v.Height, (v, o) => v.Height = o, () => -1, 10), new PropertyTestCase ("MinimumDate", v => v.MinimumDate, (v, o) => v.MinimumDate = o, () => new DateTime (1900, 1, 1), new DateTime (2014, 02, 05)), new PropertyTestCase ("MaximumDate", v => v.MaximumDate, (v, o) => v.MaximumDate = o, () => new DateTime (2100, 12, 31), new DateTime (2014, 02, 05)), new PropertyTestCase ("Date", v => v.Date, (v, o) => v.Date = o, () => DateTime.Now.Date, new DateTime (2008, 5, 5)), new PropertyTestCase ("Format", v => v.Format, (v, o) => v.Format = o, () => "d", "D"), new PropertyTestCase ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"), new PropertyTestCase ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"), new PropertyTestCase ("Placeholder", v => v.Placeholder, (v, o) => v.Placeholder = o, () => null, "Foo"), new PropertyTestCase ("IsPassword", v => v.IsPassword, (v, o) => v.IsPassword = o, () => false, true), new PropertyTestCase ("TextColor", v => v.TextColor, (v, o) => v.TextColor = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("BackgroundColor", v => v.BackgroundColor, (v, o) => v.BackgroundColor = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("OutlineColor", v => v.OutlineColor, (v, o) => v.OutlineColor = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("HasShadow", v => v.HasShadow, (v, o) => v.HasShadow = o, () => true, false), new PropertyTestCase ("RowSpacing", v => v.RowSpacing, (v, o) => v.RowSpacing = o, () => 6, 12), new PropertyTestCase ("ColumnSpacing", v => v.ColumnSpacing, (v, o) => v.ColumnSpacing = o, () => 6, 12), new PropertyTestCase ("Padding", v => v.Padding, (v, o) => v.Padding = o, () => default(Thickness), new Thickness (20, 20, 10, 10)), new PropertyTestCase ("Source", v => v.Source, (v, o) => v.Source = o, () => null, ImageSource.FromFile("Foo")), new PropertyTestCase ("Aspect", v => v.Aspect, (v, o) => v.Aspect = o, () => Aspect.AspectFit, Aspect.AspectFill), new PropertyTestCase ("IsOpaque", v => v.IsOpaque, (v, o) => v.IsOpaque = o, () => false, true), new PropertyTestCase ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"), new PropertyTestCase ("XAlign", v => v.XAlign, (v, o) => v.XAlign = o, () => TextAlignment.Start, TextAlignment.End), new PropertyTestCase ("YAlign", v => v.YAlign, (v, o) => v.YAlign = o, () => TextAlignment.Start, TextAlignment.End), new PropertyTestCase ("TextColor", v => v.TextColor, (v, o) => v.TextColor = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("LineBreakMode", v => v.LineBreakMode, (v, o) => v.LineBreakMode = o, () => LineBreakMode.WordWrap, LineBreakMode.TailTruncation), new PropertyTestCase ("Font", v => v.Font, (v, o) => v.Font = o, () => default (Font), Font.SystemFontOfSize (12)), new PropertyTestCase ("FontFamily", v => v.FontFamily, (v, o) => v.FontFamily = o, () => null, "TestingFace"), new PropertyTestCase ("FontSize", v => v.FontSize, (v, o) => v.FontSize = o, () => Device.GetNamedSize (NamedSize.Default, typeof (Label), true), 123.0), new PropertyTestCase ("FontAttributes", v => v.FontAttributes, (v, o) => v.FontAttributes = o, () => FontAttributes.None, FontAttributes.Italic), new PropertyTestCase ("FormattedText", v => v.FormattedText, (v, o) => v.FormattedText = o, () => default (FormattedString), new FormattedString()), new PropertyTestCase ("MapType", v => v.MapType, (v, o) => v.MapType = o, () => MapType.Street, MapType.Satellite), new PropertyTestCase ("IsShowingUser", v => v.IsShowingUser, (v, o) => v.IsShowingUser = o, () => false, true), new PropertyTestCase ("HasScrollEnabled", v => v.HasScrollEnabled, (v, o) => v.HasScrollEnabled = o, () => true, false), new PropertyTestCase ("HasZoomEnabled", v => v.HasZoomEnabled, (v, o) => v.HasZoomEnabled = o, () => true, false), new PropertyTestCase ("HasRenderLoop", v => v.HasRenderLoop, (v, o) => v.HasRenderLoop = o, () => false, true), new PropertyTestCase ("BackgroundImage", v => v.BackgroundImage, (v, o) => v.BackgroundImage = o, () => null, "Foo"), new PropertyTestCase ("BackgroundColor", v => v.BackgroundColor, (v, o) => v.BackgroundColor = o, () => default(Color), new Color (0, 1, 0)), new PropertyTestCase ("Title", v => v.Title, (v, o) => v.Title = o, () => null, "Foo"), new PropertyTestCase ("IsBusy", v => v.IsBusy, (v, o) => v.IsBusy = o, () => false, true), new PropertyTestCase ("IgnoresContainerArea", v => v.IgnoresContainerArea, (v, o) => v.IgnoresContainerArea = o, () => false, true), new PropertyTestCase ("Padding", v => v.Padding, (v, o) => v.Padding = o, () => default(Thickness), new Thickness (12)), new PropertyTestCase ("Title", v=>v.Title, (v, o) =>v.Title = o, () => null, "FooBar"), new PropertyTestCase ("SelectedIndex", v=>v.SelectedIndex, (v, o) =>v.SelectedIndex = o, () => -1, 2, ()=>new Picker{Items= {"Foo", "Bar", "Baz", "Qux"}}), new PropertyTestCase ("Progress", v => v.Progress, (v, o) => v.Progress = o, () => 0, .5), new PropertyTestCase ("Placeholder", v => v.Placeholder, (v, o) => v.Placeholder = o, () => null, "Foo"), new PropertyTestCase ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"), new PropertyTestCase ("Minimum", v => v.Minimum, (v, o) => v.Minimum = o, () => 0, .5), new PropertyTestCase ("Maximum", v => v.Maximum, (v, o) => v.Maximum = o, () => 1, .5), new PropertyTestCase ("Value", v => v.Value, (v, o) => v.Value = o, () => 0, .5), new PropertyTestCase ("Orientation", v => v.Orientation, (v, o) => v.Orientation = o, () => StackOrientation.Vertical, StackOrientation.Horizontal), new PropertyTestCase ("Spacing", v => v.Spacing, (v, o) => v.Spacing = o, () => 6, 12), new PropertyTestCase ("Minimum", v => v.Minimum, (v, o) => v.Minimum = o, () => 0, 50), new PropertyTestCase ("Maximum", v => v.Maximum, (v, o) => v.Maximum = o, () => 100, 50), new PropertyTestCase ("Value", v => v.Value, (v, o) => v.Value = o, () => 0, 50), new PropertyTestCase ("Increment", v => v.Increment, (v, o) => v.Increment = o, () => 1, 2), new PropertyTestCase ("Title", v => v.Title, (v, o) => v.Title = o, () => null, "Foo"), new PropertyTestCase ("RowHeight", v => v.RowHeight, (v, o) => v.RowHeight = o, () => -1, 20), new PropertyTestCase ("HasUnevenRows", v => v.HasUnevenRows, (v, o) => v.HasUnevenRows = o, () => false, true), new PropertyTestCase ("Intent", v => v.Intent, (v, o) => v.Intent = o, () => TableIntent.Data, TableIntent.Menu), new PropertyTestCase ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"), new PropertyTestCase ("Detail", v => v.Detail, (v, o) => v.Detail = o, () => null, "Foo"), new PropertyTestCase ("TextColor", v => v.TextColor, (v, o) => v.TextColor = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("DetailColor", v => v.DetailColor, (v, o) => v.DetailColor = o, () => Color.Default, new Color (0, 1, 0)), new PropertyTestCase ("Time", v => v.Time, (v, o) => v.Time = o, () => default(TimeSpan), new TimeSpan (8, 0, 0)), new PropertyTestCase ("Format", v => v.Format, (v, o) => v.Format = o, () => "t", "T"), new PropertyTestCase ("View", v => v.View, (v, o) => v.View = o, () => null, new View ()), new PropertyTestCase ("Source", v => v.Source, (v, o) => v.Source = o, () => null, new UrlWebViewSource { Url = "Foo" }), new PropertyTestCase ("NumberOfTapsRequired", t => t.NumberOfTapsRequired, (t, o) => t.NumberOfTapsRequired = o, () => 1, 3), new PropertyTestCase ("CommandParameter", t => t.CommandParameter, (t, o) => t.CommandParameter = o, () => null, "Test"), new PropertyTestCase ("Command", t => t.Command, (t, o) => t.Command = o, () => null, new Command(()=>{})), new PropertyTestCase ("IsGestureEnabled", md => md.IsGestureEnabled, (md, v) => md.IsGestureEnabled = v, () => true, false) }; [SetUp] public override void Setup () { base.Setup (); Device.PlatformServices = new MockPlatformServices (); } [TearDown] public override void TearDown () { base.TearDown (); Device.PlatformServices = null; } [Test, TestCaseSource ("Properties")] public void DefaultValues (PropertyTestCase property) { var view = property.CreateView (); Assert.AreEqual (property.ExpectedDefaultValue, property.PropertyGetter (view), property.DebugName); } [Test, TestCaseSource ("Properties")] public void Set (PropertyTestCase property) { var view = property.CreateView (); bool changed = false; view.PropertyChanged += (sender, args) => { if (args.PropertyName == property.Name) changed = true; }; var testvalue = property.TestValue; property.PropertySetter (view, testvalue); Assert.True (changed, property.DebugName); Assert.AreEqual (testvalue, property.PropertyGetter (view), property.DebugName); } [Test, TestCaseSource ("Properties")] public void DoubleSet (PropertyTestCase property) { var view = property.CreateView (); var testvalue = property.TestValue; property.PropertySetter (view, testvalue); bool changed = false; view.PropertyChanged += (sender, args) => { if (args.PropertyName == property.Name) changed = true; }; property.PropertySetter (view, testvalue); Assert.False (changed, property.DebugName); Assert.AreEqual (testvalue, property.PropertyGetter (view), property.DebugName); } } }