From a4592c0addc947036bb0f28283aa9d11835a29d5 Mon Sep 17 00:00:00 2001 From: ashishkumar Date: Tue, 8 Aug 2023 13:29:27 +0530 Subject: [PATCH 01/22] FLEXIN-74: changed endpoints for init and token refresh --- .env.sample | 6 ++-- public/index.html | 3 +- src/__tests__/index.test.tsx | 10 ------- src/__tests__/sessionDataHandler.test.ts | 38 +++++++++++++++++++++--- src/index.tsx | 3 -- src/sessionDataHandler.ts | 18 +++++------ src/utils/regionUtil.test.ts | 14 +++++++++ src/utils/regionUtil.ts | 14 +++++++++ 8 files changed, 72 insertions(+), 34 deletions(-) create mode 100644 src/utils/regionUtil.test.ts create mode 100644 src/utils/regionUtil.ts diff --git a/.env.sample b/.env.sample index 64e2200f..6ccf1f37 100644 --- a/.env.sample +++ b/.env.sample @@ -4,10 +4,8 @@ API_KEY= API_SECRET= ADDRESS_SID= CONVERSATIONS_SERVICE_SID= -# ALLOWED_ORIGINS should be a comma-separated list of origins -ALLOWED_ORIGINS=http://localhost:3000 -## base endpoint of your local server. By default it is "http://localhost:3001" -REACT_APP_SERVER_URL=http://localhost:3001 +# Region for API calls (us1, stage-us1), defaults to us1, if empty +REGION='' # Used to enable/disable downloading/emailing of chat transcripts for the customer. Enable by setting the variable to true. DOWNLOAD_TRANSCRIPT_ENABLED=false EMAIL_TRANSCRIPT_ENABLED=false diff --git a/public/index.html b/public/index.html index 5ddb00b0..fc87a8cd 100644 --- a/public/index.html +++ b/public/index.html @@ -41,7 +41,6 @@ - \ No newline at end of file + diff --git a/src/__tests__/index.test.tsx b/src/__tests__/index.test.tsx index c30607b3..04acba43 100644 --- a/src/__tests__/index.test.tsx +++ b/src/__tests__/index.test.tsx @@ -2,7 +2,6 @@ import ".."; import { Provider } from "react-redux"; import * as reactDom from "react-dom"; -import { sessionDataHandler } from "../sessionDataHandler"; import { WebchatWidget } from "../components/WebchatWidget"; import { store } from "../store/store"; import * as logger from "../logger"; @@ -32,15 +31,6 @@ describe("Index", () => { ); }); - it("sets endpoint correctly", () => { - const setEndpointSpy = jest.spyOn(sessionDataHandler, "setEndpoint"); - - const serverUrl = "serverUrl"; - initWebchat({ serverUrl }); - - expect(setEndpointSpy).toBeCalledWith(serverUrl); - }); - it("initializes config", () => { const initConfigSpy = jest.spyOn(initActions, "initConfig"); diff --git a/src/__tests__/sessionDataHandler.test.ts b/src/__tests__/sessionDataHandler.test.ts index d18e1149..5d806996 100644 --- a/src/__tests__/sessionDataHandler.test.ts +++ b/src/__tests__/sessionDataHandler.test.ts @@ -1,6 +1,6 @@ import fetchMock from "fetch-mock-jest"; -import { sessionDataHandler } from "../sessionDataHandler"; +import { sessionDataHandler, contactBackend } from "../sessionDataHandler"; Object.defineProperty(navigator, "mediaCapabilities", { writable: true, @@ -14,9 +14,39 @@ describe("session data handler", () => { jest.clearAllMocks(); }); - it("should set an endpoint", () => { - sessionDataHandler.setEndpoint("foo"); - expect(sessionDataHandler.getEndpoint()).toBe("foo"); + describe("contactBackend", () => { + const originalEnv = process.env; + + beforeEach(() => { + jest.resetModules(); + }); + + afterEach(() => { + process.env = originalEnv; + }); + + it("should call correct stage url", async () => { + const mockFetch = Promise.resolve({ ok: true, json: async () => Promise.resolve("okay") }); + const fetchSpy = jest + .spyOn(window, "fetch") + .mockImplementation(async (): Promise => mockFetch as Promise); + process.env = { + ...originalEnv, + REGION: "stage" + }; + await contactBackend("/Webchat/Tokens/Refresh", { formData: {} }); + expect(fetchSpy.mock.calls[0][0]).toEqual("https://flex-api.stage.twilio.com/V2/Webchat/Tokens/Refresh"); + }); + + it("should call correct prod url", async () => { + process.env.REGION = ""; + const mockFetch = Promise.resolve({ ok: true, json: async () => Promise.resolve("okay") }); + const fetchSpy = jest + .spyOn(window, "fetch") + .mockImplementation(async (): Promise => mockFetch as Promise); + await contactBackend("/Webchat/Tokens/Refresh", { formData: {} }); + expect(fetchSpy.mock.calls[0][0]).toEqual("https://flex-api.twilio.com/V2/Webchat/Tokens/Refresh"); + }); }); describe("fetch and store new session", () => { diff --git a/src/index.tsx b/src/index.tsx index 293ffa51..b9532da7 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,13 +4,11 @@ import { Provider } from "react-redux"; import { store } from "./store/store"; import { WebchatWidget } from "./components/WebchatWidget"; -import { sessionDataHandler } from "./sessionDataHandler"; import { initConfig } from "./store/actions/initActions"; import { ConfigState } from "./store/definitions"; import { initLogger } from "./logger"; const defaultConfig: ConfigState = { - serverUrl: "http://localhost:3001", theme: { isLight: true }, @@ -38,7 +36,6 @@ const defaultConfig: ConfigState = { const initWebchat = async (config: ConfigState) => { const mergedConfig = merge({}, defaultConfig, config); - sessionDataHandler.setEndpoint(mergedConfig.serverUrl); store.dispatch(initConfig(mergedConfig)); initLogger(); const rootElement = document.getElementById("twilio-webchat-widget-root"); diff --git a/src/sessionDataHandler.ts b/src/sessionDataHandler.ts index 78eedf81..dd7e2357 100644 --- a/src/sessionDataHandler.ts +++ b/src/sessionDataHandler.ts @@ -2,16 +2,20 @@ import log from "loglevel"; import { Token } from "./definitions"; import { generateSecurityHeaders } from "./utils/generateSecurityHeaders"; +import { buildRegionalHost } from "./utils/regionUtil"; export const LOCALSTORAGE_SESSION_ITEM_ID = "TWILIO_WEBCHAT_WIDGET"; -let _endpoint = ""; +function getServerUrl(REGION: string): string { + return `https://flex-api${buildRegionalHost(REGION)}.twilio.com/V2`; +} type SessionDataStorage = Token & { loginTimestamp: number | null; }; export async function contactBackend(endpointRoute: string, body: Record = {}): Promise { + const _endpoint = getServerUrl(process.env.REGION ?? ""); const securityHeaders = await generateSecurityHeaders(); const response = await fetch(_endpoint + endpointRoute, { method: "POST", @@ -53,14 +57,6 @@ function getStoredSessionData() { } export const sessionDataHandler = { - setEndpoint(endpoint: string = "") { - _endpoint = endpoint; - }, - - getEndpoint() { - return _endpoint; - }, - tryResumeExistingSession(): Token | null { log.debug("sessionDataHandler: trying to refresh existing session"); const storedTokenData = getStoredSessionData(); @@ -95,7 +91,7 @@ export const sessionDataHandler = { let newTokenData: Token; try { - newTokenData = await contactBackend("/refreshToken", { + newTokenData = await contactBackend("/Webchat/Tokens/Refresh", { token: storedTokenData.token }); } catch (e) { @@ -119,7 +115,7 @@ export const sessionDataHandler = { let newTokenData; try { - newTokenData = await contactBackend("/initWebchat", { formData }); + newTokenData = await contactBackend("/Webchat/Init", { formData }); } catch (e) { throw Error("No results from server"); } diff --git a/src/utils/regionUtil.test.ts b/src/utils/regionUtil.test.ts new file mode 100644 index 00000000..f05bd17c --- /dev/null +++ b/src/utils/regionUtil.test.ts @@ -0,0 +1,14 @@ +import { buildRegionalHost } from "./regionUtil"; + +describe("buildRegionalHost(region)", () => { + it("builds correct region for various values", () => { + expect(buildRegionalHost("us1")).toBe(""); + expect(buildRegionalHost("ie1")).toBe(".ie1"); + expect(buildRegionalHost("")).toBe(""); + expect(buildRegionalHost("prod")).toBe(""); + expect(buildRegionalHost("stage-au1")).toBe(".stage-au1"); + expect(buildRegionalHost("stage-us1")).toBe(".stage"); + expect(buildRegionalHost("dev-us1")).toBe(".dev"); + expect(buildRegionalHost("dev-us2")).toBe(".dev-us2"); + }); +}); diff --git a/src/utils/regionUtil.ts b/src/utils/regionUtil.ts new file mode 100644 index 00000000..563f8609 --- /dev/null +++ b/src/utils/regionUtil.ts @@ -0,0 +1,14 @@ +export function buildRegionalHost(region: string): string { + switch (region) { + case "prod": + case "us1": + case "": + return ""; + case "dev-us1": + return ".dev"; + case "stage-us1": + return ".stage"; + default: + return `.${region}`; + } +} From 3d2147a7e3e09d5f69e929631b72b50575a42f59 Mon Sep 17 00:00:00 2001 From: ashishkumar Date: Tue, 8 Aug 2023 13:41:30 +0530 Subject: [PATCH 02/22] FLEXIN-74: added spaces --- .env.sample | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.env.sample b/.env.sample index 6ccf1f37..483c61ba 100644 --- a/.env.sample +++ b/.env.sample @@ -4,11 +4,14 @@ API_KEY= API_SECRET= ADDRESS_SID= CONVERSATIONS_SERVICE_SID= + # Region for API calls (us1, stage-us1), defaults to us1, if empty REGION='' + # Used to enable/disable downloading/emailing of chat transcripts for the customer. Enable by setting the variable to true. DOWNLOAD_TRANSCRIPT_ENABLED=false EMAIL_TRANSCRIPT_ENABLED=false + # The environment variable below are optional and should only be filled if enabling email chat transcripts. SENDGRID_API_KEY= FROM_EMAIL= From 2d7a84c7991d3f7d702bf8abc0977a2fde7b32e2 Mon Sep 17 00:00:00 2001 From: ashishkumar Date: Wed, 9 Aug 2023 17:41:06 +0530 Subject: [PATCH 03/22] FLEXIN-74: added deploymentKey and region to the apis --- .env.sample | 13 ++++--- public/index.html | 2 ++ src/__tests__/sessionDataHandler.test.ts | 28 ++++++++------- src/components/PreEngagementFormPhase.tsx | 2 +- .../__tests__/PreEngagementFormPhase.test.tsx | 4 ++- src/index.tsx | 11 ++++-- src/sessionDataHandler.ts | 34 +++++++++++++++---- src/store/definitions.ts | 3 +- src/utils/regionUtil.ts | 2 +- 9 files changed, 70 insertions(+), 29 deletions(-) diff --git a/.env.sample b/.env.sample index 483c61ba..8ff636ba 100644 --- a/.env.sample +++ b/.env.sample @@ -4,14 +4,17 @@ API_KEY= API_SECRET= ADDRESS_SID= CONVERSATIONS_SERVICE_SID= - -# Region for API calls (us1, stage-us1), defaults to us1, if empty -REGION='' - +# ALLOWED_ORIGINS should be a comma-separated list of origins +ALLOWED_ORIGINS=http://localhost:3000 +## base endpoint of your local server. By default it is "http://localhost:3001" +REACT_APP_SERVER_URL=http://localhost:3001 +# region for the host (i.e stage-us1, dev-us1, us1), defaults to us1(prod) +REACT_APP_REGION='' +# deployment key for Webchat app +REACT_APP_DEPLOYMENT_KEY='' # Used to enable/disable downloading/emailing of chat transcripts for the customer. Enable by setting the variable to true. DOWNLOAD_TRANSCRIPT_ENABLED=false EMAIL_TRANSCRIPT_ENABLED=false - # The environment variable below are optional and should only be filled if enabling email chat transcripts. SENDGRID_API_KEY= FROM_EMAIL= diff --git a/public/index.html b/public/index.html index fc87a8cd..0aa5ad17 100644 --- a/public/index.html +++ b/public/index.html @@ -41,6 +41,8 @@