[TestCase(false, true)] // =
        public void IsFalse(bool value, bool isValid)
        {
            // Arrange
            var propertyName = "IsSalaried";
            var employee = new Employee()
            {
                IsHourly = true,
                IsSalaried = value
            };

            var validator = Properties<Employee>
                .For(e => e.IsSalaried)
                .If(e => e.IsHourly)
                .IsFalse()
                ;


            // Act
            var results = validator.Validate(employee);
            // Assert

            if (isValid)
            {
                results.AssertValidFor(propertyName, null);
            }
            else
            {
                results.AssertInvalidFor(propertyName, null);
            }
        }
        public void WhenRequiredAndPropertyNotSetShouldFail()
        {
            // Arrange
            const string message = "ReportsTo is required.";
            var validator = Properties<Employee>
                .For(e => e.Address  )
                .Required()
                .Message(message)
                ;

            // Act
            var employee = new Employee()
                               {
                                   Address = null,
                               };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Not.Empty);
            var result = results.First();
            Assert.That(result.Context, Is.EqualTo(employee));
            Assert.That(result.PropertyName, Is.EqualTo("Address"));
            Assert.That(result.Severity, Is.EqualTo(ValidationResultSeverity.Error));
            Assert.That(result.Type, Is.Null);
            Assert.That(result.Message, Is.EqualTo(message));
        }
        public void MaxValue(double? maxValue, double? valueToValidate, bool upperInclusive, bool isValid)
        {
            // Arrange
            var propertyName = "Salary";
            var employee = new Employee()
            {
                Salary = valueToValidate
            };
            var validator = Properties<Employee>
                .For(e => e.Salary)
                ;

            if (maxValue.HasValue)
                validator.MaxValue(maxValue.Value, upperInclusive);

            // Act
            var results = validator.Validate(employee);

            // Assert
            if (isValid)
            {
                results.AssertValidFor(propertyName, null);
            }
            else
            {
                results.AssertInvalidFor(propertyName, null);
            }
        }
        public void ValidateAge()
        {
            // Arrange
            var employee = new Employee()
                               {
                                   FirstName = "Fred",
                                   LastName = "Flintstone",
                                   Age = 0,
                               };

            // Act
            var results = new DataAnnotationsValidator<Employee>()
                .Validate(employee);

            // Assert
            results.AssertInvalidFor("Age", typeof(ValidationAttribute));
            var result = results.Single(r => r.PropertyName == "Age");
            Assert.That(result.Context, Is.SameAs(employee));
        }
        public void ValidateMinLength_IgnoreWhitespace()
        {
            // Arrange
            var employee = new Employee {LastName = "ABC  "};

            var validator = Properties<Employee>
                .For(e => e.LastName)
                .Length(5)
                .IgnoreWhiteSpace()
                ;


            // Act
            var results = validator.Validate(employee);

            // Assert

            results.AssertInvalidFor("LastName", null);

        }
        public void Severity()
        {
            // Arrange
            var validator = Properties<Employee>
                .For(e => e.Address)
                .Required()
                .Severity(ValidationResultSeverity.Warning)
                ;

            // Act
            var employee = new Employee()
            {
                Address = null,
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Not.Empty);
            var result = results.First(v => v.PropertyName == "Address");
            Assert.That(result.Severity, Is.EqualTo(ValidationResultSeverity.Warning));
        }
        public void Type()
        {
            // Arrange
            const string customValidationResultType = "CustomValidationResultType";
            var validator = Properties<Employee>
                .For(e => e.Address)
                .Required()
                .Type(customValidationResultType)
                ;

            // Act
            var employee = new Employee()
            {
                Address = null,
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Not.Empty);
            var result = results.First(v => v.PropertyName == "Address");
            Assert.That(result.Type, Is.EqualTo(customValidationResultType));
        }
        public void ValidateMinLength(int? minLength, int? actualLength, bool isValid)
        {
            // Arrange
            var employee = new Employee();
            if (actualLength.HasValue)
                employee.LastName = new string('x', actualLength.Value);

            var validator = Properties<Employee>
                .For(e => e.LastName)
                .Length(minLength);

            // Act
            var results = validator.Validate(employee);

            // Assert
            if (isValid)
            {
                results.AssertValidFor("LastName", null);
            }
            else
            {
                results.AssertInvalidFor("LastName", null);
            }
        }
        public void WhenNotRequired_AndCascading_AndPropertyIsEmpty_ShouldSucceed()
        {
            var validatorProvider = new DefaultValidatorProvider();
            validatorProvider.RegisterValidator(new SaveAddressValidator());
            Validator.SetValidatorProvider(validatorProvider);

            var validator = Properties<Employee>
                .For(e => e.Address)
                .NotRequired()
                .Cascade("Save")
                ;

            // Act
            var employee = new Employee()
            {
                ReportsTo = new Manager(),
                Address = null
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Empty);
        }
        public void WhenNotRequiredAndPropertyNotSetShouldSucceed()
        {
            // Arrange
            const string message = "ReportsTo is required.";
            var validator = Properties<Employee>
                .For(e => e.Address)
                .NotRequired()
                .Message(message)
                ;

            // Act
            var employee = new Employee()
            {
                Address = null,
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Empty);
        }
        public void If_WhenPredicateFalse_ShouldNotValidate()
        {
            var validatorProvider = new DefaultValidatorProvider();
            validatorProvider.RegisterValidator(new SaveAddressValidator());
            Validator.SetValidatorProvider(validatorProvider);

            var acceptableLine1 = "This is a test of the emergency broadcast system.";
            var validator = Properties<Employee>
                .For(e => e.Address)
                .Cascade("Save")
                .If(e => e.Address.Line1 != acceptableLine1)
                ;

            // Act
            var employee = new Employee()
            {
                ReportsTo = new Manager(),
                Address = new Address()
                {
                    Line1 = acceptableLine1,
                }
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Empty);
        }
        public void If_WhenPredicateTrue_ShouldValidate()
        {
            var validatorProvider = new DefaultValidatorProvider();
            validatorProvider.RegisterValidator(new SaveAddressValidator());
            Validator.SetValidatorProvider(validatorProvider);

            var acceptableLine1 = "This is a test of the emergency broadcast system.";
            var validator = Properties<Employee>
                .For(e => e.Address)
                .Cascade("Save")
                .If(e => e.Address.Line1 != acceptableLine1)
                ;

            // Act
            var employee = new Employee()
            {
                ReportsTo = new Manager(),
                Address = new Address()
                {
                    Line1 = null,
                }
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Not.Empty);
            var result = results.First();
            Assert.That(result.Context, Is.EqualTo(employee));
            Assert.That(result.PropertyName, Is.EqualTo("Address.Line1"));
            Assert.That(result.Severity, Is.EqualTo(ValidationResultSeverity.Error));
            Assert.That(result.Type, Is.EqualTo(null));
        }
        public void CascadeUsingType()
        {
            var validatorProvider = new DefaultValidatorProvider();
            validatorProvider.RegisterValidator(new SaveAddressValidator());
            Validator.SetValidatorProvider(validatorProvider);

            var message = "This is a test failure.";
            var validator = Properties<Employee>
                .For(e => e.Address)
                .Required()
                .Cascade<object>("Save")
                .Message(message)
                ;

            // Act
            var employee = new Employee()
            {
                ReportsTo = new Manager(),
                Address = new Address()
                {
                    Line1 = null,
                }
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Empty);
        }
        public void ValidateRequired_IgnoreWhitespace()
        {
            // Arrange
            var employee = new Employee();
            var validator = Properties<Employee>
                .For(e => e.LastName)
                .IgnoreWhiteSpace()
                .Required()
                ;

            employee.LastName  = "     ";

            // Act
            var results = validator.Validate(employee);

            // Assert

            results.AssertInvalidFor("LastName", null);

        }
        public void If_PredicateIsFalse_ShouldNotValidate()
        {
            // Arrange
            var validator = Properties<Employee>
                .For(e => e.Age)
                .GreaterThanOrEqualTo(18)
                .If(e => e.Age != -1)
                ;

            // Act
            var employee = new Employee()
            {
                Age = -1
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Empty);

        }
        public void CascadeRequiredProperty()
        {
            var validatorProvider = new DefaultValidatorProvider();
            validatorProvider.RegisterValidator(new SaveAddressValidator());
            Validator.SetValidatorProvider(validatorProvider);

            var validator = Properties<Employee>
                .For(e => e.Address)
                .Required()
                .Cascade("Save")
                ;

            // Act
            var employee = new Employee()
            {
                ReportsTo = new Manager(),
                Address = new Address()
                              {
                                  Line1 = null,
                              }
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Not.Empty);
            var result = results.First();
            Assert.That(result.Context, Is.EqualTo(employee));
            Assert.That(result.PropertyName, Is.EqualTo("Address.Line1"));
            Assert.That(result.Severity, Is.EqualTo(ValidationResultSeverity.Error));
            Assert.That(result.Type, Is.EqualTo(null));
        }
        public void RegularExpressionWithOptions(string regularExpression, string value,RegexOptions options, bool isValid)
        {
            // Arrange
            var employee = new Employee()
            {
                LastName = value
            };
            var validator = Properties<Employee>
                .For(e => e.LastName)
                .Matches(regularExpression, options)
                ;

            // Act
            var results = validator.Validate(employee);

            // Assert
            if (isValid)
            {
                results.AssertValidFor("LastName", null);
            }
            else
            {
                results.AssertInvalidFor("LastName", null);
            }
        }
        public void If_PredicateIsFalse_ShouldNotValidate()
        {
            // Arrange
            const string customMessage = "CustomMessage";
            var acceptableLongMessage = "This is a test of the emergency broadcast system.";
            var validator = Properties<Employee>
                .For(e => e.FirstName)
                .Length(3, 30)
                .If(e => e.FirstName != acceptableLongMessage)
                .Message(customMessage);

            // Act
            var employee = new Employee()
            {
                FirstName = acceptableLongMessage,
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Empty);
        }
        public void WhenCascading_Message_DoesNotOverrideMessagesFromPropertyValidation()
        {
            var validatorProvider = new DefaultValidatorProvider();
            validatorProvider.RegisterValidator(new SaveAddressValidator());
            Validator.SetValidatorProvider(validatorProvider);

            var message = "This is a test failure.";
            var validator = Properties<Employee>
                .For(e => e.Address)
                .Required()
                .Cascade("Save")
                .Message(message)
                ;

            // Act
            var employee = new Employee()
            {
                ReportsTo = new Manager(),
                Address = new Address()
                {
                    Line1 = null,
                }
            };
            var results = validator.Validate(employee);

            // Assert
            Assert.That(results, Is.Not.Empty);
            var result = results.First(vr => vr.PropertyName == "Address.Line1");
            Assert.That(result.Message, Is.Not.EqualTo(message));
        }
        public void RequiredAndAssertReturnOnlyOneResultWhenPropertyValueIsEmptyString()
        {
            // Arrange
            var employee = new Employee()
                               {
                                   LastName = string.Empty
                               };
            var validator = Properties<Employee>
                .For(e => e.LastName)
                .Required()
                .Assert((entity, propertyValue) => false)
                ;


            // Act
            var results = validator.Validate(employee).ToList();

            // Assert
            results.AssertInvalidFor("LastName", null);
            Assert.That(results, Has.Count.EqualTo(1));
     
        }