Example #1
0
    public void ShouldSupportDelayedViewModelInitialization()
    {
        var view = new TestView
        {
            NameErrorLabel     = string.Empty,
            NameErrorContainer = { Text = string.Empty }
        };

        view.Bind(view.ViewModel, x => x.Name, x => x.NameLabel);
        view.BindValidation(view.ViewModel, x => x.Name, x => x.NameErrorLabel);
        view.BindValidation(view.ViewModel, x => x.NameErrorContainer.Text);

        Assert.Empty(view.NameErrorLabel);
        Assert.Empty(view.NameErrorContainer.Text);

        const string errorMessage = "Name shouldn't be empty.";
        var          viewModel    = new TestViewModel();

        viewModel.ValidationRule(x => x.Name, x => !string.IsNullOrWhiteSpace(x), errorMessage);
        view.ViewModel = viewModel;

        Assert.NotEmpty(view.NameErrorLabel);
        Assert.NotEmpty(view.NameErrorContainer.Text);
        Assert.Equal(errorMessage, view.NameErrorLabel);
        Assert.Equal(errorMessage, view.NameErrorContainer.Text);
    }
        public void ShouldDetachAndDisposeTheComponentWhenValidationHelperDisposes()
        {
            const string nameErrorMessage  = "Name shouldn't be empty.";
            const string name2ErrorMessage = "Name shouldn't be empty.";
            var          view = new TestView(new TestViewModel {
                Name = string.Empty
            });
            var nameRule = view.ViewModel.ValidationRule(
                viewModel => viewModel.Name,
                name => !string.IsNullOrWhiteSpace(name),
                nameErrorMessage);

            var name2Rule = view.ViewModel.ValidationRule(
                viewModel => viewModel.Name2,
                name => !string.IsNullOrWhiteSpace(name),
                name2ErrorMessage);

            view.Bind(view.ViewModel, x => x.Name, x => x.NameLabel);
            view.BindValidation(view.ViewModel, x => x.Name, x => x.NameErrorLabel);
            view.BindValidation(view.ViewModel, x => x.Name2, x => x.Name2ErrorLabel);

            Assert.Equal(2, view.ViewModel.ValidationContext.Validations.Count);
            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(nameErrorMessage, view.NameErrorLabel);
            Assert.Equal(name2ErrorMessage, view.Name2ErrorLabel);

            nameRule.Dispose();

            Assert.Equal(1, view.ViewModel.ValidationContext.Validations.Count);
            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Empty(view.NameErrorLabel);
            Assert.Equal(name2ErrorMessage, view.Name2ErrorLabel);

            name2Rule.Dispose();

            Assert.Equal(0, view.ViewModel.ValidationContext.Validations.Count);
            Assert.True(view.ViewModel.ValidationContext.IsValid);
            Assert.Empty(view.NameErrorLabel);
            Assert.Empty(view.Name2ErrorLabel);

            view.ViewModel.ValidationRule(
                viewModel => viewModel.Name,
                name => !string.IsNullOrWhiteSpace(name),
                nameErrorMessage);

            Assert.Equal(1, view.ViewModel.ValidationContext.Validations.Count);
            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(nameErrorMessage, view.NameErrorLabel);
            Assert.Empty(view.Name2ErrorLabel);
        }
        public void ShouldSupportBindingTwoValidationsForOneProperty()
        {
            const int minimumLength             = 5;
            var       minimumLengthErrorMessage = $"Minimum length is {minimumLength}";
            var       view = new TestView(new TestViewModel {
                Name = "some"
            });

            view.ViewModel.ValidationRule(
                vm => vm.Name,
                s => !string.IsNullOrEmpty(s),
                "Name is required.");

            view.ViewModel.ValidationRule(
                vm => vm.Name,
                s => s.Length > minimumLength,
                s => minimumLengthErrorMessage);

            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);
            view.BindValidation(view.ViewModel, vm => vm.Name, v => v.NameErrorLabel);

            view.ViewModel.Name = "som";

            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(2, view.ViewModel.ValidationContext.Validations.Count);

            // Checks if second validation error message is shown
            Assert.Equal(minimumLengthErrorMessage, view.NameErrorLabel);
        }
        public void ShouldSupportBindingModelObservableValidationHelperProperties()
        {
            const string namesShouldMatchMessage = "Names should match.";
            var          view = new TestView(new TestViewModel
            {
                Name  = "Bingo",
                Name2 = "Bongo"
            });

            view.ViewModel.NameRule = view
                                      .ViewModel
                                      .ValidationRule(
                vm => vm.Name2,
                view.ViewModel.WhenAnyValue(x => x.Name, x => x.Name2, (name, name2) => name == name2),
                namesShouldMatchMessage);

            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);
            view.Bind(view.ViewModel, vm => vm.Name2, v => v.Name2Label);
            view.BindValidation(view.ViewModel, vm => vm.NameRule, v => v.NameErrorLabel);

            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Single(view.ViewModel.ValidationContext.Validations);
            Assert.Equal(namesShouldMatchMessage, view.NameErrorLabel);

            view.ViewModel.Name  = "Bongo";
            view.ViewModel.Name2 = "Bongo";

            Assert.True(view.ViewModel.ValidationContext.IsValid);
            Assert.Single(view.ViewModel.ValidationContext.Validations);
            Assert.Empty(view.NameErrorLabel);
        }
        public void ShouldSupportBindingValidationHelperProperties()
        {
            const string nameErrorMessage = "Name should not be empty.";
            var          view             = new TestView(new TestViewModel {
                Name = string.Empty
            });

            view.ViewModel.NameRule = view
                                      .ViewModel
                                      .ValidationRule(
                viewModelProperty => viewModelProperty.Name,
                s => !string.IsNullOrEmpty(s),
                nameErrorMessage);

            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);
            view.BindValidation(view.ViewModel, vm => vm.NameRule, v => v.NameErrorLabel);

            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Single(view.ViewModel.ValidationContext.Validations);
            Assert.Equal(nameErrorMessage, view.NameErrorLabel);

            view.ViewModel.Name = "Jonathan";

            Assert.True(view.ViewModel.ValidationContext.IsValid);
            Assert.Empty(view.NameErrorLabel);

            view.ViewModel.Name = string.Empty;

            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(nameErrorMessage, view.NameErrorLabel);
        }
        public void ShouldSupportBindingToValidationContextWrappedInValidationHelper()
        {
            const string nameValidationError = "Name should not be empty.";
            var          view = new TestView(new TestViewModel {
                Name = string.Empty
            });
            var outerContext = new ValidationContext(ImmediateScheduler.Instance);
            var validation   = new BasePropertyValidation <TestViewModel, string>(
                view.ViewModel,
                vm => vm.Name,
                name => !string.IsNullOrWhiteSpace(name),
                nameValidationError);

            outerContext.Add(validation);
            view.ViewModel.NameRule = new ValidationHelper(outerContext);

            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);
            view.BindValidation(view.ViewModel, vm => vm.NameRule, v => v.NameErrorLabel);

            Assert.False(view.ViewModel.NameRule.IsValid);
            Assert.NotEmpty(view.NameErrorLabel);
            Assert.Equal(nameValidationError, view.NameErrorLabel);

            view.ViewModel.Name = "Jotaro";

            Assert.True(view.ViewModel.NameRule.IsValid);
            Assert.Empty(view.NameErrorLabel);
        }
