diff --git a/Changelog.txt b/Changelog.txt index 42fbe2a5a..51b89d251 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,5 +1,7 @@ -7.6.105 - +7.6.105 - 11 August 2018 Added Albanian language translations +Added Chinese Traditional language translation +Fix #858 ValidationTestExtension.When() incorrectly checks each failure instead of all failures 7.6.104 - 6 July 2018 Added AbstractValidator.PreValidate to allow immediate cancellation of validation. diff --git a/build.ps1 b/build.ps1 index ac6af9433..d5a3c53da 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,5 +1,5 @@ param( - [string]$version = '7.6.104', + [string]$version = '7.6.105', [string]$configuration = 'Release', [string]$path = $PSScriptRoot ) diff --git a/src/FluentValidation.Tests/ValidatorTesterTester.cs b/src/FluentValidation.Tests/ValidatorTesterTester.cs index 1b6fc1be1..3dccb54e6 100644 --- a/src/FluentValidation.Tests/ValidatorTesterTester.cs +++ b/src/FluentValidation.Tests/ValidatorTesterTester.cs @@ -370,6 +370,20 @@ public void ShouldHaveChildValidator_should_work_with_DependentRules() { validator.ShouldHaveChildValidator(x => x.Children, typeof(InlineValidator)); } + [Fact] + public void Allows_only_one_failure_to_match() { + var validator = new InlineValidator { + v => v.RuleFor(x => x.Surname).Equal("a").WithErrorCode("nota"), + v => v.RuleFor(x => x.Surname).Equal("b").WithErrorCode("notb") + }; + + var person = new Person() { Surname = "c" }; + var result = validator.TestValidate(person); + + result.ShouldHaveError().WithErrorCode("nota"); + result.ShouldHaveError().WithErrorCode("notb"); + } + private class AddressValidator : AbstractValidator
{ } diff --git a/src/FluentValidation/Resources/LanguageManager.cs b/src/FluentValidation/Resources/LanguageManager.cs index d88bcd0aa..421b8bb19 100644 --- a/src/FluentValidation/Resources/LanguageManager.cs +++ b/src/FluentValidation/Resources/LanguageManager.cs @@ -35,6 +35,7 @@ public LanguageManager() { var languages = new Language[] { new EnglishLanguage(), new ChineseSimplifiedLanguage(), + new ChineseTraditionalLanguage(), new CroatianLanguage(), new CzechLanguage(), new DanishLanguage(), diff --git a/src/FluentValidation/Resources/Languages/ChineseTraditionalLanguage.cs b/src/FluentValidation/Resources/Languages/ChineseTraditionalLanguage.cs new file mode 100644 index 000000000..a25dedae1 --- /dev/null +++ b/src/FluentValidation/Resources/Languages/ChineseTraditionalLanguage.cs @@ -0,0 +1,51 @@ +#region License +// Copyright (c) Jeremy Skinner (http://www.jeremyskinner.co.uk) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The latest version of this file can be found at https://github.com/JeremySkinner/FluentValidation +#endregion + +namespace FluentValidation.Resources { + using Validators; + + internal class ChineseTraditionalLanguage : Language { + public override string Name => "zh-TW"; + + public ChineseTraditionalLanguage() { + Translate("'{PropertyName}' 不是有效的電子郵件地址。"); + Translate("'{PropertyName}' 必須大於或等於 '{ComparisonValue}'。"); + Translate("'{PropertyName}' 必須大於 '{ComparisonValue}'。"); + Translate("'{PropertyName}' 的長度必須在 {MinLength} 到 {MaxLength} 字符,您輸入了 {TotalLength} 字符。"); + Translate("'{PropertyName}' 必須大於或等於{MinLength}個字符。您輸入了{TotalLength}個字符。"); + Translate("'{PropertyName}' 必須小於或等於{MaxLength}個字符。您輸入了{TotalLength}個字符。"); + Translate("'{PropertyName}' 必須小於或等於 '{ComparisonValue}'。"); + Translate("'{PropertyName}' 必須小於 '{ComparisonValue}'。"); + Translate("'{PropertyName}' 不能為空。"); + Translate("'{PropertyName}' 不能和 '{ComparisonValue}' 相等。"); + Translate("'{PropertyName}' 不能為Null。"); + Translate("'{PropertyName}' 不符合指定的條件。"); + Translate("'{PropertyName}' 不符合指定的條件。"); + Translate("'{PropertyName}' 的格式不正確。"); + Translate("'{PropertyName}' 應該和 '{ComparisonValue}' 相等。"); + Translate("'{PropertyName}' 必須是 {MaxLength} 個字符,您輸入了 {TotalLength} 字符。"); + Translate("'{PropertyName}' 必須在 {From} (包含)和 {To} (包含)之間, 您輸入了 {Value}。"); + Translate("'{PropertyName}' 必須在 {From} (不包含)和 {To} (不包含)之間, 您輸入了 {Value}。"); + Translate("'{PropertyName}' 不是有效的信用卡號碼。"); + Translate("'{PropertyName}' 總位數不能超過 {expectedPrecision} 位,其中小數部份 {expectedScale} 位。您共計輸入了 {digits} 位數字,其中小數部份{actualScale} 位。"); + Translate("'{PropertyName}' 必須為空。"); + Translate("'{PropertyName}' 必須為Null。"); + Translate("'{PropertyName}' 的數值範圍不包含 '{PropertyValue}'。"); + } + } +} diff --git a/src/FluentValidation/TestHelper/ValidatorTestExtensions.cs b/src/FluentValidation/TestHelper/ValidatorTestExtensions.cs index 82454b3e0..6d64c0809 100644 --- a/src/FluentValidation/TestHelper/ValidatorTestExtensions.cs +++ b/src/FluentValidation/TestHelper/ValidatorTestExtensions.cs @@ -121,20 +121,22 @@ public static void ShouldNotHaveError(this TestValidationResult When(this IEnumerable failures, Func failurePredicate, string exceptionMessage = null) { - foreach (var failure in failures) { - if (!failurePredicate(failure)) { - string message = "Expected validation error was not found"; + bool anyMatched = failures.Any(failurePredicate); - if (exceptionMessage != null) { - message = exceptionMessage.Replace("{Code}", failure.ErrorCode) - .Replace("{Message}", failure.ErrorMessage) - .Replace("{State}", failure.CustomState?.ToString() ?? ""); - } + if (!anyMatched) { + var failure = failures.First(); + + string message = "Expected validation error was not found"; - throw new ValidationTestException(message); + if (exceptionMessage != null) { + message = exceptionMessage.Replace("{Code}", failure.ErrorCode) + .Replace("{Message}", failure.ErrorMessage) + .Replace("{State}", failure.CustomState?.ToString() ?? ""); } - } + throw new ValidationTestException(message); + } + return failures; }