using System; using System.ComponentModel; using System.Drawing.Design; using System.Linq; using Core.Common.Gui.Attributes; using Core.Common.Gui.PropertyBag; using NUnit.Framework; namespace Core.Common.Gui.Test.PropertyBag { [TestFixture] public class DynamicPropertyBagTest { [Test] public void ParameteredConstructor_ExpectedValues() { // Setup var propertyObject = new object(); // Call var dynamicPropertyBag = new DynamicPropertyBag(propertyObject); // Assert CollectionAssert.IsEmpty(dynamicPropertyBag.Properties, "Object has no properties, therefore bag should have none too."); Assert.AreSame(propertyObject, dynamicPropertyBag.WrappedObject); } [Test] public void GivenTestProperties_WhenConstructing_ThenCorrectNumberOfPropertiesCreated() { // Setup var propertyObject = new TestProperties(); // Call var dynamicPropertyBag = new DynamicPropertyBag(propertyObject); // Assert Assert.AreEqual(4, dynamicPropertyBag.Properties.Count, "Expected property count wrong"); } [Test] public void GivenTestProperties_WhenConstructing_ThenPropertySpecsHaveAttributesSet() { // Setup var propertyObject = new TestProperties(); // Call var dynamicPropertyBag = new DynamicPropertyBag(propertyObject); // Assert var namePropertySpec = dynamicPropertyBag.Properties.First(ps => ps.Name == "Name"); CollectionAssert.Contains(namePropertySpec.Attributes, new System.ComponentModel.CategoryAttribute("General"), "Should have initialized Attributes of the property spec with declared Category(\"General\")."); var descriptionPropertySpec = dynamicPropertyBag.Properties.First(ps => ps.Name == "Description"); CollectionAssert.Contains(descriptionPropertySpec.Attributes, ReadOnlyAttribute.Yes, "Should have initialized Attributes of the property spec with declared ReadOnlyAttribute."); } [Test] public void ToString_ReturnToStringFromWrappedObject() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var text = dynamicPropertyBag.ToString(); // Assert Assert.AreEqual(target.ToString(), text); } [Test] public void GetAttributes_Always_ReturnEmpty() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var attributes = dynamicPropertyBag.GetAttributes(); // Assert CollectionAssert.IsEmpty(attributes); } [Test] public void GetClassName_Always_ReturnDynamicPropertyBagClassName() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var className = dynamicPropertyBag.GetClassName(); // Assert Assert.AreEqual(dynamicPropertyBag.GetType().FullName, className); } [Test] public void GetComponentName_Always_ReturnNull() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var componentName = dynamicPropertyBag.GetComponentName(); // Assert Assert.IsNull(componentName); } [Test] public void GetConverter_Always_ReturnDefaultTypeConverter() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var typeConverter = dynamicPropertyBag.GetConverter(); // Assert Assert.AreEqual(TypeDescriptor.GetConverter(dynamicPropertyBag, true), typeConverter); } [Test] public void GetDefaultEvent_Always_ReturnNull() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var eventDescriptor = dynamicPropertyBag.GetDefaultEvent(); // Assert Assert.IsNull(eventDescriptor); } [Test] public void GetEvents_Always_ReturnEmpty() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var events = dynamicPropertyBag.GetEvents(); // Assert CollectionAssert.IsEmpty(events); } [Test] public void GetEventsParametered_Always_ReturnEmpty() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var events = dynamicPropertyBag.GetEvents(new Attribute[0]); // Assert CollectionAssert.IsEmpty(events); } [Test] public void GetEditor_Always_ReturnNull() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var editor = dynamicPropertyBag.GetEditor(typeof(UITypeEditor)); // Assert Assert.IsNull(editor); } [Test] public void GetDefaultProperty_ObjectHasNotProperties_ReturnNull() { // Setup var dynamicPropertyBag = new DynamicPropertyBag(new object()); // Call var defaultProperty = dynamicPropertyBag.GetDefaultProperty(); // Assert Assert.IsNull(defaultProperty); } [Test] public void GetDefaultProperty_ObjectWithProperties_ReturnFirstFromProperties() { // Setup var target = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(target); // Call var defaultProperty = dynamicPropertyBag.GetDefaultProperty(); // Assert Assert.AreEqual(dynamicPropertyBag.Properties.First().Name, defaultProperty.Name); } [Test] public void DynamicPropertyBagResolvesDynamicVisibleAttributes() { var propertyObject = new TestProperties { Visible = true }; var dynamicPropertyBag = new DynamicPropertyBag(propertyObject); var propertyDescriptorCollection = ((ICustomTypeDescriptor) dynamicPropertyBag).GetProperties(new[] { new BrowsableAttribute(true) }); var namePropertyDescriptor = propertyDescriptorCollection.Find("Name", false); Assert.IsTrue(namePropertyDescriptor.IsBrowsable, "Name should be visible"); propertyObject.Visible = false; propertyDescriptorCollection = ((ICustomTypeDescriptor) dynamicPropertyBag).GetProperties(new[] { new BrowsableAttribute(true) }); namePropertyDescriptor = propertyDescriptorCollection.Find("Name", false); Assert.IsNull(namePropertyDescriptor, "Name should not be visible anymore"); } [Test] public void GetProperties_SomePropertiesWithOrderAttribute_ReturnElementsInDesiredOrdering() { // Setup var dynamicPropertyBag = new DynamicPropertyBag(new TestOrderedProperties()); // Call var propertyDescriptorCollection = dynamicPropertyBag.GetProperties(); // Assert var index = 0; Assert.AreEqual("PropTwo", propertyDescriptorCollection[index++].DisplayName); Assert.AreEqual("PropOne", propertyDescriptorCollection[index++].DisplayName); Assert.AreEqual("Description", propertyDescriptorCollection[index++].DisplayName); Assert.AreEqual("Name", propertyDescriptorCollection[index++].DisplayName); var propThreeDescriptor = propertyDescriptorCollection.Find("PropThree", false); Assert.GreaterOrEqual(propertyDescriptorCollection.IndexOf(propThreeDescriptor), index, "PropThree is not decorated with PropertyOrderAttribute, therefore should come after those that are."); var propFourDescriptor = propertyDescriptorCollection.Find("PropFour", false); Assert.GreaterOrEqual(propertyDescriptorCollection.IndexOf(propFourDescriptor), index, "PropFour is not decorated with PropertyOrderAttribute, therefore should come after those that are."); } [Test] public void DynamicPropertyBagWrapsNestedPropertyObjects() { // Setup var subProperties = new TestProperties { Name = "test" }; var testProperties = new TestWithNestedPropertiesClassProperties { SubProperties = subProperties }; var dynamicPropertyBag = new DynamicPropertyBag(testProperties); var propertiesCollection = dynamicPropertyBag.GetProperties(); // Call var wrappedValue = propertiesCollection[0].GetValue(dynamicPropertyBag.WrappedObject); // Assert var bag = (DynamicPropertyBag)wrappedValue; Assert.AreSame(subProperties, bag.WrappedObject); } [Test] public void GivenPropertyDescriptorFromDynamicPropertyBag_WhenSettingProperty_ThenWrappedObjectUpdated() { // Setup var testProperties = new TestProperties { Name = "name" }; var dynamicPropertyBag = new DynamicPropertyBag(testProperties); var newName = "newName"; // Call dynamicPropertyBag.GetProperties()["Name"].SetValue(testProperties, newName); // Assert Assert.AreEqual(newName, testProperties.Name); } [Test] public void GivenPropertiesWithoutPublicSetter_WhenGettingPropertyDescriptors_ThenPropertiesDecoratedWithReadOnlyAttribute() { // Setup var dynamicPropertyBag = new DynamicPropertyBag(new TestWithoutSetterPropertyClassProperties()); // Call var propertyDescriptorCollection = dynamicPropertyBag.GetProperties(); // Assert Assert.IsTrue(propertyDescriptorCollection[0].Attributes.Matches(ReadOnlyAttribute.Yes)); Assert.IsTrue(propertyDescriptorCollection[1].Attributes.Matches(ReadOnlyAttribute.Yes)); } [Test] public void GetProperties_RepeatedCallForSameState_RetainSameElementOrderAndContents() { // Setup var propertyObject = new TestOrderedProperties(); var dynamicPropertyBag = new DynamicPropertyBag(propertyObject); var originalProperties = dynamicPropertyBag.GetProperties(); // Call for (int i = 0; i < 100; i++) { var currentProperties = dynamicPropertyBag.GetProperties(); // Assert CollectionAssert.AreEqual(originalProperties, currentProperties); } } [Test] public void GetProperties_RepeatedConstructionsForSameState_RetainSameElementOrderAndContents() { // Setup var propertyObject = new TestOrderedProperties(); var originalProperties = new DynamicPropertyBag(propertyObject).GetProperties(); // Call for (int i = 0; i < 100; i++) { var currentProperties = new DynamicPropertyBag(propertyObject).GetProperties(); // Assert CollectionAssert.AreEqual(originalProperties, currentProperties); } } [Test] public void GetProperties_BrowsableTrueFilter_ReturnOnlyPropertiesThatAreBrowsable() { // Setup var propertyObject = new TestProperties { Visible = false }; var dynamicPropertyBag = new DynamicPropertyBag(propertyObject); // Call var properties = dynamicPropertyBag.GetProperties(new Attribute[] { BrowsableAttribute.Yes }); // Assert Assert.Less(properties.Count, dynamicPropertyBag.Properties.Count); Assert.IsNull(properties.Find("Name", false), "Name is dynamically not browsable, therefore should not be returned."); Assert.IsNotNull(properties.Find("Description", false)); Assert.IsNotNull(properties.Find("IsNameReadOnly", false)); Assert.IsNull(properties.Find("Visible", false), "Visible is statically not browsable, therefore should not be returned."); } [Test] public void GetProperties_BrowsableNoFilter_ReturnOnlyPropertiesThatAreBrowsable() { // Setup var propertyObject = new TestProperties { Visible = false }; var dynamicPropertyBag = new DynamicPropertyBag(propertyObject); // Call var properties = dynamicPropertyBag.GetProperties(new Attribute[] { BrowsableAttribute.No }); // Assert Assert.Less(properties.Count, dynamicPropertyBag.Properties.Count); Assert.IsNotNull(properties.Find("Name", false), "Name is dynamically not browsable, therefore should be returned."); Assert.IsNull(properties.Find("Description", false)); Assert.IsNull(properties.Find("IsNameReadOnly", false)); Assert.IsNotNull(properties.Find("Visible", false), "Visible is statically not browsable, therefore should be returned."); } [Test] public void GetPropertyOwner_Always_ReturnWrappedObject() { // Setup var propertyObject = new TestProperties(); var dynamicPropertyBag = new DynamicPropertyBag(propertyObject); // Call var owner = dynamicPropertyBag.GetPropertyOwner(null); // Assert Assert.AreSame(propertyObject, owner); } #region Test Classes private class TestOrderedProperties { [PropertyOrder(3)] public string Name { get; set; } [PropertyOrder(2)] public string Description { get; set; } [PropertyOrder(1)] public string PropOne { get; set; } [PropertyOrder(0)] public string PropTwo { get; set; } public int PropThree { get; set; } public int PropFour { get; set; } } private class TestWithNestedPropertiesClassProperties { [TypeConverter(typeof(ExpandableObjectConverter))] public TestProperties SubProperties { get; set; } } private class TestProperties { public TestProperties() { Name = "my name"; Description = "short description"; Visible = true; IsNameReadOnly = true; } /// /// Dynamic property. ReadOnly when IsNameReadOnly true. /// [DynamicReadOnly] [DynamicVisible] [System.ComponentModel.Category("General")] public string Name { get; set; } [Browsable(true)] public bool IsNameReadOnly { get; set; } [Browsable(false)] public bool Visible { get; set; } [ReadOnly(true)] //one static property public string Description { get; set; } /// /// Method checks if propertyName property is read-only (setter can be used). /// /// /// [DynamicReadOnlyValidationMethod] public bool DynamicReadOnlyValidationMethod(string propertyName) { Assert.IsTrue(propertyName == "Name"); return IsNameReadOnly; } [DynamicVisibleValidationMethod] public bool DynamicVisibleValidationMethod(string propertyName) { return Visible; } public override string ToString() { return Name; } } private class TestWithoutSetterPropertyClassProperties { public string PrivateSetter { get; private set; } public string NoSetter { get { return ""; } } } #endregion } }