Example #7
0
        public void RegisterValidationsWithDifferentLambdaNameWorksTest()
        {
            const string validName     = "valid";
            const int    minimumLength = 5;

            var viewModel = new TestViewModel {
                Name = validName
            };
            var view = new TestView(viewModel);

            var firstValidation = new BasePropertyValidation <TestViewModel, string>(
                viewModel,
                viewModelProperty => viewModelProperty.Name,
                s => !string.IsNullOrEmpty(s),
                s => $"Name {s} isn't valid");

            // Add validations
            viewModel.ValidationContext.Add(firstValidation);

            // View bindings
            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);

            // This was throwing exception due to naming problems with lambdas expressions
            view.BindValidation(
                view.ViewModel,
                vm => vm.Name,
                v => v.NameErrorLabel);

            Assert.True(viewModel.ValidationContext.IsValid);
            Assert.Equal(1, viewModel.ValidationContext.Validations.Count);
        }
        public void ValidationMessagesDefaultConcatenationTest()
        {
            var viewModel = new TestViewModel {
                Name = string.Empty
            };
            var view = new TestView(viewModel);

            var nameValidation = new BasePropertyValidation <TestViewModel, string>(
                viewModel,
                viewModelProperty => viewModelProperty.Name,
                s => !string.IsNullOrEmpty(s),
                "Name should not be empty.");

            var name2Validation = new BasePropertyValidation <TestViewModel, string>(
                viewModel,
                viewModelProperty => viewModelProperty.Name2,
                s => !string.IsNullOrEmpty(s),
                "Name2 should not be empty.");

            viewModel.ValidationContext.Add(nameValidation);
            viewModel.ValidationContext.Add(name2Validation);

            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);
            view.Bind(view.ViewModel, vm => vm.Name2, v => v.Name2Label);
            view.BindValidation(view.ViewModel, v => v.NameErrorLabel);

            Assert.False(viewModel.ValidationContext.IsValid);
            Assert.Equal(2, viewModel.ValidationContext.Validations.Count);
            Assert.NotEmpty(view.NameErrorLabel);
            Assert.Equal("Name should not be empty. Name2 should not be empty.", view.NameErrorLabel);
        }
        public void ShouldSupportBindingTwoValidationsForOnePropertyToChainedViewProperties()
        {
            const int minimumLength             = 5;
            var       minimumLengthErrorMessage = $"Minimum length is {minimumLength}";
            var       viewModel = new TestViewModel {
                Name = "some"
            };
            var view = new TestView(viewModel);

            // Define the validations.
            viewModel.ValidationRule(
                vm => vm.Name,
                s => !string.IsNullOrEmpty(s),
                "Name is required.");

            viewModel.ValidationRule(
                vm => vm.Name,
                s => s.Length > minimumLength,
                minimumLengthErrorMessage);

            // Define view bindings.
            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);
            view.BindValidation(view.ViewModel, vm => vm.Name, v => v.NameErrorContainer.Text);

            Assert.False(viewModel.ValidationContext.IsValid);
            Assert.Equal(2, viewModel.ValidationContext.Validations.Count);
            Assert.Equal(minimumLengthErrorMessage, view.NameErrorContainer.Text);
        }
