summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:35:12 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:35:12 -0300
commit2ed1190f0f021bc4de17b47d8d4ed7241611d6f1 (patch)
tree221a8ba542c35ec66b4c79805067749e78c5e03f /tests
parentae9ad8a4c61b793f6859c84dac80b1c1b04b7b68 (diff)
downloadlisp-0.2.0.tar.gz
Carry the municipality of a CEP that does not existHEADv0.2.0main
A CEP that fails is rarely random: it is someone who knows the city and guessed the number, most often the -000 that 957 municipalities never received. The API now answers that 404 with the municipality owning the band the CEP falls in, and without it every caller can say no more than "does not exist" to a person who is one digit away from the right CEP. It lands on the condition rather than in a return value because it is context for the failure and nothing else: the answer is still a 404, and a faixa must never read as an address that resolved. Parsing it is deliberately defensive for the same reason — a missing, malformed or empty block yields NIL, so a field that only adds context cannot turn a clean not-found into a parse failure, and an older API stays supported. The ends of the band are the CEPs that actually exist, not the bounds the Correios publish, and the band is sparse; the docstrings and the README say so, because presenting the pair as a range of valid CEPs is the mistake this data invites. models is compiled before errors so the report function can name the faixa's municipality.
Diffstat (limited to 'tests')
-rw-r--r--tests/suite.lisp68
1 files changed, 68 insertions, 0 deletions
diff --git a/tests/suite.lisp b/tests/suite.lisp
index 4ef0c5f..af48426 100644
--- a/tests/suite.lisp
+++ b/tests/suite.lisp
@@ -11,10 +11,20 @@
(defparameter +csv-header+
"cep,logradouro,complemento,unidade,bairro,localidade,uf,estado,regiao,ibge,gia,ddd,siafi")
+(defparameter +areal-faixa+
+ "\"faixa\":{\"localidade\":\"Areal\",\"uf\":\"RJ\",\"estado\":\"Rio de Janeiro\",\"regiao\":\"Sudeste\",\"ibge\":\"3300225\",\"cep_ini\":\"25845001\",\"cep_fim\":\"25849899\",\"ceps\":118}"
+ "The band 25845000 falls in: the CEP that fails is the DNE's own start for
+Areal, which is why the band begins one number later.")
+
(defun se-json (&rest extra-fields)
"The fixture address, with EXTRA-FIELDS spliced in as raw JSON members."
(format nil "{~a~{,~a~}}" +se-fields+ extra-fields))
+(defun not-found-json (&rest extra-fields)
+ "The 404 body, with EXTRA-FIELDS spliced in as raw JSON members."
+ (format nil "{\"erro\":\"cep_nao_encontrado\",\"mensagem\":\"CEP não existe na base do DNE\"~{,~a~}}"
+ extra-fields))
+
(defun csv-body (&rest rows)
(format nil "~a~%~{~a~%~}" +csv-header+ rows))
@@ -90,6 +100,64 @@
(signals cep-not-found (lookup "99999999" :client client))
(is (= 1 (call-count server "/99999999")))))
+(test not-found-carries-the-band-it-falls-in
+ (with-fake-server (server client)
+ (respond server "/25845000" (reply 404 (not-found-json +areal-faixa+)))
+ (handler-case (progn (lookup "25845000" :client client) (fail "expected a cep-not-found"))
+ (cep-not-found (condition)
+ (let ((faixa (cep-not-found-faixa condition)))
+ (is (string= "25845000" (cell-error-name condition)))
+ (is (string= "Areal" (faixa-localidade faixa)))
+ (is (string= "RJ" (faixa-uf faixa)))
+ (is (string= "Rio de Janeiro" (faixa-estado faixa)))
+ (is (string= "Sudeste" (faixa-regiao faixa)))
+ (is (string= "3300225" (faixa-ibge faixa)))
+ ;; The ends are the CEPs that exist, not the bounds the Correios
+ ;; publish: the DNE's own start for Areal is the 25845000 that just
+ ;; failed. And the 118 of them are scattered over the ~4,900 numbers
+ ;; in between, so the pair is not a list of valid CEPs.
+ (is (string= "25845001" (faixa-cep-ini faixa)))
+ (is (string= "25849899" (faixa-cep-fim faixa)))
+ (is (= 118 (faixa-ceps faixa))))))))
+
+(test the-band-does-not-make-a-not-found-succeed
+ (with-fake-server (server client)
+ (respond server "/25845000" (reply 404 (not-found-json +areal-faixa+)))
+ (signals cep-not-found (lookup "25845000" :client client))
+ (is (= 1 (call-count server "/25845000")))))
+
+(test not-found-without-a-band
+ (with-fake-server (server client)
+ (respond server "/99999999" (reply 404 (not-found-json)))
+ (handler-case (progn (lookup "99999999" :client client) (fail "expected a cep-not-found"))
+ (cep-not-found (condition)
+ (is (null (cep-not-found-faixa condition)))))))
+
+(test malformed-band-does-not-lose-the-not-found
+ (dolist (field '("\"faixa\":\"Areal\"" "\"faixa\":{}" "\"faixa\":[]"
+ "\"faixa\":null" "\"faixa\":{\"uf\":\"RJ\"}"))
+ (with-fake-server (server client)
+ (respond server "/25845000" (reply 404 (not-found-json field)))
+ (handler-case (progn (lookup "25845000" :client client) (fail "expected a cep-not-found"))
+ (cep-not-found (condition)
+ (is (null (cep-not-found-faixa condition))))))))
+
+(test not-found-body-that-is-not-json-still-signals-not-found
+ (with-fake-server (server client)
+ (respond server "/25845000" (reply 404 "<html>captive portal</html>"))
+ (signals cep-not-found (lookup "25845000" :client client))))
+
+(test the-report-names-the-municipality
+ (with-fake-server (server client)
+ (respond server "/25845000" (reply 404 (not-found-json +areal-faixa+)))
+ (respond server "/99999999" (reply 404 (not-found-json)))
+ (handler-case (progn (lookup "25845000" :client client) (fail "expected a cep-not-found"))
+ (cep-not-found (condition)
+ (is (search "Areal" (princ-to-string condition)))))
+ (handler-case (progn (lookup "99999999" :client client) (fail "expected a cep-not-found"))
+ (cep-not-found (condition)
+ (is (search "99999999" (princ-to-string condition)))))))
+
(test invalid-cep-never-leaves-the-machine
(with-fake-server (server client)
(signals invalid-cep (lookup "123" :client client))