From 4ad42dd0f82e566db4113dc43a301328142bef53 Mon Sep 17 00:00:00 2001 From: Kyle Slusser Date: Sat, 13 Jul 2024 10:15:58 -0400 Subject: [PATCH 1/2] Add FailIf methods accepting a collection of errors --- .../ResultWithoutValueTests.cs | 58 +++++++++++++++++++ src/FluentResults/Factories/Results.cs | 21 +++++++ 2 files changed, 79 insertions(+) diff --git a/src/FluentResults.Test/ResultWithoutValueTests.cs b/src/FluentResults.Test/ResultWithoutValueTests.cs index dcefa38..36c5fe8 100644 --- a/src/FluentResults.Test/ResultWithoutValueTests.cs +++ b/src/FluentResults.Test/ResultWithoutValueTests.cs @@ -271,6 +271,64 @@ public void FailIf_FailedConditionIsTrueAndWithStringErrorMessageFactory_CreateF result.Errors.Single().Message.Should().Be("Error message"); } + [Fact] + public void FailIf_WithErrors_IsFailure() + { + // Arrange + string errorMessage = "Sample Error"; + var errors = new List { new Error(errorMessage) }; + + // Act + var result = Result.FailIf(true, errors); + + // Assert + result.IsFailed.Should().BeTrue(); + result.Errors.Single().Message.Should().Be(errorMessage); + } + + [Fact] + public void FailIf_WithNoErrors_IsSuccess() + { + // Arrange + var errors = new List(); + + // Act + var result = Result.FailIf(false, errors); + + // Assert + Assert.True(result.IsSuccess); + Assert.Empty(result.Errors); + } + + [Fact] + public void FailIfNotEmpty_WithErrors_IsFailure() + { + // Arrange + string errorMessage = "Sample Error"; + var errors = new List { new Error(errorMessage) }; + + // Act + var result = Result.FailIfNotEmpty(errors); + + // Assert + result.IsFailed.Should().BeTrue(); + result.Errors.Single().Message.Should().Be(errorMessage); + } + + [Fact] + public void FailIfNotEmpty_WithNoErrors_IsSuccess() + { + // Arrange + var errors = new List(); + + // Act + var result = Result.FailIfNotEmpty(errors); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Errors.Should().BeEmpty(); + } + [Fact] public void OkIf_SuccessConditionIsTrueAndWithStringErrorMessage_CreateFailedResult() { diff --git a/src/FluentResults/Factories/Results.cs b/src/FluentResults/Factories/Results.cs index 58921b5..30ec4db 100644 --- a/src/FluentResults/Factories/Results.cs +++ b/src/FluentResults/Factories/Results.cs @@ -228,6 +228,27 @@ public static Result FailIf(bool isFailure, Func errorMessageFactory) return isFailure ? Fail(errorMessageFactory.Invoke()) : Ok(); } + /// + /// Create a success/failed result depending on the parameter isFailure containing the specified errors + /// + public static Result FailIf(bool isFailure, IEnumerable errors) + => isFailure ? Fail(errors) : Ok(); + + /// + /// Create a success/failed result if any error objects exist + /// + public static Result FailIfNotEmpty(IEnumerable errors) + => errors.Any() ? Fail(errors) : Ok(); + + /// + /// Create a success/failed result depending if any error objects exist + /// + /// + /// Error is lazily evaluated. + /// + public static Result FailIfNotEmpty(IEnumerable errors, Func func) + => errors.Any() ? Fail(errors.Select(error => func(error))) : Ok(); + /// /// Executes the action. If an exception is thrown within the action then this exception is transformed via the catchHandler to an Error object /// From cfa11a7dcb45261a53af92952eb3ad64a7745bbd Mon Sep 17 00:00:00 2001 From: Kyle Slusser Date: Tue, 30 Jul 2024 18:42:19 -0400 Subject: [PATCH 2/2] Add FailIf and FailIfNotEmpty documentation --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 032e0e7..5d91fc8 100644 --- a/README.md +++ b/README.md @@ -163,10 +163,23 @@ Very often you have to create a fail or success result depending on a condition. var result = string.IsNullOrEmpty(firstName) ? Result.Fail("First Name is empty") : Result.Ok(); ``` -With the methods ```FailIf()``` and ```OkIf()``` you can also write in a more readable way: +With the methods ```FailIf()``` and ```OkIf()``` you can also write in a more readable way. You can also supply a collection of errors: ```csharp var result = Result.FailIf(string.IsNullOrEmpty(firstName), "First Name is empty"); + +bool isValid = false; // Some check +var errors = new List{ new Error("Error 1"), new Error("Error 2") }; + +var result2 = Result.FailIf(isValid, errors); +``` + +If your success check is based on whether or not there are errors, you can use `FailIfNotEmpty()` + +```csharp +var errors = PerformSomeValidation(); + +var result = Result.FailIfNotEmpty(errors); ``` If an error instance should be lazily initialized, overloads accepting ```Func``` or ```Func``` can be used to that effect: @@ -180,6 +193,12 @@ var result = Result.FailIf( bool IsDivisibleByTen(int i) => i % 10 == 0; +var errors = PerformSomeValidation(); + +var result = Result.FailIfNotEmpty( + errors, + (err) => new Error("Custom error message based on err")); + // rest of the code ```