Example #10
0
    public void ShouldBindValidationRuleEmittingValidationStates()
    {
        const StringComparison comparison = StringComparison.InvariantCulture;
        const string           viewModelIsBlockedMessage = "View model is blocked.";
        const string           nameErrorMessage          = "Name shouldn't be empty.";
        var view = new TestView(new TestViewModel {
            Name = string.Empty
        });

        using var isViewModelBlocked = new ReplaySubject <bool>(1);
        isViewModelBlocked.OnNext(true);

        // Create IObservable<IValidationState>
        var nameValidationState = view.ViewModel.WhenAnyValue(
            vm => vm.Name,
            name => (IValidationState) new CustomValidationState(
                !string.IsNullOrWhiteSpace(name),
                nameErrorMessage));

        view.ViewModel.ValidationRule(
            viewModel => viewModel.Name,
            nameValidationState);

        var viewModelBlockedValidationState = isViewModelBlocked.Select(blocked =>
                                                                        (IValidationState) new CustomValidationState(!blocked, viewModelIsBlockedMessage));

        view.ViewModel.ValidationRule(viewModelBlockedValidationState);

        view.Bind(view.ViewModel, x => x.Name, x => x.NameLabel);
        view.BindValidation(view.ViewModel, x => x.Name, x => x.NameErrorLabel);
        view.BindValidation(view.ViewModel, x => x.NameErrorContainer.Text);

        Assert.Equal(2, view.ViewModel.ValidationContext.Validations.Count);
        Assert.False(view.ViewModel.ValidationContext.IsValid);
        Assert.Contains(nameErrorMessage, view.NameErrorLabel, comparison);
        Assert.Contains(viewModelIsBlockedMessage, view.NameErrorContainer.Text, comparison);

        view.ViewModel.Name = "Qwerty";
        isViewModelBlocked.OnNext(false);

        Assert.Equal(2, view.ViewModel.ValidationContext.Validations.Count);
        Assert.True(view.ViewModel.ValidationContext.IsValid);
        Assert.DoesNotContain(nameErrorMessage, view.NameErrorLabel, comparison);
        Assert.DoesNotContain(viewModelIsBlockedMessage, view.NameErrorContainer.Text, comparison);
    }
        public void ShouldSupportObservableValidationRuleOverloads()
        {
            var view = new TestView(new TestViewModel
            {
                Name  = "Foo",
                Name2 = "Bar"
            });

            var namesAreEqual = view
                                .ViewModel
                                .WhenAnyValue(
                state => state.Name,
                state => state.Name2,
                (name, name2) => new { Name = name, Name2 = name2 });

            view.ViewModel.ValidationRule(
                state => state.Name,
                namesAreEqual,
                state => state.Name == state.Name2,
                state => $"{state.Name} != {state.Name2}.");

            view.ViewModel.ValidationRule(
                state => state.Name2,
                namesAreEqual,
                state => state.Name == state.Name2,
                state => $"{state.Name2} != {state.Name}.");

            view.ViewModel.ValidationRule(
                namesAreEqual.Select(names => names.Name == names.Name2),
                "Names should be equal.");

            view.ViewModel.ValidationRule(
                namesAreEqual,
                state => state.Name == state.Name2,
                state => $"{state.Name} should equal {state.Name2}.");

            view.Bind(view.ViewModel, x => x.Name, x => x.NameLabel);
            view.Bind(view.ViewModel, x => x.Name2, x => x.Name2Label);
            view.BindValidation(view.ViewModel, x => x.NameErrorLabel);

            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(4, view.ViewModel.ValidationContext.Validations.Count);
            Assert.NotEmpty(view.NameErrorLabel);
            Assert.Equal("Foo != Bar. Bar != Foo. Names should be equal. Foo should equal Bar.", view.NameErrorLabel);

            view.ViewModel.Name  = "Foo";
            view.ViewModel.Name2 = "Foo";

            Assert.True(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(4, view.ViewModel.ValidationContext.Validations.Count);
            Assert.Empty(view.NameErrorLabel);
        }
Example #12
0
        public void TwoValidationPropertiesInSamePropertyThrowsExceptionTest()
        {
            const string validName     = "valid";
            const int    minimumLength = 5;

            var viewModel = new TestViewModel {
                Name = validName
            };
            var view = new TestView(viewModel);

            var firstValidation = new BasePropertyValidation <TestViewModel, string>(
                viewModel,
                vm => vm.Name,
                s => !string.IsNullOrEmpty(s),
                s => $"Name {s} isn't valid");

            var secondValidation = new BasePropertyValidation <TestViewModel, string>(
                viewModel,
                vm => vm.Name,
                s => s.Length > minimumLength,
                _ => $"Minimum length is {minimumLength}");

            // Add validations
            viewModel.ValidationContext.Add(firstValidation);
            viewModel.ValidationContext.Add(secondValidation);

            // View bindings
            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);

            // View validations bindings
            var ex = Assert.Throws <MultipleValidationNotSupportedException>(() =>
            {
                return(view.BindValidation(
                           view.ViewModel,
                           vm => vm.Name,
                           v => v.NameErrorLabel));
            });

            Assert.False(viewModel.ValidationContext.IsValid);
            Assert.Equal(2, viewModel.ValidationContext.Validations.Count);

            // Checks if second validation error message is shown
            var expectedError =
                $"Property {nameof(viewModel.Name)} has more than one validation rule associated. Consider using {nameof(ValidationBindingEx)} methods.";

            Assert.Equal(expectedError, ex.Message);
        }
        public void RegisterValidationsWithDifferentLambdaNameWorksTest()
        {
            const string validName = "valid";
            var          view      = new TestView(new TestViewModel {
                Name = validName
            });

            view.ViewModel.ValidationRule(
                vm => vm.Name,
                s => !string.IsNullOrEmpty(s),
                s => $"Name {s} isn't valid");

            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);
            view.BindValidation(view.ViewModel, vm => vm.Name, v => v.NameErrorLabel);

            Assert.True(view.ViewModel.ValidationContext.IsValid);
            Assert.Single(view.ViewModel.ValidationContext.Validations);
        }
