public void SubModel_notifies_Root_validator_only_when_validity_changed()
        {
            var root = new RootModel();
            Assert.That(root.Validator.IsValid, Is.False);

            var notified = false;
            var validator = root.Validator;
            validator.PropertyChanged += (_, e) =>
            {
                if (e.PropertyName == "IsValid")
                    notified = true;
            };

            root.SubModel.NumberSetting = -1;
            Assert.That(root.Validator.IsValid, Is.False);
            Assert.That(notified, Is.False);

            root.SubModel.NumberSetting = 2;
            root.SubModel.StringSetting = "!";

            Assert.That(root.Validator.IsValid, Is.True);
            Assert.That(notified, Is.True);
        }
        public void When_SubModel_validated_by_UI_Then_RootModel_should_reflect_that()
        {
            var root = new RootModel();
            Assert.That(root.Validator.IsValid, Is.False);
            Assert.That(root.Validator.Errors["SubModel"], Is.EqualTo("Invalid"));

            root.SubModel.StringSetting = "Not empty value";
            Assert.That(root.Validator.IsValid, Is.True);
            Assert.That(root.Validator.Errors["SubModel"], Is.Null);
        }
        public void Only_parent_could_enable_property_validation_disabled_by_parent_After_it_was_disabled_by_property()
        {
            var root = new RootModel();
            root.SubModel.Validator.Enabled = false;                // disable property validation
            root.Validator.Enabled = false;                         // disable root validation, for property it changes nothing cause it was already disabled

            root.SubModel.Validator.Enabled = true;                 // try to enable property validation

            Assert.That(root.SubModel.Validator.Enabled, Is.False); // check that it is prevented, cause root is still disabled
        }
        public void Should_notify_when_property_with_validator_is_reassigned()
        {
            var root = new RootModel();
            Assert.That(root.Validator.IsValid, Is.False);

            var notified = false;
            root.Validator.PropertyChanged += (_, e) =>
            {
                if (e.PropertyName == "IsValid")
                    notified = true;
            };

            root.SubModel = new SubModel { StringSetting = "!" };

            Assert.That(notified, Is.True);
            Assert.That(root.Validator.IsValid, Is.True);
        }
        public void No_memory_leak_when_property_with_validator_is_reassigned()
        {
            var root = new RootModel();
            var rootWeakRef = new WeakReference(root);

            var oldSubModel = root.SubModel;
            root.SubModel = new SubModel { StringSetting = "!" };

            root = null;
            GC.Collect(GC.MaxGeneration);

            Assert.That(rootWeakRef.IsAlive, Is.False);
            GC.KeepAlive(oldSubModel);
        }
        public void Only_parent_could_enable_property_validation_disabled_by_parent()
        {
            var root = new RootModel();
            root.Validator.Enabled = false;                         // disable root validation
            root.SubModel.Validator.Enabled = true;                 // then try to enable property validation
            Assert.That(root.SubModel.Validator.Enabled, Is.False); // check that enabling property is failed, prevented by parent.

            root.Validator.Enabled = true;                          // enable root validation

            Assert.That(root.SubModel.Validator.Enabled, Is.True);  // check that property enabled too
        }
        public void Enabling_validation_should_revalidate_model()
        {
            var root = new RootModel();
            root.Validator.Enabled = false;
            Assert.That(root.Validator.IsValid, Is.True);

            root.Validator.Enabled = true;
            Assert.That(root.Validator.IsValid, Is.False);
        }
        public void Disabling_validation_should_notify_That_all_model_properties_changed_In_order_to_reset_UI()
        {
            var root = new RootModel();
            var invalidated = false;
            root.PropertyChanged += (sender, e) =>
                invalidated = string.IsNullOrEmpty(e.PropertyName);

            root.Validator.Enabled = false;

            Assert.That(invalidated, Is.True);
        }
        public void Disabling_validation_for_root_should_disable_sub_models()
        {
            var root = new RootModel();
            root.Validator.Enabled = false;

            Assert.That(root.SubModel.Validator.Enabled, Is.False);
        }
        public void Disabling_property_enabled_by_parent_should_work()
        {
            var root = new RootModel();
            root.Validator.Enabled = true;                          // enable root validation, no effect cause it was enabled by default

            root.SubModel.Validator.Enabled = false;                // disable property validation

            Assert.That(root.SubModel.Validator.Enabled, Is.False); // check that property validation is successfully disabled
        }
        public void Disabled_parent_should_prevent_enabling_of_property_validation()
        {
            var root = new RootModel();
            root.Validator.Enabled = false;                         // disable parent validation
            Assert.That(root.SubModel.Validator.Enabled, Is.False); // check that property validation disabled too

            root.SubModel.Validator.Enabled = true;                 // enable root validation

            Assert.That(root.SubModel.Validator.Enabled, Is.False); // check that property enabled too
        }