WuYongJie 5821d73291 初始提交:3D家具安装展示系统
包含:
- furniture-3d-system:Next.js 16 全栈应用(资产中心、产品管理、3D装配动画)
- autocad-plugin:AutoCAD 家具导出插件源码
- 资产中心改造:编辑弹窗化、删除功能、Toast反馈、自定义Select组件

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 14:00:19 +08:00

144 lines
4.6 KiB
TypeScript

import { describe, it, expect } from '@jest/globals'
import { SKUUploadService } from '@/server/services/sku-upload.service'
function buildBaseFormData(): FormData {
const formData = new FormData()
formData.append('productId', 'product-1')
formData.append('skuCode', 'SKU-001')
formData.append('attributes', JSON.stringify({ 颜色: '白色' }))
return formData
}
describe('SKUUploadService', () => {
it('应该在缺少 panels 时根据 holes 自动补齐板件', async () => {
const service = new SKUUploadService()
const formData = buildBaseFormData()
formData.append('holesData', JSON.stringify({
pluginVersion: '2.2.14',
holes: [
{
panelId: 'panel_A',
position: [100, 200, 0],
normal: [0, 0, 1],
diameter: 5,
depth: 10,
},
{
panelId: 'panel_A',
position: [320, 260, 0],
normal: [0, 0, 1],
diameter: 5,
depth: 10,
},
],
panels: [],
}))
const result = await service.prepareCreatePayload(formData)
expect(result.cadHoles).toHaveLength(2)
expect(result.cadPanels).toHaveLength(1)
expect(result.cadPanels[0].id).toBe('panel_A')
expect(result.cadPanels[0].panelType).toBe('panel')
expect(result.cadPanels[0].size[0]).toBeGreaterThan(0)
expect(result.cadPanels[0].size[1]).toBeGreaterThan(0)
expect(result.cadPanels[0].size[2]).toBeGreaterThan(0)
})
it('应该对 panelId 去空白并避免重复补板', async () => {
const service = new SKUUploadService()
const formData = buildBaseFormData()
formData.append('holesData', JSON.stringify({
pluginVersion: '2.2.14',
holes: [
{
panelId: ' Cabinet/Panel_01 ',
position: [10, 20, 0],
normal: [0, 0, 1],
diameter: 5,
depth: 10,
},
],
panels: [
{
id: 'cabinet/panel_01',
panelType: 'side_panel',
size: [1000, 500, 18],
},
],
}))
const result = await service.prepareCreatePayload(formData)
expect(result.cadPanels).toHaveLength(1)
expect(result.cadPanels[0].id).toBe('cabinet/panel_01')
expect(result.cadHoles[0].panelId).toBe('Cabinet/Panel_01')
})
it('应该允许 holes 为空但仍保存板件数据(有些板件本身无孔位)', async () => {
const service = new SKUUploadService()
const formData = buildBaseFormData()
formData.append('holesData', JSON.stringify({
pluginVersion: '2.2.14',
holes: [],
panels: [
{
id: 'panel_no_holes',
panelType: 'panel',
size: [600, 400, 18],
},
],
}))
const result = await service.prepareCreatePayload(formData)
expect(result.cadHoles).toHaveLength(0)
expect(result.cadPanels).toHaveLength(1)
expect(result.cadPanels[0].id).toBe('panel_no_holes')
})
it('应该在 holes/panels/hardwareSummary 都为空时给出明确错误', async () => {
const service = new SKUUploadService()
const formData = buildBaseFormData()
formData.append('holesData', JSON.stringify({
pluginVersion: '2.2.14',
holes: [],
panels: [],
}))
await expect(service.prepareCreatePayload(formData)).rejects.toThrow(
'hardware.json 未包含可导入的孔位/板件/五金统计数据'
)
})
it('应该在数值字段非法时抛出可读错误', async () => {
const service = new SKUUploadService()
const formData = buildBaseFormData()
formData.append('price', 'abc')
await expect(service.prepareCreatePayload(formData)).rejects.toThrow('销售价格必须是非负数字')
})
it('应该允许可转换模型源文件超过 50MB 但不超过 200MB', () => {
const service = new SKUUploadService() as unknown as {
ensureSourceModelFileSize: (file: File, ext: string) => void
}
const oversizedObj = new File([new Uint8Array(1)], 'demo.obj')
Object.defineProperty(oversizedObj, 'size', { value: 55 * 1024 * 1024 })
expect(() => service.ensureSourceModelFileSize(oversizedObj, '.obj')).not.toThrow()
})
it('应该在转换后模型仍超过 50MB 时抛出更准确的错误', () => {
const service = new SKUUploadService() as unknown as {
ensureProcessedModelFileSize: (file: File, ext: string) => void
}
const convertedFile = new File([new Uint8Array(1)], 'demo.glb')
Object.defineProperty(convertedFile, 'size', { value: 55 * 1024 * 1024 })
expect(() => service.ensureProcessedModelFileSize(convertedFile, '.obj')).toThrow(
'转换后的模型文件大小超过限制'
)
})
})