From 191bf4f3f3f122dd10fcc7242637b5ced6f9b583 Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Thu, 9 May 2024 18:58:54 +1000 Subject: [PATCH 01/11] Update tests --- .../StringAssertionSpecs.BeLowerCased.cs | 64 ++++++++++++++---- .../StringAssertionSpecs.BeUpperCased.cs | 65 +++++++++++++++---- 2 files changed, 103 insertions(+), 26 deletions(-) diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs index 016b67fc82..a795570cf6 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs @@ -32,7 +32,7 @@ public void When_an_empty_string_is_supposed_to_be_lower_it_should_succeed() } [Fact] - public void When_a_non_lower_string_is_supposed_to_be_lower_it_should_fail() + public void When_an_upper_case_string_is_supposed_to_be_lower_it_should_fail() { // Arrange string actual = "ABC"; @@ -45,10 +45,10 @@ public void When_a_non_lower_string_is_supposed_to_be_lower_it_should_fail() } [Fact] - public void When_a_lower_case_string_with_numbers_is_supposed_to_be_in_lower_case_only_it_should_throw() + public void When_a_mixed_case_string_is_supposed_to_be_lower_it_should_fail() { // Arrange - string actual = "a1"; + string actual = "AbC"; // Act Action act = () => actual.Should().BeLowerCased(); @@ -57,6 +57,26 @@ public void When_a_lower_case_string_with_numbers_is_supposed_to_be_in_lower_cas act.Should().Throw(); } + [Fact] + public void When_a_lower_case_string_with_non_alpha_chars_is_supposed_to_be_lower_it_should_succeed() + { + // Arrange + string actual = "a1!"; + + // Act / Assert + actual.Should().BeLowerCased(); + } + + [Fact] + public void When_a_string_with_caseless_chars_is_supposed_to_be_lower_it_should_succeed() + { + // Arrange + string actual = "1!漢字"; + + // Act / Assert + actual.Should().BeLowerCased(); + } + [Fact] public void When_a_non_lower_string_is_supposed_to_be_lower_it_should_fail_with_descriptive_message() { @@ -68,7 +88,7 @@ public void When_a_non_lower_string_is_supposed_to_be_lower_it_should_fail_with_ // Assert act.Should().Throw().WithMessage( - "Expected all characters in actual to be lower cased because we want to test the failure message, but found \"ABC\"."); + "Expected all alpha characters in actual to be lower cased because we want to test the failure message, but found \"ABC\"."); } [Fact] @@ -82,24 +102,24 @@ public void When_checking_for_a_lower_string_and_it_is_null_it_should_throw() // Assert act.Should().Throw().WithMessage( - "Expected all characters in nullString to be lower cased because strings should never be null, but found ."); + "Expected all alpha characters in nullString to be lower cased because strings should never be null, but found ."); } } public class NotBeLowerCased { [Fact] - public void When_a_non_lower_string_is_supposed_to_be_upper_it_should_succeed() + public void When_a_mixed_case_string_is_not_supposed_to_be_lowered_it_should_succeed() { // Arrange - string actual = "ABC"; + string actual = "AbC"; // Act / Assert actual.Should().NotBeLowerCased(); } [Fact] - public void When_a_null_string_is_not_supposed_to_be_lower_it_should_succeed() + public void When_a_null_string_is_not_supposed_to_be_lowered_it_should_succeed() { // Arrange string actual = null; @@ -109,7 +129,7 @@ public void When_a_null_string_is_not_supposed_to_be_lower_it_should_succeed() } [Fact] - public void When_a_lower_string_is_supposed_to_be_upper_it_should_throw() + public void When_a_lower_string_is_not_supposed_to_be_lowered_it_should_throw() { // Arrange string actual = "abc"; @@ -122,10 +142,30 @@ public void When_a_lower_string_is_supposed_to_be_upper_it_should_throw() } [Fact] - public void When_a_lower_case_string_with_numbers_is_not_supposed_to_be_in_lower_case_only_it_should_succeed() + public void When_a_string_containing_upper_chars_is_not_supposed_to_be_lowered_it_should_succeed() + { + // Arrange + string actual = "Ab1!"; + + // Act / Assert + actual.Should().NotBeLowerCased(); + } + + [Fact] + public void When_a_string_in_which_all_alpha_chars_are_lower_is_not_supposed_to_be_lowered_only_it_should_throw() + { + // Arrange + string actual = "a1b!"; + + // Act / Assert + actual.Should().NotBeLowerCased(); + } + + [Fact] + public void When_a_string_with_caseless_chars_is_not_supposed_to_be_lowered_it_should_succeed() { // Arrange - string actual = "A1"; + string actual = "1!漢字"; // Act / Assert actual.Should().NotBeLowerCased(); @@ -142,7 +182,7 @@ public void When_a_lower_string_is_not_supposed_to_be_lower_it_should_fail_with_ // Assert act.Should().Throw().WithMessage( - "Did not expect any characters in actual to be lower cased because we want to test the failure message."); + "Expected some charatcers in actual to be upper-case because we want to test the failure message."); } } } diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs index 3502f1728f..dd6fb509c4 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs @@ -22,7 +22,17 @@ public void When_an_upper_case_string_is_supposed_to_be_in_upper_case_only_it_sh } [Fact] - public void When_a_non_upper_string_is_supposed_to_be_upper_it_should_throw() + public void When_an_empty_string_is_supposed_to_be_upper_it_should_succeed() + { + // Arrange + string actual = ""; + + // Act / Assert + actual.Should().BeUpperCased(); + } + + [Fact] + public void When_a_lower_case_string_is_supposed_to_be_upper_it_should_throw() { // Arrange string actual = "abc"; @@ -35,16 +45,23 @@ public void When_a_non_upper_string_is_supposed_to_be_upper_it_should_throw() } [Fact] - public void When_an_upper_case_string_with_numbers_is_supposed_to_be_in_upper_case_only_it_should_throw() + public void When_an_upper_case_string_with_non_alplha_chars_is_supposed_to_be_in_upper_case_only_it_should_succeed() { // Arrange - string actual = "A1"; + string actual = "A1!"; - // Act - Action act = () => actual.Should().BeUpperCased(); + // Act / Assert + actual.Should().BeUpperCased(); + } - // Assert - act.Should().Throw(); + [Fact] + public void When_a_string_with_caseless_chars_is_supposed_to_be_upper_it_should_succeed() + { + // Arrange + string actual = "1!漢字"; + + // Act / Assert + actual.Should().BeUpperCased(); } [Fact] @@ -58,7 +75,7 @@ public void When_a_non_upper_string_is_supposed_to_be_upper_it_should_fail_with_ // Assert act.Should().Throw().WithMessage( - @"Expected all characters in actual to be upper cased because we want to test the failure message, but found ""abc""."); + @"Expected all alpha characters in actual to be upper-case because we want to test the failure message, but found ""abc""."); } [Fact] @@ -72,17 +89,17 @@ public void When_checking_for_an_upper_string_and_it_is_null_it_should_throw() // Assert act.Should().Throw().WithMessage( - "Expected all characters in nullString to be upper cased because strings should never be null, but found ."); + "Expected all alpha characters in nullString to be upper-case because strings should never be null, but found ."); } } public class NotBeUpperCased { [Fact] - public void When_a_non_upper_string_is_supposed_to_be_non_upper_it_should_succeed() + public void When_a_mixed_case_string_is_not_supposed_to_be_uppered_it_should_succeed() { // Arrange - string actual = "abc"; + string actual = "aBc"; // Act / Assert actual.Should().NotBeUpperCased(); @@ -112,10 +129,30 @@ public void When_an_upper_string_is_not_supposed_to_be_upper_it_should_throw() } [Fact] - public void When_an_upper_case_string_with_numbers_is_not_supposed_to_be_in_upper_case_only_it_should_succeed() + public void When_a_string_containing_lower_chars_is_not_supposed_to_be_uppered_it_should_succeed() + { + // Arrange + string actual = "Ab1!"; + + // Act / Assert + actual.Should().NotBeUpperCased(); + } + + [Fact] + public void When_a_string_in_which_all_alpha_chars_are_upper_is_not_supposed_to_be_uppered_only_it_should_throw() + { + // Arrange + string actual = "a1b!"; + + // Act / Assert + actual.Should().NotBeUpperCased(); + } + + [Fact] + public void When_a_string_with_caseless_chars_is_not_supposed_to_be_uppered_it_should_succeed() { // Arrange - string actual = "a1"; + string actual = "1!漢字"; // Act / Assert actual.Should().NotBeUpperCased(); @@ -132,7 +169,7 @@ public void When_an_upper_string_is_not_supposed_to_be_upper_it_should_fail_with // Assert act.Should().Throw().WithMessage( - "Did not expect any characters in actual to be upper cased because we want to test the failure message."); + "Expected some characters in actual to be lower-case because we want to test the failure message."); } } } From e7350a8690d31b70ac693a61d822edd74370c17a Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Fri, 24 May 2024 09:09:48 +1000 Subject: [PATCH 02/11] Update implementation --- .../Primitives/StringAssertions.cs | 35 ++++++++++++++----- .../StringAssertionSpecs.BeLowerCased.cs | 23 +++++++++--- .../StringAssertionSpecs.BeUpperCased.cs | 21 ++++++++--- 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/Src/FluentAssertions/Primitives/StringAssertions.cs b/Src/FluentAssertions/Primitives/StringAssertions.cs index ff968ea59d..7a31a985c9 100644 --- a/Src/FluentAssertions/Primitives/StringAssertions.cs +++ b/Src/FluentAssertions/Primitives/StringAssertions.cs @@ -1884,9 +1884,9 @@ public AndConstraint BeNullOrWhiteSpace(string because = "", params public AndConstraint BeUpperCased(string because = "", params object[] becauseArgs) { Execute.Assertion - .ForCondition(Subject?.All(char.IsUpper) == true) + .ForCondition(Subject is not null && !Subject.Any(char.IsLower)) .BecauseOf(because, becauseArgs) - .FailWith("Expected all characters in {context:string} to be upper cased{reason}, but found {0}.", Subject); + .FailWith("Expected all alpha characters in {context:string} to be upper-case{reason}, but found {0}.", Subject); return new AndConstraint((TAssertions)this); } @@ -1904,9 +1904,9 @@ public AndConstraint BeUpperCased(string because = "", params objec public AndConstraint NotBeUpperCased(string because = "", params object[] becauseArgs) { Execute.Assertion - .ForCondition(Subject is null || Subject.Any(ch => !char.IsUpper(ch))) + .ForCondition(Subject is null || HasMixedOrNoCase(Subject)) .BecauseOf(because, becauseArgs) - .FailWith("Did not expect any characters in {context:string} to be upper cased{reason}."); + .FailWith("Expected some characters in {context:string} to be lower-case{reason}."); return new AndConstraint((TAssertions)this); } @@ -1929,9 +1929,9 @@ public AndConstraint NotBeUpperCased(string because = "", params ob public AndConstraint BeLowerCased(string because = "", params object[] becauseArgs) { Execute.Assertion - .ForCondition(Subject?.All(char.IsLower) == true) + .ForCondition(Subject is not null && !Subject.Any(char.IsUpper)) .BecauseOf(because, becauseArgs) - .FailWith("Expected all characters in {context:string} to be lower cased{reason}, but found {0}.", Subject); + .FailWith("Expected all alpha characters in {context:string} to be lower cased{reason}, but found {0}.", Subject); return new AndConstraint((TAssertions)this); } @@ -1949,13 +1949,32 @@ public AndConstraint BeLowerCased(string because = "", params objec public AndConstraint NotBeLowerCased(string because = "", params object[] becauseArgs) { Execute.Assertion - .ForCondition(Subject is null || Subject.Any(ch => !char.IsLower(ch))) + .ForCondition(Subject is null || HasMixedOrNoCase(Subject)) .BecauseOf(because, becauseArgs) - .FailWith("Did not expect any characters in {context:string} to be lower cased{reason}."); + .FailWith("Expected some characters in {context:string} to be upper-case{reason}."); return new AndConstraint((TAssertions)this); } + private static bool HasMixedOrNoCase(string value) + { + var hasUpperCase = false; + var hasLowerCase = false; + + foreach (var ch in value) + { + hasUpperCase |= char.IsUpper(ch); + hasLowerCase |= char.IsLower(ch); + + if (hasUpperCase && hasLowerCase) + { + return true; + } + } + + return !hasUpperCase && !hasLowerCase; + } + internal AndConstraint Be(string expected, Func, EquivalencyOptions> config, string because = "", params object[] becauseArgs) diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs index a795570cf6..85788afabd 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs @@ -128,6 +128,16 @@ public void When_a_null_string_is_not_supposed_to_be_lowered_it_should_succeed() actual.Should().NotBeLowerCased(); } + [Fact] + public void When_an_empty_string_is_not_supposed_to_be_lowered_it_should_succeed() + { + // Arrange + string actual = ""; + + // Act / Assert + actual.Should().NotBeLowerCased(); + } + [Fact] public void When_a_lower_string_is_not_supposed_to_be_lowered_it_should_throw() { @@ -152,17 +162,20 @@ public void When_a_string_containing_upper_chars_is_not_supposed_to_be_lowered_i } [Fact] - public void When_a_string_in_which_all_alpha_chars_are_lower_is_not_supposed_to_be_lowered_only_it_should_throw() + public void When_a_string_in_which_all_alpha_chars_are_lower_is_not_supposed_to_be_lowered_it_should_throw() { // Arrange string actual = "a1b!"; - // Act / Assert - actual.Should().NotBeLowerCased(); + // Act + Action act = () => actual.Should().NotBeLowerCased(); + + // Assert + act.Should().Throw(); } [Fact] - public void When_a_string_with_caseless_chars_is_not_supposed_to_be_lowered_it_should_succeed() + public void When_a_string_with_only_caseless_chars_is_not_supposed_to_be_lowered_it_should_succeed() { // Arrange string actual = "1!漢字"; @@ -182,7 +195,7 @@ public void When_a_lower_string_is_not_supposed_to_be_lower_it_should_fail_with_ // Assert act.Should().Throw().WithMessage( - "Expected some charatcers in actual to be upper-case because we want to test the failure message."); + "Expected some characters in actual to be upper-case because we want to test the failure message."); } } } diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs index dd6fb509c4..db77688afb 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs @@ -115,6 +115,16 @@ public void When_a_null_string_is_not_supposed_to_be_upper_it_should_succeed() actual.Should().NotBeUpperCased(); } + [Fact] + public void When_an_empty_string_is_not_supposed_to_be_upper_it_should_succeed() + { + // Arrange + string actual = ""; + + // Act / Assert + actual.Should().NotBeUpperCased(); + } + [Fact] public void When_an_upper_string_is_not_supposed_to_be_upper_it_should_throw() { @@ -142,14 +152,17 @@ public void When_a_string_containing_lower_chars_is_not_supposed_to_be_uppered_i public void When_a_string_in_which_all_alpha_chars_are_upper_is_not_supposed_to_be_uppered_only_it_should_throw() { // Arrange - string actual = "a1b!"; + string actual = "A1B!"; - // Act / Assert - actual.Should().NotBeUpperCased(); + // Act + Action act = () => actual.Should().NotBeUpperCased(); + + // Assert + act.Should().Throw(); } [Fact] - public void When_a_string_with_caseless_chars_is_not_supposed_to_be_uppered_it_should_succeed() + public void When_a_string_with_only_caseless_chars_is_not_supposed_to_be_uppered_it_should_succeed() { // Arrange string actual = "1!漢字"; From f099e767c387dcd07d7c53b733a45d19f55f566b Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Fri, 24 May 2024 09:21:20 +1000 Subject: [PATCH 03/11] Update XML Docs --- .../Primitives/StringAssertions.cs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Src/FluentAssertions/Primitives/StringAssertions.cs b/Src/FluentAssertions/Primitives/StringAssertions.cs index 7a31a985c9..1ec7859700 100644 --- a/Src/FluentAssertions/Primitives/StringAssertions.cs +++ b/Src/FluentAssertions/Primitives/StringAssertions.cs @@ -1867,12 +1867,12 @@ public AndConstraint BeNullOrWhiteSpace(string because = "", params } /// - /// Asserts that all characters in a string are in upper casing. + /// Asserts that all cased characters in a string are upper-case. That is, that the string could be the result of a call to + /// . /// /// - /// Be careful that numbers and special characters don't have casing, so - /// will always fail on a string that contains anything but alphabetic characters. - /// In those cases, we recommend using . + /// Numbers, special characters, and many Asian character don't have casing, so + /// will ignore these and will fail only in the presence of lower-case characters. /// /// /// A formatted phrase as is supported by explaining why the assertion @@ -1892,7 +1892,8 @@ public AndConstraint BeUpperCased(string because = "", params objec } /// - /// Asserts that all characters in a string are not in upper casing. + /// Asserts that all of the cased characters in a string some are not upper-case. That is, the string could not be the result + /// of a call to . /// /// /// A formatted phrase as is supported by explaining why the assertion @@ -1912,12 +1913,12 @@ public AndConstraint NotBeUpperCased(string because = "", params ob } /// - /// Asserts that all characters in a string are in lower casing. + /// Asserts that all cased characters in a string are lower-case. That is, that the string could be the result of a call to + /// , /// /// - /// Be careful that numbers and special characters don't have casing, so will always fail on - /// a string that contains anything but alphabetic characters. - /// In those cases, we recommend using . + /// Numbers, special characters, and many Asian character don't have casing, so + /// will ignore these and will fail only in the presence of upper-case characters. /// /// /// A formatted phrase as is supported by explaining why the assertion @@ -1937,7 +1938,8 @@ public AndConstraint BeLowerCased(string because = "", params objec } /// - /// Asserts that all characters in a string are not in lower casing. + /// Asserts that all of the cased characters in a string some are not lower-case. That is, the string could not be the result + /// of a call to . /// /// /// A formatted phrase as is supported by explaining why the assertion From 0ef471c1e2acf0b22caa6f4c3741102a3c2afe9e Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Thu, 30 May 2024 21:50:55 +1000 Subject: [PATCH 04/11] Update release notes --- docs/_pages/releases.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/_pages/releases.md b/docs/_pages/releases.md index d0865a2c50..fa7ad93525 100644 --- a/docs/_pages/releases.md +++ b/docs/_pages/releases.md @@ -74,6 +74,7 @@ sidebar: * `IEquivalencyAssertionOptions` to `IEquivalencyOptions` * `SelfReferenceEquivalencyAssertionOptions` to `SelfReferenceEquivalencyOptions` * Allow fluently calling `WithoutMatchingRules` and `WithoutSelectionRules` while using `BeEquivalentTo` - [#2457](https://github.com/fluentassertions/fluentassertions/pull/2457) +* The semantics of `BeLowerCased`/`BeUpperCased` have been changed to align with the behaviour of `ToLower`/`ToUpper` - [#2660](https://github.com/fluentassertions/fluentassertions/pull/2660) ### Breaking Changes (for extensions) * Add `ForConstraint` to `IAssertionsScope` to support chaining `.ForConstraint()` after `.Then` - [#2324](https://github.com/fluentassertions/fluentassertions/pull/2324) From 289f32794744fa35605da9fcca1d93a54b1d6bda Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Thu, 30 May 2024 22:12:33 +1000 Subject: [PATCH 05/11] Update documentation --- docs/_pages/strings.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/_pages/strings.md b/docs/_pages/strings.md index 98b981e848..040d8c89c3 100644 --- a/docs/_pages/strings.md +++ b/docs/_pages/strings.md @@ -20,7 +20,7 @@ theString.Should().BeNullOrWhiteSpace(); // either null, empty or whitespace onl theString.Should().NotBeNullOrWhiteSpace(); ``` -To ensure the characters in a string are all (not) upper or lower cased, you can use the following assertions. +To ensure that the characters with case in a string are all (not) upper or lower cased, you can use the following assertions. ```csharp theString.Should().BeUpperCased(); @@ -29,9 +29,20 @@ theString.Should().BeLowerCased(); theString.Should().NotBeLowerCased(); ``` -However, be careful that numbers and special characters don't have casing, so `BeUpperCased` and `BeLowerCased` will always fail on a string that contains anything but alphabetic characters. In those cases, we recommend using `NotBeUpperCased` or `NotBeLowerCased`. +Note that numbers, special characters, and some alphabets don't have casing, so `BeUpperCased` and `BeLowerCased` will +ignore these characters. In other words, `BeUpperCased` will succeed if the string is a possible output of +`ToUpperInvariant`, and likewise for `BeLowerCased`. `NotBeUpperCased` will fail only if the string contains characters +with case, and all those characters are upper-case, and likewise for `NotBeLowerCased`. -Obviously you’ll find all the methods you would expect for string assertions. +The semantics of these assertions changed in FluentAssertions v7.0. For the previous semantics, asserting that all +characters in the string are upper-case characters, for example, you can use a collection assertion on the characters of +the string: + +```csharp +theString.Should().OnlyContain(c => char.IsUpper(c)); +``` + +Obviously you'll find all the methods you would expect for string assertions. ```csharp theString = "This is a String"; From 171d90304c354630d1e7ecc6eca418b6e869e8ea Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Thu, 30 May 2024 22:16:13 +1000 Subject: [PATCH 06/11] Fix spelling error --- docs/_pages/releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_pages/releases.md b/docs/_pages/releases.md index fa7ad93525..bfe33c19d3 100644 --- a/docs/_pages/releases.md +++ b/docs/_pages/releases.md @@ -74,7 +74,7 @@ sidebar: * `IEquivalencyAssertionOptions` to `IEquivalencyOptions` * `SelfReferenceEquivalencyAssertionOptions` to `SelfReferenceEquivalencyOptions` * Allow fluently calling `WithoutMatchingRules` and `WithoutSelectionRules` while using `BeEquivalentTo` - [#2457](https://github.com/fluentassertions/fluentassertions/pull/2457) -* The semantics of `BeLowerCased`/`BeUpperCased` have been changed to align with the behaviour of `ToLower`/`ToUpper` - [#2660](https://github.com/fluentassertions/fluentassertions/pull/2660) +* The semantics of `BeLowerCased`/`BeUpperCased` have been changed to align with the behavior of `ToLower`/`ToUpper` - [#2660](https://github.com/fluentassertions/fluentassertions/pull/2660) ### Breaking Changes (for extensions) * Add `ForConstraint` to `IAssertionsScope` to support chaining `.ForConstraint()` after `.Then` - [#2324](https://github.com/fluentassertions/fluentassertions/pull/2324) From bf25b359d7629ca510e5ec1d7179eed33f47408c Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Sat, 1 Jun 2024 10:52:09 +1000 Subject: [PATCH 07/11] Improve suggestion in docs for old semantics --- docs/_pages/strings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_pages/strings.md b/docs/_pages/strings.md index 040d8c89c3..d654d53d27 100644 --- a/docs/_pages/strings.md +++ b/docs/_pages/strings.md @@ -39,7 +39,7 @@ characters in the string are upper-case characters, for example, you can use a c the string: ```csharp -theString.Should().OnlyContain(c => char.IsUpper(c)); +theString.Should().OnlyContain(char.IsUpper); ``` Obviously you'll find all the methods you would expect for string assertions. From 3068ea5faf68fb369269b8343d08586f801833ae Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Sun, 2 Jun 2024 20:27:54 +1000 Subject: [PATCH 08/11] Address review comments --- .../Primitives/StringAssertions.cs | 20 ++++++++---- .../StringAssertionSpecs.BeLowerCased.cs | 32 +++++++++---------- .../StringAssertionSpecs.BeUpperCased.cs | 30 ++++++++--------- docs/_pages/strings.md | 2 +- 4 files changed, 46 insertions(+), 38 deletions(-) diff --git a/Src/FluentAssertions/Primitives/StringAssertions.cs b/Src/FluentAssertions/Primitives/StringAssertions.cs index 1ec7859700..9dfe4c5b7d 100644 --- a/Src/FluentAssertions/Primitives/StringAssertions.cs +++ b/Src/FluentAssertions/Primitives/StringAssertions.cs @@ -1886,15 +1886,19 @@ public AndConstraint BeUpperCased(string because = "", params objec Execute.Assertion .ForCondition(Subject is not null && !Subject.Any(char.IsLower)) .BecauseOf(because, becauseArgs) - .FailWith("Expected all alpha characters in {context:string} to be upper-case{reason}, but found {0}.", Subject); + .FailWith("Expected all alphabetic characters in {context:string} to be upper-case{reason}, but found {0}.", Subject); return new AndConstraint((TAssertions)this); } /// - /// Asserts that all of the cased characters in a string some are not upper-case. That is, the string could not be the result - /// of a call to . + /// Asserts that of all the cased characters in a string, some are not upper-case. That is, the string could not be + /// the result of a call to . /// + /// + /// Numbers, special characters, and many Asian character don't have casing, so + /// will ignore these and will fail only if the string contains cased characters and they are all upper-case. + /// /// /// A formatted phrase as is supported by explaining why the assertion /// is needed. If the phrase does not start with the word because, it is prepended automatically. @@ -1932,15 +1936,19 @@ public AndConstraint BeLowerCased(string because = "", params objec Execute.Assertion .ForCondition(Subject is not null && !Subject.Any(char.IsUpper)) .BecauseOf(because, becauseArgs) - .FailWith("Expected all alpha characters in {context:string} to be lower cased{reason}, but found {0}.", Subject); + .FailWith("Expected all alphabetic characters in {context:string} to be lower cased{reason}, but found {0}.", Subject); return new AndConstraint((TAssertions)this); } /// - /// Asserts that all of the cased characters in a string some are not lower-case. That is, the string could not be the result - /// of a call to . + /// Asserts that of all the cased characters in a string, some are not lower-case. That is, the string could not be + /// the result of a call to . /// + /// + /// Numbers, special characters, and many Asian character don't have casing, so + /// will ignore these and will fail only if the string contains cased characters and they are all lower-case. + /// /// /// A formatted phrase as is supported by explaining why the assertion /// is needed. If the phrase does not start with the word because, it is prepended automatically. diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs index 85788afabd..be9ca51088 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs @@ -12,7 +12,7 @@ public partial class StringAssertionSpecs public class BeLowerCased { [Fact] - public void When_a_lower_string_is_supposed_to_be_lower_it_should_succeed() + public void Lower_case_characters_are_okay() { // Arrange string actual = "abc"; @@ -22,7 +22,7 @@ public void When_a_lower_string_is_supposed_to_be_lower_it_should_succeed() } [Fact] - public void When_an_empty_string_is_supposed_to_be_lower_it_should_succeed() + public void The_empty_string_is_okay() { // Arrange string actual = ""; @@ -32,7 +32,7 @@ public void When_an_empty_string_is_supposed_to_be_lower_it_should_succeed() } [Fact] - public void When_an_upper_case_string_is_supposed_to_be_lower_it_should_fail() + public void Upper_case_characters_are_not_okay() { // Arrange string actual = "ABC"; @@ -45,7 +45,7 @@ public void When_an_upper_case_string_is_supposed_to_be_lower_it_should_fail() } [Fact] - public void When_a_mixed_case_string_is_supposed_to_be_lower_it_should_fail() + public void A_mixed_case_string_is_not_okay() { // Arrange string actual = "AbC"; @@ -58,7 +58,7 @@ public void When_a_mixed_case_string_is_supposed_to_be_lower_it_should_fail() } [Fact] - public void When_a_lower_case_string_with_non_alpha_chars_is_supposed_to_be_lower_it_should_succeed() + public void Lower_case_and_caseless_characters_are_okay() { // Arrange string actual = "a1!"; @@ -68,7 +68,7 @@ public void When_a_lower_case_string_with_non_alpha_chars_is_supposed_to_be_lowe } [Fact] - public void When_a_string_with_caseless_chars_is_supposed_to_be_lower_it_should_succeed() + public void Caseless_characters_are_okay() { // Arrange string actual = "1!漢字"; @@ -78,7 +78,7 @@ public void When_a_string_with_caseless_chars_is_supposed_to_be_lower_it_should_ } [Fact] - public void When_a_non_lower_string_is_supposed_to_be_lower_it_should_fail_with_descriptive_message() + public void The_assertion_fails_with_a_descriptive_message() { // Arrange string actual = "ABC"; @@ -92,7 +92,7 @@ public void When_a_non_lower_string_is_supposed_to_be_lower_it_should_fail_with_ } [Fact] - public void When_checking_for_a_lower_string_and_it_is_null_it_should_throw() + public void The_null_string_is_not_okay() { // Arrange string nullString = null; @@ -109,7 +109,7 @@ public void When_checking_for_a_lower_string_and_it_is_null_it_should_throw() public class NotBeLowerCased { [Fact] - public void When_a_mixed_case_string_is_not_supposed_to_be_lowered_it_should_succeed() + public void A_mixed_case_string_is_okay() { // Arrange string actual = "AbC"; @@ -119,7 +119,7 @@ public void When_a_mixed_case_string_is_not_supposed_to_be_lowered_it_should_suc } [Fact] - public void When_a_null_string_is_not_supposed_to_be_lowered_it_should_succeed() + public void The_null_string_is_okay() { // Arrange string actual = null; @@ -129,7 +129,7 @@ public void When_a_null_string_is_not_supposed_to_be_lowered_it_should_succeed() } [Fact] - public void When_an_empty_string_is_not_supposed_to_be_lowered_it_should_succeed() + public void The_empty_string_is_okay() { // Arrange string actual = ""; @@ -139,7 +139,7 @@ public void When_an_empty_string_is_not_supposed_to_be_lowered_it_should_succeed } [Fact] - public void When_a_lower_string_is_not_supposed_to_be_lowered_it_should_throw() + public void A_lower_case_string_is_not_okay() { // Arrange string actual = "abc"; @@ -152,7 +152,7 @@ public void When_a_lower_string_is_not_supposed_to_be_lowered_it_should_throw() } [Fact] - public void When_a_string_containing_upper_chars_is_not_supposed_to_be_lowered_it_should_succeed() + public void Lower_case_characters_with_upper_case_characters_are_okay() { // Arrange string actual = "Ab1!"; @@ -162,7 +162,7 @@ public void When_a_string_containing_upper_chars_is_not_supposed_to_be_lowered_i } [Fact] - public void When_a_string_in_which_all_alpha_chars_are_lower_is_not_supposed_to_be_lowered_it_should_throw() + public void All_cased_characters_being_lower_case_is_not_okay() { // Arrange string actual = "a1b!"; @@ -175,7 +175,7 @@ public void When_a_string_in_which_all_alpha_chars_are_lower_is_not_supposed_to_ } [Fact] - public void When_a_string_with_only_caseless_chars_is_not_supposed_to_be_lowered_it_should_succeed() + public void Caseless_characters_are_okay() { // Arrange string actual = "1!漢字"; @@ -185,7 +185,7 @@ public void When_a_string_with_only_caseless_chars_is_not_supposed_to_be_lowered } [Fact] - public void When_a_lower_string_is_not_supposed_to_be_lower_it_should_fail_with_descriptive_message() + public void The_assertion_fails_with_a_descriptive_message() { // Arrange string actual = "abc"; diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs index db77688afb..4d03026e88 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs @@ -12,7 +12,7 @@ public partial class StringAssertionSpecs public class BeUpperCased { [Fact] - public void When_an_upper_case_string_is_supposed_to_be_in_upper_case_only_it_should_not_throw() + public void Upper_case_characters_are_okay() { // Arrange string actual = "ABC"; @@ -22,7 +22,7 @@ public void When_an_upper_case_string_is_supposed_to_be_in_upper_case_only_it_sh } [Fact] - public void When_an_empty_string_is_supposed_to_be_upper_it_should_succeed() + public void The_empty_string_is_okay() { // Arrange string actual = ""; @@ -32,7 +32,7 @@ public void When_an_empty_string_is_supposed_to_be_upper_it_should_succeed() } [Fact] - public void When_a_lower_case_string_is_supposed_to_be_upper_it_should_throw() + public void A_lower_case_string_is_not_okay() { // Arrange string actual = "abc"; @@ -45,7 +45,7 @@ public void When_a_lower_case_string_is_supposed_to_be_upper_it_should_throw() } [Fact] - public void When_an_upper_case_string_with_non_alplha_chars_is_supposed_to_be_in_upper_case_only_it_should_succeed() + public void Upper_case_and_caseless_characters_are_ok() { // Arrange string actual = "A1!"; @@ -55,7 +55,7 @@ public void When_an_upper_case_string_with_non_alplha_chars_is_supposed_to_be_in } [Fact] - public void When_a_string_with_caseless_chars_is_supposed_to_be_upper_it_should_succeed() + public void Caseless_characters_are_okay() { // Arrange string actual = "1!漢字"; @@ -65,7 +65,7 @@ public void When_a_string_with_caseless_chars_is_supposed_to_be_upper_it_should_ } [Fact] - public void When_a_non_upper_string_is_supposed_to_be_upper_it_should_fail_with_descriptive_message() + public void The_assertion_fails_with_a_descriptive_message() { // Arrange string actual = "abc"; @@ -79,7 +79,7 @@ public void When_a_non_upper_string_is_supposed_to_be_upper_it_should_fail_with_ } [Fact] - public void When_checking_for_an_upper_string_and_it_is_null_it_should_throw() + public void The_null_string_is_not_okay() { // Arrange string nullString = null; @@ -96,7 +96,7 @@ public void When_checking_for_an_upper_string_and_it_is_null_it_should_throw() public class NotBeUpperCased { [Fact] - public void When_a_mixed_case_string_is_not_supposed_to_be_uppered_it_should_succeed() + public void A_mixed_case_string_is_okay() { // Arrange string actual = "aBc"; @@ -106,7 +106,7 @@ public void When_a_mixed_case_string_is_not_supposed_to_be_uppered_it_should_suc } [Fact] - public void When_a_null_string_is_not_supposed_to_be_upper_it_should_succeed() + public void The_null_string_is_okay() { // Arrange string actual = null; @@ -116,7 +116,7 @@ public void When_a_null_string_is_not_supposed_to_be_upper_it_should_succeed() } [Fact] - public void When_an_empty_string_is_not_supposed_to_be_upper_it_should_succeed() + public void The_empty_string_is_okay() { // Arrange string actual = ""; @@ -126,7 +126,7 @@ public void When_an_empty_string_is_not_supposed_to_be_upper_it_should_succeed() } [Fact] - public void When_an_upper_string_is_not_supposed_to_be_upper_it_should_throw() + public void A_string_of_all_upper_case_characters_is_not_okay() { // Arrange string actual = "ABC"; @@ -139,7 +139,7 @@ public void When_an_upper_string_is_not_supposed_to_be_upper_it_should_throw() } [Fact] - public void When_a_string_containing_lower_chars_is_not_supposed_to_be_uppered_it_should_succeed() + public void Upper_case_characters_with_lower_case_characters_are_okay() { // Arrange string actual = "Ab1!"; @@ -149,7 +149,7 @@ public void When_a_string_containing_lower_chars_is_not_supposed_to_be_uppered_i } [Fact] - public void When_a_string_in_which_all_alpha_chars_are_upper_is_not_supposed_to_be_uppered_only_it_should_throw() + public void All_cased_characters_being_upper_case_is_not_okay() { // Arrange string actual = "A1B!"; @@ -162,7 +162,7 @@ public void When_a_string_in_which_all_alpha_chars_are_upper_is_not_supposed_to_ } [Fact] - public void When_a_string_with_only_caseless_chars_is_not_supposed_to_be_uppered_it_should_succeed() + public void Caseless_characters_are_okay() { // Arrange string actual = "1!漢字"; @@ -172,7 +172,7 @@ public void When_a_string_with_only_caseless_chars_is_not_supposed_to_be_uppered } [Fact] - public void When_an_upper_string_is_not_supposed_to_be_upper_it_should_fail_with_descriptive_message() + public void The_assertion_fails_with_a_descriptive_message() { // Arrange string actual = "ABC"; diff --git a/docs/_pages/strings.md b/docs/_pages/strings.md index d654d53d27..1c3a66f1f9 100644 --- a/docs/_pages/strings.md +++ b/docs/_pages/strings.md @@ -20,7 +20,7 @@ theString.Should().BeNullOrWhiteSpace(); // either null, empty or whitespace onl theString.Should().NotBeNullOrWhiteSpace(); ``` -To ensure that the characters with case in a string are all (not) upper or lower cased, you can use the following assertions. +To ensure that the characters with case in a string are all upper or lower cased (or the opposite), you can use the following assertions. ```csharp theString.Should().BeUpperCased(); From 5569dcb443c89b5a451c6181a27a4d6806c44a34 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sat, 8 Jun 2024 22:18:35 +1000 Subject: [PATCH 09/11] Apply code review suggestions on comment grammar Co-authored-by: Jonas Nyrup --- Src/FluentAssertions/Primitives/StringAssertions.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Src/FluentAssertions/Primitives/StringAssertions.cs b/Src/FluentAssertions/Primitives/StringAssertions.cs index 9dfe4c5b7d..a70573ac3a 100644 --- a/Src/FluentAssertions/Primitives/StringAssertions.cs +++ b/Src/FluentAssertions/Primitives/StringAssertions.cs @@ -1871,7 +1871,7 @@ public AndConstraint BeNullOrWhiteSpace(string because = "", params /// . /// /// - /// Numbers, special characters, and many Asian character don't have casing, so + /// Numbers, special characters, and many Asian characters don't have casing, so /// will ignore these and will fail only in the presence of lower-case characters. /// /// @@ -1896,7 +1896,7 @@ public AndConstraint BeUpperCased(string because = "", params objec /// the result of a call to . /// /// - /// Numbers, special characters, and many Asian character don't have casing, so + /// Numbers, special characters, and many Asian characters don't have casing, so /// will ignore these and will fail only if the string contains cased characters and they are all upper-case. /// /// @@ -1921,7 +1921,7 @@ public AndConstraint NotBeUpperCased(string because = "", params ob /// , /// /// - /// Numbers, special characters, and many Asian character don't have casing, so + /// Numbers, special characters, and many Asian characters don't have casing, so /// will ignore these and will fail only in the presence of upper-case characters. /// /// @@ -1946,7 +1946,7 @@ public AndConstraint BeLowerCased(string because = "", params objec /// the result of a call to . /// /// - /// Numbers, special characters, and many Asian character don't have casing, so + /// Numbers, special characters, and many Asian characters don't have casing, so /// will ignore these and will fail only if the string contains cased characters and they are all lower-case. /// /// From 68ce3edf9383fb85e8771639c4b564dd32017d32 Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Sun, 9 Jun 2024 22:59:10 +1000 Subject: [PATCH 10/11] Change alpha to alphabetic --- .../Primitives/StringAssertionSpecs.BeLowerCased.cs | 4 ++-- .../Primitives/StringAssertionSpecs.BeUpperCased.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs index be9ca51088..38c1ac56d6 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeLowerCased.cs @@ -88,7 +88,7 @@ public void The_assertion_fails_with_a_descriptive_message() // Assert act.Should().Throw().WithMessage( - "Expected all alpha characters in actual to be lower cased because we want to test the failure message, but found \"ABC\"."); + "Expected all alphabetic characters in actual to be lower cased because we want to test the failure message, but found \"ABC\"."); } [Fact] @@ -102,7 +102,7 @@ public void The_null_string_is_not_okay() // Assert act.Should().Throw().WithMessage( - "Expected all alpha characters in nullString to be lower cased because strings should never be null, but found ."); + "Expected all alphabetic characters in nullString to be lower cased because strings should never be null, but found ."); } } diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs index 4d03026e88..2d808b0869 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs @@ -75,7 +75,7 @@ public void The_assertion_fails_with_a_descriptive_message() // Assert act.Should().Throw().WithMessage( - @"Expected all alpha characters in actual to be upper-case because we want to test the failure message, but found ""abc""."); + "Expected all alphabetic characters in actual to be upper-case because we want to test the failure message, but found \"abc\"."); } [Fact] @@ -89,7 +89,7 @@ public void The_null_string_is_not_okay() // Assert act.Should().Throw().WithMessage( - "Expected all alpha characters in nullString to be upper-case because strings should never be null, but found ."); + "Expected all alphabeticc characters in nullString to be upper-case because strings should never be null, but found ."); } } From bc0e79e1dee9bd1f4802b5fdeb8769243e0f9435 Mon Sep 17 00:00:00 2001 From: drewjcooper Date: Mon, 10 Jun 2024 08:35:40 +1000 Subject: [PATCH 11/11] Fix typos --- .../Primitives/StringAssertionSpecs.BeUpperCased.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs index 2d808b0869..7b16655243 100644 --- a/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs +++ b/Tests/FluentAssertions.Specs/Primitives/StringAssertionSpecs.BeUpperCased.cs @@ -89,7 +89,7 @@ public void The_null_string_is_not_okay() // Assert act.Should().Throw().WithMessage( - "Expected all alphabeticc characters in nullString to be upper-case because strings should never be null, but found ."); + "Expected all alphabetic characters in nullString to be upper-case because strings should never be null, but found ."); } }