import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import type { ReactNode } from 'react'
import AssistedAssemblyClient from './AssistedAssemblyClient'
import { createDraftGroup } from '@/lib/open-product/platform-api'
import type { AssemblyWorkspaceSnapshot } from '@/lib/open-product/assembly-workspace'
let mockSearchParams = new URLSearchParams()
jest.mock('next/link', () => ({
__esModule: true,
default: ({ href, children }: { href: string; children: ReactNode }) => {children},
}))
const push = jest.fn()
jest.mock('next/navigation', () => ({
useRouter: () => ({ push }),
useSearchParams: () => mockSearchParams,
}))
jest.mock('@/components/platform/AssemblyWorkbenchV2', () => ({
__esModule: true,
AssemblyWorkbenchV2: ({
value,
onChange,
rightDrawerContent,
}: {
value: AssemblyWorkspaceSnapshot
onChange: (next: AssemblyWorkspaceSnapshot) => void
rightDrawerContent?: ReactNode
}) => (
{rightDrawerContent}
辅助拼装工作台
库存:{value.inventory.length}
节点:{value.nodes.length}
首个规格款:{value.inventory[0]?.selectedVariantId ?? 'none'}
),
}))
jest.mock('@/lib/open-product/platform-api', () => ({
__esModule: true,
createDraftGroup: jest.fn(),
}))
describe('AssistedAssemblyClient', () => {
beforeEach(() => {
push.mockReset()
jest.mocked(createDraftGroup).mockReset()
mockSearchParams = new URLSearchParams()
})
it('默认会预选当前品类下的最新资产族,且调整选择后会同步到辅助拼装工作台', async () => {
const actor = userEvent.setup()
render(
,
)
expect(screen.getByText('辅助拼装工作台')).toBeInTheDocument()
expect(screen.getByText('库存:2')).toBeInTheDocument()
await actor.click(screen.getByRole('button', { name: '支撑组件' }))
await actor.click(screen.getByRole('button', { name: /桌腿A/ }))
await waitFor(() => {
expect(screen.getByText('库存:1')).toBeInTheDocument()
})
await actor.click(screen.getByRole('button', { name: /桌腿A/ }))
await waitFor(() => {
expect(screen.getByText('库存:2')).toBeInTheDocument()
})
})
it('保存草稿组时会发送去模板化后的辅助拼装输入', async () => {
const actor = userEvent.setup()
jest.mocked(createDraftGroup).mockResolvedValue({
draftGroup: { id: 'draft-group-1' },
} as never)
render(
,
)
await actor.click(screen.getByRole('button', { name: /准备可保存工作台/ }))
await actor.clear(screen.getByLabelText('草稿组名称'))
await actor.type(screen.getByLabelText('草稿组名称'), '测试草稿组')
await actor.click(screen.getByRole('button', { name: /仅保存草稿/ }))
await waitFor(() => {
expect(createDraftGroup).toHaveBeenCalledWith(
expect.objectContaining({
categoryId: 'category-desk',
assemblies: [
expect.objectContaining({
source: 'assisted-assembly',
}),
],
}),
)
})
expect(jest.mocked(createDraftGroup).mock.calls[0]?.[0]).not.toHaveProperty('seriesTemplateId')
})
it('资产中心带料进入时,会保留来源资产族并保留草稿规格款作为默认选择', async () => {
const actor = userEvent.setup()
mockSearchParams = new URLSearchParams(
'entryMode=asset-center&source=asset-center&desktopFamilyIds=family-board-draft',
)
render(
,
)
await waitFor(() => {
expect(screen.getByText('辅助拼装工作台')).toBeInTheDocument()
expect(screen.getByText('库存:1')).toBeInTheDocument()
expect(screen.getByText('首个规格款:variant-board-draft')).toBeInTheDocument()
})
await actor.click(screen.getByRole('button', { name: '板件资产' }))
await waitFor(() => {
expect(screen.getByRole('button', { name: /草稿桌面/ })).toHaveAttribute('aria-pressed', 'true')
})
})
it('源 SKU 新增进入时,只预选来源装配涉及的资产族,不会回退成全量默认选中', async () => {
const actor = userEvent.setup()
mockSearchParams = new URLSearchParams(
'entryMode=source-sku&source=assisted-assembly&sourceSkuId=sku-source-1&desktopFamilyIds=family-board-source',
)
render(
,
)
await waitFor(() => {
expect(screen.getByText('库存:1')).toBeInTheDocument()
expect(screen.getByText('首个规格款:variant-board-source')).toBeInTheDocument()
})
await actor.click(screen.getByRole('button', { name: '板件资产' }))
await waitFor(() => {
expect(screen.getByRole('button', { name: /源桌面/ })).toHaveAttribute('aria-pressed', 'true')
expect(screen.getByRole('button', { name: /额外桌面/ })).toHaveAttribute('aria-pressed', 'false')
})
})
})