feat(canvas): raise switch port cap to 64, add port numbers and fibre edge type
Issue #20: bump MAX_BOTTOM_HANDLES 48 -> 64 (covers 48+4 SFP switches) and add a per-node "Show Port Numbers" toggle that labels each bottom connection point. Issue #21: add `fibre` as a first-class edge/connection type (bright cyan with a subtle glow) alongside ethernet/wifi/iot/vlan/virtual/cluster - selectable in the edge modal, themeable, registered in the React Flow edgeTypes registry, and round-tripped through YAML import/export. Backport of homelable-hacs PR #23. ha-relevant: yes
This commit is contained in:
@@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest'
|
||||
import { EDGE_DEFAULT_COLORS } from '../edgeColors'
|
||||
import type { EdgeType } from '@/types'
|
||||
|
||||
const EDGE_TYPES: EdgeType[] = ['ethernet', 'wifi', 'iot', 'vlan', 'virtual', 'cluster']
|
||||
const EDGE_TYPES: EdgeType[] = ['ethernet', 'wifi', 'iot', 'vlan', 'virtual', 'cluster', 'fibre']
|
||||
|
||||
describe('EDGE_DEFAULT_COLORS', () => {
|
||||
it('has an entry for every EdgeType', () => {
|
||||
@@ -36,4 +36,8 @@ describe('EDGE_DEFAULT_COLORS', () => {
|
||||
it('cluster default is proxmox orange', () => {
|
||||
expect(EDGE_DEFAULT_COLORS.cluster).toBe('#ff6e00')
|
||||
})
|
||||
|
||||
it('fibre default is bright cyan', () => {
|
||||
expect(EDGE_DEFAULT_COLORS.fibre).toBe('#22d3ee')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -102,6 +102,15 @@ describe('exportCanvasToYaml', () => {
|
||||
expect(entryA).not.toHaveProperty('clusterR')
|
||||
})
|
||||
|
||||
it('serializes a fibre edge with linkType "fibre" (issue #21)', () => {
|
||||
const nodeA = makeNode({ label: 'Switch', type: 'switch' }, 'sw')
|
||||
const nodeB = makeNode({ label: 'Server1', type: 'server' }, 's1')
|
||||
const edge = makeEdge('e1', 'sw', 's1', { type: 'fibre', label: 'sfp0' })
|
||||
const result = yaml.load(exportCanvasToYaml([nodeA, nodeB], [edge])) as Record<string, unknown>[]
|
||||
const entryA = result.find((e) => e.label === 'Switch')!
|
||||
expect(entryA.links).toEqual([{ label: 'Server1', linkType: 'fibre', linkLabel: 'sfp0' }])
|
||||
})
|
||||
|
||||
it('serializes multiple outgoing edges as links array', () => {
|
||||
const sw = makeNode({ label: 'Switch', type: 'switch' }, 'sw')
|
||||
const s1 = makeNode({ label: 'Server1', type: 'server' }, 's1')
|
||||
|
||||
@@ -29,8 +29,12 @@ describe('clampBottomHandles', () => {
|
||||
expect(clampBottomHandles(-5)).toBe(MIN_BOTTOM_HANDLES)
|
||||
})
|
||||
|
||||
it('supports at least 52 ports (issue #20 — Cisco 48+4 SFP)', () => {
|
||||
expect(MAX_BOTTOM_HANDLES).toBeGreaterThanOrEqual(52)
|
||||
})
|
||||
|
||||
it('clamps above MAX to MAX', () => {
|
||||
expect(clampBottomHandles(49)).toBe(MAX_BOTTOM_HANDLES)
|
||||
expect(clampBottomHandles(65)).toBe(MAX_BOTTOM_HANDLES)
|
||||
expect(clampBottomHandles(9999)).toBe(MAX_BOTTOM_HANDLES)
|
||||
})
|
||||
|
||||
@@ -49,6 +53,8 @@ describe('clampBottomHandles', () => {
|
||||
expect(clampBottomHandles(1)).toBe(1)
|
||||
expect(clampBottomHandles(24)).toBe(24)
|
||||
expect(clampBottomHandles(48)).toBe(48)
|
||||
expect(clampBottomHandles(52)).toBe(52)
|
||||
expect(clampBottomHandles(64)).toBe(64)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -89,6 +89,22 @@ describe('parseYamlToCanvas', () => {
|
||||
expect(edges[0].targetHandle).toBe('top-t')
|
||||
})
|
||||
|
||||
it('imports a fibre link type onto the edge (issue #21)', () => {
|
||||
const yaml = `
|
||||
- nodeType: switch
|
||||
label: "SW"
|
||||
links:
|
||||
- label: "SRV"
|
||||
linkType: fibre
|
||||
- nodeType: server
|
||||
label: "SRV"
|
||||
`
|
||||
const { edges } = parseYamlToCanvas(yaml, empty, emptyEdges)
|
||||
expect(edges).toHaveLength(1)
|
||||
expect(edges[0].type).toBe('fibre')
|
||||
expect(edges[0].data?.type).toBe('fibre')
|
||||
})
|
||||
|
||||
it('cluster edges have cluster-right→cluster-left handles', () => {
|
||||
const yaml = `
|
||||
- nodeType: proxmox
|
||||
|
||||
@@ -6,7 +6,7 @@ const NODE_TYPES: NodeType[] = [
|
||||
'isp', 'router', 'firewall', 'switch', 'server', 'proxmox', 'vm', 'lxc',
|
||||
'nas', 'iot', 'ap', 'camera', 'printer', 'computer', 'laptop', 'mobile', 'cpl', 'docker_host', 'docker_container', 'generic', 'groupRect',
|
||||
]
|
||||
const EDGE_TYPES: EdgeType[] = ['ethernet', 'wifi', 'iot', 'vlan', 'virtual', 'cluster']
|
||||
const EDGE_TYPES: EdgeType[] = ['ethernet', 'wifi', 'iot', 'vlan', 'virtual', 'cluster', 'fibre']
|
||||
const STATUS_TYPES: NodeStatus[] = ['online', 'offline', 'pending', 'unknown']
|
||||
|
||||
describe('THEME_ORDER', () => {
|
||||
|
||||
Reference in New Issue
Block a user