Skip to content

Commit

Permalink
feat: add async extensions for Do, DoWhenSuccess and DoWhenFailure on…
Browse files Browse the repository at this point in the history
… Result
  • Loading branch information
Tr00d committed Dec 17, 2024
1 parent 2af8a0b commit 60e14a1
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 8 deletions.
64 changes: 63 additions & 1 deletion Vonage.Test/Common/Monads/ResultExtensionsTest.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.Threading.Tasks;
#region
using System.Threading.Tasks;
using FluentAssertions;
using Vonage.Common.Monads;
using Vonage.Test.Common.Extensions;
using Xunit;
#endregion

namespace Vonage.Test.Common.Monads;

Expand Down Expand Up @@ -127,4 +129,64 @@ public async Task Match_ShouldReturnValue_GivenSuccess()
var result = await TestBehaviors.CreateSuccessAsync(10).Match(_ => "some", _ => "none");
result.Should().Be("some");
}

[Fact]
public async Task Do_ShouldExecuteSuccessAction_GivenStateIsSuccess()
{
var value = 0;
await TestBehaviors.CreateSuccessAsync(5).Do(success => value += success, _ => { });
value.Should().Be(5);
}

[Fact]
public async Task Do_ShouldExecuteFailureAction_GivenStateIsFailure()
{
var value = 0;
await TestBehaviors.CreateFailureAsync<int>().Do(_ => { }, _ => value = 10);
value.Should().Be(10);
}

[Fact]
public async Task Do_ShouldReturnInstance() =>
await TestBehaviors.CreateSuccessAsync(5).Do(_ => { }, _ => { }).Should().BeSuccessAsync(5);

[Fact]
public async Task DoWhenSuccess_ShouldExecuteAction_GivenStateIsSuccess()
{
var value = 0;
await TestBehaviors.CreateSuccessAsync(5).DoWhenSuccess(success => value += success);
value.Should().Be(5);
}

[Fact]
public async Task DoWhenSuccess_ShouldNotExecuteAction_GivenStateIsFailure()
{
var value = 0;
await TestBehaviors.CreateFailureAsync<int>().DoWhenSuccess(_ => value = 10);
value.Should().Be(0);
}

[Fact]
public async Task DoWhenSuccess_ShouldReturnInstance() =>
await TestBehaviors.CreateSuccessAsync(5).DoWhenSuccess(_ => { }).Should().BeSuccessAsync(5);

[Fact]
public async Task DoWhenFailure_ShouldExecuteAction_GivenStateIsFailure()
{
var value = 0;
await TestBehaviors.CreateFailureAsync<int>().DoWhenFailure(_ => value = 10);
value.Should().Be(10);
}

[Fact]
public async Task DoWhenFailure_ShouldNotExecuteAction_GivenStateIsSuccess()
{
var value = 0;
await TestBehaviors.CreateSuccessAsync(5).DoWhenFailure(_ => value = 10);
value.Should().Be(0);
}

[Fact]
public async Task DoWhenFailure_ShouldReturnInstance() =>
await TestBehaviors.CreateSuccessAsync(5).DoWhenFailure(_ => { }).Should().BeSuccessAsync(5);
}
59 changes: 52 additions & 7 deletions Vonage/Common/Monads/ResultExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
#region
using System;
using System.Threading.Tasks;
using Vonage.Common.Failures;
#endregion

namespace Vonage.Common.Monads;

Expand All @@ -23,7 +25,7 @@ public static async Task<Result<TDestination>> Bind<TSource, TDestination>(this
var result = await task.ConfigureAwait(false);
return result.Bind(bind);
}

/// <summary>
/// Monadic bind operation.
/// </summary>
Expand All @@ -38,7 +40,7 @@ public static async Task<Result<TDestination>> BindAsync<TSource, TDestination>(
var result = await task.ConfigureAwait(false);
return await result.BindAsync(bind).ConfigureAwait(false);
}

/// <summary>
/// Returns the default value if the Result is in the Failure state, the success value otherwise.
/// </summary>
Expand All @@ -51,7 +53,7 @@ public static async Task<TSource> IfFailure<TSource>(this Task<Result<TSource>>
var result = await task.ConfigureAwait(false);
return result.IfFailure(defaultValue);
}

/// <summary>
/// Invokes the action if Result is in the Success state, otherwise nothing happens.
/// </summary>
Expand All @@ -64,7 +66,7 @@ public static async Task<Result<T>> IfSuccessAsync<T>(this Task<Result<T>> task,
var result = await task.ConfigureAwait(false);
return await result.IfSuccessAsync(action).ConfigureAwait(false);
}

/// <summary>
/// Projects from one value to another.
/// </summary>
Expand All @@ -79,7 +81,7 @@ public static async Task<Result<TDestination>> Map<TSource, TDestination>(this T
var result = await task.ConfigureAwait(false);
return result.Map(map);
}

/// <summary>
/// Projects from one value to another.
/// </summary>
Expand All @@ -94,7 +96,7 @@ public static async Task<Result<TDestination>> MapAsync<TSource, TDestination>(t
var result = await task.ConfigureAwait(false);
return await result.MapAsync(map).ConfigureAwait(false);
}

/// <summary>
/// Match the two states of the Result and return a non-null TB.
/// </summary>
Expand All @@ -110,4 +112,47 @@ public static async Task<TDestination> Match<TSource, TDestination>(this Task<Re
var result = await task.ConfigureAwait(false);
return result.Match(successOperation, failureOperation);
}

/// <summary>
/// Executes operations depending on the current state.
/// </summary>
/// <param name="task">Asynchronous result.</param>
/// <param name="successOperation">Success operation.</param>
/// <param name="failureOperation">Failure operation.</param>
/// <typeparam name="TSource">Source type.</typeparam>
/// <returns>The initial result.</returns>
public static async Task<Result<TSource>> Do<TSource>(this Task<Result<TSource>> task,
Action<TSource> successOperation, Action<IResultFailure> failureOperation)
{
var result = await task.ConfigureAwait(false);
return result.Do(successOperation, failureOperation);
}

/// <summary>
/// Executes an operation if success.
/// </summary>
/// <param name="task">Asynchronous result.</param>
/// <param name="successOperation">Success operation.</param>
/// <typeparam name="TSource">Source type.</typeparam>
/// <returns>The initial result.</returns>
public static async Task<Result<TSource>> DoWhenSuccess<TSource>(this Task<Result<TSource>> task,
Action<TSource> successOperation)
{
var result = await task.ConfigureAwait(false);
return result.DoWhenSuccess(successOperation);
}

/// <summary>
/// Executes an operation if failure.
/// </summary>
/// <param name="task">Asynchronous result.</param>
/// <param name="failureOperation">Failure operation.</param>
/// <typeparam name="TSource">Source type.</typeparam>
/// <returns>The initial result.</returns>
public static async Task<Result<TSource>> DoWhenFailure<TSource>(this Task<Result<TSource>> task,
Action<IResultFailure> failureOperation)
{
var result = await task.ConfigureAwait(false);
return result.DoWhenFailure(failureOperation);
}
}

0 comments on commit 60e14a1

Please sign in to comment.