summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:32:01 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:32:01 -0300
commitb402de683eecef4c890081dd72edbcaf57f375e0 (patch)
tree13e184ad13b3cad394e5c84c25b48df3b2052781 /test
parent36a0ddb01a4fcb8fb2fefd7c407ecca0e3e56e7c (diff)
downloadruby-b402de683eecef4c890081dd72edbcaf57f375e0.tar.gz
Expose the band of a CEP that does not existHEADv0.2.0main
A CEP that fails a lookup is rarely a random number: it is someone who knows the city and guessed the digits, most often the -000 that 957 municipalities never received. The API now answers that 404 with an optional faixa naming the municipality those numbers belong to, so the caller can say "not found, but you seem to be looking at Areal/RJ" instead of just "not found". It stays an error. Faixa hangs off CEPNotFound and nothing about it promotes a nonexistent CEP into an address. Its cep_ini/cep_fim are the smallest and largest CEP that really exist there, not the published bounds — the DNE's own start for Areal is the CEP that just failed — and the band is sparse, which is what ceps is for; both facts are spelled out in the docs so nobody iterates the pair. Parsing is deliberately toothless: a missing, empty or malformed faixa, or a 404 body that is not JSON at all, all yield nil. Losing the consolation prize must never replace a clean not-found with a parse failure.
Diffstat (limited to 'test')
-rw-r--r--test/cepis_test.rb61
-rw-r--r--test/test_helper.rb16
2 files changed, 77 insertions, 0 deletions
diff --git a/test/cepis_test.rb b/test/cepis_test.rb
index 06a6bf6..6fd3353 100644
--- a/test/cepis_test.rb
+++ b/test/cepis_test.rb
@@ -91,6 +91,67 @@ class LookupTest < ServerTest
assert_includes error.message, "99999999"
end
+ def test_not_found_carries_the_band
+ body = { "erro" => "cep_nao_encontrado", "mensagem" => "CEP não existe na base do DNE",
+ "faixa" => AREAL_FAIXA }
+ routes.respond("/25845000", [404, JSON.generate(body), {}])
+ error = assert_raises(Cepis::CEPNotFound) { @client.lookup("25845000") }
+
+ assert_equal "Areal", error.faixa.localidade
+ assert_equal "RJ", error.faixa.uf
+ assert_equal "3300225", error.faixa.ibge
+ assert_equal 118, error.faixa.ceps
+ # The band starts above the CEP that just failed: cep_ini is the smallest
+ # CEP that exists, not the DNE's published start, which is 25845000.
+ assert_equal "25845001", error.faixa.cep_ini
+ assert_equal "25849899", error.faixa.cep_fim
+ end
+
+ def test_the_band_names_the_municipality_in_the_message
+ body = { "erro" => "cep_nao_encontrado", "faixa" => AREAL_FAIXA }
+ routes.respond("/25845000", [404, JSON.generate(body), {}])
+ error = assert_raises(Cepis::CEPNotFound) { @client.lookup("25845000") }
+
+ assert_includes error.message, "25845000"
+ assert_includes error.message, "Areal/RJ"
+ end
+
+ def test_band_is_absent_when_no_municipality_owns_the_numbers
+ # The API omits `faixa` in that case — it never sends null.
+ routes.respond(
+ "/99999999",
+ [404, JSON.generate({ "erro" => "cep_nao_encontrado", "mensagem" => "gone" }), {}]
+ )
+ error = assert_raises(Cepis::CEPNotFound) { @client.lookup("99999999") }
+
+ assert_nil error.faixa
+ end
+
+ def test_malformed_band_does_not_break_the_not_found
+ ["Areal", {}, { "uf" => "RJ" }, { "localidade" => "" }, [], 7].each do |faixa|
+ body = { "erro" => "cep_nao_encontrado", "faixa" => faixa }
+ routes.respond("/99999999", [404, JSON.generate(body), {}])
+ error = assert_raises(Cepis::CEPNotFound) { @client.lookup("99999999") }
+
+ assert_nil error.faixa, "expected #{faixa.inspect} to be ignored"
+ assert_includes error.message, "99999999"
+ end
+ end
+
+ def test_unreadable_404_body_is_still_a_clean_not_found
+ routes.respond("/99999999", [404, "<html>captive portal</html>", {}])
+ error = assert_raises(Cepis::CEPNotFound) { @client.lookup("99999999") }
+
+ assert_nil error.faixa
+ end
+
+ def test_band_never_turns_a_not_found_into_an_address
+ body = { "erro" => "cep_nao_encontrado", "faixa" => AREAL_FAIXA }
+ routes.respond("/25845000", [404, JSON.generate(body), {}])
+
+ assert_raises(Cepis::CEPNotFound) { @client.lookup("25845000") }
+ end
+
def test_not_found_is_not_retried
routes.respond("/99999999", [404, JSON.generate({ "erro" => "x" }), {}])
assert_raises(Cepis::CEPNotFound) { @client.lookup("99999999") }
diff --git a/test/test_helper.rb b/test/test_helper.rb
index e12bd9d..48b581d 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -24,6 +24,22 @@ SE_ADDRESS = {
"siafi" => "7107"
}.freeze
+# The band of a CEP that does not exist, as the API returns it on the 404.
+#
+# 25845000 is the DNE's own start for Areal and does not exist: `cep_ini` is
+# the smallest CEP that really is there, one number above it. The 118 CEPs are
+# scattered across the ~4,900 numbers up to `cep_fim`.
+AREAL_FAIXA = {
+ "localidade" => "Areal",
+ "uf" => "RJ",
+ "estado" => "Rio de Janeiro",
+ "regiao" => "Sudeste",
+ "ibge" => "3300225",
+ "cep_ini" => "25845001",
+ "cep_fim" => "25849899",
+ "ceps" => 118
+}.freeze
+
CSV_HEADER = "cep,logradouro,complemento,unidade,bairro,localidade,uf,estado," \
"regiao,ibge,gia,ddd,siafi"