Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion aselo-webchat-react-app/configSrc/as/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
"alwaysOpen": false,
"helplineCode": "as",
"enableRecaptcha": true,
"captureIp": true
"captureIp": true,
"contactIdentifierField": "ip"
}
9 changes: 5 additions & 4 deletions aselo-webchat-react-app/src/components/ConversationEnded.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { changeEngagementPhase, updatePreEngagementData } from '../store/actions
import { EngagementPhase } from '../store/definitions';
import { containerStyles, textStyles, titleStyles } from './styles/ConversationEnded.styles';
import { useClearParticipantNameMap } from '../hooks/useClearParticipantNameMap';
import LocalizedTemplate from '../localization/LocalizedTemplate';

export const ConversationEnded = () => {
const dispatch = useDispatch();
Expand All @@ -39,13 +40,13 @@ export const ConversationEnded = () => {
return (
<Box {...containerStyles}>
<Text as="h3" {...titleStyles}>
Thanks for chatting with us!
<LocalizedTemplate code="MessagePhase-ConversationEnded-Heading" />
</Text>
<Text as="p" {...textStyles}>
If you have any more questions, feel free to reach out again.
<LocalizedTemplate code="MessagePhase-ConversationEnded-Detail" />
</Text>
<Button variant="primary" data-test="start-new-chat-button" onClick={handleStartNewChat}>
Start new chat
<Button variant="primary" data-testid="start-new-chat-button" onClick={handleStartNewChat}>
<LocalizedTemplate code="MessagePhase-ConversationEnded-ButtonText" />
</Button>
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/

// eslint-disable-next-line import/order
import { resetMockRedux } from '../../__mocks__/redux/mockRedux';

// eslint-disable-next-line import/order
import { render, fireEvent } from '@testing-library/react';

import '@testing-library/jest-dom';
import { useSelector } from 'react-redux';

Expand All @@ -24,12 +29,6 @@ import { sessionDataHandler } from '../../sessionDataHandler';
import { EngagementPhase } from '../../store/definitions';
import WebChatLogger from '../../logger';

jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useDispatch: () => jest.fn(),
useSelector: jest.fn(),
}));

