summaryrefslogtreecommitdiffstats
path: root/tests/Cepis.Tests/LookupTests.cs
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-26 12:42:38 -0300
committerMurilo Ijanc <[email protected]>2026-07-26 13:10:34 -0300
commita2b10fd494fb389e556e40134031eb86e56e11e7 (patch)
tree08b6df8a06f2c7c15488b90d57a6d8286cd57a22 /tests/Cepis.Tests/LookupTests.cs
downloadcsharp-a2b10fd494fb389e556e40134031eb86e56e11e7.tar.gz
Initial importv0.1.0
Diffstat (limited to 'tests/Cepis.Tests/LookupTests.cs')
-rw-r--r--tests/Cepis.Tests/LookupTests.cs168
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));
+ }
+}