import { render, fireEvent } from '@testing-library/react' import Taro from '@tarojs/taro' import CancelReasonDialog from '@/components/common/CancelReasonDialog' // Mock Taro API jest.mock('@tarojs/taro', () => ({ showToast: jest.fn() })) describe('CancelReasonDialog', () => { const defaultProps = { visible: true, onCancel: jest.fn(), onConfirm: jest.fn(), loading: false } beforeEach(() => { jest.clearAllMocks() }) it('should render dialog when visible is true', () => { const { getByText } = render() expect(getByText('取消订单')).toBeTruthy() expect(getByText('请选择或填写取消原因:')).toBeTruthy() expect(getByText('我不想买了')).toBeTruthy() expect(getByText('信息填写错误,重新下单')).toBeTruthy() expect(getByText('商家缺货')).toBeTruthy() expect(getByText('价格不合适')).toBeTruthy() expect(getByText('其他原因')).toBeTruthy() }) it('should not render dialog when visible is false', () => { const { queryByText } = render( ) expect(queryByText('取消订单')).toBeNull() }) it('should select predefined reason when clicked', () => { const { getByText } = render() const reasonOption = getByText('我不想买了') fireEvent.click(reasonOption) // 检查样式变化(这里需要根据实际实现调整) expect(reasonOption).toBeTruthy() }) it('should call onConfirm with reason when confirm button is clicked', () => { const { getByText } = render() const reasonOption = getByText('我不想买了') fireEvent.click(reasonOption) const confirmButton = getByText('确认取消') fireEvent.click(confirmButton) expect(defaultProps.onConfirm).toHaveBeenCalledWith('我不想买了') }) it('should call onCancel when cancel button is clicked', () => { const { getByText } = render() const cancelButton = getByText('取消') fireEvent.click(cancelButton) expect(defaultProps.onCancel).toHaveBeenCalled() }) it('should show error when confirming with empty reason', () => { const mockShowToast = Taro.showToast as jest.Mock const { getByText } = render() const confirmButton = getByText('确认取消') fireEvent.click(confirmButton) expect(mockShowToast).toHaveBeenCalledWith({ title: '请填写取消原因', icon: 'error', duration: 2000 }) expect(defaultProps.onConfirm).not.toHaveBeenCalled() }) it('should show error when reason exceeds 500 characters', () => { const mockShowToast = Taro.showToast as jest.Mock const { getByPlaceholderText, getByText } = render( ) const input = getByPlaceholderText('请输入其他取消原因...') fireEvent.input(input, { target: { value: 'a'.repeat(501) } }) const confirmButton = getByText('确认取消') fireEvent.click(confirmButton) expect(mockShowToast).toHaveBeenCalledWith({ title: '取消原因不能超过500字', icon: 'error', duration: 2000 }) expect(defaultProps.onConfirm).not.toHaveBeenCalled() }) it('should handle custom reason input', () => { const { getByPlaceholderText, getByText } = render( ) const input = getByPlaceholderText('请输入其他取消原因...') fireEvent.input(input, { target: { value: '自定义取消原因' } }) const confirmButton = getByText('确认取消') fireEvent.click(confirmButton) expect(defaultProps.onConfirm).toHaveBeenCalledWith('自定义取消原因') }) it('should show loading state when loading is true', () => { const { getByText } = render( ) expect(getByText('提交中...')).toBeTruthy() }) it('should disable buttons when loading is true', () => { const { getByText } = render( ) const cancelButton = getByText('取消') const confirmButton = getByText('提交中...') // 检查按钮是否被禁用(这里需要根据实际实现调整) expect(cancelButton).toBeTruthy() expect(confirmButton).toBeTruthy() }) it('should reset state when dialog is closed', () => { const { getByText, rerender } = render( ) const reasonOption = getByText('我不想买了') fireEvent.click(reasonOption) // 重新渲染关闭的对话框 rerender() rerender() // 检查状态是否重置 const confirmButton = getByText('确认取消') fireEvent.click(confirmButton) expect(Taro.showToast).toHaveBeenCalledWith({ title: '请填写取消原因', icon: 'error', duration: 2000 }) }) })