From 2e5660d47e11c6af7f8b982df6bf028d68b7f7f8 Mon Sep 17 00:00:00 2001 From: Paul Jung Date: Tue, 9 Sep 2025 11:53:59 -0400 Subject: [PATCH 1/3] [MOB-11504] Fix Persistent Scrollbar in In-App Message Iframes --- src/inapp/inapp.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/inapp/inapp.ts b/src/inapp/inapp.ts index c338f19d..95908229 100644 --- a/src/inapp/inapp.ts +++ b/src/inapp/inapp.ts @@ -175,10 +175,24 @@ export function getInAppMessages( const throttledResize = messagePosition !== 'Full' - ? throttle(750, () => { + ? throttle(100, () => { + const iframeBody = activeIframeDocument?.body; + if (!iframeBody) return; + + /** Hide overflow to prevent scrolling */ + const originalOverflow = iframeBody.style.overflow; + const shouldHideOverflow = originalOverflow !== 'hidden'; + if (shouldHideOverflow) iframeBody.style.overflow = 'hidden'; + + /** Set the height of the iframe to the height of the iframe body */ activeIframe.style.height = `${ - activeIframeDocument?.body?.scrollHeight || 0 + iframeBody.scrollHeight || 0 }px`; + + /** Restore overflow after new height is set */ + if (shouldHideOverflow) { + iframeBody.style.overflow = originalOverflow; + } }) : () => null; global.addEventListener('resize', throttledResize); From db5a85da147e8f5f7994dca6d5e7acb7b5ad4372 Mon Sep 17 00:00:00 2001 From: Paul Jung Date: Tue, 9 Sep 2025 14:46:35 -0400 Subject: [PATCH 2/3] [MOB-11504] Remove BASE_URL from react sample app env.example --- react-example/.env.example | 3 --- 1 file changed, 3 deletions(-) diff --git a/react-example/.env.example b/react-example/.env.example index a7fb6d98..8887e134 100644 --- a/react-example/.env.example +++ b/react-example/.env.example @@ -6,9 +6,6 @@ # API_KEY=1234 # JWT_SECRET=1234 -# Only set BASE_URL if developing locally, as it will take precedence over the production api urls. -# BASE_URL="https://api.iterable.com/api" - # You may authenticate with JWT; be sure to use an API key that is configured to require JWT. # USE_JWT=true From d280687de836f461689de90ebffb70427cbc1f87 Mon Sep 17 00:00:00 2001 From: Paul Jung Date: Tue, 9 Sep 2025 14:46:55 -0400 Subject: [PATCH 3/3] [MOB-11504] Add unit tests --- src/inapp/inapp.ts | 2 +- src/inapp/tests/inapp.test.ts | 59 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/inapp/inapp.ts b/src/inapp/inapp.ts index 95908229..1c954925 100644 --- a/src/inapp/inapp.ts +++ b/src/inapp/inapp.ts @@ -179,7 +179,7 @@ export function getInAppMessages( const iframeBody = activeIframeDocument?.body; if (!iframeBody) return; - /** Hide overflow to prevent scrolling */ + /** Hide overflow to prevent scrollbar affecting height determination */ const originalOverflow = iframeBody.style.overflow; const shouldHideOverflow = originalOverflow !== 'hidden'; if (shouldHideOverflow) iframeBody.style.overflow = 'hidden'; diff --git a/src/inapp/tests/inapp.test.ts b/src/inapp/tests/inapp.test.ts index f7b4b6b6..28433e36 100644 --- a/src/inapp/tests/inapp.test.ts +++ b/src/inapp/tests/inapp.test.ts @@ -1252,5 +1252,64 @@ describe('getInAppMessages', () => { // Note: sendBeacon property is used internally by the authorization system // but not preserved in the mock request history, so we don't test it here }); + + it('should resize iframe and restore/hide overflow when necessary', async () => { + mockRequest.onGet(GETMESSAGES_PATH).reply(200, { + inAppMessages: [ + { + ...messages[0], + content: { + ...messages[0].content, + html: '
hello
' + } + } + ] + }); + const { request } = getInAppMessages( + { count: 10, packageName: 'my-lil-website' }, + { display: DisplayOptions.Immediate } + ); + await request(); + + const iframe = document.getElementById( + 'iterable-iframe' + ) as HTMLIFrameElement; + const iframeBody = iframe?.contentWindow?.document.body; + if (iframeBody) { + Object.defineProperty(iframeBody, 'scrollHeight', { + value: 500, + writable: true + }); + Object.defineProperty(iframeBody, 'offsetHeight', { + value: 400, + writable: true + }); + iframeBody.style.overflow = 'scroll'; + } + + global.dispatchEvent(new Event('resize')); + jest.advanceTimersByTime(100); + + expect(iframe.style.height).toBe('500px'); + expect(iframeBody?.style.overflow).toBe('scroll'); + + if (iframeBody) { + Object.defineProperty(iframeBody, 'scrollHeight', { + value: 500, + writable: true + }); + Object.defineProperty(iframeBody, 'offsetHeight', { + value: 900, + writable: true + }); + iframeBody.style.overflow = 'hidden'; + } + + global.dispatchEvent(new Event('resize')); + jest.advanceTimersByTime(100); + + expect(iframe.style.height).toBe('500px'); + expect(iframeBody?.style.overflow).toBe('hidden'); + }); }); });