172 lines
5.9 KiB
C#
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));
|
||
|
|
}
|
||
|
|
}
|