Skip to content

Commit 7db77e8

Browse files
added test cases of chatMessageContainer
1 parent a3aa421 commit 7db77e8

File tree

2 files changed

+86
-54
lines changed

2 files changed

+86
-54
lines changed
Lines changed: 84 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
import React from 'react'
2-
import { fireEvent, render, screen } from '@testing-library/react'
3-
import '@testing-library/jest-dom'
4-
import ChatMessageContainer, { parseCitationFromMessage } from './ChatMessageContainer'
5-
6-
import { type ChatMessage } from '../../api'
7-
2+
import { render, screen, fireEvent } from '@testing-library/react'
3+
import { ChatMessageContainer } from './ChatMessageContainer'
4+
import { type ChatMessage } from '../../api/models'
5+
import { Answer } from '../Answer'
86
jest.mock('remark-supersub', () => () => {})
97
jest.mock('remark-gfm', () => () => {})
108
jest.mock('rehype-raw', () => () => {})
11-
jest.mock('../Answer', () => ({
9+
jest.mock('../Answer/Answer', () => ({
1210
Answer: jest.fn((props: any) => <div>
1311
<p>{props.answer.answer}</p>
1412
<span>Mock Answer Component</span>
15-
{props.answer.answer === 'Generating answer...'
13+
{props.answer.answer == 'Generating answer...'
1614
? <button onClick={() => props.onCitationClicked()}>Mock Citation Loading</button>
17-
: <button onClick={() => props.onCitationClicked({ title: 'Test Citation' })}>Mock Citation</button>
15+
: <button aria-label="citationButton" onClick={() => props.onCitationClicked({ title: 'Test Citation' })}>Mock Citation</button>
1816
}
1917

2018
</div>)
2119
}))
2220

2321
const mockOnShowCitation = jest.fn()
22+
2423
describe('ChatMessageContainer', () => {
2524
beforeEach(() => {
2625
global.fetch = jest.fn()
@@ -52,26 +51,36 @@ describe('ChatMessageContainer', () => {
5251
date: new Date().toDateString()
5352
}
5453

55-
const nullMessage: ChatMessage = {
56-
role: '',
57-
content: 'Null role message',
58-
id: '4',
59-
date: ''
60-
}
61-
it('renders user messages correctly', () => {
62-
render(<ChatMessageContainer messages={[userMessage]} onShowCitation={mockOnShowCitation} showLoadingMessage={false} />)
63-
expect(screen.getByText('User message')).toBeInTheDocument()
64-
})
54+
it('renders user and assistant messages correctly', () => {
55+
render(
56+
<ChatMessageContainer
57+
messages={[userMessage, assistantMessage]}
58+
showLoadingMessage={false}
59+
onShowCitation={mockOnShowCitation}
60+
/>
61+
)
6562

66-
it('renders assistant messages correctly', () => {
67-
render(<ChatMessageContainer messages={[assistantMessage]} onShowCitation={mockOnShowCitation} showLoadingMessage={false} />)
68-
expect(screen.getByText('Assistant message')).toBeInTheDocument()
63+
// Check if user message is displayed
64+
expect(screen.getByText('User message')).toBeInTheDocument()
65+
screen.debug()
66+
// Check if assistant message is displayed via Answer component
67+
expect(screen.getByText('Mock Answer Component')).toBeInTheDocument()
68+
expect(Answer).toHaveBeenCalledWith(
69+
expect.objectContaining({
70+
answer: {
71+
answer: 'Assistant message',
72+
citations: []
73+
}
74+
}),
75+
{}
76+
)
6977
})
7078

7179
it('renders an error message correctly', () => {
7280
render(
7381
<ChatMessageContainer
7482
messages={[errorMessage]}
83+
7584
showLoadingMessage={false}
7685
onShowCitation={mockOnShowCitation}
7786
/>
@@ -82,41 +91,64 @@ describe('ChatMessageContainer', () => {
8291
expect(screen.getByText('Error message')).toBeInTheDocument()
8392
})
8493

85-
it('returns citations when message role is "tool" and content is valid JSON', () => {
86-
const message: ChatMessage = {
87-
role: 'tool',
88-
content: JSON.stringify({ citations: [{ filepath: 'path/to/file', chunk_id: '1' }] }),
89-
id: '1',
90-
date: ''
91-
}
92-
const citations = parseCitationFromMessage(message)
93-
expect(citations).toEqual([{ filepath: 'path/to/file', chunk_id: '1' }])
94+
it('displays the loading message when showLoadingMessage is true', () => {
95+
render(
96+
<ChatMessageContainer
97+
messages={[]}
98+
99+
showLoadingMessage={true}
100+
onShowCitation={mockOnShowCitation}
101+
/>
102+
)
103+
// Check if the loading message is displayed via Answer component
104+
expect(screen.getByText('Generating answer...')).toBeInTheDocument()
105+
})
106+
107+
it('calls onShowCitation when a citation is clicked', () => {
108+
render(
109+
<ChatMessageContainer
110+
messages={[assistantMessage]}
111+
showLoadingMessage={false}
112+
onShowCitation={mockOnShowCitation}
113+
/>
114+
)
115+
116+
// Simulate a citation click
117+
const citationButton = screen.getByText('Mock Citation')
118+
fireEvent.click(citationButton)
119+
120+
// Check if onShowCitation is called with the correct argument
121+
expect(mockOnShowCitation).toHaveBeenCalledWith({ title: 'Test Citation' })
94122
})
95123

96-
it('returns an empty array when message role is "tool" and content is invalid JSON', () => {
97-
const message: ChatMessage = {
98-
role: 'tool',
99-
content: 'invalid JSON',
100-
id: '1',
101-
date: ''
102-
}
103-
const citations = parseCitationFromMessage(message)
104-
expect(citations).toEqual([])
124+
test('does not call onShowCitation when citation click is a no-op', () => {
125+
render(
126+
<ChatMessageContainer
127+
messages={[]}
128+
showLoadingMessage={true}
129+
onShowCitation={mockOnShowCitation} // No-op function
130+
/>
131+
)
132+
// Simulate a citation click
133+
const citationButton = screen.getByRole('button', { name: 'Mock Citation Loading' })
134+
fireEvent.click(citationButton)
135+
136+
// Check if onShowCitation is NOT called
137+
expect(mockOnShowCitation).not.toHaveBeenCalled()
105138
})
106139

107-
it('returns an empty array when message role is not "tool"', () => {
108-
const message: ChatMessage = {
109-
role: 'user',
110-
content: JSON.stringify({ citations: [{ filepath: 'path/to/file', chunk_id: '1' }] }),
111-
id: '1',
112-
date: ''
113-
}
114-
const citations = parseCitationFromMessage(message)
115-
expect(citations).toEqual([])
140+
test('calls onShowCitation when citation button is clicked', async () => {
141+
render(<ChatMessageContainer messages={[userMessage, assistantMessage]} onShowCitation={mockOnShowCitation} showLoadingMessage={false} />)
142+
const buttonEle = await screen.findByRole('button', { name: 'citationButton' })
143+
fireEvent.click(buttonEle)
144+
expect(mockOnShowCitation).toHaveBeenCalledWith({ title: 'Test Citation' })
116145
})
117146

118-
it('handles null role messages correctly', () => {
119-
render(<ChatMessageContainer messages={[nullMessage]} onShowCitation={mockOnShowCitation} showLoadingMessage={false} />)
120-
expect(screen.queryByText('Null role message')).not.toBeInTheDocument()
147+
test('does not call onCitationClicked when citation button is clicked', async () => {
148+
const mockOnCitationClicked = jest.fn()
149+
render(<ChatMessageContainer messages={[userMessage, assistantMessage]} onShowCitation={mockOnShowCitation} showLoadingMessage={false} />)
150+
const buttonEle = await screen.findByRole('button', { name: 'citationButton' })
151+
fireEvent.click(buttonEle)
152+
expect(mockOnCitationClicked).not.toHaveBeenCalled()
121153
})
122154
})

ResearchAssistant/App/frontend/src/components/ChatMessageContainer/ChatMessageContainer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type ChatMessageContainerProps = {
1111
showLoadingMessage: boolean;
1212
};
1313

14-
export const parseCitationFromMessage = (message: ChatMessage) => {
14+
const parseCitationFromMessage = (message: ChatMessage) => {
1515
if (message?.role && message?.role === "tool") {
1616
try {
1717
const toolMessage = JSON.parse(message.content) as ToolMessageContent;
@@ -23,7 +23,7 @@ export const parseCitationFromMessage = (message: ChatMessage) => {
2323
return [];
2424
};
2525

26-
const ChatMessageContainer = (props: ChatMessageContainerProps): JSX.Element => {
26+
export const ChatMessageContainer = (props: ChatMessageContainerProps): JSX.Element => {
2727
const [ASSISTANT, TOOL, ERROR, USER] = ["assistant", "tool", "error", "user"];
2828
const { messages, onShowCitation , showLoadingMessage} = props;
2929
return (

0 commit comments

Comments
 (0)