Files

172 lines
5.9 KiB
C#

using System.Net;
using System.Text.Json;
using StevanFreeborn.Atproto.IdentityResolver.Exceptions;
using RichardSzalay.MockHttp;
using StevanFreeborn.Atproto.IdentityResolver.Retrieval;
namespace StevanFreeborn.Atproto.IdentityResolver.Tests.Unit;
public sealed class DefaultDidRetrieverTests : IDisposable
{
private readonly MockHttpMessageHandler _mockHttpMessageHandler = new();
private readonly DefaultDidRetriever _sut;
public DefaultDidRetrieverTests()
{
_sut = new(_mockHttpMessageHandler.ToHttpClient());
}
public void Dispose()
{
_mockHttpMessageHandler.Dispose();
}
[Fact]
public async Task GetByDnsOrThrowAsync_WhenHandleIsNull_ItShouldThrowArgumentNullException()
{
var act = async () => await _sut.GetByDnsOrThrowAsync(null!, TestContext.Current.CancellationToken);
var e = await act.Should().ThrowAsync<ArgumentNullException>();
}
[Fact]
public async Task GetByDnsOrThrowAsync_WhenResponseIsNotSuccessful_ItShouldThrowDidNotFoundException()
{
var handle = "stevan.cc";
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://cloudflare-dns.com/dns-query?name=_atproto.{handle}&type=TXT")
.Respond(HttpStatusCode.InternalServerError);
var act = async () => await _sut.GetByDnsOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
await act.Should().ThrowAsync<DidNotFoundException>();
}
[Fact]
public async Task GetByDnsOrThrowAsync_WhenResponseIsSuccessfulButDeserialziationFails_ItShouldThrowDidNotFoundException()
{
var handle = "stevan.cc";
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://cloudflare-dns.com/dns-query?name=_atproto.{handle}&type=TXT")
.Respond("application/json", JsonSerializer.Serialize("null"));
var act = async () => await _sut.GetByDnsOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
var e = await act.Should().ThrowAsync<DidNotFoundException>();
e.WithInnerException<JsonException>();
}
[Fact]
public async Task GetByDnsOrThrowAsync_WhenResponseIsSuccessfulButBodyIsNull_ItShouldThrowDidNotFoundException()
{
var handle = "stevan.cc";
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://cloudflare-dns.com/dns-query?name=_atproto.{handle}&type=TXT")
.Respond("application/json", "null");
var act = async () => await _sut.GetByDnsOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
await act.Should().ThrowAsync<DidNotFoundException>();
}
[Fact]
public async Task GetByDnsOrThrowAsync_WhenResponseIsSuccessfulButNoAnswers_ItShouldThrowDidNotFoundException()
{
var handle = "stevan.cc";
var response = new DnsQueryResponse();
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://cloudflare-dns.com/dns-query?name=_atproto.{handle}&type=TXT")
.Respond("application/json", JsonSerializer.Serialize(response));
var act = async () => await _sut.GetByDnsOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
await act.Should().ThrowAsync<DidNotFoundException>();
}
[Fact]
public async Task GetByDnsOrThrowAsync_WhenResponseIsSuccessfulButTextRecordValueFormattedIncorrectly_ItShouldThrowDidNotFoundException()
{
var handle = "stevan.cc";
var response = new DnsQueryResponse()
{
Answer = [new() { Data = $"did:web:{handle}" }]
};
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://cloudflare-dns.com/dns-query?name=_atproto.{handle}&type=TXT")
.Respond("application/json", JsonSerializer.Serialize(response));
var act = async () => await _sut.GetByDnsOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
await act.Should().ThrowAsync<DidNotFoundException>();
}
[Fact]
public async Task GetByDnsOrThrowAsync_WhenResponseIsSuccessfulAndTextRecordValueFormattedCorrectly_ItShouldReturnDid()
{
var handle = "stevan.cc";
var response = new DnsQueryResponse()
{
Answer = [new() { Data = $@"did=did:web:{handle}" }]
};
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://cloudflare-dns.com/dns-query?name=_atproto.{handle}&type=TXT")
.Respond("application/json", JsonSerializer.Serialize(response));
var result = await _sut.GetByDnsOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
result.Should().BeEquivalentTo(Did.From($"did:web:{handle}"));
}
[Fact]
public async Task GetByWellKnownOrThrowAsync_WhenResponseIsUnsuccessful_ItShouldThrowDidNotFoundException()
{
var handle = "stevan.cc";
var did = $"did:web:{handle}";
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://{handle}/.well-known/atproto-did")
.Respond(HttpStatusCode.InternalServerError);
var act = async () => await _sut.GetByWellKnownOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
await act.Should().ThrowAsync<DidNotFoundException>();
}
[Fact]
public async Task GetByWellKnownOrThrowAsync_WhenResponseIsSuccessfulAndButDoesNotContainDid_ItShouldThrowDidNotFoundException()
{
var handle = "stevan.cc";
var did = $"did:web:{handle}";
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://{handle}/.well-known/atproto-did")
.Respond("application/json", JsonSerializer.Serialize(new { did }));
var act = async () => await _sut.GetByWellKnownOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
await act.Should().ThrowAsync<DidNotFoundException>();
}
[Fact]
public async Task GetByWellKnownOrThrowAsync_WhenResponseIsSuccessfulAndContainsDid_ItShouldReturnDid()
{
var handle = "stevan.cc";
var did = $"did:web:{handle}";
_mockHttpMessageHandler
.When(HttpMethod.Get, $"https://{handle}/.well-known/atproto-did")
.Respond("text/plain", did);
var result = await _sut.GetByWellKnownOrThrowAsync(Handle.From(handle), TestContext.Current.CancellationToken);
result.Should().BeEquivalentTo(Did.From(did));
}
}