Skip to content

Commit 0549692

Browse files
refactor(agentflow): remove unused components, fix connector anchor bug (#5863)
refactor(agentflow): remove unused components, fix connector anchor bug, and enhance test coverage - Deleted unused Input and ConfirmDialog components to streamline the codebase. - Updated jest.config.js to improve coverage thresholds and exclude deprecated hooks. - Enhanced test coverage for useAgentflow and AgentflowContext with new E2E tests. - Adjusted architecture documentation to reflect the removal of components and updated file structure.
1 parent 86ac9f6 commit 0549692

13 files changed

Lines changed: 549 additions & 278 deletions

File tree

packages/agentflow/ARCHITECTURE.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ src/
3030
```
3131
atoms/
3232
├── MainCard.tsx # Styled card wrapper
33-
├── Input.tsx # Basic input component
34-
├── ConfirmDialog.tsx # Confirmation dialog with context
3533
├── NodeInputHandler.tsx # Form input for node properties
3634
└── index.ts # Central export
3735
```
@@ -157,14 +155,12 @@ infrastructure/
157155
│ ├── client.ts # Axios factory
158156
│ ├── nodes.ts # Nodes API endpoints
159157
│ ├── chatflows.ts # Chatflows API endpoints
160-
│ ├── hooks/
161-
│ │ └── useApi.ts # API hook (co-located)
162158
│ └── index.ts
163159
164160
└── store/ # State management
161+
├── AgentflowContext.tsx # Flow state context
165162
├── ApiContext.tsx # API client context
166163
├── ConfigContext.tsx # Configuration context
167-
├── AgentflowContext.tsx # Flow state context
168164
├── useFlowInstance.ts # ReactFlow instance hook
169165
└── index.ts
170166
```

packages/agentflow/TESTS.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ These modules carry the highest risk. Test in the same PR when modifying.
3434
| `src/infrastructure/api/client.ts` | `createApiClient` — headers, auth token, 401 interceptor | ✅ Done |
3535
| `src/infrastructure/api/chatflows.ts` | All CRUD + `generateAgentflow` + `getChatModels`, FlowData serialization | ✅ Done |
3636
| `src/infrastructure/api/nodes.ts` | `getAllNodes`, `getNodeByName`, `getNodeIconUrl` | ✅ Done |
37-
| `src/infrastructure/store/AgentflowContext.tsx` | `agentflowReducer` (all actions), `normalizeNodes`, `deleteNode()`, `duplicateNode()`. Remaining: `updateNodeData()`, `getFlowData()` | 🟡 Partial|
38-
| `src/useAgentflow.ts` | `getFlow()`, `toJSON()`, `validate()`, `addNode()`, `clear()` | ⬜ Not yet — thin wrapper |
37+
| `src/infrastructure/store/AgentflowContext.tsx` | `agentflowReducer` (all actions), `normalizeNodes`, `deleteNode()`, `duplicateNode()`, `openEditDialog()`, `closeEditDialog()`, `setNodes()`, `setEdges()`, `updateNodeData()`, `deleteEdge()`, state synchronization with local setters. E2E: composite workflow (add→connect→edit→save), load→modify→save roundtrip, multi-edge from single node, rapid connect/disconnect cycles, edge deletion | ✅ Done |
38+
| `src/useAgentflow.ts` | `getFlow()`, `toJSON()`, `validate()`, `addNode()`, `clear()`, `fitView()`, `getReactFlowInstance()`, instance stability | ✅ Done |
3939
| `src/features/canvas/hooks/useFlowHandlers.ts` | `handleConnect`, `handleNodesChange`, `handleEdgesChange`, `handleAddNode` — synchronous `onFlowChange` callbacks, dirty tracking, viewport resolution, change filtering | ✅ Done |
4040

4141
### Tier 2 — Feature Hooks & Dialogs
@@ -52,7 +52,6 @@ Test when adding features or fixing bugs in these areas.
5252
| `src/infrastructure/store/ConfigContext.tsx` | `ConfigProvider` — theme detection (light/dark/system), media query listener | ⬜ Not yet |
5353
| `src/features/generator/GenerateFlowDialog.tsx` | Dialog state machine — API call flow, error handling, progress state | ⬜ Not yet |
5454
| `src/features/node-editor/EditNodeDialog.tsx` | Label editing — keyboard handling (Enter/Escape), node data updates | ⬜ Not yet |
55-
| `src/infrastructure/api/hooks/useApi.ts` | `useApi()` — loading/error/data state transitions | ⬜ Not yet — may be deprecated |
5655

5756
### Tier 3 — UI Components
5857

@@ -66,13 +65,12 @@ Mostly JSX with minimal logic. Only add tests if business logic is introduced.
6665
| `src/features/canvas/containers/AgentFlowNode.tsx` | If warning state or color logic becomes more complex | ⬜ Not yet |
6766
| `src/features/canvas/containers/AgentFlowEdge.tsx` | If edge deletion or interaction logic changes | ⬜ Not yet |
6867
| `src/features/canvas/containers/IterationNode.tsx` | If resize or dimension calculation logic changes | ⬜ Not yet |
69-
| `src/atoms/ConfirmDialog.tsx` | If promise-based confirmation pattern is modified | ⬜ Not yet |
7068
| `src/atoms/NodeInputHandler.tsx` | If input rendering or position calculation logic changes | ⬜ Not yet |
7169
| `src/features/canvas/components/ConnectionLine.tsx` | If edge label determination logic becomes more complex | ⬜ Not yet |
7270
| `src/features/canvas/components/NodeStatusIndicator.tsx` | If status-to-color/icon mapping expands | ⬜ Not yet |
7371
| `src/Agentflow.tsx` | Integration test — dark mode, ThemeProvider, CSS variables, header rendering, keyboard shortcuts (Cmd+S / Ctrl+S save), generate flow dialog, imperative ref | ✅ Done |
7472

75-
Files that are pure styling or data constants (`styled.ts`, `nodeIcons.ts`, `MainCard.tsx`, `Input.tsx`, etc.) do not need dedicated tests.
73+
Files that are pure styling or data constants (`styled.ts`, `nodeIcons.ts`, `MainCard.tsx`, etc.) do not need dedicated tests.
7674

7775
## Test Utilities
7876

@@ -119,21 +117,32 @@ Key features:
119117

120118
**CSS Mock** (`src/__mocks__/styleMock.js`): Empty object export for CSS imports.
121119

120+
## File Extension Convention
121+
122+
The jest config uses file extensions to select the test environment:
123+
124+
| Extension | Environment | When to use |
125+
| ----------- | ----------------------- | -------------------------------------------------------------------------- |
126+
| `.test.ts` | **node** (no DOM) | Pure logic — utilities, reducers, data transformations |
127+
| `.test.tsx` | **jsdom** (browser DOM) | Anything that renders React — `renderHook` with providers, component tests |
128+
129+
**Source files** follow a different rule: use `.tsx` only when the file contains JSX syntax. A React hook like `useAgentflow.ts` has no JSX, so it stays `.ts` even though its test file is `.test.tsx` (because the test uses `renderHook` with a JSX wrapper).
130+
122131
## Configuration
123132

124133
- **Jest config**: `jest.config.js` — two projects: `unit` (node env, `.test.ts`) and `components` (custom jsdom env, `.test.tsx`)
125134
- **Test environment**: Component tests use custom jsdom environment (`src/__test_utils__/jest-environment-jsdom.js`) to handle canvas loading
126135
- **Import aliases**: `@test-utils` maps to `src/__test_utils__` for convenient imports
127136
- **Coverage thresholds**: uniform 80% floor (`branches`, `functions`, `lines`, `statements`) enforced per-path:
137+
- `./src/*.ts` (root-level modules like `useAgentflow.ts`)
128138
- `./src/Agentflow.tsx`
129139
- `./src/core/`
130140
- `./src/features/canvas/hooks/useFlowHandlers.ts`
131141
- `./src/features/node-palette/search.ts`
132142
- `./src/infrastructure/api/`
133-
- `./src/infrastructure/store/AgentflowContext.tsx` — will be added when coverage reaches 80%
143+
- `./src/infrastructure/store/AgentflowContext.tsx`
134144
- **Coverage exclusions**:
135145
- `src/__test_utils__/**` — test utilities
136146
- `src/__mocks__/**` — module mocks
137-
- `src/infrastructure/api/hooks/useApi.ts` — potentially deprecated
138147
- **CI**: `pnpm test:coverage` runs in GitHub Actions between lint and build
139148
- **Reports**: `coverage/lcov-report/index.html` for detailed HTML report

packages/agentflow/jest.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ module.exports = {
2727
'!src/**/index.ts',
2828
'!src/__mocks__/**',
2929
'!src/__test_utils__/**',
30-
// Potentially deprecated — exclude until resolved (see TESTS.md)
31-
'!src/infrastructure/api/hooks/useApi.ts'
30+
'!src/infrastructure/api/hooks/**'
3231
],
3332
// text: per-folder table, text-summary: totals, lcov: HTML report at coverage/lcov-report/
3433
coverageReporters: ['text', 'text-summary', 'lcov'],
3534
coverageDirectory: 'coverage',
3635
// 80% floor to catch regressions without blocking active development.
3736
// Add new paths here as more modules gain test coverage.
3837
coverageThreshold: {
38+
'./src/*.ts': { branches: 80, functions: 80, lines: 80, statements: 80 },
3939
'./src/Agentflow.tsx': { branches: 80, functions: 80, lines: 80, statements: 80 },
4040
'./src/core/': { branches: 80, functions: 80, lines: 80, statements: 80 },
4141
'./src/features/canvas/hooks/useFlowHandlers.ts': { branches: 80, functions: 80, lines: 80, statements: 80 },

packages/agentflow/src/atoms/ConfirmDialog.tsx

Lines changed: 0 additions & 116 deletions
This file was deleted.

packages/agentflow/src/atoms/Input.tsx

Lines changed: 0 additions & 74 deletions
This file was deleted.
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
// UI Components - Internal design system
2-
export { ConfirmDialog, ConfirmProvider, useConfirm } from './ConfirmDialog'
3-
export { Input } from './Input'
42
export { MainCard, type MainCardProps } from './MainCard'
53
export { NodeInputHandler } from './NodeInputHandler'

packages/agentflow/src/features/canvas/components/NodeOutputHandles.tsx

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { CSSProperties, RefObject } from 'react'
2-
import { memo, useMemo } from 'react'
2+
import { memo, useEffect, useMemo, useState } from 'react'
33
import { Handle, Position, useUpdateNodeInternals } from 'reactflow'
44

55
import { useTheme } from '@mui/material/styles'
@@ -37,17 +37,32 @@ export function getMinimumNodeHeight(outputCount: number): number {
3737
function NodeOutputHandlesComponent({ outputAnchors, nodeColor, isHovered, nodeRef, nodeId }: NodeOutputHandlesProps) {
3838
const theme = useTheme()
3939
const updateNodeInternals = useUpdateNodeInternals()
40+
const [nodeHeight, setNodeHeight] = useState(0)
4041

41-
const getAnchorPosition = (index: number) => {
42-
const currentHeight = nodeRef.current?.clientHeight || 0
43-
const spacing = currentHeight / (outputAnchors.length + 1)
44-
const anchorPosition = spacing * (index + 1)
42+
// Track actual node height via ResizeObserver so we re-render once layout is done
43+
useEffect(() => {
44+
const el = nodeRef.current
45+
if (!el) return
4546

46-
if (anchorPosition > 0) {
47-
updateNodeInternals(nodeId)
48-
}
47+
const observer = new ResizeObserver((entries) => {
48+
for (const entry of entries) {
49+
const height = entry.contentRect.height
50+
setNodeHeight((prev) => {
51+
if (prev !== height) {
52+
updateNodeInternals(nodeId)
53+
return height
54+
}
55+
return prev
56+
})
57+
}
58+
})
59+
observer.observe(el)
60+
return () => observer.disconnect()
61+
}, [nodeRef, nodeId, updateNodeInternals])
4962

50-
return anchorPosition
63+
const getAnchorPosition = (index: number) => {
64+
const spacing = nodeHeight / (outputAnchors.length + 1)
65+
return spacing * (index + 1)
5166
}
5267

5368
// Memoize static styles

packages/agentflow/src/features/canvas/containers/AgentFlowNode.tsx

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { memo, useEffect, useRef, useState } from 'react'
2-
import { useUpdateNodeInternals } from 'reactflow'
32

43
import { Box, Typography } from '@mui/material'
54

@@ -31,7 +30,6 @@ function AgentFlowNodeComponent({ data }: AgentFlowNodeProps) {
3130
const { isDarkMode } = useConfigContext()
3231
const { apiBaseUrl } = useApiContext()
3332
const ref = useRef<HTMLDivElement>(null)
34-
const updateNodeInternals = useUpdateNodeInternals()
3533
const { openNodeEditor } = useOpenNodeEditor()
3634

3735
const [isHovered, setIsHovered] = useState(false)
@@ -52,14 +50,6 @@ function AgentFlowNodeComponent({ data }: AgentFlowNodeProps) {
5250
const outputAnchors = data.outputAnchors ?? []
5351
const minHeight = getMinimumNodeHeight(outputAnchors.length)
5452

55-
useEffect(() => {
56-
if (ref.current) {
57-
setTimeout(() => {
58-
updateNodeInternals(data.id)
59-
}, 10)
60-
}
61-
}, [data, ref, updateNodeInternals])
62-
6353
useEffect(() => {
6454
if (data.warning) {
6555
setWarningMessage(data.warning)

packages/agentflow/src/features/node-editor/EditNodeDialog.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ export interface EditNodeDialogProps {
1919
onCancel: () => void
2020
}
2121

22-
// TODO: Integrate with canvas node click/double-click to open this dialog for editing node properties
2322
/**
2423
* Dialog for editing node properties
2524
*/

0 commit comments

Comments
 (0)