194 lines
7.1 KiB
TypeScript
194 lines
7.1 KiB
TypeScript
import { render, screen, waitFor, within } from '@testing-library/react'
|
|
import userEvent from '@testing-library/user-event'
|
|
|
|
import ProductPackageUploader from '@/components/upload/ProductPackageUploader'
|
|
|
|
const mockAddCategory = jest.fn()
|
|
const mockAddScene = jest.fn()
|
|
|
|
jest.mock('@/components/upload/category-handlers', () => ({
|
|
addCategory: (...args: unknown[]) => mockAddCategory(...args),
|
|
addScene: (...args: unknown[]) => mockAddScene(...args),
|
|
}))
|
|
|
|
jest.mock('@/components/upload/DetailImageSorter', () => ({
|
|
__esModule: true,
|
|
default: () => <div data-testid="detail-image-sorter" />,
|
|
}))
|
|
|
|
const defaultProps = {
|
|
onSuccess: jest.fn(),
|
|
onCancel: jest.fn(),
|
|
categories: [
|
|
{ id: 'cat-1', name: '店铺A' },
|
|
{ id: 'cat-2', name: '店铺B' },
|
|
],
|
|
scenes: [
|
|
{ id: 'scene-1', name: '场景A' },
|
|
{ id: 'scene-2', name: '场景B' },
|
|
],
|
|
platforms: [
|
|
{ id: 'platform-1', name: '淘宝' },
|
|
{ id: 'platform-2', name: '天猫' },
|
|
],
|
|
productCategories: [
|
|
{ id: 'pc-1', name: '沙发' },
|
|
{ id: 'pc-2', name: '餐桌' },
|
|
],
|
|
onRefreshCategories: jest.fn().mockResolvedValue(undefined),
|
|
onRefreshScenes: jest.fn().mockResolvedValue(undefined),
|
|
}
|
|
|
|
function installUsersFetch() {
|
|
const fetchMock = jest.fn((input: RequestInfo | URL) => {
|
|
const url = String(input)
|
|
if (url === '/api/users/list') {
|
|
return Promise.resolve({
|
|
ok: true,
|
|
json: async () => [
|
|
{ id: 'requester-1', username: 'operator-a', displayName: '运营甲' },
|
|
{ id: 'requester-2', username: 'operator-b', displayName: '运营乙' },
|
|
],
|
|
})
|
|
}
|
|
return Promise.reject(new Error(`测试未处理请求:${url}`))
|
|
})
|
|
global.fetch = fetchMock as unknown as typeof fetch
|
|
return fetchMock
|
|
}
|
|
|
|
async function renderUploader() {
|
|
render(<ProductPackageUploader {...defaultProps} />)
|
|
await screen.findByPlaceholderText('搜索发起本次出图需求的运营人员')
|
|
}
|
|
|
|
describe('ProductPackageUploader compact layout interactions', () => {
|
|
const originalFetch = global.fetch
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
installUsersFetch()
|
|
|
|
mockAddCategory.mockImplementation(async (
|
|
name: string,
|
|
onSuccess?: (category: { id: string; name: string }) => Promise<void> | void,
|
|
) => {
|
|
await onSuccess?.({ id: 'cat-new', name })
|
|
})
|
|
mockAddScene.mockImplementation(async (
|
|
name: string,
|
|
onSuccess?: (scene: { id: string; name: string }) => Promise<void> | void,
|
|
) => {
|
|
await onSuccess?.({ id: 'scene-new', name })
|
|
})
|
|
})
|
|
|
|
afterAll(() => {
|
|
global.fetch = originalFetch
|
|
})
|
|
|
|
it('需求运营标签可访问,真实 UploadForm 的 SPU 品类 店铺 场景 平台字段仍可用', async () => {
|
|
const user = userEvent.setup()
|
|
await renderUploader()
|
|
|
|
const requester = screen.getByLabelText(/需求运营/) as HTMLInputElement
|
|
expect(requester).toBeInTheDocument()
|
|
await user.click(requester)
|
|
await user.type(requester, '运营甲')
|
|
await user.click(screen.getByRole('option', { name: /运营甲/ }))
|
|
expect(requester).toHaveValue('运营甲 (operator-a)')
|
|
|
|
const productModel = screen.getByLabelText(/SPU型号/) as HTMLInputElement
|
|
await user.type(productModel, 'df-a3dz0008')
|
|
expect(productModel).toHaveValue('DF-A3DZ0008')
|
|
|
|
await user.selectOptions(screen.getByLabelText(/品类/), '沙发')
|
|
expect(screen.getByLabelText(/品类/)).toHaveValue('沙发')
|
|
|
|
await user.selectOptions(screen.getByLabelText(/使用店铺/), '店铺B')
|
|
expect(screen.getByLabelText(/使用店铺/)).toHaveValue('店铺B')
|
|
|
|
await user.selectOptions(screen.getByLabelText(/场景类别/), '场景A')
|
|
expect(screen.getByLabelText(/场景类别/)).toHaveValue('场景A')
|
|
|
|
await user.selectOptions(screen.getByLabelText(/平台分类/), '淘宝')
|
|
expect(screen.getByLabelText(/平台分类/)).toHaveValue('淘宝')
|
|
})
|
|
|
|
it('内联新建店铺和场景输入可打开、添加、取消', async () => {
|
|
const user = userEvent.setup()
|
|
await renderUploader()
|
|
|
|
await user.click(screen.getByRole('button', { name: '新建店铺' }))
|
|
const categoryInput = screen.getByPlaceholderText('输入新店铺名称')
|
|
await user.type(categoryInput, '新店铺C')
|
|
await user.click(screen.getByRole('button', { name: '添加' }))
|
|
|
|
await waitFor(() => expect(mockAddCategory).toHaveBeenCalled())
|
|
expect(mockAddCategory).toHaveBeenCalledWith(
|
|
'新店铺C',
|
|
expect.any(Function),
|
|
expect.any(Function),
|
|
)
|
|
expect(defaultProps.onRefreshCategories).toHaveBeenCalled()
|
|
expect(screen.queryByPlaceholderText('输入新店铺名称')).not.toBeInTheDocument()
|
|
|
|
await user.click(screen.getByRole('button', { name: '新建场景' }))
|
|
const sceneInput = screen.getByPlaceholderText('输入新场景类别')
|
|
await user.type(sceneInput, '新场景C')
|
|
await user.click(within(sceneInput.parentElement as HTMLElement).getByRole('button', { name: '取消' }))
|
|
|
|
expect(screen.queryByPlaceholderText('输入新场景类别')).not.toBeInTheDocument()
|
|
expect(mockAddScene).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('新品只能公开,优化时才可选私密,切回新品会恢复公开', async () => {
|
|
const user = userEvent.setup()
|
|
await renderUploader()
|
|
|
|
const demandType = screen.getByLabelText(/需求类型/) as HTMLSelectElement
|
|
const visibility = screen.getByLabelText(/可见性/) as HTMLSelectElement
|
|
const privateOption = screen.getByRole('option', { name: '私密' }) as HTMLOptionElement
|
|
|
|
expect(demandType.value).toBe('新品')
|
|
expect(visibility.value).toBe('public')
|
|
expect(privateOption.disabled).toBe(true)
|
|
expect(screen.getByText(/新品固定公开,仅优化需求支持私密/)).toBeInTheDocument()
|
|
|
|
await user.selectOptions(demandType, '优化')
|
|
expect(privateOption.disabled).toBe(false)
|
|
expect(screen.getByText('私密仅所选需求运营及已授权权限组可访问,上传人不自动放行。')).toBeInTheDocument()
|
|
|
|
await user.selectOptions(visibility, 'private')
|
|
expect(visibility.value).toBe('private')
|
|
|
|
await user.selectOptions(demandType, '新品')
|
|
expect(visibility.value).toBe('public')
|
|
expect(privateOption.disabled).toBe(true)
|
|
})
|
|
|
|
it('四类文件选择入口都存在', async () => {
|
|
await renderUploader()
|
|
|
|
expect(screen.getByLabelText('主图')).toBeInTheDocument()
|
|
expect(screen.getByLabelText('SKU图')).toBeInTheDocument()
|
|
expect(screen.getByLabelText('详情图')).toBeInTheDocument()
|
|
expect(screen.getByLabelText(/PSD源文件/)).toBeInTheDocument()
|
|
})
|
|
|
|
it('校验失败时将错误提示滚动到可见位置', async () => {
|
|
const original = HTMLElement.prototype.scrollIntoView
|
|
const scrollIntoView = jest.fn()
|
|
HTMLElement.prototype.scrollIntoView = scrollIntoView
|
|
try {
|
|
const user = userEvent.setup()
|
|
await renderUploader()
|
|
await user.click(screen.getByRole('button', { name: '提交', exact: true }))
|
|
expect(screen.getByRole('alert')).toHaveTextContent('请选择需求运营人员')
|
|
expect(scrollIntoView).toHaveBeenCalledWith({ block: 'nearest' })
|
|
} finally {
|
|
HTMLElement.prototype.scrollIntoView = original
|
|
}
|
|
})
|
|
})
|