furniture-3d-system-Wu/tests/lib/install-order-rules.test.ts

262 lines
10 KiB
TypeScript

/**
* InstallOrderRulesEngine 单元测试
*/
import {
InstallOrderRulesEngine,
InstallStepItem,
InstallOrderRule,
HardwareCategory,
PanelCategory,
} from '@/lib/3d/install-order-rules'
describe('InstallOrderRulesEngine', () => {
let engine: InstallOrderRulesEngine
beforeEach(() => {
engine = new InstallOrderRulesEngine()
})
describe('规则管理', () => {
it('应该加载内置规则', () => {
const rules = engine.getRules()
expect(rules.length).toBeGreaterThan(0)
})
it('应该能添加自定义规则', () => {
const customRule: InstallOrderRule = {
id: 'custom-rule',
name: '自定义规则',
description: '测试用',
priority: 100,
condition: () => false,
getOrder: (item) => item.originalOrder,
}
const initialCount = engine.getRules().length
engine.addRule(customRule)
expect(engine.getRules().length).toBe(initialCount + 1)
})
it('添加规则后应该按优先级排序', () => {
const highPriorityRule: InstallOrderRule = {
id: 'high-priority',
name: '高优先级',
description: '',
priority: 1,
condition: () => false,
getOrder: (item) => item.originalOrder,
}
engine.addRule(highPriorityRule)
const rules = engine.getRules()
expect(rules[0].id).toBe('high-priority')
})
it('应该能移除规则', () => {
const rules = engine.getRules()
const firstRuleId = rules[0].id
const result = engine.removeRule(firstRuleId)
expect(result).toBe(true)
expect(engine.getRules().find(r => r.id === firstRuleId)).toBeUndefined()
})
it('移除不存在的规则应该返回 false', () => {
const result = engine.removeRule('not-exist')
expect(result).toBe(false)
})
})
describe('合页-门板排序', () => {
it('合页应该在门板之前', () => {
const items: InstallStepItem[] = [
{ id: 'door-1', type: 'panel', category: 'door', name: '门板', originalOrder: 1 },
{ id: 'hinge-1', type: 'hardware', category: 'hinge', name: '合页', parentPanelId: 'door-1', originalOrder: 2 },
]
const sorted = engine.sortInstallSteps(items)
const hingeIndex = sorted.findIndex(i => i.id === 'hinge-1')
const doorIndex = sorted.findIndex(i => i.id === 'door-1')
expect(hingeIndex).toBeLessThan(doorIndex)
})
it('多个合页都应该在门板之前', () => {
const items: InstallStepItem[] = [
{ id: 'door-1', type: 'panel', category: 'door', name: '门板', originalOrder: 1 },
{ id: 'hinge-1', type: 'hardware', category: 'hinge', name: '合页1', parentPanelId: 'door-1', originalOrder: 3 },
{ id: 'hinge-2', type: 'hardware', category: 'hinge', name: '合页2', parentPanelId: 'door-1', originalOrder: 4 },
]
const sorted = engine.sortInstallSteps(items)
const doorIndex = sorted.findIndex(i => i.id === 'door-1')
sorted
.filter(i => i.category === 'hinge')
.forEach(hinge => {
const hingeIndex = sorted.findIndex(i => i.id === hinge.id)
expect(hingeIndex).toBeLessThan(doorIndex)
})
})
})
describe('滑轨-抽屉排序', () => {
it('滑轨应该在抽屉面板之前', () => {
const items: InstallStepItem[] = [
{ id: 'drawer-front', type: 'panel', category: 'drawer-front', name: '抽屉面板', originalOrder: 1 },
{ id: 'slide-1', type: 'hardware', category: 'slide', name: '滑轨', parentPanelId: 'drawer-front', originalOrder: 2 },
]
const sorted = engine.sortInstallSteps(items)
const slideIndex = sorted.findIndex(i => i.id === 'slide-1')
const drawerIndex = sorted.findIndex(i => i.id === 'drawer-front')
expect(slideIndex).toBeLessThan(drawerIndex)
})
})
describe('把手排序', () => {
it('门板上的把手应该在门板之后', () => {
const items: InstallStepItem[] = [
{ id: 'door-1', type: 'panel', category: 'door', name: '门板', originalOrder: 2 },
{ id: 'handle-1', type: 'hardware', category: 'handle', name: '把手', parentPanelId: 'door-1', originalOrder: 1 },
]
const sorted = engine.sortInstallSteps(items)
const handleIndex = sorted.findIndex(i => i.id === 'handle-1')
const doorIndex = sorted.findIndex(i => i.id === 'door-1')
expect(handleIndex).toBeGreaterThan(doorIndex)
})
})
describe('验证功能', () => {
it('正确的顺序应该通过验证', () => {
const items: InstallStepItem[] = [
{ id: 'hinge-1', type: 'hardware', category: 'hinge', name: '合页', parentPanelId: 'door-1', originalOrder: 1 },
{ id: 'door-1', type: 'panel', category: 'door', name: '门板', originalOrder: 2 },
]
const sorted = engine.sortInstallSteps(items)
const result = engine.validateOrder(sorted)
expect(result.valid).toBe(true)
expect(result.warnings.length).toBe(0)
})
it('错误的顺序应该产生警告', () => {
// 直接创建一个错误顺序的列表(跳过排序)
const items = [
{ id: 'door-1', type: 'panel' as const, category: 'door' as const, name: '门板', originalOrder: 1, finalOrder: 1 },
{ id: 'hinge-1', type: 'hardware' as const, category: 'hinge' as const, name: '合页', parentPanelId: 'door-1', originalOrder: 2, finalOrder: 2 },
]
const result = engine.validateOrder(items)
expect(result.valid).toBe(false)
expect(result.warnings.length).toBeGreaterThan(0)
})
})
describe('类型推断', () => {
describe('inferHardwareCategory', () => {
const testCases: Array<{ code: string; name: string; expected: HardwareCategory }> = [
{ code: 'HINGE-001', name: '铰链', expected: 'hinge' },
{ code: 'HG-001', name: '合页', expected: 'hinge' },
{ code: 'SLIDE-001', name: '滑轨', expected: 'slide' },
{ code: 'DR-001', name: '导轨', expected: 'slide' },
{ code: 'CON-001', name: '连接件', expected: 'connector' },
{ code: 'HANDLE-001', name: '把手', expected: 'handle' },
{ code: 'LS-001', name: '拉手', expected: 'handle' },
{ code: 'LOCK-001', name: '锁', expected: 'lock' },
{ code: 'DMP-001', name: '阻尼器', expected: 'damper' },
{ code: 'BF-001', name: '缓冲器', expected: 'damper' },
{ code: 'SUP-001', name: '支撑件', expected: 'support' },
{ code: 'SCR-001', name: '螺丝', expected: 'screw' },
{ code: 'M4X20', name: '螺钉', expected: 'screw' },
{ code: 'ABC-001', name: '未知类型', expected: 'other' },
]
testCases.forEach(({ code, name, expected }) => {
it(`应该将 "${code}" / "${name}" 识别为 "${expected}"`, () => {
const result = InstallOrderRulesEngine.inferHardwareCategory(code, name)
expect(result).toBe(expected)
})
})
})
describe('inferPanelCategory', () => {
const testCases: Array<{ name: string; expected: PanelCategory }> = [
{ name: '门板', expected: 'door' },
{ name: 'Door Panel', expected: 'door' },
{ name: '抽屉面板', expected: 'drawer-front' },
{ name: '抽屉侧板', expected: 'drawer-side' },
{ name: '抽屉背板', expected: 'drawer-back' },
{ name: '抽屉底板', expected: 'drawer-bottom' },
{ name: '层板', expected: 'shelf' },
{ name: 'Shelf', expected: 'shelf' },
{ name: '侧板', expected: 'side' },
{ name: '顶板', expected: 'top' },
{ name: '底板', expected: 'bottom' },
{ name: '背板', expected: 'back' },
{ name: '隔板', expected: 'partition' },
{ name: '未知板材', expected: 'other' },
]
testCases.forEach(({ name, expected }) => {
it(`应该将 "${name}" 识别为 "${expected}"`, () => {
const result = InstallOrderRulesEngine.inferPanelCategory(name)
expect(result).toBe(expected)
})
})
})
})
describe('复杂场景', () => {
it('完整的门板安装顺序', () => {
const items: InstallStepItem[] = [
{ id: 'side-1', type: 'panel', category: 'side', name: '侧板', originalOrder: 1 },
{ id: 'door-1', type: 'panel', category: 'door', name: '门板', originalOrder: 2 },
{ id: 'hinge-1', type: 'hardware', category: 'hinge', name: '合页', parentPanelId: 'door-1', originalOrder: 3 },
{ id: 'handle-1', type: 'hardware', category: 'handle', name: '把手', parentPanelId: 'door-1', originalOrder: 4 },
{ id: 'damper-1', type: 'hardware', category: 'damper', name: '阻尼器', parentPanelId: 'door-1', originalOrder: 5 },
]
const sorted = engine.sortInstallSteps(items)
// 验证顺序:侧板 -> 合页 -> 门板 -> (阻尼器/把手)
const sideIndex = sorted.findIndex(i => i.id === 'side-1')
const hingeIndex = sorted.findIndex(i => i.id === 'hinge-1')
const doorIndex = sorted.findIndex(i => i.id === 'door-1')
const handleIndex = sorted.findIndex(i => i.id === 'handle-1')
expect(sideIndex).toBeLessThan(hingeIndex)
expect(hingeIndex).toBeLessThan(doorIndex)
expect(doorIndex).toBeLessThan(handleIndex)
})
it('完整的抽屉安装顺序', () => {
const items: InstallStepItem[] = [
{ id: 'side-1', type: 'panel', category: 'side', name: '侧板', originalOrder: 1 },
{ id: 'drawer-front', type: 'panel', category: 'drawer-front', name: '抽屉面板', originalOrder: 2 },
{ id: 'slide-1', type: 'hardware', category: 'slide', name: '滑轨', parentPanelId: 'drawer-front', originalOrder: 3 },
{ id: 'handle-1', type: 'hardware', category: 'handle', name: '把手', parentPanelId: 'drawer-front', originalOrder: 4 },
]
const sorted = engine.sortInstallSteps(items)
// 验证顺序:侧板 -> 滑轨 -> 抽屉面板 -> 把手
const sideIndex = sorted.findIndex(i => i.id === 'side-1')
const slideIndex = sorted.findIndex(i => i.id === 'slide-1')
const drawerIndex = sorted.findIndex(i => i.id === 'drawer-front')
expect(sideIndex).toBeLessThan(slideIndex)
expect(slideIndex).toBeLessThan(drawerIndex)
})
})
})