362 lines
11 KiB
TypeScript
362 lines
11 KiB
TypeScript
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 }) => <a href={href}>{children}</a>,
|
|
}))
|
|
|
|
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
|
|
}) => (
|
|
<div>
|
|
<div>{rightDrawerContent}</div>
|
|
<div>辅助拼装工作台</div>
|
|
<div>库存:{value.inventory.length}</div>
|
|
<div>节点:{value.nodes.length}</div>
|
|
<div>首个规格款:{value.inventory[0]?.selectedVariantId ?? 'none'}</div>
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
onChange({
|
|
...value,
|
|
nodes: [
|
|
{
|
|
nodeId: 'node-desktop-1',
|
|
role: 'desktop',
|
|
label: '桌面板',
|
|
assetFamilyId: 'family-board-1',
|
|
variantId: 'variant-board-1',
|
|
code: 'BOARD-A-001',
|
|
name: '桌面A',
|
|
modelUrl: '/board.glb',
|
|
thumbnailUrl: null,
|
|
position: [0, 720, 0],
|
|
rotation: [0, 0, 0],
|
|
scale: [1, 1, 1],
|
|
zone: 'main',
|
|
source: 'desktop',
|
|
inventoryId: value.inventory[0]?.inventoryId ?? 'desktop:family-board-1:1',
|
|
slotKey: 'desktop-1',
|
|
roleRecommendation: 'desktop',
|
|
roleConfirmed: 'desktop',
|
|
weakSlot: { role: 'desktop', parentRolePath: null, instanceIndex: 1 },
|
|
targetPosition: [0, 720, 0],
|
|
targetRotation: [0, 0, 0],
|
|
isSnapped: true,
|
|
subassemblyId: null,
|
|
mountPoints: [],
|
|
assemblyBasis: { anchor: 'desktop-center' },
|
|
compatibilityRules: null,
|
|
materialConfig: null,
|
|
},
|
|
],
|
|
validation: {
|
|
level: 'PASSED',
|
|
blockingIssues: [],
|
|
warnings: [],
|
|
},
|
|
})
|
|
}
|
|
>
|
|
准备可保存工作台
|
|
</button>
|
|
</div>
|
|
),
|
|
}))
|
|
|
|
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(
|
|
<AssistedAssemblyClient
|
|
families={[
|
|
{
|
|
id: 'family-board-1',
|
|
type: 'BOARD',
|
|
code: 'BOARD-A',
|
|
name: '桌面A',
|
|
productCategoryId: 'category-desk',
|
|
productCategoryName: '书桌',
|
|
} as never,
|
|
{
|
|
id: 'family-leg-1',
|
|
type: 'COMPONENT',
|
|
code: 'LEG-A',
|
|
name: '桌腿A',
|
|
productCategoryId: 'category-desk',
|
|
productCategoryName: '书桌',
|
|
} as never,
|
|
]}
|
|
variants={[
|
|
{
|
|
id: 'variant-board-1',
|
|
assetFamilyId: 'family-board-1',
|
|
assetType: 'BOARD',
|
|
code: 'BOARD-A-001',
|
|
name: '桌面A',
|
|
status: 'AVAILABLE',
|
|
modelUrl: '/board.glb',
|
|
thumbnailUrl: null,
|
|
dimensions: {},
|
|
mountPoints: [],
|
|
assemblyBasis: { anchor: 'desktop-center' },
|
|
compatibilityRules: null,
|
|
} as never,
|
|
{
|
|
id: 'variant-leg-1',
|
|
assetFamilyId: 'family-leg-1',
|
|
assetType: 'COMPONENT',
|
|
code: 'LEG-A-001',
|
|
name: '桌腿A',
|
|
status: 'AVAILABLE',
|
|
modelUrl: '/leg.glb',
|
|
thumbnailUrl: null,
|
|
dimensions: {},
|
|
mountPoints: [{ name: 'origin', position: [0, 0, 0] }],
|
|
assemblyBasis: { attachTo: 'desktop' },
|
|
compatibilityRules: { allowedSlots: ['frontLeftLeg'] },
|
|
} as never,
|
|
]}
|
|
metrics={[]}
|
|
/>,
|
|
)
|
|
|
|
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(
|
|
<AssistedAssemblyClient
|
|
families={[
|
|
{
|
|
id: 'family-board-1',
|
|
type: 'BOARD',
|
|
code: 'BOARD-A',
|
|
name: '桌面A',
|
|
productCategoryId: 'category-desk',
|
|
productCategoryName: '书桌',
|
|
} as never,
|
|
]}
|
|
variants={[
|
|
{
|
|
id: 'variant-board-1',
|
|
assetFamilyId: 'family-board-1',
|
|
assetType: 'BOARD',
|
|
code: 'BOARD-A-001',
|
|
name: '桌面A',
|
|
status: 'AVAILABLE',
|
|
modelUrl: '/board.glb',
|
|
thumbnailUrl: null,
|
|
dimensions: {},
|
|
mountPoints: [],
|
|
assemblyBasis: { anchor: 'desktop-center' },
|
|
compatibilityRules: null,
|
|
} as never,
|
|
]}
|
|
metrics={[]}
|
|
/>,
|
|
)
|
|
|
|
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(
|
|
<AssistedAssemblyClient
|
|
families={[
|
|
{
|
|
id: 'family-board-draft',
|
|
type: 'BOARD',
|
|
code: 'BOARD-DRAFT',
|
|
name: '草稿桌面',
|
|
status: 'DRAFT',
|
|
productCategoryId: 'category-desk',
|
|
productCategoryName: '书桌',
|
|
} as never,
|
|
]}
|
|
variants={[
|
|
{
|
|
id: 'variant-board-draft',
|
|
assetFamilyId: 'family-board-draft',
|
|
assetType: 'BOARD',
|
|
code: 'BOARD-DRAFT-001',
|
|
name: '草稿桌面规格款',
|
|
status: 'DRAFT',
|
|
modelUrl: '/board-draft.glb',
|
|
thumbnailUrl: null,
|
|
dimensions: {},
|
|
mountPoints: [],
|
|
assemblyBasis: { anchor: 'desktop-center' },
|
|
compatibilityRules: null,
|
|
} as never,
|
|
]}
|
|
metrics={[]}
|
|
/>,
|
|
)
|
|
|
|
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(
|
|
<AssistedAssemblyClient
|
|
families={[
|
|
{
|
|
id: 'family-board-source',
|
|
type: 'BOARD',
|
|
code: 'BOARD-SOURCE',
|
|
name: '源桌面',
|
|
status: 'AVAILABLE',
|
|
productCategoryId: 'category-desk',
|
|
productCategoryName: '书桌',
|
|
} as never,
|
|
{
|
|
id: 'family-board-extra',
|
|
type: 'BOARD',
|
|
code: 'BOARD-EXTRA',
|
|
name: '额外桌面',
|
|
status: 'AVAILABLE',
|
|
productCategoryId: 'category-desk',
|
|
productCategoryName: '书桌',
|
|
} as never,
|
|
]}
|
|
variants={[
|
|
{
|
|
id: 'variant-board-source',
|
|
assetFamilyId: 'family-board-source',
|
|
assetType: 'BOARD',
|
|
code: 'BOARD-SOURCE-001',
|
|
name: '源桌面规格款',
|
|
status: 'AVAILABLE',
|
|
modelUrl: '/board-source.glb',
|
|
thumbnailUrl: null,
|
|
dimensions: {},
|
|
mountPoints: [],
|
|
assemblyBasis: { anchor: 'desktop-center' },
|
|
compatibilityRules: null,
|
|
} as never,
|
|
{
|
|
id: 'variant-board-extra',
|
|
assetFamilyId: 'family-board-extra',
|
|
assetType: 'BOARD',
|
|
code: 'BOARD-EXTRA-001',
|
|
name: '额外桌面规格款',
|
|
status: 'AVAILABLE',
|
|
modelUrl: '/board-extra.glb',
|
|
thumbnailUrl: null,
|
|
dimensions: {},
|
|
mountPoints: [],
|
|
assemblyBasis: { anchor: 'desktop-center' },
|
|
compatibilityRules: null,
|
|
} as never,
|
|
]}
|
|
metrics={[]}
|
|
/>,
|
|
)
|
|
|
|
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')
|
|
})
|
|
})
|
|
})
|