dify/web/app/components/base/prompt-editor/plugins/component-picker-block/prompt-option.spec.tsx

132 lines
4.4 KiB
TypeScript

import { createEvent, fireEvent, render, screen } from '@testing-library/react'
import { PromptMenuItem } from './prompt-option'
describe('PromptMenuItem', () => {
const defaultProps = {
icon: <span data-testid="test-icon">icon</span>,
title: 'Test Option',
isSelected: false,
onClick: vi.fn(),
onMouseEnter: vi.fn(),
}
beforeEach(() => {
vi.clearAllMocks()
})
describe('Rendering', () => {
it('should render the icon and title correctly', () => {
render(<PromptMenuItem {...defaultProps} />)
expect(screen.getByTestId('test-icon')).toBeInTheDocument()
expect(screen.getByText('Test Option')).toBeInTheDocument()
})
it('should have the correct display name', () => {
expect(PromptMenuItem.displayName).toBe('PromptMenuItem')
})
})
describe('Styling and States', () => {
it('should apply selected styles when isSelected is true and not disabled', () => {
const { container } = render(<PromptMenuItem {...defaultProps} isSelected={true} />)
const menuDiv = container.firstChild as HTMLElement
expect(menuDiv.className).toContain('!bg-state-base-hover')
expect(menuDiv.className).toContain('cursor-pointer')
expect(menuDiv.className).not.toContain('cursor-not-allowed')
})
it('should apply disabled styles and ignore isSelected when disabled is true', () => {
const { container } = render(
<PromptMenuItem {...defaultProps} isSelected={true} disabled={true} />,
)
const menuDiv = container.firstChild as HTMLElement
expect(menuDiv.className).toContain('cursor-not-allowed')
expect(menuDiv.className).toContain('opacity-30')
expect(menuDiv.className).not.toContain('!bg-state-base-hover')
})
it('should render with default styles when not selected and not disabled', () => {
const { container } = render(<PromptMenuItem {...defaultProps} />)
const menuDiv = container.firstChild as HTMLElement
expect(menuDiv.className).toContain('cursor-pointer')
expect(menuDiv.className).not.toContain('!bg-state-base-hover')
expect(menuDiv.className).not.toContain('cursor-not-allowed')
})
})
describe('Interactions', () => {
describe('onClick', () => {
it('should call onClick when not disabled', () => {
render(<PromptMenuItem {...defaultProps} />)
fireEvent.click(screen.getByText('Test Option'))
expect(defaultProps.onClick).toHaveBeenCalledTimes(1)
})
it('should NOT call onClick when disabled', () => {
render(<PromptMenuItem {...defaultProps} disabled={true} />)
fireEvent.click(screen.getByText('Test Option'))
expect(defaultProps.onClick).not.toHaveBeenCalled()
})
})
describe('onMouseEnter', () => {
it('should call onMouseEnter when not disabled', () => {
render(<PromptMenuItem {...defaultProps} />)
fireEvent.mouseEnter(screen.getByText('Test Option'))
expect(defaultProps.onMouseEnter).toHaveBeenCalledTimes(1)
})
it('should NOT call onMouseEnter when disabled', () => {
render(<PromptMenuItem {...defaultProps} disabled={true} />)
fireEvent.mouseEnter(screen.getByText('Test Option'))
expect(defaultProps.onMouseEnter).not.toHaveBeenCalled()
})
})
describe('onMouseDown', () => {
it('should prevent default and stop propagation', () => {
render(<PromptMenuItem {...defaultProps} />)
const element = screen.getByText('Test Option').parentElement!
// Use createEvent to properly spy on preventDefault and stopPropagation
const mouseDownEvent = createEvent.mouseDown(element)
const preventDefault = vi.fn()
const stopPropagation = vi.fn()
mouseDownEvent.preventDefault = preventDefault
mouseDownEvent.stopPropagation = stopPropagation
fireEvent(element, mouseDownEvent)
expect(preventDefault).toHaveBeenCalled()
expect(stopPropagation).toHaveBeenCalled()
})
})
})
describe('Reference Management', () => {
it('should call setRefElement with the div element if provided', () => {
const setRefElement = vi.fn()
const { container } = render(
<PromptMenuItem {...defaultProps} setRefElement={setRefElement} />,
)
const menuDiv = container.firstChild
expect(setRefElement).toHaveBeenCalledWith(menuDiv)
})
})
})