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

fix: Webchat Inspector context #6067

Merged
merged 5 commits into from
Mar 2, 2021
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { Indicator } from './Indicator';

export const DebugPanelErrorIndicator = (props: { hasError: boolean; hasWarning?: boolean }) => {
const indicator = props.hasError ? (
<Indicator color={`${SharedColors.red10}`} size={8} />
<Indicator color={`${SharedColors.red10}`} />
) : props.hasWarning ? (
<Indicator color={`${SharedColors.yellow10}`} size={8} />
<Indicator color={`${SharedColors.yellow10}`} />
) : null;
return indicator;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@
// Licensed under the MIT License.

/** @jsx jsx */
import { jsx } from '@emotion/core';
import { css, jsx } from '@emotion/core';
import formatMessage from 'format-message';
import React from 'react';

export interface IndicatorProps {
size: number;
color: string;
}

export const Indicator: React.FC<IndicatorProps> = ({ size, color }) => {
export const Indicator: React.FC<IndicatorProps> = ({ color }) => {
return (
<svg fill={color} height={size} viewBox="0 0 100 100" width={size} xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" />
</svg>
<div
aria-label={formatMessage('Unread notifications Indicator')}
css={css`
background: ${color};
width: 10px;
height: 10px;
border-radius: 50%;
`}
data-testid="DebugErrorIndicator"
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
import { jsx } from '@emotion/core';
import { useRecoilValue } from 'recoil';

import { currentProjectIdState } from '../../../../../recoilModel';
import { rootBotProjectIdSelector } from '../../../../../recoilModel';
import { webChatLogsState } from '../../../../../recoilModel/atoms';

import { WebchatLogItem } from './WebchatLogItem';

// R12: We are showing Errors from the root bot only.
export const WebchatLogContent = () => {
const currentProjectId = useRecoilValue(currentProjectIdState);
const displayedLogs = useRecoilValue(webChatLogsState(currentProjectId));
const currentProjectId = useRecoilValue(rootBotProjectIdSelector);
const displayedLogs = useRecoilValue(webChatLogsState(currentProjectId ?? ''));

return (
<div css={{ padding: '16px 24px' }} data-testid="Webchat-Logs-Container">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,22 @@ export const WebChatLogItemHeader: React.FC<DebugPanelTabHeaderProps> = ({ isAct
const rootBotId = useRecoilValue(rootBotProjectIdSelector);
const logItems = useRecoilValue(webChatLogsState(rootBotId ?? ''));

const [hasUnreadLog, setHasUnreadLog] = useState(false);
const [hasUnreadLogs, setHasUnreadLogs] = useState(false);
const [lastReadLogIds, setLastReadLogIds] = useState<string[]>([]);

useEffect(() => {
if (isActive || !logItems.length) {
setHasUnreadLog(false);
return;
}

const newLogIds = logItems.map((item) => item.timestamp);
if (!isEqual(newLogIds, lastReadLogIds)) {
const areLogsSame = isEqual(newLogIds, lastReadLogIds);

if (!areLogsSame) {
setLastReadLogIds(newLogIds);
if (!isActive) {
setHasUnreadLog(true);
if (isActive || !logItems.length) {
setHasUnreadLogs(false);
return;
}
setHasUnreadLogs(true);
} else {
setHasUnreadLogs(false);
}
}, [logItems, isActive]);

Expand All @@ -50,7 +51,7 @@ export const WebChatLogItemHeader: React.FC<DebugPanelTabHeaderProps> = ({ isAct
>
{formatMessage('Webchat Inspector')}
</div>
<DebugPanelErrorIndicator hasError={hasUnreadLog} />
<DebugPanelErrorIndicator hasError={hasUnreadLogs} />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import * as React from 'react';

import { renderWithRecoil, wrapWithRecoil } from '../../../../__tests__/testUtils/renderWithRecoil';
import { botProjectIdsState, projectMetaDataState, webChatLogsState } from '../../../recoilModel';
import { WebChatLogItemHeader } from '../DebugPanel/TabExtensions/WebchatLog/WebchatLogItemHeader';

const rootBotId = '123-adc';

describe('<DebugPanel />', () => {
beforeEach(() => {});

describe('<WebchatLogItemheader />', () => {
it('should render Webchat inspector header', async () => {
const { findByText } = renderWithRecoil(<WebChatLogItemHeader isActive />, ({ set }) => {
set(botProjectIdsState, [rootBotId]);
set(webChatLogsState(rootBotId), []);
});
await findByText('Webchat Inspector');
});

it('should render unread error indicator as the tab is inactive. Once read, the error indicator needs to disappear.', async () => {
const { findByTestId, rerender, queryByTestId } = renderWithRecoil(
<WebChatLogItemHeader isActive={false} />,
({ set }) => {
set(botProjectIdsState, [rootBotId]);
set(projectMetaDataState(rootBotId), {
isRootBot: true,
isRemote: false,
});
set(webChatLogsState(rootBotId), [
{
timestamp: '2021-03-01 13:21:16',
route: 'POST /v3/directline/conversations/36842e12-3ac5-446a-bafd-d073c2d8cb1d%7Clivechat/activities',
logType: 'Error',
status: 400,
message: 'Error validating Microsoft App ID and Password',
details: '',
},
]);
}
);
await findByTestId('DebugErrorIndicator');

rerender(
wrapWithRecoil(<WebChatLogItemHeader isActive />, ({ set }) => {
set(botProjectIdsState, [rootBotId]);
set(projectMetaDataState(rootBotId), {
isRootBot: true,
isRemote: false,
});
set(webChatLogsState(rootBotId), [
{
timestamp: '2021-03-01 13:21:16',
route: 'POST /v3/directline/conversations/36842e12-3ac5-446a-bafd-d073c2d8cb1d%7Clivechat/activities',
logType: 'Error',
status: 400,
message: 'Error validating Microsoft App ID and Password',
details: '',
},
]);
})
);
expect(queryByTestId('DebugErrorIndicator')).toBeNull();
});

it('should not render unread error indicator as the tab is active', async () => {
const { queryByTestId } = renderWithRecoil(<WebChatLogItemHeader isActive />, ({ set }) => {
set(botProjectIdsState, [rootBotId]);
set(projectMetaDataState(rootBotId), {
isRootBot: true,
isRemote: false,
});
set(webChatLogsState(rootBotId), [
{
timestamp: '2021-03-01 13:21:16',
route: 'POST /v3/directline/conversations/36842e12-3ac5-446a-bafd-d073c2d8cb1d%7Clivechat/activities',
logType: 'Error',
status: 400,
message: 'Error validating Microsoft App ID and Password',
details: '',
},
]);
});
expect(queryByTestId('DebugErrorIndicator')).toBeNull();
});
});
});