diff --git a/aselo-webchat-react-app/package-lock.json b/aselo-webchat-react-app/package-lock.json index 55f1df8059..f510682242 100644 --- a/aselo-webchat-react-app/package-lock.json +++ b/aselo-webchat-react-app/package-lock.json @@ -107,12 +107,12 @@ "eslint-import-resolver-typescript": "^2.4.0", "eslint-plugin-import": "^2.22.0", "eslint-plugin-prettier": "^3.1.4", - "jest": "^27.4.5", + "jest": "^30.3.0", "jest-config": "^28.1.3", "jest-each": "^28.1.1", "jest-junit": "^16.0.0", "prettier": "^2.3.2", - "ts-jest": "^27.1.2", + "ts-jest": "^29.4.6", "ts-node": "^10.1.0", "typescript": "^4.3.5" } @@ -31416,6 +31416,23 @@ } } }, + "node_modules/tailwindcss/node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/tapable": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", diff --git a/aselo-webchat-react-app/package.json b/aselo-webchat-react-app/package.json index e8ced9a5d0..9682ab57ec 100644 --- a/aselo-webchat-react-app/package.json +++ b/aselo-webchat-react-app/package.json @@ -84,7 +84,7 @@ "scripts": { "preinstall": "cd ../lambdas/packages/hrm-form-definitions && npm ci && npm run build && cd ../hrm-types && npm ci && npm run build", "start": "react-app-rewired start", - "start:as_dev": "cross-env REACT_APP_CONFIG_URL='http://localhost:9090/as/development.json' run-p dev:merge-configs dev:local-config-server start", + "start:as_dev": "cross-env REACT_APP_CONFIG_URL='http://localhost:9090/as/development.json' REACT_APP_FORM_DEFINITIONS_BASE_URL='http://localhost:8091' run-p dev:merge-configs dev:local-config-server dev:local-form-definition-server start", "build": "react-app-rewired build", "lint": "eslint --ext js --ext jsx --ext ts --ext tsx src/", "lint:fix": "npm run lint -- --fix", @@ -97,7 +97,8 @@ "eject": "react-app-rewired eject", "test:e2e": "cypress open", "dev:merge-configs": "npm run mergeConfigs development as", - "dev:local-config-server": "npx http-server ./mergedConfigs -p 9090 --cors -c-1" + "dev:local-config-server": "npx http-server ./mergedConfigs -p 9090 --cors -c-1", + "dev:local-form-definition-server": "npx http-server ../lambdas/packages/hrm-form-definitions/form-definitions -p 8091 --cors -c-1" }, "browserslist": [ ">0.2%", diff --git a/aselo-webchat-react-app/src/components/MessageBubble.tsx b/aselo-webchat-react-app/src/components/MessageBubble.tsx index c8ac40cb1e..587bc383bb 100644 --- a/aselo-webchat-react-app/src/components/MessageBubble.tsx +++ b/aselo-webchat-react-app/src/components/MessageBubble.tsx @@ -37,6 +37,8 @@ import { readStatusStyles, bubbleAndAvatarContainerStyles, } from './styles/MessageBubble.styles'; +import { selectCurrentTranslations } from '../store/config.reducer'; +import { localizeKey } from '../localization/localizeKey'; const doubleDigit = (number: number) => `${number < 10 ? 0 : ''}${number}`; @@ -56,12 +58,12 @@ export const MessageBubble = ({ }) => { const [read, setRead] = useState(false); const [isMouseDown, setIsMouseDown] = useState(false); - const { conversationsClient, participants, fileAttachmentConfig, participantNames } = useSelector( + const { conversationsClient, participants, fileAttachmentConfig, currentTranslations } = useSelector( (state: AppState) => ({ conversationsClient: state.chat.conversationsClient, participants: state.chat.participants, fileAttachmentConfig: state.config.fileAttachment, - participantNames: state.chat.participantNames, + currentTranslations: selectCurrentTranslations(state), }), ); const messageRef = useRef(null); @@ -129,7 +131,15 @@ export const MessageBubble = ({ }; // const author = users?.find((u) => u.identity === message.author)?.friendlyName || message.author; - const name = participantNames ? participantNames[message.participantSid] : ''; + let name: string; + if (belongsToCurrentUser) { + name = 'MessagePhase-MessageBubble-OwnMessageSenderName'; + } else if (message.participantSid) { + name = 'MessagePhase-MessageBubble-OtherParticipantMessageSenderName'; + } else { + name = message.author || ''; + } + const translatedName = localizeKey(currentTranslations)(name); return ( - - {name} + + {translatedName} - {belongsToCurrentUser ? 'You sent at' : `${name} sent at`} + {`${translatedName} sent at`} {`${doubleDigit(message.dateCreated.getHours())}:${doubleDigit(message.dateCreated.getMinutes())}`} diff --git a/aselo-webchat-react-app/src/components/__tests__/MessageBubble.test.tsx b/aselo-webchat-react-app/src/components/__tests__/MessageBubble.test.tsx index 649e990005..fe54a4c384 100644 --- a/aselo-webchat-react-app/src/components/__tests__/MessageBubble.test.tsx +++ b/aselo-webchat-react-app/src/components/__tests__/MessageBubble.test.tsx @@ -37,7 +37,16 @@ const user2 = { sid: '62563cwqdc213cec23', }; const defaultState = { - config: { fileAttachment: fileAttachmentConfig }, + config: { + fileAttachment: fileAttachmentConfig, + translations: { + 'en-US': { + 'MessagePhase-MessageBubble-OwnMessageSenderName': 'You', + 'MessagePhase-MessageBubble-OtherParticipantMessageSenderName': 'Counsellor', + }, + }, + defaultLocale: 'en-US', + }, chat: { conversationsClient: { user: user1 }, participants: [{ identity: user1.identity }, { identity: user2.identity }], @@ -115,7 +124,7 @@ describe('Message Bubble', () => { />, ); - expect(queryByText(user1.friendlyName)).toBeInTheDocument(); + expect(queryByText('You')).toBeInTheDocument(); }); it('renders the message body', () => { @@ -172,7 +181,7 @@ describe('Message Bubble', () => { />, ); - expect(getByText(`${user2.friendlyName} sent at`)).toBeInTheDocument(); + expect(getByText('Counsellor sent at')).toBeInTheDocument(); }); it("renders 'is read' and icon when message read by other participant", () => { diff --git a/aselo-webchat-react-app/src/services/configService.ts b/aselo-webchat-react-app/src/services/configService.ts index 3dc62d0eb4..d360386bab 100644 --- a/aselo-webchat-react-app/src/services/configService.ts +++ b/aselo-webchat-react-app/src/services/configService.ts @@ -25,7 +25,10 @@ export const getDefinitionVersion = async ({ }): Promise<{ preEngagementForm: PreEngagementForm; }> => { - const formDefinitionsBaseUrl = buildFormDefinitionsBaseUrlGetter({ environment })(definitionVersionId); + const formDefinitionsBaseUrl = buildFormDefinitionsBaseUrlGetter({ + environment, + configuredFormDefinitionsBaseUrl: process.env.REACT_APP_FORM_DEFINITIONS_BASE_URL, + })(definitionVersionId); // eslint-disable-next-line const definition = await loadWebchatDefinition(formDefinitionsBaseUrl); return definition; diff --git a/aselo-webchat-react-app/src/sessionDataHandler.ts b/aselo-webchat-react-app/src/sessionDataHandler.ts index 257d3543c1..e7c4297c49 100644 --- a/aselo-webchat-react-app/src/sessionDataHandler.ts +++ b/aselo-webchat-react-app/src/sessionDataHandler.ts @@ -19,9 +19,10 @@ import { LocalStorageUtil } from './utils/LocalStorage'; import { generateMixPanelHeaders, generateSecurityHeaders } from './utils/generateHeaders'; import { ConfigState } from './store/definitions'; import { store } from './store/store'; +import { localizeKey } from './localization/localizeKey'; export const LOCALSTORAGE_SESSION_ITEM_ID = 'TWILIO_WEBCHAT_WIDGET'; -const CUSTOMER_DEFAULT_NAME = 'Customer'; +const CUSTOMER_DEFAULT_NAME_KEY = 'Conversation-Participants-CustomerDefaultName'; type SessionDataStorage = TokenResponse & { loginTimestamp: string | null; @@ -189,19 +190,25 @@ class SessionDataHandler { }); try { + const { config } = store.getState(); const payload: InitWebchatAPIPayload = { DeploymentKey: this.getDeploymentKey(), - CustomerFriendlyName: (formData?.friendlyName as string) || CUSTOMER_DEFAULT_NAME, + CustomerFriendlyName: (() => { + const localizedName = localizeKey(config.translations[config.currentLocale ?? config.defaultLocale])( + CUSTOMER_DEFAULT_NAME_KEY, + ); + return ( + (formData?.friendlyName as string) || + (localizedName === CUSTOMER_DEFAULT_NAME_KEY ? 'Anonymous' : localizedName) + ); + })(), PreEngagementData: JSON.stringify(formData), }; if (customerIdentity) { payload.Identity = customerIdentity; } - newTokenData = await contactBackend(store.getState().config)( - '/webchatAuthentication/initWebchat', - payload, - ); + newTokenData = await contactBackend(config)('/webchatAuthentication/initWebchat', payload); } catch (e) { logger.error('No results from server'); throw Error('No results from server'); diff --git a/aselo-webchat-react-app/translationsSrc/en.json b/aselo-webchat-react-app/translationsSrc/en.json index 9df5323256..14b6c5240b 100644 --- a/aselo-webchat-react-app/translationsSrc/en.json +++ b/aselo-webchat-react-app/translationsSrc/en.json @@ -1,9 +1,12 @@ { + "Conversation-Participants-CustomerDefaultName": "Anonymous", "Header-CloseChatButtons-EndChatButtonLabel": "End Chat", "Header-CloseChatButtons-EndChatConfirmDialogMessageFromChat": "End the current chat? Your messages will be lost.", "Header-CloseChatButtons-EndChatConfirmDialogMessageFromPreEngagement": "Abandon the current chat?", "Header-CloseChatButtons-QuickExitButtonLabel": "Quick Exit", "Header-CloseChatButtons-QuickExitDescription": "Need to leave immediately?", "Header-TitleBar-Title": "Live Chat", - "MessagePhase-MessageList-ChatStartMessage": "Chat Started" + "MessagePhase-MessageList-ChatStartMessage": "Chat Started", + "MessagePhase-MessageBubble-OtherParticipantMessageSenderName": "Counsellor", + "MessagePhase-MessageBubble-OwnMessageSenderName": "You" } \ No newline at end of file diff --git a/lambdas/account-scoped/src/conversation/createConversation.ts b/lambdas/account-scoped/src/conversation/createConversation.ts index 2a4ddc5989..0a584aaa69 100644 --- a/lambdas/account-scoped/src/conversation/createConversation.ts +++ b/lambdas/account-scoped/src/conversation/createConversation.ts @@ -17,6 +17,7 @@ import { Twilio } from 'twilio'; import { ConversationSID } from '@tech-matters/twilio-types'; import { AseloCustomChannel } from '../customChannels/aseloCustomChannels'; +import { newErr, newOk, Result } from '../Result'; const CONVERSATION_CLOSE_TIMEOUT = 'P3D'; // ISO 8601 duration format https://en.wikipedia.org/wiki/ISO_8601 export type CreateFlexConversationParams = { @@ -47,19 +48,32 @@ export const createConversation = async ( additionalConversationAttributes, testSessionId, }: CreateFlexConversationParams, -): Promise<{ conversationSid: ConversationSID; error?: Error }> => { +): Promise< + Result< + { conversationSid?: ConversationSID; cause: Error }, + { conversationSid: ConversationSID } + > +> => { if (testSessionId) { console.info( 'testSessionId specified. All outgoing messages will be sent to the test API.', ); } - const conversationInstance = await client.conversations.v1.conversations.create({ - xTwilioWebhookEnabled: 'true', - friendlyName: conversationFriendlyName, - uniqueName: `${channelType}/${uniqueUserName}/${Date.now()}`, - }); - const conversationSid = conversationInstance.sid as ConversationSID; + let conversationSid: ConversationSID; + try { + const conversationInstance = await client.conversations.v1.conversations.create({ + xTwilioWebhookEnabled: 'true', + friendlyName: conversationFriendlyName, + uniqueName: `${channelType}/${uniqueUserName}/${Date.now()}`, + }); + conversationSid = conversationInstance.sid as ConversationSID; + } catch (err) { + return newErr({ + message: `Create conversation failed: ${(err as Error)?.message}`, + error: { cause: err as Error }, + }); + } try { const conversationContext = @@ -67,6 +81,9 @@ export const createConversation = async ( await conversationContext.participants.create({ identity: uniqueUserName, }); + await client.conversations.v1.users + .get(uniqueUserName) + .update({ friendlyName: senderScreenName }); const channelAttributes = JSON.parse((await conversationContext.fetch()).attributes); console.debug('channelAttributes prior to update', channelAttributes); @@ -91,7 +108,6 @@ export const createConversation = async ( 'configuration.filters': ['onMessageAdded'], }); if (onMessageAddedWebhookUrl) { - /* const onMessageAdded = */ await conversationContext.webhooks.create({ target: 'webhook', 'configuration.method': 'POST', @@ -100,8 +116,11 @@ export const createConversation = async ( }); } } catch (err) { - return { conversationSid, error: err as Error }; + return newErr({ + message: `Create conversation failed: ${(err as Error)?.message}`, + error: { conversationSid, cause: err as Error }, + }); } - return { conversationSid }; + return newOk({ conversationSid }); }; diff --git a/lambdas/account-scoped/src/customChannels/customChannelToFlex.ts b/lambdas/account-scoped/src/customChannels/customChannelToFlex.ts index 7abfbd0ea5..c07b0e7b4a 100644 --- a/lambdas/account-scoped/src/customChannels/customChannelToFlex.ts +++ b/lambdas/account-scoped/src/customChannels/customChannelToFlex.ts @@ -21,6 +21,7 @@ import { createConversation, CreateFlexConversationParams, } from '../conversation/createConversation'; +import { isErr } from '../Result'; export const findExistingConversation = async ( client: Twilio, @@ -75,7 +76,7 @@ export const removeConversation = async ( }: { conversationSid: ConversationSID; }, -) => client.conversations.v1.conversations(conversationSid).remove(); +) => client.conversations.v1.conversations.get(conversationSid).remove(); export { AseloCustomChannel, isAseloCustomChannel } from './aseloCustomChannels'; @@ -125,26 +126,28 @@ export const sendConversationMessageToFlex = async ( let conversationSid = await findExistingConversation(client, uniqueUserName); if (!conversationSid) { - const { conversationSid: newConversationSid, error } = await createConversation( - client, - { - studioFlowSid, - channelType, - twilioNumber, - uniqueUserName, - senderScreenName, - onMessageAddedWebhookUrl, - conversationFriendlyName, - testSessionId, - }, - ); + const createConversationResult = await createConversation(client, { + studioFlowSid, + channelType, + twilioNumber, + uniqueUserName, + senderScreenName, + onMessageAddedWebhookUrl, + conversationFriendlyName, + testSessionId, + }); - if (error) { - await removeConversation(client, { - conversationSid: newConversationSid, - }); - throw error; + if (isErr(createConversationResult)) { + const { conversationSid: newConversationSid, cause } = + createConversationResult.error; + if (newConversationSid) { + await removeConversation(client, { + conversationSid: newConversationSid, + }); + } + throw cause; } + const { conversationSid: newConversationSid } = createConversationResult.data; conversationSid = newConversationSid; } diff --git a/lambdas/account-scoped/src/customChannels/instagram/instagramToFlex.ts b/lambdas/account-scoped/src/customChannels/instagram/instagramToFlex.ts index 5231a99599..c9c5a7e397 100644 --- a/lambdas/account-scoped/src/customChannels/instagram/instagramToFlex.ts +++ b/lambdas/account-scoped/src/customChannels/instagram/instagramToFlex.ts @@ -120,7 +120,7 @@ export const instagramToFlexHandler: AccountScopedHandler = async ( const channelType = AseloCustomChannel.Instagram; const chatFriendlyName = `${channelType}:${senderExternalId}`; const uniqueUserName = `${channelType}:${senderExternalId}`; - const senderScreenName = uniqueUserName; // TODO: see if we can use ig handle somehow + const senderScreenName = senderExternalId; // TODO: see if we can use ig handle somehow const messageAttributes = JSON.stringify({ messageExternalId }); const onMessageSentWebhookUrl = `${process.env.WEBHOOK_BASE_URL}/lambda/twilio/account-scoped/${accountSid}/customChannels/instagram/flexToInstagram?recipientId=${senderExternalId}`; const studioFlowSid = await getChannelStudioFlowSid( diff --git a/lambdas/account-scoped/src/customChannels/line/lineToFlex.ts b/lambdas/account-scoped/src/customChannels/line/lineToFlex.ts index a4cdc06871..37aaa6d5b9 100644 --- a/lambdas/account-scoped/src/customChannels/line/lineToFlex.ts +++ b/lambdas/account-scoped/src/customChannels/line/lineToFlex.ts @@ -136,7 +136,7 @@ export const lineToFlexHandler: AccountScopedHandler = async ( const senderExternalId = messageEvent.source.userId; // The child ID on Line const chatFriendlyName = `${channelType}:${senderExternalId}`; const uniqueUserName = `${channelType}:${senderExternalId}`; - const senderScreenName = 'child'; + const senderScreenName = senderExternalId; const onMessageSentWebhookUrl = `${process.env.WEBHOOK_BASE_URL}/lambda/twilio/account-scoped/${accountSid}/customChannels/line/flexToLine?recipientId=${senderExternalId}`; console.debug( 'LineToFlex: sending message from', diff --git a/lambdas/account-scoped/src/customChannels/modica/modicaToFlex.ts b/lambdas/account-scoped/src/customChannels/modica/modicaToFlex.ts index 6721656caf..8db9599512 100644 --- a/lambdas/account-scoped/src/customChannels/modica/modicaToFlex.ts +++ b/lambdas/account-scoped/src/customChannels/modica/modicaToFlex.ts @@ -46,7 +46,7 @@ export const modicaToFlexHandler: AccountScopedHandler = async ( const senderExternalId = source; // The child phone number const chatFriendlyName = senderExternalId; const uniqueUserName = `${channelType}:${senderExternalId}`; - const senderScreenName = 'child'; + const senderScreenName = senderExternalId; const onMessageSentWebhookUrl = `${process.env.WEBHOOK_BASE_URL}/lambda/twilio/account-scoped/${accountSid}/customChannels/modica/flexToModica?recipientId=${senderExternalId}`; const studioFlowSid = await getChannelStudioFlowSid( accountSid, diff --git a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts index a6860ddc9e..49bd391d86 100644 --- a/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts +++ b/lambdas/account-scoped/src/webchatAuthentication/initWebchat.ts @@ -42,7 +42,7 @@ const contactWebchatOrchestrator = async ({ console.info(`Creating new conversation via the API with sender ID: ${senderId}`); const client = await getTwilioClient(accountSid); - const { conversationSid, error } = await createConversation(client, { + const result = await createConversation(client, { channelType: 'web', conversationFriendlyName: customerFriendlyName, senderScreenName: customerFriendlyName, @@ -55,16 +55,22 @@ const contactWebchatOrchestrator = async ({ from: customerFriendlyName, }, }); - if (error) { - console.error('Error creating web conversation', accountSid, error); + if (isErr(result)) { + const { conversationSid, cause } = result.error; + console.error( + `Error creating web conversation ${conversationSid}`, + accountSid, + cause, + ); return newErr({ - message: error.message, + message: result.message, error: { statusCode: 500, - cause: error, + cause, }, }); } + const { conversationSid } = result.data; console.info( `Created new conversation ${conversationSid} via the API with sender ID: ${senderId}`, ); diff --git a/lambdas/account-scoped/tests/unit/customChannels/line/lineToFlex.test.ts b/lambdas/account-scoped/tests/unit/customChannels/line/lineToFlex.test.ts index 43e8dd9f6f..dc01f96555 100644 --- a/lambdas/account-scoped/tests/unit/customChannels/line/lineToFlex.test.ts +++ b/lambdas/account-scoped/tests/unit/customChannels/line/lineToFlex.test.ts @@ -117,6 +117,13 @@ describe('LineToFlex', () => { participantConversations: { list: () => [{ conversationState: 'active' }], }, + users: { + get: (identifier: string) => { + return { + update: jest.fn().mockResolvedValue({ identifier }), + }; + }, + }, }, }, }; diff --git a/lambdas/account-scoped/tests/unit/customChannels/modica/modicaToFlex.test.ts b/lambdas/account-scoped/tests/unit/customChannels/modica/modicaToFlex.test.ts index d7bb3c8c5e..363efdbafd 100644 --- a/lambdas/account-scoped/tests/unit/customChannels/modica/modicaToFlex.test.ts +++ b/lambdas/account-scoped/tests/unit/customChannels/modica/modicaToFlex.test.ts @@ -72,6 +72,7 @@ const validBody = ({ }); describe('ModicaToFlex', () => { + const userUpdate = jest.fn(); beforeEach(() => { mockTwilioClient = { conversations: { @@ -89,6 +90,13 @@ describe('ModicaToFlex', () => { participantConversations: { list: () => [{ conversationState: 'active' }], }, + users: { + get: (identifier: string) => { + return { + update: userUpdate.mockResolvedValue({ identifier }), + }; + }, + }, }, }, }; @@ -116,7 +124,6 @@ describe('ModicaToFlex', () => { { body: validBody() } as HttpRequest, ACCOUNT_SID, ); - expect(result).toBeDefined(); expect(isOk(result)).toBe(true); }); diff --git a/lambdas/account-scoped/tests/unit/customChannels/telegram/telegramToFlex.test.ts b/lambdas/account-scoped/tests/unit/customChannels/telegram/telegramToFlex.test.ts index d8b3eac2b7..1076c4ed1b 100644 --- a/lambdas/account-scoped/tests/unit/customChannels/telegram/telegramToFlex.test.ts +++ b/lambdas/account-scoped/tests/unit/customChannels/telegram/telegramToFlex.test.ts @@ -103,6 +103,13 @@ describe('TelegramToFlex', () => { participantConversations: { list: () => [{ conversationState: 'active' }], }, + users: { + get: (identifier: string) => { + return { + update: jest.fn().mockResolvedValue({ identifier }), + }; + }, + }, }, }, }; diff --git a/lambdas/account-scoped/tests/unit/webchatAuthentication/initWebchat.test.ts b/lambdas/account-scoped/tests/unit/webchatAuthentication/initWebchat.test.ts index 5c449bf744..f983a01021 100644 --- a/lambdas/account-scoped/tests/unit/webchatAuthentication/initWebchat.test.ts +++ b/lambdas/account-scoped/tests/unit/webchatAuthentication/initWebchat.test.ts @@ -16,7 +16,7 @@ import { initWebchatHandler } from '../../../src/webchatAuthentication/initWebchat'; import { TEST_ACCOUNT_SID, TEST_CONVERSATION_SID } from '../../testTwilioValues'; -import { isErr, isOk } from '../../../src/Result'; +import { isErr, isOk, newErr, newOk } from '../../../src/Result'; jest.mock('@tech-matters/twilio-configuration', () => ({ getTwilioClient: jest.fn(), @@ -72,7 +72,9 @@ describe('initWebchatHandler', () => { jest.clearAllMocks(); mockGetTwilioClient.mockResolvedValue(mockTwilioClient); mockGetChannelStudioFlowSid.mockResolvedValue(TEST_STUDIO_FLOW_SID); - mockCreateConversation.mockResolvedValue({ conversationSid: TEST_CONVERSATION_SID }); + mockCreateConversation.mockResolvedValue( + newOk({ conversationSid: TEST_CONVERSATION_SID }), + ); mockCreateToken.mockResolvedValue(TEST_TOKEN); }); @@ -123,15 +125,17 @@ describe('initWebchatHandler', () => { } }); - it('returns an error result when createConversation throws', async () => { - mockCreateConversation.mockRejectedValue(new Error('Conversation creation failed')); + it('returns an error result when createConversation returns error result', async () => { + mockCreateConversation.mockResolvedValue( + newErr({ message: 'Boom', error: { cause: new Error('Shakalakka') } }), + ); const request = createMockRequest(); const result = await initWebchatHandler(request, TEST_ACCOUNT_SID); expect(isErr(result)).toBe(true); if (isErr(result)) { expect(result.error.statusCode).toBe(500); - expect(result.message).toBe('Conversation creation failed'); + expect(result.message).toBe('Boom'); } expect(mockCreateToken).not.toHaveBeenCalled(); }); diff --git a/lambdas/packages/hrm-form-definitions/form-definitions/as/v1/webchat/PreEngagementForm.json b/lambdas/packages/hrm-form-definitions/form-definitions/as/v1/webchat/PreEngagementForm.json index 039c816f2d..97ba2a595e 100644 --- a/lambdas/packages/hrm-form-definitions/form-definitions/as/v1/webchat/PreEngagementForm.json +++ b/lambdas/packages/hrm-form-definitions/form-definitions/as/v1/webchat/PreEngagementForm.json @@ -2,6 +2,13 @@ "description": "PreEngagementDescription", "submitLabel": "LetsChat", "fields": [ + { + "type": "input", + "name": "friendlyName", + "label": "Nickname", + "placeholder": "GuestName", + "required": true + }, { "type": "input", "name": "firstName",