diff --git a/Pipeline/Build.cs b/Pipeline/Build.cs index a07a0cc08..25356ef59 100644 --- a/Pipeline/Build.cs +++ b/Pipeline/Build.cs @@ -19,7 +19,7 @@ partial class Build : NukeBuild /// /// Afterward, you can update the package reference in `Directory.Packages.props` and reset this flag. /// - readonly BuildScope BuildScope = BuildScope.Default; + readonly BuildScope BuildScope = BuildScope.CoreOnly; [Parameter("Github Token")] readonly string GithubToken; diff --git a/Source/aweXpect.Core/Formatting/ValueFormatters.Collection.cs b/Source/aweXpect.Core/Formatting/ValueFormatters.Collection.cs index 005329f3a..c3e197cbc 100644 --- a/Source/aweXpect.Core/Formatting/ValueFormatters.Collection.cs +++ b/Source/aweXpect.Core/Formatting/ValueFormatters.Collection.cs @@ -85,6 +85,7 @@ public static void Format( stringBuilder.Append(Format(formatter, v, options with { IncludeType = false, + UseLineBreaks = options.UseLineBreaks && v?.GetType() != typeof(string), }).Indent(" ", false)); } diff --git a/Source/aweXpect/Results/HasItemObjectResult.cs b/Source/aweXpect.Core/Results/ObjectHasItemResult.cs similarity index 64% rename from Source/aweXpect/Results/HasItemObjectResult.cs rename to Source/aweXpect.Core/Results/ObjectHasItemResult.cs index ebfc92dda..babd61ef6 100644 --- a/Source/aweXpect/Results/HasItemObjectResult.cs +++ b/Source/aweXpect.Core/Results/ObjectHasItemResult.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using aweXpect.Core; -using aweXpect.Equivalency; using aweXpect.Options; namespace aweXpect.Results; @@ -12,41 +10,35 @@ namespace aweXpect.Results; /// /// /// -public class HasItemObjectResult( +public class ObjectHasItemResult( ExpectationBuilder expectationBuilder, IThat collection, CollectionIndexOptions collectionIndexOptions, ObjectEqualityOptions options) - : HasItemObjectResult>( + : ObjectHasItemResult>( expectationBuilder, collection, collectionIndexOptions, options); - /// /// The result for verifying that a collection has a specific item at a given index. /// /// /// /// -public class HasItemObjectResult( +public class ObjectHasItemResult( ExpectationBuilder expectationBuilder, IThat collection, CollectionIndexOptions collectionIndexOptions, ObjectEqualityOptions options) - : HasItemResult(expectationBuilder, collection, collectionIndexOptions) - where TSelf : HasItemObjectResult + : HasItemResult(expectationBuilder, collection, collectionIndexOptions), + IOptionsProvider> + where TSelf : ObjectHasItemResult { - /// - /// Use equivalency to compare objects. - /// - public TSelf Equivalent(Func? optionsCallback = null) - { - options.Equivalent(EquivalencyOptionsExtensions.FromCallback(optionsCallback)); - return (TSelf)this; - } + /// + ObjectEqualityOptions IOptionsProvider>.Options => options; /// /// Uses the provided for comparing s. diff --git a/Source/aweXpect.Core/Results/StringHasItemResult.cs b/Source/aweXpect.Core/Results/StringHasItemResult.cs new file mode 100644 index 000000000..7905bf4a7 --- /dev/null +++ b/Source/aweXpect.Core/Results/StringHasItemResult.cs @@ -0,0 +1,138 @@ +using System.Collections.Generic; +using System.Text.RegularExpressions; +using aweXpect.Core; +using aweXpect.Options; + +namespace aweXpect.Results; + +/// +/// The result for verifying that a collection has a specific item at a given index. +/// +/// +/// +/// +public class StringHasItemResult( + ExpectationBuilder expectationBuilder, + IThat collection, + CollectionIndexOptions collectionIndexOptions, + StringEqualityOptions options) + : StringHasItemResult>( + expectationBuilder, + collection, + collectionIndexOptions, + options); + +/// +/// The result for verifying that a collection has a specific item at a given index. +/// +/// +/// +/// +public class StringHasItemResult( + ExpectationBuilder expectationBuilder, + IThat collection, + CollectionIndexOptions collectionIndexOptions, + StringEqualityOptions options) + : HasItemResult(expectationBuilder, collection, collectionIndexOptions), + IOptionsProvider + where TSelf : StringHasItemResult +{ + /// + StringEqualityOptions IOptionsProvider.Options => options; + + /// + /// Ignores casing when comparing the s, + /// according to the parameter. + /// + public TSelf IgnoringCase(bool ignoreCase = true) + { + options.IgnoringCase(ignoreCase); + return (TSelf)this; + } + + /// + /// Ignores the newline style when comparing s, + /// according to the parameter. + /// + /// + /// Enabling this option will replace all occurrences of \r\n and \r with \n in the strings before + /// comparing them. + /// + public TSelf IgnoringNewlineStyle(bool ignoreNewlineStyle = true) + { + options.IgnoringNewlineStyle(ignoreNewlineStyle); + return (TSelf)this; + } + + /// + /// Ignores leading white-space when comparing s, + /// according to the parameter. + /// + /// + /// Note:
+ /// This affects the index of first mismatch, as the removed whitespace is also ignored for the index calculation! + ///
+ public TSelf IgnoringLeadingWhiteSpace(bool ignoreLeadingWhiteSpace = true) + { + options.IgnoringLeadingWhiteSpace(ignoreLeadingWhiteSpace); + return (TSelf)this; + } + + /// + /// Ignores trailing white-space when comparing s, + /// according to the parameter. + /// + public TSelf IgnoringTrailingWhiteSpace(bool ignoreTrailingWhiteSpace = true) + { + options.IgnoringTrailingWhiteSpace(ignoreTrailingWhiteSpace); + return (TSelf)this; + } + + /// + /// Uses the provided for comparing s. + /// + public TSelf Using( + IEqualityComparer comparer) + { + options.UsingComparer(comparer); + return (TSelf)this; + } + + /// + /// Interprets the expected as a prefix, so that the actual value starts with it. + /// + public TSelf AsPrefix() + { + options.AsPrefix(); + return (TSelf)this; + } + + /// + /// Interprets the expected as pattern. + /// + public TSelf AsRegex() + { + options.AsRegex(); + return (TSelf)this; + } + + /// + /// Interprets the expected as a suffix, so that the actual value ends with it. + /// + public TSelf AsSuffix() + { + options.AsSuffix(); + return (TSelf)this; + } + + /// + /// Interprets the expected as wildcard pattern.
+ /// Supports * to match zero or more characters and ? to match exactly one character. + ///
+ public TSelf AsWildcard() + { + options.AsWildcard(); + return (TSelf)this; + } +} diff --git a/Source/aweXpect/Equivalency/EquivalencyExtensions.cs b/Source/aweXpect/Equivalency/EquivalencyExtensions.cs index f4e66837f..a756d588b 100644 --- a/Source/aweXpect/Equivalency/EquivalencyExtensions.cs +++ b/Source/aweXpect/Equivalency/EquivalencyExtensions.cs @@ -24,6 +24,19 @@ public static TSelf Equivalent( return (TSelf)result; } + /// + /// Use equivalency to compare objects. + /// + public static TSelf Equivalent( + this ObjectHasItemResult result, + Func? options = null) + where TSelf : ObjectHasItemResult + { + ((IOptionsProvider>)result).Options.SetMatchType( + new EquivalencyComparer(EquivalencyOptionsExtensions.FromCallback(options))); + return (TSelf)result; + } + /// /// Use equivalency to compare objects. /// diff --git a/Source/aweXpect/That/Collections/ThatAsyncEnumerable.HasItem.cs b/Source/aweXpect/That/Collections/ThatAsyncEnumerable.HasItem.cs index bb9766454..8c2d13506 100644 --- a/Source/aweXpect/That/Collections/ThatAsyncEnumerable.HasItem.cs +++ b/Source/aweXpect/That/Collections/ThatAsyncEnumerable.HasItem.cs @@ -38,13 +38,13 @@ public static partial class ThatAsyncEnumerable /// /// Verifies that the collection has the item… /// - public static HasItemObjectResult?, TItem> HasItem( + public static ObjectHasItemResult?, TItem> HasItem( this IThat?> source, TItem expected) { CollectionIndexOptions indexOptions = new(); ExpectationBuilder expectationBuilder = source.Get().ExpectationBuilder; ObjectEqualityOptions options = new(); - return new HasItemObjectResult?, TItem>( + return new ObjectHasItemResult?, TItem>( expectationBuilder.AddConstraint((it, grammars) => new HasItemConstraint(expectationBuilder, it, grammars, a => options.AreConsideredEqual(a, expected), @@ -55,6 +55,26 @@ public static partial class ThatAsyncEnumerable options); } + /// + /// Verifies that the collection has the item… + /// + public static StringHasItemResult?> HasItem( + this IThat?> source, string? expected) + { + CollectionIndexOptions indexOptions = new(); + ExpectationBuilder expectationBuilder = source.Get().ExpectationBuilder; + StringEqualityOptions options = new(); + return new StringHasItemResult?>( + expectationBuilder.AddConstraint((it, grammars) + => new HasItemConstraint(expectationBuilder, it, grammars, + a => options.AreConsideredEqual(a, expected), + () => options.GetExpectation(expected, grammars), + indexOptions)), + source, + indexOptions, + options); + } + private sealed class HasItemConstraint( ExpectationBuilder expectationBuilder, string it, diff --git a/Source/aweXpect/That/Collections/ThatEnumerable.HasItem.cs b/Source/aweXpect/That/Collections/ThatEnumerable.HasItem.cs index 8ed042eda..bbef4fa7d 100644 --- a/Source/aweXpect/That/Collections/ThatEnumerable.HasItem.cs +++ b/Source/aweXpect/That/Collections/ThatEnumerable.HasItem.cs @@ -40,13 +40,13 @@ public static partial class ThatEnumerable /// /// Verifies that the collection has the item… /// - public static HasItemObjectResult?, TItem> HasItem( + public static ObjectHasItemResult?, TItem> HasItem( this IThat?> source, TItem expected) { CollectionIndexOptions indexOptions = new(); ExpectationBuilder expectationBuilder = source.Get().ExpectationBuilder; ObjectEqualityOptions options = new(); - return new HasItemObjectResult?, TItem>( + return new ObjectHasItemResult?, TItem>( expectationBuilder.AddConstraint((it, grammars) => new HasItemConstraint(expectationBuilder, it, grammars, a => options.AreConsideredEqual(a, expected), @@ -57,6 +57,26 @@ public static partial class ThatEnumerable options); } + /// + /// Verifies that the collection has the item… + /// + public static StringHasItemResult?> HasItem( + this IThat?> source, string? expected) + { + CollectionIndexOptions indexOptions = new(); + ExpectationBuilder expectationBuilder = source.Get().ExpectationBuilder; + StringEqualityOptions options = new(); + return new StringHasItemResult?>( + expectationBuilder.AddConstraint((it, grammars) + => new HasItemConstraint(expectationBuilder, it, grammars, + a => options.AreConsideredEqual(a, expected), + () => options.GetExpectation(expected, grammars), + indexOptions)), + source, + indexOptions, + options); + } + /// /// Verifies that the collection has an item matching the … /// @@ -80,13 +100,13 @@ public static HasItemResult HasItem( /// /// Verifies that the collection has the item… /// - public static HasItemObjectResult HasItem( + public static ObjectHasItemResult HasItem( this IThat source, object? expected) { CollectionIndexOptions indexOptions = new(); ExpectationBuilder expectationBuilder = source.Get().ExpectationBuilder; ObjectEqualityOptions options = new(); - return new HasItemObjectResult( + return new ObjectHasItemResult( expectationBuilder.AddConstraint((it, grammars) => new HasItemForEnumerableConstraint( expectationBuilder, it, grammars, @@ -124,13 +144,13 @@ public static HasItemResult> HasItem( /// /// Verifies that the collection has the item… /// - public static HasItemObjectResult, TItem> HasItem( + public static ObjectHasItemResult, TItem> HasItem( this IThat> source, TItem expected) { CollectionIndexOptions indexOptions = new(); ExpectationBuilder expectationBuilder = source.Get().ExpectationBuilder; ObjectEqualityOptions options = new(); - return new HasItemObjectResult, TItem>( + return new ObjectHasItemResult, TItem>( expectationBuilder.AddConstraint((it, grammars) => new HasItemForEnumerableConstraint, TItem>( expectationBuilder, it, grammars, @@ -143,6 +163,29 @@ public static HasItemObjectResult, TItem> HasItem( } #endif +#if NET8_0_OR_GREATER + /// + /// Verifies that the collection has the item… + /// + public static StringHasItemResult> HasItem( + this IThat> source, string? expected) + { + CollectionIndexOptions indexOptions = new(); + ExpectationBuilder expectationBuilder = source.Get().ExpectationBuilder; + StringEqualityOptions options = new(); + return new StringHasItemResult>( + expectationBuilder.AddConstraint((it, grammars) + => new HasItemForEnumerableConstraint, string?>( + expectationBuilder, it, grammars, + a => options.AreConsideredEqual(a, expected), + () => $"{Formatter.Format(expected)}{options}", + indexOptions)), + source, + indexOptions, + options); + } +#endif + private sealed class HasItemConstraint( ExpectationBuilder expectationBuilder, string it, diff --git a/Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt b/Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt index 253aeb4ee..0e00314d5 100644 --- a/Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt +++ b/Tests/aweXpect.Api.Tests/Expected/aweXpect_net8.0.txt @@ -88,7 +88,8 @@ namespace aweXpect public static aweXpect.ThatAsyncEnumerable.Elements Exactly(this aweXpect.Core.IThat?> subject, int expected) { } public static aweXpect.CollectionCountResult, aweXpect.Core.IThat?>>> HasCount(this aweXpect.Core.IThat?> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat?>> HasCount(this aweXpect.Core.IThat?> subject, int expected) { } - public static aweXpect.Results.HasItemObjectResult?, TItem> HasItem(this aweXpect.Core.IThat?> source, TItem expected) { } + public static aweXpect.Results.StringHasItemResult?> HasItem(this aweXpect.Core.IThat?> source, string? expected) { } + public static aweXpect.Results.ObjectHasItemResult?, TItem> HasItem(this aweXpect.Core.IThat?> source, TItem expected) { } public static aweXpect.Results.HasItemResult?> HasItem(this aweXpect.Core.IThat?> source, System.Func predicate, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") { } public static aweXpect.Results.SingleItemResult, TItem>.Async HasSingle(this aweXpect.Core.IThat?> source) { } public static aweXpect.Results.StringCollectionBeContainedInResult, aweXpect.Core.IThat?>> IsContainedIn(this aweXpect.Core.IThat?> source, System.Collections.Generic.IEnumerable expected, [System.Runtime.CompilerServices.CallerArgumentExpression("expected")] string doNotPopulateThisValue = "") { } @@ -481,10 +482,12 @@ namespace aweXpect public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat?>> HasCount(this aweXpect.Core.IThat?> subject, int expected) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> HasCount(this aweXpect.Core.IThat> subject, int expected) { } public static aweXpect.Results.AndOrResult> HasCount(this aweXpect.Core.IThat subject, int expected) { } - public static aweXpect.Results.HasItemObjectResult HasItem(this aweXpect.Core.IThat source, object? expected) { } + public static aweXpect.Results.StringHasItemResult?> HasItem(this aweXpect.Core.IThat?> source, string? expected) { } + public static aweXpect.Results.ObjectHasItemResult HasItem(this aweXpect.Core.IThat source, object? expected) { } + public static aweXpect.Results.StringHasItemResult> HasItem(this aweXpect.Core.IThat> source, string? expected) { } public static aweXpect.Results.HasItemResult HasItem(this aweXpect.Core.IThat source, System.Func predicate, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") { } - public static aweXpect.Results.HasItemObjectResult?, TItem> HasItem(this aweXpect.Core.IThat?> source, TItem expected) { } - public static aweXpect.Results.HasItemObjectResult, TItem> HasItem(this aweXpect.Core.IThat> source, TItem expected) { } + public static aweXpect.Results.ObjectHasItemResult?, TItem> HasItem(this aweXpect.Core.IThat?> source, TItem expected) { } + public static aweXpect.Results.ObjectHasItemResult, TItem> HasItem(this aweXpect.Core.IThat> source, TItem expected) { } public static aweXpect.Results.HasItemResult?> HasItem(this aweXpect.Core.IThat?> source, System.Func predicate, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") { } public static aweXpect.Results.HasItemResult> HasItem(this aweXpect.Core.IThat> source, System.Func predicate, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") { } public static aweXpect.Results.SingleItemResult HasSingle(this aweXpect.Core.IThat source) { } @@ -1176,6 +1179,8 @@ namespace aweXpect.Equivalency { public static class EquivalencyExtensions { + public static TSelf Equivalent(this aweXpect.Results.ObjectHasItemResult result, System.Func? options = null) + where TSelf : aweXpect.Results.ObjectHasItemResult { } public static TSelf Equivalent(this aweXpect.Results.ObjectEqualityResult result, System.Func? options = null) where TSelf : aweXpect.Results.ObjectEqualityResult { } } @@ -1238,17 +1243,6 @@ namespace aweXpect.Results aweXpect.Results.EventTriggerResult WithParameter(string expression, int? position, System.Func predicate); } } - public class HasItemObjectResult : aweXpect.Results.HasItemObjectResult> - { - public HasItemObjectResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.ObjectEqualityOptions options) { } - } - public class HasItemObjectResult : aweXpect.Results.HasItemResult - where TSelf : aweXpect.Results.HasItemObjectResult - { - public HasItemObjectResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.ObjectEqualityOptions options) { } - public TSelf Equivalent(System.Func? optionsCallback = null) { } - public TSelf Using(System.Collections.Generic.IEqualityComparer comparer) { } - } public class ObjectCollectionBeContainedInResult : aweXpect.Results.ObjectCollectionMatchResult { public ObjectCollectionBeContainedInResult(aweXpect.Core.ExpectationBuilder expectationBuilder, TThat returnValue, aweXpect.Options.ObjectEqualityOptions options, aweXpect.Options.CollectionMatchOptions collectionMatchOptions) { } diff --git a/Tests/aweXpect.Api.Tests/Expected/aweXpect_netstandard2.0.txt b/Tests/aweXpect.Api.Tests/Expected/aweXpect_netstandard2.0.txt index 4e99c2639..834832d75 100644 --- a/Tests/aweXpect.Api.Tests/Expected/aweXpect_netstandard2.0.txt +++ b/Tests/aweXpect.Api.Tests/Expected/aweXpect_netstandard2.0.txt @@ -291,9 +291,10 @@ namespace aweXpect public static aweXpect.CollectionCountResult>> HasCount(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat?>> HasCount(this aweXpect.Core.IThat?> subject, int expected) { } public static aweXpect.Results.AndOrResult> HasCount(this aweXpect.Core.IThat subject, int expected) { } - public static aweXpect.Results.HasItemObjectResult HasItem(this aweXpect.Core.IThat source, object? expected) { } + public static aweXpect.Results.StringHasItemResult?> HasItem(this aweXpect.Core.IThat?> source, string? expected) { } + public static aweXpect.Results.ObjectHasItemResult HasItem(this aweXpect.Core.IThat source, object? expected) { } public static aweXpect.Results.HasItemResult HasItem(this aweXpect.Core.IThat source, System.Func predicate, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") { } - public static aweXpect.Results.HasItemObjectResult?, TItem> HasItem(this aweXpect.Core.IThat?> source, TItem expected) { } + public static aweXpect.Results.ObjectHasItemResult?, TItem> HasItem(this aweXpect.Core.IThat?> source, TItem expected) { } public static aweXpect.Results.HasItemResult?> HasItem(this aweXpect.Core.IThat?> source, System.Func predicate, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") { } public static aweXpect.Results.SingleItemResult HasSingle(this aweXpect.Core.IThat source) { } public static aweXpect.Results.SingleItemResult, TItem> HasSingle(this aweXpect.Core.IThat?> source) { } @@ -1155,6 +1156,8 @@ namespace aweXpect.Equivalency { public static class EquivalencyExtensions { + public static TSelf Equivalent(this aweXpect.Results.ObjectHasItemResult result, System.Func? options = null) + where TSelf : aweXpect.Results.ObjectHasItemResult { } public static TSelf Equivalent(this aweXpect.Results.ObjectEqualityResult result, System.Func? options = null) where TSelf : aweXpect.Results.ObjectEqualityResult { } } @@ -1217,17 +1220,6 @@ namespace aweXpect.Results aweXpect.Results.EventTriggerResult WithParameter(string expression, int? position, System.Func predicate); } } - public class HasItemObjectResult : aweXpect.Results.HasItemObjectResult> - { - public HasItemObjectResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.ObjectEqualityOptions options) { } - } - public class HasItemObjectResult : aweXpect.Results.HasItemResult - where TSelf : aweXpect.Results.HasItemObjectResult - { - public HasItemObjectResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.ObjectEqualityOptions options) { } - public TSelf Equivalent(System.Func? optionsCallback = null) { } - public TSelf Using(System.Collections.Generic.IEqualityComparer comparer) { } - } public class ObjectCollectionBeContainedInResult : aweXpect.Results.ObjectCollectionMatchResult { public ObjectCollectionBeContainedInResult(aweXpect.Core.ExpectationBuilder expectationBuilder, TThat returnValue, aweXpect.Options.ObjectEqualityOptions options, aweXpect.Options.CollectionMatchOptions collectionMatchOptions) { } diff --git a/Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_net8.0.txt b/Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_net8.0.txt index d051fdc08..80520748e 100644 --- a/Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_net8.0.txt +++ b/Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_net8.0.txt @@ -1127,6 +1127,16 @@ namespace aweXpect.Results public ObjectEqualityResult(aweXpect.Core.ExpectationBuilder expectationBuilder, TThat returnValue, aweXpect.Options.ObjectEqualityOptions options) { } public TSelf Using(System.Collections.Generic.IEqualityComparer comparer) { } } + public class ObjectHasItemResult : aweXpect.Results.ObjectHasItemResult> + { + public ObjectHasItemResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.ObjectEqualityOptions options) { } + } + public class ObjectHasItemResult : aweXpect.Results.HasItemResult, aweXpect.Core.IOptionsProvider> + where TSelf : aweXpect.Results.ObjectHasItemResult + { + public ObjectHasItemResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.ObjectEqualityOptions options) { } + public TSelf Using(System.Collections.Generic.IEqualityComparer comparer) { } + } public static class PropertyResult { public class DateTimeKind @@ -1215,6 +1225,24 @@ namespace aweXpect.Results public TSelf AsWildcard() { } public TSelf Exactly() { } } + public class StringHasItemResult : aweXpect.Results.StringHasItemResult> + { + public StringHasItemResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.StringEqualityOptions options) { } + } + public class StringHasItemResult : aweXpect.Results.HasItemResult, aweXpect.Core.IOptionsProvider + where TSelf : aweXpect.Results.StringHasItemResult + { + public StringHasItemResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.StringEqualityOptions options) { } + public TSelf AsPrefix() { } + public TSelf AsRegex() { } + public TSelf AsSuffix() { } + public TSelf AsWildcard() { } + public TSelf IgnoringCase(bool ignoreCase = true) { } + public TSelf IgnoringLeadingWhiteSpace(bool ignoreLeadingWhiteSpace = true) { } + public TSelf IgnoringNewlineStyle(bool ignoreNewlineStyle = true) { } + public TSelf IgnoringTrailingWhiteSpace(bool ignoreTrailingWhiteSpace = true) { } + public TSelf Using(System.Collections.Generic.IEqualityComparer comparer) { } + } public class TimeToleranceResult : aweXpect.Results.TimeToleranceResult> { public TimeToleranceResult(aweXpect.Core.ExpectationBuilder expectationBuilder, TThat returnValue, aweXpect.Options.TimeTolerance options) { } diff --git a/Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_netstandard2.0.txt b/Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_netstandard2.0.txt index 09f752909..a00956315 100644 --- a/Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_netstandard2.0.txt +++ b/Tests/aweXpect.Core.Api.Tests/Expected/aweXpect.Core_netstandard2.0.txt @@ -1110,6 +1110,16 @@ namespace aweXpect.Results public ObjectEqualityResult(aweXpect.Core.ExpectationBuilder expectationBuilder, TThat returnValue, aweXpect.Options.ObjectEqualityOptions options) { } public TSelf Using(System.Collections.Generic.IEqualityComparer comparer) { } } + public class ObjectHasItemResult : aweXpect.Results.ObjectHasItemResult> + { + public ObjectHasItemResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.ObjectEqualityOptions options) { } + } + public class ObjectHasItemResult : aweXpect.Results.HasItemResult, aweXpect.Core.IOptionsProvider> + where TSelf : aweXpect.Results.ObjectHasItemResult + { + public ObjectHasItemResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.ObjectEqualityOptions options) { } + public TSelf Using(System.Collections.Generic.IEqualityComparer comparer) { } + } public static class PropertyResult { public class DateTimeKind @@ -1198,6 +1208,24 @@ namespace aweXpect.Results public TSelf AsWildcard() { } public TSelf Exactly() { } } + public class StringHasItemResult : aweXpect.Results.StringHasItemResult> + { + public StringHasItemResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.StringEqualityOptions options) { } + } + public class StringHasItemResult : aweXpect.Results.HasItemResult, aweXpect.Core.IOptionsProvider + where TSelf : aweXpect.Results.StringHasItemResult + { + public StringHasItemResult(aweXpect.Core.ExpectationBuilder expectationBuilder, aweXpect.Core.IThat collection, aweXpect.Options.CollectionIndexOptions collectionIndexOptions, aweXpect.Options.StringEqualityOptions options) { } + public TSelf AsPrefix() { } + public TSelf AsRegex() { } + public TSelf AsSuffix() { } + public TSelf AsWildcard() { } + public TSelf IgnoringCase(bool ignoreCase = true) { } + public TSelf IgnoringLeadingWhiteSpace(bool ignoreLeadingWhiteSpace = true) { } + public TSelf IgnoringNewlineStyle(bool ignoreNewlineStyle = true) { } + public TSelf IgnoringTrailingWhiteSpace(bool ignoreTrailingWhiteSpace = true) { } + public TSelf Using(System.Collections.Generic.IEqualityComparer comparer) { } + } public class TimeToleranceResult : aweXpect.Results.TimeToleranceResult> { public TimeToleranceResult(aweXpect.Core.ExpectationBuilder expectationBuilder, TThat returnValue, aweXpect.Options.TimeTolerance options) { } diff --git a/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.Contains.Tests.cs b/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.Contains.Tests.cs index 9961d45ef..cdd264da5 100644 --- a/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.Contains.Tests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.Contains.Tests.cs @@ -718,12 +718,9 @@ but it did not contain it Collection: [ - "fo - o", - "ba - r", - "ba - z" + "fo{nl.DisplayWhitespace()}o", + "ba{nl.DisplayWhitespace()}r", + "ba{nl.DisplayWhitespace()}z" ] """); } diff --git a/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.HasItem.Tests.cs b/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.HasItem.Tests.cs index 1caf3d44b..45fa7cb23 100644 --- a/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.HasItem.Tests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.HasItem.Tests.cs @@ -1,6 +1,7 @@ #if NET8_0_OR_GREATER using System.Collections.Generic; using System.Linq; +using aweXpect.Equivalency; // ReSharper disable PossibleMultipleEnumeration @@ -289,6 +290,409 @@ but it was """); } + [Fact] + public async Task WithMultipleFailures_ShouldIncludeCollectionOnlyOnce() + { + IAsyncEnumerable subject = ToAsyncEnumerable(1, 2, 3); + + async Task Act() + => await That(subject).HasItem(4).AtIndex(0).And.HasItem(5).AtIndex(1).And.HasItem(6) + .AtAnyIndex(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item 4 at index 0 and has item 5 at index 1 and has item 6, + but it had item 1 at index 0 and it had item 2 at index 1 and it did not match at any index + + Collection: + [1, 2, 3] + """); + } + } + + public sealed class StringItemTests + { + [Fact] + public async Task AsPrefix_WhenItemDoesNotStartWithExpected_ShouldFail() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("f").AsPrefix().AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item starting with "f" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task AsPrefix_WhenItemStartsWithExpected_ShouldSucceed() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("b").AsPrefix().AtIndex(1); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task AsRegex_WhenItemDoesNotMatch_ShouldFail() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("f[aeiou]?o").AsRegex().AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item matching regex "f[aeiou]?o" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task AsRegex_WhenItemMatches_ShouldSucceed() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("b[aeiou]?r").AsRegex().AtIndex(1); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task AsSuffix_WhenItemDoesNotEndWithExpected_ShouldFail() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("o").AsSuffix().AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item ending with "o" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task AsSuffix_WhenItemEndsWithExpected_ShouldSucceed() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("r").AsSuffix().AtIndex(1); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task AsWildcard_WhenItemDoesNotMatch_ShouldFail() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("f*o").AsWildcard().AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item matching "f*o" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task AsWildcard_WhenItemMatches_ShouldSucceed() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("b?r").AsWildcard().AtIndex(1); + + await That(Act).DoesNotThrow(); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ShouldSupportIgnoringCase(bool ignoreCase) + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("BAR").IgnoringCase(ignoreCase).AtIndex(1); + + await That(Act).Throws().OnlyIf(!ignoreCase) + .WithMessage(""" + Expected that subject + has item equal to "BAR" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ShouldSupportIgnoringLeadingWhiteSpace(bool ignoreLeadingWhiteSpace) + { + IAsyncEnumerable subject = ToAsyncEnumerable([" foo", "\tbar", "baz",]); + + async Task Act() + => await That(subject).HasItem("bar").IgnoringLeadingWhiteSpace(ignoreLeadingWhiteSpace).AtIndex(1); + + await That(Act).Throws().OnlyIf(!ignoreLeadingWhiteSpace) + .WithMessage(""" + Expected that subject + has item equal to "bar" at index 1, + but it had item "\tbar" at index 1 + + Collection: + [ + " foo", + "\tbar", + "baz" + ] + """); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ShouldSupportIgnoringNewlineStyle(bool ignoreNewlineStyle) + { + IAsyncEnumerable subject = ToAsyncEnumerable(["a\nb", "c\nd", "e\nf",]); + + async Task Act() + => await That(subject).HasItem("c\r\nd").IgnoringNewlineStyle(ignoreNewlineStyle).AtIndex(1); + + await That(Act).Throws().OnlyIf(!ignoreNewlineStyle) + .WithMessage(""" + Expected that subject + has item equal to "c\r\nd" at index 1, + but it had item "c\nd" at index 1 + + Collection: + [ + "a\nb", + "c\nd", + "e\nf" + ] + """); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ShouldSupportIgnoringTrailingWhiteSpace(bool ignoreTrailingWhiteSpace) + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo ", "bar\t", "baz",]); + + async Task Act() + => await That(subject).HasItem("bar").IgnoringTrailingWhiteSpace(ignoreTrailingWhiteSpace) + .AtIndex(1); + + await That(Act).Throws().OnlyIf(!ignoreTrailingWhiteSpace) + .WithMessage(""" + Expected that subject + has item equal to "bar" at index 1, + but it had item "bar\t" at index 1 + + Collection: + [ + "foo ", + "bar\t", + "baz" + ] + """); + } + + [Fact] + public async Task WhenEnumerableContainsDifferentItemAtGivenIndex_ShouldSucceed() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["a", "b", "bar", "c",]); + + async Task Act() + => await That(subject).HasItem("foo").AtIndex(2); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "foo" at index 2, + but it had item "bar" at index 2 + + Collection: + [ + "a", + "b", + "bar", + "c" + ] + """); + } + + [Fact] + public async Task WhenEnumerableContainsExpectedItemAtGivenIndex_ShouldSucceed() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["a", "b", "bar", "c",]); + + async Task Act() + => await That(subject).HasItem("bar").AtIndex(2); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenEnumerableContainsNoItemAtGivenIndex_ShouldSucceed() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["a", "b", "c",]); + + async Task Act() + => await That(subject).HasItem("c").AtIndex(3); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "c" at index 3, + but it did not contain any item at index 3 + + Collection: + [ + "a", + "b", + "c" + ] + """); + } + + [Fact] + public async Task WhenEnumerableIsEmpty_ShouldFail() + { + IAsyncEnumerable subject = ToAsyncEnumerable(Array.Empty()); + + async Task Act() + => await That(subject).HasItem("foo").AtAnyIndex(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "foo", + but it did not contain any item + + Collection: + [] + """); + } + + [Fact] + public async Task WhenSubjectIsNull_WithAnyIndex_ShouldFail() + { + IAsyncEnumerable? subject = null; + + async Task Act() + => await That(subject!).HasItem("foo").AtAnyIndex(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "foo", + but it was + """); + } + + [Fact] + public async Task WhenSubjectIsNull_WithFixedIndex_ShouldFail() + { + IAsyncEnumerable? subject = null; + + async Task Act() + => await That(subject!).HasItem("bar").AtIndex(0); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "bar" at index 0, + but it was + """); + } + + [Fact] + public async Task WithCustomStringComparer_WhenItemsDoNotMatch_ShouldFail() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("BaR").Using(new IgnoreCaseForVocalsComparer()).AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "BaR" using IgnoreCaseForVocalsComparer at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task WithCustomStringComparer_WhenItemsMatch_ShouldSucceed() + { + IAsyncEnumerable subject = ToAsyncEnumerable(["foo", "bar", "baz",]); + + async Task Act() + => await That(subject).HasItem("bAr").Using(new IgnoreCaseForVocalsComparer()).AtIndex(1); + + await That(Act).DoesNotThrow(); + } + [Fact] public async Task WithMultipleFailures_ShouldIncludeCollectionOnlyOnce() { @@ -301,7 +705,7 @@ async Task Act() await That(Act).Throws() .WithMessage(""" Expected that subject - has item "d" at index 0 and has item "e" at index 1 and has item "f", + has item equal to "d" at index 0 and has item equal to "e" at index 1 and has item equal to "f", but it had item "a" at index 0 and it had item "b" at index 1 and it did not match at any index Collection: @@ -401,7 +805,7 @@ public sealed class UsingTests [Fact] public async Task WithAllDifferentComparer_ShouldFail() { - IEnumerable subject = Factory.GetFibonacciNumbers(20); + IAsyncEnumerable subject = Factory.GetAsyncFibonacciNumbers(20); async Task Act() => await That(subject).HasItem(1).Using(new AllDifferentComparer()).AtAnyIndex(); @@ -432,7 +836,7 @@ but it did not match at any index [Fact] public async Task WithAllEqualComparer_ShouldSucceed() { - IEnumerable subject = Factory.GetFibonacciNumbers(20); + IAsyncEnumerable subject = Factory.GetAsyncFibonacciNumbers(20); async Task Act() => await That(subject).HasItem(4).Using(new AllEqualComparer()).AtAnyIndex(); diff --git a/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.IsNotEqualTo.Tests.cs b/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.IsNotEqualTo.Tests.cs index c1e1fc9aa..a3cd81627 100644 --- a/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.IsNotEqualTo.Tests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatAsyncEnumerable.IsNotEqualTo.Tests.cs @@ -1205,7 +1205,7 @@ but it did [ " a", "b", - " c" + "\tc" ] Expected: @@ -1237,7 +1237,7 @@ but it did [ "a ", "b", - "c " + "c\t" ] Expected: diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.All.AreEqualTo.ImmutableTests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.All.AreEqualTo.ImmutableTests.cs index 61ddd373c..3a7957cfb 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.All.AreEqualTo.ImmutableTests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.All.AreEqualTo.ImmutableTests.cs @@ -397,14 +397,14 @@ but only 1 of 3 were Not matching items: [ " foo", - " foo" + "\tfoo" ] - + Collection: [ " foo", "foo", - " foo" + "\tfoo" ] """); } @@ -459,14 +459,14 @@ but only 1 of 3 were Not matching items: [ "foo ", - "foo " + "foo\t" ] - + Collection: [ "foo ", "foo", - "foo " + "foo\t" ] """); } diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.All.AreEqualTo.Tests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.All.AreEqualTo.Tests.cs index 33762e3d8..847828beb 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.All.AreEqualTo.Tests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.All.AreEqualTo.Tests.cs @@ -492,18 +492,18 @@ await That(Act).Throws().OnlyIf(!ignoreLeadingWhiteSpace) Expected that subject is equal to "foo" for all items, but only 1 of 3 were - + Not matching items: [ " foo", - " foo" + "\tfoo" ] - + Collection: [ " foo", "foo", - " foo" + "\tfoo" ] """); } @@ -554,18 +554,18 @@ await That(Act).Throws().OnlyIf(!ignoreTrailingWhiteSpace) Expected that subject is equal to "foo" for all items, but only 1 of 3 were - + Not matching items: [ "foo ", - "foo " + "foo\t" ] - + Collection: [ "foo ", "foo", - "foo " + "foo\t" ] """); } diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.ImmutableTests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.ImmutableTests.cs index 4419a3d9d..8a5298c9d 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.ImmutableTests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.ImmutableTests.cs @@ -735,12 +735,9 @@ but it did not contain it Collection: [ - "fo - o", - "ba - r", - "ba - z" + "fo{nl.DisplayWhitespace()}o", + "ba{nl.DisplayWhitespace()}r", + "ba{nl.DisplayWhitespace()}z" ] """); } diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.Tests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.Tests.cs index c554811d3..1e0d27cf8 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.Tests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.Contains.Tests.cs @@ -807,15 +807,12 @@ await That(Act).Throws().OnlyIf(!expectSuccess) Expected that subject contains {Formatter.Format(match)} ignoring newline style at least once, but it did not contain it - + Collection: [ - "fo - o", - "ba - r", - "ba - z" + "fo{nl.DisplayWhitespace()}o", + "ba{nl.DisplayWhitespace()}r", + "ba{nl.DisplayWhitespace()}z" ] """); } diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.EnumerableTests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.EnumerableTests.cs index 21083ad65..0a86be961 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.EnumerableTests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.EnumerableTests.cs @@ -1,6 +1,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using aweXpect.Equivalency; // ReSharper disable PossibleMultipleEnumeration diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.ImmutableTests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.ImmutableTests.cs index 9a86ba174..92bef3a5f 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.ImmutableTests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.ImmutableTests.cs @@ -1,6 +1,7 @@ #if NET8_0_OR_GREATER using System.Collections.Immutable; using System.Linq; +using aweXpect.Equivalency; // ReSharper disable PossibleMultipleEnumeration @@ -180,7 +181,7 @@ but it did not contain any item [Fact] public async Task WithMultipleFailures_ShouldIncludeCollectionOnlyOnce() { - ImmutableArray subject = ["a", "b", "c",]; + ImmutableArray subject = ["a", "b", "c",]; async Task Act() => await That(subject).HasItem("d").AtIndex(0).And.HasItem("e").AtIndex(1).And.HasItem("f") diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.Tests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.Tests.cs index ce9e5750b..026cf5920 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.Tests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.HasItem.Tests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using aweXpect.Equivalency; // ReSharper disable PossibleMultipleEnumeration @@ -164,7 +165,7 @@ but it had item "a" at index 0 and it had item "b" at index 1 and it did not mat """); } } - + public sealed class ItemTests { [Fact] @@ -307,6 +308,412 @@ but it was """); } + [Fact] + public async Task WithMultipleFailures_ShouldIncludeCollectionOnlyOnce() + { + IEnumerable subject = ToEnumerable([1, 2, 3,]); + + async Task Act() + => await That(subject).HasItem(4).AtIndex(0).And.HasItem(5).AtIndex(1).And.HasItem(6) + .AtAnyIndex(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item 4 at index 0 and has item 5 at index 1 and has item 6, + but it had item 1 at index 0 and it had item 2 at index 1 and it did not match at any index + + Collection: + [1, 2, 3] + """); + } + } + + public sealed class StringItemTests + { + [Fact] + public async Task AsPrefix_WhenItemDoesNotStartWithExpected_ShouldFail() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("f").AsPrefix().AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item starting with "f" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task AsPrefix_WhenItemStartsWithExpected_ShouldSucceed() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("b").AsPrefix().AtIndex(1); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task AsRegex_WhenItemDoesNotMatch_ShouldFail() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("f[aeiou]?o").AsRegex().AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item matching regex "f[aeiou]?o" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task AsRegex_WhenItemMatches_ShouldSucceed() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("b[aeiou]?r").AsRegex().AtIndex(1); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task AsSuffix_WhenItemDoesNotEndWithExpected_ShouldFail() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("o").AsSuffix().AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item ending with "o" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task AsSuffix_WhenItemEndsWithExpected_ShouldSucceed() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("r").AsSuffix().AtIndex(1); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task AsWildcard_WhenItemDoesNotMatch_ShouldFail() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("f*o").AsWildcard().AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item matching "f*o" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task AsWildcard_WhenItemMatches_ShouldSucceed() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("b?r").AsWildcard().AtIndex(1); + + await That(Act).DoesNotThrow(); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ShouldSupportIgnoringCase(bool ignoreCase) + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("BAR").IgnoringCase(ignoreCase).AtIndex(1); + + await That(Act).Throws().OnlyIf(!ignoreCase) + .WithMessage(""" + Expected that subject + has item equal to "BAR" at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ShouldSupportIgnoringLeadingWhiteSpace(bool ignoreLeadingWhiteSpace) + { + IEnumerable subject = [" foo", "\tbar", "baz",]; + + async Task Act() + => await That(subject).HasItem("bar").IgnoringLeadingWhiteSpace(ignoreLeadingWhiteSpace).AtIndex(1); + + await That(Act).Throws().OnlyIf(!ignoreLeadingWhiteSpace) + .WithMessage(""" + Expected that subject + has item equal to "bar" at index 1, + but it had item "\tbar" at index 1 + + Collection: + [ + " foo", + "\tbar", + "baz" + ] + """); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ShouldSupportIgnoringNewlineStyle(bool ignoreNewlineStyle) + { + IEnumerable subject = ["a\nb", "c\nd", "e\nf",]; + + async Task Act() + => await That(subject).HasItem("c\r\nd").IgnoringNewlineStyle(ignoreNewlineStyle).AtIndex(1); + + await That(Act).Throws().OnlyIf(!ignoreNewlineStyle) + .WithMessage(""" + Expected that subject + has item equal to "c\r\nd" at index 1, + but it had item "c\nd" at index 1 + + Collection: + [ + "a\nb", + "c\nd", + "e\nf" + ] + """); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ShouldSupportIgnoringTrailingWhiteSpace(bool ignoreTrailingWhiteSpace) + { + IEnumerable subject = ["foo ", "bar\t", "baz",]; + + async Task Act() + => await That(subject).HasItem("bar").IgnoringTrailingWhiteSpace(ignoreTrailingWhiteSpace) + .AtIndex(1); + + await That(Act).Throws().OnlyIf(!ignoreTrailingWhiteSpace) + .WithMessage(""" + Expected that subject + has item equal to "bar" at index 1, + but it had item "bar\t" at index 1 + + Collection: + [ + "foo ", + "bar\t", + "baz" + ] + """); + } + + [Theory] + [AutoData] + public async Task WhenEnumerableContainsDifferentItemAtGivenIndex_ShouldSucceed( + List subject) + { + subject.Add("a"); + subject.Add("b"); + subject.Insert(2, "bar"); + + async Task Act() + => await That(subject).HasItem("foo").AtIndex(2); + + await That(Act).Throws() + .WithMessage($""" + Expected that subject + has item equal to "foo" at index 2, + but it had item "bar" at index 2 + + Collection: + {Formatter.Format(subject, FormattingOptions.MultipleLines)} + """); + } + + [Theory] + [AutoData] + public async Task WhenEnumerableContainsExpectedItemAtGivenIndex_ShouldSucceed( + List subject) + { + subject.Add("a"); + subject.Add("b"); + subject.Insert(2, "bar"); + + async Task Act() + => await That(subject).HasItem("bar").AtIndex(2); + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenEnumerableContainsNoItemAtGivenIndex_ShouldSucceed() + { + List subject = ["a", "b", "c",]; + + async Task Act() + => await That(subject).HasItem("c").AtIndex(3); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "c" at index 3, + but it did not contain any item at index 3 + + Collection: + [ + "a", + "b", + "c" + ] + """); + } + + [Fact] + public async Task WhenEnumerableIsEmpty_ShouldFail() + { + List subject = []; + + async Task Act() + => await That(subject).HasItem("foo").AtAnyIndex(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "foo", + but it did not contain any item + + Collection: + [] + """); + } + + [Fact] + public async Task WhenSubjectIsNull_WithAnyIndex_ShouldFail() + { + IEnumerable? subject = null; + + async Task Act() + => await That(subject!).HasItem("foo").AtAnyIndex(); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "foo", + but it was + """); + } + + [Fact] + public async Task WhenSubjectIsNull_WithFixedIndex_ShouldFail() + { + IEnumerable? subject = null; + + async Task Act() + => await That(subject!).HasItem("bar").AtIndex(0); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "bar" at index 0, + but it was + """); + } + + [Fact] + public async Task WithCustomStringComparer_WhenItemsDoNotMatch_ShouldFail() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("BaR").Using(new IgnoreCaseForVocalsComparer()).AtIndex(1); + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + has item equal to "BaR" using IgnoreCaseForVocalsComparer at index 1, + but it had item "bar" at index 1 + + Collection: + [ + "foo", + "bar", + "baz" + ] + """); + } + + [Fact] + public async Task WithCustomStringComparer_WhenItemsMatch_ShouldSucceed() + { + IEnumerable subject = ["foo", "bar", "baz",]; + + async Task Act() + => await That(subject).HasItem("bAr").Using(new IgnoreCaseForVocalsComparer()).AtIndex(1); + + await That(Act).DoesNotThrow(); + } + [Fact] public async Task WithMultipleFailures_ShouldIncludeCollectionOnlyOnce() { @@ -319,7 +726,7 @@ async Task Act() await That(Act).Throws() .WithMessage(""" Expected that subject - has item "d" at index 0 and has item "e" at index 1 and has item "f", + has item equal to "d" at index 0 and has item equal to "e" at index 1 and has item equal to "f", but it had item "a" at index 0 and it had item "b" at index 1 and it did not match at any index Collection: diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.IsNotEqualTo.ImmutableTests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.IsNotEqualTo.ImmutableTests.cs index 2cb18824d..81b56b110 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.IsNotEqualTo.ImmutableTests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.IsNotEqualTo.ImmutableTests.cs @@ -1206,9 +1206,9 @@ but it did [ " a", "b", - " c" + "\tc" ] - + Expected: [ "a", @@ -1233,14 +1233,14 @@ await That(Act).Throws() Expected that subject does not match collection unexpected in order ignoring trailing white-space, but it did - + Collection: [ "a ", "b", - "c " + "c\t" ] - + Expected: [ "a", diff --git a/Tests/aweXpect.Tests/Collections/ThatEnumerable.IsNotEqualTo.Tests.cs b/Tests/aweXpect.Tests/Collections/ThatEnumerable.IsNotEqualTo.Tests.cs index d8176b4ef..0f001795d 100644 --- a/Tests/aweXpect.Tests/Collections/ThatEnumerable.IsNotEqualTo.Tests.cs +++ b/Tests/aweXpect.Tests/Collections/ThatEnumerable.IsNotEqualTo.Tests.cs @@ -1204,7 +1204,7 @@ but it did [ " a", "b", - " c" + "\tc" ] Expected: @@ -1236,7 +1236,7 @@ but it did [ "a ", "b", - "c " + "c\t" ] Expected: