From 583bf7d9e20034cb8200627f5630ceea5be975dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Standa=20Luke=C5=A1?= Date: Fri, 20 Sep 2024 12:13:44 +0200 Subject: [PATCH] capabilities: fix assignment to default value of non-standard DotvvmProperty There was an inverted condition when compared to SetValueDirect. In most cases, SetValueDirect is used, except when the property is a DotvvmProperty with overriden GetValue/SetValue or is inherited --- .../DotvvmCapabilityProperty.Helpers.cs | 2 +- src/Tests/Runtime/CapabilityPropertyTests.cs | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/Framework/Framework/Binding/DotvvmCapabilityProperty.Helpers.cs b/src/Framework/Framework/Binding/DotvvmCapabilityProperty.Helpers.cs index ff6f5e2ad..a276c1b98 100644 --- a/src/Framework/Framework/Binding/DotvvmCapabilityProperty.Helpers.cs +++ b/src/Framework/Framework/Binding/DotvvmCapabilityProperty.Helpers.cs @@ -80,7 +80,7 @@ public static void SetOptionalValueOrBindingSlow(DotvvmBindableObject c, Dotv public static void SetValueOrBindingSlow(DotvvmBindableObject c, DotvvmProperty p, ValueOrBinding val) { var boxedVal = val.UnwrapToObject(); - if (Object.Equals(boxedVal, p.DefaultValue) && c.IsPropertySet(p)) + if (Object.Equals(boxedVal, p.DefaultValue) && !c.IsPropertySet(p)) { // setting to default value and the property is not set -> do nothing } diff --git a/src/Tests/Runtime/CapabilityPropertyTests.cs b/src/Tests/Runtime/CapabilityPropertyTests.cs index eac2acee2..2fc85ab26 100644 --- a/src/Tests/Runtime/CapabilityPropertyTests.cs +++ b/src/Tests/Runtime/CapabilityPropertyTests.cs @@ -237,6 +237,58 @@ public void BitMoreComplexCapability_InheritedProperties() Assert.AreEqual(null, control2.Nullable); } + [DataTestMethod] + [DataRow(typeof(TestControl6))] + [DataRow(typeof(TestControlFallbackProps))] + [DataRow(typeof(TestControlInheritedProps))] + public void BitMoreComplexCapability_SetDefaultValue(Type controlType) + { + var control1 = (DotvvmBindableObject)Activator.CreateInstance(controlType); + var capProp = DotvvmCapabilityProperty.Find(controlType, typeof(BitMoreComplexCapability)); + control1.SetValue(capProp, new BitMoreComplexCapability { NotNullable = 30, ValueOrBinding = new((int?)null) }); // default + // XAssert.Empty(control1.Properties); + Assert.AreEqual(30, control1.GetCapability().NotNullable); + Assert.AreEqual(null, control1.GetCapability().ValueOrBinding.GetValue()); + + control1.SetProperty("NotNullable", 1); + control1.SetProperty("ValueOrBinding", 2); + Assert.AreEqual(1, control1.GetCapability().NotNullable); + Assert.AreEqual(2, control1.GetCapability().ValueOrBinding.GetValue()); + + control1.SetValue(capProp, new BitMoreComplexCapability { NotNullable = 30, ValueOrBinding = new((int?)null) }); // reset defaults + Assert.AreEqual(30, control1.GetCapability().NotNullable); + Assert.AreEqual(null, control1.GetCapability().ValueOrBinding.GetValue()); + } + + [DataTestMethod] + [DataRow(typeof(TestControl6))] + [DataRow(typeof(TestControlFallbackProps))] + [DataRow(typeof(TestControlInheritedProps))] + public void BitMoreComplexCapability_SetEmptyValue(Type controlType) + { + var control1 = (DotvvmBindableObject)Activator.CreateInstance(controlType); + var capProp = DotvvmCapabilityProperty.Find(controlType, typeof(BitMoreComplexCapability)); + + Assert.IsFalse(control1.GetCapability().ValueOrBindingNullable.HasValue); + + var prop = controlType == typeof(TestControlFallbackProps) ? "ValueOrBindingNullable2" : "ValueOrBindingNullable"; + + control1.SetProperty(prop, null); + XAssert.Single(control1.Properties); + Assert.IsFalse(control1.GetCapability().ValueOrBindingNullable.HasValue); + + control1.SetProperty(prop, 1); + Assert.AreEqual(1, control1.GetCapability().ValueOrBindingNullable?.GetValue()); + + + control1.SetValue(capProp, new BitMoreComplexCapability { ValueOrBindingNullable = null }); // removes property + Assert.AreEqual(null, control1.GetCapability().ValueOrBindingNullable); + Assert.IsFalse(control1.IsPropertySet(control1.GetDotvvmProperty(prop))); + + control1.SetValue(capProp, new BitMoreComplexCapability { ValueOrBindingNullable = new(2) }); // sets new value + Assert.AreEqual(2, control1.GetCapability().ValueOrBindingNullable?.GetValue()); + } + [DataTestMethod] [DataRow(typeof(TestControl6))] [DataRow(typeof(TestControlFallbackProps))]