diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 04e2a4348..8497d08c6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,3 +10,14 @@ * [ ] If the PR changes the public API the changes needs to be included by running [AcceptApiChanges.ps1](../tree/develop/AcceptApiChanges.ps1) or [AcceptApiChanges.sh](../tree/develop/AcceptApiChanges.sh). * [ ] If the PR affects [the documentation](../tree/develop/docs/_pages), please include your changes in this pull request so the documentation will appear on the [website](https://www.fluentassertions.com/introduction). * [ ] Please also run `./build.sh --target spellcheck` or `.\build.ps1 --target spellcheck` before pushing and check the good outcome + +## CONTRIBUTOR LICENSE GRANT + +By submitting this contribution, the contributor hereby irrevocably grants to the project owners and maintainers a perpetual, worldwide, royalty-free, irrevocable license to use, reproduce, modify, distribute, sublicense, and create derivative works of the contribution for any purpose and under any terms, including proprietary licensing. + +The contributor waives any moral rights in the contribution to the extent permitted by law and agrees not to assert any claim of authorship or control over the contribution. The contributor represents that they are the sole author of the contribution and that it is provided free of any third-party claims. + +The contributor understands and agrees that the maintainers may, at their sole discretion, use, license, or redistribute the contribution as part of any work and under any terms they choose, without further permission or attribution. + +* [ ] I have read the Contributor License Grant and accept the conditions +* [ ] I'm interested in a free license for Fluent Assertions and will share my email address through sales@xceed.com \ No newline at end of file diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index e743e206d..301d4fdb4 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -18,7 +18,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - name: 'Qodana Scan' - uses: JetBrains/qodana-action@v2024.2 + uses: JetBrains/qodana-action@v2025.1 with: upload-result: ${{ github.ref_name == 'main' || github.ref_name == 'develop' }} args: --baseline,qodana.sarif.json,--ide,QDNET diff --git a/Src/FluentAssertions/Collections/GenericCollectionAssertions.cs b/Src/FluentAssertions/Collections/GenericCollectionAssertions.cs index 908a8bfad..43de5f4a8 100644 --- a/Src/FluentAssertions/Collections/GenericCollectionAssertions.cs +++ b/Src/FluentAssertions/Collections/GenericCollectionAssertions.cs @@ -3050,8 +3050,6 @@ public AndConstraint AllSatisfy(Action expected, [StringSyntax(" chain => chain .FailWithPreFormatted(failureMessage)); } - - return new AndConstraint((TAssertions)this); } return new AndConstraint((TAssertions)this); diff --git a/Src/FluentAssertions/Equivalency/Selection/ExcludeMembersByNameSelectionRule.cs b/Src/FluentAssertions/Equivalency/Selection/ExcludeMembersByNameSelectionRule.cs new file mode 100644 index 000000000..d9ff233fc --- /dev/null +++ b/Src/FluentAssertions/Equivalency/Selection/ExcludeMembersByNameSelectionRule.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Linq; + +namespace FluentAssertions.Equivalency.Selection; + +/// +/// Represents a member selection rule that excludes certain fields or properties from being considered during +/// structural equality checks based on their names. +/// +internal class ExcludeMembersByNameSelectionRule : IMemberSelectionRule +{ + private readonly string[] membersToExclude; + private readonly string description; + + /// + /// Initializes the rule with a list of filed or property names to exclude from the structural equality check. + /// + public ExcludeMembersByNameSelectionRule(string[] membersToExclude) + { + this.membersToExclude = membersToExclude; + description = string.Join(", ", membersToExclude); + } + + public bool IncludesMembers => false; + + public IEnumerable SelectMembers(INode currentNode, IEnumerable selectedMembers, + MemberSelectionContext context) + { + return selectedMembers.Where(m => !membersToExclude.Contains(m.Expectation.Name)).ToArray(); + } + + /// + /// 2 + public override string ToString() + { + return "Exclude members named: " + description; + } +} diff --git a/Src/FluentAssertions/Equivalency/SelfReferenceEquivalencyOptions.cs b/Src/FluentAssertions/Equivalency/SelfReferenceEquivalencyOptions.cs index be199b415..5bf49e595 100644 --- a/Src/FluentAssertions/Equivalency/SelfReferenceEquivalencyOptions.cs +++ b/Src/FluentAssertions/Equivalency/SelfReferenceEquivalencyOptions.cs @@ -275,6 +275,7 @@ public TSelf IncludingProperties() { includedProperties = MemberVisibility.Public | MemberVisibility.ExplicitlyImplemented | MemberVisibility.DefaultInterfaceProperties; + return (TSelf)this; } @@ -285,6 +286,7 @@ public TSelf IncludingInternalProperties() { includedProperties = MemberVisibility.Public | MemberVisibility.Internal | MemberVisibility.ExplicitlyImplemented | MemberVisibility.DefaultInterfaceProperties; + return (TSelf)this; } @@ -300,6 +302,18 @@ public TSelf ExcludingProperties() return (TSelf)this; } + /// + /// Excludes the specified member(s) from the structural equality check anywhere in the object graph. + /// + public TSelf ExcludingMembersNamed(params string[] memberNames) + { + Guard.ThrowIfArgumentIsNull(memberNames, nameof(memberNames), "Member names cannot be null."); + Guard.ThrowIfArgumentIsEmpty(memberNames, nameof(memberNames), "At least one member name must be specified."); + + AddSelectionRule(new ExcludeMembersByNameSelectionRule(memberNames)); + return (TSelf)this; + } + /// /// Excludes properties that are explicitly implemented from the equivalency comparison. /// diff --git a/Src/FluentAssertions/Formatting/LineCollection.cs b/Src/FluentAssertions/Formatting/LineCollection.cs index ec07978a1..7abde5c7c 100644 --- a/Src/FluentAssertions/Formatting/LineCollection.cs +++ b/Src/FluentAssertions/Formatting/LineCollection.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using FluentAssertions.Execution; diff --git a/Src/FluentAssertions/Formatting/XElementValueFormatter.cs b/Src/FluentAssertions/Formatting/XElementValueFormatter.cs index 953fea747..3d34495f3 100644 --- a/Src/FluentAssertions/Formatting/XElementValueFormatter.cs +++ b/Src/FluentAssertions/Formatting/XElementValueFormatter.cs @@ -48,6 +48,6 @@ private static string FormatElementWithChildren(XElement element) private static string[] SplitIntoSeparateLines(XElement element) { string formattedXml = element.ToString(); - return formattedXml.Split(Environment.NewLine, StringSplitOptions.None); + return formattedXml.Split(Environment.NewLine); } } diff --git a/Src/FluentAssertions/Primitives/StringWildcardMatchingStrategy.cs b/Src/FluentAssertions/Primitives/StringWildcardMatchingStrategy.cs index d545ce52a..ce93197ef 100644 --- a/Src/FluentAssertions/Primitives/StringWildcardMatchingStrategy.cs +++ b/Src/FluentAssertions/Primitives/StringWildcardMatchingStrategy.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; using System.Text.RegularExpressions; using FluentAssertions.Common; diff --git a/Src/FluentAssertions/Specialized/AsyncFunctionAssertions.cs b/Src/FluentAssertions/Specialized/AsyncFunctionAssertions.cs index 6f5d0cc81..6f6d2e883 100644 --- a/Src/FluentAssertions/Specialized/AsyncFunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/AsyncFunctionAssertions.cs @@ -112,6 +112,22 @@ public async Task> ThrowExactlyAsync return new ExceptionAssertions([], assertionChain); } + /// + /// Asserts that the current throws any exception. + /// + /// + /// (Optional) 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. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public async Task> ThrowAsync( + [StringSyntax("CompositeFormat")] string because = "", params object[] becauseArgs) + { + return await ThrowAsync(because, becauseArgs); + } + /// /// Asserts that the current throws an exception of type . /// @@ -141,6 +157,26 @@ public async Task> ThrowAsync( return new ExceptionAssertions([], assertionChain); } + /// + /// Asserts that the current throws any exception within a specific timeout. + /// + /// + /// The allowed time span for the operation. + /// + /// + /// (Optional) + /// 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. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public async Task> ThrowWithinAsync(TimeSpan timeSpan, + [StringSyntax("CompositeFormat")] string because = "", params object[] becauseArgs) + { + return await ThrowWithinAsync(timeSpan, because, becauseArgs); + } + /// /// Asserts that the current throws an exception of type /// within a specific timeout. diff --git a/Src/FluentAssertions/Specialized/DelegateAssertions.cs b/Src/FluentAssertions/Specialized/DelegateAssertions.cs index f10a4b588..b0586629b 100644 --- a/Src/FluentAssertions/Specialized/DelegateAssertions.cs +++ b/Src/FluentAssertions/Specialized/DelegateAssertions.cs @@ -30,6 +30,22 @@ private protected DelegateAssertions(TDelegate @delegate, IExtractExceptions ext this.assertionChain = assertionChain; } + /// + /// Asserts that the current throws any exception. + /// + /// + /// (Optional) + /// 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. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public ExceptionAssertions Throw([StringSyntax("CompositeFormat")] string because = "", params object[] becauseArgs) + { + return Throw(because, becauseArgs); + } + /// /// Asserts that the current throws an exception of type . /// diff --git a/Src/FluentAssertions/Streams/BufferedStreamAssertions.cs b/Src/FluentAssertions/Streams/BufferedStreamAssertions.cs index 58b5d2095..1073684a4 100644 --- a/Src/FluentAssertions/Streams/BufferedStreamAssertions.cs +++ b/Src/FluentAssertions/Streams/BufferedStreamAssertions.cs @@ -1,7 +1,9 @@ using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using FluentAssertions.Execution; +#if NET6_0_OR_GREATER || NETSTANDARD2_1 +using System.Diagnostics.CodeAnalysis; +#endif namespace FluentAssertions.Streams; diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net47.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net47.verified.txt index a27b801a9..e54ea43a3 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net47.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net47.verified.txt @@ -911,6 +911,7 @@ namespace FluentAssertions.Equivalency public TSelf Excluding(System.Linq.Expressions.Expression> predicate) { } public TSelf ExcludingExplicitlyImplementedProperties() { } public TSelf ExcludingFields() { } + public TSelf ExcludingMembersNamed(params string[] memberNames) { } public TSelf ExcludingMissingMembers() { } public TSelf ExcludingNonBrowsableMembers() { } public TSelf ExcludingProperties() { } @@ -2090,10 +2091,12 @@ namespace FluentAssertions.Specialized public System.Threading.Tasks.Task> NotCompleteWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> NotThrowAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public System.Threading.Tasks.Task> ThrowAsync(string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> ThrowAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } public System.Threading.Tasks.Task> ThrowExactlyAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public System.Threading.Tasks.Task> ThrowWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> ThrowWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) where TException : System.Exception { } } @@ -2115,6 +2118,7 @@ namespace FluentAssertions.Specialized protected abstract void InvokeSubject(); public FluentAssertions.AndConstraint NotThrow(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public FluentAssertions.Specialized.ExceptionAssertions Throw(string because = "", params object[] becauseArgs) { } public FluentAssertions.Specialized.ExceptionAssertions Throw(string because = "", params object[] becauseArgs) where TException : System.Exception { } public FluentAssertions.Specialized.ExceptionAssertions ThrowExactly(string because = "", params object[] becauseArgs) diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net6.0.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net6.0.verified.txt index 399891910..0aa96806b 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net6.0.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net6.0.verified.txt @@ -924,6 +924,7 @@ namespace FluentAssertions.Equivalency public TSelf Excluding(System.Linq.Expressions.Expression> predicate) { } public TSelf ExcludingExplicitlyImplementedProperties() { } public TSelf ExcludingFields() { } + public TSelf ExcludingMembersNamed(params string[] memberNames) { } public TSelf ExcludingMissingMembers() { } public TSelf ExcludingNonBrowsableMembers() { } public TSelf ExcludingProperties() { } @@ -2211,10 +2212,12 @@ namespace FluentAssertions.Specialized public System.Threading.Tasks.Task> NotCompleteWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> NotThrowAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public System.Threading.Tasks.Task> ThrowAsync(string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> ThrowAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } public System.Threading.Tasks.Task> ThrowExactlyAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public System.Threading.Tasks.Task> ThrowWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> ThrowWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) where TException : System.Exception { } } @@ -2236,6 +2239,7 @@ namespace FluentAssertions.Specialized protected abstract void InvokeSubject(); public FluentAssertions.AndConstraint NotThrow(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public FluentAssertions.Specialized.ExceptionAssertions Throw(string because = "", params object[] becauseArgs) { } public FluentAssertions.Specialized.ExceptionAssertions Throw(string because = "", params object[] becauseArgs) where TException : System.Exception { } public FluentAssertions.Specialized.ExceptionAssertions ThrowExactly(string because = "", params object[] becauseArgs) diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.0.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.0.verified.txt index acbf851e3..217fcf880 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.0.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.0.verified.txt @@ -903,6 +903,7 @@ namespace FluentAssertions.Equivalency public TSelf Excluding(System.Linq.Expressions.Expression> predicate) { } public TSelf ExcludingExplicitlyImplementedProperties() { } public TSelf ExcludingFields() { } + public TSelf ExcludingMembersNamed(params string[] memberNames) { } public TSelf ExcludingMissingMembers() { } public TSelf ExcludingNonBrowsableMembers() { } public TSelf ExcludingProperties() { } @@ -2034,10 +2035,12 @@ namespace FluentAssertions.Specialized public System.Threading.Tasks.Task> NotCompleteWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> NotThrowAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public System.Threading.Tasks.Task> ThrowAsync(string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> ThrowAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } public System.Threading.Tasks.Task> ThrowExactlyAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public System.Threading.Tasks.Task> ThrowWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> ThrowWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) where TException : System.Exception { } } @@ -2059,6 +2062,7 @@ namespace FluentAssertions.Specialized protected abstract void InvokeSubject(); public FluentAssertions.AndConstraint NotThrow(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public FluentAssertions.Specialized.ExceptionAssertions Throw(string because = "", params object[] becauseArgs) { } public FluentAssertions.Specialized.ExceptionAssertions Throw(string because = "", params object[] becauseArgs) where TException : System.Exception { } public FluentAssertions.Specialized.ExceptionAssertions ThrowExactly(string because = "", params object[] becauseArgs) diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.1.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.1.verified.txt index 44fb44ddd..a380bf182 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.1.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.1.verified.txt @@ -911,6 +911,7 @@ namespace FluentAssertions.Equivalency public TSelf Excluding(System.Linq.Expressions.Expression> predicate) { } public TSelf ExcludingExplicitlyImplementedProperties() { } public TSelf ExcludingFields() { } + public TSelf ExcludingMembersNamed(params string[] memberNames) { } public TSelf ExcludingMissingMembers() { } public TSelf ExcludingNonBrowsableMembers() { } public TSelf ExcludingProperties() { } @@ -2090,10 +2091,12 @@ namespace FluentAssertions.Specialized public System.Threading.Tasks.Task> NotCompleteWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> NotThrowAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public System.Threading.Tasks.Task> ThrowAsync(string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> ThrowAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } public System.Threading.Tasks.Task> ThrowExactlyAsync(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public System.Threading.Tasks.Task> ThrowWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) { } public System.Threading.Tasks.Task> ThrowWithinAsync(System.TimeSpan timeSpan, string because = "", params object[] becauseArgs) where TException : System.Exception { } } @@ -2115,6 +2118,7 @@ namespace FluentAssertions.Specialized protected abstract void InvokeSubject(); public FluentAssertions.AndConstraint NotThrow(string because = "", params object[] becauseArgs) where TException : System.Exception { } + public FluentAssertions.Specialized.ExceptionAssertions Throw(string because = "", params object[] becauseArgs) { } public FluentAssertions.Specialized.ExceptionAssertions Throw(string because = "", params object[] becauseArgs) where TException : System.Exception { } public FluentAssertions.Specialized.ExceptionAssertions ThrowExactly(string because = "", params object[] becauseArgs) diff --git a/Tests/FluentAssertions.Equivalency.Specs/SelectionRulesSpecs.Excluding.cs b/Tests/FluentAssertions.Equivalency.Specs/SelectionRulesSpecs.Excluding.cs index 3413bcf74..44b8686a8 100644 --- a/Tests/FluentAssertions.Equivalency.Specs/SelectionRulesSpecs.Excluding.cs +++ b/Tests/FluentAssertions.Equivalency.Specs/SelectionRulesSpecs.Excluding.cs @@ -685,7 +685,8 @@ public void Abstract_properties_cannot_be_excluded() Action act = () => obj1.Should().BeEquivalentTo(obj2, opt => opt .Excluding(o => o.AbstractProperty + "B")); - act.Should().Throw().WithMessage("*(o.AbstractProperty + \"B\")*cannot be used to select a member*"); + act.Should().Throw() + .WithMessage("*(o.AbstractProperty + \"B\")*cannot be used to select a member*"); } #if NETCOREAPP3_0_OR_GREATER @@ -1156,5 +1157,107 @@ public void An_empty_anonymous_object_excludes_nothing_inside_collections() // Assert act.Should().Throw().WithMessage("*Pets[1].Name*Pets[1].Age*"); } + + [Fact] + public void Can_exclude_root_properties_by_name() + { + // Arrange + var subject = new + { + FirstName = "John", + LastName = "Doe", + Age = 30 + }; + + var expectation = new + { + FirstName = "John", + LastName = "Smith", + Age = 35 + }; + + // Act / Assert + subject.Should().BeEquivalentTo(expectation, options => options + .ExcludingMembersNamed("LastName", "Age")); + } + + [Fact] + public void Can_exclude_properties_deeper_in_the_graph_by_name() + { + // Arrange + var subject = new + { + Person = new + { + FirstName = "John", + LastName = "Doe", + Age = 30 + }, + Address = new + { + Street = "123 Main St", + City = "Anytown", + ZipCode = "12345" + } + }; + + var expectation = new + { + Person = new + { + FirstName = "John", + LastName = "Smith", + Age = 35 + }, + Address = new + { + Street = "123 Main St", + City = "Othertown", + ZipCode = "54321" + } + }; + + // Act / Assert + subject.Should().BeEquivalentTo(expectation, options => options + .ExcludingMembersNamed("LastName", "Age", "City", "ZipCode")); + } + + [Fact] + public void Must_provide_property_names_when_excluding_by_name() + { + // Arrange + var subject = new + { + FirstName = "John", + LastName = "Doe" + }; + + // Act + Action act = () => subject.Should().BeEquivalentTo(subject, options => options + .ExcludingMembersNamed()); + + // Assert + act.Should().Throw() + .WithMessage("*least one*name*"); + } + + [Fact] + public void Cannot_provide_null_as_a_property_name() + { + // Arrange + var subject = new + { + FirstName = "John", + LastName = "Doe" + }; + + // Act + Action act = () => subject.Should().BeEquivalentTo(subject, options => options + .ExcludingMembersNamed(null)); + + // Assert + act.Should().Throw() + .WithMessage("*Member names cannot be null*"); + } } } diff --git a/Tests/FluentAssertions.Specs/Exceptions/AsyncFunctionExceptionAssertionSpecs.cs b/Tests/FluentAssertions.Specs/Exceptions/AsyncFunctionExceptionAssertionSpecs.cs index 66bcf91d7..6617d0b65 100644 --- a/Tests/FluentAssertions.Specs/Exceptions/AsyncFunctionExceptionAssertionSpecs.cs +++ b/Tests/FluentAssertions.Specs/Exceptions/AsyncFunctionExceptionAssertionSpecs.cs @@ -936,7 +936,21 @@ public async Task When_async_method_throws_aggregate_exception_containing_expect } [Fact] - public async Task When_async_method_throws_the_expected_exception_it_should_succeed() + public async Task Succeeds_for_any_exception_thrown_by_async_method() + { + // Arrange + Func task = () => Throw.Async(); + + // Act + Func action = () => task + .Should().ThrowAsync(); + + // Assert + await action.Should().NotThrowAsync(); + } + + [Fact] + public async Task Succeeds_for_expected_exception_thrown_by_async_method() { // Arrange Func task = () => Throw.Async(); @@ -949,6 +963,20 @@ public async Task When_async_method_throws_the_expected_exception_it_should_succ await action.Should().NotThrowAsync(); } + [Fact] + public async Task Succeeds_for_any_exception_thrown_within_timespan_by_async_method() + { + // Arrange + Func task = () => Throw.Async(); + + // Act + Func action = () => task.Should().ThrowWithinAsync( + 100.Milliseconds()); + + // Assert + await action.Should().NotThrowAsync(); + } + [Fact] public async Task When_async_method_does_not_throw_the_expected_inner_exception_it_should_fail() { diff --git a/Tests/FluentAssertions.Specs/Exceptions/ThrowAssertionsSpecs.cs b/Tests/FluentAssertions.Specs/Exceptions/ThrowAssertionsSpecs.cs index b56825373..ae93bd1eb 100644 --- a/Tests/FluentAssertions.Specs/Exceptions/ThrowAssertionsSpecs.cs +++ b/Tests/FluentAssertions.Specs/Exceptions/ThrowAssertionsSpecs.cs @@ -7,7 +7,17 @@ namespace FluentAssertions.Specs.Exceptions; public class ThrowAssertionsSpecs { [Fact] - public void When_subject_throws_expected_exception_it_should_not_do_anything() + public void Succeeds_for_any_exception_thrown_by_subject() + { + // Arrange + Does testSubject = Does.Throw(); + + // Act / Assert + testSubject.Invoking(x => x.Do()).Should().Throw(); + } + + [Fact] + public void Succeeds_for_expected_exception_thrown_by_subject() { // Arrange Does testSubject = Does.Throw(); @@ -17,7 +27,17 @@ public void When_subject_throws_expected_exception_it_should_not_do_anything() } [Fact] - public void When_func_throws_expected_exception_it_should_not_do_anything() + public void Succeeds_for_any_exception_thrown_by_func() + { + // Arrange + Does testSubject = Does.Throw(); + + // Act / Assert + testSubject.Invoking(x => x.Return()).Should().Throw(); + } + + [Fact] + public void Succeeds_for_expected_exception_thrown_by_func() { // Arrange Does testSubject = Does.Throw(); @@ -27,7 +47,17 @@ public void When_func_throws_expected_exception_it_should_not_do_anything() } [Fact] - public void When_action_throws_expected_exception_it_should_not_do_anything() + public void Succeeds_for_any_exception_thrown_by_action() + { + // Arrange + var act = new Action(() => throw new InvalidOperationException("Some exception")); + + // Act / Assert + act.Should().Throw(); + } + + [Fact] + public void Succeeds_for_expected_exception_thrown_by_action() { // Arrange var act = new Action(() => throw new InvalidOperationException("Some exception")); diff --git a/Tests/FluentAssertions.Specs/Xml/XmlNodeFormatterSpecs.cs b/Tests/FluentAssertions.Specs/Xml/XmlNodeFormatterSpecs.cs index 9f2ea3fc8..2cbc17d94 100644 --- a/Tests/FluentAssertions.Specs/Xml/XmlNodeFormatterSpecs.cs +++ b/Tests/FluentAssertions.Specs/Xml/XmlNodeFormatterSpecs.cs @@ -1,5 +1,4 @@ -using System; -using System.Xml; +using System.Xml; using FluentAssertions.Formatting; using Xunit; diff --git a/docs/_pages/objectgraphs.md b/docs/_pages/objectgraphs.md index f0756e45f..04d077606 100644 --- a/docs/_pages/objectgraphs.md +++ b/docs/_pages/objectgraphs.md @@ -123,6 +123,13 @@ orderDto.Should().BeEquivalentTo(order, options => options .Excluding(ctx => ctx.Path == "Level.Level.Text")); ``` +And if you want to exclude one or more specific properties everywhere in the object graph just by their names, use `ExcludingMembersNamed` like this: + +```csharp +orderDto.Should().BeEquivalentTo(order, options => options + .ExcludingMembersNamed("ID", "Version")); +``` + Maybe far-fetched, but you may even decide to exclude a member on a particular nested object by its index. ```csharp diff --git a/docs/_pages/releases.md b/docs/_pages/releases.md index b7013598b..e9aa3856e 100644 --- a/docs/_pages/releases.md +++ b/docs/_pages/releases.md @@ -7,6 +7,13 @@ sidebar: nav: "sidebar" --- +## 8.4.0 + +## Enhancements + +* Added `ExcludingMembersNamed` to `BeEquivalentTo` to exclude fields and properties anywhere in the graph - [3062](https://github.com/fluentassertions/fluentassertions/pull/3062) +* Added `Should().Throw()`, `ThrowAsync()` and `ThrowWithinAsync()` flavors that don’t require a specific exception type - [3059](https://github.com/fluentassertions/fluentassertions/pull/3059) + ## 8.3.0 ## Enhancements @@ -18,7 +25,7 @@ sidebar: ## Fixes -* Fixed a regression from 8.1.0 where a `NullReferenceException` was thrown during subject identification - [#3036](https://github.com/fluentassertions/fluentassertions/pull/3036 +* Fixed a regression from 8.1.0 where a `NullReferenceException` was thrown during subject identification - [#3036](https://github.com/fluentassertions/fluentassertions/pull/3036) ## Enhancements diff --git a/package-lock.json b/package-lock.json index bc528e8a7..2321e9b67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,13 +7,13 @@ "": { "version": "1.0.1", "dependencies": { - "cspell": "^9.0.1" + "cspell": "^9.1.1" } }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.0.1.tgz", - "integrity": "sha512-h7gTqg0VF4N8VhOPk66XewuSsT56OP2ujgxtAyYQ4H+NuYd3HMfS0h/I3/y9uBhllwOEamaeAzYhc5JF/qIrsQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.1.1.tgz", + "integrity": "sha512-AbaIez18Puo9SbnhYsZnzG90ohelWWFQVbEIdtwMmRRItoIevF8wcNkQrFeFCXINs+FZH+aDGkt7oA1dwKgJFA==", "license": "MIT", "dependencies": { "@cspell/dict-ada": "^4.1.0", @@ -31,33 +31,33 @@ "@cspell/dict-docker": "^1.1.14", "@cspell/dict-dotnet": "^5.0.9", "@cspell/dict-elixir": "^4.0.7", - "@cspell/dict-en_us": "^4.4.8", - "@cspell/dict-en-common-misspellings": "^2.0.11", - "@cspell/dict-en-gb-mit": "^3.0.6", + "@cspell/dict-en_us": "^4.4.11", + "@cspell/dict-en-common-misspellings": "^2.1.1", + "@cspell/dict-en-gb-mit": "^3.1.1", "@cspell/dict-filetypes": "^3.0.12", "@cspell/dict-flutter": "^1.1.0", "@cspell/dict-fonts": "^4.0.4", "@cspell/dict-fsharp": "^1.1.0", "@cspell/dict-fullstack": "^3.2.6", "@cspell/dict-gaming-terms": "^1.1.1", - "@cspell/dict-git": "^3.0.4", - "@cspell/dict-golang": "^6.0.21", + "@cspell/dict-git": "^3.0.6", + "@cspell/dict-golang": "^6.0.22", "@cspell/dict-google": "^1.0.8", "@cspell/dict-haskell": "^4.0.5", "@cspell/dict-html": "^4.0.11", "@cspell/dict-html-symbol-entities": "^4.0.3", "@cspell/dict-java": "^5.0.11", "@cspell/dict-julia": "^1.1.0", - "@cspell/dict-k8s": "^1.0.10", + "@cspell/dict-k8s": "^1.0.11", "@cspell/dict-kotlin": "^1.1.0", "@cspell/dict-latex": "^4.0.3", "@cspell/dict-lorem-ipsum": "^4.0.4", "@cspell/dict-lua": "^4.0.7", "@cspell/dict-makefile": "^1.0.4", - "@cspell/dict-markdown": "^2.0.10", + "@cspell/dict-markdown": "^2.0.11", "@cspell/dict-monkeyc": "^1.0.10", "@cspell/dict-node": "^5.0.7", - "@cspell/dict-npm": "^5.2.3", + "@cspell/dict-npm": "^5.2.6", "@cspell/dict-php": "^4.0.14", "@cspell/dict-powershell": "^5.0.14", "@cspell/dict-public-licenses": "^2.0.13", @@ -67,12 +67,12 @@ "@cspell/dict-rust": "^4.0.11", "@cspell/dict-scala": "^5.0.7", "@cspell/dict-shell": "^1.1.0", - "@cspell/dict-software-terms": "^5.0.8", + "@cspell/dict-software-terms": "^5.1.0", "@cspell/dict-sql": "^2.2.0", "@cspell/dict-svelte": "^1.0.6", "@cspell/dict-swift": "^2.0.5", "@cspell/dict-terraform": "^1.1.1", - "@cspell/dict-typescript": "^3.2.1", + "@cspell/dict-typescript": "^3.2.2", "@cspell/dict-vue": "^3.0.4" }, "engines": { @@ -80,30 +80,30 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.0.1.tgz", - "integrity": "sha512-Rpn7Tuq9t8bZpXZFV43NkhCl0LaPDJZSON4/JFxGbOcH16ryXfrx7oObUTIIyxSxO3fGkzaJZHIwGibRJSsbNQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.1.1.tgz", + "integrity": "sha512-bvbBXr77yz0xu/6GckWMWoUyjSL5MqF86y7g0DkGnNpB5Bu5fCNAltR5yNo1xlBCtbUwB0zrlPENSSxRmNpPCA==", "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.0.1" + "@cspell/cspell-types": "9.1.1" }, "engines": { "node": ">=20" } }, "node_modules/@cspell/cspell-pipe": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.0.1.tgz", - "integrity": "sha512-bhFcvF2a8KYKVh/OebCfJ8LFw5GYHyUsUjAbxnznTBrYOFSIclDjwUwT29yVDXwnQkJkB6Px5Y9e2VvtFizVFg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.1.1.tgz", + "integrity": "sha512-WFh6+Fig//8Ev8mxBHjKiKhYfJHez5JyI2ioWBgh16EL08k5kfqIsANX8/ij+k0QvfObA4J4LRJ6RUoExvD+4g==", "license": "MIT", "engines": { "node": ">=20" } }, "node_modules/@cspell/cspell-resolver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.0.1.tgz", - "integrity": "sha512-AhIXAhX1qt7Y3EyiP/5rAk7Ow7DJpAyB44wPbfdF9p1vhnk6oQ7RslnD3G6S9o/vNxZ0DWFPREMWx19J/3c+hw==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.1.1.tgz", + "integrity": "sha512-nnHE6ZA4tGA0jU1Yco6OuXUwPvFqHrWqMwvbmOHRLPZRLrtbqKUQGxUuSHlM3aGLHBfaPZSZqBl5rvGyj2EX1Q==", "license": "MIT", "dependencies": { "global-directory": "^4.0.1" @@ -113,18 +113,18 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.0.1.tgz", - "integrity": "sha512-DoW6hLkFIO3BXePtUYQEax3FTH9fkwCUbf6qphAEXnr4PjoyPZsgBhR6iCrZd4DyhuFiRvK3Cgpq2o3O0NdODQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.1.1.tgz", + "integrity": "sha512-0eFZe4dsEaETsNsqcFilWwfi2VRHRxldSkNZFGXf/QbamSK89VNf0X/q9CtAU90PVgJAzYevV2r6uyWX2poZpQ==", "license": "MIT", "engines": { "node": ">=20" } }, "node_modules/@cspell/cspell-types": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.0.1.tgz", - "integrity": "sha512-8FRmvyV1AYEepJB3J7jji1ZYG9yOK0eYr4WuUVPfUJa6N3HyeZjWKhxbVvqedmEI74f5Ls3cQKHY1T2Yvqk/ag==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.1.1.tgz", + "integrity": "sha512-xouQmxgAuEz+jnmyzQV6LoAKzwTt/wF1xjRgVW1ssMFDlRGPtvEOmfk3yk79Ror0AnHmA5O1xXpFQ/VgFU56MQ==", "license": "MIT", "engines": { "node": ">=20" @@ -224,21 +224,21 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.8.tgz", - "integrity": "sha512-OkNUVuU9Q+Sf827/61YPkk6ya6dSsllzeYniBFqNW9TkoqQXT3vggkgmtCE1aEhSvVctMwxpPYoC8pZgn1TeSA==", + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.11.tgz", + "integrity": "sha512-ls3ASwIL0uuAEXsxB7NsIe6GRBQ+NZfqI5k1qtNgOZ1eh1MFYjCiF+YcqArH5SFHNzOwCHRKzlLeX0ZFIok7GQ==", "license": "MIT" }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.11.tgz", - "integrity": "sha512-xFQjeg0wFHh9sFhshpJ+5BzWR1m9Vu8pD0CGPkwZLK9oii8AD8RXNchabLKy/O5VTLwyqPOi9qpyp1cxm3US4Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.1.1.tgz", + "integrity": "sha512-6m2EEm4WUgsNzFzz/2boeOVrZenYQRaDXFtDNcaQK5Ly4A37HTRPm8uVvE8cAlACVk+HBHhH/4e7ebxdXwId9w==", "license": "CC BY-SA 4.0" }, "node_modules/@cspell/dict-en-gb-mit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.0.6.tgz", - "integrity": "sha512-QYDwuXi9Yh+AvU1omhz8sWX+A1SxWI3zeK1HdGfTrICZavhp8xxcQGTa5zxTTFRCcQc483YzUH2Dl+6Zd50tJg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.1.tgz", + "integrity": "sha512-sZbuOPlAGDwudoquXjaSA+TbJEzfG0MkUeF4Iz3tdL9xOYDb6lgueNVnDJfBrw6jrKKDdOI68MJqiLjW4uth8A==", "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { @@ -278,15 +278,15 @@ "license": "MIT" }, "node_modules/@cspell/dict-git": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.4.tgz", - "integrity": "sha512-C44M+m56rYn6QCsLbiKiedyPTMZxlDdEYAsPwwlL5bhMDDzXZ3Ic8OCQIhMbiunhCOJJT+er4URmOmM+sllnjg==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.6.tgz", + "integrity": "sha512-nazfOqyxlBOQGgcur9ssEOEQCEZkH8vXfQe8SDEx8sCN/g0SFm8ktabgLVmBOXjy3RzjVNLlM2nBfRQ7e6+5hQ==", "license": "MIT" }, "node_modules/@cspell/dict-golang": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.21.tgz", - "integrity": "sha512-D3wG1MWhFx54ySFJ00CS1MVjR4UiBVsOWGIjJ5Av+HamnguqEshxbF9mvy+BX0KqzdLVzwFkoLBs8QeOID56HA==", + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.22.tgz", + "integrity": "sha512-FvV0m3Y0nUFxw36uDCD8UtfOPv4wsZnnlabNwB3xNZ2IBn0gBURuMUZywScb9sd2wXM8VFBRoU//tc6NQsOVOg==", "license": "MIT" }, "node_modules/@cspell/dict-google": { @@ -326,9 +326,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-k8s": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.10.tgz", - "integrity": "sha512-313haTrX9prep1yWO7N6Xw4D6tvUJ0Xsx+YhCP+5YrrcIKoEw5Rtlg8R4PPzLqe6zibw6aJ+Eqq+y76Vx5BZkw==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.11.tgz", + "integrity": "sha512-8ojNwB5j4PfZ1Gq9n5c/HKJCtZD3h6+wFy+zpALpDWFFQ2qT22Be30+3PVd+G5gng8or0LeK8VgKKd0l1uKPTA==", "license": "MIT" }, "node_modules/@cspell/dict-kotlin": { @@ -362,15 +362,15 @@ "license": "MIT" }, "node_modules/@cspell/dict-markdown": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.10.tgz", - "integrity": "sha512-vtVa6L/84F9sTjclTYDkWJF/Vx2c5xzxBKkQp+CEFlxOF2SYgm+RSoEvAvg5vj4N5kuqR4350ZlY3zl2eA3MXw==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.11.tgz", + "integrity": "sha512-stZieFKJyMQbzKTVoalSx2QqCpB0j8nPJF/5x+sBnDIWgMC65jp8Wil+jccWh9/vnUVukP3Ejewven5NC7SWuQ==", "license": "MIT", "peerDependencies": { "@cspell/dict-css": "^4.0.17", "@cspell/dict-html": "^4.0.11", "@cspell/dict-html-symbol-entities": "^4.0.3", - "@cspell/dict-typescript": "^3.2.1" + "@cspell/dict-typescript": "^3.2.2" } }, "node_modules/@cspell/dict-monkeyc": { @@ -386,9 +386,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.3.tgz", - "integrity": "sha512-EdGkCpAq66Mhi9Qldgsr+NvPVL4TdtmdlqDe4VBp0P3n6J0B7b0jT1MlVDIiLR+F1eqBfL0qjfHf0ey1CafeNw==", + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.6.tgz", + "integrity": "sha512-VGEY1ZjE8c8JCA+dic1IdYmVTNfVtWAw7V2n4TXO1+mKfRL+BsPsqEoH8iR0OMutC9QXjVNh32rzMh4D3E+Lxw==", "license": "MIT" }, "node_modules/@cspell/dict-php": { @@ -449,9 +449,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.0.8.tgz", - "integrity": "sha512-VsJesitvaHZpMgNwHHms3yDsZz7LNToC2HuSAnyt1znn37ribiJF1ty0jWhVQO6fv7K4PM1KsKTJIwqBwc446g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.1.0.tgz", + "integrity": "sha512-8zsOVzcHpb4PAaKtOWAIJRbpaNINaUZRsHzqFb3K9hQIC6hxmet/avLlCeKdnmBVZkn3TmRN5caxTJamJvbXww==", "license": "MIT" }, "node_modules/@cspell/dict-sql": { @@ -479,9 +479,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-typescript": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.1.tgz", - "integrity": "sha512-jdnKg4rBl75GUBTsUD6nTJl7FGvaIt5wWcWP7TZSC3rV1LfkwvbUiY3PiGpfJlAIdnLYSeFWIpYU9gyVgz206w==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.2.tgz", + "integrity": "sha512-H9Y+uUHsTIDFO/jdfUAcqmcd5osT+2DB5b0aRCHfLWN/twUbGn/1qq3b7YwEvttxKlYzWHU3uNFf+KfA93VY7w==", "license": "MIT" }, "node_modules/@cspell/dict-vue": { @@ -491,12 +491,12 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.0.1.tgz", - "integrity": "sha512-BoWzHwkufo90ubMZUN8Jy4HQYYWFW7psVCdG/4RUgfvVnazkPfLxWBbsPQsLrlIP0utaqei7D9FU0K7r7mpl4A==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.1.1.tgz", + "integrity": "sha512-jcg5Wti4kcPh4Deds009MEZvuN3tViUft079MTsdSpNPNhRf/gKwSIQnkda9g4ppsVPh5mxkE0nUZLxfZRZYMg==", "license": "MIT", "dependencies": { - "@cspell/url": "9.0.1", + "@cspell/url": "9.1.1", "import-meta-resolve": "^4.1.0" }, "engines": { @@ -504,27 +504,27 @@ } }, "node_modules/@cspell/filetypes": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.0.1.tgz", - "integrity": "sha512-swZu3ra2AueyjEz/bPsvwFuHGYhjWZBx1K9FSvZA/yDIX5RVr6orQSuf9zvXNFui6Nyk0tudLnn3y9jT0LHk8A==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.1.1.tgz", + "integrity": "sha512-kQ1mD+hPxh8KRbDtPvCb6nuODwJV26W43sC77I5Vpk+IDXZqxEhkTCXB6OefnfplOl6+wU0e/EAw+7XYtlKjfg==", "license": "MIT", "engines": { "node": ">=20" } }, "node_modules/@cspell/strong-weak-map": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.0.1.tgz", - "integrity": "sha512-u87PWr1xACqs/F3HibZ4Eb0Za/ghWIa6WLvEKV9OaiLfEUQuczbrXPVgHmGr83H0XXWUKy8FvVbWGFmXwiw+gQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.1.1.tgz", + "integrity": "sha512-D9dDws2MmE24zxkT9TcxYzOAiZncllgcfAGVswklM+dpQeHyZgRDPpdjVhz+nrYrwVwTbdWlRNJ9RiwzRN+jpA==", "license": "MIT", "engines": { "node": ">=20" } }, "node_modules/@cspell/url": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.0.1.tgz", - "integrity": "sha512-8xaLrsQ742dmwXwS6tjreps3NpSQe6WEZFPQQT2DprVJXGZnfQR8ob0c+kPhD0hu9A6PwShJsRsfh3DQGKCqAw==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.1.1.tgz", + "integrity": "sha512-/RL/QTcaFBr0UGl6uLc9d2kPCEpqWHmBs8uFRnBottJ3I5tMOiaVtkEKFTx5FIxrlWTjZwW3rWaIUspNX5ejUw==", "license": "MIT", "engines": { "node": ">=20" @@ -588,12 +588,12 @@ } }, "node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/comment-json": { @@ -619,28 +619,29 @@ "license": "MIT" }, "node_modules/cspell": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.0.1.tgz", - "integrity": "sha512-AJqsX+3eSTz9GmIuyEZUzCCTbvCPw6+Nv7UYa4PCn7vNV3XEb5LHTp5i9y2i65fNaeNEcQXLrLYoY/JcBFmUSQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.1.1.tgz", + "integrity": "sha512-srPIS39EzbgRLncBIbsJy3GzYWxrSm0mbXj24XLxZgVBjMps+/uxpVo0aXEFy4JClUSNBoYxhCb+vSHZUoqu3w==", "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "9.0.1", - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-types": "9.0.1", - "@cspell/dynamic-import": "9.0.1", - "@cspell/url": "9.0.1", + "@cspell/cspell-json-reporter": "9.1.1", + "@cspell/cspell-pipe": "9.1.1", + "@cspell/cspell-types": "9.1.1", + "@cspell/dynamic-import": "9.1.1", + "@cspell/url": "9.1.1", "chalk": "^5.4.1", "chalk-template": "^1.1.0", - "commander": "^13.1.0", - "cspell-dictionary": "9.0.1", - "cspell-gitignore": "9.0.1", - "cspell-glob": "9.0.1", - "cspell-io": "9.0.1", - "cspell-lib": "9.0.1", + "commander": "^14.0.0", + "cspell-config-lib": "9.1.1", + "cspell-dictionary": "9.1.1", + "cspell-gitignore": "9.1.1", + "cspell-glob": "9.1.1", + "cspell-io": "9.1.1", + "cspell-lib": "9.1.1", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", - "semver": "^7.7.1", - "tinyglobby": "^0.2.13" + "semver": "^7.7.2", + "tinyglobby": "^0.2.14" }, "bin": { "cspell": "bin.mjs", @@ -654,28 +655,28 @@ } }, "node_modules/cspell-config-lib": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.0.1.tgz", - "integrity": "sha512-hbeyU6cY4NPKh69L4QpBZgGz00f7rLk10xPlCo6MxEmCqSOTuXXvDEUR51d2ED69G+GyFAeZi5VU9IdJ4jhvzQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.1.1.tgz", + "integrity": "sha512-fi/ohH5mIeba416Jl0DREm+A4QssC3OCY8wjze7hAZ9lOzFuuBmyjoo5OD/J48stkCt1pf2TIAAU3up5o/oaBw==", "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.0.1", + "@cspell/cspell-types": "9.1.1", "comment-json": "^4.2.5", - "yaml": "^2.7.1" + "yaml": "^2.8.0" }, "engines": { "node": ">=20" } }, "node_modules/cspell-dictionary": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.0.1.tgz", - "integrity": "sha512-I9gjRpfV4djxN0i2p9OzWIrkjtUaGUyVE9atvRbkHUMeqDUhC2Qt0Mb9tnF8I7qnHeZt+U44vUa9Dg7yrJ+k4Q==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.1.1.tgz", + "integrity": "sha512-VobPhTE/+hMsI5qppKsuljdDkG23av16bNRBR0hA0O/pG07SXZ6nzwWIwdPoKSjiWSGTmmCGXv45W0sn20ahbA==", "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-types": "9.0.1", - "cspell-trie-lib": "9.0.1", + "@cspell/cspell-pipe": "9.1.1", + "@cspell/cspell-types": "9.1.1", + "cspell-trie-lib": "9.1.1", "fast-equals": "^5.2.2" }, "engines": { @@ -683,14 +684,14 @@ } }, "node_modules/cspell-gitignore": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.0.1.tgz", - "integrity": "sha512-xjgOmeGbHEaeF0erRQ2QXwqxWqGDiI4mu+NjCL7ZHPoAM5y8PEO6IbxVNabIB1xC4QAborbtEQ/8ydDWLJcPoQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.1.1.tgz", + "integrity": "sha512-8gx61lyxdAMLulL7Mtb10jOBzL/e3rU34YW0kaTT3LkHBb/LGapmOFKRiJyt2bA/UA6kJkR/wPLmsjUfRJwOmA==", "license": "MIT", "dependencies": { - "@cspell/url": "9.0.1", - "cspell-glob": "9.0.1", - "cspell-io": "9.0.1" + "@cspell/url": "9.1.1", + "cspell-glob": "9.1.1", + "cspell-io": "9.1.1" }, "bin": { "cspell-gitignore": "bin.mjs" @@ -700,12 +701,12 @@ } }, "node_modules/cspell-glob": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.0.1.tgz", - "integrity": "sha512-dQU/ln6J9Qe31zk1cLJnq/WNAjRrTUig1GG8WA2oK1jHZKY9VbyJLb5DUFnDUx35cI0jdOEnGSCWi8qNjHSc1Q==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.1.1.tgz", + "integrity": "sha512-f274mlln/QG/wj12xF/SnvfdUAx0pGjIxnNOYGwRXS1MbaH0B4F9pkhkMqY0GwqAsvPxT6NzJybAoivS4Icvzg==", "license": "MIT", "dependencies": { - "@cspell/url": "9.0.1", + "@cspell/url": "9.1.1", "picomatch": "^4.0.2" }, "engines": { @@ -713,13 +714,13 @@ } }, "node_modules/cspell-grammar": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.0.1.tgz", - "integrity": "sha512-FZ1z1p3pslfotZT/W/VRZjB4S+z0ETrTbNmQ5pGmhdY0nm7Slmg+8nIJluLEjBneBGTJIOcLjYykwS2vI6jzxw==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.1.1.tgz", + "integrity": "sha512-IBOOzmj1z4IWHSis6iGZNbE0syEiT0Rz4NbbHwscCMc30jgbotupscn6T8PhqmDwmlXCW81C4vGSMzqQh0UaLQ==", "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-types": "9.0.1" + "@cspell/cspell-pipe": "9.1.1", + "@cspell/cspell-types": "9.1.1" }, "bin": { "cspell-grammar": "bin.mjs" @@ -729,40 +730,40 @@ } }, "node_modules/cspell-io": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.0.1.tgz", - "integrity": "sha512-L5fZY0glVeQb6nmt1WL1wKzZzoHJUkBQ9BGCrwqSXIrjZrYmBNSKixCjo6o9n2keRUwpNjsvZj1TQDKDV+FsXA==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.1.1.tgz", + "integrity": "sha512-LMzoBvbWqVokrkrnLrdnCzX8Sf77Q42nvj7Q36G4sqZaB3Lr/ih+iZ4t5l90Wlsnst5flrQmIy0YNtndAWzp2A==", "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "9.0.1", - "@cspell/url": "9.0.1" + "@cspell/cspell-service-bus": "9.1.1", + "@cspell/url": "9.1.1" }, "engines": { "node": ">=20" } }, "node_modules/cspell-lib": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.0.1.tgz", - "integrity": "sha512-F4vJG6GmAGVAuhgcepO12UtG7yev7Rcfa31MLIyYNTrd5NeORzM+GTHnL970FlEflwYPYjcSTGwkyowQ+ZbmDg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.1.1.tgz", + "integrity": "sha512-On2m0/UFtsKenEHTfvNA5EoKI5YcnOzgGQF3yX4CllvtGQXCewB5U1TBCqTR/0wckw5q94iqZJDF2oY3GBGBAg==", "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "9.0.1", - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-resolver": "9.0.1", - "@cspell/cspell-types": "9.0.1", - "@cspell/dynamic-import": "9.0.1", - "@cspell/filetypes": "9.0.1", - "@cspell/strong-weak-map": "9.0.1", - "@cspell/url": "9.0.1", + "@cspell/cspell-bundled-dicts": "9.1.1", + "@cspell/cspell-pipe": "9.1.1", + "@cspell/cspell-resolver": "9.1.1", + "@cspell/cspell-types": "9.1.1", + "@cspell/dynamic-import": "9.1.1", + "@cspell/filetypes": "9.1.1", + "@cspell/strong-weak-map": "9.1.1", + "@cspell/url": "9.1.1", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "9.0.1", - "cspell-dictionary": "9.0.1", - "cspell-glob": "9.0.1", - "cspell-grammar": "9.0.1", - "cspell-io": "9.0.1", - "cspell-trie-lib": "9.0.1", + "cspell-config-lib": "9.1.1", + "cspell-dictionary": "9.1.1", + "cspell-glob": "9.1.1", + "cspell-grammar": "9.1.1", + "cspell-io": "9.1.1", + "cspell-trie-lib": "9.1.1", "env-paths": "^3.0.0", "fast-equals": "^5.2.2", "gensequence": "^7.0.0", @@ -777,13 +778,13 @@ } }, "node_modules/cspell-trie-lib": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.0.1.tgz", - "integrity": "sha512-gIupiHwLdsQun79biJgiqmXffKUGzFjGLFEeVptI2Zy5Oa3XhRJsHap4PyeleErONkpzxMG1tgpOWzhOqwl65Q==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.1.1.tgz", + "integrity": "sha512-eULMGTTbvmuOWpAM34wodpbAM3dXscLL26WOn9/9uyQJ36dZ0u8B+ctrYf17Ij/wcpGzLqwTNspJN2fkbiXkBQ==", "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-types": "9.0.1", + "@cspell/cspell-pipe": "9.1.1", + "@cspell/cspell-types": "9.1.1", "gensequence": "^7.0.0" }, "engines": { @@ -831,9 +832,9 @@ "license": "MIT" }, "node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -1017,9 +1018,9 @@ } }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -1029,9 +1030,9 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "license": "MIT", "dependencies": { "fdir": "^6.4.4", @@ -1069,15 +1070,15 @@ } }, "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" } } } diff --git a/package.json b/package.json index 14ff472b1..28e338fe7 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,6 @@ "cspell": "cspell --config ./cSpell.json ./docs/**/*.md --no-progress --no-summary" }, "dependencies": { - "cspell": "^9.0.1" + "cspell": "^9.1.1" } }