Skip to content

Commit 8babb88

Browse files
author
Erik Rasmussen
committed
Add checkbox and radio tests for dynamic name changes
1 parent fad4873 commit 8babb88

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed

src/useField.dynamic-name-869.test.js

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,173 @@ describe('useField - Dynamic Name (Issue #869)', () => {
9393
expect(getByTestId('name')).toHaveTextContent('b')
9494
expect(getByTestId('value')).toHaveTextContent('value-b')
9595
})
96+
97+
it('should keep name and checked in sync when checkbox field name changes', () => {
98+
const renderSpy = jest.fn()
99+
100+
const TestComponent = ({ fieldName }) => {
101+
return (
102+
<Form
103+
onSubmit={() => {}}
104+
initialValues={{ a: true, b: false }}
105+
>
106+
{() => (
107+
<Field name={fieldName} type="checkbox">
108+
{({ input }) => {
109+
// Log every render to track name/checked sync
110+
renderSpy(input.name, input.checked)
111+
return <input {...input} data-testid="field" />
112+
}}
113+
</Field>
114+
)}
115+
</Form>
116+
)
117+
}
118+
119+
const { rerender } = render(<TestComponent fieldName="a" />)
120+
121+
// Initial render - field 'a' checked
122+
expect(renderSpy).toHaveBeenCalledWith('a', true)
123+
124+
renderSpy.mockClear()
125+
126+
// Change field name from 'a' to 'b'
127+
act(() => {
128+
rerender(<TestComponent fieldName="b" />)
129+
})
130+
131+
// Verify all renders after name change have name='b' and checked=false
132+
const calls = renderSpy.mock.calls
133+
134+
// Ensure Field actually rendered
135+
expect(calls.length).toBeGreaterThan(0)
136+
137+
// After rerender with fieldName="b", ALL calls should be for field 'b'
138+
calls.forEach(call => {
139+
const [name, checked] = call
140+
expect(name).toBe('b')
141+
expect(checked).toBe(false)
142+
})
143+
})
144+
145+
it('should have correct checked immediately after checkbox name change', () => {
146+
const TestComponent = ({ fieldName }) => {
147+
return (
148+
<Form
149+
onSubmit={() => {}}
150+
initialValues={{ a: true, b: false }}
151+
>
152+
{() => (
153+
<Field name={fieldName} type="checkbox">
154+
{({ input }) => (
155+
<div>
156+
<span data-testid="name">{input.name}</span>
157+
<span data-testid="checked">{String(input.checked)}</span>
158+
</div>
159+
)}
160+
</Field>
161+
)}
162+
</Form>
163+
)
164+
}
165+
166+
const { rerender, getByTestId } = render(<TestComponent fieldName="a" />)
167+
168+
expect(getByTestId('name')).toHaveTextContent('a')
169+
expect(getByTestId('checked')).toHaveTextContent('true')
170+
171+
// Change field name
172+
act(() => {
173+
rerender(<TestComponent fieldName="b" />)
174+
})
175+
176+
// Immediately after rerender, name and checked should be in sync
177+
expect(getByTestId('name')).toHaveTextContent('b')
178+
expect(getByTestId('checked')).toHaveTextContent('false')
179+
})
180+
181+
it('should keep name and checked in sync when radio field name changes', () => {
182+
const renderSpy = jest.fn()
183+
184+
const TestComponent = ({ fieldName }) => {
185+
return (
186+
<Form
187+
onSubmit={() => {}}
188+
initialValues={{ a: 'option1', b: 'option2' }}
189+
>
190+
{() => (
191+
<Field name={fieldName} type="radio" value="option2">
192+
{({ input }) => {
193+
// Log every render to track name/checked sync
194+
renderSpy(input.name, input.checked)
195+
return <input {...input} data-testid="field" />
196+
}}
197+
</Field>
198+
)}
199+
</Form>
200+
)
201+
}
202+
203+
const { rerender } = render(<TestComponent fieldName="a" />)
204+
205+
// Initial render - field 'a' has value 'option1', not checked for 'option2'
206+
expect(renderSpy).toHaveBeenCalledWith('a', false)
207+
208+
renderSpy.mockClear()
209+
210+
// Change field name from 'a' to 'b'
211+
act(() => {
212+
rerender(<TestComponent fieldName="b" />)
213+
})
214+
215+
// Verify all renders after name change have name='b' and checked=true
216+
const calls = renderSpy.mock.calls
217+
218+
// Ensure Field actually rendered
219+
expect(calls.length).toBeGreaterThan(0)
220+
221+
// After rerender with fieldName="b", ALL calls should be for field 'b'
222+
// Field 'b' has value 'option2', so radio with value="option2" should be checked
223+
calls.forEach(call => {
224+
const [name, checked] = call
225+
expect(name).toBe('b')
226+
expect(checked).toBe(true)
227+
})
228+
})
229+
230+
it('should have correct checked immediately after radio name change', () => {
231+
const TestComponent = ({ fieldName }) => {
232+
return (
233+
<Form
234+
onSubmit={() => {}}
235+
initialValues={{ a: 'option1', b: 'option2' }}
236+
>
237+
{() => (
238+
<Field name={fieldName} type="radio" value="option2">
239+
{({ input }) => (
240+
<div>
241+
<span data-testid="name">{input.name}</span>
242+
<span data-testid="checked">{String(input.checked)}</span>
243+
</div>
244+
)}
245+
</Field>
246+
)}
247+
</Form>
248+
)
249+
}
250+
251+
const { rerender, getByTestId } = render(<TestComponent fieldName="a" />)
252+
253+
expect(getByTestId('name')).toHaveTextContent('a')
254+
expect(getByTestId('checked')).toHaveTextContent('false')
255+
256+
// Change field name
257+
act(() => {
258+
rerender(<TestComponent fieldName="b" />)
259+
})
260+
261+
// Immediately after rerender, name and checked should be in sync
262+
expect(getByTestId('name')).toHaveTextContent('b')
263+
expect(getByTestId('checked')).toHaveTextContent('true')
264+
})
96265
})

0 commit comments

Comments
 (0)