Skip to content

Commit

Permalink
Rz na add close button in head (#47)
Browse files Browse the repository at this point in the history
* Add tests and close button in the head of the chatbot plus option to be hidden through config;

---------

Co-authored-by: IlievaDayana <[email protected]>
Co-authored-by: Dayana Ilieva <[email protected]>
  • Loading branch information
3 people authored Dec 14, 2023
1 parent c33e03f commit 7435a27
Show file tree
Hide file tree
Showing 15 changed files with 2,099 additions and 1,947 deletions.
51 changes: 48 additions & 3 deletions __tests__/components/AppBase/index.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ describe('AppBase, chat-history event and execute properly', () => {
const { chat } = root.store.getState();
expect(localStorage.getItem(LINK_CLICKED_KEY)).toBeTruthy();
expect(document.querySelector).toHaveBeenCalledWith('#chatbot-container');
expect(nodeElem.remove).toHaveBeenCalled();
expect(chat.closed).toBeTruthy();
});

Expand Down Expand Up @@ -221,6 +220,53 @@ describe('AppBase, streaming events execute properly', () => {
});
});

describe('Close button closes chat', () => {
const href = 'https://example.com/?utm_chat=default';
const search = '?utm_chat=default';

beforeEach(async () => {
const mockLocation = {
href,
search,
};

Object.defineProperty(window, 'location', {
value: mockLocation,
writable: true,
enumerable: true,
});
await localSetup();
});

afterEach(localTearDown);

test('chat.closed is true after close button is clicked', async () => {
// Arrange
expect(window.location.search).toContain('?utm_chat=default');

const nodeElem = { remove: jest.fn() };
const querySelectorSpy = jest.spyOn(document, 'querySelector');
const ioCloseSpy = jest.spyOn(io.connect(), 'close');
spies.push(querySelectorSpy, ioCloseSpy);
querySelectorSpy.mockImplementation(() => nodeElem);

// Act
act(dispatchSocketChange);
const closeButton = root.container.querySelector('[data-e2e="chat-close-btn"]');
fireEvent.click(closeButton);

// Assert
setTimeout(() => {
const { chat } = root.store.getState();
expect(chat.closed).toBeTruthy();
expect(querySelectorSpy).toHaveBeenCalledWith('#chatbot-container');
expect(nodeElem.remove).toHaveBeenCalled();
expect(window.location.search).not.toContain(search);
expect(ioCloseSpy).toHaveBeenCalled();
}, 501);
});
});

