Skip to content

Commit

Permalink
Added support for BindAsync.
Browse files Browse the repository at this point in the history
  • Loading branch information
jscarle committed Mar 20, 2024
1 parent 37ad226 commit 958575b
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 2 deletions.
3 changes: 2 additions & 1 deletion src/LightResults/LightResults.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<RootNamespace>LightResults</RootNamespace>
<LangVersion>latest</LangVersion>
<Version>9.0.0-preview.6</Version>
<Version>9.0.0-preview.7</Version>
<Title>LightResults</Title>
<Authors>Jean-Sebastien Carle</Authors>
<Description>An extremely light and modern Result Pattern library.</Description>
Expand Down Expand Up @@ -55,6 +55,7 @@
<PackagePath>\</PackagePath>
<Visible>False</Visible>
</None>
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.0"/>
</ItemGroup>

</Project>
19 changes: 18 additions & 1 deletion src/LightResults/ResultExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

/// <summary>Provides extension methods for working with <see cref="Result{TValue}" />.</summary>
public static class ResultExtensions

{
/// <summary>Binds a transformation to the result, invoking the transformation if the result is successful.</summary>
/// <typeparam name="TSource">The type of the value in the source result.</typeparam>
Expand All @@ -21,4 +20,22 @@ public static Result<TDestination> Bind<TSource, TDestination>(this Result<TSour
#endif
return source.IsFailed(out var error, out var value) ? Result.Fail<TDestination>(error) : transform(value);
}

/// <summary>Binds an asynchronous transformation to the result, invoking the transformation if the result is successful.</summary>
/// <typeparam name="TSource">The type of the value in the source result.</typeparam>
/// <typeparam name="TDestination">The type of the value in the destination result.</typeparam>
/// <param name="source">The source result.</param>
/// <param name="transform">The transformation to invoke on the source result.</param>
/// <returns>A new instance of <see cref="Result{TResult}" /> representing the result, or a failed result if the source result is failed.</returns>
/// <exception cref="ArgumentNullException">Thrown when the function is <see langword="null" />.</exception>
public static async ValueTask<Result<TDestination>> BindAsync<TSource, TDestination>(this Result<TSource> source, Func<TSource, ValueTask<Result<TDestination>>> transform)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(transform);
#else
if (transform is null)
throw new ArgumentNullException(nameof(transform));
#endif
return source.IsFailed(out var error, out var value) ? Result.Fail<TDestination>(error) : await transform(value).ConfigureAwait(false);
}
}
50 changes: 50 additions & 0 deletions tests/LightResults.Tests/ResultExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,54 @@ public void Bind_WithFailedSource_ShouldNotInvokeFunctionAndReturnFailedResult()
resultError.Should().BeOfType<Error>().Which.Message.Should().Be("Generic error");
}
}

[Fact]
public async Task BindAsync_WithSuccessfulSource_ShouldInvokeFunctionAndReturnNewResult()
{
// Arrange
var sourceResult = Result.Ok(42);
var bindFunctionCalled = false;

// Act
var result = await sourceResult.BindAsync(async value =>
{
bindFunctionCalled = true;
await Task.Delay(10); // Simulate some asynchronous operation
return Result.Ok(value.ToString());
});

// Assert
using (new AssertionScope())
{
bindFunctionCalled.Should().BeTrue();
result.Should().BeOfType<Result<string>>();
result.IsSuccess(out var resultValue).Should().BeTrue();
resultValue.Should().Be("42");
}
}

[Fact]
public async Task BindAsync_WithFailedSource_ShouldNotInvokeFunctionAndReturnFailedResult()
{
// Arrange
var sourceResult = Result.Fail<int>("Generic error");
var bindFunctionCalled = false;

// Act
var result = await sourceResult.BindAsync(async value =>
{
bindFunctionCalled = true;
await Task.Delay(10); // Simulate some asynchronous operation
return Result.Ok(value.ToString());
});

// Assert
using (new AssertionScope())
{
bindFunctionCalled.Should().BeFalse();
result.Should().BeOfType<Result<string>>();
result.IsFailed(out var resultError).Should().BeTrue();
resultError.Should().BeOfType<Error>().Which.Message.Should().Be("Generic error");
}
}
}

0 comments on commit 958575b

Please sign in to comment.