From d840907c1f27c0115d04b63c213c934a7b96a324 Mon Sep 17 00:00:00 2001 From: Mamavee001 <307202201+Mamavee001@users.noreply.github.com> Date: Fri, 28 Aug 2026 17:57:53 +0100 Subject: [PATCH] fix(web,widget): embed checkout styles and no silent host fallback (issue 5.10) - globals.css: real .shell--embed / .panel--embed rules - no page-level max-width/centering/32-80px padding inside the widget's 440x680 iframe (the outer modal
in packages/widget/src/modal.ts already supplies the rounded corners/border/shadow, so the page inside only needs to fill the frame). Added .checkout--embed overrides tightening heading scale, QR wrap margins, memo-note spacing, and the status-rail/icon sizes specifically for the narrower embed context - checked against the "active - waiting for payment" render, the tallest of the states. - CheckoutClient now takes an `embed` prop (threaded from pay/[id]/page.tsx's existing isEmbed flag) so it can apply the .checkout--embed class and use a smaller QR size (140px vs 180px) - the one thing CSS alone can't resize, since it's a real prop on QRCodeSVG, not a stylable dimension. - packages/widget/src/modal.ts: deleted the DEFAULT_HOST fallback (https://quay-web.vercel.app - the maintainer's own deployment). openModal() now resolves the host via an explicit `host` option or the widget's own ``` +**Self-hosting the widget?** Point the script tag at your own deployment and +the widget infers the host from its own ` + + `; + Quay.init(); const btn = document.getElementById("pay-btn")!; @@ -53,13 +59,14 @@ describe("Quay Widget SDK", () => { expect(modal).not.toBeNull(); const iframe = document.getElementById("quay-checkout-iframe") as HTMLIFrameElement; expect(iframe.src).toContain("/pay/lnk_btn_456?embed=true"); + expect(iframe.src).toContain(TEST_HOST); }); it("subscribes to events with Quay.on()", () => { const onPaid = vi.fn(); const unsubscribe = Quay.on("quay:paid", onPaid); - Quay.open("lnk_test_123"); + Quay.open({ linkId: "lnk_test_123", host: TEST_HOST }); const event = new MessageEvent("message", { data: { type: "quay:paid", linkId: "lnk_test_123", link: { id: "lnk_test_123" } }, @@ -75,4 +82,56 @@ describe("Quay Widget SDK", () => { unsubscribe(); }); + + // --------------------------------------------------------------------------- + // Host resolution (issue 5.10) - no silent fallback to someone else's deployment. + // --------------------------------------------------------------------------- + + describe("host resolution", () => { + it("throws a clear error when no host can be determined - no explicit host and no widget.js script tag", () => { + expect(() => Quay.open("lnk_test_123")).toThrow(/could not determine which Quay deployment/i); + // A failed open() must be a true no-op - nothing left in the DOM. + expect(document.getElementById("quay-checkout-modal")).toBeNull(); + }); + + it("does not fall back to https://quay-web.vercel.app or any other hardcoded host", () => { + try { + Quay.open("lnk_test_123"); + } catch { + /* expected */ + } + expect(document.getElementById("quay-checkout-iframe")).toBeNull(); + }); + + it("uses the explicit host option when given, even with no script tag present", () => { + Quay.open({ linkId: "lnk_test_123", host: TEST_HOST }); + const iframe = document.getElementById("quay-checkout-iframe") as HTMLIFrameElement; + expect(iframe.src.startsWith(TEST_HOST)).toBe(true); + }); + + it("infers the host from the widget's own script tag when no explicit host is given", () => { + document.body.innerHTML = ``; + Quay.open("lnk_test_123"); + const iframe = document.getElementById("quay-checkout-iframe") as HTMLIFrameElement; + expect(iframe.src.startsWith(TEST_HOST)).toBe(true); + }); + + it("an explicit host option takes precedence over a detected script tag", () => { + document.body.innerHTML = ``; + Quay.open({ linkId: "lnk_test_123", host: TEST_HOST }); + const iframe = document.getElementById("quay-checkout-iframe") as HTMLIFrameElement; + expect(iframe.src.startsWith(TEST_HOST)).toBe(true); + }); + + it("a failed open() does not disturb a modal that was already open", () => { + Quay.open({ linkId: "lnk_already_open", host: TEST_HOST }); + expect(document.getElementById("quay-checkout-modal")).not.toBeNull(); + + expect(() => Quay.open("lnk_no_host")).toThrow(); + + // The original modal, for the original link, is untouched. + const iframe = document.getElementById("quay-checkout-iframe") as HTMLIFrameElement; + expect(iframe.src).toContain("lnk_already_open"); + }); + }); });