diff --git a/tests/newsletter.test.js b/tests/newsletter.test.js new file mode 100644 index 0000000..4189769 --- /dev/null +++ b/tests/newsletter.test.js @@ -0,0 +1,278 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; +import { + NEWSLETTER_ERROR_MESSAGE, + NEWSLETTER_SUCCESS_MESSAGE, + handleNewsletterSubmit, + isValidEmail, + readFormEmail, + submitNewsletterSignup, +} from "../js/newsletter.js"; +import { + NEWSLETTER_API_TOKEN, + NEWSLETTER_ENDPOINT, +} from "../js/newsletter-config.js"; + +const root = join(dirname(fileURLToPath(import.meta.url)), ".."); +const newsletterHtml = readFileSync(join(root, "newsletter.html"), "utf8"); +const indexHtml = readFileSync(join(root, "index.html"), "utf8"); +const readingHtml = readFileSync(join(root, "reading.html"), "utf8"); +const contactHtml = readFileSync(join(root, "contact.html"), "utf8"); +const newsletterJs = readFileSync(join(root, "js/newsletter.js"), "utf8"); +const configJs = readFileSync(join(root, "js/newsletter-config.js"), "utf8"); + +/** Minimal stand-in for a DOM form (has querySelectorAll("[name]")). */ +function fakeForm(email) { + return { + querySelectorAll(selector) { + assert.equal(selector, "[name]"); + return [{ name: "email", value: email }]; + }, + }; +} + +/** Record calls and respond — pass an object or a (url, init) => response fn. */ +function fakeFetch(respond) { + const calls = []; + const impl = async (url, init) => { + calls.push({ url, init }); + return typeof respond === "function" ? respond(url, init) : respond; + }; + impl.calls = calls; + return impl; +} + +// --------------------------------------------------------------------------- +// Component tests: the signup form renders on the blog +// --------------------------------------------------------------------------- + +test("newsletter page renders an email field and a submit button", () => { + assert.match(newsletterHtml, /