109 lines
3.7 KiB
TypeScript
109 lines
3.7 KiB
TypeScript
import { createEvent, fireEvent, render, screen } from '@testing-library/react'
|
|
|
|
import AIOriginalUploader from '@/components/upload/AIOriginalUploader'
|
|
import RealPhotoUploader from '@/components/upload/RealPhotoUploader'
|
|
import TaskPageUploader from '@/components/upload/TaskPageUploader'
|
|
import ThreeDOriginalUploader from '@/components/upload/ThreeDOriginalUploader'
|
|
import VideoScreenshotUploader from '@/components/upload/VideoScreenshotUploader'
|
|
|
|
const defaultProps = {
|
|
onSuccess: jest.fn(),
|
|
onCancel: jest.fn(),
|
|
categories: [],
|
|
scenes: [],
|
|
platforms: [],
|
|
productCategories: [],
|
|
onRefreshCategories: jest.fn(),
|
|
onRefreshScenes: jest.fn(),
|
|
}
|
|
|
|
const uploaders = [
|
|
['AI 原图', AIOriginalUploader],
|
|
['实拍原图', RealPhotoUploader],
|
|
['3D 原图', ThreeDOriginalUploader],
|
|
['视频截图', VideoScreenshotUploader],
|
|
['任务页面', TaskPageUploader],
|
|
] as const
|
|
|
|
describe.each(uploaders)('%s拖拽上传', (_name, Uploader) => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
Object.defineProperty(URL, 'createObjectURL', {
|
|
configurable: true,
|
|
writable: true,
|
|
value: jest.fn(() => 'blob:preview'),
|
|
})
|
|
Object.defineProperty(URL, 'revokeObjectURL', {
|
|
configurable: true,
|
|
writable: true,
|
|
value: jest.fn(),
|
|
})
|
|
})
|
|
|
|
test('经过上传框内部按钮时应保持拖拽高亮', () => {
|
|
const { container } = render(<Uploader {...defaultProps} />)
|
|
const input = container.querySelector('input[type="file"][accept="image/*"][multiple]') as HTMLInputElement
|
|
const dropZone = input.parentElement as HTMLDivElement
|
|
const childButton = dropZone.querySelector('button') as HTMLButtonElement
|
|
|
|
Object.defineProperty(dropZone, 'getBoundingClientRect', {
|
|
configurable: true,
|
|
value: () => ({
|
|
x: 0,
|
|
y: 0,
|
|
top: 0,
|
|
right: 100,
|
|
bottom: 100,
|
|
left: 0,
|
|
width: 100,
|
|
height: 100,
|
|
toJSON: () => ({}),
|
|
}),
|
|
})
|
|
|
|
const dragData = {
|
|
clientX: 20,
|
|
clientY: 20,
|
|
dataTransfer: { files: [], types: ['Files'], dropEffect: 'none' },
|
|
}
|
|
fireEvent.dragEnter(dropZone, dragData)
|
|
fireEvent.dragOver(dropZone, dragData)
|
|
expect(dropZone).toHaveClass('border-blue-500')
|
|
|
|
const internalDragLeave = createEvent.dragLeave(dropZone)
|
|
Object.defineProperties(internalDragLeave, {
|
|
clientX: { value: 50 },
|
|
clientY: { value: 50 },
|
|
relatedTarget: { value: childButton },
|
|
dataTransfer: { value: { files: [], types: ['Files'], dropEffect: 'copy' } },
|
|
})
|
|
fireEvent(dropZone, internalDragLeave)
|
|
expect(dropZone).toHaveClass('border-blue-500')
|
|
|
|
const outerDragLeave = createEvent.dragLeave(dropZone)
|
|
Object.defineProperties(outerDragLeave, {
|
|
clientX: { value: 120 },
|
|
clientY: { value: 50 },
|
|
relatedTarget: { value: document.body },
|
|
dataTransfer: { value: { files: [], types: ['Files'], dropEffect: 'copy' } },
|
|
})
|
|
fireEvent(dropZone, outerDragLeave)
|
|
expect(dropZone).not.toHaveClass('border-blue-500')
|
|
})
|
|
})
|
|
|
|
test('混合拖入有效图片和非法文件时应保留图片并显示错误', () => {
|
|
const { container } = render(<AIOriginalUploader {...defaultProps} />)
|
|
const input = container.querySelector('input[type="file"][accept="image/*"][multiple]') as HTMLInputElement
|
|
const dropZone = input.parentElement as HTMLDivElement
|
|
const image = new File(['image'], 'valid.png', { type: 'image/png' })
|
|
const invalid = new File(['text'], 'invalid.txt', { type: 'text/plain' })
|
|
|
|
fireEvent.drop(dropZone, {
|
|
dataTransfer: { files: [image, invalid], types: ['Files'], dropEffect: 'copy' },
|
|
})
|
|
|
|
expect(screen.getByAltText('原图 1')).toBeInTheDocument()
|
|
expect(screen.getByText(/invalid\.txt/)).toBeInTheDocument()
|
|
})
|