@@ -193,6 +193,165 @@ describe('Field', () => {
193193 expect ( render . mock . calls [ 2 ] [ 0 ] . values . foo ) . toBeUndefined ( )
194194 } )
195195
196+ it ( 'should accept parse and normalize function props' , ( ) => {
197+ const parse = jest . fn ( ( value , name ) => `parse.${ value } ` )
198+ const normalize = jest . fn (
199+ ( value , previousValue , allValues ) => `normalize.${ value } `
200+ )
201+ const renderInput = jest . fn ( ( { input } ) => < input { ...input } /> )
202+ const render = jest . fn ( ( ) => (
203+ < form >
204+ < Field
205+ name = "foo"
206+ render = { renderInput }
207+ parse = { parse }
208+ normalize = { normalize }
209+ />
210+ < Field name = "boo" component = "select" />
211+ </ form >
212+ ) )
213+
214+ const dom = TestUtils . renderIntoDocument (
215+ < Form
216+ onSubmit = { onSubmitMock }
217+ render = { render }
218+ initialValues = { { boo : 'abc' } }
219+ />
220+ )
221+
222+ expect ( render ) . toHaveBeenCalled ( )
223+ expect ( render ) . toHaveBeenCalledTimes ( 1 )
224+ expect ( render . mock . calls [ 0 ] [ 0 ] . values ) . toEqual ( {
225+ foo : undefined ,
226+ boo : 'abc'
227+ } )
228+
229+ const input = TestUtils . findRenderedDOMComponentWithTag ( dom , 'input' )
230+
231+ TestUtils . Simulate . change ( input , { target : { value : 'bar' } } )
232+
233+ expect ( render ) . toHaveBeenCalledTimes ( 2 )
234+ expect ( render . mock . calls [ 1 ] [ 0 ] . values . foo ) . toBe ( 'normalize.parse.bar' )
235+
236+ expect ( parse ) . toHaveBeenCalled ( )
237+ expect ( parse ) . toHaveBeenCalledTimes ( 1 )
238+ expect ( parse . mock . calls [ 0 ] ) . toEqual ( [ 'bar' , 'foo' ] )
239+
240+ expect ( normalize ) . toHaveBeenCalled ( )
241+ expect ( normalize ) . toHaveBeenCalledTimes ( 1 )
242+ expect ( normalize . mock . calls [ 0 ] ) . toEqual ( [
243+ 'parse.bar' ,
244+ undefined ,
245+ { foo : undefined , boo : 'abc' }
246+ ] )
247+
248+ TestUtils . Simulate . change ( input , { target : { value : 'x' } } )
249+
250+ expect ( render ) . toHaveBeenCalledTimes ( 3 )
251+ expect ( render . mock . calls [ 2 ] [ 0 ] . values . foo ) . toBe ( 'normalize.parse.x' )
252+
253+ expect ( parse ) . toHaveBeenCalledTimes ( 2 )
254+ expect ( parse . mock . calls [ 1 ] ) . toEqual ( [ 'x' , 'foo' ] )
255+
256+ expect ( normalize ) . toHaveBeenCalledTimes ( 2 )
257+ expect ( normalize . mock . calls [ 1 ] ) . toEqual ( [
258+ 'parse.x' ,
259+ 'normalize.parse.bar' ,
260+ { foo : 'normalize.parse.bar' , boo : 'abc' }
261+ ] )
262+ } )
263+
264+ it ( 'should accept a null parse prop to preserve empty strings' , ( ) => {
265+ const renderInput = jest . fn ( ( { input } ) => < input { ...input } /> )
266+ const render = jest . fn ( ( ) => (
267+ < form >
268+ < Field name = "foo" render = { renderInput } parse = { null } />
269+ </ form >
270+ ) )
271+
272+ const dom = TestUtils . renderIntoDocument (
273+ < Form onSubmit = { onSubmitMock } render = { render } />
274+ )
275+
276+ expect ( render ) . toHaveBeenCalled ( )
277+ expect ( render ) . toHaveBeenCalledTimes ( 1 )
278+ expect ( render . mock . calls [ 0 ] [ 0 ] . values . foo ) . toBeUndefined ( )
279+
280+ const input = TestUtils . findRenderedDOMComponentWithTag ( dom , 'input' )
281+
282+ TestUtils . Simulate . change ( input , { target : { value : '' } } )
283+
284+ expect ( render ) . toHaveBeenCalledTimes ( 2 )
285+ expect ( render . mock . calls [ 1 ] [ 0 ] . values . foo ) . toBe ( '' )
286+
287+ TestUtils . Simulate . change ( input , { target : { value : 'abc' } } )
288+
289+ expect ( render ) . toHaveBeenCalledTimes ( 3 )
290+ expect ( render . mock . calls [ 2 ] [ 0 ] . values . foo ) . toBe ( 'abc' )
291+ } )
292+
293+ it ( 'should accept a format function prop' , ( ) => {
294+ const format = jest . fn ( ( value , name ) => `format.${ value } ` )
295+ const renderInput = jest . fn ( ( { input } ) => < input { ...input } /> )
296+ const render = jest . fn ( ( ) => (
297+ < form >
298+ < Field name = "foo" render = { renderInput } format = { format } />
299+ </ form >
300+ ) )
301+
302+ TestUtils . renderIntoDocument (
303+ < Form onSubmit = { onSubmitMock } render = { render } />
304+ )
305+
306+ expect ( render ) . toHaveBeenCalled ( )
307+ expect ( render ) . toHaveBeenCalledTimes ( 1 )
308+ expect ( render . mock . calls [ 0 ] [ 0 ] . values . foo ) . toBeUndefined ( )
309+
310+ expect ( format ) . toHaveBeenCalled ( )
311+ expect ( format ) . toHaveBeenCalledTimes ( 1 )
312+ expect ( format . mock . calls [ 0 ] ) . toEqual ( [ undefined , 'foo' ] )
313+
314+ expect ( renderInput ) . toHaveBeenCalled ( )
315+ expect ( renderInput ) . toHaveBeenCalledTimes ( 1 )
316+ expect ( renderInput . mock . calls [ 0 ] [ 0 ] . input . value ) . toBe ( 'format.undefined' )
317+
318+ renderInput . mock . calls [ 0 ] [ 0 ] . input . onChange ( 'bar' )
319+
320+ expect ( format ) . toHaveBeenCalledTimes ( 2 )
321+ expect ( format . mock . calls [ 1 ] ) . toEqual ( [ 'bar' , 'foo' ] )
322+
323+ expect ( renderInput ) . toHaveBeenCalledTimes ( 2 )
324+ expect ( renderInput . mock . calls [ 1 ] [ 0 ] . input . value ) . toBe ( 'format.bar' )
325+ } )
326+
327+ it ( 'should accept a null format prop to preserve undefined values' , ( ) => {
328+ const renderInput = jest . fn ( ( { input } ) => (
329+ < input { ...input } value = { input . value || '' } />
330+ ) )
331+ const render = jest . fn ( ( ) => (
332+ < form >
333+ < Field name = "foo" render = { renderInput } format = { null } />
334+ </ form >
335+ ) )
336+
337+ TestUtils . renderIntoDocument (
338+ < Form onSubmit = { onSubmitMock } render = { render } />
339+ )
340+
341+ expect ( render ) . toHaveBeenCalled ( )
342+ expect ( render ) . toHaveBeenCalledTimes ( 1 )
343+ expect ( render . mock . calls [ 0 ] [ 0 ] . values . foo ) . toBeUndefined ( )
344+
345+ expect ( renderInput ) . toHaveBeenCalled ( )
346+ expect ( renderInput ) . toHaveBeenCalledTimes ( 1 )
347+ expect ( renderInput . mock . calls [ 0 ] [ 0 ] . input . value ) . toBeUndefined ( )
348+
349+ renderInput . mock . calls [ 0 ] [ 0 ] . input . onChange ( 'bar' )
350+
351+ expect ( renderInput ) . toHaveBeenCalledTimes ( 2 )
352+ expect ( renderInput . mock . calls [ 1 ] [ 0 ] . input . value ) . toBe ( 'bar' )
353+ } )
354+
196355 it ( 'should provide a value of [] when empty on a select multiple' , ( ) => {
197356 const dom = TestUtils . renderIntoDocument (
198357 < Form onSubmit = { onSubmitMock } >
@@ -210,7 +369,36 @@ describe('Field', () => {
210369 expect ( select . value ) . toBe ( '' )
211370 } )
212371
213- it ( 'should optionally allow null' , ( ) => {
372+ it ( "should convert null values to ''" , ( ) => {
373+ const renderInput = jest . fn ( ( { input } ) => (
374+ < input { ...input } value = { input . value } />
375+ ) )
376+ const render = jest . fn ( ( ) => (
377+ < form >
378+ < Field name = "foo" render = { renderInput } />
379+ </ form >
380+ ) )
381+
382+ TestUtils . renderIntoDocument (
383+ < Form onSubmit = { onSubmitMock } render = { render } />
384+ )
385+
386+ expect ( renderInput ) . toHaveBeenCalled ( )
387+ expect ( renderInput ) . toHaveBeenCalledTimes ( 1 )
388+ expect ( renderInput . mock . calls [ 0 ] [ 0 ] . input . value ) . toBe ( '' )
389+
390+ renderInput . mock . calls [ 0 ] [ 0 ] . input . onChange ( 'bar' )
391+
392+ expect ( renderInput ) . toHaveBeenCalledTimes ( 2 )
393+ expect ( renderInput . mock . calls [ 1 ] [ 0 ] . input . value ) . toBe ( 'bar' )
394+
395+ renderInput . mock . calls [ 1 ] [ 0 ] . input . onChange ( null )
396+
397+ expect ( renderInput ) . toHaveBeenCalledTimes ( 3 )
398+ expect ( renderInput . mock . calls [ 2 ] [ 0 ] . input . value ) . toBe ( '' )
399+ } )
400+
401+ it ( 'should optionally allow null values' , ( ) => {
214402 const renderInput = jest . fn ( ( { input } ) => (
215403 < input
216404 { ...input }
0 commit comments