summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:37:09 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:37:09 -0300
commita891657aa43d2aba06a6347dd2f94edd19afd6ba (patch)
treeb6369ed2c8485455f9c1aa707c1cd287cb8e7065 /test
parent794f28199a4dde9d18ec711864336c96c58bb422 (diff)
downloadd-a891657aa43d2aba06a6347dd2f94edd19afd6ba.tar.gz
Carry the municipality a missing CEP would belong toHEADv0.2.0main
A 404 is rarely a random number: it is usually someone who knows the city and guessed the digits, and the classic guess is the -000 that 957 municipalities never received. The API now attaches a faixa to the not-found body naming the municipality that owns the range, so the caller can say "no such CEP, but that range is Areal/RJ" instead of only "no". It stays an error. Faixa hangs off CepNotFoundException, never off Address, and parsing is deliberately lenient: an absent, malformed or unnamed block yields a null Nullable, so reading the extra context can never cost the caller the answer it already had. cep_ini and cep_fim are the smallest and largest CEP that actually exist there, not the bounds the Correios publish, and the range between them is sparse — hence ceps, so nobody mistakes the pair for a list.
Diffstat (limited to 'test')
-rw-r--r--test/cepis_test.d99
1 files changed, 98 insertions, 1 deletions
diff --git a/test/cepis_test.d b/test/cepis_test.d
index 3ced878..694da0f 100644
--- a/test/cepis_test.d
+++ b/test/cepis_test.d
@@ -16,7 +16,7 @@ module cepis_test;
import core.sync.mutex : Mutex;
import core.thread : Thread;
import core.time : Duration, MonoTime, dur;
-import std.algorithm : filter, map, startsWith;
+import std.algorithm : canFind, filter, map, startsWith;
import std.array : array, join;
import std.conv : to;
import std.exception : assertThrown;
@@ -35,6 +35,22 @@ private enum string SE_ADDRESS = `{
"ddd": "11", "siafi": "7107"
}`;
+/**
+ * A 404 that knows which municipality the CEP would have belonged to.
+ *
+ * `25845000` is the DNE's own start for Areal and does not exist; the smallest
+ * one that does is `25845001`. Fixed here rather than fetched: production does
+ * not serve `faixa` yet, so a live call would pass for the wrong reason.
+ */
+private enum string AREAL_NOT_FOUND = `{
+ "erro": "cep_nao_encontrado", "mensagem": "CEP não existe na base do DNE",
+ "faixa": {
+ "localidade": "Areal", "uf": "RJ", "estado": "Rio de Janeiro",
+ "regiao": "Sudeste", "ibge": "3300225", "cep_ini": "25845001",
+ "cep_fim": "25849899", "ceps": 118
+ }
+}`;
+
private enum string CSV_HEADER = "cep,logradouro,complemento,unidade,bairro,localidade,uf,"
~ "estado,regiao,ibge,gia,ddd,siafi";
@@ -339,6 +355,87 @@ unittest
assert(server.calledTimes("/99999999") == 1);
}
+@("a not-found says which municipality the cep would have belonged to")
+unittest
+{
+ auto server = new TestServer();
+ server.respond("/25845000", Reply(404, AREAL_NOT_FOUND));
+
+ auto client = server.client;
+ bool caught;
+ try
+ client.lookup("25845-000");
+ catch (CepNotFoundException error)
+ {
+ caught = true;
+ assert(error.cep == "25845000");
+ assert(!error.retriable);
+ assert(!error.faixa.isNull);
+
+ const faixa = error.faixa.get;
+ assert(faixa.localidade == "Areal");
+ assert(faixa.uf == "RJ");
+ assert(faixa.estado == "Rio de Janeiro");
+ assert(faixa.regiao == "Sudeste");
+ assert(faixa.ibge == "3300225");
+ assert(faixa.cep_ini == "25845001");
+ assert(faixa.cep_fim == "25849899");
+ assert(faixa.ceps == 118);
+ assert(error.msg.canFind("Areal/RJ"));
+ }
+
+ assert(caught);
+ assert(server.calledTimes("/25845000") == 1);
+}
+
+@("a not-found in a band nobody owns carries no faixa")
+unittest
+{
+ auto server = new TestServer();
+ server.respond("/99999999", Reply(404,
+ `{"erro":"cep_nao_encontrado","mensagem":"CEP não existe na base do DNE"}`));
+
+ auto client = server.client;
+ bool caught;
+ try
+ client.lookup("99999999");
+ catch (CepNotFoundException error)
+ {
+ caught = true;
+ assert(error.faixa.isNull);
+ assert(error.msg.canFind("99999999"));
+ }
+
+ assert(caught);
+}
+
+@("a malformed faixa is still an ordinary not-found")
+unittest
+{
+ foreach (content; [
+ `{"erro":"cep_nao_encontrado","faixa":{}}`,
+ `{"erro":"cep_nao_encontrado","faixa":{"uf":"RJ"}}`,
+ `{"erro":"cep_nao_encontrado","faixa":"Areal"}`,
+ `{"erro":"cep_nao_encontrado","faixa":null}`, `<html>gateway</html>`, ``
+ ])
+ {
+ auto server = new TestServer();
+ server.respond("/99999999", Reply(404, content));
+
+ auto client = server.client;
+ bool caught;
+ try
+ client.lookup("99999999");
+ catch (CepNotFoundException error)
+ {
+ caught = true;
+ assert(error.faixa.isNull);
+ }
+
+ assert(caught);
+ }
+}
+
@("an invalid cep never leaves the machine")
unittest
{