From 8882c06535794d7e625524797cef06fe32c84003 Mon Sep 17 00:00:00 2001 From: MGREMY Date: Tue, 23 Apr 2024 09:38:45 +0200 Subject: [PATCH 1/4] Add FailIfAsync --- ErrorOr.sln.DotSettings.user | 6 ++++ src/ErrorOr.FailIf.cs | 16 +++++++++ src/ErrorOr.FailIfExtensions.cs | 5 +++ tests/ErrorOr.FailIfAsyncTests.cs | 54 +++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 ErrorOr.sln.DotSettings.user create mode 100644 src/ErrorOr.FailIfExtensions.cs create mode 100644 tests/ErrorOr.FailIfAsyncTests.cs diff --git a/ErrorOr.sln.DotSettings.user b/ErrorOr.sln.DotSettings.user new file mode 100644 index 0000000..b41a307 --- /dev/null +++ b/ErrorOr.sln.DotSettings.user @@ -0,0 +1,6 @@ + + <SessionState ContinuousTestingMode="0" IsActive="True" Name="FailIfAsyncTests" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <TestAncestor> + <TestId>xUnit::0E84EC69-4E4C-4195-907D-06C96D0140A6::net6.0::Tests.FailIfAsyncTests</TestId> + </TestAncestor> +</SessionState> \ No newline at end of file diff --git a/src/ErrorOr.FailIf.cs b/src/ErrorOr.FailIf.cs index 5e51d79..7764d42 100644 --- a/src/ErrorOr.FailIf.cs +++ b/src/ErrorOr.FailIf.cs @@ -20,4 +20,20 @@ public ErrorOr FailIf(Func onValue, Error error) return onValue(Value) ? error : this; } + + /// + /// If the state is error, the provider is invoked asynchronously. + /// + /// The function to execute if the statement is value. + /// The to return if the given function returned true. + /// The given if returns true; otherwise, the original instance. + public async Task> FailIfAsync(Func> onValue, Error error) + { + if (IsError) + { + return this; + } + + return await onValue(Value).ConfigureAwait(false) ? error : this; + } } diff --git a/src/ErrorOr.FailIfExtensions.cs b/src/ErrorOr.FailIfExtensions.cs new file mode 100644 index 0000000..bcfe5f5 --- /dev/null +++ b/src/ErrorOr.FailIfExtensions.cs @@ -0,0 +1,5 @@ +namespace ErrorOr; + +public static partial class ErrorOrfExtensions +{ +} diff --git a/tests/ErrorOr.FailIfAsyncTests.cs b/tests/ErrorOr.FailIfAsyncTests.cs new file mode 100644 index 0000000..407669c --- /dev/null +++ b/tests/ErrorOr.FailIfAsyncTests.cs @@ -0,0 +1,54 @@ +using ErrorOr; +using FluentAssertions; + +namespace Tests; + +public class FailIfAsyncTests +{ + private record Person(string Name); + + [Fact] + public async Task CallingFailIfAsync_WhenFailIf_ShouldReturnError() + { + // Arrange + ErrorOr errorOrInt = 5; + + // Act + ErrorOr result = await errorOrInt + .FailIfAsync(num => Task.FromResult(num > 3), Error.Failure()); + + // Assert + result.IsError.Should().BeTrue(); + result.FirstError.Type.Should().Be(ErrorType.Failure); + } + + [Fact] + public async Task CallingFailIfAsync_WhenFailIf_ShouldReturnValue() + { + // Arrange + ErrorOr errorOrInt = 5; + + // Act + ErrorOr result = await errorOrInt + .FailIfAsync(num => Task.FromResult(num > 10), Error.Failure()); + + // Assert + result.IsError.Should().BeFalse(); + result.Value.Should().Be(5); + } + + [Fact] + public async Task CallingFailIf_WhenIsError_ShouldNotInvoke_FailIfFunc() + { + // Arrange + ErrorOr errorOrString = Error.NotFound(); + + // Act + ErrorOr result = await errorOrString + .FailIfAsync(str => Task.FromResult(str == string.Empty), Error.Failure()); + + // Assert + result.IsError.Should().BeTrue(); + result.FirstError.Type.Should().Be(ErrorType.NotFound); + } +} From 534a9e4f98f1213500670ec9fd953012cbc4d722 Mon Sep 17 00:00:00 2001 From: MGREMY Date: Tue, 23 Apr 2024 09:42:52 +0200 Subject: [PATCH 2/4] Remove rider settings --- ErrorOr.sln.DotSettings.user | 6 ------ src/ErrorOr.FailIfExtensions.cs | 5 ----- 2 files changed, 11 deletions(-) delete mode 100644 ErrorOr.sln.DotSettings.user delete mode 100644 src/ErrorOr.FailIfExtensions.cs diff --git a/ErrorOr.sln.DotSettings.user b/ErrorOr.sln.DotSettings.user deleted file mode 100644 index b41a307..0000000 --- a/ErrorOr.sln.DotSettings.user +++ /dev/null @@ -1,6 +0,0 @@ - - <SessionState ContinuousTestingMode="0" IsActive="True" Name="FailIfAsyncTests" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> - <TestAncestor> - <TestId>xUnit::0E84EC69-4E4C-4195-907D-06C96D0140A6::net6.0::Tests.FailIfAsyncTests</TestId> - </TestAncestor> -</SessionState> \ No newline at end of file diff --git a/src/ErrorOr.FailIfExtensions.cs b/src/ErrorOr.FailIfExtensions.cs deleted file mode 100644 index bcfe5f5..0000000 --- a/src/ErrorOr.FailIfExtensions.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace ErrorOr; - -public static partial class ErrorOrfExtensions -{ -} From f214b0e14f9909a5b0f2ed9f828026deb3bd22d0 Mon Sep 17 00:00:00 2001 From: MGREMY Date: Wed, 24 Apr 2024 09:30:00 +0200 Subject: [PATCH 3/4] Add FailIf extensions --- src/ErrorOr.FailIfExtensions.cs | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/ErrorOr.FailIfExtensions.cs diff --git a/src/ErrorOr.FailIfExtensions.cs b/src/ErrorOr.FailIfExtensions.cs new file mode 100644 index 0000000..f772b55 --- /dev/null +++ b/src/ErrorOr.FailIfExtensions.cs @@ -0,0 +1,40 @@ +namespace ErrorOr; + +public static partial class ErrorOrExtensions +{ + /// + /// If the state is error, the provided function is executed and its result is returned. + /// + /// The instance. + /// The function to execute if the state is a value. + /// The to return if the given function returned true.. + /// The type of the underlying value in the . + /// The given if returns true; otherwise, the original instance. + public static async Task> FailIf( + this Task> errorOr, + Func onValue, + Error error) + { + var result = await errorOr.ConfigureAwait(false); + + return result.FailIf(onValue, error); + } + + /// + /// If the state is error, the provider is invoked asynchronously. + /// + /// The instance. + /// The function to execute if the statement is value. + /// The to return if the given function returned true. + /// The type of the underlying value in the . + /// The given if returns true; otherwise, the original instance. + public static async Task> FailIfAsync( + this Task> errorOr, + Func> onValue, + Error error) + { + var result = await errorOr.ConfigureAwait(false); + + return await result.FailIfAsync(onValue, error); + } +} From 86431e7654889a184e6e0868eb7cbfdde4660331 Mon Sep 17 00:00:00 2001 From: Amichai Mantinband Date: Thu, 9 May 2024 13:04:07 +0300 Subject: [PATCH 4/4] Update docs and add missing tests --- src/ErrorOr.FailIf.cs | 8 +- src/ErrorOr.FailIfExtensions.cs | 82 ++++++++++---------- tests/ErrorOr.FailIfAsyncTests.cs | 124 +++++++++++++++++------------- tests/ErrorOr.FailIfTests.cs | 16 ++++ 4 files changed, 133 insertions(+), 97 deletions(-) diff --git a/src/ErrorOr.FailIf.cs b/src/ErrorOr.FailIf.cs index 7764d42..c59fab0 100644 --- a/src/ErrorOr.FailIf.cs +++ b/src/ErrorOr.FailIf.cs @@ -6,10 +6,11 @@ namespace ErrorOr; public readonly partial record struct ErrorOr : IErrorOr { /// - /// If the state is error, the provided function is executed and its result is returned. + /// If the state is value, the provided function is invoked. + /// If returns true, the given will be returned, and the state will be error. /// /// The function to execute if the state is value. - /// The to return if the given function returned true.. + /// The to return if the given function returned true. /// The given if returns true; otherwise, the original instance. public ErrorOr FailIf(Func onValue, Error error) { @@ -22,7 +23,8 @@ public ErrorOr FailIf(Func onValue, Error error) } /// - /// If the state is error, the provider is invoked asynchronously. + /// If the state is value, the provided function is invoked asynchronously. + /// If returns true, the given will be returned, and the state will be error. /// /// The function to execute if the statement is value. /// The to return if the given function returned true. diff --git a/src/ErrorOr.FailIfExtensions.cs b/src/ErrorOr.FailIfExtensions.cs index f772b55..9fbd39c 100644 --- a/src/ErrorOr.FailIfExtensions.cs +++ b/src/ErrorOr.FailIfExtensions.cs @@ -1,40 +1,42 @@ -namespace ErrorOr; - -public static partial class ErrorOrExtensions -{ - /// - /// If the state is error, the provided function is executed and its result is returned. - /// - /// The instance. - /// The function to execute if the state is a value. - /// The to return if the given function returned true.. - /// The type of the underlying value in the . - /// The given if returns true; otherwise, the original instance. - public static async Task> FailIf( - this Task> errorOr, - Func onValue, - Error error) - { - var result = await errorOr.ConfigureAwait(false); - - return result.FailIf(onValue, error); - } - - /// - /// If the state is error, the provider is invoked asynchronously. - /// - /// The instance. - /// The function to execute if the statement is value. - /// The to return if the given function returned true. - /// The type of the underlying value in the . - /// The given if returns true; otherwise, the original instance. - public static async Task> FailIfAsync( - this Task> errorOr, - Func> onValue, - Error error) - { - var result = await errorOr.ConfigureAwait(false); - - return await result.FailIfAsync(onValue, error); - } -} +namespace ErrorOr; + +public static partial class ErrorOrExtensions +{ + /// + /// If the state is value, the provided function is invoked asynchronously. + /// If returns true, the given will be returned, and the state will be error. + /// + /// The instance. + /// The function to execute if the state is a value. + /// The to return if the given function returned true.. + /// The type of the underlying value in the . + /// The given if returns true; otherwise, the original instance. + public static async Task> FailIf( + this Task> errorOr, + Func onValue, + Error error) + { + var result = await errorOr.ConfigureAwait(false); + + return result.FailIf(onValue, error); + } + + /// + /// If the state is value, the provided function is invoked asynchronously. + /// If returns true, the given will be returned, and the state will be error. + /// + /// The instance. + /// The function to execute if the statement is value. + /// The to return if the given function returned true. + /// The type of the underlying value in the . + /// The given if returns true; otherwise, the original instance. + public static async Task> FailIfAsync( + this Task> errorOr, + Func> onValue, + Error error) + { + var result = await errorOr.ConfigureAwait(false); + + return await result.FailIfAsync(onValue, error); + } +} diff --git a/tests/ErrorOr.FailIfAsyncTests.cs b/tests/ErrorOr.FailIfAsyncTests.cs index 407669c..b1a64a2 100644 --- a/tests/ErrorOr.FailIfAsyncTests.cs +++ b/tests/ErrorOr.FailIfAsyncTests.cs @@ -1,54 +1,70 @@ -using ErrorOr; -using FluentAssertions; - -namespace Tests; - -public class FailIfAsyncTests -{ - private record Person(string Name); - - [Fact] - public async Task CallingFailIfAsync_WhenFailIf_ShouldReturnError() - { - // Arrange - ErrorOr errorOrInt = 5; - - // Act - ErrorOr result = await errorOrInt - .FailIfAsync(num => Task.FromResult(num > 3), Error.Failure()); - - // Assert - result.IsError.Should().BeTrue(); - result.FirstError.Type.Should().Be(ErrorType.Failure); - } - - [Fact] - public async Task CallingFailIfAsync_WhenFailIf_ShouldReturnValue() - { - // Arrange - ErrorOr errorOrInt = 5; - - // Act - ErrorOr result = await errorOrInt - .FailIfAsync(num => Task.FromResult(num > 10), Error.Failure()); - - // Assert - result.IsError.Should().BeFalse(); - result.Value.Should().Be(5); - } - - [Fact] - public async Task CallingFailIf_WhenIsError_ShouldNotInvoke_FailIfFunc() - { - // Arrange - ErrorOr errorOrString = Error.NotFound(); - - // Act - ErrorOr result = await errorOrString - .FailIfAsync(str => Task.FromResult(str == string.Empty), Error.Failure()); - - // Assert - result.IsError.Should().BeTrue(); - result.FirstError.Type.Should().Be(ErrorType.NotFound); - } -} +using ErrorOr; +using FluentAssertions; + +namespace Tests; + +public class FailIfAsyncTests +{ + private record Person(string Name); + + [Fact] + public async Task CallingFailIfAsync_WhenFailsIf_ShouldReturnError() + { + // Arrange + ErrorOr errorOrInt = 5; + + // Act + ErrorOr result = await errorOrInt + .FailIfAsync(num => Task.FromResult(num > 3), Error.Failure()); + + // Assert + result.IsError.Should().BeTrue(); + result.FirstError.Type.Should().Be(ErrorType.Failure); + } + + [Fact] + public async Task CallingFailIfAsyncExtensionMethod_WhenFailsIf_ShouldReturnError() + { + // Arrange + ErrorOr errorOrInt = 5; + + // Act + ErrorOr result = await errorOrInt + .ThenAsync(num => Task.FromResult(num)) + .FailIfAsync(num => Task.FromResult(num > 3), Error.Failure()); + + // Assert + result.IsError.Should().BeTrue(); + result.FirstError.Type.Should().Be(ErrorType.Failure); + } + + [Fact] + public async Task CallingFailIfAsync_WhenDoesNotFailIf_ShouldReturnValue() + { + // Arrange + ErrorOr errorOrInt = 5; + + // Act + ErrorOr result = await errorOrInt + .FailIfAsync(num => Task.FromResult(num > 10), Error.Failure()); + + // Assert + result.IsError.Should().BeFalse(); + result.Value.Should().Be(5); + } + + [Fact] + public async Task CallingFailIf_WhenIsError_ShouldNotInvokeFailIfFunc() + { + // Arrange + ErrorOr errorOrString = Error.NotFound(); + + // Act + ErrorOr result = await errorOrString + .FailIfAsync(str => Task.FromResult(str == string.Empty), Error.Failure()); + + // Assert + result.IsError.Should().BeTrue(); + result.FirstError.Type.Should().Be(ErrorType.NotFound); + } +} diff --git a/tests/ErrorOr.FailIfTests.cs b/tests/ErrorOr.FailIfTests.cs index 0f6b591..ed60531 100644 --- a/tests/ErrorOr.FailIfTests.cs +++ b/tests/ErrorOr.FailIfTests.cs @@ -20,6 +20,22 @@ public void CallingFailIf_WhenFailsIf_ShouldReturnError() result.FirstError.Type.Should().Be(ErrorType.Failure); } + [Fact] + public async Task CallingFailIfExtensionMethod_WhenFailsIf_ShouldReturnError() + { + // Arrange + ErrorOr errorOrInt = 5; + + // Act + ErrorOr result = await errorOrInt + .ThenAsync(num => Task.FromResult(num)) + .FailIf(num => num > 3, Error.Failure()); + + // Assert + result.IsError.Should().BeTrue(); + result.FirstError.Type.Should().Be(ErrorType.Failure); + } + [Fact] public void CallingFailIf_WhenDoesNotFailIf_ShouldReturnValue() {