const fs = require("fs"); const path = require("path"); const vm = require("vm"); const scriptPath = path.join(__dirname, "script.js"); const scriptSource = fs.readFileSync(scriptPath, "utf8"); function createClassList() { const values = new Set(); return { toggle(name, enabled) { if (enabled) values.add(name); else values.delete(name); }, has(name) { return values.has(name); }, }; } function createForm(valid, entries) { const listeners = {}; let resetCount = 0; return { __entries: entries, reportValidity() { return valid; }, reset() { resetCount += 1; }, get resetCount() { return resetCount; }, addEventListener(type, handler) { listeners[type] = handler; }, dispatch(type, event) { if (!listeners[type]) throw new Error(`missing listener: ${type}`); return listeners[type](event); }, }; } function createButton() { const listeners = {}; return { addEventListener(type, handler) { listeners[type] = handler; }, dispatch(type, event) { if (!listeners[type]) throw new Error(`missing listener: ${type}`); return listeners[type](event); }, }; } function createEnv({ valid = true, fetchOk = true, clipboardFails = false } = {}) { const timers = []; const output = { textContent: "", classList: createClassList() }; const heroAnimation = { src: "./squaremcp_launch.gif", dataset: { posterSrc: "./squaremcp_launch_poster.png", playMs: "9600", }, }; const entries = [ ["name", "Casey"], ["email", "casey@example.com"], ["company", "SquareMCP Labs"], ["role", "Founder"], ["use_case", "Internal support copilot"], ["timeline", "Within 2 weeks"], ["systems", "Postgres, internal REST APIs"], ["requirements", "Audit logs and SSO"], ]; const form = createForm(valid, entries); const button = createButton(); const fetchCalls = []; let clipboardText = null; const context = { console, window: { setTimeout(fn, ms) { timers.push({ fn, ms }); return timers.length; }, }, document: { getElementById(id) { if (id === "pilotIntakeForm") return form; if (id === "pilotOutput") return output; if (id === "copyRequestButton") return button; if (id === "heroAnimation") return heroAnimation; return null; }, }, navigator: { clipboard: { async writeText(value) { if (clipboardFails) throw new Error("clipboard denied"); clipboardText = value; }, }, }, fetch: async (url, options) => { fetchCalls.push({ url, options }); if (!fetchOk) { return { ok: false, status: 500, async json() { return { error: "submit failed" }; }, }; } return { ok: true, status: 201, async json() { return { ok: true, request_id: "req-123" }; }, }; }, FormData: class MockFormData { constructor(target) { this.target = target; } entries() { return this.target.__entries[Symbol.iterator](); } [Symbol.iterator]() { return this.entries(); } }, }; vm.createContext(context); vm.runInContext(scriptSource, context, { filename: "script.js" }); return { form, button, output, heroAnimation, timers, fetchCalls, getClipboardText: () => clipboardText, }; } function assert(condition, message) { if (!condition) throw new Error(message); } async function run() { const validEnv = createEnv(); assert(validEnv.timers.length === 1, "hero animation timer missing"); assert(validEnv.timers[0].ms === 9600, "hero animation timer mismatch"); validEnv.timers[0].fn(); assert(validEnv.heroAnimation.src === "./squaremcp_launch_poster.png", "hero poster swap failed"); let prevented = false; await validEnv.form.dispatch("submit", { preventDefault() { prevented = true; }, }); assert(prevented, "submit did not prevent default"); assert(validEnv.fetchCalls.length === 1, "submit did not call fetch"); assert(validEnv.fetchCalls[0].url === "/api/pilot-request", "submit endpoint mismatch"); assert(validEnv.fetchCalls[0].options.method === "POST", "submit method mismatch"); const payload = JSON.parse(validEnv.fetchCalls[0].options.body); assert(payload.company === "SquareMCP Labs", "submit payload mismatch"); assert(validEnv.form.resetCount === 1, "form did not reset after success"); assert(validEnv.output.textContent.includes("Saved to SquareMCP intake successfully."), "submit success message missing"); assert(validEnv.output.classList.has("ready"), "submit did not set ready class"); await validEnv.button.dispatch("click", {}); assert(validEnv.getClipboardText().includes("SquareMCP Labs"), "copy handler did not write clipboard"); assert(validEnv.output.textContent.includes("Copied to clipboard."), "copy success message missing"); const invalidEnv = createEnv({ valid: false }); await invalidEnv.form.dispatch("submit", { preventDefault() {} }); assert(invalidEnv.fetchCalls.length === 0, "invalid submit should not call fetch"); assert(invalidEnv.output.textContent === "", "invalid submit should not update output"); const failureEnv = createEnv({ fetchOk: false }); await failureEnv.form.dispatch("submit", { preventDefault() {} }); assert(failureEnv.output.textContent.includes("Submission failed."), "submit failure message missing"); assert(failureEnv.form.resetCount === 0, "failed submit should not reset form"); const clipboardFailureEnv = createEnv({ clipboardFails: true }); await clipboardFailureEnv.button.dispatch("click", {}); assert( clipboardFailureEnv.output.textContent.includes("Clipboard access failed."), "clipboard failure message missing" ); console.log("squaremcp product site smoke test: PASS"); } run().catch((error) => { console.error(`squaremcp product site smoke test: FAIL: ${error.message}`); process.exit(1); });