public void Validates_collection() { var validator = new InlineValidator <Root>(); var impl1Validator = new InlineValidator <FooImpl1>(); var impl2Validator = new InlineValidator <FooImpl2>(); impl1Validator.RuleFor(x => x.Name).NotNull(); impl2Validator.RuleFor(x => x.Number).GreaterThan(0); validator.RuleForEach(x => x.Foos).SetInheritanceValidator(v => { v.Add(impl1Validator) .Add(impl2Validator); }); var result = validator.Validate(new Root { Foos = { new FooImpl1() } }); result.Errors.Count.ShouldEqual(1); result.Errors[0].PropertyName.ShouldEqual("Foos[0].Name"); result = validator.Validate(new Root { Foos = { new FooImpl2() } }); result.Errors.Count.ShouldEqual(1); result.Errors[0].PropertyName.ShouldEqual("Foos[0].Number"); }
public async Task When_async_condition_executed_for_each_instance_of_RuleForEach_condition_should_not_be_cached() { var person = new Person { Children = new List <Person> { new Person { Id = 1 }, new Person { Id = 0 } } }; var childValidator = new InlineValidator <Person>(); int executions = 0; childValidator.WhenAsync(async(a, ct) => { executions++; return(a.Id != 0); }, () => { childValidator.RuleFor(a => a.Id).Equal(1); }); var personValidator = new InlineValidator <Person>(); personValidator.RuleForEach(p => p.Children).SetValidator(childValidator); var validationResult = await personValidator.ValidateAsync(person); validationResult.IsValid.ShouldBeTrue(); executions.ShouldEqual(2); }
public void Can_define_nested_rules_for_collection() { var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.Orders).ChildRules(order => { order.RuleFor(x => x.ProductName).NotNull(); order.RuleFor(x => x.Amount).GreaterThan(0); }); var result = validator.Validate(new Person { Orders = new List <Order> { new Order { ProductName = null, Amount = 10 }, new Order { ProductName = "foo", Amount = 0 }, new Order { ProductName = "foo", Amount = 10 } } }); result.Errors.Count.ShouldEqual(2); result.Errors[0].PropertyName.ShouldEqual("Orders[0].ProductName"); result.Errors[1].PropertyName.ShouldEqual("Orders[1].Amount"); }
public void Rule_ForEach_display_name_should_match_RuleForEach_display_name() { var validator = new InlineValidator <Person>(); // These 2 rule definitions should produce the same error message and property name. // https://github.com/FluentValidation/FluentValidation/issues/1231 validator .RuleForEach(x => x.NickNames) .Must(x => false) .WithMessage("{PropertyName}"); validator .RuleFor(x => x.NickNames) .ForEach(n => n.Must(x => false).WithMessage("{PropertyName}")); var result = validator.Validate(new Person() { NickNames = new[] { "foo" } }); result.Errors[0].PropertyName.ShouldEqual("NickNames[0]"); result.Errors[0].ErrorMessage.ShouldEqual("Nick Names"); result.Errors[1].PropertyName.ShouldEqual("NickNames[0]"); result.Errors[1].ErrorMessage.ShouldEqual("Nick Names"); }
public async Task RuleForEach_async_RunsTasksSynchronously() { var validator = new InlineValidator <Person>(); var result = new List <bool>(); validator.RuleForEach(x => x.Children).MustAsync(async(person, token) => await ExclusiveDelay(1) .ContinueWith(t => result.Add(t.Result), token) .ContinueWith(t => true, token) ); await validator.ValidateAsync(new Person() { Children = new List <Person> { new Person(), new Person() } }); Assert.NotEmpty(result); #if NET35 AssertEx #else Assert #endif .All(result, Assert.True); }
public void Nested_collection_for_null_property_should_not_throw_null_reference() { var validator = new InlineValidator<request>(); validator.When(r => r.person != null, () => { validator.RuleForEach(x => x.person.NickNames).NotNull(); }); var result = validator.Validate(new request()); result.Errors.Count.ShouldEqual(0); }
public void Nested_collection_for_null_property_should_not_throw_null_reference() { var validator = new InlineValidator <request>(); validator.When(r => r.person != null, () => { validator.RuleForEach(x => x.person.NickNames).NotNull(); }); var result = validator.Validate(new request()); result.Errors.Count.ShouldEqual(0); }
public void ShouldHaveChildValidator_should_work_with_DependentRules() { var validator = new InlineValidator <Person>(); validator.RuleFor(x => x.Children) .NotNull().When(p => true) .DependentRules(() => { validator.RuleForEach(p => p.Children).SetValidator(p => new InlineValidator <Person>()); }); validator.ShouldHaveChildValidator(x => x.Children, typeof(InlineValidator <Person>)); }
public async Task Can_access_colletion_index_async() { var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.Orders).NotNull().WithMessage("{CollectionIndex}"); var result = await validator.ValidateAsync(new Person { Orders = new List <Order>() { new Order(), null } }); result.IsValid.ShouldBeFalse(); result.Errors[0].ErrorMessage.ShouldEqual("1"); }
public async Task Failing_condition_should_prevent_multiple_components_running_and_not_throw_async() { // https://github.com/FluentValidation/FluentValidation/issues/1698 var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.Orders) .MustAsync((o, ct) => Task.FromResult(o != null)) .MustAsync((o, ct) => Task.FromResult(o != null)) .When(x => x.Orders.Count > 0); var result = await validator.ValidateAsync(new Person()); result.IsValid.ShouldBeTrue(); }
public void Failing_condition_should_prevent_multiple_components_running_and_not_throw() { // https://github.com/FluentValidation/FluentValidation/issues/1698 var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.Orders) .NotNull() .NotNull() .When(x => x.Orders.Count > 0); var result = validator.Validate(new Person()); result.IsValid.ShouldBeTrue(); }
public void Can_use_cascade_with_RuleForEach() { var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.NickNames) .Cascade(CascadeMode.StopOnFirstFailure) .NotNull() .NotEqual("foo"); var result = validator.Validate(new Person { NickNames = new string[] { null } }); result.Errors.Count.ShouldEqual(1); }
public void Top_level_collection() { var v = new InlineValidator <IEnumerable <Order> >(); v.RuleForEach(x => x).SetValidator(new OrderValidator()); var orders = new List <Order> { new Order(), new Order() }; var result = v.Validate(orders); result.Errors.Count.ShouldEqual(4); result.Errors[0].PropertyName.ShouldEqual("x[0].ProductName"); }
public void Does_not_throw_InvalidCastException_when_using_RuleForEach() { var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.NickNames) .Must(x => false) .WithMessage((parent, name) => "x"); var result = validator.Validate(new Person() { NickNames = new[] { "What" } }); result.Errors.Single().ErrorMessage.ShouldEqual("x"); }
public void Nested_conditions_Rule_For_Each() { var validator = new InlineValidator <request>(); validator.When(x => true, () => { validator.When(r => r.person?.NickNames?.Any() == true, () => { validator.RuleForEach(x => x.person.NickNames) .Must(nn => true) .WithMessage("Failed RuleForEach"); }); }); var result = validator.Validate(new request()); result.Errors.Count.ShouldEqual(0); }
public void Transforms_collection_element() { var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.Orders) .Transform(order => order.Amount) .GreaterThan(0); var result = validator.Validate(new Person() { Orders = new List <Order> { new Order() } }); result.Errors.Count.ShouldEqual(1); }
public void Can_use_indexer_in_string_message_inverse() { var validator = new InlineValidator <Person>(); var orderValidator = new InlineValidator <Order>(); orderValidator.RuleFor(x => x.ProductName).Null(); validator.RuleForEach(x => x.Orders).SetValidator(orderValidator); var model = new Person { Orders = new List <Order> { new Order() } }; var result = validator.TestValidate(model); result.ShouldNotHaveValidationErrorFor("Orders[0].ProductName"); }
public async Task Transforms_collection_element_async() { var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.Orders) .Transform(order => order.Amount) .MustAsync((amt, token) => Task.FromResult(amt > 0)); var result = await validator.ValidateAsync(new Person() { Orders = new List <Order> { new Order() } }); result.Errors.Count.ShouldEqual(1); }
public void Should_work_with_top_level_collection_validator_and_overriden_name() { var personValidator = new InlineValidator <Person>(); personValidator.RuleFor(x => x.Surname).NotNull(); var validator = new InlineValidator <List <Person> >(); validator.RuleForEach(x => x).SetValidator(personValidator).OverridePropertyName("test"); var results = validator.Validate(new List <Person> { new Person(), new Person(), new Person { Surname = "Bishop" } }); results.Errors.Count.ShouldEqual(2); results.Errors[0].PropertyName.ShouldEqual("test[0].Surname"); }
public void Uses_useful_error_message_when_used_on_non_property() { var validator = new InlineValidator <Person>(); validator.RuleForEach(x => x.NickNames.AsEnumerable()).NotNull(); bool thrown = false; try { validator.Validate(new Person { NickNames = new string[] { null, null } }); } catch (System.InvalidOperationException ex) { thrown = true; ex.Message.ShouldEqual("Could not infer property name for expression: x => x.NickNames.AsEnumerable(). Please explicitly specify a property name by calling OverridePropertyName as part of the rule chain. Eg: RuleForEach(x => x).NotNull().OverridePropertyName(\"MyProperty\")"); } thrown.ShouldBeTrue(); }
public void When_runs_outside_RuleForEach_loop() { // Shouldn't throw an exception if the condition is run outside the loop. var validator = new InlineValidator <Tuple <Person> >(); validator.RuleForEach(x => x.Item1.Orders).Must(x => false) .When(x => x.Item1 != null); var result = validator.Validate(Tuple.Create((Person)null)); result.IsValid.ShouldBeTrue(); result = validator.Validate(Tuple.Create(new Person() { Orders = new List <Order> { new Order() } })); result.IsValid.ShouldBeFalse(); }
public async Task Resets_state_correctly_between_rules_async() { var v = new InlineValidator <Person>(); v.RuleForEach(x => x.NickNames).NotNull(); v.RuleFor(x => x.Forename).NotNull(); // The ValidationContext is reinitialized for each item in the collection // Specifically, the PropertyChain is reset and modified. // After the collection has been validated, the PropertyChain should be reset to its original value. // We can test this by checking the final output of the property names for subsequent rules after the RuleForEach. var result = await v.ValidateAsync(new Person() { NickNames = new[] { null, "Foo", null }, Forename = null }); result.Errors.Count.ShouldEqual(3); result.Errors[0].PropertyName.ShouldEqual("NickNames[0]"); result.Errors[1].PropertyName.ShouldEqual("NickNames[2]"); result.Errors[2].PropertyName.ShouldEqual("Forename"); }
public async Task When_runs_outside_RuleForEach_loop_async() { // Shouldn't throw an exception if the condition is run outside the loop. var validator = new InlineValidator <Tuple <Person> >(); validator.RuleForEach(x => x.Item1.Orders) .MustAsync((x, c) => Task.FromResult(false)) .When(x => x.Item1 != null); var result = await validator.ValidateAsync(Tuple.Create((Person)null)); result.IsValid.ShouldBeTrue(); result = await validator.ValidateAsync(Tuple.Create(new Person() { Orders = new List <Order> { new Order() } })); result.IsValid.ShouldBeFalse(); }
public async Task Can_access_parent_index_async() { var personValidator = new InlineValidator <Person>(); var orderValidator = new InlineValidator <Order>(); orderValidator.RuleFor(order => order.ProductName) .NotEmpty() .WithMessage("{CollectionIndex} must not be empty"); // Two rules - one for each collection syntax. personValidator.RuleFor(x => x.Orders) .NotEmpty() .ForEach(order => { order.SetValidator(orderValidator); }); personValidator.RuleForEach(x => x.Orders).SetValidator(orderValidator); var result = await personValidator.ValidateAsync(new Person() { Orders = new List <Order> { new Order() { ProductName = "foo" }, new Order(), new Order() { ProductName = "bar" } } }); result.IsValid.ShouldBeFalse(); result.Errors[0].ErrorMessage.ShouldEqual("1 must not be empty"); result.Errors[0].ErrorMessage.ShouldEqual("1 must not be empty"); }
public void Shouldnt_break_with_hashcode_collision() { var v1 = new InlineValidator <Collision1>(); var v2 = new InlineValidator <Collision2>(); var v = new InlineValidator <CollisionBase>(); v.When(x => x is Collision1, () => { v.RuleFor(x => ((Collision1)x).Name).NotNull(); }); v.When(x => x is Collision2, () => { v.RuleFor(x => ((Collision2)x).Name).NotNull(); }); // shouldn't throw an InvalidCastException. var containerValidator = new InlineValidator <List <CollisionBase> >(); containerValidator.RuleForEach(x => x).SetValidator(v); containerValidator.Validate(new List <CollisionBase> { new Collision1(), new Collision2() }); }
public async Task Shouldnt_break_with_hashcode_collision_async() { var v1 = new InlineValidator <Collision1>(); var v2 = new InlineValidator <Collision2>(); var v = new InlineValidator <CollisionBase>(); v.WhenAsync((x, ct) => Task.FromResult(x is Collision1), () => { v.RuleFor(x => ((Collision1)x).Name).NotNull(); }); v.WhenAsync((x, ct) => Task.FromResult(x is Collision2), () => { v.RuleFor(x => ((Collision2)x).Name).NotNull(); }); var containerValidator = new InlineValidator <List <CollisionBase> >(); containerValidator.RuleForEach(x => x).SetValidator(v); // shouldn't throw an InvalidCastException. await containerValidator.ValidateAsync(new List <CollisionBase> { new Collision1(), new Collision2() }); }
public async Task Validates_collection_async() { var validator = new InlineValidator <Root>(); var impl1Validator = new InlineValidator <FooImpl1>(); var impl2Validator = new InlineValidator <FooImpl2>(); impl1Validator.RuleFor(x => x.Name).MustAsync((s, token) => Task.FromResult(s != null)); impl2Validator.RuleFor(x => x.Number).MustAsync((i, token) => Task.FromResult(i > 0)); validator.RuleForEach(x => x.Foos).SetInheritanceValidator(v => { v.Add(impl1Validator) .Add(impl2Validator); }); var result = await validator.ValidateAsync(new Root { Foos = { new FooImpl1() } }); result.Errors.Count.ShouldEqual(1); result.Errors[0].PropertyName.ShouldEqual("Foos[0].Name"); result = await validator.ValidateAsync(new Root { Foos = { new FooImpl2() } }); result.Errors.Count.ShouldEqual(1); result.Errors[0].PropertyName.ShouldEqual("Foos[0].Number"); }
public void Creates_validator_using_context_from_property_value() { var personValidator = new InlineValidator <Person>(); var normalOrderValidator = new InlineValidator <Order>(); normalOrderValidator.RuleFor(x => x.Amount).GreaterThan(0); var freeOrderValidator = new InlineValidator <Order>(); freeOrderValidator.RuleFor(x => x.Amount).Equal(0); personValidator.RuleForEach(x => x.Orders) .SetValidator((p, order) => order.ProductName == "FreeProduct" ? freeOrderValidator : normalOrderValidator); var result1 = personValidator.Validate(new Person() { Orders = new List <Order> { new Order { ProductName = "FreeProduct" } } }); result1.IsValid.ShouldBeTrue(); var result2 = personValidator.Validate(new Person() { Orders = new List <Order> { new Order() } }); result2.IsValid.ShouldBeFalse(); result2.Errors[0].ErrorCode.ShouldEqual("GreaterThanValidator"); }