diff --git a/tests/newsletter.test.js b/tests/newsletter.test.js index 615edbe..16edf6c 100644 --- a/tests/newsletter.test.js +++ b/tests/newsletter.test.js @@ -197,7 +197,20 @@ test("submitNewsletterSignup POSTs the email with no Authorization header or cre !Object.keys(init.headers).some((h) => h.toLowerCase() === "authorization"), "request must not carry an Authorization header", ); + // No credential of any kind: no api-key/auth-token headers, and no token or + // secret in the body or URL either. + for (const header of Object.keys(init.headers)) { + const lower = header.toLowerCase(); + assert.ok( + !["x-api-key", "x-auth-token", "x-access-token", "cookie"].includes(lower), + `request must not carry credential header ${header}`, + ); + } assert.deepEqual(JSON.parse(init.body), { email: "ada@example.com" }); + assert.ok(!url.includes("token")); + assert.ok(!url.includes("key")); + assert.ok(!url.includes("secret")); + assert.ok(!JSON.stringify(init.body).includes("token")); }); test("submitNewsletterSignup defaults to the configured endpoint", async () => { @@ -285,6 +298,18 @@ test("a network failure shows the same user-safe error", async () => { assert.equal(result.message, NEWSLETTER_ERROR_MESSAGE); }); +test("a redirect (3xx) is treated as a failure with the same user-safe error", async () => { + for (const status of [301, 302, 307, 308]) { + const fetchImpl = fakeFetch({ ok: false, status, text: async () => "redirecting" }); + const result = await submitNewsletterSignup("ada@example.com", { + endpoint: "https://api.example.com/newsletter", + fetchImpl, + }); + assert.equal(result.ok, false); + assert.equal(result.message, NEWSLETTER_ERROR_MESSAGE); + } +}); + test("an invalid email fails fast with a user-safe error and no network call", async () => { const fetchImpl = fakeFetch({ ok: true }); const result = await submitNewsletterSignup("not-an-email", {