jest.mock('../../sessionDataHandler', () => ({
sessionDataHandler: {
clear: jest.fn(),
Expand Down Expand Up @@ -97,7 +96,7 @@ const defaultState = {
};

describe('Conversation Ended', () => {
const newChatButtonText = 'Start new chat';
const newChatButtonTestId = 'start-new-chat-button';

beforeAll(() => {
Object.defineProperty(window, 'Twilio', {
Expand All @@ -111,6 +110,7 @@ describe('Conversation Ended', () => {

beforeEach(() => {
(useSelector as jest.Mock).mockImplementation((callback: any) => callback(defaultState));
resetMockRedux({});
});

afterEach(() => {
Expand All @@ -124,17 +124,17 @@ describe('Conversation Ended', () => {
});

it('renders the new chat button', () => {
const { queryByText } = render(<ConversationEnded />);
const newChatButton = queryByText(newChatButtonText);
const { queryByTestId } = render(<ConversationEnded />);
const newChatButton = queryByTestId(newChatButtonTestId);

expect(newChatButton).toBeInTheDocument();
});

it('clears session data on new chat button click', () => {
const clearSessionDataSpy = jest.spyOn(sessionDataHandler, 'clear');

const { queryByText } = render(<ConversationEnded />);
const newChatButton = queryByText(newChatButtonText) as Element;
const { queryByTestId } = render(<ConversationEnded />);
const newChatButton = queryByTestId(newChatButtonTestId) as Element;

fireEvent.click(newChatButton);

Expand All @@ -144,8 +144,8 @@ describe('Conversation Ended', () => {
it('changes engagement phase to engagement form on new chat button click', () => {
const changeEngagementPhaseSpy = jest.spyOn(genericActions, 'changeEngagementPhase');

const { queryByText } = render(<ConversationEnded />);
const newChatButton = queryByText(newChatButtonText) as Element;
const { queryByTestId } = render(<ConversationEnded />);
const newChatButton = queryByTestId(newChatButtonTestId) as Element;
fireEvent.click(newChatButton);

expect(changeEngagementPhaseSpy).toHaveBeenCalledWith({ phase: EngagementPhase.PreEngagementForm });
Expand All @@ -154,8 +154,8 @@ describe('Conversation Ended', () => {
it('resets pre-engagement data on new chat button click', () => {
const updatePreEngagementDataSpy = jest.spyOn(genericActions, 'updatePreEngagementData');

const { queryByText } = render(<ConversationEnded />);
const newChatButton = queryByText(newChatButtonText) as Element;
const { queryByTestId } = render(<ConversationEnded />);
const newChatButton = queryByTestId(newChatButtonTestId) as Element;
fireEvent.click(newChatButton);

expect(updatePreEngagementDataSpy).toHaveBeenCalledWith({});
Expand Down
6 changes: 5 additions & 1 deletion aselo-webchat-react-app/src/sessionDataHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,16 @@ class SessionDataHandler {

try {
const { config } = store.getState();
const preEngagementData = {
...formData,
...(config.contactIdentifierField ? { contactIdentifier: formData[config.contactIdentifierField] } : {}),
};
const payload: InitWebchatAPIPayload = {
DeploymentKey: this.getDeploymentKey(),
CustomerFriendlyName:
(formData?.friendlyName as string) ||
localizeKey(config.translations[config.currentLocale ?? config.defaultLocale])(CUSTOMER_DEFAULT_NAME_KEY),
PreEngagementData: JSON.stringify(formData),
PreEngagementData: JSON.stringify(preEngagementData),
};

if (customerIdentity) {
Expand Down
1 change: 1 addition & 0 deletions aselo-webchat-react-app/src/store/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export type ConfigState = {
recaptchaSiteKey?: string;
captureIp?: boolean;
ipLookupServiceApiKey?: string;
contactIdentifierField?: string;
};

export type Notification = {
Expand Down
5 changes: 4 additions & 1 deletion aselo-webchat-react-app/translationsSrc/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
"Header-TitleBar-Title": "Live Chat",
"MessagePhase-MessageList-ChatStartMessage": "Chat Started",
"MessagePhase-MessageBubble-OtherParticipantMessageSenderName": "Counsellor",
"MessagePhase-MessageBubble-OwnMessageSenderName": "You"
"MessagePhase-MessageBubble-OwnMessageSenderName": "You",
"MessagePhase-ConversationEnded-Heading": "Thanks for chatting with us!",
"MessagePhase-ConversationEnded-Detail": "If you have any more questions, feel free to reach out again.",
"MessagePhase-ConversationEnded-ButtonText": "Start new chat"
}
2 changes: 1 addition & 1 deletion lambdas/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module.exports = {
'@typescript-eslint/quotes': 'off',
'import/prefer-default-export': 'off',
// This rule gives false positives in CI for some reason.
// When getSsmParameter was moved to a separate library, calling it with 'return await getSssmParameter'
// When getSsmParameter was moved to a separate library, calling it with 'return await getSsmParameter'
'@typescript-eslint/return-await': 'warn',
},
settings: {
Expand Down
16 changes: 14 additions & 2 deletions lambdas/account-scoped/src/hrm/sanitizeIdentifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export type TriggerEvent = {
type ConversationTrigger = {
conversation: {
Author: string;
ChannelAttributes: ChannelAttributes;
};
};

Expand Down Expand Up @@ -147,6 +148,17 @@ export const sanitizeIdentifierFromTrigger = ({
}

if (isConversationTrigger(trigger) && channelType) {
// webchat is a special case since it does not only depends on channel but in the task attributes too
if (trigger.conversation.ChannelAttributes.channel_type === 'chat') {
const identifier = getContactValueFromWebchat({
preEngagementData: trigger.conversation.ChannelAttributes.pre_engagement_data,
});

console.debug(
`Found Aselo Webchat identifier ${identifier} from contactIdentifier field in preEngagement data`,
);
return newOk(identifier);
}
if (!channelTransformations[channelType] || !channelType) {
console.error(`Channel type ${channelType} is not supported`);
return newErr({
Expand Down Expand Up @@ -178,7 +190,7 @@ export const sanitizeIdentifierFromTask = ({
channelType,
taskAttributes,
}: {
channelType: HrmContact['channel'];
channelType: HrmContact['channel'] | 'chat';
taskAttributes: any;
}): Result<
UnsupportedChannelResultPayload | InvalidTaskAttributesResultPayload | Error,
Expand All @@ -189,7 +201,7 @@ export const sanitizeIdentifierFromTask = ({
return newOk('');
}

if (channelType === 'web') {
if (channelType === 'web' || channelType === 'chat') {
const identifier = getContactValueFromWebchat({
preEngagementData: taskAttributes.preEngagementData,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ describe('getProfileFlagsForIdentifier endpoint', () => {
trigger: {
conversation: {
Author: 'telegram:bobs-address',
ChannelAttributes: {
pre_engagement_data: {
contactIdentifier: '1.2.3.4',
},
from: 'bob',
channel_type: 'telegram',
},
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const newConversationEvent = (channelType: string, from: string): TriggerEvent =
trigger: {
conversation: {
Author: from,
ChannelAttributes: { from: '', channel_type: 'telegram' },
},
},
channelType,
Expand Down
40 changes: 32 additions & 8 deletions lambdas/account-scoped/tests/unit/hrm/sanitizeIdentifier.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,10 @@ describe('sanitizeIdentifierFromTrigger', () => {
channelType: 'sms',
description: 'conversation - sanitizes conversation "Author"',
trigger: {
conversation: { Author: '+123 456-789' },
conversation: {
Author: '+123 456-789',
ChannelAttributes: { channel_type: 'sms', from: '+123 456-789' },
},
},
expected: '+123456789',
},
Expand All @@ -318,7 +321,10 @@ describe('sanitizeIdentifierFromTrigger', () => {
channelType: 'whatsapp',
description: 'conversation - sanitizes conversation "Author"',
trigger: {
conversation: { Author: 'whatsapp:+123456789' },
conversation: {
Author: 'whatsapp:+123456789',
ChannelAttributes: { from: '', channel_type: 'whatsapp' },
},
},
expected: '+123456789',
},
Expand All @@ -336,7 +342,10 @@ describe('sanitizeIdentifierFromTrigger', () => {
channelType: 'modica',
description: 'conversation - sanitizes conversation "Author"',
trigger: {
conversation: { Author: 'modica:+123456789' },
conversation: {
Author: 'modica:+123456789',
ChannelAttributes: { from: '', channel_type: 'modica' },
},
},
expected: '+123456789',
},
Expand All @@ -354,7 +363,10 @@ describe('sanitizeIdentifierFromTrigger', () => {
channelType: 'messenger',
description: 'conversation - sanitizes conversation "Author"',
trigger: {
conversation: { Author: 'messenger:123456789' },
conversation: {
Author: 'messenger:123456789',
ChannelAttributes: { from: '', channel_type: 'messenger' },
},
},
expected: '123456789',
},
Expand All @@ -372,7 +384,10 @@ describe('sanitizeIdentifierFromTrigger', () => {
channelType: 'instagram',
description: 'conversation - sanitizes conversation "Author"',
trigger: {
conversation: { Author: 'instagram:123456789' },
conversation: {
Author: 'instagram:123456789',
ChannelAttributes: { channel_type: 'instagram', from: 'instagram:123456789' },
},
},
expected: '123456789',
},
Expand All @@ -390,7 +405,10 @@ describe('sanitizeIdentifierFromTrigger', () => {
channelType: 'line',
description: 'conversation - sanitizes conversation "Author"',
trigger: {
conversation: { Author: 'line:123456789' },
conversation: {
Author: 'line:123456789',
ChannelAttributes: { channel_type: 'line', from: 'line:123456789' },
},
},
expected: 'line:123456789',
},
Expand All @@ -408,7 +426,10 @@ describe('sanitizeIdentifierFromTrigger', () => {
channelType: 'telegram',
description: 'conversation - sanitizes conversation "Author"',
trigger: {
conversation: { Author: 'telegram:123456789' },
conversation: {
Author: 'telegram:123456789',
ChannelAttributes: { from: '', channel_type: 'telegram' },
},
},
expected: '123456789',
},
Expand Down Expand Up @@ -458,7 +479,10 @@ describe('sanitizeIdentifierFromTrigger', () => {
channelType: 'web',
description: 'conversation - returns unmodified',
trigger: {
conversation: { Author: 'this!' },
conversation: {
Author: 'this!',
ChannelAttributes: { channel_type: 'web', from: '0.0.0.0' },
},
},
expected: 'this!',
expectErr: false,
Expand Down
Loading