Skip to content

Commit 34d2a22

Browse files
jocelynlin-wdclaude
andcommitted
feat(agentflow): enhance ExpandTextDialog to handle value updates correctly
- Added tests to ensure the dialog displays the current value when opened after changes while closed. - Implemented logic to reset the dialog's value to the original when reopened after cancellation. - Updated state management in ExpandTextDialog to synchronize local value immediately upon opening. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a345a34 commit 34d2a22

File tree

3 files changed

+64
-7
lines changed

3 files changed

+64
-7
lines changed

packages/agentflow/src/atoms/ExpandTextDialog.test.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,41 @@ describe('ExpandTextDialog', () => {
8282
expect(textarea).toHaveAttribute('placeholder', 'Type here...')
8383
})
8484

85+
it('should show current value when opened after value changed while closed', () => {
86+
const { rerender } = render(
87+
<ExpandTextDialog open={false} value='' inputType='code' onConfirm={mockOnConfirm} onCancel={mockOnCancel} />
88+
)
89+
90+
// Simulate value changing while dialog is closed (user typing in inline editor)
91+
rerender(<ExpandTextDialog open={false} value='Updated text' inputType='code' onConfirm={mockOnConfirm} onCancel={mockOnCancel} />)
92+
93+
// Open the dialog — it should show the updated value, not the initial empty value
94+
rerender(<ExpandTextDialog open={true} value='Updated text' inputType='code' onConfirm={mockOnConfirm} onCancel={mockOnCancel} />)
95+
96+
const textarea = screen.getByTestId('expand-content-input').querySelector('textarea')!
97+
expect(textarea).toHaveValue('Updated text')
98+
})
99+
100+
it('should reset to current value when re-opened after cancel', () => {
101+
const { rerender } = render(
102+
<ExpandTextDialog open={true} value='Original' inputType='code' onConfirm={mockOnConfirm} onCancel={mockOnCancel} />
103+
)
104+
105+
// User types in the dialog then cancels
106+
const textarea = screen.getByTestId('expand-content-input').querySelector('textarea')!
107+
fireEvent.change(textarea, { target: { value: 'Unsaved edits' } })
108+
fireEvent.click(screen.getByRole('button', { name: 'Cancel' }))
109+
110+
// Close the dialog
111+
rerender(<ExpandTextDialog open={false} value='Original' inputType='code' onConfirm={mockOnConfirm} onCancel={mockOnCancel} />)
112+
113+
// Re-open — should show the original value, not the unsaved edits
114+
rerender(<ExpandTextDialog open={true} value='Original' inputType='code' onConfirm={mockOnConfirm} onCancel={mockOnCancel} />)
115+
116+
const textarea2 = screen.getByTestId('expand-content-input').querySelector('textarea')!
117+
expect(textarea2).toHaveValue('Original')
118+
})
119+
85120
// --- Rich text mode ---
86121

87122
describe('inputType="string" (richtext)', () => {

packages/agentflow/src/atoms/ExpandTextDialog.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useEffect, useState } from 'react'
1+
import { useCallback, useState } from 'react'
22

33
import { Box, Button, Dialog, DialogActions, DialogContent, TextField, Typography } from '@mui/material'
44

@@ -32,13 +32,17 @@ export function ExpandTextDialog({
3232
onCancel
3333
}: ExpandTextDialogProps) {
3434
const [localValue, setLocalValue] = useState(value)
35+
const [prevOpen, setPrevOpen] = useState(open)
3536

36-
// Sync local state when the value prop changes while dialog is open
37-
useEffect(() => {
38-
if (open) {
39-
setLocalValue(value)
40-
}
41-
}, [open, value])
37+
// Sync localValue synchronously when the dialog opens so the TipTap editor
38+
// initialises with the correct content (useEffect would leave a one-render
39+
// gap where localValue is stale, causing the editor to show empty/old text).
40+
if (open && !prevOpen) {
41+
setLocalValue(value)
42+
setPrevOpen(true)
43+
} else if (!open && prevOpen) {
44+
setPrevOpen(false)
45+
}
4246

4347
const handleConfirm = useCallback(() => {
4448
onConfirm(localValue)

packages/agentflow/src/atoms/NodeInputHandler.test.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@ describe('NodeInputHandler – expand dialog', () => {
145145
})
146146
})
147147

148+
it('should reflect updated data prop in expand dialog after rerender', () => {
149+
const param = makeParam({ type: 'string', rows: 4 })
150+
const initialData = { ...baseNodeData, inputValues: { myField: '' } }
151+
152+
const { rerender } = render(
153+
<NodeInputHandler inputParam={param} data={initialData} isAdditionalParams onDataChange={mockOnDataChange} />
154+
)
155+
156+
// Simulate parent updating data after user types in inline editor
157+
const updatedData = { ...baseNodeData, inputValues: { myField: '<p>Updated instructions</p>' } }
158+
rerender(<NodeInputHandler inputParam={param} data={updatedData} isAdditionalParams onDataChange={mockOnDataChange} />)
159+
160+
// Open expand dialog — it should show the updated value, not the initial empty value
161+
fireEvent.click(screen.getByTitle('Expand'))
162+
const editors = screen.getAllByTestId('rich-text-editor')
163+
expect(editors[1]).toHaveValue('<p>Updated instructions</p>')
164+
})
165+
148166
it('should not show expand icon for non-multiline string fields', () => {
149167
render(
150168
<NodeInputHandler

0 commit comments

Comments
 (0)