|
|
@@ -0,0 +1,301 @@
|
|
|
+import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
|
+import { PhotoUploadField } from '../../src/components/PhotoUploadField';
|
|
|
+import { toast } from 'sonner';
|
|
|
+
|
|
|
+// Mock toast
|
|
|
+vi.mock('sonner', () => ({
|
|
|
+ toast: {
|
|
|
+ warning: vi.fn(),
|
|
|
+ success: vi.fn(),
|
|
|
+ error: vi.fn(),
|
|
|
+ },
|
|
|
+}));
|
|
|
+
|
|
|
+// Mock FileSelector
|
|
|
+vi.mock('@d8d/file-management-ui/components', () => ({
|
|
|
+ FileSelector: ({ value, onChange, accept, filterType, placeholder, showPreview, previewSize }: any) => (
|
|
|
+ <div data-testid="file-selector">
|
|
|
+ <button
|
|
|
+ data-testid="file-selector-button"
|
|
|
+ onClick={() => onChange?.(123)}
|
|
|
+ >
|
|
|
+ {placeholder || '选择文件'}
|
|
|
+ </button>
|
|
|
+ <div data-testid="file-selector-accept">{accept}</div>
|
|
|
+ <div data-testid="file-selector-filter-type">{filterType}</div>
|
|
|
+ <div data-testid="file-selector-preview">{showPreview ? 'show' : 'hide'}</div>
|
|
|
+ <div data-testid="file-selector-preview-size">{previewSize}</div>
|
|
|
+ </div>
|
|
|
+ ),
|
|
|
+}));
|
|
|
+
|
|
|
+describe('PhotoUploadField', () => {
|
|
|
+ beforeEach(() => {
|
|
|
+ vi.clearAllMocks();
|
|
|
+ });
|
|
|
+
|
|
|
+ const defaultProps = {
|
|
|
+ value: [],
|
|
|
+ onChange: vi.fn(),
|
|
|
+ photoTypes: ['身份证照片', '残疾证照片', '个人照片', '其他照片'],
|
|
|
+ };
|
|
|
+
|
|
|
+ it('应该正确渲染组件', () => {
|
|
|
+ render(<PhotoUploadField {...defaultProps} />);
|
|
|
+
|
|
|
+ expect(screen.getByText('照片上传')).toBeInTheDocument();
|
|
|
+ expect(screen.getByTestId('add-photo-button')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('暂无照片')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('点击"添加照片"按钮上传照片')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该添加照片', () => {
|
|
|
+ render(<PhotoUploadField {...defaultProps} />);
|
|
|
+
|
|
|
+ const addButton = screen.getByTestId('add-photo-button');
|
|
|
+ fireEvent.click(addButton);
|
|
|
+
|
|
|
+ expect(defaultProps.onChange).toHaveBeenCalledWith([
|
|
|
+ expect.objectContaining({
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: null,
|
|
|
+ canDownload: 0,
|
|
|
+ })
|
|
|
+ ]);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该添加多张照片(无限制)', () => {
|
|
|
+ render(<PhotoUploadField {...defaultProps} />);
|
|
|
+
|
|
|
+ const addButton = screen.getByTestId('add-photo-button');
|
|
|
+
|
|
|
+ // 添加5张照片(原来限制是5张)
|
|
|
+ for (let i = 0; i < 5; i++) {
|
|
|
+ fireEvent.click(addButton);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 应该可以添加超过5张照片
|
|
|
+ fireEvent.click(addButton);
|
|
|
+
|
|
|
+ expect(defaultProps.onChange).toHaveBeenCalledTimes(6);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该支持自定义最大照片数量', () => {
|
|
|
+ render(<PhotoUploadField {...defaultProps} maxPhotos={3} />);
|
|
|
+
|
|
|
+ const addButton = screen.getByTestId('add-photo-button');
|
|
|
+
|
|
|
+ // 添加3张照片
|
|
|
+ for (let i = 0; i < 3; i++) {
|
|
|
+ fireEvent.click(addButton);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 尝试添加第4张照片应该显示警告
|
|
|
+ fireEvent.click(addButton);
|
|
|
+
|
|
|
+ expect(toast.warning).toHaveBeenCalledWith('最多只能上传 3 张照片');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该移除照片', () => {
|
|
|
+ const initialValue = [
|
|
|
+ {
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ tempId: 'temp-1',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ photoType: '残疾证照片',
|
|
|
+ fileId: 456,
|
|
|
+ canDownload: 0,
|
|
|
+ tempId: 'temp-2',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ render(<PhotoUploadField {...defaultProps} value={initialValue} />);
|
|
|
+
|
|
|
+ // 找到并点击删除按钮
|
|
|
+ const deleteButtons = screen.getAllByRole('button', { name: '' });
|
|
|
+ const firstDeleteButton = deleteButtons.find(button =>
|
|
|
+ button.innerHTML.includes('Trash2')
|
|
|
+ );
|
|
|
+
|
|
|
+ if (firstDeleteButton) {
|
|
|
+ fireEvent.click(firstDeleteButton);
|
|
|
+ }
|
|
|
+
|
|
|
+ expect(defaultProps.onChange).toHaveBeenCalledWith([
|
|
|
+ expect.objectContaining({
|
|
|
+ photoType: '残疾证照片',
|
|
|
+ fileId: 456,
|
|
|
+ canDownload: 0,
|
|
|
+ })
|
|
|
+ ]);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该更新照片类型', () => {
|
|
|
+ const initialValue = [
|
|
|
+ {
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ tempId: 'temp-1',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ render(<PhotoUploadField {...defaultProps} value={initialValue} />);
|
|
|
+
|
|
|
+ // 找到选择器并更改值
|
|
|
+ const selectTrigger = screen.getByText('身份证照片');
|
|
|
+ fireEvent.click(selectTrigger);
|
|
|
+
|
|
|
+ // 选择新类型
|
|
|
+ const newTypeOption = screen.getByText('残疾证照片');
|
|
|
+ fireEvent.click(newTypeOption);
|
|
|
+
|
|
|
+ expect(defaultProps.onChange).toHaveBeenCalledWith([
|
|
|
+ expect.objectContaining({
|
|
|
+ photoType: '残疾证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ })
|
|
|
+ ]);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该更新文件ID', () => {
|
|
|
+ const initialValue = [
|
|
|
+ {
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: null,
|
|
|
+ canDownload: 1,
|
|
|
+ tempId: 'temp-1',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ render(<PhotoUploadField {...defaultProps} value={initialValue} />);
|
|
|
+
|
|
|
+ // 点击文件选择器按钮
|
|
|
+ const fileSelectorButton = screen.getByTestId('file-selector-button');
|
|
|
+ fireEvent.click(fileSelectorButton);
|
|
|
+
|
|
|
+ expect(defaultProps.onChange).toHaveBeenCalledWith([
|
|
|
+ expect.objectContaining({
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ })
|
|
|
+ ]);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该更新下载权限', () => {
|
|
|
+ const initialValue = [
|
|
|
+ {
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 0,
|
|
|
+ tempId: 'temp-1',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ render(<PhotoUploadField {...defaultProps} value={initialValue} />);
|
|
|
+
|
|
|
+ // 找到开关并切换
|
|
|
+ const switchElement = screen.getByRole('switch');
|
|
|
+ fireEvent.click(switchElement);
|
|
|
+
|
|
|
+ expect(defaultProps.onChange).toHaveBeenCalledWith([
|
|
|
+ expect.objectContaining({
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ })
|
|
|
+ ]);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该显示正确的文件格式和大小限制提示', () => {
|
|
|
+ render(<PhotoUploadField {...defaultProps} />);
|
|
|
+
|
|
|
+ expect(screen.getByText('支持的照片格式:JPG、JPEG、PNG、GIF、BMP、WebP等常见图片格式')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('文件大小限制:无限制(建议不超过500MB)')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该使用正确的文件选择器配置', () => {
|
|
|
+ render(<PhotoUploadField {...defaultProps} />);
|
|
|
+
|
|
|
+ // 添加一张照片以显示文件选择器
|
|
|
+ const addButton = screen.getByTestId('add-photo-button');
|
|
|
+ fireEvent.click(addButton);
|
|
|
+
|
|
|
+ expect(screen.getByTestId('file-selector-accept')).toHaveTextContent('image/*,.jpg,.jpeg,.png,.gif,.bmp,.webp');
|
|
|
+ expect(screen.getByTestId('file-selector-filter-type')).toHaveTextContent('all');
|
|
|
+ expect(screen.getByTestId('file-selector-preview')).toHaveTextContent('show');
|
|
|
+ expect(screen.getByTestId('file-selector-preview-size')).toHaveTextContent('medium');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该显示照片类型标签(无星号)', () => {
|
|
|
+ const initialValue = [
|
|
|
+ {
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ tempId: 'temp-1',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ render(<PhotoUploadField {...defaultProps} value={initialValue} />);
|
|
|
+
|
|
|
+ // 检查照片类型标签没有星号
|
|
|
+ const photoTypeLabel = screen.getByText('照片类型');
|
|
|
+ expect(photoTypeLabel).toBeInTheDocument();
|
|
|
+ expect(photoTypeLabel.innerHTML).not.toContain('*');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该显示照片文件标签(无星号)', () => {
|
|
|
+ const initialValue = [
|
|
|
+ {
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ tempId: 'temp-1',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ render(<PhotoUploadField {...defaultProps} value={initialValue} />);
|
|
|
+
|
|
|
+ // 检查照片文件标签没有星号
|
|
|
+ const photoFileLabel = screen.getByText('照片文件');
|
|
|
+ expect(photoFileLabel).toBeInTheDocument();
|
|
|
+ expect(photoFileLabel.innerHTML).not.toContain('*');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该显示添加更多照片按钮(无数量限制时)', () => {
|
|
|
+ const initialValue = [
|
|
|
+ {
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ tempId: 'temp-1',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ render(<PhotoUploadField {...defaultProps} value={initialValue} />);
|
|
|
+
|
|
|
+ expect(screen.getByText('添加更多照片')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该显示添加更多照片按钮(有数量限制时)', () => {
|
|
|
+ const initialValue = [
|
|
|
+ {
|
|
|
+ photoType: '身份证照片',
|
|
|
+ fileId: 123,
|
|
|
+ canDownload: 1,
|
|
|
+ tempId: 'temp-1',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ render(<PhotoUploadField {...defaultProps} value={initialValue} maxPhotos={5} />);
|
|
|
+
|
|
|
+ expect(screen.getByText('添加更多照片(1/5)')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+});
|