@@ -4,138 +4,154 @@ import Input from './fixtures/input.svelte';
44import StoreContextInspector from './fixtures/store-context-inspector.svelte' ;
55
66import Form from 'lib/components/Form.svelte' ;
7+ import { createForm } from 'lib/index' ;
78
89const defaultProps = {
910 initialValues : { foo : '' } ,
1011 onSubmit ( ) { } ,
1112} ;
1213
14+ const contextType = {
15+ userDefined : 'user' ,
16+ fallback : 'fallback' ,
17+ } ;
18+
1319describe ( 'Form' , ( ) => {
14- test ( '-> exposes `form` store to children via context' , async ( ) => {
15- const inputId = 'foo' ;
16- const props = {
17- ...defaultProps ,
18- initialValues : { [ inputId ] : '' } ,
20+ describe . each `
21+ contextName | type
22+ ${ 'fallback' } | ${ contextType . fallback }
23+ ${ 'user-defined' } | ${ contextType . userDefined }
24+ ` ( '-> with $contextName context' , ( { type} ) => {
25+ const getForm = ( props = defaultProps ) => {
26+ const form =
27+ type === contextType . userDefined ? createForm ( props ) : undefined ;
28+ const resultProps = type === contextType . userDefined ? { } : props ;
29+
30+ return [ resultProps , form ] ;
1931 } ;
20- const { getByLabelText, getByTestId} = render (
21- < Form { ...props } >
22- < Input field = { inputId } />
2332
24- < StoreContextInspector data-testid = "values" storeProp = "form" />
25- </ Form > ,
26- ) ;
27- const input = getByLabelText ( inputId ) ;
28- const valuesEl = getByTestId ( 'values' ) ;
29- let values = JSON . parse ( valuesEl . textContent ) ;
33+ test ( '-> exposes `form` store to children via context' , async ( ) => {
34+ const inputId = 'foo' ;
35+ const baseProps = { ...defaultProps , initialValues : { [ inputId ] : '' } } ;
36+ const [ props , form ] = getForm ( baseProps ) ;
37+ const { getByLabelText, getByTestId} = render (
38+ < Form { ...props } context = { form } >
39+ < Input field = { inputId } />
3040
31- expect ( values [ inputId ] ) . toBe ( props . initialValues [ inputId ] ) ;
32- expect ( input . value ) . toBe ( values [ inputId ] ) ;
41+ < StoreContextInspector data-testid = "values" storeProp = "form" />
42+ </ Form > ,
43+ ) ;
44+ const input = getByLabelText ( inputId ) ;
45+ const valuesEl = getByTestId ( 'values' ) ;
46+ let values = JSON . parse ( valuesEl . textContent ) ;
3347
34- const value = 'bar' ;
48+ expect ( values [ inputId ] ) . toBe ( baseProps . initialValues [ inputId ] ) ;
49+ expect ( input . value ) . toBe ( values [ inputId ] ) ;
3550
36- await fireEvent . input ( input , { target : { value} } ) ;
51+ const value = 'bar' ;
3752
38- values = JSON . parse ( valuesEl . textContent ) ;
53+ await fireEvent . input ( input , { target : { value } } ) ;
3954
40- expect ( values [ inputId ] ) . toBe ( value ) ;
41- expect ( input . value ) . toBe ( value ) ;
42- } ) ;
55+ values = JSON . parse ( valuesEl . textContent ) ;
4356
44- test ( '-> exposes `state` store to children via context' , async ( ) => {
45- const inputId = 'foo' ;
46- const props = {
47- ...defaultProps ,
48- initialValues : { [ inputId ] : '' } ,
49- } ;
50- const { getByLabelText, getByTestId} = render (
51- < Form { ...props } >
52- < Input field = { inputId } />
57+ expect ( values [ inputId ] ) . toBe ( value ) ;
58+ expect ( input . value ) . toBe ( value ) ;
59+ } ) ;
5360
54- < StoreContextInspector data-testid = "state" storeProp = "state" />
55- </ Form > ,
56- ) ;
57- const input = getByLabelText ( inputId ) ;
58- const stateEl = getByTestId ( 'state' ) ;
59- let state = JSON . parse ( stateEl . textContent ) ;
61+ test ( '-> exposes `state` store to children via context' , async ( ) => {
62+ const inputId = 'foo' ;
63+ const baseProps = { ...defaultProps , initialValues : { [ inputId ] : '' } } ;
64+ const [ props , form ] = getForm ( baseProps ) ;
65+ const { getByLabelText, getByTestId} = render (
66+ < Form { ...props } context = { form } >
67+ < Input field = { inputId } />
6068
61- expect ( state ) . toHaveProperty ( 'isModified' , false ) ;
69+ < StoreContextInspector data-testid = "state" storeProp = "state" />
70+ </ Form > ,
71+ ) ;
72+ const input = getByLabelText ( inputId ) ;
73+ const stateEl = getByTestId ( 'state' ) ;
74+ let state = JSON . parse ( stateEl . textContent ) ;
6275
63- const value = 'bar' ;
76+ expect ( state ) . toHaveProperty ( 'isModified' , false ) ;
6477
65- await fireEvent . input ( input , { target : { value} } ) ;
78+ const value = 'bar' ;
6679
67- state = JSON . parse ( stateEl . textContent ) ;
68- expect ( state ) . toHaveProperty ( 'isModified' , true ) ;
69- } ) ;
80+ await fireEvent . input ( input , { target : { value} } ) ;
7081
71- test ( '-> exposes `errors` store to children via context' , async ( ) => {
72- const inputId = 'foo' ;
73- const validationError = `${ inputId } is required` ;
74- const props = {
75- initialValues : { [ inputId ] : '' } ,
76- validate : ( values ) => {
77- if ( ! values [ inputId ] ) {
78- return { [ inputId ] : validationError } ;
79- }
80- } ,
81- } ;
82- const { getByTestId, getByLabelText, getByRole} = render (
83- < Form { ...props } >
84- < Input field = { inputId } />
85- < StoreContextInspector data-testid = "error" storeProp = "errors" />
86-
87- < button type = "submit" > submit</ button >
88- </ Form > ,
89- ) ;
90- const input = getByLabelText ( inputId ) ;
91- const button = getByRole ( 'button' ) ;
92- const errorEl = getByTestId ( 'error' ) ;
93- let errors = JSON . parse ( errorEl . textContent ) ;
94-
95- expect ( errors ) . toHaveProperty ( inputId , '' ) ;
96-
97- await fireEvent . click ( button ) ;
98-
99- await waitFor ( ( ) => {
100- errors = JSON . parse ( errorEl . textContent ) ;
101- expect ( errors ) . toHaveProperty ( inputId , validationError ) ;
82+ state = JSON . parse ( stateEl . textContent ) ;
83+ expect ( state ) . toHaveProperty ( 'isModified' , true ) ;
10284 } ) ;
10385
104- const value = 'bar' ;
105-
106- await fireEvent . input ( input , { target : { value} } ) ;
107- await fireEvent . click ( button ) ;
86+ test ( '-> exposes `errors` store to children via context' , async ( ) => {
87+ const inputId = 'foo' ;
88+ const validationError = `${ inputId } is required` ;
89+ const baseProps = {
90+ ...defaultProps ,
91+ initialValues : { [ inputId ] : '' } ,
92+ validate : ( values ) => {
93+ if ( ! values [ inputId ] ) {
94+ return { [ inputId ] : validationError } ;
95+ }
96+ } ,
97+ } ;
98+ const [ props , form ] = getForm ( baseProps ) ;
99+ const { getByTestId, getByLabelText, getByRole} = render (
100+ < Form { ...props } context = { form } >
101+ < Input field = { inputId } />
102+ < StoreContextInspector data-testid = "error" storeProp = "errors" />
103+
104+ < button type = "submit" > submit</ button >
105+ </ Form > ,
106+ ) ;
107+ const input = getByLabelText ( inputId ) ;
108+ const button = getByRole ( 'button' ) ;
109+ const errorEl = getByTestId ( 'error' ) ;
110+ let errors = JSON . parse ( errorEl . textContent ) ;
108111
109- await waitFor ( ( ) => {
110- errors = JSON . parse ( errorEl . textContent ) ;
111112 expect ( errors ) . toHaveProperty ( inputId , '' ) ;
113+
114+ await fireEvent . click ( button ) ;
115+
116+ await waitFor ( ( ) => {
117+ errors = JSON . parse ( errorEl . textContent ) ;
118+ expect ( errors ) . toHaveProperty ( inputId , validationError ) ;
119+ } ) ;
120+
121+ const value = 'bar' ;
122+
123+ await fireEvent . input ( input , { target : { value} } ) ;
124+ await fireEvent . click ( button ) ;
125+
126+ await waitFor ( ( ) => {
127+ errors = JSON . parse ( errorEl . textContent ) ;
128+ expect ( errors ) . toHaveProperty ( inputId , '' ) ;
129+ } ) ;
112130 } ) ;
113- } ) ;
114131
115- test . each `
116- methodName
117- ${ 'handleChange' }
118- ${ 'handleSubmit' }
119- ${ 'updateField' }
120- ${ 'updateInitialValues' }
121- ${ 'updateTouched' }
122- ${ 'updateValidateField' }
123- ${ 'validateField' }
124- ` ( '-> exposes $methodName via slot properties' , ( { methodName} ) => {
125- const inputId = 'foo' ;
126- const methodSetter = jest . fn ( ) ;
127- const props = {
128- ...defaultProps ,
129- initialValues : { [ inputId ] : '' } ,
130- [ `let_${ methodName } ` ] : methodSetter ,
131- } ;
132- render (
133- < Form { ...props } >
134- < Input field = { inputId } />
135- </ Form > ,
136- ) ;
137-
138- expect ( methodSetter . mock . calls [ 0 ] [ 0 ] ) . toBeInstanceOf ( Function ) ;
139- expect ( methodSetter . mock . calls [ 0 ] [ 0 ] ) . toHaveProperty ( 'name' , methodName ) ;
132+ test . each `
133+ methodName
134+ ${ 'handleChange' }
135+ ${ 'handleSubmit' }
136+ ${ 'updateField' }
137+ ${ 'updateInitialValues' }
138+ ${ 'updateTouched' }
139+ ${ 'updateValidateField' }
140+ ${ 'validateField' }
141+ ` ( '-> exposes $methodName via slot properties' , ( { methodName} ) => {
142+ const inputId = 'foo' ;
143+ const methodSetter = jest . fn ( ) ;
144+ const baseProps = { ...defaultProps , initialValues : { [ inputId ] : '' } } ;
145+ const methodProps = { [ `let_${ methodName } ` ] : methodSetter } ;
146+ const [ props , form ] = getForm ( baseProps ) ;
147+ render (
148+ < Form { ...props } { ...methodProps } context = { form } >
149+ < Input field = { inputId } />
150+ </ Form > ,
151+ ) ;
152+
153+ expect ( methodSetter . mock . calls [ 0 ] [ 0 ] ) . toBeInstanceOf ( Function ) ;
154+ expect ( methodSetter . mock . calls [ 0 ] [ 0 ] ) . toHaveProperty ( 'name' , methodName ) ;
155+ } ) ;
140156 } ) ;
141157} ) ;
0 commit comments