import { render, fireEvent } from '@testing-library/react'
import { mockShowToast } from '~/__mocks__/taroMock'
import CancelReasonDialog from '@/components/common/CancelReasonDialog'
describe('CancelReasonDialog', () => {
const defaultProps = {
open: true,
onOpenChange: jest.fn(),
onConfirm: jest.fn(),
loading: false
}
beforeEach(() => {
jest.clearAllMocks()
})
it('应该渲染对话框当可见时为true', () => {
const { getByText, getAllByText } = render()
expect(getByText('取消订单')).toBeTruthy()
expect(getByText('请选择或填写取消原因,这将帮助我们改进服务')).toBeTruthy()
expect(getByText('我不想买了')).toBeTruthy()
expect(getByText('信息填写错误,重新下单')).toBeTruthy()
expect(getByText('商家缺货')).toBeTruthy()
expect(getByText('价格不合适')).toBeTruthy()
// 有多个"其他原因"文本,使用getAllByText
expect(getAllByText('其他原因').length).toBeGreaterThan(0)
})
it('不应该渲染对话框当open为false时', () => {
const { queryByText } = render(
)
expect(queryByText('取消订单')).toBeNull()
})
it.each([
'我不想买了',
'信息填写错误,重新下单',
'商家缺货',
'价格不合适',
'其他原因'
])('应该选择预定义原因 %s 当点击时', (reason) => {
const { getByTestId } = render()
const reasonOption = getByTestId(`cancel-reason-${reason}`)
fireEvent.click(reasonOption)
const confirmButton = getByTestId('confirm-cancel-button')
fireEvent.click(confirmButton)
expect(defaultProps.onConfirm).toHaveBeenCalledWith(reason)
})
it('应该调用onConfirm当确认按钮被点击时', () => {
const { getByTestId } = render()
const reasonOption = getByTestId('cancel-reason-我不想买了')
fireEvent.click(reasonOption)
const confirmButton = getByTestId('confirm-cancel-button')
fireEvent.click(confirmButton)
expect(defaultProps.onConfirm).toHaveBeenCalledWith('我不想买了')
})
it('应该调用onOpenChange当取消按钮被点击时', () => {
const { getByText } = render()
const cancelButton = getByText('取消')
fireEvent.click(cancelButton)
expect(defaultProps.onOpenChange).toHaveBeenCalledWith(false)
})
it('应该显示错误当确认空原因时', () => {
const { getByTestId, getByText } = render()
const confirmButton = getByTestId('confirm-cancel-button')
fireEvent.click(confirmButton)
// 使用更精确的查询方式查找错误消息
const errorMessage = getByText('请输入取消原因')
expect(errorMessage).toBeTruthy()
expect(defaultProps.onConfirm).not.toHaveBeenCalled()
})
it('应该显示错误当原因超过200字符时', () => {
const { getByPlaceholderText, getByTestId, getByText } = render(
)
const input = getByPlaceholderText('请输入其他取消原因...')
fireEvent.input(input, { target: { value: 'a'.repeat(201) } })
const confirmButton = getByTestId('confirm-cancel-button')
fireEvent.click(confirmButton)
const errorMessage = getByText('取消原因不能超过200个字符')
expect(errorMessage).toBeTruthy()
expect(defaultProps.onConfirm).not.toHaveBeenCalled()
})
it('应该处理自定义原因输入', () => {
const { getByPlaceholderText, getByTestId } = render(
)
const input = getByPlaceholderText('请输入其他取消原因...')
fireEvent.input(input, { target: { value: '自定义取消原因' } })
const confirmButton = getByTestId('confirm-cancel-button')
fireEvent.click(confirmButton)
expect(defaultProps.onConfirm).toHaveBeenCalledWith('自定义取消原因')
})
it('应该显示加载状态当loading为true时', () => {
const { getByTestId } = render(
)
const confirmButton = getByTestId('confirm-cancel-button')
expect(confirmButton).toHaveTextContent('提交中...')
})
it('应该禁用按钮当loading为true时', () => {
const { getByText, getByTestId } = render(
)
const cancelButton = getByText('取消')
const confirmButton = getByTestId('confirm-cancel-button')
// 检查按钮是否被禁用
expect(cancelButton).toBeTruthy()
expect(confirmButton).toBeTruthy()
})
it('应该重置状态当对话框关闭时', () => {
const { getByTestId, getByText, rerender } = render(
)
const reasonOption = getByTestId('cancel-reason-我不想买了')
fireEvent.click(reasonOption)
// 重新渲染关闭的对话框
rerender()
// 重新渲染打开的对话框
rerender()
// 检查状态是否重置 - 直接点击确认按钮应该显示错误
const confirmButton = getByTestId('confirm-cancel-button')
fireEvent.click(confirmButton)
const errorMessage = getByText('请输入取消原因')
expect(errorMessage).toBeTruthy()
})
})