mirror of
https://github.com/langgenius/dify.git
synced 2026-09-01 15:09:21 +08:00
fix(web): make suggested questions native buttons (#40200)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -779,14 +779,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/base/chat/chat/answer/suggested-questions.tsx": {
|
||||
"jsx_a11y/click-events-have-key-events": {
|
||||
"count": 1
|
||||
},
|
||||
"jsx_a11y/no-static-element-interactions": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/base/chat/chat/answer/workflow-process.tsx": {
|
||||
"eslint-react/set-state-in-effect": {
|
||||
"count": 1
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { Mock } from 'vitest' // Or 'jest' if using Jest
|
||||
import type { Mock } from 'vitest'
|
||||
import type { IChatItem } from '../../type'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { useChatContext } from '../../context'
|
||||
import SuggestedQuestions from '../suggested-questions'
|
||||
|
||||
// Mock the chat context
|
||||
vi.mock('../../context', () => ({
|
||||
useChatContext: vi.fn(),
|
||||
}))
|
||||
@@ -15,7 +14,6 @@ describe('SuggestedQuestions', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
// Use 'as Mock' instead of 'as any'
|
||||
;(useChatContext as Mock).mockReturnValue({
|
||||
onSend: mockOnSend,
|
||||
readonly: false,
|
||||
@@ -33,41 +31,52 @@ describe('SuggestedQuestions', () => {
|
||||
it('should render suggested questions and filter out empty ones', () => {
|
||||
render(<SuggestedQuestions item={mockItem} />)
|
||||
|
||||
const questions = screen.getAllByTestId('suggested-question')
|
||||
const questions = screen.getAllByRole('button')
|
||||
expect(questions).toHaveLength(2)
|
||||
expect(questions[0])!.toHaveTextContent('What is Dify?')
|
||||
expect(questions[1])!.toHaveTextContent('How to use it?')
|
||||
expect(questions[0]).toHaveAccessibleName('What is Dify?')
|
||||
expect(questions[1]).toHaveAccessibleName('How to use it?')
|
||||
})
|
||||
|
||||
it('should call onSend when a question is clicked', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<SuggestedQuestions item={mockItem} />)
|
||||
|
||||
const questions = screen.getAllByTestId('suggested-question')
|
||||
await user.click(questions[0]!)
|
||||
await user.click(screen.getByRole('button', { name: 'What is Dify?' }))
|
||||
|
||||
expect(mockOnSend).toHaveBeenCalledWith('What is Dify?')
|
||||
})
|
||||
|
||||
it.each([
|
||||
['Enter', '{Enter}'],
|
||||
['Space', ' '],
|
||||
])('should send a question with the %s key', async (_, key) => {
|
||||
const user = userEvent.setup()
|
||||
render(<SuggestedQuestions item={mockItem} />)
|
||||
|
||||
const question = screen.getByRole('button', { name: 'What is Dify?' })
|
||||
question.focus()
|
||||
await user.keyboard(key)
|
||||
|
||||
expect(mockOnSend).toHaveBeenCalledWith('What is Dify?')
|
||||
})
|
||||
|
||||
it('should not render if isOpeningStatement is false', () => {
|
||||
render(<SuggestedQuestions item={{ ...mockItem, isOpeningStatement: false }} />)
|
||||
expect(screen.queryByTestId('suggested-question')).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should not render if suggestedQuestions is missing or empty', () => {
|
||||
render(<SuggestedQuestions item={{ ...mockItem, suggestedQuestions: [] }} />)
|
||||
expect(screen.queryByTestId('suggested-question')).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button')).not.toBeInTheDocument()
|
||||
|
||||
// Use 'as IChatItem' instead of 'as any'
|
||||
render(
|
||||
<SuggestedQuestions item={{ ...mockItem, suggestedQuestions: undefined } as IChatItem} />,
|
||||
)
|
||||
expect(screen.queryByTestId('suggested-question')).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should be disabled and not call onSend when readonly is true', async () => {
|
||||
const user = userEvent.setup()
|
||||
// Use 'as Mock' instead of 'as any'
|
||||
;(useChatContext as Mock).mockReturnValue({
|
||||
onSend: mockOnSend,
|
||||
readonly: true,
|
||||
@@ -75,11 +84,10 @@ describe('SuggestedQuestions', () => {
|
||||
|
||||
render(<SuggestedQuestions item={mockItem} />)
|
||||
|
||||
const questions = screen.getAllByTestId('suggested-question')
|
||||
expect(questions[0])!.toHaveClass('pointer-events-none')
|
||||
expect(questions[0])!.toHaveClass('opacity-50')
|
||||
const question = screen.getByRole('button', { name: 'What is Dify?' })
|
||||
expect(question).toBeDisabled()
|
||||
|
||||
await user.click(questions[0]!)
|
||||
await user.click(question)
|
||||
expect(mockOnSend).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -19,17 +19,18 @@ const SuggestedQuestions: FC<SuggestedQuestionsProps> = ({ item }) => {
|
||||
{suggestedQuestions
|
||||
.filter((q) => !!q && q.trim())
|
||||
.map((question, index) => (
|
||||
<div
|
||||
<button
|
||||
type="button"
|
||||
key={index}
|
||||
className={cn(
|
||||
'mt-1 mr-1 inline-flex max-w-full shrink-0 cursor-pointer flex-wrap rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-3.5 py-2 system-sm-medium text-components-button-secondary-accent-text shadow-xs last:mr-0 hover:border-components-button-secondary-border-hover hover:bg-components-button-secondary-bg-hover',
|
||||
'mt-1 mr-1 inline-flex max-w-full shrink-0 cursor-pointer appearance-none flex-wrap rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg px-3.5 py-2 text-start system-sm-medium text-components-button-secondary-accent-text shadow-xs last:mr-0 hover:border-components-button-secondary-border-hover hover:bg-components-button-secondary-bg-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden',
|
||||
readonly && 'pointer-events-none opacity-50',
|
||||
)}
|
||||
onClick={() => !readonly && onSend?.(question)}
|
||||
data-testid="suggested-question"
|
||||
disabled={readonly}
|
||||
onClick={() => onSend?.(question)}
|
||||
>
|
||||
{question}
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user