gongxiangp2/components/upload/BatchFileList.video-preview.test.tsx
2026-08-13 12:09:14 +08:00

286 lines
9.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* eslint-disable @next/next/no-img-element, jsx-a11y/alt-text */
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import BatchFileList from './BatchFileList'
import { BatchVideoList } from './SpecialBatchUploadUI'
function createPngFile(name: string, width = 1920, height = 1080) {
const bytes = new Uint8Array(24)
bytes.set([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
const view = new DataView(bytes.buffer)
view.setUint32(16, width)
view.setUint32(20, height)
return new File([bytes], name, { type: 'image/png' })
}
jest.mock('next/image', () => ({
__esModule: true,
default: (props: any) => {
const { fill, unoptimized, sizes, ...rest } = props
return <img {...rest} />
},
}))
test('无法从视频文件名确认 SPU 时直接显示可恢复的填写提示', () => {
render(
<BatchFileList
batchFiles={[{
id: 'video-missing-spu',
file: new File(['video'], '抖音素材-624-456.mp4', { type: 'video/mp4' }),
expanded: true,
productModel: '',
categoryName: '通用',
sceneName: '通用',
platformName: '',
productCategoryName: '',
}]}
materialType="抖音-千川素材"
categories={[]}
scenes={[]}
platforms={[]}
productCategories={[]}
renderer=""
batchPreviewDragging={{}}
onToggleExpand={jest.fn()}
onDelete={jest.fn()}
onUpdateProductModel={jest.fn()}
onUpdatePreviewImage={jest.fn()}
onRemovePreviewImage={jest.fn()}
onUpdateCategory={jest.fn()}
onUpdateScene={jest.fn()}
onUpdatePlatform={jest.fn()}
onUpdateProductCategory={jest.fn()}
onUpdateRenderer={jest.fn()}
onExitBatchMode={jest.fn()}
onPreviewDragEnter={jest.fn()}
onPreviewDragLeave={jest.fn()}
onValidationError={jest.fn()}
/>,
)
expect(screen.getByText(/未识别到 SPU,请填写/)).toBeInTheDocument()
const input = screen.getByRole('textbox', { name: 'SPU型号 *' })
expect(input).toHaveAttribute('aria-invalid', 'true')
expect(input).toHaveAccessibleDescription(/纯数字或 “-624-456” 这类文件编号不能作为 SPU/)
})
test('批量视频的每个文件都提供独立的选填预览图入口', async () => {
const onUpdatePreviewImage = jest.fn().mockResolvedValue(undefined)
render(
<BatchFileList
batchFiles={[{
id: 'video-1',
file: new File(['video'], 'SPU001.mp4', { type: 'video/mp4' }),
expanded: true,
productModel: 'SPU001',
categoryName: '通用',
sceneName: '通用',
platformName: '',
productCategoryName: '',
}]}
materialType="淘系-逛逛视频"
categories={[]}
scenes={[]}
platforms={[]}
productCategories={[]}
renderer=""
batchPreviewDragging={{}}
onToggleExpand={jest.fn()}
onDelete={jest.fn()}
onUpdateProductModel={jest.fn()}
onUpdatePreviewImage={onUpdatePreviewImage}
onRemovePreviewImage={jest.fn()}
onUpdateCategory={jest.fn()}
onUpdateScene={jest.fn()}
onUpdatePlatform={jest.fn()}
onUpdateProductCategory={jest.fn()}
onUpdateRenderer={jest.fn()}
onExitBatchMode={jest.fn()}
onPreviewDragEnter={jest.fn()}
onPreviewDragLeave={jest.fn()}
onValidationError={jest.fn()}
/>,
)
expect(screen.getByText('视频预览图')).toBeInTheDocument()
expect(screen.getByText('(选填)')).toBeInTheDocument()
expect(screen.queryByText('预览图片 *')).not.toBeInTheDocument()
const input = screen.getByLabelText(/视频预览图/) as HTMLInputElement
const cover = createPngFile('SPU001-cover.png')
fireEvent.change(input, { target: { files: [cover] } })
await waitFor(() => expect(onUpdatePreviewImage).toHaveBeenCalledWith(0, cover))
})
test('淘系-逛逛视频专用批量列表也提供独立的选填预览图入口', async () => {
const onUpdatePreviewImage = jest.fn().mockResolvedValue(undefined)
render(
<BatchVideoList
files={[{
file: new File(['video'], 'SPU002.mp4', { type: 'video/mp4' }),
productModel: 'SPU002',
}]}
productCategories={[]}
onUpdateProductModel={jest.fn()}
onUpdatePreviewImage={onUpdatePreviewImage}
onRemovePreviewImage={jest.fn()}
onValidationError={jest.fn()}
onDelete={jest.fn()}
/>,
)
expect(screen.getByText('视频预览图')).toBeInTheDocument()
expect(screen.getByText('(选填)')).toBeInTheDocument()
const input = screen.getByLabelText(/视频预览图/) as HTMLInputElement
const cover = createPngFile('SPU002-cover.png')
fireEvent.change(input, { target: { files: [cover] } })
await waitFor(() => expect(onUpdatePreviewImage).toHaveBeenCalledWith(0, cover))
})
test('通用和专用批量入口都在创建预览前拒绝超大像素图片', async () => {
const hugeCover = createPngFile('huge-cover.png', 10_000, 7_000)
const generalUpdate = jest.fn()
const generalError = jest.fn()
const generalView = render(
<BatchFileList
batchFiles={[{
id: 'video-huge-general',
file: new File(['video'], 'SPU-HUGE-1.mp4', { type: 'video/mp4' }),
expanded: true,
productModel: 'SPU-HUGE-1',
categoryName: '通用',
sceneName: '通用',
platformName: '',
productCategoryName: '',
}]}
materialType="淘系-逛逛视频"
categories={[]}
scenes={[]}
platforms={[]}
productCategories={[]}
renderer=""
batchPreviewDragging={{}}
onToggleExpand={jest.fn()}
onDelete={jest.fn()}
onUpdateProductModel={jest.fn()}
onUpdatePreviewImage={generalUpdate}
onRemovePreviewImage={jest.fn()}
onUpdateCategory={jest.fn()}
onUpdateScene={jest.fn()}
onUpdatePlatform={jest.fn()}
onUpdateProductCategory={jest.fn()}
onUpdateRenderer={jest.fn()}
onExitBatchMode={jest.fn()}
onPreviewDragEnter={jest.fn()}
onPreviewDragLeave={jest.fn()}
onValidationError={generalError}
/>,
)
fireEvent.change(screen.getByLabelText(/视频预览图/), {
target: { files: [hugeCover] },
})
await waitFor(() => expect(generalError).toHaveBeenLastCalledWith(
expect.stringContaining('像素总量超过 60,000,000'),
))
expect(generalUpdate).not.toHaveBeenCalled()
generalView.unmount()
const specialUpdate = jest.fn()
const specialError = jest.fn()
render(
<BatchVideoList
files={[{
file: new File(['video'], 'SPU-HUGE-2.mp4', { type: 'video/mp4' }),
productModel: 'SPU-HUGE-2',
}]}
productCategories={[]}
onUpdateProductModel={jest.fn()}
onUpdatePreviewImage={specialUpdate}
onRemovePreviewImage={jest.fn()}
onValidationError={specialError}
onDelete={jest.fn()}
/>,
)
fireEvent.change(screen.getByLabelText(/视频预览图/), {
target: { files: [hugeCover] },
})
await waitFor(() => expect(specialError).toHaveBeenLastCalledWith(
expect.stringContaining('像素总量超过 60,000,000'),
))
expect(specialUpdate).not.toHaveBeenCalled()
})
test('上传期间锁定通用批量视频的元数据和删除操作', () => {
render(
<BatchFileList
batchFiles={[{
id: 'video-disabled-1',
file: new File(['video'], 'SPU003.mp4', { type: 'video/mp4' }),
expanded: true,
productModel: 'SPU003',
categoryName: '通用',
sceneName: '通用',
platformName: '',
productCategoryName: '',
}]}
materialType="淘系-逛逛视频"
categories={[]}
scenes={[]}
platforms={[]}
productCategories={[]}
renderer=""
disabled
batchPreviewDragging={{}}
onToggleExpand={jest.fn()}
onDelete={jest.fn()}
onUpdateProductModel={jest.fn()}
onUpdatePreviewImage={jest.fn()}
onRemovePreviewImage={jest.fn()}
onUpdateCategory={jest.fn()}
onUpdateScene={jest.fn()}
onUpdatePlatform={jest.fn()}
onUpdateProductCategory={jest.fn()}
onUpdateRenderer={jest.fn()}
onExitBatchMode={jest.fn()}
onPreviewDragEnter={jest.fn()}
onPreviewDragLeave={jest.fn()}
onValidationError={jest.fn()}
/>,
)
expect(screen.getByRole('textbox', { name: 'SPU型号 *' })).toBeDisabled()
expect(screen.getByRole('button', { name: '删除' })).toBeDisabled()
expect(screen.getByRole('button', { name: '退出批量模式' })).toBeDisabled()
expect(screen.getByLabelText(/视频预览图/)).toBeDisabled()
})
test('上传期间锁定专用批量视频的 SPU、品类和删除操作', () => {
render(
<BatchVideoList
files={[{
file: new File(['video'], 'SPU004.mp4', { type: 'video/mp4' }),
productModel: 'SPU004',
productCategoryName: '沙发',
}]}
productCategories={[{ id: 'category-1', name: '沙发' }]}
disabled
onUpdateProductModel={jest.fn()}
onUpdateProductCategory={jest.fn()}
onUpdatePreviewImage={jest.fn()}
onRemovePreviewImage={jest.fn()}
onValidationError={jest.fn()}
onDelete={jest.fn()}
/>,
)
expect(screen.getByPlaceholderText('SPU型号')).toBeDisabled()
expect(screen.getByRole('combobox', { name: '品类(可选)' })).toBeDisabled()
expect(screen.getByRole('button', { name: '删除' })).toBeDisabled()
expect(screen.getByLabelText(/视频预览图/)).toBeDisabled()
})