diff --git a/README.md b/README.md index b589937d4..7febfc480 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,19 @@ Embed the lightweight modal checkout script tag in your HTML and attach it to an ``` +**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"); + }); + }); });