From af36e468e9c388a0df0bac4b90fb164085a36396 Mon Sep 17 00:00:00 2001 From: Esme <23175119+esme@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:50:56 -0800 Subject: [PATCH] Create a broadcast channel in the demo widget (#241) * Create a broadcast channel in the demo widget --- demos/demo-minimal-js/package-lock.json | 9 +- demos/demo-minimal-js/package.json | 2 +- demos/demo-react-ts/package-lock.json | 15 ++- demos/demo-react-ts/package.json | 2 +- demos/demo-react-ts/src/components/App.tsx | 127 +++++++++++++++--- .../src/components/screens/CallingScreen.tsx | 1 + .../src/components/screens/DialingScreen.tsx | 4 +- .../src/components/screens/IncomingScreen.tsx | 4 +- .../src/components/screens/KeypadScreen.tsx | 13 +- demos/demo-react-ts/src/hooks/useCti.ts | 117 +++++++++++++++- demos/demo-react-ts/src/types/ScreenTypes.ts | 1 + .../screens/IncomingScreen-test.tsx | 5 +- .../components/screens/KeypadScreen-test.tsx | 11 +- package-lock.json | 4 +- package.json | 2 +- src/Constants.js | 2 +- src/IFrameManager.js | 7 +- 17 files changed, 275 insertions(+), 51 deletions(-) diff --git a/demos/demo-minimal-js/package-lock.json b/demos/demo-minimal-js/package-lock.json index d589d44..6cb1700 100644 --- a/demos/demo-minimal-js/package-lock.json +++ b/demos/demo-minimal-js/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@hubspot/calling-extensions-sdk": "^0.8.0", + "@hubspot/calling-extensions-sdk": "^0.8.1-alpha.1", "uuid": "^10.0.0" }, "devDependencies": { @@ -33,9 +33,10 @@ } }, "node_modules/@hubspot/calling-extensions-sdk": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@hubspot/calling-extensions-sdk/-/calling-extensions-sdk-0.8.0.tgz", - "integrity": "sha512-p6lwJd4tKnQVG3PGO6VRPeZ0finADOTw3pw9jGFwAXKQTODYNTIRSq0ekxRmRMsShmw4b1pXtsiiiw5+zuITkQ==", + "version": "0.8.1-alpha.1", + "resolved": "https://registry.npmjs.org/@hubspot/calling-extensions-sdk/-/calling-extensions-sdk-0.8.1-alpha.1.tgz", + "integrity": "sha512-70vdhlgMgkDHo+zn4w+qxNpfCwLE2PECAITL3j3FknzrOTfdMsKxa3nHWzwV9iNmKEdU/UUhbEFmv49/GkUA9g==", + "license": "MIT", "engines": { "node": ">=14" } diff --git a/demos/demo-minimal-js/package.json b/demos/demo-minimal-js/package.json index 03ffc6a..588bcba 100644 --- a/demos/demo-minimal-js/package.json +++ b/demos/demo-minimal-js/package.json @@ -21,7 +21,7 @@ "webpack-dev-server": "^4.11.1" }, "dependencies": { - "@hubspot/calling-extensions-sdk": "^0.8.0", + "@hubspot/calling-extensions-sdk": "^0.8.1-alpha.1", "uuid": "^10.0.0" } } diff --git a/demos/demo-react-ts/package-lock.json b/demos/demo-react-ts/package-lock.json index d33a85f..62bc770 100644 --- a/demos/demo-react-ts/package-lock.json +++ b/demos/demo-react-ts/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@hubspot/calling-extensions-sdk": "^0.8.0", + "@hubspot/calling-extensions-sdk": "^0.8.1-alpha.1", "react": "^18.2.0", "react-aria": "^3.22.0", "react-dom": "^18.2.0", @@ -1861,9 +1861,10 @@ } }, "node_modules/@hubspot/calling-extensions-sdk": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@hubspot/calling-extensions-sdk/-/calling-extensions-sdk-0.8.0.tgz", - "integrity": "sha512-p6lwJd4tKnQVG3PGO6VRPeZ0finADOTw3pw9jGFwAXKQTODYNTIRSq0ekxRmRMsShmw4b1pXtsiiiw5+zuITkQ==", + "version": "0.8.1-alpha.1", + "resolved": "https://registry.npmjs.org/@hubspot/calling-extensions-sdk/-/calling-extensions-sdk-0.8.1-alpha.1.tgz", + "integrity": "sha512-70vdhlgMgkDHo+zn4w+qxNpfCwLE2PECAITL3j3FknzrOTfdMsKxa3nHWzwV9iNmKEdU/UUhbEFmv49/GkUA9g==", + "license": "MIT", "engines": { "node": ">=14" } @@ -10040,9 +10041,9 @@ } }, "@hubspot/calling-extensions-sdk": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@hubspot/calling-extensions-sdk/-/calling-extensions-sdk-0.8.0.tgz", - "integrity": "sha512-p6lwJd4tKnQVG3PGO6VRPeZ0finADOTw3pw9jGFwAXKQTODYNTIRSq0ekxRmRMsShmw4b1pXtsiiiw5+zuITkQ==" + "version": "0.8.1-alpha.1", + "resolved": "https://registry.npmjs.org/@hubspot/calling-extensions-sdk/-/calling-extensions-sdk-0.8.1-alpha.1.tgz", + "integrity": "sha512-70vdhlgMgkDHo+zn4w+qxNpfCwLE2PECAITL3j3FknzrOTfdMsKxa3nHWzwV9iNmKEdU/UUhbEFmv49/GkUA9g==" }, "@internationalized/date": { "version": "3.1.0", diff --git a/demos/demo-react-ts/package.json b/demos/demo-react-ts/package.json index a6ba6ab..5e631f6 100644 --- a/demos/demo-react-ts/package.json +++ b/demos/demo-react-ts/package.json @@ -18,7 +18,7 @@ "node": ">=14" }, "dependencies": { - "@hubspot/calling-extensions-sdk": "^0.8.0", + "@hubspot/calling-extensions-sdk": "^0.8.1-alpha.1", "react": "^18.2.0", "react-aria": "^3.22.0", "react-dom": "^18.2.0", diff --git a/demos/demo-react-ts/src/components/App.tsx b/demos/demo-react-ts/src/components/App.tsx index e2cdcd5..16ac333 100644 --- a/demos/demo-react-ts/src/components/App.tsx +++ b/demos/demo-react-ts/src/components/App.tsx @@ -1,5 +1,6 @@ import { useState, useMemo, useCallback } from "react"; import { ThemeProvider } from "styled-components"; +import { Constants } from "@hubspot/calling-extensions-sdk"; import { createTheme } from "../visitor-ui-component-library/theme/createTheme"; import { setDisabledBackgroundColor, @@ -25,6 +26,9 @@ import Alert from "./Alert"; import { CALYPSO, GYPSUM, KOALA, OLAF, SLINKY } from "../utils/colors"; import { FROM_NUMBER_ONE } from "../utils/phoneNumberUtils"; +// import { thirdPartyToHostEvents } from "../../../../src/Constants"; +const { thirdPartyToHostEvents } = Constants; + export const OUTBOUND_SCREENS = [ LoginScreen, KeypadScreen, @@ -41,6 +45,19 @@ export const INBOUND_SCREENS = [ CallEndedScreen, ]; +export const broadcastEventHandlers = { + [thirdPartyToHostEvents.LOGGED_IN]: "userLoggedIn", + [thirdPartyToHostEvents.LOGGED_OUT]: "userLoggedOut", + [thirdPartyToHostEvents.INITIALIZE]: "initialize", + [thirdPartyToHostEvents.OUTGOING_CALL_STARTED]: "outgoingCall", + [thirdPartyToHostEvents.USER_AVAILABLE]: "userAvailable", + [thirdPartyToHostEvents.USER_UNAVAILABLE]: "userUnavailable", + [thirdPartyToHostEvents.INCOMING_CALL]: "incomingCall", + [thirdPartyToHostEvents.CALL_ANSWERED]: "callAnswered", + [thirdPartyToHostEvents.CALL_ENDED]: "callEnded", + [thirdPartyToHostEvents.CALL_COMPLETED]: "callCompleted", +}; + const ALERT_CONTENT = ( Open your console to see the{" "} @@ -93,9 +110,13 @@ function App() { setIncomingNumber(incomingNumber); }; - const { cti, phoneNumber, engagementId, incomingContactName } = useCti( - initializeCallingStateForExistingCall - ); + const { + cti, + phoneNumber, + engagementId, + incomingContactName, + iframeLocation, + } = useCti(initializeCallingStateForExistingCall); const screens = direction === "OUTBOUND" ? OUTBOUND_SCREENS : INBOUND_SCREENS; @@ -129,17 +150,85 @@ function App() { } }, [screenIndex]); - const screenComponent = useMemo(() => { - const handleEndCall = () => { - stopTimer(); - handleNavigateToScreen(ScreenNames.CallEnded); - }; + const handleOutgoingCallStarted = useCallback(() => { + const callStartTime = Date.now(); + startTimer(callStartTime); + setDirection("OUTBOUND"); + handleNavigateToScreen(ScreenNames.Dialing); + }, []); + + const handleIncomingCall = useCallback(() => { + setDirection("INBOUND"); + handleNavigateToScreen(ScreenNames.Incoming); + }, []); + + const handleCallEnded = useCallback(() => { + stopTimer(); + handleNavigateToScreen(ScreenNames.CallEnded); + }, [stopTimer]); + + const handleCallCompleted = useCallback(() => { + resetInputs(); + handleNavigateToScreen(ScreenNames.Keypad); + }, [resetInputs]); + + cti.broadcastChannel.onmessage = ({ + data, + }: MessageEvent<{ type: string }>) => { + // Send SDK message to HubSpot + if (iframeLocation === "window") { + const eventHandler = broadcastEventHandlers[data.type]; + if (eventHandler) { + cti[eventHandler](data.payload); + } + } + + // Handle SDK message in iframe + switch (data.type) { + case thirdPartyToHostEvents.LOGGED_IN: + handleNavigateToScreen(ScreenNames.Keypad); + break; + + case thirdPartyToHostEvents.LOGGED_OUT: + handleNavigateToScreen(ScreenNames.Login); + break; + + case thirdPartyToHostEvents.USER_AVAILABLE: + setAvailability("AVAILABLE"); + break; + + case thirdPartyToHostEvents.USER_UNAVAILABLE: + setAvailability("UNAVAILABLE"); + break; + + case thirdPartyToHostEvents.OUTGOING_CALL_STARTED: + handleOutgoingCallStarted(); + break; + + case thirdPartyToHostEvents.INCOMING_CALL: + setIncomingNumber(data.payload.fromNumber); + handleIncomingCall(); + break; + + case thirdPartyToHostEvents.CALL_ANSWERED: { + handleNavigateToScreen(ScreenNames.Calling); + break; + } - const handleSaveCall = () => { - resetInputs(); - handleNavigateToScreen(ScreenNames.Keypad); - }; + case thirdPartyToHostEvents.CALL_ENDED: + handleCallEnded(); + break; + case thirdPartyToHostEvents.CALL_COMPLETED: + handleCallCompleted(); + break; + + default: + // Do nothing + } + }; + + const screenComponent = useMemo(() => { const Component = screens[screenIndex]; if (!Component) { return null; @@ -162,8 +251,10 @@ function App() { callDurationString={callDurationString} startTimer={startTimer} stopTimer={stopTimer} - handleEndCall={handleEndCall} - handleSaveCall={handleSaveCall} + handleOutgoingCallStarted={handleOutgoingCallStarted} + handleIncomingCall={handleIncomingCall} + handleCallEnded={handleCallEnded} + handleCallCompleted={handleCallCompleted} fromNumber={fromNumber} setFromNumber={setFromNumber} incomingNumber={incomingNumber} @@ -187,17 +278,21 @@ function App() { engagementId, dialNumber, notes, + isCallRecorded, callDuration, callDurationString, startTimer, stopTimer, + handleCallEnded, + handleCallCompleted, fromNumber, incomingNumber, - callStatus, availability, direction, incomingContactName, - resetInputs, + callStatus, + handleIncomingCall, + handleOutgoingCallStarted, ]); return ( diff --git a/demos/demo-react-ts/src/components/screens/CallingScreen.tsx b/demos/demo-react-ts/src/components/screens/CallingScreen.tsx index fdd9155..9f91360 100644 --- a/demos/demo-react-ts/src/components/screens/CallingScreen.tsx +++ b/demos/demo-react-ts/src/components/screens/CallingScreen.tsx @@ -57,6 +57,7 @@ function CallingScreen({ cti.callEnded({ callEndStatus: "COMPLETED", }); + handleEndCall(); }; diff --git a/demos/demo-react-ts/src/components/screens/DialingScreen.tsx b/demos/demo-react-ts/src/components/screens/DialingScreen.tsx index 2feaefc..8dee1ef 100644 --- a/demos/demo-react-ts/src/components/screens/DialingScreen.tsx +++ b/demos/demo-react-ts/src/components/screens/DialingScreen.tsx @@ -9,7 +9,7 @@ function DialingScreen({ handleNextScreen, dialNumber, callDurationString, - handleEndCall, + handleCallEnded, cti, }: ScreenProps) { useEffect(() => { @@ -24,7 +24,7 @@ function DialingScreen({ cti.callEnded({ callEndStatus: "COMPLETED", }); - handleEndCall(); + handleCallEnded(); }; return ( diff --git a/demos/demo-react-ts/src/components/screens/IncomingScreen.tsx b/demos/demo-react-ts/src/components/screens/IncomingScreen.tsx index 400843e..357b20f 100644 --- a/demos/demo-react-ts/src/components/screens/IncomingScreen.tsx +++ b/demos/demo-react-ts/src/components/screens/IncomingScreen.tsx @@ -16,7 +16,7 @@ import { ANSWER_CALL, END_CALL } from "../../constants/buttonIds"; function IncomingScreen({ handleNextScreen, incomingNumber, - handleEndCall, + handleCallEnded, cti, startTimer, incomingContactName, @@ -32,7 +32,7 @@ function IncomingScreen({ const onEndIncomingCall = () => { setCallStatus("CANCELED"); cti.callEnded({ callEndStatus: "CANCELED" }); - handleEndCall(); + handleCallEnded(); }; return ( diff --git a/demos/demo-react-ts/src/components/screens/KeypadScreen.tsx b/demos/demo-react-ts/src/components/screens/KeypadScreen.tsx index 05f10a2..14abf73 100644 --- a/demos/demo-react-ts/src/components/screens/KeypadScreen.tsx +++ b/demos/demo-react-ts/src/components/screens/KeypadScreen.tsx @@ -52,6 +52,8 @@ function KeypadScreen({ setDirection, incomingNumber, setIncomingNumber, + handleIncomingCall, + handleOutgoingCallStarted, }: ScreenProps) { const dialNumberInput = useAutoFocus(); const [cursorStart, setCursorStart] = useState(dialNumber.length || 0); @@ -109,10 +111,8 @@ function KeypadScreen({ fromNumber, callStartTime, }); - startTimer(callStartTime); - setDirection("OUTBOUND"); - handleNextScreen(); - }, [cti, dialNumber, handleNextScreen, startTimer, setDirection, fromNumber]); + handleOutgoingCallStarted(); + }, [cti, dialNumber, fromNumber, handleOutgoingCallStarted]); const handleTriggerIncomingCall = useCallback( (incomingCallNumber: string) => { @@ -121,10 +121,9 @@ function KeypadScreen({ fromNumber: incomingCallNumber, toNumber: fromNumber, }); - setDirection("INBOUND"); - handleNextScreen(); + handleIncomingCall(); }, - [handleNextScreen, setDirection, cti, fromNumber] + [cti, fromNumber, handleIncomingCall] ); const handleBackspace = useCallback(() => { diff --git a/demos/demo-react-ts/src/hooks/useCti.ts b/demos/demo-react-ts/src/hooks/useCti.ts index 08a38e0..cc65b6f 100644 --- a/demos/demo-react-ts/src/hooks/useCti.ts +++ b/demos/demo-react-ts/src/hooks/useCti.ts @@ -13,10 +13,16 @@ import CallingExtensions, { OnPublishToChannel, OnResize, Options, + Constants, } from "@hubspot/calling-extensions-sdk"; +// } from "../../../../src/CallingExtensions"; + import { useMemo, useState } from "react"; import { v4 as uuidv4 } from "uuid"; +// import { thirdPartyToHostEvents } from "../../../../src/Constants"; +const { thirdPartyToHostEvents } = Constants; + const INCOMING_NUMBER_KEY = "LocalSettings:Calling:DemoReact:incomingNumber"; const INCOMING_CONTACT_NAME_KEY = "LocalSettings:Calling:DemoReact:incomingContactName"; @@ -49,8 +55,15 @@ class CallingExtensionsWrapper implements CallingExtensionsContract { private _externalCallId = ""; + private _iframeLocation = ""; + + broadcastChannel: BroadcastChannel = new BroadcastChannel( + "calling-extensions-demo-react-ts" + ); + constructor(options: Options) { this._cti = new CallingExtensions(options); + window.broadcastChannel = this.broadcastChannel; } get externalCallId() { @@ -69,36 +82,99 @@ class CallingExtensionsWrapper implements CallingExtensionsContract { this._incomingNumber = number; } + get iframeLocation() { + return this._iframeLocation; + } + + set iframeLocation(location: string) { + this._iframeLocation = location; + } + initialized(userData: OnInitialized) { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ type: thirdPartyToHostEvents.INITIALIZED }); + return; + } + + if (userData.iframeLocation) { + this._iframeLocation = userData.iframeLocation; + } + return this._cti.initialized(userData); } userAvailable() { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ type: thirdPartyToHostEvents.USER_AVAILABLE }); + return; + } + return this._cti.userAvailable(); } userUnavailable() { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ type: thirdPartyToHostEvents.USER_UNAVAILABLE }); + return; + } + return this._cti.userUnavailable(); } userLoggedIn() { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ type: thirdPartyToHostEvents.LOGGED_IN }); + return; + } + return this._cti.userLoggedIn(); } userLoggedOut() { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ type: thirdPartyToHostEvents.LOGGED_OUT }); + return; + } + return this._cti.userLoggedOut(); } incomingCall(callDetails: OnIncomingCall) { + // Triggered from remote + if (this._iframeLocation === "remote") { + this.broadcastMessage({ + type: thirdPartyToHostEvents.INCOMING_CALL, + payload: callDetails, + }); + return; + } + + // Triggered from popup + if (this._iframeLocation === "window") { + this.broadcastMessage({ + type: thirdPartyToHostEvents.INCOMING_CALL, + payload: callDetails, + }); + } + + // Send message to HubSpot this.incomingNumber = callDetails.fromNumber; this.externalCallId = uuidv4(); - return this._cti.incomingCall({ + this._cti.incomingCall({ ...callDetails, externalCallId: this.externalCallId, }); } outgoingCall(callDetails: OnOutgoingCall) { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ + type: thirdPartyToHostEvents.OUTGOING_CALL_STARTED, + payload: callDetails, + }); + return; + } + this.externalCallId = uuidv4(); return this._cti.outgoingCall({ ...callDetails, @@ -111,6 +187,14 @@ class CallingExtensionsWrapper implements CallingExtensionsContract { } callAnswered(data: OnCallAnswered) { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ + type: thirdPartyToHostEvents.CALL_ANSWERED, + payload: data, + }); + return; + } + return this._cti.callAnswered({ ...data, externalCallId: this.externalCallId, @@ -122,6 +206,14 @@ class CallingExtensionsWrapper implements CallingExtensionsContract { } callEnded(engagementData: OnCallEnded) { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ + type: thirdPartyToHostEvents.CALL_ENDED, + payload: engagementData, + }); + return; + } + return this._cti.callEnded({ ...engagementData, externalCallId: this.externalCallId, @@ -129,6 +221,14 @@ class CallingExtensionsWrapper implements CallingExtensionsContract { } callCompleted(callCompletedData: OnCallCompleted) { + if (this._iframeLocation === "remote") { + this.broadcastMessage({ + type: thirdPartyToHostEvents.CALL_COMPLETED, + payload: callCompletedData, + }); + return; + } + this._cti.callCompleted({ ...callCompletedData, externalCallId: this.externalCallId, @@ -155,6 +255,13 @@ class CallingExtensionsWrapper implements CallingExtensionsContract { logDebugMessage(messageData: any) { return this._cti.logDebugMessage(messageData); } + + broadcastMessage({ type, payload }: { type: string; payload: any }) { + this.broadcastChannel.postMessage({ + type, + payload: { ...payload, externalCallId: this.externalCallId }, + }); + } } export const useCti = ( @@ -163,6 +270,8 @@ export const useCti = ( const [phoneNumber, setPhoneNumber] = useState(""); const [engagementId, setEngagementId] = useState(null); const [incomingContactName, setIncomingContactName] = useState(""); + const [iframeLocation, setIframeLocation] = useState(""); + const cti = useMemo(() => { return new CallingExtensionsWrapper({ debugMode: true, @@ -172,6 +281,7 @@ export const useCti = ( portalId?: number; userId?: number; ownerId?: number; + iframeLocation?: string; }) => { const engagementId = (data && data.engagementId) || 0; @@ -183,6 +293,7 @@ export const useCti = ( width: 400, height: 650, }, + iframeLocation: data.iframeLocation, } as OnInitialized); const incomingNumber = window.localStorage.getItem(INCOMING_NUMBER_KEY); @@ -198,6 +309,9 @@ export const useCti = ( window.localStorage.removeItem(INCOMING_NUMBER_KEY); window.localStorage.removeItem(INCOMING_CONTACT_NAME_KEY); } + if (data.iframeLocation) { + setIframeLocation(data.iframeLocation); + } }, onDialNumber: (data: any, _rawEvent: any) => { const { phoneNumber } = data; @@ -301,5 +415,6 @@ export const useCti = ( engagementId, cti, incomingContactName, + iframeLocation, }; }; diff --git a/demos/demo-react-ts/src/types/ScreenTypes.ts b/demos/demo-react-ts/src/types/ScreenTypes.ts index 17633a3..722fa28 100644 --- a/demos/demo-react-ts/src/types/ScreenTypes.ts +++ b/demos/demo-react-ts/src/types/ScreenTypes.ts @@ -41,4 +41,5 @@ export interface ScreenProps { setIncomingNumber: (number: string) => void; callStatus: CallStatus | null; setCallStatus: (callStatus: CallStatus) => void; + iframeLocation: string; } diff --git a/demos/demo-react-ts/test/spec/components/screens/IncomingScreen-test.tsx b/demos/demo-react-ts/test/spec/components/screens/IncomingScreen-test.tsx index 230fc87..26d8895 100644 --- a/demos/demo-react-ts/test/spec/components/screens/IncomingScreen-test.tsx +++ b/demos/demo-react-ts/test/spec/components/screens/IncomingScreen-test.tsx @@ -24,7 +24,7 @@ const props: Partial = { callDurationString: "", startTimer: noop, stopTimer: noop, - handleEndCall: noop, + handleCallEnded: noop, handleSaveCall: noop, fromNumber: "", setFromNumber: noop, @@ -42,6 +42,7 @@ describe("IncomingScreen", () => { props.handleNextScreen = jasmine.createSpy("handleNextScreen"); props.startTimer = jasmine.createSpy("startTimer"); cti.callAnswered = jasmine.createSpy("callAnswered"); + props.handleCallEnded = jasmine.createSpy("handleCallEnded"); }); it("Shows call ended text - no contact match", () => { @@ -110,7 +111,7 @@ describe("IncomingScreen", () => { button.click(); // ASSERT - expect(props.handleEndCall).toHaveBeenCalled(); + expect(props.handleCallEnded).toHaveBeenCalled(); expect(cti.callEnded).toHaveBeenCalledWith({ callEndStatus: "CANCELED", }); diff --git a/demos/demo-react-ts/test/spec/components/screens/KeypadScreen-test.tsx b/demos/demo-react-ts/test/spec/components/screens/KeypadScreen-test.tsx index 2ef84b5..2cbdaf4 100644 --- a/demos/demo-react-ts/test/spec/components/screens/KeypadScreen-test.tsx +++ b/demos/demo-react-ts/test/spec/components/screens/KeypadScreen-test.tsx @@ -40,6 +40,8 @@ const props: Partial = { setDirection: noop, setIncomingNumber: noop, setAvailability: noop, + handleIncomingCall: noop, + handleOutgoingCallStarted: noop, }; describe("KeypadScreen", () => { @@ -56,6 +58,10 @@ describe("KeypadScreen", () => { props.setDirection = jasmine.createSpy("setDirection"); cti.incomingCall = jasmine.createSpy("incomingCall"); props.setIncomingNumber = jasmine.createSpy("setIncomingNumber"); + props.handleIncomingCall = jasmine.createSpy("handleIncomingCall"); + props.handleOutgoingCallStarted = jasmine.createSpy( + "handleOutgoingCallStarted" + ); }); it("Shows initial dial number", () => { @@ -216,13 +222,12 @@ describe("KeypadScreen", () => { triggerCallBtn.click(); // ASSERT - expect(props.setDirection).toHaveBeenCalledWith("INBOUND"); expect(cti.incomingCall).toHaveBeenCalledWith({ createEngagement: true, fromNumber: "6476251259", toNumber: "123456789", }); - expect(props.handleNextScreen).toHaveBeenCalled(); + expect(props.handleIncomingCall).toHaveBeenCalled(); }); }); @@ -256,7 +261,7 @@ describe("KeypadScreen", () => { fromNumber: "+161", callStartTime: jasmine.anything(), }); - expect(props.handleNextScreen).toHaveBeenCalled(); + expect(props.handleOutgoingCallStarted).toHaveBeenCalled(); }); }); diff --git a/package-lock.json b/package-lock.json index 0f45628..2d65034 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@hubspot/calling-extensions-sdk", - "version": "0.8.1-alpha.0", + "version": "0.8.1-alpha.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@hubspot/calling-extensions-sdk", - "version": "0.8.1-alpha.0", + "version": "0.8.1-alpha.1", "license": "MIT", "devDependencies": { "@babel/cli": "^7.21.0", diff --git a/package.json b/package.json index 78d4427..4fc5526 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hubspot/calling-extensions-sdk", - "version": "0.8.1-alpha.0", + "version": "0.8.1-alpha.1", "description": "A JavaScript SDK for integrating calling apps into HubSpot.", "publishConfig": { "access": "public" diff --git a/src/Constants.js b/src/Constants.js index aad2b53..5e22d32 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -10,7 +10,7 @@ export const debugMessageType = { GENERIC_MESSAGE: "Generic Message", }; -const thirdPartyToHostEvents = { +export const thirdPartyToHostEvents = { CALL_ANSWERED: "CALL_ANSWERED", CALL_COMPLETED: "CALL_COMPLETED", CALL_DATA: "CALL_DATA", diff --git a/src/IFrameManager.js b/src/IFrameManager.js index f402afc..40429b9 100644 --- a/src/IFrameManager.js +++ b/src/IFrameManager.js @@ -233,8 +233,11 @@ class IFrameManager { onMessage(event) { const { data, origin } = event; // eslint-disable-next-line object-curly-newline - const { type, engagementId, portalId, userId, ownerId } = event.data; + const { type } = event.data; if (type === messageType.SYNC) { + const { portalId, userId, ownerId, engagementId, iframeLocation } = + event.data; + // The iFrame host can send this message multiple times, don't respond more than once if (!this.isReady) { this.isReady = true; @@ -255,8 +258,10 @@ class IFrameManager { portalId, userId, ownerId, + iframeLocation, }); } + return; }