function dispatchSocketChange(history = defaultHistory) {
serverSocket.emit('connect');
serverSocket.emit(events.chatHistory, { history, errors: [], region: 'frankfurt' });
Expand All @@ -236,12 +282,11 @@ function dispatchStreaming(chunks) {
async function localSetup() {
localStorage.setItem('__pd', JSON.stringify(pd));
spies.push(jest.spyOn(intent.core, 'emit'));

const intentOnSpy = jest.spyOn(intent.core, 'on');
spies.push(intentOnSpy);
intentOnSpy.mockReturnValue(() => true);
await waitFor(() => {
root = renderWithProviders(<AppBase config={ initialConfig } />);
root = renderWithProviders(<div id="chatbot-container"><AppBase config={ initialConfig } /></div>);
});
}

Expand Down
3,885 changes: 1,969 additions & 1,916 deletions dist/index.es.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.es.js.map

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions dist/index.umd.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.umd.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
</head>

<body class="tw--grid tw--w-full tw--h-screen">
<div id="root" class="tw--grid tw--self-stretch tw--justify-self-stretch"></div>
<div id="chatbot-container" class="tw--grid tw--self-stretch tw--justify-self-stretch"></div>
<script type="module" src="index.js"></script>
</body>

</html>
</html>
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line no-unused-expressions
!localStorage.getItem('__cid') && localStorage.setItem('__cid', id);

ReactBotClient({ root: document.querySelector('#root'), initialConfig: getChatConfig(id) });
ReactBotClient({ root: document.querySelector('#chatbot-container'), initialConfig: getChatConfig(id) });
// example implementation from the plugin user side
intent.core.on(intent.type.email, (data) => {
// MOCKERIES FOR TESTING PURPOSES
Expand Down
3 changes: 2 additions & 1 deletion src/chatMocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export const initialConfig = {
mealButton: 'Create your meal plan',
error: 'Oops something went wrong.',
tm505: 'Please enter valid email address',
}
},
closeVisible: true,
},
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/Button/variants.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const basic = /*tw*/ tv({

export const icon = /*tw*/ tv({
slots: {
base: 'tw--flex-1 tw--text-[inherit]',
base: 'tw--text-[inherit]',
},
variants: {
theme: {
Expand Down
46 changes: 44 additions & 2 deletions src/components/Layout/head.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,58 @@
import { useAppSelector } from '@/hooks';
import { useAppDispatch, useAppSelector } from '@/hooks';

import { Profile } from '@/components/Profile';
import { getConfig } from '@/store/slices/config';
import { IconBtn } from '@/components/Button';
import { customEvents } from '@/config/analytics';
import { track } from '@/services/tracking';
import { getMeta } from '@/store/slices/meta';
import { setClosed } from '@/store/slices/chat';
import { layoutHead as variant } from './variants';

export const LayoutHead = () => {
const { themeId: theme } = useAppSelector(getConfig);
const { themeId: theme, closeVisible } = useAppSelector(getConfig);
const dispatch = useAppDispatch();
const { cid, systemType, marketing } = useAppSelector(getMeta);
const { base } = variant({ theme });

const onClick = (e) => {
e.currentTarget.disabled = true;
track({
eventType: customEvents.closeClicked,
systemType,
utmParams: marketing.lastUtmParams,
customerUuid: cid,
});
setTimeout(() => {
dispatch(setClosed());
}, 500);
};

return (
<div className={ base() }>
<Profile />
{ closeVisible && (
<IconBtn e2e="chat-close-btn" onClick={ onClick }>
<svg
height="24px" viewBox="0 0 24 24"
width="24px"
>
<g
stroke="currentColor" strokeLinecap="round"
strokeWidth="2"
>
<line
x1="6" x2="18"
y1="6" y2="18"
/>
<line
x1="6" x2="18"
y1="18" y2="6"
/>
</g>
</svg>
</IconBtn>
) }
</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/Layout/variants.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const layoutBase = /*tw*/ tv({

export const layoutHead = /*tw*/ tv({
slots: {
base: 'tw--flex tw--px-5 tw--py-[11px] tw--shadow-[-1px_2px_5px_0]',
base: 'tw--flex tw--px-5 tw--py-[11px] tw--shadow-[-1px_2px_5px_0] tw--justify-between',
},
variants: {
theme: {
Expand Down
1 change: 1 addition & 0 deletions src/config/analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const customEvents = {
emailExist: 'EmailExist',
priceSeen: 'PriceSeen',
buttonClick: 'ButtonClick',
closeClicked: 'CloseClicked',
};

export const baseEventsArr = getKeys(baseEvents);
Expand Down
6 changes: 4 additions & 2 deletions src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ export const chat = (id) => ({
mealButton: 'Create your meal plan',
error: 'Oops something went wrong.',
tm505: 'Please enter valid email address',
}
},
closeVisible: true
},
});

export const paymentData = { amount: '29.90',
export const paymentData = {
amount: '29.90',
amountInUSD: 29.9,
frequency: 1,
frequencyInMonths: 1,
Expand Down
15 changes: 11 additions & 4 deletions src/middleware/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ const chatMiddleware = store => next => action => {
if (socket && socket.connected && message.trim() !== '') {
socket.volatile.emit(
events.chat,
{ role: roles.user,
{
role: roles.user,
message,
term: getQueryParam(window.location.search, 'utm_chat'),
user_id: meta.cid,
Expand Down Expand Up @@ -127,10 +128,16 @@ const chatMiddleware = store => next => action => {
}

if (setClosed.match(action)) {
document.querySelector('#chatbot-container')?.remove();
document.body.classList?.remove('scroll-stop');
const chatBotContainer = document.querySelector('#chatbot-container');
if (document.body && chatBotContainer) {
chatBotContainer.innerHTML = '';
document.body.classList.remove('scroll-stop');
}
const currentLocation = new URL(window.location.href);
currentLocation.search = '';
localStorage.setItem(CHAT_FINISHED_TIMESTAMP, new Date().getTime());
socket.close();
window.location = currentLocation.toString();
if (socket) socket.close();
}

if (setTypingTimeoutExpired.match(action) && action.payload) {
Expand Down
1 change: 1 addition & 0 deletions src/store/slices/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const configSlice = createSlice({
state.translations = { ...initialState.translations, ...payload.translations };
state.themeId = payload.themeId;
state.chatUrl = payload.chatUrl;
state.closeVisible = payload.closeVisible;
},
resetConfig(state) {
state.aiProfile = initialState.aiProfile;
Expand Down

0 comments on commit 7435a27

Please sign in to comment.