mirror of
https://github.com/bitwarden/server
synced 2025-12-24 20:23:21 +00:00
* Refactor IntegrationHandlerResult to provide more detail around failures * ServiceUnavailable now retryable, more explicit http status handling, more consistency with different handlers, additional xmldocs * Address PR feedback
199 lines
8.7 KiB
C#
199 lines
8.7 KiB
C#
using System.Text.Json;
|
|
using Bit.Core.AdminConsole.Models.Data.EventIntegrations;
|
|
using Bit.Core.Services;
|
|
using Bit.Test.Common.AutoFixture;
|
|
using Bit.Test.Common.AutoFixture.Attributes;
|
|
using Bit.Test.Common.Helpers;
|
|
using Microsoft.Rest;
|
|
using NSubstitute;
|
|
using NSubstitute.ExceptionExtensions;
|
|
using Xunit;
|
|
|
|
namespace Bit.Core.Test.Services;
|
|
|
|
[SutProviderCustomize]
|
|
public class TeamsIntegrationHandlerTests
|
|
{
|
|
private readonly ITeamsService _teamsService = Substitute.For<ITeamsService>();
|
|
private readonly string _channelId = "C12345";
|
|
private readonly Uri _serviceUrl = new Uri("http://localhost");
|
|
|
|
private SutProvider<TeamsIntegrationHandler> GetSutProvider()
|
|
{
|
|
return new SutProvider<TeamsIntegrationHandler>()
|
|
.SetDependency(_teamsService)
|
|
.Create();
|
|
}
|
|
|
|
[Theory, BitAutoData]
|
|
public async Task HandleAsync_SuccessfulRequest_ReturnsSuccess(IntegrationMessage<TeamsIntegrationConfigurationDetails> message)
|
|
{
|
|
var sutProvider = GetSutProvider();
|
|
message.Configuration = new TeamsIntegrationConfigurationDetails(_channelId, _serviceUrl);
|
|
|
|
var result = await sutProvider.Sut.HandleAsync(message);
|
|
|
|
Assert.True(result.Success);
|
|
Assert.Equal(result.Message, message);
|
|
|
|
await sutProvider.GetDependency<ITeamsService>().Received(1).SendMessageToChannelAsync(
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_serviceUrl)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_channelId)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(message.RenderedTemplate))
|
|
);
|
|
}
|
|
|
|
[Theory, BitAutoData]
|
|
public async Task HandleAsync_ArgumentException_ReturnsConfigurationError(IntegrationMessage<TeamsIntegrationConfigurationDetails> message)
|
|
{
|
|
var sutProvider = GetSutProvider();
|
|
message.Configuration = new TeamsIntegrationConfigurationDetails(_channelId, _serviceUrl);
|
|
|
|
sutProvider.GetDependency<ITeamsService>()
|
|
.SendMessageToChannelAsync(Arg.Any<Uri>(), Arg.Any<string>(), Arg.Any<string>())
|
|
.ThrowsAsync(new ArgumentException("argument error"));
|
|
var result = await sutProvider.Sut.HandleAsync(message);
|
|
|
|
Assert.False(result.Success);
|
|
Assert.Equal(IntegrationFailureCategory.ConfigurationError, result.Category);
|
|
Assert.False(result.Retryable);
|
|
Assert.Equal(result.Message, message);
|
|
|
|
await sutProvider.GetDependency<ITeamsService>().Received(1).SendMessageToChannelAsync(
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_serviceUrl)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_channelId)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(message.RenderedTemplate))
|
|
);
|
|
}
|
|
|
|
[Theory, BitAutoData]
|
|
public async Task HandleAsync_JsonException_ReturnsPermanentFailure(IntegrationMessage<TeamsIntegrationConfigurationDetails> message)
|
|
{
|
|
var sutProvider = GetSutProvider();
|
|
message.Configuration = new TeamsIntegrationConfigurationDetails(_channelId, _serviceUrl);
|
|
|
|
sutProvider.GetDependency<ITeamsService>()
|
|
.SendMessageToChannelAsync(Arg.Any<Uri>(), Arg.Any<string>(), Arg.Any<string>())
|
|
.ThrowsAsync(new JsonException("JSON error"));
|
|
var result = await sutProvider.Sut.HandleAsync(message);
|
|
|
|
Assert.False(result.Success);
|
|
Assert.Equal(IntegrationFailureCategory.PermanentFailure, result.Category);
|
|
Assert.False(result.Retryable);
|
|
Assert.Equal(result.Message, message);
|
|
|
|
await sutProvider.GetDependency<ITeamsService>().Received(1).SendMessageToChannelAsync(
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_serviceUrl)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_channelId)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(message.RenderedTemplate))
|
|
);
|
|
}
|
|
|
|
[Theory, BitAutoData]
|
|
public async Task HandleAsync_UriFormatException_ReturnsConfigurationError(IntegrationMessage<TeamsIntegrationConfigurationDetails> message)
|
|
{
|
|
var sutProvider = GetSutProvider();
|
|
message.Configuration = new TeamsIntegrationConfigurationDetails(_channelId, _serviceUrl);
|
|
|
|
sutProvider.GetDependency<ITeamsService>()
|
|
.SendMessageToChannelAsync(Arg.Any<Uri>(), Arg.Any<string>(), Arg.Any<string>())
|
|
.ThrowsAsync(new UriFormatException("Bad URI"));
|
|
var result = await sutProvider.Sut.HandleAsync(message);
|
|
|
|
Assert.False(result.Success);
|
|
Assert.Equal(IntegrationFailureCategory.ConfigurationError, result.Category);
|
|
Assert.False(result.Retryable);
|
|
Assert.Equal(result.Message, message);
|
|
|
|
await sutProvider.GetDependency<ITeamsService>().Received(1).SendMessageToChannelAsync(
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_serviceUrl)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_channelId)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(message.RenderedTemplate))
|
|
);
|
|
}
|
|
|
|
[Theory, BitAutoData]
|
|
public async Task HandleAsync_HttpExceptionForbidden_ReturnsAuthenticationFailed(IntegrationMessage<TeamsIntegrationConfigurationDetails> message)
|
|
{
|
|
var sutProvider = GetSutProvider();
|
|
message.Configuration = new TeamsIntegrationConfigurationDetails(_channelId, _serviceUrl);
|
|
|
|
sutProvider.GetDependency<ITeamsService>()
|
|
.SendMessageToChannelAsync(Arg.Any<Uri>(), Arg.Any<string>(), Arg.Any<string>())
|
|
.ThrowsAsync(new HttpOperationException("Server error")
|
|
{
|
|
Response = new HttpResponseMessageWrapper(
|
|
new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden),
|
|
"Forbidden"
|
|
)
|
|
}
|
|
);
|
|
var result = await sutProvider.Sut.HandleAsync(message);
|
|
|
|
Assert.False(result.Success);
|
|
Assert.Equal(IntegrationFailureCategory.AuthenticationFailed, result.Category);
|
|
Assert.False(result.Retryable);
|
|
Assert.Equal(result.Message, message);
|
|
|
|
await sutProvider.GetDependency<ITeamsService>().Received(1).SendMessageToChannelAsync(
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_serviceUrl)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_channelId)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(message.RenderedTemplate))
|
|
);
|
|
}
|
|
|
|
[Theory, BitAutoData]
|
|
public async Task HandleAsync_HttpExceptionTooManyRequests_ReturnsRateLimited(IntegrationMessage<TeamsIntegrationConfigurationDetails> message)
|
|
{
|
|
var sutProvider = GetSutProvider();
|
|
message.Configuration = new TeamsIntegrationConfigurationDetails(_channelId, _serviceUrl);
|
|
|
|
sutProvider.GetDependency<ITeamsService>()
|
|
.SendMessageToChannelAsync(Arg.Any<Uri>(), Arg.Any<string>(), Arg.Any<string>())
|
|
.ThrowsAsync(new HttpOperationException("Server error")
|
|
{
|
|
Response = new HttpResponseMessageWrapper(
|
|
new HttpResponseMessage(System.Net.HttpStatusCode.TooManyRequests),
|
|
"Too Many Requests"
|
|
)
|
|
}
|
|
);
|
|
|
|
var result = await sutProvider.Sut.HandleAsync(message);
|
|
|
|
Assert.False(result.Success);
|
|
Assert.Equal(IntegrationFailureCategory.RateLimited, result.Category);
|
|
Assert.True(result.Retryable);
|
|
Assert.Equal(result.Message, message);
|
|
|
|
await sutProvider.GetDependency<ITeamsService>().Received(1).SendMessageToChannelAsync(
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_serviceUrl)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_channelId)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(message.RenderedTemplate))
|
|
);
|
|
}
|
|
|
|
[Theory, BitAutoData]
|
|
public async Task HandleAsync_UnknownException_ReturnsTransientError(IntegrationMessage<TeamsIntegrationConfigurationDetails> message)
|
|
{
|
|
var sutProvider = GetSutProvider();
|
|
message.Configuration = new TeamsIntegrationConfigurationDetails(_channelId, _serviceUrl);
|
|
|
|
sutProvider.GetDependency<ITeamsService>()
|
|
.SendMessageToChannelAsync(Arg.Any<Uri>(), Arg.Any<string>(), Arg.Any<string>())
|
|
.ThrowsAsync(new Exception("Unknown error"));
|
|
var result = await sutProvider.Sut.HandleAsync(message);
|
|
|
|
Assert.False(result.Success);
|
|
Assert.Equal(IntegrationFailureCategory.TransientError, result.Category);
|
|
Assert.True(result.Retryable);
|
|
Assert.Equal(result.Message, message);
|
|
|
|
await sutProvider.GetDependency<ITeamsService>().Received(1).SendMessageToChannelAsync(
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_serviceUrl)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(_channelId)),
|
|
Arg.Is(AssertHelper.AssertPropertyEqual(message.RenderedTemplate))
|
|
);
|
|
}
|
|
}
|