diff --git a/src/app/components/ATIAnalytics/canonical/index.test.tsx b/src/app/components/ATIAnalytics/canonical/index.test.tsx index ed23c754270..7c7e859b4d8 100644 --- a/src/app/components/ATIAnalytics/canonical/index.test.tsx +++ b/src/app/components/ATIAnalytics/canonical/index.test.tsx @@ -79,7 +79,7 @@ describe('Canonical ATI Analytics', () => { const helmet = Helmet.peek(); expect(helmet.scriptTags[0].innerHTML).toEqual( - addSendStaticBeaconToWindow(), + `(${addSendStaticBeaconToWindow.toString()})()`, ); }); diff --git a/src/app/components/ATIAnalytics/canonical/index.tsx b/src/app/components/ATIAnalytics/canonical/index.tsx index 2b9f3d011d4..7fe8c16cb95 100644 --- a/src/app/components/ATIAnalytics/canonical/index.tsx +++ b/src/app/components/ATIAnalytics/canonical/index.tsx @@ -59,7 +59,10 @@ const CanonicalATIAnalytics = ({ reverbParams }: ATIAnalyticsProps) => { return ( <> - {addScript({ script: addSendStaticBeaconToWindow(), nonce })} + {addScript({ + script: addSendStaticBeaconToWindow, + nonce, + })} {isLite && addScript({ script: sendPageViewBeaconLite, diff --git a/src/app/lib/analyticsUtils/staticATITracking/sendStaticBeacon/index.test.ts b/src/app/lib/analyticsUtils/staticATITracking/sendStaticBeacon/index.test.ts index 6fa7679c7cc..b8f1d5c8563 100644 --- a/src/app/lib/analyticsUtils/staticATITracking/sendStaticBeacon/index.test.ts +++ b/src/app/lib/analyticsUtils/staticATITracking/sendStaticBeacon/index.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-eval */ import sendStaticBeacon, { addSendStaticBeaconToWindow } from '.'; let XMLHttpRequestSpy: jest.SpyInstance; @@ -12,7 +11,7 @@ describe('sendStaticBeacon', () => { beforeEach(() => { XMLHttpRequestSpy = jest.spyOn(window, 'XMLHttpRequest'); - eval(addSendStaticBeaconToWindow()); + addSendStaticBeaconToWindow(); }); afterEach(() => { @@ -31,7 +30,7 @@ describe('sendStaticBeacon', () => { () => XMLHttpRequestMock as XMLHttpRequest, ); - eval(sendStaticBeacon('https://foobar.com')); + sendStaticBeacon('https://foobar.com'); expect(XMLHttpRequestMock.open).toHaveBeenCalledWith( 'GET', diff --git a/src/app/lib/analyticsUtils/staticATITracking/sendStaticBeacon/index.ts b/src/app/lib/analyticsUtils/staticATITracking/sendStaticBeacon/index.ts index 40757b2ef6f..b7f0a605f27 100644 --- a/src/app/lib/analyticsUtils/staticATITracking/sendStaticBeacon/index.ts +++ b/src/app/lib/analyticsUtils/staticATITracking/sendStaticBeacon/index.ts @@ -1,12 +1,12 @@ -export const addSendStaticBeaconToWindow = () => ` - window.sendStaticBeacon = function (atiUrlString) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", atiUrlString, true); - xhr.withCredentials = true; - xhr.send(); - }; -`; +export const addSendStaticBeaconToWindow = () => { + window.sendStaticBeacon = function (atiUrlString) { + const xhr = new XMLHttpRequest(); + xhr.open('GET', atiUrlString, true); + xhr.withCredentials = true; + xhr.send(); + return true; + }; +}; -export default (atiUrlString: string) => ` - window.sendStaticBeacon("${atiUrlString}"); -`; +export default (atiUrlString: string) => + window.sendStaticBeacon(`${atiUrlString}`); diff --git a/src/app/lib/utilities/addInlineScript/index.test.tsx b/src/app/lib/utilities/addInlineScript/index.test.tsx index 6def38988a1..f32f3ded247 100644 --- a/src/app/lib/utilities/addInlineScript/index.test.tsx +++ b/src/app/lib/utilities/addInlineScript/index.test.tsx @@ -73,4 +73,22 @@ describe('addInlineScript', () => { , ); }); + + it('should inject callable functions as script parameters', () => { + const script = (callback: () => void) => callback(); + const callback = () => console.log('hello world'); + + const inlineScript = addInlineScript({ + script, + parameters: [callback], + }); + + expect(inlineScript).toStrictEqual( + , + ); + }); }); diff --git a/src/app/lib/utilities/addInlineScript/index.tsx b/src/app/lib/utilities/addInlineScript/index.tsx index 6218487f6bd..a7fd7cbf0d3 100644 --- a/src/app/lib/utilities/addInlineScript/index.tsx +++ b/src/app/lib/utilities/addInlineScript/index.tsx @@ -1,6 +1,6 @@ export type InlineScriptProps = { script: string | { toString: () => string }; - parameters?: string | string[]; + parameters?: string | string[] | (string | { toString: () => string })[]; nonce?: string | null; }; @@ -8,7 +8,12 @@ export default ({ script, parameters, nonce }: InlineScriptProps) => { let inlineScript = script; const stringifiedParams = [parameters] .flat() - .map(param => `"${param}"`) + .map(param => { + if (typeof param === 'function') { + return param.toString(); + } + return `"${param}"`; + }) .join(', '); let paramLiteral = '';