<commit_before>﻿using System;
using MFlow.Core.Events;
using MFlow.Core.Validation.Factories;
using MFlow.Core.Tests.Supporting;
using System.Linq;
using System.Threading;
using System.Globalization;
using MFlow.Core.Conditions.Enums;
using NUnit.Framework;
using MFlow.Core.Validation.Builder;

namespace MFlow.Core.Tests.Validation
{
    [TestFixture]
    public partial class FluentValidation
    {

        readonly IFluentValidationFactory _factory = new FluentValidationFactory();

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Test_Fluent_Validation_Constructor_Exception()
        {
            var fluentValidation = _factory.GetFluentValidation<User>(null);
            fluentValidation.Validate();
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Test_Fluent_Validation_Set_Target_When_Null()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            fluentValidation.SetTarget(null);
        }

        [Test]
        public void Test_Fluent_Validation_Set_Target_When_Not_Null()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            Assert.DoesNotThrow(() => { fluentValidation.SetTarget(user); });
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Test_Fluent_Validation_Set_Target_When_Null_After_Check()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            fluentValidation.Check(u=>u.Username).IsNotEmpty().SetTarget(null);
        }

        [Test]
        public void Test_Fluent_Validation_Set_Target_When_Not_Null_After_Check()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            Assert.DoesNotThrow(() => { fluentValidation.Check(u => u.Username).IsNotEmpty().SetTarget(user); });
        }


        [Test]
        public void Test_Fluent_Validation_Get_And_Set_Target()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            fluentValidation.SetTarget(user);

            var target = fluentValidation.GetTarget();
            Assert.AreEqual(user, target);
        }

        [Test]
        public void Test_Fluent_Validation_Get_And_Set_Target_After_Check()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            fluentValidation.Check(u=>u.Username).IsNotEmpty().SetTarget(user);

            var target = fluentValidation.Check(u=>u.Username).IsNotEmpty().GetTarget();
            Assert.AreEqual(user, target);
        }

        [Test]
        public void Test_Fluent_Validation_Clears_Conditions()
        {
            var user = new User
            {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("xxx").Clear();

            Assert.IsTrue(fluentValidation.Satisfied());
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void Test_Chained_Fluent_Validation_ValidateAndThrow_InValid()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("xxx").ValidateAndThrow<ArgumentException>();
        }

        [Test]
        public void Test_Chained_Fluent_Validation_ValidateAndThrow_Valid()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "xxx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsFalse(fluentValidation
                           .Check(u => u.Username).IsEqualTo("xxx").ValidateAndThrow<ArgumentException>().Any());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_InValid_Expression()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsFalse(fluentValidation
                           .Check(u => u.Username).IsEqualTo("xxx").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_Valid_Expression_Chain()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsTrue(fluentValidation
                          .Check(u => u.Username).IsEqualTo("testing")
                          .Check(u => u.Password).IsEqualTo("<PASSWORD>").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_InValid_Expression_Chain()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsFalse(fluentValidation
                           .Check(u => u.Username).IsEqualTo("testing")
                           .Check(u => u.Password).IsEqualTo("<PASSWORD>").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_Valid_Or_Expression_Chain()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsTrue(fluentValidation
                          .Check(u => u.Username).IsEqualTo("testing")
                          .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                          .Check(u => u.Username, conditionType: ConditionType.Or).IsEqualTo("testingx").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_InValid_Or_Expression_Chain()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsFalse(fluentValidation
                           .Check(u => u.Username).IsEqualTo("testing")
                           .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                           .Check(u => u.Username, conditionType: ConditionType.Or).IsEqualTo("test").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_Valid_Expression_Executes()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                .Then(() =>
                      {
                          user.Username = "valid";
                      });

            Assert.IsTrue(user.Username == "valid");
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_Valid_Expression_Executes_Else()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing2"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                .Then(() => {
                          user.Username = "valid"; })
                .Else(() => {
                          user.Username = "invalid"; });

            Assert.IsTrue(user.Username == "invalid");
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Raises_Event()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);

            var events = new EventsFactory().GetEventStore();
            events.Register<UserCreatedEvent>(s =>
                                              {
                                                  s.Source.Username = "caught event";
                                                  user = s.Source;
                                              });

            fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                .Raise(new UserCreatedEvent(user));

            Assert.AreEqual(user.Username, "caught event");
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Number_Of_Results()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual(1, results.ToList().Count());

        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Key()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual("Username", results.First().Condition.Key);

        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Message()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing").Message("Username is not valid")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual("Username is not valid", results.First().Condition.Message);

        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Number_Of_Multipe_Results()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual(2, results.ToList().Count());

        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Number_Of_Multipe_Results_With_Warnings_Supressed()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Username).IsEqualTo("abc").Warn()
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual(2, results.ToList().Count());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Number_Of_Multipe_Results_With_Warnings()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Username).IsEqualTo("abc").Warn()
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate(suppressWarnings: false);

            Assert.AreEqual(3, results.ToList().Count());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Keys()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual("Username", results.First().Condition.Key);
            Assert.AreEqual("Password", results.Skip(1).Take(1).First().Condition.Key);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Messages()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing").Message("Username is not valid")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Message("Password is now valid").Validate();

            Assert.AreEqual("Username is not valid", results.First().Condition.Message);
            Assert.AreEqual("Password is now valid", results.Skip(1).Take(1).First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Complex_Keys()
        {
            var fluentValidation = _factory.GetFluentValidation<Thread>(Thread.CurrentThread);
            var results = fluentValidation
                .Check(u => u.CurrentCulture.DisplayName).IsEqualTo("")
                .Check(u => u.CurrentCulture.EnglishName).IsEqualTo("").Validate();

            Assert.AreEqual("CurrentCulture.DisplayName", results.First().Condition.Key);
            Assert.AreEqual("CurrentCulture.EnglishName", results.Skip(1).Take(1).First().Condition.Key);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_NotNullOrEmpty_With_Valid_Value()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsNotEmpty().Message("Username is not valid")
                .Validate();

            Assert.AreEqual(0, results.Count());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_NotNullOrEmpty_Message_Lookup()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsNotEmpty()
                .Validate();

            Assert.AreEqual("Username should not be empty", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Equal_Message_Lookup()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("test")
                .Validate();

            Assert.AreEqual("Username should be equal to test", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_NotEqual_Message_Lookup()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "test"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsNotEqualTo("test")
                .Validate();

            Assert.AreEqual("Username should not be equal to test", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_LessThan_Message_Lookup()
        {
            var user = new User {
                LoginCount = 11
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LoginCount).IsLessThan(10)
                .Validate();

            Assert.AreEqual("LoginCount should be less than 10", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_LessThanOrEqualTo_Message_Lookup()
        {
            var user = new User {
                LoginCount = 11
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LoginCount).IsLessThanOrEqualTo(10)
                .Validate();

            Assert.AreEqual("LoginCount should be less than or equal to 10", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_GreaterThan_Message_Lookup()
        {
            var user = new User {
                LoginCount = 9
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LoginCount).IsGreaterThan(10)
                .Validate();

            Assert.AreEqual("LoginCount should be greater than 10", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_GreaterThanOrEqualTo_Message_Lookup()
        {
            var user = new User {
                LoginCount = 9
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LoginCount).IsGreaterThanOrEqualTo(10)
                .Validate();

            Assert.AreEqual("LoginCount should be greater than or equal to 10", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Email_Message_Lookup()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Validate();

            Assert.AreEqual("Username should be an email", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Contains_Message_Lookup()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).Contains("dave")
                .Validate();

            Assert.AreEqual("Username should contain dave", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_IsLength_Message_Lookup()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsLength(5)
                .Validate();

            Assert.AreEqual("Username should be 5 characters long", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_IsRequired_Message_Lookup()
        {
            var user = new User {
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsRequired<string>()
                .Validate();

            Assert.AreEqual("Username is a required field", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Before_Message_Lookup()
        {
            var user = new User {
                LastLogin = DateTime.Now
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LastLogin).IsBefore(DateTime.Parse("01/01/2001 00:00:00"))
                .Validate();

            var message = string.Format("LastLogin should be before {0}", DateTime.Parse("01/01/2001 00:00:00"));

            Assert.AreEqual(message, results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_After_Message_Lookup()
        {
            var user = new User {
                LastLogin = DateTime.Parse("01/01/2001 00:00:00")
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LastLogin).IsAfter(DateTime.Parse("01/01/2012 00:00:00"))
                .Validate();

            var message = string.Format("LastLogin should be after {0}", DateTime.Parse("01/01/2012 00:00:00"));

            Assert.AreEqual(message, results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_On_Message_Lookup()
        {
            var user = new User {
                LastLogin = DateTime.Parse("01/01/2001 00:00:00")
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LastLogin).IsOn(DateTime.Parse("01/01/2012 00:00:00"))
                .Validate();

            var message = string.Format("LastLogin should be on {0}", DateTime.Parse("01/01/2012 00:00:00"));

            Assert.AreEqual(message, results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_On_Message_Lookup_Different_Culture()
        {
            var defaultCulture =  Thread.CurrentThread.CurrentUICulture;
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");

            var user = new User {
                LastLogin = DateTime.Parse("01/01/2001 00:00:00")
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LastLogin).IsOn(DateTime.Parse("01/01/2012 00:00:00"))
                .Validate();

            var message = string.Format("LastLogin doit être mis sur {0}", DateTime.Parse("01/01/2012 00:00:00"));

            Assert.AreEqual(message, results.First().Condition.Message);
            Thread.CurrentThread.CurrentUICulture = defaultCulture;
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Message_Lookup_Missing_Culture()
        {

            Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-RU");

            var user = new User {
                Password = "<PASSWORD>",
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsNotEmpty()
                .Validate();

            Assert.AreEqual("Username should not be empty", results.First().Condition.Message);
        }

        [Test]
        public void Test_Fluent_Validation_IsEmail_False_Loaded_From_Xml()
        {
            var user = new User {
                Username = "testing"
            };
            var fluentValidation = new FluentValidationFactory().GetFluentValidationFromConfig<User>(user, "IsEmail.validation.xml");
            Assert.IsFalse(fluentValidation.Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Email_Fluent_Message()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("The username should be some kind of valid email address")
                .Validate();

            Assert.AreEqual("The username should be some kind of valid email address", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Email_Chained_Fluent_Message()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("The username should be some kind of valid email address")
                .Check(u => u.Password).IsNotEmpty()
                .Message("The password should not be empty or null")
                .Validate();

            Assert.AreEqual("The password should not be empty or null", results.Skip(1).Take(1).First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Email_Chained_Fluent_Custom_Message()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("$ACustomMessage$")
                .Validate();

            Assert.AreEqual("Something different here", results.First().Condition.Message);
        }
        
        [Test]
        public void Test_Chained_Fluent_Validation_Multiple_Validation_Instances()
        {
            var user = new User {
                Username = "fred"
            };
            var emptyUser = new User {
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var secondFluentValidation = _factory.GetFluentValidation<User>(emptyUser);
            fluentValidation.Check(u => u.Username).IsNotEmpty();
            secondFluentValidation.Check(u => u.Username).IsNotEmpty();
            
            var first = fluentValidation.Satisfied();
            var second = secondFluentValidation.Satisfied();
            
            Assert.IsTrue(first && !second);
            
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Hint()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("Some kind of message")
                .Hint("A different hint message")
                .Validate();
            
            Assert.AreEqual("A different hint message", results.First().Condition.Hint);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Custom_Hint()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("Some kind of message")
                .Hint("$ACustomMessage$")
                .Validate();
            
            Assert.AreEqual("Something different here", results.First().Condition.Hint);
        }
    }
}
<commit_msg>More tests<commit_after>﻿using System;
using MFlow.Core.Events;
using MFlow.Core.Validation.Factories;
using MFlow.Core.Tests.Supporting;
using System.Linq;
using System.Threading;
using System.Globalization;
using MFlow.Core.Conditions.Enums;
using NUnit.Framework;
using MFlow.Core.Validation.Builder;

namespace MFlow.Core.Tests.Validation
{
    [TestFixture]
    public partial class FluentValidation
    {

        readonly IFluentValidationFactory _factory = new FluentValidationFactory();

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Test_Fluent_Validation_Constructor_Exception()
        {
            var fluentValidation = _factory.GetFluentValidation<User>(null);
            fluentValidation.Validate();
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Test_Fluent_Validation_Set_Target_When_Null()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            fluentValidation.SetTarget(null);
        }

        [Test]
        public void Test_Fluent_Validation_Set_Target_When_Not_Null()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            Assert.DoesNotThrow(() => { fluentValidation.SetTarget(user); });
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Test_Fluent_Validation_Set_Target_When_Null_After_Check()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            fluentValidation.Check(u=>u.Username).IsNotEmpty().SetTarget(null);
        }

        [Test]
        public void Test_Fluent_Validation_Set_Target_When_Not_Null_After_Check()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            Assert.DoesNotThrow(() => { fluentValidation.Check(u => u.Username).IsNotEmpty().SetTarget(user); });
        }


        [Test]
        public void Test_Fluent_Validation_Get_And_Set_Target()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            fluentValidation.SetTarget(user);

            var target = fluentValidation.GetTarget();
            Assert.AreEqual(user, target);
        }

        [Test]
        public void Test_Fluent_Validation_Get_And_Set_Target_After_Check()
        {
            var user = new User();
            var fluentValidation = _factory.GetFluentValidation(user);
            fluentValidation.Check(u=>u.Username).IsNotEmpty().SetTarget(user);

            var target = fluentValidation.Check(u=>u.Username).IsNotEmpty().GetTarget();
            Assert.AreEqual(user, target);
        }

        [Test]
        public void Test_Fluent_Validation_Clears_Conditions()
        {
            var user = new User
            {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("xxx").Clear();

            Assert.IsTrue(fluentValidation.Satisfied());
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void Test_Chained_Fluent_Validation_ValidateAndThrow_InValid()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("xxx").ValidateAndThrow<ArgumentException>();
        }

        [Test]
        public void Test_Chained_Fluent_Validation_ValidateAndThrow_Valid()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "xxx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsFalse(fluentValidation
                           .Check(u => u.Username).IsEqualTo("xxx").ValidateAndThrow<ArgumentException>().Any());
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void Test_Chained_Fluent_Validation_Throw_InValid()
        {
            var user = new User
            {
                Password = "<PASSWORD>",
                Username = "xxx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("xxx").Throw(new ArgumentException());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Throw_Valid()
        {
            var user = new User
            {
                Password = "<PASSWORD>",
                Username = "xxx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.DoesNotThrow(() =>
            {
                fluentValidation
                    .Check(u => u.Username).IsEqualTo("aaa").Throw(new ArgumentException());
            });
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_InValid_Expression()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsFalse(fluentValidation
                           .Check(u => u.Username).IsEqualTo("xxx").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_Valid_Expression_Chain()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsTrue(fluentValidation
                          .Check(u => u.Username).IsEqualTo("testing")
                          .Check(u => u.Password).IsEqualTo("<PASSWORD>").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_InValid_Expression_Chain()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsFalse(fluentValidation
                           .Check(u => u.Username).IsEqualTo("testing")
                           .Check(u => u.Password).IsEqualTo("<PASSWORD>").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_Valid_Or_Expression_Chain()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsTrue(fluentValidation
                          .Check(u => u.Username).IsEqualTo("testing")
                          .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                          .Check(u => u.Username, conditionType: ConditionType.Or).IsEqualTo("testingx").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_InValid_Or_Expression_Chain()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            Assert.IsFalse(fluentValidation
                           .Check(u => u.Username).IsEqualTo("testing")
                           .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                           .Check(u => u.Username, conditionType: ConditionType.Or).IsEqualTo("test").Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_Valid_Expression_Executes()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                .Then(() =>
                      {
                          user.Username = "valid";
                      });

            Assert.IsTrue(user.Username == "valid");
        }

        [Test]
        public void Test_Chained_Fluent_Validation_With_Valid_Expression_Executes_Else()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing2"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                .Then(() => {
                          user.Username = "valid"; })
                .Else(() => {
                          user.Username = "invalid"; });

            Assert.IsTrue(user.Username == "invalid");
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Raises_Event()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testing"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);

            var events = new EventsFactory().GetEventStore();
            events.Register<UserCreatedEvent>(s =>
                                              {
                                                  s.Source.Username = "caught event";
                                                  user = s.Source;
                                              });

            fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>")
                .Raise(new UserCreatedEvent(user));

            Assert.AreEqual(user.Username, "caught event");
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Number_Of_Results()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual(1, results.ToList().Count());

        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Key()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual("Username", results.First().Condition.Key);

        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Message()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing").Message("Username is not valid")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual("Username is not valid", results.First().Condition.Message);

        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Number_Of_Multipe_Results()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual(2, results.ToList().Count());

        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Number_Of_Multipe_Results_With_Warnings_Supressed()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Username).IsEqualTo("abc").Warn()
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual(2, results.ToList().Count());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Number_Of_Multipe_Results_With_Warnings()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Username).IsEqualTo("abc").Warn()
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate(suppressWarnings: false);

            Assert.AreEqual(3, results.ToList().Count());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Keys()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Validate();

            Assert.AreEqual("Username", results.First().Condition.Key);
            Assert.AreEqual("Password", results.Skip(1).Take(1).First().Condition.Key);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Messages()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("testing").Message("Username is not valid")
                .Check(u => u.Password).IsEqualTo("<PASSWORD>").Message("Password is now valid").Validate();

            Assert.AreEqual("Username is not valid", results.First().Condition.Message);
            Assert.AreEqual("Password is now valid", results.Skip(1).Take(1).First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Returns_Correct_Complex_Keys()
        {
            var fluentValidation = _factory.GetFluentValidation<Thread>(Thread.CurrentThread);
            var results = fluentValidation
                .Check(u => u.CurrentCulture.DisplayName).IsEqualTo("")
                .Check(u => u.CurrentCulture.EnglishName).IsEqualTo("").Validate();

            Assert.AreEqual("CurrentCulture.DisplayName", results.First().Condition.Key);
            Assert.AreEqual("CurrentCulture.EnglishName", results.Skip(1).Take(1).First().Condition.Key);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_NotNullOrEmpty_With_Valid_Value()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "testingx"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsNotEmpty().Message("Username is not valid")
                .Validate();

            Assert.AreEqual(0, results.Count());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_NotNullOrEmpty_Message_Lookup()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsNotEmpty()
                .Validate();

            Assert.AreEqual("Username should not be empty", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Equal_Message_Lookup()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEqualTo("test")
                .Validate();

            Assert.AreEqual("Username should be equal to test", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_NotEqual_Message_Lookup()
        {
            var user = new User {
                Password = "<PASSWORD>",
                Username = "test"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsNotEqualTo("test")
                .Validate();

            Assert.AreEqual("Username should not be equal to test", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_LessThan_Message_Lookup()
        {
            var user = new User {
                LoginCount = 11
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LoginCount).IsLessThan(10)
                .Validate();

            Assert.AreEqual("LoginCount should be less than 10", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_LessThanOrEqualTo_Message_Lookup()
        {
            var user = new User {
                LoginCount = 11
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LoginCount).IsLessThanOrEqualTo(10)
                .Validate();

            Assert.AreEqual("LoginCount should be less than or equal to 10", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_GreaterThan_Message_Lookup()
        {
            var user = new User {
                LoginCount = 9
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LoginCount).IsGreaterThan(10)
                .Validate();

            Assert.AreEqual("LoginCount should be greater than 10", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_GreaterThanOrEqualTo_Message_Lookup()
        {
            var user = new User {
                LoginCount = 9
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LoginCount).IsGreaterThanOrEqualTo(10)
                .Validate();

            Assert.AreEqual("LoginCount should be greater than or equal to 10", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Email_Message_Lookup()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Validate();

            Assert.AreEqual("Username should be an email", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Contains_Message_Lookup()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).Contains("dave")
                .Validate();

            Assert.AreEqual("Username should contain dave", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_IsLength_Message_Lookup()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsLength(5)
                .Validate();

            Assert.AreEqual("Username should be 5 characters long", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_IsRequired_Message_Lookup()
        {
            var user = new User {
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsRequired<string>()
                .Validate();

            Assert.AreEqual("Username is a required field", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Before_Message_Lookup()
        {
            var user = new User {
                LastLogin = DateTime.Now
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LastLogin).IsBefore(DateTime.Parse("01/01/2001 00:00:00"))
                .Validate();

            var message = string.Format("LastLogin should be before {0}", DateTime.Parse("01/01/2001 00:00:00"));

            Assert.AreEqual(message, results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_After_Message_Lookup()
        {
            var user = new User {
                LastLogin = DateTime.Parse("01/01/2001 00:00:00")
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LastLogin).IsAfter(DateTime.Parse("01/01/2012 00:00:00"))
                .Validate();

            var message = string.Format("LastLogin should be after {0}", DateTime.Parse("01/01/2012 00:00:00"));

            Assert.AreEqual(message, results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_On_Message_Lookup()
        {
            var user = new User {
                LastLogin = DateTime.Parse("01/01/2001 00:00:00")
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LastLogin).IsOn(DateTime.Parse("01/01/2012 00:00:00"))
                .Validate();

            var message = string.Format("LastLogin should be on {0}", DateTime.Parse("01/01/2012 00:00:00"));

            Assert.AreEqual(message, results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_On_Message_Lookup_Different_Culture()
        {
            var defaultCulture =  Thread.CurrentThread.CurrentUICulture;
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");

            var user = new User {
                LastLogin = DateTime.Parse("01/01/2001 00:00:00")
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.LastLogin).IsOn(DateTime.Parse("01/01/2012 00:00:00"))
                .Validate();

            var message = string.Format("LastLogin doit être mis sur {0}", DateTime.Parse("01/01/2012 00:00:00"));

            Assert.AreEqual(message, results.First().Condition.Message);
            Thread.CurrentThread.CurrentUICulture = defaultCulture;
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Message_Lookup_Missing_Culture()
        {

            Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-RU");

            var user = new User {
                Password = "<PASSWORD>",
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsNotEmpty()
                .Validate();

            Assert.AreEqual("Username should not be empty", results.First().Condition.Message);
        }

        [Test]
        public void Test_Fluent_Validation_IsEmail_False_Loaded_From_Xml()
        {
            var user = new User {
                Username = "testing"
            };
            var fluentValidation = new FluentValidationFactory().GetFluentValidationFromConfig<User>(user, "IsEmail.validation.xml");
            Assert.IsFalse(fluentValidation.Satisfied());
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Email_Fluent_Message()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("The username should be some kind of valid email address")
                .Validate();

            Assert.AreEqual("The username should be some kind of valid email address", results.First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Email_Chained_Fluent_Message()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("The username should be some kind of valid email address")
                .Check(u => u.Password).IsNotEmpty()
                .Message("The password should not be empty or null")
                .Validate();

            Assert.AreEqual("The password should not be empty or null", results.Skip(1).Take(1).First().Condition.Message);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Email_Chained_Fluent_Custom_Message()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("$ACustomMessage$")
                .Validate();

            Assert.AreEqual("Something different here", results.First().Condition.Message);
        }
        
        [Test]
        public void Test_Chained_Fluent_Validation_Multiple_Validation_Instances()
        {
            var user = new User {
                Username = "fred"
            };
            var emptyUser = new User {
                Username = ""
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var secondFluentValidation = _factory.GetFluentValidation<User>(emptyUser);
            fluentValidation.Check(u => u.Username).IsNotEmpty();
            secondFluentValidation.Check(u => u.Username).IsNotEmpty();
            
            var first = fluentValidation.Satisfied();
            var second = secondFluentValidation.Satisfied();
            
            Assert.IsTrue(first && !second);
            
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Hint()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("Some kind of message")
                .Hint("A different hint message")
                .Validate();
            
            Assert.AreEqual("A different hint message", results.First().Condition.Hint);
        }

        [Test]
        public void Test_Chained_Fluent_Validation_Custom_Hint()
        {
            var user = new User {
                Username = "fred"
            };
            var fluentValidation = _factory.GetFluentValidation<User>(user);
            var results = fluentValidation
                .Check(u => u.Username).IsEmail()
                .Message("Some kind of message")
                .Hint("$ACustomMessage$")
                .Validate();
            
            Assert.AreEqual("Something different here", results.First().Condition.Hint);
        }
    }
}

{'fraction_non_alphanumeric': 0.10135671740569159, 'fraction_numerical': 0.006485771012574454, 'mean_word_length': 1.6579155672823218, 'pattern_counts': {'":': 0, '<': 185, '<?xml version=': 0, '>': 338, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6981876', 'n_tokens_mistral': 15721, 'n_tokens_neox': 14575, 'n_words': 2677}