From 47c822d0d5e690092617b6170972917058a6d45d Mon Sep 17 00:00:00 2001 From: Murilo Ijanc Date: Mon, 27 Jul 2026 20:15:36 -0300 Subject: Carry the municipality of a CEP that does not exist A 404 that only says "not found" is correct and useless. The CEP that fails is almost never random: it is someone who knows the city and guessed the number, and the classic guess is the -000 that 957 municipalities never received. The API now names the municipality on the 404, so surface it as Error.Faixa instead of throwing the body away. --- cepis_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'cepis_test.go') diff --git a/cepis_test.go b/cepis_test.go index 888ded5..2394175 100644 --- a/cepis_test.go +++ b/cepis_test.go @@ -268,6 +268,54 @@ func TestLookupNotFound(t *testing.T) { } } +func TestLookupNotFoundCarriesTheMunicipality(t *testing.T) { + api := newFakeAPI(t) + api.respond("/25845000", ok(404, `{"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}}`)) + + _, err := newClient(t, api).Lookup(context.Background(), "25845-000") + var cerr *cepis.Error + if !errors.As(err, &cerr) { + t.Fatalf("error %v is not a *cepis.Error", err) + } + if cerr.Faixa == nil { + t.Fatal("Faixa is nil, want the municipality of the range") + } + if cerr.Faixa.Localidade != "Areal" || cerr.Faixa.UF != "RJ" { + t.Errorf("Faixa = %+v, want Areal/RJ", cerr.Faixa) + } + // The published bounds are the CEPs that exist, never the DNE's own start + // — 25845000 is exactly the CEP the caller just got wrong. + if cerr.Faixa.CEPIni != "25845001" || cerr.Faixa.CEPFim != "25849899" { + t.Errorf("range = %s-%s, want 25845001-25849899", + cerr.Faixa.CEPIni, cerr.Faixa.CEPFim) + } + if cerr.Faixa.CEPs != 118 { + t.Errorf("CEPs = %d, want 118", cerr.Faixa.CEPs) + } + if !strings.Contains(cerr.Error(), "Areal/RJ") { + t.Errorf("message %q does not mention the municipality", cerr.Error()) + } +} + +func TestLookupNotFoundWithoutAFaixa(t *testing.T) { + // A CEP in a band the Correios gave to no municipality. The API omits the + // object rather than sending null, and the error stays perfectly usable. + api := newFakeAPI(t) + api.respond("/06000000", ok(404, `{"erro":"cep_nao_encontrado"}`)) + + _, err := newClient(t, api).Lookup(context.Background(), "06000000") + var cerr *cepis.Error + if !errors.As(err, &cerr) || !errors.Is(err, cepis.ErrCEPNotFound) { + t.Fatalf("error = %v, want ErrCEPNotFound", err) + } + if cerr.Faixa != nil { + t.Errorf("Faixa = %+v, want nil", cerr.Faixa) + } +} + func TestLookupNotFoundIsNotRetried(t *testing.T) { api := newFakeAPI(t) api.respond("/99999999", ok(404, `{"erro":"cep_nao_encontrado"}`)) -- cgit v1.3