diff options
Diffstat (limited to 'tests/Cepis.Tests/LookupTests.cs')
| -rw-r--r-- | tests/Cepis.Tests/LookupTests.cs | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/tests/Cepis.Tests/LookupTests.cs b/tests/Cepis.Tests/LookupTests.cs new file mode 100644 index 0000000..ad3e2bf --- /dev/null +++ b/tests/Cepis.Tests/LookupTests.cs @@ -0,0 +1,168 @@ +namespace Cepis.Tests; + +/// <summary>A single lookup: the happy path, the coordinate, and the refusals.</summary> +public sealed class LookupTests : HttpTestBase +{ + [Fact] + public async Task ReadsEveryField() + { + Server.Respond("/01001000", Reply.Of(200, Fixtures.SeAddress)); + + var address = await Client.LookupAsync("01001-000"); + + Assert.Equal("01001000", address.Cep); + Assert.Equal("01001-000", address.FormattedCep); + Assert.Equal("Praça da Sé", address.Logradouro); + Assert.Equal("lado ímpar", address.Complemento); + Assert.Equal("", address.Unidade); + Assert.Equal("Sé", address.Bairro); + Assert.Equal("São Paulo", address.Localidade); + Assert.Equal("SP", address.UF); + Assert.Equal("São Paulo", address.Estado); + Assert.Equal("Sudeste", address.Regiao); + Assert.Equal("3550308", address.Ibge); + Assert.Equal("1004", address.Gia); + Assert.Equal("11", address.Ddd); + Assert.Equal("7107", address.Siafi); + } + + [Fact] + public async Task TheMaskIsStrippedBeforeTheRequest() + { + Server.Respond("/01001000", Reply.Of(200, Fixtures.SeAddress)); + + await Client.LookupAsync("01001-000"); + + Assert.Equal("/01001000", Assert.Single(Server.Calls).Path); + } + + [Fact] + public async Task ReadsTheCoordinate() + { + Server.Respond("/01001000", Reply.Of(200, Fixtures.SeAddress)); + + var address = await Client.LookupAsync("01001000"); + + var geo = address.Geo; + Assert.NotNull(geo); + Assert.Equal(-23.567202, geo.Lat, 6); + Assert.Equal(-46.649659, geo.Lon, 6); + Assert.Equal(1084, geo.RaioM); + Assert.Equal("logradouro", geo.Precisao); + Assert.True(geo.IsPrecise); + } + + [Fact] + public async Task AnAbsentCoordinateIsNull() + { + Server.Respond("/20040020", Reply.Of(200, Fixtures.NoGeoAddress)); + + var address = await Client.LookupAsync("20040020"); + + Assert.Null(address.Geo); + Assert.Equal("Rio de Janeiro", address.Localidade); + } + + [Fact] + public async Task AMalformedCoordinateDoesNotLoseTheAddress() + { + Server.Respond("/01001000", Reply.Of(200, Fixtures.BrokenGeoAddress)); + + var address = await Client.LookupAsync("01001000"); + + Assert.Null(address.Geo); + Assert.Equal("São Paulo", address.Localidade); + } + + [Fact] + public async Task ACoordinateOfTheWrongShapeIsDropped() + { + Server.Respond("/01001000", Reply.Of(200, """{"cep":"01001000","localidade":"X","geo":[]}""")); + + var address = await Client.LookupAsync("01001000"); + + Assert.Null(address.Geo); + Assert.Equal("X", address.Localidade); + } + + [Fact] + public async Task AFieldThisLibraryDoesNotKnowIsKept() + { + Server.Respond("/01001000", Reply.Of(200, Fixtures.FutureAddress)); + + var address = await Client.LookupAsync("01001000"); + + Assert.Equal("São Paulo", address.Localidade); + var extra = address.Extra; + Assert.NotNull(extra); + Assert.Equal("01000000", extra["cep_pai"].GetString()); + } + + [Fact] + public async Task AMissingCepThrows() + { + Server.Respond("/99999999", Reply.Of(404, Fixtures.NotFound)); + + var failure = await Assert.ThrowsAsync<CepNotFoundException>( + () => Client.LookupAsync("99999999")); + + Assert.Contains("99999999", failure.Message, StringComparison.Ordinal); + } + + [Fact] + public async Task A404IsNeverRetried() + { + Server.Respond("/99999999", Reply.Of(404, Fixtures.NotFound)); + + await Assert.ThrowsAsync<CepNotFoundException>(() => Client.LookupAsync("99999999")); + + Assert.Equal(1, Server.Count("/99999999")); + } + + [Fact] + public async Task A400CarriesTheApiMessage() + { + Server.Respond("/00000000", Reply.Of(400, Fixtures.InvalidCep)); + + var failure = await Assert.ThrowsAsync<InvalidCepException>( + () => Client.LookupAsync("00000000")); + + Assert.Equal("CEP deve ter 8 dígitos", failure.Message); + Assert.Equal(1, Server.Count("/00000000")); + } + + [Fact] + public async Task AMalformedCepCostsNoRequest() + { + await Assert.ThrowsAsync<InvalidCepException>(() => Client.LookupAsync("1234567")); + + Assert.Empty(Server.Calls); + } + + [Fact] + public async Task AnUnintelligibleBodyIsDiagnosed() + { + Server.Respond("/01001000", Reply.Of(200, "<html><body>captive portal</body></html>")); + + await Assert.ThrowsAsync<InvalidResponseException>(() => Client.LookupAsync("01001000")); + } + + [Fact] + public async Task AJsonBodyThatIsNotAnObjectIsDiagnosed() + { + Server.Respond("/01001000", Reply.Of(200, "null")); + + await Assert.ThrowsAsync<InvalidResponseException>(() => Client.LookupAsync("01001000")); + } + + [Fact] + public async Task ACancelledCallDoesNotBecomeANetworkError() + { + Server.Respond("/01001000", Reply.Of(200, Fixtures.SeAddress)); + using var cancellation = new CancellationTokenSource(); + await cancellation.CancelAsync(); + + await Assert.ThrowsAnyAsync<OperationCanceledException>( + () => Client.LookupAsync("01001000", cancellation.Token)); + } +} |