public async Task For_Validate_WhenRuleHasSetToStopValidationAfterFailure_Then_ValidationStopsWhenErrorOccurs()
        {
            // Arrange:
            var memberInfo = PropertyValidatorTestsCommon.CreateTestMemberInfo();
            var validator  = new AsyncPropertyValidator <string>(memberInfo);
            Func <string, Task <bool> > validationPredicate = async x =>
            {
                await Task.CompletedTask;
                return(x != "x");
            };
            const string message = "SOME MESSAGE";
            const string code    = "SOME CODE";

            validator.AddRule(validationPredicate, message, code);
            validator.StopValidationAfterFailure();
            validator.AddRule(x => x == null, "must be null", "MUST_BE_NULL");

            var toValidate = "x";

            // Act:
            var validationErrors = await validator.Validate(toValidate);

            // Assert:
            validationErrors.Count.Should().Be(1);
            validationErrors[0].ErrorMessage.Should().Be("SOME MESSAGE");
            validationErrors[0].ErrorCode.Should().Be("SOME CODE");
            validationErrors[0].PropertyPath.ToString().Should().Be("SomeProperty");
            validationErrors[0].ProvidedValue.Should().Be(toValidate);
        }
        public async Task For_Validate_When_ThereIsValidationRuleForAsyncRule_Then_ValidationErrorIsReturned()
        {
            // Arrange:
            var memberInfo = PropertyValidatorTestsCommon.CreateTestMemberInfo();
            var validator  = new AsyncPropertyValidator <string>(memberInfo);
            Func <string, Task <bool> > validationPredicate = async x =>
            {
                await Task.CompletedTask;
                return(x != "x");
            };
            const string message = "SOME MESSAGE";
            const string code    = "SOME CODE";

            validator.AddRule(validationPredicate, message, code);

            var toValidate = "x";

            // Act:
            var validationErrors = await validator.Validate(toValidate);

            // Assert:
            validationErrors.Count.Should().Be(1);
            var validationError = validationErrors.First();

            validationError.ErrorMessage.Should().Be(message);
            validationError.ErrorCode.Should().Be(code);
            validationError.PropertyPath.ToString().Should().Be("SomeProperty");
            validationError.ProvidedValue.Should().Be(toValidate);
        }
        public void For_AddRuleAsync_When_PredicateIsNull_Then_ExceptionIsThrown()
        {
            // Arrange:
            var memberInfo = PropertyValidatorTestsCommon.CreateTestMemberInfo();
            var validator  = new AsyncPropertyValidator <string>(memberInfo);
            Func <string, Task <bool> > validationPredicate = null;

            // Act & Assert:
            Assert.Throws <ArgumentNullException>(() =>
                                                  validator.AddRule(validationPredicate, It.IsAny <string>()));
        }
        public async Task For_Validate_When_ThereAreOverridesToApplyToValidationErrors_Then_AreAppliedToValidationErrors()
        {
            // Arrange:
            var memberInfo = PropertyValidatorTestsCommon.CreateTestMemberInfo();
            var validator  = new AsyncPropertyValidator <string>(memberInfo);
            Func <string, Task <bool> > validationPredicate = async x =>
            {
                await Task.CompletedTask;
                return(x != "x");
            };
            const string message = "SOME MESSAGE";
            const string code    = "SOME CODE";

            validator.AddRule(validationPredicate, message, code);
            validator.WithMessage("Cannot be x");
            validator.WithCode("MUST_NOT_BE_X");
            validator.AddRule(x => x == null, "must be null", "MUST_BE_NULL");
            validator.SetPropertyDisplayName("OverridenPropertyDisplayName");

            var toValidate = "x";

            // Act:
            var validationErrors = await validator.Validate(toValidate);

            // Assert:
            validationErrors.Count.Should().Be(2);

            validationErrors[0].ErrorMessage.Should().Be("Cannot be x");
            validationErrors[0].ErrorCode.Should().Be("MUST_NOT_BE_X");
            validationErrors[0].PropertyPath.ToString().Should().Be("OverridenPropertyDisplayName");
            validationErrors[0].ProvidedValue.Should().Be(toValidate);

            validationErrors[1].ErrorMessage.Should().Be("must be null");
            validationErrors[1].ErrorCode.Should().Be("MUST_BE_NULL");
            validationErrors[1].PropertyPath.ToString().Should().Be("OverridenPropertyDisplayName");
            validationErrors[1].ProvidedValue.Should().Be(toValidate);
        }
        public void For_AddRuleAsync_When_MessageIsNull_Then_ExceptionIsThrown()
        {
            // Arrange:
            var memberInfo = PropertyValidatorTestsCommon.CreateTestMemberInfo();
            var validator  = new AsyncPropertyValidator <string>(memberInfo);
            Func <string, Task <bool> > validationPredicate = async x =>
            {
                await Task.CompletedTask;
                return(x != "x");
            };

            // Act & Assert:
            Assert.Throws <ArgumentNullException>(() =>
                                                  validator.AddRule(validationPredicate, null));
        }
        public void For_AddRuleAsync_When_PassedArgumentsAreValid_Then_NewValidationTaskIsAdded()
        {
            // Arrange:
            var memberInfo = PropertyValidatorTestsCommon.CreateTestMemberInfo();
            var validator  = new AsyncPropertyValidator <string>(memberInfo);
            Func <string, Task <bool> > validationPredicate = async x =>
            {
                await Task.CompletedTask;
                return(x != "x");
            };
            const string message = "SOME MESSAGE";

            // Act & Assert:
            Assert.DoesNotThrow(() => validator.AddRule(validationPredicate, message));
            validator.ValidationTasksAsReadonly.Count.Should().Be(1);
            var validationTask = validator.ValidationTasksAsReadonly.First();

            validationTask.Validator.Should().Should().NotBeNull();
            validationTask.Validator.GetType().Should().BeAssignableTo <IAsyncValidator>();
        }