1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-05 05:00:19 -05:00

[PM-15621] Add support for handling multiple validators.

This commit is contained in:
Jimmy Vo 2025-03-06 16:56:48 -05:00
parent bea0d0d76f
commit 9281b8623a
No known key found for this signature in database
GPG Key ID: 7CB834D6F4FFCA11
2 changed files with 166 additions and 0 deletions

View File

@ -0,0 +1,36 @@
using Bit.Core.Models.Commands;
namespace Bit.Core.Validators;
public static class CommandResultValidator
{
public static CommandResult ExecuteValidators(Func<CommandResult>[] validators)
{
foreach (var validator in validators)
{
var result = validator();
if (result is not Success)
{
return result;
}
}
return new Success();
}
public static async Task<CommandResult> ExecuteValidatorAsync(Func<Task<CommandResult>>[] validators)
{
foreach (var validator in validators)
{
var result = await validator();
if (result is not Success)
{
return result;
}
}
return new Success();
}
}

View File

@ -0,0 +1,130 @@
using Bit.Core.Models.Commands;
using Bit.Core.Validators;
using Xunit;
namespace Bit.Core.Test.Validators;
public class CommandResultValidatorTests
{
[Fact]
public void ExecuteValidators_AllSuccess_ReturnsSuccess()
{
// Arrange
var validators = new Func<CommandResult>[]
{
() => new Success(),
() => new Success(),
() => new Success()
};
// Act
var result = CommandResultValidator.ExecuteValidators(validators);
// Assert
Assert.IsType<Success>(result);
}
public static IEnumerable<object[]> TestCases()
{
yield return new object[]
{
new Func<CommandResult>[]
{
() => new Failure("First failure"),
() => new Success(),
() => new Failure("Second failure"),
}
};
yield return new object[]
{
new Func<CommandResult>[]
{
() => new Success(),
() => new Failure("First failure"),
() => new Failure("Second failure"),
}
};
yield return new object[]
{
new Func<CommandResult>[]
{
() => new Success(),
() => new Success(),
() => new Failure("First failure"),
}
};
}
[Theory]
[MemberData(nameof(TestCases))]
public void ExecuteValidators_WhenValidatorFails_ReturnsFirstFailure(Func<CommandResult>[] validators)
{
// Act
var result = CommandResultValidator.ExecuteValidators(validators);
// Assert
Assert.IsType<Failure>(result);
Assert.Equal(["First failure"], ((Failure)result).ErrorMessages);
}
[Fact]
public async Task ExecuteValidatorAsync_AllSuccess_ReturnsSuccess()
{
// Arrange
var validators = new Func<Task<CommandResult>>[]
{
async () => await Task.FromResult(new Success()),
async () => await Task.FromResult(new Success()),
async () => await Task.FromResult(new Success())
};
// Act
var result = await CommandResultValidator.ExecuteValidatorAsync(validators);
// Assert
Assert.IsType<Success>(result);
}
public static IEnumerable<object[]> AsyncTestCases()
{
yield return new object[]
{
new Func<Task<CommandResult>>[]
{
async () => await Task.FromResult(new Failure("First failure")),
async () => await Task.FromResult(new Success()),
async () => await Task.FromResult(new Failure("Second failure")),
}
};
yield return new object[]
{
new Func<Task<CommandResult>>[]
{
async () => await Task.FromResult(new Success()),
async () => await Task.FromResult(new Failure("First failure")),
async () => await Task.FromResult(new Failure("Second failure")),
}
};
yield return new object[]
{
new Func<Task<CommandResult>>[]
{
async () => await Task.FromResult(new Success()),
async () => await Task.FromResult(new Success()),
async () => await Task.FromResult(new Failure("First failure")),
}
};
}
[Theory]
[MemberData(nameof(AsyncTestCases))]
public async Task ExecuteValidatorAsync_WhenValidatorFails_ReturnsFirstFailure(Func<Task<CommandResult>>[] validators)
{
// Act
var result = await CommandResultValidator.ExecuteValidatorAsync(validators);
// Assert
Assert.IsType<Failure>(result);
Assert.Equal(["First failure"], ((Failure)result).ErrorMessages);
}
}