diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/checkout.test.js | 171 | ||||
| -rw-r--r-- | test/fake-api.js | 44 |
2 files changed, 209 insertions, 6 deletions
diff --git a/test/checkout.test.js b/test/checkout.test.js index 074b13a..cce2575 100644 --- a/test/checkout.test.js +++ b/test/checkout.test.js @@ -168,7 +168,7 @@ describe("plugin", () => { }); test("declares the version WooCommerce reports", () => { - expect(wp(["plugin", "get", "cepis-woocommerce", "--field=version"])).toBe("0.1.0"); + expect(wp(["plugin", "get", "cepis-woocommerce", "--field=version"])).toBe("0.2.0"); }); }); @@ -280,6 +280,47 @@ describe("block checkout", () => { await close(); }, 90000); + + test("a CEP that does not exist names its municipality and still fills nothing", async () => { + const { page, close } = await checkout("/checkout/"); + + await settled(page); + await typeCep(page, "#shipping-postcode", "01001000"); + await page.waitForFunction( + () => document.querySelector("#shipping-address_1").value !== "", + undefined, + { timeout: 15000 }, + ); + + await typeCep(page, "#shipping-postcode", "25845000"); + await page.waitForFunction( + () => + document.body.innerText.includes( + "would be in Areal/RJ, which has CEPs from 25845-001 to 25849-899", + ), + undefined, + { timeout: 15000 }, + ); + + const after = await page.evaluate(() => ({ + street: document.querySelector("#shipping-address_1").value, + city: document.querySelector("#shipping-city").value, + state: document.querySelector("#shipping-state").value, + store: JSON.stringify(window.wp.data.select("wc/store/cart").getCustomerData()), + })); + + // The address the previous, real CEP produced is still there, untouched. + expect(after.street).toBe("Praça da Sé"); + expect(after.city).toBe("São Paulo"); + expect(after.state).toBe("SP"); + + // And nothing from the 404 reached the data store the order is built from. + // A municipality named in an error is a guess about a typo, not an address. + expect(after.store).not.toContain("Areal"); + expect(after.store).not.toContain('"state":"RJ"'); + + await close(); + }, 90000); }); describe("classic checkout", () => { @@ -443,6 +484,82 @@ describe("classic checkout", () => { await close(); }, 90000); + + test("a CEP that does not exist names its municipality and still fills nothing", async () => { + const { page, errors, close } = await checkout("/checkout-classico/"); + + await ready(page); + await typeCep(page, "#billing_postcode", "01001000"); + await page.waitForFunction( + () => document.querySelector("#billing_address_1").value !== "", + undefined, + { timeout: 15000 }, + ); + + await typeCep(page, "#billing_postcode", "25845000"); + await page.waitForFunction( + () => + (document.querySelector(".cepis-autofill-status") || {}).textContent === + "CEP not found. This number would be in Areal/RJ, which has CEPs from 25845-001 to 25849-899. Check the number.", + undefined, + { timeout: 15000 }, + ); + + const after = await page.evaluate(() => ({ + street: document.querySelector("#billing_address_1").value, + city: document.querySelector("#billing_city").value, + state: document.querySelector("#billing_state").value, + invalid: document.querySelector("#billing_postcode").getAttribute("aria-invalid"), + leaked: Array.from(document.querySelectorAll("input, select, textarea")) + .map((field) => String(field.value == null ? "" : field.value)) + .filter((value) => /areal|rio de janeiro|^RJ$/i.test(value)), + })); + + // What the previous, real CEP filled in is still there. + expect(after.street).toBe("Praça da Sé"); + expect(after.city).toBe("São Paulo"); + expect(after.state).toBe("SP"); + expect(after.invalid).toBe("true"); + + // The whole point: naming the municipality must not put it in a field. + // Shipping to a town the CEP does not belong to is a parcel gone astray. + expect(after.leaked).toEqual([]); + expect(errors).toEqual([]); + + await close(); + }, 90000); + + test("a faixa it cannot use falls back to the plain message", async () => { + const { page, errors, close } = await checkout("/checkout-classico/"); + const plain = "CEP not found. Check the number or fill the address in by hand."; + + await ready(page); + await typeCep(page, "#billing_postcode", "25849000"); + + await page.waitForFunction( + (expected) => + (document.querySelector(".cepis-autofill-status") || {}).textContent === expected, + plain, + { timeout: 15000 }, + ); + + // Long enough for the follow-up request to have come back and, if it were + // going to, made a mess of the line. + await page.waitForTimeout(3000); + + const after = await page.evaluate(() => ({ + status: (document.querySelector(".cepis-autofill-status") || {}).textContent, + street: document.querySelector("#billing_address_1").value, + city: document.querySelector("#billing_city").value, + })); + + expect(after.status).toBe(plain); + expect(after.street).toBe(""); + expect(after.city).toBe(""); + expect(errors).toEqual([]); + + await close(); + }, 90000); }); describe("proxy mode", () => { @@ -482,7 +599,7 @@ describe("proxy mode", () => { const served = api.state.requests.filter((entry) => entry.cep === "01001000"); expect(served.length).toBe(1); - expect(served[0].userAgent).toContain("cepis-woocommerce/0.1.0"); + expect(served[0].userAgent).toContain("cepis-woocommerce/0.2.0"); expect(errors).toEqual([]); await close(); @@ -516,6 +633,39 @@ describe("proxy mode", () => { expect(api.state.requests.filter((entry) => entry.cep === "20040020").length).toBe(1); }, 120000); + test("the municipality survives the proxy and its cache, and fills nothing", async () => { + api.reset(); + const { page, close } = await checkout("/checkout-classico/"); + + await ready(page); + await typeCep(page, "#billing_postcode", "25845000"); + + await page.waitForFunction( + () => + (document.querySelector(".cepis-autofill-status") || {}).textContent === + "CEP not found. This number would be in Areal/RJ, which has CEPs from 25845-001 to 25849-899. Check the number.", + undefined, + { timeout: 20000 }, + ); + + const after = await page.evaluate(() => ({ + street: document.querySelector("#billing_address_1").value, + leaked: Array.from(document.querySelectorAll("input, select, textarea")) + .map((field) => String(field.value == null ? "" : field.value)) + .filter((value) => /areal|rio de janeiro|^RJ$/i.test(value)), + })); + + expect(after.street).toBe(""); + expect(after.leaked).toEqual([]); + + // One request reached the API. The lookup itself made it; the follow-up + // that reads the municipality out of the 404 body was served from the + // transient, which is only possible if the miss was cached with it. + expect(api.state.requests.filter((entry) => entry.cep === "25845000")).toHaveLength(1); + + await close(); + }, 90000); + test("the REST route refuses a request without a valid token", async () => { const context = await browser.newContext(); const page = await context.newPage(); @@ -564,6 +714,23 @@ describe("translations", () => { await close(); }, 90000); + + test("so is the message that names the municipality", async () => { + const { page, close } = await checkout("/checkout-classico/"); + + await ready(page); + await typeCep(page, "#billing_postcode", "25845000"); + + await page.waitForFunction( + () => + (document.querySelector(".cepis-autofill-status") || {}).textContent === + "CEP não encontrado. Esse número seria de Areal/RJ, que tem CEPs de 25845-001 a 25849-899. Confira o número.", + undefined, + { timeout: 15000 }, + ); + + await close(); + }, 90000); }); describe("housekeeping", () => { 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 }); |