feat: create request projects for basic CQRS

This commit is contained in:
Louis Seubert 2026-05-08 20:26:26 +02:00
commit d614788e06
Signed by: louis9902
GPG key ID: 4B9DB28F826553BD
190 changed files with 12236 additions and 0 deletions

View file

@ -0,0 +1,15 @@
[*.{cs,vb}]
# disable CA1822: Mark members as static
# -> TUnit requiring instance methods for test cases
dotnet_diagnostic.CA1822.severity = none
# disable CA1707: Identifiers should not contain underscores
dotnet_diagnostic.CA1707.severity = none
# disable IDE0060: Remove unused parameter
dotnet_diagnostic.IDE0060.severity = none
# disable IDE0005: Unnecessary using directive
dotnet_diagnostic.IDE0005.severity = none
# disable IDE0390: Method can be made synchronous
dotnet_diagnostic.IDE0390.severity = none
# disable IDE0391: Method can be made synchronous
dotnet_diagnostic.IDE0391.severity = none

View file

@ -0,0 +1,27 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class ErrorTests
{
[Test]
public async Task I_can_implicitly_convert_from_string_and_get_string_error()
{
Error error = "error";
using var scope = Assert.Multiple();
await Assert.That(error).IsTypeOf<StringError>();
await Assert.That(error.Message).IsEqualTo("error");
}
[Test]
public async Task I_can_implicitly_convert_from_exception_and_get_exception_error()
{
Error error = new CustomTestException();
using var scope = Assert.Multiple();
var instance = await Assert.That(error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
}

View file

@ -0,0 +1,50 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class ExtensionsEnumerableTests
{
[Test]
public async Task I_can_join_sequence_and_get_all_success_when_all_elements_are_success()
{
IEnumerable<Result<int>> xs = [1, 2, 3, 4, 5];
var result = xs.Join();
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEquivalentTo([1, 2, 3, 4, 5]);
}
[Test]
public async Task I_can_join_sequence_and_get_first_failure_when_sequence_contains_failure()
{
IEnumerable<Result<int>> xs =
[
Prelude.Success(1),
Prelude.Success(2),
Prelude.Failure<int>("error 1"),
Prelude.Success(4),
Prelude.Failure<int>("error 2")
];
var result = xs.Join();
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
await Assert.That(result.Error?.Message).IsEqualTo("error 1");
}
[Test]
public async Task I_can_join_empty_sequence_and_get_success()
{
IEnumerable<Result<int>> xs = [];
var result = xs.Join();
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEmpty();
}
}

View file

@ -0,0 +1,107 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
using System.Globalization;
namespace Geekeey.Request.Result.Tests;
internal sealed class ExtensionsTaskTests
{
[Test]
public async Task I_can_map_on_task_and_it_returns_success_for_success()
{
var start = Task.FromResult(Prelude.Success(2));
var result = await start.Map(value => value.ToString(CultureInfo.InvariantCulture));
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo("2");
}
[Test]
public async Task I_can_try_map_on_task_and_it_returns_failure_for_success_with_throwing()
{
var start = Task.FromResult(Prelude.Success(2));
var result = await start.TryMap<int, string>(value => throw new CustomTestException());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
[Test]
public async Task I_can_map_async_on_task_and_it_returns_success_for_success()
{
var start = Task.FromResult(Prelude.Success(2));
var result = await start.MapAsync(value => Task.FromResult(value.ToString(CultureInfo.InvariantCulture)));
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo("2");
}
[Test]
public async Task I_can_then_on_task_and_it_returns_success_for_success()
{
var start = Task.FromResult(Prelude.Success(2));
var result = await start.Then(value => Prelude.Success(value.ToString(CultureInfo.InvariantCulture)));
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo("2");
}
[Test]
public async Task I_can_then_non_generic_on_task_and_it_returns_success_for_success()
{
var start = Task.FromResult(Prelude.Success(2));
var result = await start.Then(value => Prelude.Success());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
}
[Test]
public async Task I_can_map_on_value_task_and_it_returns_success_for_success()
{
var start = ValueTask.FromResult(Prelude.Success(2));
var result = await start.Map(value => value.ToString(CultureInfo.InvariantCulture));
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo("2");
}
[Test]
public async Task I_can_map_on_task_result_and_it_returns_success_for_success()
{
var start = Task.FromResult(Prelude.Success());
var result = await start.Map(() => "2");
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo("2");
}
[Test]
public async Task I_can_then_on_task_result_and_it_returns_success_for_success()
{
var start = Task.FromResult(Prelude.Success());
var result = await start.Then(Prelude.Success);
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
}
[Test]
public async Task I_can_then_generic_on_task_result_and_it_returns_success_for_success()
{
var start = Task.FromResult(Prelude.Success());
var result = await start.Then(() => Prelude.Success("2"));
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo("2");
}
}

View file

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TUnit" />
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\request.result\Geekeey.Request.Result.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,34 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
public class IResultFactoryTests
{
[Test]
public async Task I_can_assign_result_to_result_factory()
{
await Assert.That(typeof(IResultFactory<Result>).IsAssignableFrom(typeof(Result))).IsTrue();
await Assert.That(typeof(IResultFactory<Result<int>>).IsAssignableFrom(typeof(Result<int>))).IsTrue();
}
[Test]
public async Task I_can_create_failure_result_from_error_with_result_factory()
{
{
var error = new StringError("error");
var result = CreateFailure<Result>(error);
await Assert.That(result.IsFailure).IsTrue();
}
{
var error = new StringError("error");
var result = CreateFailure<Result<int>>(error);
await Assert.That(result.IsFailure).IsTrue();
}
}
private static TResult CreateFailure<TResult>(Error error) where TResult : IResultFactory<TResult>
{
return TResult.Failure(error);
}
}

View file

@ -0,0 +1,180 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class PreludeTests
{
[Test]
public async Task I_can_try_with_success_value_and_get_a_success_result()
{
var result = Prelude.Try(() => 2);
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo(2);
}
[Test]
public async Task I_can_try_with_throwing_exception_and_get_a_failure_result()
{
var result = Prelude.Try<int>(() => throw new CustomTestException());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
[Test]
public async Task I_can_try_with_async_success_value_and_get_a_success_result()
{
var result = await Prelude.TryAsync(() => Task.FromResult(2));
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo(2);
}
[Test]
public async Task I_can_try_with_async_throwing_exception_and_get_a_failure_result()
{
var result = await Prelude.TryAsync(Task<int> () => throw new CustomTestException());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
[Test]
public async Task I_can_try_with_async_await_throwing_exception_and_get_a_failure_result()
{
var result = await Prelude.TryAsync(async Task<int> () =>
{
await Task.CompletedTask;
throw new CustomTestException();
});
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
[Test]
public async Task I_can_try_with_async_success_value_and_get_a_success_result_of_type_ValueTask()
{
var result = await Prelude.TryAsync(() => ValueTask.FromResult(2));
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.Value).IsEqualTo(2);
}
[Test]
public async Task I_can_try_with_async_throwing_exception_and_get_a_failure_result_of_type_ValueTask()
{
var result = await Prelude.TryAsync(ValueTask<int> () => throw new CustomTestException());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
[Test]
public async Task I_can_try_with_async_await_throwing_exception_and_get_a_failure_result_of_type_ValueTask()
{
var result = await Prelude.TryAsync(async ValueTask<int> () =>
{
await Task.CompletedTask;
throw new CustomTestException();
});
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
[Test]
public async Task I_can_create_success_result_using_prelude()
{
var result = Prelude.Success();
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.IsFailure).IsFalse();
}
[Test]
public async Task I_can_create_failure_result_using_prelude()
{
var result = Prelude.Failure("error");
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
await Assert.That(result.IsFailure).IsTrue();
}
[Test]
public async Task I_can_try_action_with_success_and_get_a_success_result()
{
var result = Prelude.Try(() => { });
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
}
[Test]
public async Task I_can_try_action_with_throwing_exception_and_get_a_failure_result()
{
var result = Prelude.Try(() => throw new CustomTestException());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
[Test]
public async Task I_can_try_async_action_with_success_and_get_a_success_result()
{
var result = await Prelude.TryAsync(() => Task.CompletedTask);
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
}
[Test]
public async Task I_can_try_async_action_with_throwing_exception_and_get_a_failure_result()
{
var result = await Prelude.TryAsync(Task () => throw new CustomTestException());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
[Test]
public async Task I_can_try_async_value_action_with_success_and_get_a_success_result()
{
var result = await Prelude.TryAsync(() => ValueTask.CompletedTask);
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
}
[Test]
public async Task I_can_try_async_value_action_with_throwing_exception_and_get_a_failure_result()
{
var result = await Prelude.TryAsync(ValueTask () => throw new CustomTestException());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
var instance = await Assert.That(result.Error).IsTypeOf<ExceptionError>();
await Assert.That(instance?.Exception).IsTypeOf<CustomTestException>();
}
}

View file

@ -0,0 +1,76 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class ResultConversionTests
{
[Test]
public async Task I_can_implicitly_convert_from_value_and_get_success()
{
var result = Prelude.Success(2);
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.IsFailure).IsFalse();
await Assert.That(result.Value).IsEqualTo(2);
}
[Test]
public async Task I_can_implicitly_convert_from_error_and_get_failure()
{
var error = new CustomTestError();
var result = Prelude.Failure<int>(error);
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
await Assert.That(result.IsFailure).IsTrue();
await Assert.That(result.Error).IsTypeOf<CustomTestError>();
}
[Test]
public async Task I_can_unwrap_and_get_value_for_success()
{
var result = Prelude.Success(2);
var value = result.Unwrap();
await Assert.That(value).IsEqualTo(2);
}
[Test]
public async Task I_can_unwrap_and_get_exception_for_failure()
{
var result = Prelude.Failure<int>("error");
await Assert.That(result.Unwrap).Throws<UnwrapException>();
}
[Test]
public async Task I_can_explicitly_convert_and_get_value_for_success()
{
var result = Prelude.Success(2);
var value = (int)result;
await Assert.That(value).IsEqualTo(2);
}
[Test]
public async Task I_can_explicitly_convert_and_get_exception_for_failure()
{
var result = Prelude.Failure<int>("error");
await Assert.That(() => (int)result).Throws<UnwrapException>();
}
[Test]
public async Task I_can_implicitly_convert_from_error_to_non_generic_result()
{
var error = new CustomTestError();
Result result = error;
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
await Assert.That(result.IsFailure).IsTrue();
await Assert.That(result.Error).IsTypeOf<CustomTestError>();
}
}

View file

@ -0,0 +1,202 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class ResultEqualityTests
{
[Test]
public async Task I_can_equal_t_and_get_true_for_success_with_equal_value()
{
var a = Prelude.Success(2);
var b = 2;
await Assert.That(a.Equals(b)).IsTrue();
}
[Test]
public async Task I_can_equal_t_and_get_false_for_success_with_unequal_value()
{
var a = Prelude.Success(2);
var b = 3;
await Assert.That(a.Equals(b)).IsFalse();
}
[Test]
public async Task I_can_equal_t_and_get_false_for_failure()
{
var a = Prelude.Failure<int>("error");
var b = 2;
await Assert.That(a.Equals(b)).IsFalse();
}
[Test]
public async Task I_can_equal_result_and_get_true_for_success_and_success_with_equal_value()
{
var a = Prelude.Success(2);
var b = Prelude.Success(2);
await Assert.That(a.Equals(b)).IsTrue();
}
[Test]
public async Task I_can_equal_result_and_get_false_for_success_and_success_with_unequal_value()
{
var a = Prelude.Success(2);
var b = Prelude.Success(3);
await Assert.That(a.Equals(b)).IsFalse();
}
[Test]
public async Task I_can_equals_result_and_get_false_for_success_and_failure()
{
var a = Prelude.Success(2);
var b = Prelude.Failure<int>("error 1");
await Assert.That(a.Equals(b)).IsFalse();
}
[Test]
public async Task I_can_equals_result_and_get_false_for_failure_and_success()
{
var a = Prelude.Failure<int>("error");
var b = Prelude.Success(2);
await Assert.That(a.Equals(b)).IsFalse();
}
[Test]
public async Task I_can_equals_result_and_get_true_for_failure_and_failure()
{
var a = Prelude.Failure<int>("error 1");
var b = Prelude.Failure<int>("error 2");
await Assert.That(a.Equals(b)).IsTrue();
}
[Test]
public async Task I_can_equal_t_and_get_true_for_success_with_equal_value_using_comparer()
{
var a = Prelude.Success(2);
var b = 2;
await Assert.That(a.Equals(b, EqualityComparer<int>.Default)).IsTrue();
}
[Test]
public async Task I_can_equal_t_and_get_false_for_success_with_unequal_value_using_comparer()
{
var a = Prelude.Success(2);
var b = 3;
await Assert.That(a.Equals(b, EqualityComparer<int>.Default)).IsFalse();
}
[Test]
public async Task I_can_equal_t_and_get_false_for_failure_using_comparer()
{
var a = Prelude.Failure<int>("error");
var b = 2;
await Assert.That(a.Equals(b, EqualityComparer<int>.Default)).IsFalse();
}
[Test]
public async Task I_can_equal_result_and_get_true_for_success_and_success_with_equal_value_using_comparer()
{
var a = Prelude.Success(2);
var b = Prelude.Success(2);
await Assert.That(a.Equals(b, EqualityComparer<int>.Default)).IsTrue();
}
[Test]
public async Task I_can_equal_result_and_get_false_for_success_and_success_with_unequal_value_using_comparer()
{
var a = Prelude.Success(2);
var b = Prelude.Success(3);
await Assert.That(a.Equals(b, EqualityComparer<int>.Default)).IsFalse();
}
[Test]
public async Task I_can_equals_result_and_get_false_for_success_and_failure_using_comparer()
{
var a = Prelude.Success(2);
var b = Prelude.Failure<int>("error 1");
await Assert.That(a.Equals(b, EqualityComparer<int>.Default)).IsFalse();
}
[Test]
public async Task I_can_equals_result_and_get_false_for_failure_and_success_using_comparer()
{
var a = Prelude.Failure<int>("error");
var b = Prelude.Success(2);
await Assert.That(a.Equals(b, EqualityComparer<int>.Default)).IsFalse();
}
[Test]
public async Task I_can_equals_result_and_get_true_for_failure_and_failure_using_comparer()
{
var a = Prelude.Failure<int>("error 1");
var b = Prelude.Failure<int>("error 2");
await Assert.That(a.Equals(b, EqualityComparer<int>.Default)).IsTrue();
}
[Test]
public async Task I_can_get_hashcode_and_get_hashcode_for_success()
{
var result = Prelude.Success(2);
await Assert.That(result.GetHashCode()).IsEqualTo(2.GetHashCode());
}
[Test]
public async Task I_can_get_hashcode_and_get_zero_for_null()
{
var result = Prelude.Success<string?>(null);
await Assert.That(result.GetHashCode()).IsZero();
}
[Test]
public async Task I_can_get_hashcode_and_get_zero_for_failure()
{
var result = Prelude.Failure<int>("error");
await Assert.That(result.GetHashCode()).IsZero();
}
[Test]
public async Task I_can_equal_non_generic_result_and_get_true_for_success_and_success()
{
var a = Prelude.Success();
var b = Prelude.Success();
await Assert.That(a.Equals(b)).IsTrue();
}
[Test]
public async Task I_can_equal_non_generic_result_and_get_true_for_failure_and_failure()
{
var a = Prelude.Failure("error 1");
var b = Prelude.Failure("error 2");
await Assert.That(a.Equals(b)).IsTrue();
}
[Test]
public async Task I_can_equal_non_generic_result_and_get_false_for_success_and_failure()
{
var a = Prelude.Success();
var b = Prelude.Failure("error");
await Assert.That(a.Equals(b)).IsFalse();
}
}

View file

@ -0,0 +1,365 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class ResultMatchingTests
{
[Test]
public async Task I_can_match_and_it_calls_success_func_for_success()
{
var result = Prelude.Success(2);
var match = result.Match(
v => v,
_ => throw new InvalidOperationException());
await Assert.That(match).IsEqualTo(2);
}
[Test]
public async Task I_can_match_and_it_calls_failure_func_for_failure()
{
var result = Prelude.Failure<int>("error");
var match = result.Match(
_ => throw new InvalidOperationException(),
e => e);
await Assert.That(match.Message).IsEqualTo("error");
}
[Test]
public async Task I_can_switch_and_it_calls_success_action_for_success()
{
var called = false;
var value = default(int);
var result = Prelude.Success(2);
result.Switch(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
await Assert.That(value).IsEqualTo(2);
return;
void OnSuccess(int i)
{
value = i;
called = true;
}
void OnFailure(Error e)
{
throw new InvalidOperationException();
}
}
[Test]
public async Task I_can_switch_and_it_calls_failure_action_for_failure()
{
var called = false;
var value = default(Error);
var result = Prelude.Failure<int>("error");
result.Switch(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
await Assert.That(value?.Message).IsEqualTo("error");
return;
void OnSuccess(int i)
{
throw new InvalidOperationException();
}
void OnFailure(Error e)
{
value = e;
called = true;
}
}
[Test]
public async Task I_can_match_async_and_it_calls_success_func_for_success()
{
var result = Prelude.Success(2);
var match = await result.MatchAsync(
Task.FromResult,
_ => throw new InvalidOperationException());
await Assert.That(match).IsEqualTo(2);
}
[Test]
public async Task I_can_match_async_and_it_calls_failure_func_for_failure()
{
var result = Prelude.Failure<int>("error");
var match = await result.MatchAsync(
_ => throw new InvalidOperationException(),
Task.FromResult);
await Assert.That(match.Message).IsEqualTo("error");
}
[Test]
public async Task I_can_switch_async_and_it_calls_success_action_for_success()
{
var called = false;
var value = default(int);
var result = Prelude.Success(2);
await result.SwitchAsync(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
await Assert.That(value).IsEqualTo(2);
return;
Task OnSuccess(int i)
{
value = i;
called = true;
return Task.CompletedTask;
}
Task OnFailure(Error e)
{
throw new InvalidOperationException();
}
}
[Test]
public async Task I_can_switch_async_and_it_calls_failure_action_for_failure()
{
var called = false;
var value = default(Error);
var result = Prelude.Failure<int>("error");
await result.SwitchAsync(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
await Assert.That(value?.Message).IsEqualTo("error");
return;
Task OnSuccess(int i)
{
throw new InvalidOperationException();
}
Task OnFailure(Error e)
{
value = e;
called = true;
return Task.CompletedTask;
}
}
[Test]
public async Task I_can_match_and_it_calls_success_func_for_success_ValueTask()
{
var result = Prelude.Success(2);
var match = await result.MatchAsync(
ValueTask.FromResult,
_ => throw new InvalidOperationException());
await Assert.That(match).IsEqualTo(2);
}
[Test]
public async Task I_can_match_async_and_it_calls_failure_func_for_failure_ValueTask()
{
var result = Prelude.Failure<int>("error");
var match = await result.MatchAsync(
_ => throw new InvalidOperationException(),
ValueTask.FromResult);
await Assert.That(match.Message).IsEqualTo("error");
}
[Test]
public async Task I_can_switch_async_and_it_calls_success_action_for_success_ValueTask()
{
var called = false;
var value = default(int);
var result = Prelude.Success(2);
await result.SwitchAsync(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
await Assert.That(value).IsEqualTo(2);
return;
ValueTask OnSuccess(int i)
{
value = i;
called = true;
return ValueTask.CompletedTask;
}
ValueTask OnFailure(Error e)
{
throw new InvalidOperationException();
}
}
[Test]
public async Task I_can_switch_async_and_it_calls_failure_action_for_failure_ValueTask()
{
var called = false;
var value = default(Error);
var result = Prelude.Failure<int>("error");
await result.SwitchAsync(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
await Assert.That(value?.Message).IsEqualTo("error");
return;
ValueTask OnSuccess(int i)
{
throw new InvalidOperationException();
}
ValueTask OnFailure(Error e)
{
value = e;
called = true;
return ValueTask.CompletedTask;
}
}
[Test]
public async Task I_can_match_non_generic_result_and_it_calls_success_func_for_success()
{
var result = Prelude.Success();
var match = result.Match(
() => "success",
_ => throw new InvalidOperationException());
await Assert.That(match).IsEqualTo("success");
}
[Test]
public async Task I_can_match_non_generic_result_and_it_calls_failure_func_for_failure()
{
var result = Prelude.Failure("error");
var match = result.Match(
() => throw new InvalidOperationException(),
e => e);
await Assert.That(match.Message).IsEqualTo("error");
}
[Test]
public async Task I_can_switch_non_generic_result_and_it_calls_success_action_for_success()
{
var called = false;
var result = Prelude.Success();
result.Switch(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
void OnSuccess()
{
called = true;
}
void OnFailure(Error e)
{
throw new InvalidOperationException();
}
}
[Test]
public async Task I_can_switch_non_generic_result_and_it_calls_failure_action_for_failure()
{
var called = false;
var value = default(Error);
var result = Prelude.Failure("error");
result.Switch(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
await Assert.That(value?.Message).IsEqualTo("error");
void OnSuccess()
{
throw new InvalidOperationException();
}
void OnFailure(Error e)
{
value = e;
called = true;
}
}
[Test]
public async Task I_can_match_async_non_generic_result_and_it_calls_success_func_for_success()
{
var result = Prelude.Success();
var match = await result.MatchAsync(
() => Task.FromResult("success"),
_ => throw new InvalidOperationException());
await Assert.That(match).IsEqualTo("success");
}
[Test]
public async Task I_can_switch_async_non_generic_result_and_it_calls_success_action_for_success()
{
var called = false;
var result = Prelude.Success();
await result.SwitchAsync(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
Task OnSuccess()
{
called = true;
return Task.CompletedTask;
}
Task OnFailure(Error e)
{
throw new InvalidOperationException();
}
}
[Test]
public async Task I_can_match_async_non_generic_result_and_it_calls_success_func_for_success_ValueTask()
{
var result = Prelude.Success();
var match = await result.MatchAsync(
() => ValueTask.FromResult("success"),
_ => throw new InvalidOperationException());
await Assert.That(match).IsEqualTo("success");
}
[Test]
public async Task I_can_switch_async_non_generic_result_and_it_calls_success_action_for_success_ValueTask()
{
var called = false;
var result = Prelude.Success();
await result.SwitchAsync(OnSuccess, OnFailure);
await Assert.That(called).IsTrue();
ValueTask OnSuccess()
{
called = true;
return ValueTask.CompletedTask;
}
ValueTask OnFailure(Error e)
{
throw new InvalidOperationException();
}
}
}

View file

@ -0,0 +1,104 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
using Geekeey.Request.Result;
namespace Geekeey.Request.Result.Tests;
internal sealed class ResultOperatorTests
{
[Test]
public async Task I_can_compare_non_generic_results_with_operator_and_get_true_for_success_and_success()
{
var a = Prelude.Success();
var b = Prelude.Success();
await Assert.That(a == b).IsTrue();
}
[Test]
public async Task I_can_compare_non_generic_results_with_operator_and_get_true_for_failure_and_failure()
{
var a = Prelude.Failure("error 1");
var b = Prelude.Failure("error 2");
await Assert.That(a == b).IsTrue();
}
[Test]
public async Task I_can_compare_non_generic_results_with_operator_and_get_false_for_success_and_failure()
{
var a = Prelude.Success();
var b = Prelude.Failure("error");
await Assert.That(a == b).IsFalse();
}
[Test]
public async Task I_can_compare_non_generic_results_with_operator_and_handle_nulls()
{
Result? a = null;
Result? b = null;
var c = Prelude.Success();
await Assert.That(a == b).IsTrue();
await Assert.That(a == c).IsFalse();
await Assert.That(c == a).IsFalse();
await Assert.That(a != b).IsFalse();
}
[Test]
public async Task I_can_compare_generic_results_with_operator_and_get_true_for_success_with_equal_value()
{
var a = Prelude.Success(2);
var b = Prelude.Success(2);
await Assert.That(a == b).IsTrue();
}
[Test]
public async Task I_can_compare_generic_results_with_operator_and_get_false_for_success_with_unequal_value()
{
var a = Prelude.Success(2);
var b = Prelude.Success(3);
await Assert.That(a == b).IsFalse();
}
[Test]
public async Task I_can_compare_generic_results_with_operator_and_get_true_for_failure_and_failure()
{
var a = Prelude.Failure<int>("error 1");
var b = Prelude.Failure<int>("error 2");
await Assert.That(a == b).IsTrue();
}
[Test]
public async Task I_can_compare_generic_result_with_value_using_operator_true_when_success_and_equal()
{
var a = Prelude.Success(2);
var b = 2;
await Assert.That(a == b).IsTrue();
}
[Test]
public async Task I_can_compare_generic_result_with_value_using_operator_false_when_failure()
{
var a = Prelude.Failure<int>("error");
var b = 2;
await Assert.That(a == b).IsFalse();
}
[Test]
public async Task I_can_get_hashcode_non_generic_success_and_failure()
{
var success = Prelude.Success();
var failure = Prelude.Failure("error");
await Assert.That(success.GetHashCode()).IsEqualTo(true.GetHashCode());
await Assert.That(failure.GetHashCode()).IsEqualTo(false.GetHashCode());
}
}

View file

@ -0,0 +1,96 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class ResultTests
{
[Test]
public async Task I_can_create_new_success_result_from_t()
{
var result = new Result<int>(1);
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.IsFailure).IsFalse();
await Assert.That(result.Value).IsNotEqualTo(default);
await Assert.That(result.Error).IsNull();
}
[Test]
public async Task I_can_create_new_failure_result_from_error()
{
var result = new Result<int>(new CustomTestError());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
await Assert.That(result.IsFailure).IsTrue();
await Assert.That(result.Value).IsEqualTo(default(int));
await Assert.That(result.Error).IsTypeOf<CustomTestError>();
}
[Test]
public async Task I_can_to_string_success_result_value()
{
Result<int> result = 2;
await Assert.That(result.ToString()).IsEqualTo("Success { 2 }");
}
[Test]
public async Task I_can_to_string_failure_result_value()
{
Result<int> result = new StringError("error");
await Assert.That(result.ToString()).IsEqualTo("Failure { error }");
}
[Test]
public async Task I_can_create_new_success_result()
{
var result = new Result();
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.IsFailure).IsFalse();
await Assert.That(result.Error).IsNull();
}
[Test]
public async Task I_can_create_new_failure_result()
{
var result = new Result(new CustomTestError());
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsFalse();
await Assert.That(result.IsFailure).IsTrue();
await Assert.That(result.Error).IsTypeOf<CustomTestError>();
}
[Test]
public async Task I_can_to_string_success_result()
{
var result = new Result();
await Assert.That(result.ToString()).IsEqualTo("Success");
}
[Test]
public async Task I_can_to_string_failure_result()
{
var result = new Result(new StringError("error"));
await Assert.That(result.ToString()).IsEqualTo("Failure { error }");
}
[Test]
public async Task I_can_use_generic_result_as_non_generic_result()
{
Result result = new Result<int>(1);
using var scope = Assert.Multiple();
await Assert.That(result.IsSuccess).IsTrue();
await Assert.That(result.IsFailure).IsFalse();
await Assert.That(result.Error).IsNull();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,99 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class ResultUnboxTests
{
[Test]
public async Task I_can_try_get_value_and_it_returns_true_and_sets_value_for_success_with_1_param()
{
var result = Prelude.Success(2);
var ok = result.TryGetValue(out int value);
using var scope = Assert.Multiple();
await Assert.That(ok).IsTrue();
await Assert.That(value).IsEqualTo(2);
}
[Test]
public async Task I_can_try_get_value_and_it_returns_false_for_failure_with_1_param()
{
var result = Prelude.Failure<int>("error");
var ok = result.TryGetValue(out int value);
using var scope = Assert.Multiple();
await Assert.That(ok).IsFalse();
await Assert.That(value).IsEqualTo(default(int));
}
[Test]
public async Task I_can_try_get_value_and_it_returns_true_and_sets_value_for_success_with_2_param()
{
var result = Prelude.Success(2);
var ok = result.TryGetValue(out int value, out var error);
using var scope = Assert.Multiple();
await Assert.That(ok).IsTrue();
await Assert.That(value).IsEqualTo(2);
await Assert.That(error).IsEqualTo(default(Error));
}
[Test]
public async Task I_can_try_get_value_and_it_returns_false_and_sets_error_for_failure_with_2_param()
{
var result = Prelude.Failure<int>("error");
var ok = result.TryGetValue(out int value, out var error);
using var scope = Assert.Multiple();
await Assert.That(ok).IsFalse();
await Assert.That(value).IsEqualTo(default(int));
await Assert.That(error?.Message).IsEqualTo("error");
}
[Test]
public async Task I_can_try_get_error_and_it_returns_true_and_sets_error_for_failure_with_1_param()
{
var result = Prelude.Failure<int>("error");
var ok = result.TryGetValue(out Error? error);
using var scope = Assert.Multiple();
await Assert.That(ok).IsTrue();
await Assert.That(error?.Message).IsEqualTo("error");
}
[Test]
public async Task I_can_try_get_error_and_it_returns_false_for_success_with_1_param()
{
var result = Prelude.Success(2);
var ok = result.TryGetValue(out Error? error);
using var scope = Assert.Multiple();
await Assert.That(ok).IsFalse();
await Assert.That(error).IsEqualTo(default(Error));
}
[Test]
public async Task I_can_try_get_error_and_it_returns_true_and_sets_error_for_failure_with_2_param()
{
var result = Prelude.Failure<int>("error");
var ok = result.TryGetValue(out Error? error, out var value);
using var scope = Assert.Multiple();
await Assert.That(ok).IsTrue();
await Assert.That(error?.Message).IsEqualTo("error");
await Assert.That(value).IsEqualTo(default(int));
}
[Test]
public async Task I_can_try_get_error_and_it_returns_false_and_sets_value_for_success_with_2_param()
{
var result = Prelude.Success(2);
var ok = result.TryGetValue(out Error? error, out var value);
using var scope = Assert.Multiple();
await Assert.That(ok).IsFalse();
await Assert.That(error).IsEqualTo(default(Error));
await Assert.That(value).IsEqualTo(2);
}
}

View file

@ -0,0 +1,11 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class CustomTestError : Error
{
internal const string DefaultMessage = "This is a custom error for test";
public override string Message => DefaultMessage;
}

View file

@ -0,0 +1,8 @@
// Copyright (c) The Geekeey Authors
// SPDX-License-Identifier: EUPL-1.2
namespace Geekeey.Request.Result.Tests;
internal sealed class CustomTestException : Exception
{
}