public void RemoveRule_ThereAreTwoFailedRules_RemoveOne_ResultChangedShouldBeFiredWithNewResultStillInvalid() { // ARRANGE var dummy = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(nameof(dummy.Foo), () => RuleResult.Invalid("error2")); var invalidRule = validation.AddRule(nameof(dummy.Foo), () => RuleResult.Invalid("error")); var validationResult = validation.ValidateAll(); Assert.False(validationResult.IsValid); bool resultChangedEventFired = false; validation.ResultChanged += (sender, args) => { Assert.Equal(nameof(dummy.Foo), args.Target); Assert.False(args.NewResult.IsValid); resultChangedEventFired = true; }; // ACT validation.RemoveRule(invalidRule); // VERIFY Assert.True(resultChangedEventFired); }
private void SetupValidation() { var validationRules = new ValidationHelper(); // Simple properties validationRules.AddRule(nameof(StringProperty), () => RuleResult.Assert(!string.IsNullOrEmpty(StringProperty), "StringProperty cannot be null or empty string")); validationRules.AddRule(nameof(IntProperty), () => RuleResult.Assert(IntProperty > 0, "IntProperty should be greater than zero.")); // Dependant properties validationRules.AddRule(nameof(RangeStart), nameof(RangeEnd), () => RuleResult.Assert(RangeEnd > RangeStart, "RangeEnd must be grater than RangeStart")); // Long-running validation (simulates call to a web service or something) validationRules.AddRule( nameof(StringProperty2), () => { SyncValidationRuleExecutedAsyncroniouslyDelegate?.Invoke(); return(RuleResult.Assert(!string.IsNullOrEmpty(StringProperty2), "StringProperty2 cannot be null or empty string")); }); Validation = validationRules; DataErrorInfoValidationAdapter = new NotifyDataErrorInfoAdapter(Validation); }
public void Validate_MultipleRulesForSameTarget_DoesNotExecuteRulesIfPerviousFailed() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); bool firstRuleExecuted = false; bool secondRuleExecuted = false; validation.AddRule(nameof(dummy.Foo), () => { firstRuleExecuted = true; return(RuleResult.Invalid("Error1")); }); validation.AddRule(nameof(dummy.Foo), () => { secondRuleExecuted = true; return(RuleResult.Invalid("Error2")); }); // ACT validation.ValidateAll(); // VERIFY Assert.True(firstRuleExecuted, "First rule must have been executed"); Assert.False(secondRuleExecuted, "Second rule should not have been executed because first rule failed."); }
public void RemoveAllRules_HadTwoNegativeRulesRegisteredForDifferentTargets_ResultChangedIsFiredForAllTargets() { // ARRANGE var dummy = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(() => dummy.Foo, () => RuleResult.Invalid("error1")); validation.AddRule(() => dummy.Bar, () => RuleResult.Invalid("error2")); validation.ValidateAll(); int resultChangedFiredCount = 0; validation.ResultChanged += (sender, args) => { resultChangedFiredCount++; }; // ACT validation.RemoveAllRules(); // VERIFY Assert.Equal(2, resultChangedFiredCount); }
public void Validate_MultipleRulesForSameTarget_ClearsResultsBeforeValidation() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); RuleResult firstRuleResult = RuleResult.Valid(); RuleResult secondRuleResult = RuleResult.Invalid("Error2"); validation.AddRule(nameof(dummy.Foo), () => { return(firstRuleResult); }); validation.AddRule(nameof(dummy.Foo), () => { return(secondRuleResult); }); // ACT validation.ValidateAll(); firstRuleResult = RuleResult.Invalid("Error1"); validation.ValidateAll(); // VERIFY var result = validation.GetResult(nameof(dummy.Foo)); Assert.False(result.IsValid); Assert.Equal(1, result.ErrorList.Count); Assert.Equal("Error1", result.ErrorList[0].ErrorText); }
public void ResultChanged_ValidateExecutedForSeveralRules_FiresForEachTarget() { // Arrange var validation = new ValidationHelper(); var dummy = new DummyViewModel(); validation.AddRule(nameof(dummy.Foo), () => RuleResult.Invalid("Error")); validation.AddRule(nameof(dummy.Foo), RuleResult.Valid); validation.AddRule(nameof(dummy.Bar), RuleResult.Valid); validation.AddRule(() => RuleResult.Invalid("Error")); const int expectedTimesToFire = 0 + 1 /*Invalid Foo*/ + 1 /* Invalid general target */; var eventFiredTimes = 0; validation.ResultChanged += (o, e) => { eventFiredTimes++; }; // Act validation.ValidateAll(); // Verify Assert.Equal(expectedTimesToFire, eventFiredTimes); }
public void RemoveRule_ThisRuleHadValidationError_ResultChangedEventIsFiredForCorrectTargetAndTargetIsValid() { // ARRANGE var validation = new ValidationHelper(); validation.AddRule(RuleResult.Valid); var invalidRule = validation.AddRule("test_target", () => RuleResult.Invalid("error")); var validationResult = validation.ValidateAll(); Assert.False(validationResult.IsValid); bool resultChangedEventFired = false; validation.ResultChanged += (sender, args) => { Assert.Equal("test_target", args.Target); Assert.True(args.NewResult.IsValid); resultChangedEventFired = true; }; // ACT validation.RemoveRule(invalidRule); // VERIFY Assert.True(resultChangedEventFired); }
public void CombineRuleResults_ResultContainsErrorsFromAllCombinedResults() { // Arrange var validation = new ValidationHelper(); validation.AddRule(() => { //var r1 = RuleResult.Invalid("Error1"); //var r2 = RuleResult.Valid(); //var r3 = RuleResult.Invalid("Error2"); return (RuleResult.Assert(false, "Error1").Combine( RuleResult.Assert(true, "Error0")).Combine( RuleResult.Assert(false, "Error2"))); //return r1.Combine(r2).Combine(r3); }); // Act var result = validation.ValidateAll(); // Assert Assert.False(result.IsValid, "The validation must fail"); Assert.Equal(2, result.ErrorList.Count); Assert.True(result.ErrorList.Any(e => e.ErrorText == "Error1")); Assert.True(result.ErrorList.Any(e => e.ErrorText == "Error2")); }
public void CombineRuleResults_ResultContainsErrorsFromAllCombinedResults() { // Arrange var validation = new ValidationHelper(); validation.AddRule(() => { //var r1 = RuleResult.Invalid("Error1"); //var r2 = RuleResult.Valid(); //var r3 = RuleResult.Invalid("Error2"); return RuleResult.Assert(false, "Error1").Combine( RuleResult.Assert(true, "Error0")).Combine( RuleResult.Assert(false, "Error2")); //return r1.Combine(r2).Combine(r3); }); // Act var result = validation.ValidateAll(); // Assert Assert.False(result.IsValid, "The validation must fail"); Assert.Equal(2, result.ErrorList.Count); Assert.True(result.ErrorList.Any(e => e.ErrorText == "Error1")); Assert.True(result.ErrorList.Any(e => e.ErrorText == "Error2")); }
public void RemoveAllRules_HadTwoNegativeRulesRegistered_ValidationSucceds() { // ARRANGE var validation = new ValidationHelper(); validation.AddRule(() => RuleResult.Invalid("error1")); validation.AddRule(() => RuleResult.Invalid("error2")); // ACT validation.RemoveAllRules(); var validationResult = validation.ValidateAll(); // VERIFY Assert.True(validationResult.IsValid, "Validation should not produce any errors after all rules were removed."); }
public void SyncValidation_SeveralRulesForOneTarget_ValidWhenAllRulesAreValid() { var vm = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(vm, RuleResult.Valid); validation.AddRule(vm, () => { return(RuleResult.Invalid("Rule 2 failed")); }); validation.AddRule(vm, RuleResult.Valid); var r = validation.Validate(vm); Assert.False(r.IsValid); }
public void AsyncValidation_SyncRule_ExecutedAsyncroniously() { TestUtils.ExecuteWithDispatcher((dispatcher, completedAction) => { var vm = new DummyViewModel(); vm.Foo = null; var validation = new ValidationHelper(); validation.AddRule(() => { Assert.False(dispatcher.Thread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId, "Rule must be executed in a background thread."); if (string.IsNullOrEmpty(vm.Foo)) { return(RuleResult.Invalid("Foo cannot be empty string.")); } return(RuleResult.Valid()); }); validation.ValidateAllAsync().ContinueWith(r => completedAction()); }); }
private bool ValidateTokenAddress() { var validator = new ValidationHelper(); validator.AddRequiredRule(() => ContractAddress, "Token address is required."); var resultOne = validator.ValidateAll(); if (!resultOne.IsValid) { Errors = resultOne.ErrorList; return(resultOne.IsValid); } bool isValidAddress; try { isValidAddress = new Regex("^(?=.{42}$)0x[a-fA-F0-9]*").IsMatch(ContractAddress); } catch (Exception e) { isValidAddress = false; } validator.AddRule(ContractAddress, () => RuleResult.Assert(isValidAddress, "Token address is not valid Ethereum smart contract address.")); var result = validator.ValidateAll(); Errors = result.ErrorList; return(result.IsValid); }
public static void AddErrors(this ValidationHelper validator, string target, List <string> errors) { errors?.ForEach(it => { validator.AddRule(target, () => RuleResult.Invalid($"{target}: {it}")); }); }
protected override void ConfigureValidationRules(ValidationHelper validationHelper) { validationHelper.AddRule( () => Username, () => !string.IsNullOrWhiteSpace(Password) && string.IsNullOrWhiteSpace(Username) ? RuleResult.Invalid("Username is required") : RuleResult.Valid() ); validationHelper.AddRule( () => Password, () => !string.IsNullOrWhiteSpace(Username) && string.IsNullOrWhiteSpace(Password) ? RuleResult.Invalid("Password is required") : RuleResult.Valid() ); }
private void ValidateTransaction() { try { this._amount = BigDecimal.Parse(this._amountString); } catch (Exception e) { this._amount = null; } var validator = new ValidationHelper(); validator.AddRequiredRule(() => ReceiverAddress, "Address receiver is required."); validator.AddRequiredRule(() => _amount, "Valid amount is required."); validator.AddRequiredRule(() => Token, "Select token to send."); var resultTemp = validator.ValidateAll(); if (!resultTemp.IsValid) { Errors = resultTemp.ErrorList; IsValid = resultTemp.IsValid; return; } bool isValidAddress; try { isValidAddress = new Regex("^(?=.{42}$)0x[a-zA-Z0-9]*").IsMatch(ReceiverAddress); } catch (Exception e) { isValidAddress = false; } validator.AddRule(ReceiverAddress, () => RuleResult.Assert(isValidAddress, "Receiver address is not valid Ethereum account address.")); validator.AddRule(Amount, () => RuleResult.Assert(this._amount > new BigDecimal(0), "Amount is zero.")); validator.AddRule(Amount, () => RuleResult.Assert(this._amount < Token.Balance, "You don't have enough funds.")); var result = validator.ValidateAll(); Errors = result.ErrorList; IsValid = result.IsValid; }
public void RemoveAllRules_HadTwoFailedRules_ErrorGetsRemovedAlso() { // ARRANGE var validation = new ValidationHelper(); validation.AddRule(() => RuleResult.Invalid("error1")); validation.AddRule(() => RuleResult.Invalid("error2")); var validationResult = validation.ValidateAll(); // ACT validation.RemoveAllRules(); validationResult = validation.GetResult(); // VERIFY Assert.True(validationResult.IsValid, "Validation should not produce any errors after all rules were removed."); }
public async void SyncValidation_RuleThrowsException_ExceptionIsPropogated() { // ARRANGE var validator = new ValidationHelper(); validator.AddRule(() => { throw new InvalidOperationException("Test"); }); // ACT & VERIFY await Assert.ThrowsAsync <ValidationException>(() => validator.ValidateAllAsync()); }
public void RemoveRule_ThisRuleHadValidationError_ErrorGetsRemovedAlso() { // ARRANGE var validation = new ValidationHelper(); validation.AddRule(RuleResult.Valid); var invalidRule = validation.AddRule(() => RuleResult.Invalid("error")); var validationResult = validation.ValidateAll(); Assert.False(validationResult.IsValid); // ACT validation.RemoveRule(invalidRule); validationResult = validation.GetResult(); // VERIFY Assert.True(validationResult.IsValid); }
public void Reset_AllTargetsBecomeValidAgain() { // ARRANGE var dummy = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(nameof(dummy.Foo), () => RuleResult.Invalid("error1")); validation.AddRule(nameof(dummy.Bar), () => RuleResult.Invalid("error2")); validation.ValidateAll(); // ACT validation.Reset(); // VERIFY Assert.True(validation.GetResult().IsValid); Assert.True(validation.GetResult(nameof(dummy.Foo)).IsValid); Assert.True(validation.GetResult(nameof(dummy.Bar)).IsValid); }
public void Validate_MultipleRulesForSameTarget_OptionToAllowValidationOnFailedTargetsIsSetForSpecificRule_ThatRuleIsExecuted() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); bool firstRuleExecuted = false; bool secondRuleExecuted = false; bool thirdRuleExecuted = false; validation.AddRule(nameof(dummy.Foo), () => { firstRuleExecuted = true; return(RuleResult.Invalid("Error1")); }); validation.AddRule(nameof(dummy.Foo), () => { secondRuleExecuted = true; return(RuleResult.Invalid("Error2")); }); validation.AddRule(nameof(dummy.Foo), () => { thirdRuleExecuted = true; return(RuleResult.Invalid("Error3")); }).WithSettings(s => s.ExecuteOnAlreadyInvalidTarget = true); // ACT validation.ValidateAll(); // VERIFY Assert.True(firstRuleExecuted, "First rule must have been executed"); Assert.False(secondRuleExecuted, "Second rule should not have been executed because first rule failed."); Assert.True(thirdRuleExecuted, "Third rule should be executed because it is configured to be executed on already invalid target."); }
public void Reset_ResultChangedFiresForInvalidTargets() { // ARRANGE var dummy = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(RuleResult.Valid); validation.AddRule(nameof(dummy.Foo), () => RuleResult.Invalid("error1")); validation.AddRule(nameof(dummy.Bar), () => RuleResult.Invalid("error2")); validation.ValidateAll(); bool eventFiredForFoo = false; bool evernFiredForBar = false; validation.ResultChanged += (sender, args) => { if (Equals(args.Target, nameof(dummy.Foo))) { eventFiredForFoo = true; } else if (Equals(args.Target, nameof(dummy.Bar))) { evernFiredForBar = true; } else { Assert.False(true, "ResultChanged event fired for an unexpected target."); } Assert.True(args.NewResult.IsValid); }; // ACT validation.Reset(); // VERIFY Assert.True(eventFiredForFoo); Assert.True(evernFiredForBar); }
public void RemoveRule_ReExecuteValidation_RemovedRuleDoesNotExecute() { // ARRANGE var validation = new ValidationHelper(); validation.AddRule(RuleResult.Valid); var invalidRule = validation.AddRule(() => RuleResult.Invalid("error")); var validationResult = validation.ValidateAll(); Assert.False(validationResult.IsValid); // ACT validation.RemoveRule(invalidRule); validationResult = validation.ValidateAll(); // VERIFY Assert.True(validationResult.IsValid); }
public void ResultChanged_RuleErrorsChangedButRuleValidityDidNotChange_EventStillFires() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); validation.AddRule(() => dummy.Foo, () => { if (string.IsNullOrEmpty(dummy.Foo)) { return(RuleResult.Invalid("Foo should not be empty")); } return (RuleResult.Assert(dummy.Foo.Length > 5, "Length must be greater than 5").Combine( RuleResult.Assert(dummy.Foo.Any(Char.IsDigit), "Must contain digit"))); }); var resultChangedCalledTimes = 0; const int expectedResultChangedCalls = 1 /* First invalid value */ + 1 /* Second invalid value */ + 1 /* Third invalid value */ + 1 /* Valid value */; validation.ResultChanged += (o, e) => { resultChangedCalledTimes++; }; // ACT dummy.Foo = null; // Should generage "Foo should not be empty" error validation.ValidateAll(); dummy.Foo = "123"; // Should generate the "Length must be greater than 5" error validation.ValidateAll(); dummy.Foo = "sdfldlssd"; // Should generate the "Must contain digit" error validation.ValidateAll(); dummy.Foo = "lsdklfjsld2342"; // Now should be valid validation.ValidateAll(); // VERIFY Assert.Equal(expectedResultChangedCalls, resultChangedCalledTimes); }
private void ValidateToken() { var validator = new ValidationHelper(); validator.AddRequiredRule(() => TokenName, "Token name is required."); validator.AddRequiredRule(() => TokenSymbol, "Token symbol is required."); validator.AddRequiredRule(() => Decimals, "Token decimals is required."); if (!string.IsNullOrWhiteSpace(Decimals)) { var isValid = int.TryParse(Decimals, out int temp); validator.AddRule(ContractAddress, () => RuleResult.Assert(temp >= 0, "Decimals must be greater than zero.")); validator.AddRule(ContractAddress, () => RuleResult.Assert(isValid, "Decimals must be valid number.")); } var result = validator.ValidateAll(); Errors = result.ErrorList; IsValid = result.IsValid; }
public void Validate_ValidationResultIsValid_ToStringReturnsEmptyString() { // ARRANGE var validation = new ValidationHelper(); validation.AddRule(RuleResult.Valid); // ACT var r = validation.ValidateAll(); // VERIFY Assert.True(r.ToString() == string.Empty); }
public void Validate_MultipleRulesForSameTarget_OptionToAllowValidationOnFailedTargetsIsSetGlobally_AllRulesAreExecuted() { // ARRANGE var validation = new ValidationHelper(new ValidationSettings { DefaultRuleSettings = new ValidationRuleSettings { ExecuteOnAlreadyInvalidTarget = true } }); var dummy = new DummyViewModel(); bool firstRuleExecuted = false; bool secondRuleExecuted = false; validation.AddRule(nameof(dummy.Foo), () => { firstRuleExecuted = true; return(RuleResult.Invalid("Error1")); }); validation.AddRule(nameof(dummy.Foo), () => { secondRuleExecuted = true; return(RuleResult.Invalid("Error2")); }); // ACT validation.ValidateAll(); // VERIFY Assert.True(firstRuleExecuted, "First rule must have been executed"); Assert.True(secondRuleExecuted, "Second rule should be executed as well even though the target is already invalid."); }
public void Validate_ThereAreAsyncRules_ThrowsException() { // ARRANGE var validation = new ValidationHelper(); // Add a simple sync rule validation.AddRule(RuleResult.Valid); // Add an async rule validation.AddAsyncRule(() => Task.Run(() => RuleResult.Invalid("Error"))); // ACT Assert.Throws <InvalidOperationException>(() => { validation.ValidateAll(); }); }
public void AsyncValidation_MixedAsyncAndNotAsyncRules_AllExecutedBeforeValidationCompleted() { TestUtils.ExecuteWithDispatcher((dispatcher, completedAction) => { var vm = new DummyViewModel(); var validation = new ValidationHelper(); bool rule1Executed = false; validation.AddAsyncRule(vm, () => { return(Task.Run(() => { rule1Executed = true; return RuleResult.Valid(); })); }); bool rule2Executed = false; validation.AddRule(vm, () => { rule2Executed = true; return(RuleResult.Valid()); }); bool rule3Executed = false; validation.AddAsyncRule(vm, () => { return(Task.Run(() => { rule3Executed = true; return RuleResult.Valid(); })); }); validation.ValidateAllAsync().ContinueWith(r => { Assert.True(rule1Executed); Assert.True(rule2Executed); Assert.True(rule3Executed); Assert.True(r.Result.IsValid); completedAction(); }); }); }
private bool ValidateMnemonicPhrase() { var validator = new ValidationHelper(); validator.AddRequiredRule(() => this.InputMnemonic, "Mnemonic phrase is required."); foreach (var func in Validators) { validator.AddRule(nameof(this.InputMnemonic), () => RuleResult.Assert(func.Value(InputMnemonic), func.Key)); } var result = validator.ValidateAll(); Errors = result.ErrorList; return(result.IsValid); }
private bool Validate() { ValidationHelper validator = new ValidationHelper(); validator.AddRequiredRule(() => ReminderDay, LocalizationManager.GetString("reminder_date_required")); validator.AddRequiredRule(() => ReminderTime, LocalizationManager.GetString("reminder_time_required")); validator.AddRequiredRule(() => SelectedReminder.Title, LocalizationManager.GetString("reminder_title_required")); validator.AddRule("MinimumDate", () => { bool condition = true; if (_reminderDay.HasValue && !string.IsNullOrEmpty(_reminderTime)) { var day = _reminderDay.Value; var timeElements = _reminderTime.Split(':'); if (timeElements.Length >= 2) { int hour = -1, minute = -1; if (int.TryParse(timeElements[0], out hour)) { if (int.TryParse(timeElements[1], out minute)) { DateTime newDate = new DateTime(day.Year, day.Month, day.Day, hour, minute, 0, DateTimeKind.Local); newDate = newDate.ToUniversalTime(); long unixDateTime = ((DateTimeOffset)newDate).ToUnixTimeSeconds(); _selectedReminder.Date = unixDateTime; condition = _selectedReminder.Date > ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds(); } } } } return(RuleResult.Assert(condition, LocalizationManager.GetString("date_time_not_past_error"))); }); var result = validator.ValidateAll(); Errors = result.AsObservableDictionary(); return(result.IsValid); }
public void SyncValidation_SeveralRulesForOneTarget_ValidWhenAllRulesAreValid() { var vm = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(vm, RuleResult.Valid); validation.AddRule(vm, () => { return RuleResult.Invalid("Rule 2 failed"); }); validation.AddRule(vm, RuleResult.Valid); var r = validation.Validate(vm); Assert.False(r.IsValid); }
public void AsyncValidation_SyncRule_ExecutedAsyncroniously() { TestUtils.ExecuteWithDispatcher((dispatcher, completedAction) => { var vm = new DummyViewModel(); vm.Foo = null; var validation = new ValidationHelper(); validation.AddRule(() => { Assert.False(dispatcher.Thread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId, "Rule must be executed in a background thread."); if (string.IsNullOrEmpty(vm.Foo)) { return RuleResult.Invalid("Foo cannot be empty string."); } return RuleResult.Valid(); }); validation.ValidateAllAsync().ContinueWith(r => completedAction()); }); }
public void ValidateAsync_MultipleRulesForSameTarget_DoesNotExecuteRulesIfPerviousFailed() { TestUtils.ExecuteWithDispatcher((uiThreadDispatcher, completedAction) => { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); bool firstRuleExecuted = false; bool secondRuleExecuted = false; validation.AddRule(() => dummy.Foo, () => { firstRuleExecuted = true; return RuleResult.Invalid("Error1"); }); validation.AddAsyncRule(() => dummy.Foo, onCompleted => { secondRuleExecuted = true; onCompleted(RuleResult.Invalid("Error2")); }); // ACT validation.ValidateAllAsync().ContinueWith(result => { // VERIFY Assert.True(firstRuleExecuted, "First rule must have been executed"); Assert.False(secondRuleExecuted, "Second rule should not have been executed because first rule failed."); completedAction(); }); }); }
public void ValidationResultChanged_ValidateExecutedForOneRule_FiresOneTime() { // Arrange var validation = new ValidationHelper(); var dummy = new DummyViewModel(); validation.AddRule(() => dummy.Foo, () => RuleResult.Invalid("Error")); var eventFiredTimes = 0; validation.ResultChanged += (o, e) => { eventFiredTimes++; }; // Act validation.ValidateAll(); // Verity Assert.Equal(1, eventFiredTimes); }
public void Reset_AllTargetsBecomeValidAgain() { // ARRANGE var dummy = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(() => dummy.Foo, () => RuleResult.Invalid("error1")); validation.AddRule(() => dummy.Bar, () => RuleResult.Invalid("error2")); validation.ValidateAll(); // ACT validation.Reset(); // VERIFY Assert.True(validation.GetResult().IsValid); Assert.True(validation.GetResult(() => dummy.Foo).IsValid); Assert.True(validation.GetResult(() => dummy.Bar).IsValid); }
public void Validate_MultipleRulesForSameTarget_OptionToAllowValidationOnFailedTargetsIsSetForSpecificRule_ThatRuleIsExecuted() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); bool firstRuleExecuted = false; bool secondRuleExecuted = false; bool thirdRuleExecuted = false; validation.AddRule(nameof(dummy.Foo), () => { firstRuleExecuted = true; return RuleResult.Invalid("Error1"); }); validation.AddRule(nameof(dummy.Foo), () => { secondRuleExecuted = true; return RuleResult.Invalid("Error2"); }); validation.AddRule(nameof(dummy.Foo), () => { thirdRuleExecuted = true; return RuleResult.Invalid("Error3"); }).WithSettings(s => s.ExecuteOnAlreadyInvalidTarget = true); // ACT validation.ValidateAll(); // VERIFY Assert.True(firstRuleExecuted, "First rule must have been executed"); Assert.False(secondRuleExecuted, "Second rule should not have been executed because first rule failed."); Assert.True(thirdRuleExecuted, "Third rule should be executed because it is configured to be executed on already invalid target."); }
public void Validate_MultipleRulesForSameTarget_OptionToAllowValidationOnFailedTargetsIsSetGlobally_AllRulesAreExecuted() { // ARRANGE var validation = new ValidationHelper(new ValidationSettings { DefaultRuleSettings = new ValidationRuleSettings { ExecuteOnAlreadyInvalidTarget = true } }); var dummy = new DummyViewModel(); bool firstRuleExecuted = false; bool secondRuleExecuted = false; validation.AddRule(nameof(dummy.Foo), () => { firstRuleExecuted = true; return RuleResult.Invalid("Error1"); }); validation.AddRule(nameof(dummy.Foo), () => { secondRuleExecuted = true; return RuleResult.Invalid("Error2"); }); // ACT validation.ValidateAll(); // VERIFY Assert.True(firstRuleExecuted, "First rule must have been executed"); Assert.True(secondRuleExecuted, "Second rule should be executed as well even though the target is already invalid."); }
public void ResultChanged_RuleErrorsChangedButRuleValidityDidNotChange_EventStillFires() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); validation.AddRule(() => dummy.Foo, () => { if (string.IsNullOrEmpty(dummy.Foo)) { return RuleResult.Invalid("Foo should not be empty"); } return RuleResult.Assert(dummy.Foo.Length > 5, "Length must be greater than 5").Combine( RuleResult.Assert(dummy.Foo.Any(Char.IsDigit), "Must contain digit")); }); var resultChangedCalledTimes = 0; const int expectedResultChangedCalls = 1 /* First invalid value */+ 1 /* Second invalid value */+ 1 /* Third invalid value */ + 1 /* Valid value */; validation.ResultChanged += (o, e) => { resultChangedCalledTimes++; }; // ACT dummy.Foo = null; // Should generage "Foo should not be empty" error validation.ValidateAll(); dummy.Foo = "123"; // Should generate the "Length must be greater than 5" error validation.ValidateAll(); dummy.Foo = "sdfldlssd"; // Should generate the "Must contain digit" error validation.ValidateAll(); dummy.Foo = "lsdklfjsld2342"; // Now should be valid validation.ValidateAll(); // VERIFY Assert.Equal(expectedResultChangedCalls, resultChangedCalledTimes); }
public void ResultChanged_ValidateExecutedForSeveralRules_FiresForEachTarget() { // Arrange var validation = new ValidationHelper(); var dummy = new DummyViewModel(); validation.AddRule(() => dummy.Foo, () => RuleResult.Invalid("Error")); validation.AddRule(() => dummy.Foo, RuleResult.Valid); validation.AddRule(() => dummy.Bar, RuleResult.Valid); validation.AddRule(() => RuleResult.Invalid("Error")); const int expectedTimesToFire = 0 + 1 /*Invalid Foo*/+ 1 /* Invalid general target */; var eventFiredTimes = 0; validation.ResultChanged += (o, e) => { eventFiredTimes++; }; // Act validation.ValidateAll(); // Verify Assert.Equal(expectedTimesToFire, eventFiredTimes); }
public void ValidateAllAsync_SimilteniousCalls_DoesNotFail() { TestUtils.ExecuteWithDispatcher((dispatcher, completedAction) => { const int numThreadsPerIternation = 4; const int iterationCount = 10; const int numThreads = numThreadsPerIternation * iterationCount; var resetEvent = new ManualResetEvent(false); int toProcess = numThreads; var validation = new ValidationHelper(); for (int i = 0; i < iterationCount; i++) { var target1 = new object(); var target2 = new object(); validation.AddAsyncRule(setResult => { setResult(RuleResult.Invalid("Error1")); }); validation.AddAsyncRule(target1, setResult => { setResult(RuleResult.Valid()); }); validation.AddRule(target2, () => { return RuleResult.Invalid("Error2"); }); validation.AddRule(target2, RuleResult.Valid); Action<Action> testThreadBody = exercise => { try { exercise(); if (Interlocked.Decrement(ref toProcess) == 0) resetEvent.Set(); } catch (Exception ex) { dispatcher.BeginInvoke(new Action(() => { throw new AggregateException(ex); })); } }; var thread1 = new Thread(() => { testThreadBody(() => { validation.ValidateAllAsync().Wait(); }); }); var thread2 = new Thread(() => { testThreadBody(() => { validation.ValidateAllAsync().Wait(); }); }); var thread3 = new Thread(() => { testThreadBody(() => { validation.Validate(target2); }); }); var thread4 = new Thread(() => { testThreadBody(() => { validation.Validate(target2); }); }); thread1.Start(); thread2.Start(); thread3.Start(); thread4.Start(); } ThreadPool.QueueUserWorkItem(_ => { resetEvent.WaitOne(); completedAction(); }); }); }
public void ResultChanged_CorrectingValidationError_EventIsFiredForWithValidResultAfterCorrection() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); var fooResult = RuleResult.Valid(); // ReSharper disable AccessToModifiedClosure // Intended validation.AddRule(() => dummy.Foo, () => fooResult); // ReSharper restore AccessToModifiedClosure var onResultChanged = new Action<ValidationResultChangedEventArgs>(r => { }); // ReSharper disable AccessToModifiedClosure // Intended validation.ResultChanged += (o, e) => onResultChanged(e); // ReSharper restore AccessToModifiedClosure // ACT & VERIFY // First, verify that the event is fired with invalid result fooResult = RuleResult.Invalid("Error"); onResultChanged = r => { Assert.False(r.NewResult.IsValid, "ResultChanged must be fired with invalid result first."); }; validation.ValidateAll(); // Second, verify that after second validation when error was corrected, the event fires with the valid result fooResult = RuleResult.Valid(); onResultChanged = r => { Assert.True(r.NewResult.IsValid, "ResultChanged must be fired with valid result after succesfull validation."); }; validation.ValidateAll(); }
public void Reset_ResultChangedFiresForInvalidTargets() { // ARRANGE var dummy = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(RuleResult.Valid); validation.AddRule(() => dummy.Foo, () => RuleResult.Invalid("error1")); validation.AddRule(() => dummy.Bar, () => RuleResult.Invalid("error2")); validation.ValidateAll(); bool eventFiredForFoo = false; bool evernFiredForBar = false; validation.ResultChanged += (sender, args) => { if (Equals(args.Target, PropertyName.For(() => dummy.Foo))) { eventFiredForFoo = true; } else if (Equals(args.Target, PropertyName.For(() => dummy.Bar))) { evernFiredForBar = true; } else { Assert.False(true, "ResultChanged event fired for an unexpected target."); } Assert.True(args.NewResult.IsValid); }; // ACT validation.Reset(); // VERIFY Assert.True(eventFiredForFoo); Assert.True(evernFiredForBar); }
public void AsyncValidation_MixedAsyncAndNotAsyncRules_AllExecutedBeforeValidationCompleted() { TestUtils.ExecuteWithDispatcher((dispatcher, completedAction) => { var vm = new DummyViewModel(); var validation = new ValidationHelper(); bool rule1Executed = false; validation.AddAsyncRule(vm, setResultDelegate => ThreadPool.QueueUserWorkItem(_ => { rule1Executed = true; setResultDelegate(RuleResult.Valid()); })); bool rule2Executed = false; validation.AddRule(vm, () => { rule2Executed = true; return RuleResult.Valid(); }); bool rule3Executed = false; validation.AddAsyncRule(vm, setResultDelegate => ThreadPool.QueueUserWorkItem(_ => { rule3Executed = true; setResultDelegate(RuleResult.Valid()); })); validation.ValidateAllAsync().ContinueWith(r => { Assert.True(rule1Executed); Assert.True(rule2Executed); Assert.True(rule3Executed); Assert.True(r.Result.IsValid); completedAction(); }); }); }
public void Validate_ThereAreAsyncRules_ThrowsException() { // ARRANGE var validation = new ValidationHelper(); // Add a simple sync rule validation.AddRule(RuleResult.Valid); // Add an async rule validation.AddAsyncRule(onCompleted => onCompleted(RuleResult.Invalid("Error"))); // ACT Assert.Throws<InvalidOperationException>(() => { validation.ValidateAll(); }); }
public void ValidationCompleted_ValidateRuleWithMultipleTargets_ResultContainsErrorsForAllTargsts() { // Arrange var validation = new ValidationHelper(); var dummy = new DummyViewModel(); validation.AddRule(() => dummy.Foo, () => dummy.Bar, () => { return RuleResult.Invalid("Error"); }); // Act var result = validation.ValidateAll(); // Assert Assert.False(result.IsValid); Assert.True(result.ErrorList.Count == 2, "There must be two errors: one for each property target"); Assert.True(Equals(result.ErrorList[0].Target, "dummy.Foo"), "Target for the first error must be dummy.Foo"); Assert.True(Equals(result.ErrorList[1].Target, "dummy.Bar"), "Target for the second error must be dummy.Bar"); }
public void Validate_MultipleRulesForSameTarget_ClearsResultsBeforeValidation() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); RuleResult firstRuleResult = RuleResult.Valid(); RuleResult secondRuleResult = RuleResult.Invalid("Error2"); validation.AddRule(() => dummy.Foo, () => { return firstRuleResult; }); validation.AddRule(() => dummy.Foo, () => { return secondRuleResult; }); // ACT validation.ValidateAll(); firstRuleResult = RuleResult.Invalid("Error1"); validation.ValidateAll(); // VERIFY var result = validation.GetResult(() => dummy.Foo); Assert.False(result.IsValid); Assert.Equal(1, result.ErrorList.Count); Assert.Equal("Error1", result.ErrorList[0].ErrorText); }
public void Validate_MultipleRulesForSameTarget_DoesNotExecuteRulesIfPerviousFailed() { // ARRANGE var validation = new ValidationHelper(); var dummy = new DummyViewModel(); bool firstRuleExecuted = false; bool secondRuleExecuted = false; validation.AddRule(() => dummy.Foo, () => { firstRuleExecuted = true; return RuleResult.Invalid("Error1"); }); validation.AddRule(() => dummy.Foo, () => { secondRuleExecuted = true; return RuleResult.Invalid("Error2"); }); // ACT validation.ValidateAll(); // VERIFY Assert.True(firstRuleExecuted, "First rule must have been executed"); Assert.False(secondRuleExecuted, "Second rule should not have been executed because first rule failed."); }
public void RemoveRule_ThereAreTwoFailedRules_RemoveOne_ResultChangedShouldBeFiredWithNewResultStillInvalid() { // ARRANGE var dummy = new DummyViewModel(); var validation = new ValidationHelper(); validation.AddRule(() => dummy.Foo, () => RuleResult.Invalid("error2")); var invalidRule = validation.AddRule(() => dummy.Foo, () => RuleResult.Invalid("error")); var validationResult = validation.ValidateAll(); Assert.False(validationResult.IsValid); bool resultChangedEventFired = false; validation.ResultChanged += (sender, args) => { Assert.Equal(PropertyName.For(() => dummy.Foo), args.Target); Assert.False(args.NewResult.IsValid); resultChangedEventFired = true; }; // ACT validation.RemoveRule(invalidRule); // VERIFY Assert.True(resultChangedEventFired); }
private void SetupValidation() { var validationRules = new ValidationHelper(); // Simple properties validationRules.AddRule(() => StringProperty, () => { return RuleResult.Assert(!string.IsNullOrEmpty(StringProperty), "StringProperty cannot be null or empty string"); }); validationRules.AddRule(() => IntProperty, () => { return RuleResult.Assert(IntProperty > 0, "IntProperty should be greater than zero."); }); // Dependant properties validationRules.AddRule(() => RangeStart, () => RangeEnd, () => { return RuleResult.Assert(RangeEnd > RangeStart, "RangeEnd must be grater than RangeStart"); }); // Long-running validation (simulates call to a web service or something) validationRules.AddRule( () => StringProperty2, () => { if (SyncValidationRuleExecutedAsyncroniouslyDelegate != null) { SyncValidationRuleExecutedAsyncroniouslyDelegate(); } return RuleResult.Assert(!string.IsNullOrEmpty(StringProperty2), "StringProperty2 cannot be null or empty string"); }); Validation = validationRules; DataErrorInfoValidationAdapter = new NotifyDataErrorInfoAdapter(Validation); }
public void SyncValidation_RuleThrowsException_ExceptionIsPropogated() { // ARRANGE var validator = new ValidationHelper(); validator.AddRule(() => { throw new InvalidOperationException("Test"); }); // ACT & VERIFY Assert.Throws<ValidationException>(validator.ValidateAllAsync()); }