import { describe, it, expect } from 'vitest'; import { NODE_TYPES, getNodeType, nodeTypesByCategory, defaultNodeProps } from '../src/model/nodeTypes'; import { PROPERTY_GROUPS } from '../src/model/properties'; describe('node type registry', () => { it('contains the core pipeline equipment', () => { const ids = NODE_TYPES.map((t) => t.id); for (const expected of ['waterSource', 'pump', 'valve', 'tee', 'tank', 'consumer', 'boiler', 'powerSupply']) { expect(ids).toContain(expected); } }); it('every type has SVG markup, ports and grouped properties', () => { for (const type of NODE_TYPES) { expect(type.svg.length, type.id).toBeGreaterThan(10); expect(type.ports.length, type.id).toBeGreaterThan(0); expect(type.width).toBeGreaterThan(0); const groups = new Set(type.properties.map((p) => p.group)); expect(groups.has('general'), type.id).toBe(true); expect(groups.has('presentation'), type.id).toBe(true); for (const g of groups) { expect(PROPERTY_GROUPS.some((pg) => pg.id === g), `unknown group ${g} in ${type.id}`).toBe(true); } } }); it('port ids are unique per type and positions are normalized 0..1', () => { for (const type of NODE_TYPES) { const ids = type.ports.map((p) => p.id); expect(new Set(ids).size, type.id).toBe(ids.length); for (const port of type.ports) { expect(port.x, `${type.id}.${port.id}`).toBeGreaterThanOrEqual(0); expect(port.x).toBeLessThanOrEqual(1); expect(port.y).toBeGreaterThanOrEqual(0); expect(port.y).toBeLessThanOrEqual(1); } } }); it('groups types by category for the palette', () => { const grouped = nodeTypesByCategory(); expect(grouped.length).toBeGreaterThanOrEqual(5); const total = grouped.reduce((s, g) => s + g.types.length, 0); expect(total).toBe(NODE_TYPES.length); }); it('builds default props including physics values', () => { const props = defaultNodeProps('waterSource'); expect(props.supply).toBe(50); expect(props.title).toBe('Water source'); expect(defaultNodeProps('unknown-type')).toEqual({}); expect(getNodeType('pump')?.simRole).toBe('junction'); }); });