diff --git a/frontend/src/components/canvas/edges/__tests__/HomelableEdge.label.test.tsx b/frontend/src/components/canvas/edges/__tests__/HomelableEdge.label.test.tsx new file mode 100644 index 0000000..1468e4e --- /dev/null +++ b/frontend/src/components/canvas/edges/__tests__/HomelableEdge.label.test.tsx @@ -0,0 +1,70 @@ +import { describe, it, expect, vi } from 'vitest' +import { render } from '@testing-library/react' +import { ReactFlowProvider } from '@xyflow/react' +import type { EdgeProps, Edge } from '@xyflow/react' +import type { EdgeData } from '@/types' + +/** + * Issue #183 — connection labels must support multiple lines. + * + * The label is a free-text string; newlines entered in the EdgeModal textarea + * are stored verbatim. The rendered label div must preserve those newlines + * (`whitespace-pre-line`) instead of collapsing them into a single line. + * + * normally portals into a node that only exists inside a + * full host, so we stub it to a passthrough to render the label + * markup directly. + */ +vi.mock('@xyflow/react', async (importOriginal) => { + const actual = await importOriginal() + return { + ...actual, + EdgeLabelRenderer: ({ children }: { children: React.ReactNode }) => <>{children}, + } +}) + +const { HomelableEdge } = await import('../index') + +function renderEdge(data: Partial = {}) { + const props = { + id: 'e1', + source: 'a', + target: 'b', + sourceX: 0, + sourceY: 0, + targetX: 100, + targetY: 100, + sourcePosition: 'bottom', + targetPosition: 'top', + data: { type: 'ethernet', ...data } as EdgeData, + selected: false, + } as unknown as EdgeProps> + + return render( + + + + + , + ) +} + +describe('HomelableEdge label', () => { + it('renders the label text', () => { + const { getByText } = renderEdge({ label: 'uplink' }) + expect(getByText('uplink')).toBeTruthy() + }) + + it('preserves newlines in the rendered label (issue #183)', () => { + const { container } = renderEdge({ label: 'line one\nline two' }) + const label = Array.from(container.querySelectorAll('div.whitespace-pre-line')).find((d) => + d.textContent === 'line one\nline two', + ) + expect(label).toBeTruthy() + }) + + it('renders no label div when label is empty', () => { + const { container } = renderEdge({ label: undefined }) + expect(container.querySelector('div.whitespace-pre-line')).toBeNull() + }) +}) diff --git a/frontend/src/components/canvas/edges/index.tsx b/frontend/src/components/canvas/edges/index.tsx index b7e6afd..bae77b8 100644 --- a/frontend/src/components/canvas/edges/index.tsx +++ b/frontend/src/components/canvas/edges/index.tsx @@ -406,7 +406,7 @@ export function HomelableEdge({ id, source, target, sourceHandleId, targetHandle {data?.label && (
- - Label (optional, multi-line) +