Example #14
0
        public void ComplexValidationRulesShouldBeBoundToView()
        {
            const string errorMessage = "Both inputs should be the same";
            var          view         = new TestView(new TestViewModel
            {
                Name  = "Josuke Hikashikata",
                Name2 = "Jotaro Kujo"
            });

            view.ViewModel.ValidationRule(
                m => m.Name,
                m => m.WhenAnyValue(x => x.Name, x => x.Name2, (name, name2) => name == name2),
                (vm, isValid) => isValid ? string.Empty : errorMessage);

            view.BindValidation(view.ViewModel, x => x.Name, x => x.NameErrorLabel);

            Assert.NotEmpty(view.NameErrorLabel);
            Assert.Equal(errorMessage, view.NameErrorLabel);
        }
        public void ShouldUpdateViewModelValidityWhenValidationHelpersDetach()
        {
            var view = new TestView(new TestViewModel {
                Name = string.Empty
            });
            var nameRule = view.ViewModel.ValidationRule(
                viewModel => viewModel.Name,
                name => !string.IsNullOrWhiteSpace(name),
                "Name is empty.");

            var name2Rule = view.ViewModel.ValidationRule(
                viewModel => viewModel.Name2,
                name => !string.IsNullOrWhiteSpace(name),
                "Name2 is empty.");

            view.Bind(view.ViewModel, x => x.Name, x => x.NameLabel);
            view.BindValidation(view.ViewModel, x => x.NameErrorContainer.Text);

            Assert.Equal(2, view.ViewModel.ValidationContext.Validations.Count);
            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal("Name is empty. Name2 is empty.", view.NameErrorContainer.Text);

            nameRule.Dispose();

            Assert.Equal(1, view.ViewModel.ValidationContext.Validations.Count);
            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal("Name2 is empty.", view.NameErrorContainer.Text);

            name2Rule.Dispose();

            Assert.Equal(0, view.ViewModel.ValidationContext.Validations.Count);
            Assert.True(view.ViewModel.ValidationContext.IsValid);
            Assert.Empty(view.NameErrorContainer.Text);

            view.ViewModel.ValidationRule(
                viewModel => viewModel.Name,
                name => !string.IsNullOrWhiteSpace(name),
                "Name is empty.");

            Assert.Equal(1, view.ViewModel.ValidationContext.Validations.Count);
            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal("Name is empty.", view.NameErrorContainer.Text);
        }
        public void ShouldAllowUsingCustomFormatters()
        {
            const string validationConstant = "View model is invalid.";
            var          view = new TestView(new TestViewModel {
                Name = string.Empty
            });

            view.ViewModel.ValidationRule(
                vm => vm.Name,
                s => !string.IsNullOrEmpty(s),
                "Name should not be empty.");

            view.Bind(view.ViewModel, vm => vm.Name, v => v.NameLabel);
            view.BindValidation(view.ViewModel, v => v.NameErrorLabel, new ConstFormatter(validationConstant));

            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(1, view.ViewModel.ValidationContext.Validations.Count);
            Assert.NotEmpty(view.NameErrorLabel);
            Assert.Equal(validationConstant, view.NameErrorLabel);
        }
        public void ShouldUpdateValidationHelperBindingOnPropertyChange()
        {
            var view = new TestView(new TestViewModel {
                Name = string.Empty
            });

            const string nameErrorMessage = "Name shouldn't be empty.";

            view.ViewModel.NameRule = view.ViewModel
                                      .ValidationRule(
                viewModel => viewModel.Name,
                name => !string.IsNullOrWhiteSpace(name),
                nameErrorMessage);

            view.Bind(view.ViewModel, x => x.Name, x => x.NameLabel);
            view.BindValidation(view.ViewModel, x => x.NameRule, x => x.NameErrorLabel);

            Assert.Equal(1, view.ViewModel.ValidationContext.Validations.Count);
            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(nameErrorMessage, view.NameErrorLabel);

            view.ViewModel.NameRule.Dispose();
            view.ViewModel.NameRule = null;

            Assert.Equal(0, view.ViewModel.ValidationContext.Validations.Count);
            Assert.True(view.ViewModel.ValidationContext.IsValid);
            Assert.Empty(view.NameErrorLabel);

            const string secretMessage = "This is the secret message.";

            view.ViewModel.NameRule = view.ViewModel
                                      .ValidationRule(
                viewModel => viewModel.Name,
                name => !string.IsNullOrWhiteSpace(name),
                secretMessage);

            Assert.Equal(1, view.ViewModel.ValidationContext.Validations.Count);
            Assert.False(view.ViewModel.ValidationContext.IsValid);
            Assert.Equal(secretMessage, view.NameErrorLabel);
        }