-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…279) * support context aware alert analysis * Render GeneratePopover IncontextInsight component as a button to generate summary * Remove hardcoded assistant role from the parameter payload * Make GeneratePopoverBody as independent component * Update change log * Add independent GeneratePopoverBody ut and reorgnize constants * Simplify states of loading to get summary process * Make IncontextInsight not shareable and each component has its own IncontextInsight * Enable context aware alert only if feature flag is enabled --------- (cherry picked from commit 32888dd) Signed-off-by: Songkan Tang <[email protected]> Co-authored-by: Songkan Tang <[email protected]> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
94dc4a2
commit 2152d02
Showing
14 changed files
with
527 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
199 changes: 199 additions & 0 deletions
199
public/components/incontext_insight/generate_popover_body.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import React from 'react'; | ||
import { render, cleanup, fireEvent, waitFor } from '@testing-library/react'; | ||
import { getConfigSchema, getNotifications } from '../../services'; | ||
import { GeneratePopoverBody } from './generate_popover_body'; | ||
import { HttpSetup } from '../../../../../src/core/public'; | ||
import { ASSISTANT_API } from '../../../common/constants/llm'; | ||
|
||
jest.mock('../../services'); | ||
|
||
const mockToasts = { | ||
addDanger: jest.fn(), | ||
}; | ||
|
||
beforeEach(() => { | ||
(getNotifications as jest.Mock).mockImplementation(() => ({ | ||
toasts: mockToasts, | ||
})); | ||
(getConfigSchema as jest.Mock).mockReturnValue({ | ||
chat: { enabled: true }, | ||
}); | ||
}); | ||
|
||
afterEach(cleanup); | ||
|
||
const mockPost = jest.fn(); | ||
const mockHttpSetup: HttpSetup = ({ | ||
post: mockPost, | ||
} as unknown) as HttpSetup; // Mocking HttpSetup | ||
|
||
describe('GeneratePopoverBody', () => { | ||
const incontextInsightMock = { | ||
contextProvider: jest.fn(), | ||
suggestions: ['Test summarization question'], | ||
datasourceId: 'test-datasource', | ||
key: 'test-key', | ||
}; | ||
|
||
const closePopoverMock = jest.fn(); | ||
|
||
it('renders the generate summary button', () => { | ||
const { getByText } = render( | ||
<GeneratePopoverBody | ||
incontextInsight={incontextInsightMock} | ||
httpSetup={mockHttpSetup} | ||
closePopover={closePopoverMock} | ||
/> | ||
); | ||
|
||
expect(getByText('Generate summary')).toBeInTheDocument(); | ||
}); | ||
|
||
it('calls onGenerateSummary when button is clicked', async () => { | ||
mockPost.mockResolvedValue({ | ||
interactions: [{ conversation_id: 'test-conversation' }], | ||
messages: [{ type: 'output', content: 'Generated summary content' }], | ||
}); | ||
|
||
const { getByText } = render( | ||
<GeneratePopoverBody | ||
incontextInsight={incontextInsightMock} | ||
httpSetup={mockHttpSetup} | ||
closePopover={closePopoverMock} | ||
/> | ||
); | ||
|
||
const button = getByText('Generate summary'); | ||
fireEvent.click(button); | ||
|
||
// Wait for loading to complete and summary to render | ||
await waitFor(() => { | ||
expect(getByText('Generated summary content')).toBeInTheDocument(); | ||
}); | ||
|
||
expect(mockPost).toHaveBeenCalledWith(ASSISTANT_API.SEND_MESSAGE, expect.any(Object)); | ||
expect(mockToasts.addDanger).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('shows loading state while generating summary', async () => { | ||
const { getByText } = render( | ||
<GeneratePopoverBody | ||
incontextInsight={incontextInsightMock} | ||
httpSetup={mockHttpSetup} | ||
closePopover={closePopoverMock} | ||
/> | ||
); | ||
|
||
const button = getByText('Generate summary'); | ||
fireEvent.click(button); | ||
|
||
// Wait for loading state to appear | ||
expect(getByText('Generating summary...')).toBeInTheDocument(); | ||
}); | ||
|
||
it('handles error during summary generation', async () => { | ||
mockPost.mockRejectedValue(new Error('Network Error')); | ||
|
||
const { getByText } = render( | ||
<GeneratePopoverBody | ||
incontextInsight={incontextInsightMock} | ||
httpSetup={mockHttpSetup} | ||
closePopover={closePopoverMock} | ||
/> | ||
); | ||
|
||
const button = getByText('Generate summary'); | ||
fireEvent.click(button); | ||
|
||
await waitFor(() => { | ||
expect(mockToasts.addDanger).toHaveBeenCalledWith('Generate summary error'); | ||
}); | ||
}); | ||
|
||
it('renders the continue in chat button after summary is generated', async () => { | ||
mockPost.mockResolvedValue({ | ||
interactions: [{ conversation_id: 'test-conversation' }], | ||
messages: [{ type: 'output', content: 'Generated summary content' }], | ||
}); | ||
|
||
const { getByText } = render( | ||
<GeneratePopoverBody | ||
incontextInsight={incontextInsightMock} | ||
httpSetup={mockHttpSetup} | ||
closePopover={closePopoverMock} | ||
/> | ||
); | ||
|
||
const button = getByText('Generate summary'); | ||
fireEvent.click(button); | ||
|
||
// Wait for the summary to be displayed | ||
await waitFor(() => { | ||
expect(getByText('Generated summary content')).toBeInTheDocument(); | ||
}); | ||
|
||
// Check for continue in chat button | ||
expect(getByText('Continue in chat')).toBeInTheDocument(); | ||
}); | ||
|
||
it('calls onChatContinuation when continue in chat button is clicked', async () => { | ||
mockPost.mockResolvedValue({ | ||
interactions: [{ conversation_id: 'test-conversation' }], | ||
messages: [{ type: 'output', content: 'Generated summary content' }], | ||
}); | ||
|
||
const { getByText } = render( | ||
<GeneratePopoverBody | ||
incontextInsight={incontextInsightMock} | ||
httpSetup={mockHttpSetup} | ||
closePopover={closePopoverMock} | ||
/> | ||
); | ||
|
||
const button = getByText('Generate summary'); | ||
fireEvent.click(button); | ||
|
||
await waitFor(() => { | ||
expect(getByText('Generated summary content')).toBeInTheDocument(); | ||
}); | ||
|
||
const continueButton = getByText('Continue in chat'); | ||
fireEvent.click(continueButton); | ||
|
||
expect(mockPost).toHaveBeenCalledTimes(1); | ||
expect(closePopoverMock).toHaveBeenCalled(); | ||
}); | ||
|
||
it("continue in chat button doesn't appear when chat is disabled", async () => { | ||
mockPost.mockResolvedValue({ | ||
interactions: [{ conversation_id: 'test-conversation' }], | ||
messages: [{ type: 'output', content: 'Generated summary content' }], | ||
}); | ||
(getConfigSchema as jest.Mock).mockReturnValue({ | ||
chat: { enabled: false }, | ||
}); | ||
|
||
const { getByText, queryByText } = render( | ||
<GeneratePopoverBody | ||
incontextInsight={incontextInsightMock} | ||
httpSetup={mockHttpSetup} | ||
closePopover={closePopoverMock} | ||
/> | ||
); | ||
|
||
const button = getByText('Generate summary'); | ||
fireEvent.click(button); | ||
|
||
await waitFor(() => { | ||
expect(getByText('Generated summary content')).toBeInTheDocument(); | ||
}); | ||
|
||
expect(queryByText('Continue in chat')).toBeNull(); | ||
expect(mockPost).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
Oops, something went wrong.