Skip to content

Commit

Permalink
added test case of citation panel and chatMessageContainer
Browse files Browse the repository at this point in the history
  • Loading branch information
Rohini-Microsoft committed Oct 10, 2024
1 parent fe316c7 commit a3aa421
Show file tree
Hide file tree
Showing 3 changed files with 270 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import React from 'react'
import { fireEvent, render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import ChatMessageContainer, { parseCitationFromMessage } from './ChatMessageContainer'

import { type ChatMessage } from '../../api'

jest.mock('remark-supersub', () => () => {})
jest.mock('remark-gfm', () => () => {})
jest.mock('rehype-raw', () => () => {})
jest.mock('../Answer', () => ({
Answer: jest.fn((props: any) => <div>
<p>{props.answer.answer}</p>
<span>Mock Answer Component</span>
{props.answer.answer === 'Generating answer...'
? <button onClick={() => props.onCitationClicked()}>Mock Citation Loading</button>
: <button onClick={() => props.onCitationClicked({ title: 'Test Citation' })}>Mock Citation</button>
}

</div>)
}))

const mockOnShowCitation = jest.fn()
describe('ChatMessageContainer', () => {
beforeEach(() => {
global.fetch = jest.fn()
jest.spyOn(console, 'error').mockImplementation(() => { })
})

afterEach(() => {
jest.clearAllMocks()
})

const userMessage: ChatMessage = {
role: 'user',
content: 'User message',
id: '1',
date: new Date().toDateString()
}

const assistantMessage: ChatMessage = {
role: 'assistant',
content: 'Assistant message',
id: '2',
date: new Date().toDateString()
}

const errorMessage: ChatMessage = {
role: 'error',
content: 'Error message',
id: '3',
date: new Date().toDateString()
}

const nullMessage: ChatMessage = {
role: '',
content: 'Null role message',
id: '4',
date: ''
}
it('renders user messages correctly', () => {
render(<ChatMessageContainer messages={[userMessage]} onShowCitation={mockOnShowCitation} showLoadingMessage={false} />)
expect(screen.getByText('User message')).toBeInTheDocument()
})

it('renders assistant messages correctly', () => {
render(<ChatMessageContainer messages={[assistantMessage]} onShowCitation={mockOnShowCitation} showLoadingMessage={false} />)
expect(screen.getByText('Assistant message')).toBeInTheDocument()
})

it('renders an error message correctly', () => {
render(
<ChatMessageContainer
messages={[errorMessage]}
showLoadingMessage={false}
onShowCitation={mockOnShowCitation}
/>
)

// Check if error message is displayed with the error icon
expect(screen.getByText('Error')).toBeInTheDocument()
expect(screen.getByText('Error message')).toBeInTheDocument()
})

it('returns citations when message role is "tool" and content is valid JSON', () => {
const message: ChatMessage = {
role: 'tool',
content: JSON.stringify({ citations: [{ filepath: 'path/to/file', chunk_id: '1' }] }),
id: '1',
date: ''
}
const citations = parseCitationFromMessage(message)
expect(citations).toEqual([{ filepath: 'path/to/file', chunk_id: '1' }])
})

it('returns an empty array when message role is "tool" and content is invalid JSON', () => {
const message: ChatMessage = {
role: 'tool',
content: 'invalid JSON',
id: '1',
date: ''
}
const citations = parseCitationFromMessage(message)
expect(citations).toEqual([])
})

it('returns an empty array when message role is not "tool"', () => {
const message: ChatMessage = {
role: 'user',
content: JSON.stringify({ citations: [{ filepath: 'path/to/file', chunk_id: '1' }] }),
id: '1',
date: ''
}
const citations = parseCitationFromMessage(message)
expect(citations).toEqual([])
})

it('handles null role messages correctly', () => {
render(<ChatMessageContainer messages={[nullMessage]} onShowCitation={mockOnShowCitation} showLoadingMessage={false} />)
expect(screen.queryByText('Null role message')).not.toBeInTheDocument()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type ChatMessageContainerProps = {
showLoadingMessage: boolean;
};

const parseCitationFromMessage = (message: ChatMessage) => {
export const parseCitationFromMessage = (message: ChatMessage) => {
if (message?.role && message?.role === "tool") {
try {
const toolMessage = JSON.parse(message.content) as ToolMessageContent;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// CitationPanel.test.tsx
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import CitationPanel from './CitationPanel'
import { type Citation } from '../../api'

jest.mock('remark-gfm', () => jest.fn())
jest.mock('rehype-raw', () => jest.fn())
const mockIsCitationPanelOpen = jest.fn()
const mockOnViewSource = jest.fn()
const mockOnClickAddFavorite = jest.fn()

const mockCitation = {
id: '123',
title: 'Sample Citation',
content: 'This is a sample citation content.',
url: 'https://example.com/sample-citation',
filepath: 'path',
metadata: '',
chunk_id: '',
reindex_id: ''
}

describe('CitationPanel', () => {
beforeEach(() => {
// Reset mocks before each test
mockIsCitationPanelOpen.mockClear()
mockOnViewSource.mockClear()
})

test('renders CitationPanel with citation title and content', () => {
render(
<CitationPanel
activeCitation={mockCitation}
onViewSource={mockOnViewSource} setIsCitationPanelOpen={function (flag: boolean): void {
throw new Error('Function not implemented.')
} } onClickAddFavorite={function (): void {
throw new Error('Function not implemented.')
} } />
)

// Check if title is rendered
expect(screen.getByRole('heading', { name: /Sample Citation/i })).toBeInTheDocument()
})

test('renders CitationPanel with citation title and content without url ', () => {
render(
<CitationPanel
activeCitation={{ ...mockCitation, url: null, title: null }}
onViewSource={mockOnViewSource} setIsCitationPanelOpen={mockIsCitationPanelOpen} onClickAddFavorite={mockOnClickAddFavorite} />
)

expect(screen.getByRole('heading', { name: '' })).toBeInTheDocument()
})

test('renders CitationPanel with citation title and content includes blob.core in url ', () => {
render(
<CitationPanel
activeCitation={{ ...mockCitation, url: 'blob.core', title: null }}
onViewSource={mockOnViewSource} setIsCitationPanelOpen={mockIsCitationPanelOpen} onClickAddFavorite={mockOnClickAddFavorite} />
)

expect(screen.getByRole('heading', { name: '' })).toBeInTheDocument()
})

test('renders CitationPanel with citation title and content title is null ', () => {
render(
<CitationPanel
activeCitation={{ ...mockCitation, title: null }}
onViewSource={mockOnViewSource} setIsCitationPanelOpen={mockIsCitationPanelOpen} onClickAddFavorite={mockOnClickAddFavorite} />
)

expect(screen.getByRole('heading', { name: 'https://example.com/sample-citation' })).toBeInTheDocument()
})

test('calls IsCitationPanelOpen with false when close button is clicked', () => {
render(
<CitationPanel
activeCitation={mockCitation}
onViewSource={mockOnViewSource} setIsCitationPanelOpen={mockIsCitationPanelOpen} onClickAddFavorite={mockOnClickAddFavorite}/>
)
const closeButton = screen.getByRole('button', { name: /Close citations panel/i })
fireEvent.click(closeButton)

expect(mockIsCitationPanelOpen).toHaveBeenCalledWith(false)
})

test('calls onViewSource with citation when title is clicked', () => {
render(
<CitationPanel
activeCitation={mockCitation}
setIsCitationPanelOpen={mockIsCitationPanelOpen}
onViewSource={mockOnViewSource} onClickAddFavorite={mockOnClickAddFavorite}/>
)

const title = screen.getByRole('heading', { name: /Sample Citation/i })
fireEvent.click(title)

expect(mockOnViewSource).toHaveBeenCalledWith(mockCitation)
})

test('renders the title correctly and sets the correct title attribute for non-blob URL', () => {
render(
<CitationPanel
activeCitation={mockCitation} setIsCitationPanelOpen={mockIsCitationPanelOpen} onViewSource={mockOnViewSource} onClickAddFavorite={mockOnClickAddFavorite}
/>
)

const titleElement = screen.getByRole('heading', { name: /Sample Citation/i })

// Ensure the title is rendered
expect(titleElement).toBeInTheDocument()

// Ensure the title attribute is set to the URL since it's not a blob URL
expect(titleElement).toHaveAttribute('title', 'https://example.com/sample-citation')

// Trigger the onClick event and ensure onViewSource is called with the correct citation
fireEvent.click(titleElement)
expect(mockOnViewSource).toHaveBeenCalledWith(mockCitation)
})

test('renders the title correctly and sets the title attribute to the citation title for blob URL', () => {
const mockCitationWithBlobUrl: Citation = {
...mockCitation,
title: 'Test Citation with Blob URL',
url: 'https://blob.core.example.com/resource',
content: ''
}
render(
<CitationPanel
activeCitation={mockCitationWithBlobUrl}
onViewSource={mockOnViewSource} setIsCitationPanelOpen={mockIsCitationPanelOpen} onClickAddFavorite={mockOnClickAddFavorite}/>
)

const titleElement = screen.getByRole('heading', { name: /Test Citation with Blob URL/i })

// Ensure the title is rendered
expect(titleElement).toBeInTheDocument()

// Ensure the title attribute is set to the citation title since the URL contains "blob.core"
expect(titleElement).toHaveAttribute('title', 'Test Citation with Blob URL')

// Trigger the onClick event and ensure onViewSource is called with the correct citation
fireEvent.click(titleElement)
expect(mockOnViewSource).toHaveBeenCalledWith(mockCitationWithBlobUrl)
})
})

0 comments on commit a3aa421

Please sign in to comment.