dify/web/app/components/base/prompt-log-modal/__tests__/index.spec.tsx
2026-03-12 15:09:10 +08:00

106 lines
3.5 KiB
TypeScript

import { fireEvent, render, screen } from '@testing-library/react'
import { useClickAway } from 'ahooks'
import PromptLogModal from '..'
let clickAwayHandlers: (() => void)[] = []
vi.mock('ahooks', async (importOriginal) => {
const actual = await importOriginal<typeof import('ahooks')>()
return {
...actual,
useClickAway: vi.fn((fn: () => void) => {
clickAwayHandlers.push(fn)
}),
}
})
describe('PromptLogModal', () => {
const defaultProps = {
width: 1000,
onCancel: vi.fn(),
currentLogItem: {
id: '1',
content: 'test',
log: [{ role: 'user', text: 'Hello' }],
} as unknown as Parameters<typeof PromptLogModal>[0]['currentLogItem'],
}
beforeEach(() => {
vi.clearAllMocks()
clickAwayHandlers = []
})
describe('Render', () => {
it('renders correctly when currentLogItem is provided', () => {
render(<PromptLogModal {...defaultProps} />)
expect(screen.getByText('PROMPT LOG')).toBeInTheDocument()
expect(screen.getByText('Hello')).toBeInTheDocument()
})
it('returns null when currentLogItem is missing', () => {
const { container } = render(<PromptLogModal {...defaultProps} currentLogItem={undefined} />)
expect(container.firstChild).toBeNull()
})
it('renders copy feedback when log length is 1', () => {
render(<PromptLogModal {...defaultProps} />)
expect(screen.getByTestId('close-btn-container')).toBeInTheDocument()
})
it('renders multiple logs in Card correctly', () => {
const props = {
...defaultProps,
currentLogItem: {
...defaultProps.currentLogItem,
log: [
{ role: 'user', text: 'Hello' },
{ role: 'assistant', text: 'Hi there' },
],
},
} as unknown as Parameters<typeof PromptLogModal>[0]
render(<PromptLogModal {...props} />)
expect(screen.getByText('USER')).toBeInTheDocument()
expect(screen.getByText('ASSISTANT')).toBeInTheDocument()
expect(screen.getByText('Hi there')).toBeInTheDocument()
})
it('returns null when currentLogItem.log is missing', () => {
const { container } = render(<PromptLogModal {...defaultProps} currentLogItem={{ id: '1' } as unknown as Parameters<typeof PromptLogModal>[0]['currentLogItem']} />)
expect(container.firstChild).toBeNull()
})
})
describe('Interactions', () => {
it('calls onCancel when close button is clicked', () => {
render(<PromptLogModal {...defaultProps} />)
const closeBtn = screen.getByTestId('close-btn')
expect(closeBtn).toBeInTheDocument()
fireEvent.click(closeBtn)
expect(defaultProps.onCancel).toHaveBeenCalled()
})
it('calls onCancel when clicking outside', async () => {
const onCancel = vi.fn()
render(
<PromptLogModal {...defaultProps} onCancel={onCancel} />,
)
expect(useClickAway).toHaveBeenCalled()
expect(clickAwayHandlers.length).toBeGreaterThan(0)
// Call the last registered handler (simulating click away)
clickAwayHandlers[clickAwayHandlers.length - 1]()
expect(onCancel).toHaveBeenCalled()
})
it('does not call onCancel when clicking outside if not mounted', () => {
const onCancel = vi.fn()
render(<PromptLogModal {...defaultProps} onCancel={onCancel} />)
expect(clickAwayHandlers.length).toBeGreaterThan(0)
// The first handler in the array is captured during the initial render before useEffect runs
clickAwayHandlers[0]()
expect(onCancel).not.toHaveBeenCalled()
})
})
})