summaryrefslogtreecommitdiffstats
path: root/test/fake-api.js
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:52:15 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:52:15 -0300
commit511a0ab33b5b12a4cd8a1d4dca6c5dce50cdb6c1 (patch)
tree462412b439743c2d04f1acf24f6557251d3a8265 /test/fake-api.js
parent535dbda6b48171f8115b455e54790de94d97d42a (diff)
downloadwoocommerce-797d25bb066c40c5c6c0c44a728140914b1e6477.tar.gz
Name the municipality behind a CEP that does not existHEADv0.2.0main
A CEP that fails at the checkout is almost never a random number. It is a shopper who knows perfectly well which town they live in and got a digit wrong, most often by reaching for the -000 that 957 municipalities never received. The API now names the municipality such a number would have belonged to, in the body of its own 404, so the message can say "that would be in Areal/RJ, which has CEPs from 25845-001 to 25849-899" instead of leaving the shopper at a dead end with nothing to act on. It stays an error. Nothing from it is written into a checkout field, on either checkout and in either lookup mode: a CEP that does not exist has no address, and filling one in from the municipality behind it means a parcel delivered to the wrong town and a chargeback behind that. The one module that reads the 404 body hands its callers a finished sentence and never the data itself, so there is no shape in which it could leak into a field later. The two CEPs quoted are the lowest and the highest that really exist there, never a list and never a suggestion, because the range is sparse enough that a number out of the middle of it would most likely not exist either. The widget correctly throws its 404 away without reading it, so the body is fetched once more, on the miss path only and once per CEP. In proxy mode PHP passes the municipality through with the 404 and caches it with the miss, which is what keeps the two modes indistinguishable from the browser. Anything missing or misshapen falls back to the message the plugin has always shown.
Diffstat (limited to 'test/fake-api.js')
-rw-r--r--test/fake-api.js44
1 files changed, 40 insertions, 4 deletions
diff --git a/test/fake-api.js b/test/fake-api.js
index 4b6ac39..d787bf1 100644
--- a/test/fake-api.js
+++ b/test/fake-api.js
@@ -43,6 +43,39 @@ const ADDRESSES = {
},
};
+/**
+ * The municipality a CEP that does not exist would have belonged to, keyed by
+ * the CEP that provokes it.
+ *
+ * `25845000` is the real-world shape of the whole problem: Areal/RJ answers
+ * from 25845-001 upwards and never at the `-000` a shopper reaches for. Any
+ * other missing CEP — `99999999` — belongs to no municipality at all, and the
+ * API then omits `faixa` entirely rather than sending it as null, which is what
+ * the plugin's fallback path has to keep working against.
+ */
+const RANGES = {
+ 25845000: {
+ localidade: "Areal",
+ uf: "RJ",
+ estado: "Rio de Janeiro",
+ regiao: "Sudeste",
+ ibge: "3300225",
+ cep_ini: "25845001",
+ cep_fim: "25849899",
+ ceps: 118,
+ },
+
+ // A faixa with no municipality in it. The real API does not send this, and
+ // the point of having it here is that the checkout must not care: an
+ // unusable faixa has to end in exactly the message the plugin has always
+ // shown, not in a broken sentence and not in a JavaScript error.
+ 25849000: {
+ uf: "RJ",
+ cep_ini: "25845001",
+ cep_fim: "25849899",
+ },
+};
+
const HEADERS = {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json; charset=utf-8",
@@ -76,10 +109,13 @@ export function startFakeApi(port) {
const address = ADDRESSES[cep];
if (!address) {
- return new Response(
- JSON.stringify({ erro: "cep_nao_encontrado", mensagem: "CEP não existe na base do DNE" }),
- { status: 404, headers: HEADERS },
- );
+ const missing = { erro: "cep_nao_encontrado", mensagem: "CEP não existe na base do DNE" };
+
+ if (RANGES[cep]) {
+ missing.faixa = RANGES[cep];
+ }
+
+ return new Response(JSON.stringify(missing), { status: 404, headers: HEADERS });
}
return new Response(JSON.stringify(address), { status: 200, headers: HEADERS });