Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FLEXIN-74: changed endpoints for init and token refresh #46

Merged
merged 28 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a4592c0
FLEXIN-74: changed endpoints for init and token refresh
ashishkumarTWLO Aug 8, 2023
3d2147a
FLEXIN-74: added spaces
ashishkumarTWLO Aug 8, 2023
2d7a84c
FLEXIN-74: added deploymentKey and region to the apis
ashishkumarTWLO Aug 9, 2023
0d6c019
FLEXIN-74: updated deprecated event
ashishkumarTWLO Aug 9, 2023
93a237d
FLEXIN-74: updated test
ashishkumarTWLO Aug 9, 2023
9426d99
FLEXIN-74: updated test
ashishkumarTWLO Aug 9, 2023
1c29d80
FLEXIN-74: address PR comments
ashishkumarTWLO Aug 9, 2023
fe1d04b
FLEXIN-74: added validation
ashishkumarTWLO Aug 11, 2023
e935b78
FLEXIN-74: removed default value for setDeploymentKey()
ashishkumarTWLO Aug 11, 2023
fd6a707
FLEXIN-74: added msg to env variable
ashishkumarTWLO Aug 16, 2023
00df233
Merge branch 'flex-webchat-ui' into FLEXIN-74
ashishkumarTWLO Aug 17, 2023
15bd19e
FLEXIN-74: replaced console with logger framework
ashishkumarTWLO Aug 17, 2023
4d66a64
FLEXIN-74: using each
ashishkumarTWLO Aug 18, 2023
84bedfd
FLEXIN-74: POC changes
ashishkumarTWLO Oct 3, 2023
ee17eba
FLEXIN-74: POC changes 2
ashishkumarTWLO Oct 5, 2023
b7139ac
FLEXIN-74: POC changes 3
ashishkumarTWLO Oct 6, 2023
7465863
Merge branch 'flex-webchat-ui' into FLEXIN-74
ashishkumarTWLO Oct 10, 2023
5fca1f7
FLEXIN-74: corrections after merge conflicts
ashishkumarTWLO Oct 10, 2023
6fc69be
Merge branch 'flex-webchat-ui' into FLEXIN-74
ashishkumarTWLO Oct 10, 2023
ba6e1ba
FLEXIN-74: fixing unit tests
ashishkumarTWLO Oct 10, 2023
80cc23d
FLEXIN-74: fixing unit tests
ashishkumarTWLO Oct 11, 2023
d757719
FLEXIN-74: more fixing
ashishkumarTWLO Oct 11, 2023
807c1dc
FLEXIN-74: more fixing
ashishkumarTWLO Oct 11, 2023
2fece92
Merge branch 'flex-webchat-ui' into FLEXIN-74
ashishkumarTWLO Oct 12, 2023
3b4a1ea
Merge branch 'flex-webchat-ui' into FLEXIN-74
ashishkumarTWLO Oct 12, 2023
8db9c5f
Merge remote-tracking branch 'origin/flex-webchat-ui' into FLEXIN-74
ashishkumarTWLO Oct 16, 2023
4e750f7
FLEXIN-74: fixing more unit tests
ashishkumarTWLO Oct 16, 2023
b45928d
FLEXIN-74: removing log
ashishkumarTWLO Oct 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ CONVERSATIONS_SERVICE_SID=
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
AnudeepChPaul marked this conversation as resolved.
Show resolved Hide resolved
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
Expand Down
5 changes: 3 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
<script>
window.addEventListener("DOMContentLoaded", () => {
Twilio.initWebchat({
serverUrl: "%REACT_APP_SERVER_URL%",
deploymentKey: "%REACT_APP_DEPLOYMENT_KEY%",
region: "%REACT_APP_REGION%",
theme: {
isLight: true
}
Expand All @@ -50,4 +51,4 @@
</script>
</body>

</html>
</html>
19 changes: 14 additions & 5 deletions src/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,22 @@ describe("Index", () => {
);
});

it("sets endpoint correctly", () => {
const setEndpointSpy = jest.spyOn(sessionDataHandler, "setEndpoint");
it("sets region correctly", () => {
const setEndpointSpy = jest.spyOn(sessionDataHandler, "setRegion");
AnudeepChPaul marked this conversation as resolved.
Show resolved Hide resolved

const serverUrl = "serverUrl";
initWebchat({ serverUrl });
const region = "Foo";
initWebchat({ region });

expect(setEndpointSpy).toBeCalledWith(region);
});

it("sets deployment key correctly", () => {
const setEndpointSpy = jest.spyOn(sessionDataHandler, "setDeploymentKey");
AnudeepChPaul marked this conversation as resolved.
Show resolved Hide resolved

const deploymentKey = "Foo";
initWebchat({ deploymentKey });

expect(setEndpointSpy).toBeCalledWith(serverUrl);
expect(setEndpointSpy).toBeCalledWith(deploymentKey);
});

it("initializes config", () => {
Expand Down
42 changes: 38 additions & 4 deletions src/__tests__/sessionDataHandler.test.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -14,9 +14,43 @@ describe("session data handler", () => {
jest.clearAllMocks();
});

it("should set an endpoint", () => {
sessionDataHandler.setEndpoint("foo");
expect(sessionDataHandler.getEndpoint()).toBe("foo");
it("should set the region", () => {
sessionDataHandler.setRegion("Foo");
expect(sessionDataHandler.getRegion()).toBe("Foo");
});

it("should set the deployment key", () => {
sessionDataHandler.setDeploymentKey("key1");
expect(sessionDataHandler.getDeploymentKey()).toBe("key1");
});

describe("contactBackend", () => {
beforeEach(() => () => {
sessionDataHandler.setRegion("");
AnudeepChPaul marked this conversation as resolved.
Show resolved Hide resolved
});

afterEach(() => {
sessionDataHandler.setRegion("");
});

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<never> => mockFetch as Promise<never>);
mdeshpande12 marked this conversation as resolved.
Show resolved Hide resolved
sessionDataHandler.setRegion("stage");
await contactBackend("/Webchat/Tokens/Refresh", { formData: {} });
AnudeepChPaul marked this conversation as resolved.
Show resolved Hide resolved
expect(fetchSpy.mock.calls[0][0]).toEqual("https://flex-api.stage.twilio.com/v2/Webchat/Tokens/Refresh");
});

it("should call correct prod url", async () => {
const mockFetch = Promise.resolve({ ok: true, json: async () => Promise.resolve("okay") });
const fetchSpy = jest
.spyOn(window, "fetch")
.mockImplementation(async (): Promise<never> => mockFetch as Promise<never>);
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", () => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/PreEngagementFormPhase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const PreEngagementFormPhase = () => {
try {
const data = await sessionDataHandler.fetchAndStoreNewSession({
formData: {
friendlyName: name && onUserInputSubmit(name, true),
customerFriendlyName: name && onUserInputSubmit(name, true),
email,
query: query && onUserInputSubmit(query)
}
Expand Down Expand Up @@ -92,7 +92,7 @@ export const PreEngagementFormPhase = () => {
data-test="pre-engagement-chat-form-query-textarea"
value={query}
onChange={(e) => dispatch(updatePreEngagementData({ query: e.target.value }))}
onKeyPress={handleKeyPress}
onKeyDown={handleKeyPress}
vinesh-kumar marked this conversation as resolved.
Show resolved Hide resolved
required
/>
</Box>
Expand Down
8 changes: 5 additions & 3 deletions src/components/__tests__/PreEngagementFormPhase.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,17 @@ describe("Pre Engagement Form Phase", () => {
fireEvent.change(queryInput, { target: { value: query } });
fireEvent.submit(formBox);

expect(fetchAndStoreNewSessionSpy).toHaveBeenCalledWith({ formData: { friendlyName: name, query, email } });
expect(fetchAndStoreNewSessionSpy).toHaveBeenCalledWith({
formData: { customerFriendlyName: name, query, email }
});
});

it("submits form on enter within textarea", () => {
const fetchAndStoreNewSessionSpy = jest.spyOn(sessionDataHandler, "fetchAndStoreNewSession");
const { container } = render(withStore(<PreEngagementFormPhase />));

const textArea = container.querySelector("textarea") as Element;
fireEvent.keyPress(textArea, { key: "Enter", code: "Enter", charCode: 13, shiftKey: false });
fireEvent.keyDown(textArea, { key: "Enter", code: "Enter", charCode: 13, shiftKey: false });

expect(fetchAndStoreNewSessionSpy).toHaveBeenCalled();
});
Expand All @@ -153,7 +155,7 @@ describe("Pre Engagement Form Phase", () => {
const { container } = render(withStore(<PreEngagementFormPhase />));

const textArea = container.querySelector("textarea") as Element;
fireEvent.keyPress(textArea, { key: "Enter", code: "Enter", charCode: 13, shiftKey: true });
fireEvent.keyDown(textArea, { key: "Enter", code: "Enter", charCode: 13, shiftKey: true });

expect(fetchAndStoreNewSessionSpy).not.toHaveBeenCalled();
});
Expand Down
6 changes: 4 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { ConfigState } from "./store/definitions";
import { initLogger } from "./logger";

const defaultConfig: ConfigState = {
serverUrl: "http://localhost:3001",
deploymentKey: "",
region: "",
theme: {
isLight: true
},
Expand Down Expand Up @@ -38,7 +39,8 @@ const defaultConfig: ConfigState = {

const initWebchat = async (config: ConfigState) => {
const mergedConfig = merge({}, defaultConfig, config);
sessionDataHandler.setEndpoint(mergedConfig.serverUrl);
sessionDataHandler.setDeploymentKey(mergedConfig.deploymentKey);
sessionDataHandler.setRegion(mergedConfig.region);
store.dispatch(initConfig(mergedConfig));
initLogger();
const rootElement = document.getElementById("twilio-webchat-widget-root");
Expand Down
32 changes: 25 additions & 7 deletions src/sessionDataHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ 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 = "";
let _region = "";
let _deploymentKey = "";

type SessionDataStorage = Token & {
loginTimestamp: number | null;
};

export async function contactBackend<T>(endpointRoute: string, body: Record<string, unknown> = {}): Promise<T> {
AnudeepChPaul marked this conversation as resolved.
Show resolved Hide resolved
const _endpoint = `https://flex-api${buildRegionalHost(_region)}.twilio.com/v2`;
const securityHeaders = await generateSecurityHeaders();
const response = await fetch(_endpoint + endpointRoute, {
method: "POST",
Expand Down Expand Up @@ -53,12 +56,20 @@ function getStoredSessionData() {
}

export const sessionDataHandler = {
setEndpoint(endpoint: string = "") {
_endpoint = endpoint;
setRegion(region: string = "") {
_region = region;
},

getEndpoint() {
return _endpoint;
getRegion(): string {
return _region;
},

setDeploymentKey(key: string = "") {
ashishkumarTWLO marked this conversation as resolved.
Show resolved Hide resolved
_deploymentKey = key;
},

getDeploymentKey(): string {
return _deploymentKey;
},

tryResumeExistingSession(): Token | null {
Expand Down Expand Up @@ -95,7 +106,9 @@ export const sessionDataHandler = {
let newTokenData: Token;

try {
newTokenData = await contactBackend<Token>("/refreshToken", {
newTokenData = await contactBackend<Token>("/Webchat/Tokens/Refresh", {
// eslint-disable-next-line camelcase
AnudeepChPaul marked this conversation as resolved.
Show resolved Hide resolved
deployment_key: _deploymentKey,
token: storedTokenData.token
});
} catch (e) {
Expand All @@ -119,7 +132,12 @@ export const sessionDataHandler = {
let newTokenData;

try {
newTokenData = await contactBackend<Token>("/initWebchat", { formData });
newTokenData = await contactBackend<Token>("/Webchat/Init", {
// eslint-disable-next-line camelcase
deployment_key: _deploymentKey,
customerFriendlyName: formData?.customerFriendlyName || "Customer",
preEngagementData: formData
AnudeepChPaul marked this conversation as resolved.
Show resolved Hide resolved
});
} catch (e) {
throw Error("No results from server");
}
Expand Down
3 changes: 2 additions & 1 deletion src/store/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ export type SessionState = {
};

export type ConfigState = {
serverUrl?: string;
deploymentKey?: string;
region?: string;
theme?: {
isLight?: boolean;
overrides?: Partial<GenericThemeShape>;
Expand Down
14 changes: 14 additions & 0 deletions src/utils/regionUtil.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { buildRegionalHost } from "./regionUtil";

describe("buildRegionalHost(region)", () => {
it("builds correct region for various values", () => {
ashishkumarTWLO marked this conversation as resolved.
Show resolved Hide resolved
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");
});
});
14 changes: 14 additions & 0 deletions src/utils/regionUtil.ts
Original file line number Diff line number Diff line change
@@ -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}`;
}
}