Initial commit
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using RudderSdk.Core;
|
||||
using RudderSdk.Core.Models.Player;
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace RudderSdk.Core.Tests;
|
||||
|
||||
public sealed class HttpClientTransportTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Maps_404_To_NotFoundException_With_Code_And_RequestId()
|
||||
{
|
||||
var transport = CreateTransport(_ => Error(HttpStatusCode.NotFound, """{"code":"store_not_found","error":"Store not found","requestId":"req-123"}"""));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<RudderNotFoundException>(
|
||||
() => transport.SendAsync<object, PlayerProfile>("GET", "/sdk/v1/stores/main", null, "token"));
|
||||
|
||||
Assert.Equal(404, exception.StatusCode);
|
||||
Assert.Equal("store_not_found", exception.Code);
|
||||
Assert.Equal("req-123", exception.RequestId);
|
||||
Assert.Equal("Store not found", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Maps_429_To_RateLimitException()
|
||||
{
|
||||
var transport = CreateTransport(_ => Error(HttpStatusCode.TooManyRequests, """{"code":"rate_limited","error":"Slow down"}"""));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<RudderRateLimitException>(
|
||||
() => transport.SendAsync<object, PlayerProfile>("GET", "/sdk/v1/player/information", null, null));
|
||||
|
||||
Assert.Equal(429, exception.StatusCode);
|
||||
Assert.Equal("rate_limited", exception.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Maps_401_To_AuthException()
|
||||
{
|
||||
var transport = CreateTransport(_ => Error(HttpStatusCode.Unauthorized, """{"error":"Unauthorized"}"""));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<RudderAuthException>(
|
||||
() => transport.SendAsync<object, PlayerProfile>("GET", "/sdk/v1/player/information", null, null));
|
||||
|
||||
Assert.Equal(401, exception.StatusCode);
|
||||
Assert.Null(exception.RequestId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Maps_500_To_Base_ApiException()
|
||||
{
|
||||
var transport = CreateTransport(_ => Error(HttpStatusCode.InternalServerError, """{"code":"internal","error":"Boom"}"""));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<RudderApiException>(
|
||||
() => transport.SendAsync<object, PlayerProfile>("GET", "/sdk/v1/player/information", null, null));
|
||||
|
||||
Assert.Equal(typeof(RudderApiException), exception.GetType());
|
||||
Assert.Equal(500, exception.StatusCode);
|
||||
Assert.Equal("internal", exception.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Non_Json_Error_Body_Falls_Back_To_Reason_Phrase()
|
||||
{
|
||||
var transport = CreateTransport(_ => new HttpResponseMessage(HttpStatusCode.BadGateway)
|
||||
{
|
||||
Content = new StringContent("<html>bad gateway</html>", Encoding.UTF8, "text/html"),
|
||||
ReasonPhrase = "Bad Gateway"
|
||||
});
|
||||
|
||||
var exception = await Assert.ThrowsAsync<RudderApiException>(
|
||||
() => transport.SendAsync<object, PlayerProfile>("GET", "/sdk/v1/player/information", null, null));
|
||||
|
||||
Assert.Equal(502, exception.StatusCode);
|
||||
Assert.Equal(string.Empty, exception.Code);
|
||||
Assert.Equal("Bad Gateway", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Network_Failure_Maps_To_NetworkException()
|
||||
{
|
||||
var transport = CreateTransport(_ => throw new HttpRequestException("Connection refused"));
|
||||
|
||||
var exception = await Assert.ThrowsAsync<RudderNetworkException>(
|
||||
() => transport.SendAsync<object, PlayerProfile>("GET", "/sdk/v1/player/information", null, null));
|
||||
|
||||
Assert.Equal(0, exception.StatusCode);
|
||||
Assert.Equal("Connection refused", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Success_Deserializes_Response_And_Sends_Bearer_Token()
|
||||
{
|
||||
StubHandler? handler = null;
|
||||
var transport = CreateTransport(request =>
|
||||
{
|
||||
return new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{
|
||||
Content = new StringContent("""{"player":{"id":"p1"},"wallets":[]}""", Encoding.UTF8, "application/json")
|
||||
};
|
||||
}, h => handler = h);
|
||||
|
||||
var profile = await transport.SendAsync<object, PlayerProfile>("GET", "/sdk/v1/player/information", null, "access-token");
|
||||
|
||||
Assert.Equal("p1", profile.Player.Id);
|
||||
Assert.Equal("Bearer", handler!.LastRequest!.Headers.Authorization!.Scheme);
|
||||
Assert.Equal("access-token", handler.LastRequest.Headers.Authorization.Parameter);
|
||||
Assert.Equal("http://localhost:8082/sdk/v1/player/information", handler.LastRequest.RequestUri!.ToString());
|
||||
}
|
||||
|
||||
private static HttpClientTransport CreateTransport(
|
||||
Func<HttpRequestMessage, HttpResponseMessage> respond,
|
||||
Action<StubHandler>? capture = null)
|
||||
{
|
||||
var handler = new StubHandler(respond);
|
||||
capture?.Invoke(handler);
|
||||
return new HttpClientTransport("http://localhost:8082/", new HttpClient(handler));
|
||||
}
|
||||
|
||||
private static HttpResponseMessage Error(HttpStatusCode statusCode, string json)
|
||||
{
|
||||
return new HttpResponseMessage(statusCode)
|
||||
{
|
||||
Content = new StringContent(json, Encoding.UTF8, "application/json")
|
||||
};
|
||||
}
|
||||
|
||||
private sealed class StubHandler : HttpMessageHandler
|
||||
{
|
||||
private readonly Func<HttpRequestMessage, HttpResponseMessage> _respond;
|
||||
|
||||
public StubHandler(Func<HttpRequestMessage, HttpResponseMessage> respond) => _respond = respond;
|
||||
|
||||
public HttpRequestMessage? LastRequest { get; private set; }
|
||||
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
LastRequest = request;
|
||||
return Task.FromResult(_respond(request));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user