Skip to content

Commit

Permalink
add unit tests for CoreVisualization and ChatFlyout (#56)
Browse files Browse the repository at this point in the history
Signed-off-by: Yulong Ruan <ruanyl@amazon.com>
  • Loading branch information
ruanyl committed Dec 12, 2023
1 parent 47a8cc0 commit 3ff4134
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 5 deletions.
149 changes: 149 additions & 0 deletions public/chat_flyout.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';

import { ChatFlyout } from './chat_flyout';
import * as chatContextExports from './contexts/chat_context';
import { TAB_ID } from './utils/constants';

jest.mock('./tabs/chat/chat_page', () => ({
ChatPage: () => <div aria-label="mock chat page" />,
}));

jest.mock('./tabs/chat_window_header', () => ({
ChatWindowHeader: () => <div aria-label="mock chat window header" />,
}));

jest.mock('./tabs/history/chat_history_page', () => ({
ChatHistoryPage: () => <div aria-label="mock chat history page" />,
}));

jest.mock('./components/agent_framework_traces_flyout_body', () => ({
AgentFrameworkTracesFlyoutBody: () => (
<div aria-label="mock agent framework traces flyout body" />
),
}));

describe('<ChatFlyout />', () => {
beforeEach(() => {
jest.spyOn(chatContextExports, 'useChatContext').mockReturnValue({
setFlyoutVisible: jest.fn(),
selectedTabId: TAB_ID.CHAT,
traceId: 'chat_trace_id_mock',
});
});

afterEach(() => {
jest.resetAllMocks();
});

it('should only display chat panel when current tab is TAB_ID.CHAT under non-fullscreen mode', () => {
jest.spyOn(chatContextExports, 'useChatContext').mockReturnValue({
setFlyoutVisible: jest.fn(),
selectedTabId: TAB_ID.CHAT,
traceId: 'chat_trace_id_mock',
});

render(
<ChatFlyout
flyoutVisible={true}
overrideComponent={null}
flyoutProps={{}}
flyoutFullScreen={false}
toggleFlyoutFullScreen={jest.fn()}
/>
);
expect(screen.getByLabelText('chat panel').classList).not.toContain('llm-chat-hidden');
expect(screen.getByLabelText('history panel').classList).toContain('llm-chat-hidden');
});

it('should only display history panel when current tab is TAB_ID.HISTORY under non-fullscreen mode', () => {
jest.spyOn(chatContextExports, 'useChatContext').mockReturnValue({
setFlyoutVisible: jest.fn(),
selectedTabId: TAB_ID.HISTORY,
traceId: 'chat_trace_id_mock',
});

render(
<ChatFlyout
flyoutVisible={true}
overrideComponent={null}
flyoutProps={{}}
flyoutFullScreen={false}
toggleFlyoutFullScreen={jest.fn()}
/>
);
expect(screen.getByLabelText('chat panel').classList).toContain('llm-chat-hidden');
expect(screen.getByLabelText('history panel').classList).not.toContain('llm-chat-hidden');
});

it('should display chat history page', () => {
jest.spyOn(chatContextExports, 'useChatContext').mockReturnValue({
setFlyoutVisible: jest.fn(),
selectedTabId: TAB_ID.HISTORY,
traceId: 'chat_trace_id_mock',
});

render(
<ChatFlyout
flyoutVisible={true}
overrideComponent={null}
flyoutProps={{}}
flyoutFullScreen={false}
toggleFlyoutFullScreen={jest.fn()}
/>
);

expect(screen.queryByLabelText('mock chat history page')).toBeInTheDocument();
expect(
screen.queryByLabelText('mock agent framework traces flyout body')
).not.toBeInTheDocument();
});

it('should display traces page', () => {
jest.spyOn(chatContextExports, 'useChatContext').mockReturnValue({
setFlyoutVisible: jest.fn(),
selectedTabId: TAB_ID.TRACE,
traceId: 'chat_trace_id_mock',
});

render(
<ChatFlyout
flyoutVisible={true}
overrideComponent={null}
flyoutProps={{}}
flyoutFullScreen={false}
toggleFlyoutFullScreen={jest.fn()}
/>
);

expect(screen.queryByLabelText('mock chat history page')).not.toBeInTheDocument();
expect(screen.queryByLabelText('mock agent framework traces flyout body')).toBeInTheDocument();
});

it('should always display chat panel when in fullscreen mode', () => {
jest.spyOn(chatContextExports, 'useChatContext').mockReturnValue({
setFlyoutVisible: jest.fn(),
// current tab is NOT chat
selectedTabId: TAB_ID.HISTORY,
traceId: 'chat_trace_id_mock',
});

render(
<ChatFlyout
flyoutVisible={true}
overrideComponent={null}
flyoutProps={{}}
flyoutFullScreen={true} // fullscreen
toggleFlyoutFullScreen={jest.fn()}
/>
);

expect(screen.getByLabelText('chat panel').classList).not.toContain('llm-chat-hidden');
expect(screen.getByLabelText('history panel').classList).not.toContain('llm-chat-hidden');
});
});
12 changes: 7 additions & 5 deletions public/chat_flyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@

import { EuiFlyout, EuiFlyoutHeader, EuiResizableContainer } from '@elastic/eui';
import cs from 'classnames';
import React from 'react';
import React, { useRef } from 'react';
import { useChatContext } from './contexts/chat_context';
import { ChatPage } from './tabs/chat/chat_page';
import { ChatWindowHeader } from './tabs/chat_window_header';
import { ChatHistoryPage } from './tabs/history/chat_history_page';
import { AgentFrameworkTracesFlyoutBody } from './components/agent_framework_traces_flyout_body';
import { TAB_ID } from './utils/constants';

let chatHistoryPageLoaded = false;

interface ChatFlyoutProps {
flyoutVisible: boolean;
overrideComponent: React.ReactNode | null;
Expand All @@ -25,6 +23,7 @@ interface ChatFlyoutProps {

export const ChatFlyout: React.FC<ChatFlyoutProps> = (props) => {
const chatContext = useChatContext();
const chatHistoryPageLoadedRef = useRef(false);

let chatPageVisible = false;
let chatHistoryPageVisible = false;
Expand Down Expand Up @@ -54,7 +53,8 @@ export const ChatFlyout: React.FC<ChatFlyoutProps> = (props) => {
chatPageVisible = true;
}

if (!chatHistoryPageLoaded && chatHistoryPageVisible) chatHistoryPageLoaded = true;
if (!chatHistoryPageLoadedRef.current && chatHistoryPageVisible)
chatHistoryPageLoadedRef.current = true;

const resizable = props.flyoutFullScreen && (chatHistoryPageVisible || chatTraceVisible);
const getLeftPanelSize = () => {
Expand Down Expand Up @@ -107,6 +107,7 @@ export const ChatFlyout: React.FC<ChatFlyoutProps> = (props) => {
{(Panel, Resizer) => (
<>
<Panel
aria-label="chat panel"
className={cs('llm-chat-horizontal-resize-panel', {
'llm-chat-hidden': leftPanelSize === 0,
})}
Expand All @@ -120,6 +121,7 @@ export const ChatFlyout: React.FC<ChatFlyoutProps> = (props) => {
<>
{resizable && <Resizer />}
<Panel
aria-label="history panel"
className={cs('llm-chat-horizontal-resize-panel', {
'llm-chat-hidden': leftPanelSize === 100,
})}
Expand All @@ -128,7 +130,7 @@ export const ChatFlyout: React.FC<ChatFlyoutProps> = (props) => {
initialSize={resizable ? 30 : undefined}
paddingSize="none"
>
{chatHistoryPageLoaded && (
{chatHistoryPageLoadedRef.current && (
<ChatHistoryPage
// refresh data when user switched to table from another tab
shouldRefresh={chatHistoryPageVisible}
Expand Down
40 changes: 40 additions & 0 deletions public/components/core_visualization.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';

import * as coreContextExports from '../contexts/core_context';
import { CoreVisualization } from './core_visualization';

describe('<CoreVisualization />', () => {
beforeEach(() => {
jest.spyOn(coreContextExports, 'useCore').mockReturnValue({
services: {
uiSettings: {
get: jest.fn().mockReturnValue('MMM D, YYYY @ HH:mm:ss.SSS'),
},
startDeps: {
dashboard: {
DashboardContainerByValueRenderer: () => <div />,
},
},
},
});
});

afterEach(() => {
jest.resetAllMocks();
});

it('should display visualization of last 15 minutes by default', () => {
render(
<CoreVisualization
message={{ type: 'output', contentType: 'visualization', content: 'vis_id_mock' }}
/>
);
expect(screen.queryByText('Last 15 minutes')).toBeInTheDocument();
});
});

0 comments on commit 3ff4134

Please sign in to comment.