From 3680332e6b821b22895671c6c665d5ebda07d8a6 Mon Sep 17 00:00:00 2001 From: teallarson Date: Wed, 23 Apr 2025 16:03:44 -0400 Subject: [PATCH 1/2] styling updates --- src/EmbeddedWidget.ts | 62 +++++++++++-------------------------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/src/EmbeddedWidget.ts b/src/EmbeddedWidget.ts index e960455..8b501c2 100644 --- a/src/EmbeddedWidget.ts +++ b/src/EmbeddedWidget.ts @@ -55,7 +55,7 @@ export class EmbeddedWidget { } private initialize(hideButton = false): void { - // Add font import + // Add font import for button const fontLink = document.createElement("link"); fontLink.rel = "stylesheet"; fontLink.href = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"; @@ -68,18 +68,16 @@ export class EmbeddedWidget { padding: 0; border: none; border-radius: 10px; - box-shadow: 0 10px 19px hsla(241, 51%, 20%, 16%); - max-width: 90vw; - max-height: 90vh; - width: 1200px; - height: 800px; - background: white; - font-family: Inter, Helvetica, Arial, sans-serif; + width: 500px; + height: 722px; + background: none; + position: relative; + overflow: hidden; } .airbyte-widget-dialog::backdrop { - background: hsla(241, 51%, 20%, 50%); - backdrop-filter: blur(4px); + background-color: hsl(241, 51%, 20%); + opacity: 60%; } .airbyte-widget-button { @@ -113,33 +111,6 @@ export class EmbeddedWidget { .airbyte-widget-button:focus-visible { outline: 3px solid hsl(240, 100%, 98%); } - - .airbyte-widget-iframe { - width: 100%; - height: 100%; - border: none; - border-radius: 10px; - } - - .airbyte-widget-close { - position: absolute; - top: 16px; - right: 16px; - background-color: transparent; - color: hsl(240, 13%, 72%); - box-shadow: none; - padding: 0; - height: 32px; - } - - .airbyte-widget-close:hover { - color: hsl(240, 10%, 59%); - background-color: transparent; - } - - .airbyte-widget-close:active { - color: hsl(240, 10%, 59%); - } `; document.head.appendChild(style); @@ -148,11 +119,12 @@ export class EmbeddedWidget { this.dialog.classList.add("airbyte-widget-dialog"); // Create iframe - this.iframe.setAttribute("src", this.decodedToken.widgetUrl); this.iframe.setAttribute("frameborder", "0"); this.iframe.setAttribute("allow", "fullscreen"); - this.iframe.classList.add("airbyte-widget-iframe"); + this.iframe.style.width = "100%"; + this.iframe.style.height = "100%"; + this.iframe.style.border = "none"; this.dialog.appendChild(this.iframe); // Listen for messages from the iframe @@ -182,6 +154,11 @@ export class EmbeddedWidget { } } + // Handle close dialog message from the webapp + if (event.data && event.data === "CLOSE_DIALOG") { + this.dialog.close(); + } + // Pass the event to the callback if provided if (this.onEvent && event.data && event.data.type) { this.onEvent(event.data as WidgetEvent); @@ -197,13 +174,6 @@ export class EmbeddedWidget { document.body.appendChild(button); } - // Add close button to dialog - const closeButton = document.createElement("button"); - closeButton.textContent = "Close"; - closeButton.classList.add("airbyte-widget-button", "airbyte-widget-close"); - closeButton.addEventListener("click", () => this.dialog.close()); - this.dialog.appendChild(closeButton); - // Add dialog to document document.body.appendChild(this.dialog); } From a6ec97fb4b8a4ef5e616421d004293c559a3d231 Mon Sep 17 00:00:00 2001 From: teallarson Date: Wed, 23 Apr 2025 16:26:58 -0400 Subject: [PATCH 2/2] fix tests to match new DOM --- tests/EmbeddedWidget.test.ts | 43 +++++++++++++++++------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/tests/EmbeddedWidget.test.ts b/tests/EmbeddedWidget.test.ts index 26bb8c9..be5a679 100644 --- a/tests/EmbeddedWidget.test.ts +++ b/tests/EmbeddedWidget.test.ts @@ -12,10 +12,8 @@ describe("EmbeddedWidget", () => { let mockShowModal: jest.Mock; let mockClose: jest.Mock; let mockButton: HTMLButtonElement; - let mockCloseButton: HTMLButtonElement; let mockIframe: HTMLIFrameElement; let originalCreateElement: typeof document.createElement; - let buttonCount = 0; /** * The tests below are minimal due to limitations in jsdom's implementation of: @@ -25,9 +23,6 @@ describe("EmbeddedWidget", () => { */ beforeEach(() => { - // Reset button count - buttonCount = 0; - // Store original createElement originalCreateElement = document.createElement; @@ -53,15 +48,6 @@ describe("EmbeddedWidget", () => { } }); - mockCloseButton = originalCreateElement.call(document, "button"); - mockCloseButton.textContent = "Close"; - mockCloseButton.classList.add("airbyte-widget-button", "airbyte-widget-close"); - mockCloseButton.addEventListener = jest.fn((event, handler: EventListener) => { - if (event === "click") { - mockCloseButton.onclick = handler as (ev: MouseEvent) => any; - } - }); - mockIframe = { ...originalCreateElement.call(document, "iframe"), addEventListener: jest.fn((event, handler: EventListener) => { @@ -85,19 +71,24 @@ describe("EmbeddedWidget", () => { src: "https://foo.airbyte.com/embedded-widget&workspaceId=foo&allowedOrigin=https%3A%2F%2Flocalhost%3A3003", frameBorder: "0", allow: "fullscreen", + style: { + width: "", + height: "", + border: "", + }, classList: { add: jest.fn(), - contains: jest.fn().mockReturnValue(true), + contains: jest.fn((className) => { + if (className === "airbyte-widget-iframe") return true; + return false; + }), }, } as unknown as HTMLIFrameElement; // Mock document.createElement document.createElement = jest.fn((tagName: string) => { if (tagName === "dialog") return mockDialog; - if (tagName === "button") { - buttonCount++; - return buttonCount === 1 ? mockButton : mockCloseButton; - } + if (tagName === "button") return mockButton; if (tagName === "iframe") return mockIframe; return originalCreateElement.call(document, tagName); }); @@ -111,7 +102,6 @@ describe("EmbeddedWidget", () => { // Mock querySelector jest.spyOn(document, "querySelector").mockImplementation((selector: string) => { if (selector === "button") return mockButton; - if (selector === "button.airbyte-widget-close") return mockCloseButton; if (selector === "iframe") return mockIframe; return null; }); @@ -175,9 +165,16 @@ describe("EmbeddedWidget", () => { expect(mockShowModal).toHaveBeenCalled(); }); - test("closes dialog when close button is clicked", () => { - const closeButton = document.querySelector("button.airbyte-widget-close") as HTMLButtonElement; - closeButton.onclick?.({} as MouseEvent); + test("closes dialog when CLOSE_DIALOG message is received", () => { + // Simulate receiving the CLOSE_DIALOG message + const messageEvent = new MessageEvent("message", { + data: "CLOSE_DIALOG", + origin: "https://foo.airbyte.com", + source: mockIframe.contentWindow as Window, + }); + window.dispatchEvent(messageEvent); + + // Verify that the dialog's close method was called expect(mockClose).toHaveBeenCalled(); }); });