Skip to content
This repository was archived by the owner on Aug 23, 2022. It is now read-only.

Commit 912ee8a

Browse files
committed
Exposing getField and getModel utility functions. Fixes #424
1 parent 28dd69e commit 912ee8a

File tree

4 files changed

+133
-38
lines changed

4 files changed

+133
-38
lines changed

src/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import combineForms from './reducers/forms-reducer';
1919
import modelReducer from './reducers/model-reducer';
2020

2121
import track from './utils/track';
22-
import getField from './utils/get-field';
22+
import getFieldFromState from './utils/get-field-from-state';
23+
import get from './utils/get';
2324

2425
import form from './form';
2526

@@ -53,6 +54,7 @@ export {
5354
form,
5455

5556
// Utilities
56-
getField,
57+
getFieldFromState as getField,
58+
get as getModel,
5759
track,
5860
};

src/utils/get-field-from-state.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import getForm from './get-form';
44
import isPlainObject from 'lodash/isPlainObject';
55

66
export default function getFieldFromState(state, modelString) {
7-
const form = getForm(state, modelString);
7+
const form = (state && '$form' in state)
8+
? state
9+
: getForm(state, modelString);
810

911
if (!form) return null;
1012

test/form-reducer-spec.js

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { assert } from 'chai';
2-
import { actions, formReducer, initialFieldState, getField } from '../src';
2+
import {
3+
actions,
4+
formReducer,
5+
} from '../src';
36
import isValid from '../src/form/is-valid';
47

58
describe('formReducer()', () => {
@@ -15,38 +18,6 @@ describe('formReducer()', () => {
1518
assert.doesNotThrow(() => reducer(undefined, { type: 'ANY' }));
1619
});
1720

18-
describe('getField() function', () => {
19-
it('should return an initialFieldState given an uninitialized model', () => {
20-
const reducer = formReducer('test');
21-
22-
const actual = reducer(undefined, { type: 'ANY' });
23-
24-
assert.isFunction(getField);
25-
26-
assert.deepEqual(getField(actual, 'any'), initialFieldState);
27-
28-
assert.isObject(getField(actual, 'foo').errors);
29-
});
30-
31-
it('should maintain the full fieldState of an updated model', () => {
32-
const reducer = formReducer('test');
33-
34-
const actual = reducer(undefined, actions.focus('test.foo'));
35-
36-
assert.containSubset(getField(actual, 'foo'), {
37-
focus: true,
38-
});
39-
40-
assert.isObject(getField(actual, 'foo').errors);
41-
});
42-
43-
it('should throw an error when given an invalid argument for form state', () => {
44-
assert.throws(() => getField(true, 'foo'));
45-
assert.throws(() => getField(undefined, 'foo'));
46-
assert.throws(() => getField(null, 'foo'));
47-
});
48-
});
49-
5021
describe('deep paths', () => {
5122
it('should be able to handle model at deep state path', () => {
5223
const reducer = formReducer('forms.test');

test/utils-spec.js

Lines changed: 122 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
import invertValidators from '../src/utils/invert-validators';
22
import getValidity from '../src/utils/get-validity';
33
import isValidityInvalid from '../src/utils/is-validity-invalid';
4-
import { getFormStateKey } from '../src/utils/get-form';
4+
import getForm, { getFormStateKey } from '../src/utils/get-form';
55
import getFieldFromState from '../src/utils/get-field-from-state';
66
import { createStore, applyMiddleware, combineReducers } from 'redux';
77
import thunk from 'redux-thunk';
88
import mapValues from 'lodash/mapValues';
99
import _get from 'lodash/get';
1010
import { assert } from 'chai';
1111

12-
import { actions, formReducer } from '../src';
12+
import {
13+
actions,
14+
formReducer,
15+
getField,
16+
getModel,
17+
combineForms,
18+
} from '../src';
1319

1420
describe('utils', () => {
1521
describe('invertValidators()', () => {
@@ -160,4 +166,118 @@ describe('utils', () => {
160166
'deep.deeper.thirdForm');
161167
});
162168
});
169+
170+
describe('getField()', () => {
171+
beforeEach(() => getForm.clearCache());
172+
173+
it('should exist', () => {
174+
assert.isFunction(getField);
175+
});
176+
177+
const store = createStore(combineForms({
178+
test: {
179+
foo: 'foo',
180+
deep: {
181+
bar: 'bar',
182+
},
183+
},
184+
}));
185+
186+
it('should find a field from a store', () => {
187+
assert.containSubset(getField(store.getState(), 'test.foo'), {
188+
model: 'test.foo',
189+
});
190+
});
191+
192+
it('should find a deep field from a store', () => {
193+
assert.containSubset(getField(store.getState(), 'test.deep.bar'), {
194+
model: 'test.deep.bar',
195+
});
196+
});
197+
198+
it('should find a nested form from a store', () => {
199+
assert.containSubset(getField(store.getState(), 'test.deep'), {
200+
model: 'test.deep',
201+
});
202+
});
203+
});
204+
205+
describe('getModel', () => {
206+
it('should exist', () => {
207+
assert.isFunction(getModel);
208+
});
209+
210+
const store = createStore(combineForms({
211+
test: {
212+
foo: 'foo',
213+
deep: {
214+
bar: 'bar',
215+
},
216+
},
217+
}));
218+
219+
it('should find a model from a store', () => {
220+
assert.equal(
221+
getModel(store.getState(), 'test.foo'),
222+
'foo');
223+
});
224+
225+
it('should find a deep model from a store', () => {
226+
assert.equal(
227+
getModel(store.getState(), 'test.deep.bar'),
228+
'bar');
229+
});
230+
231+
it('should work with bracket notation', () => {
232+
assert.equal(
233+
getModel(store.getState(), 'test.deep["bar"]'),
234+
'bar');
235+
236+
assert.equal(
237+
getModel(store.getState(), 'test["deep"].bar'),
238+
'bar');
239+
240+
assert.equal(
241+
getModel(store.getState(), 'test["deep"]["bar"]'),
242+
'bar');
243+
});
244+
245+
it('should find a complex model from a store', () => {
246+
assert.deepEqual(
247+
getModel(store.getState(), 'test.deep'),
248+
{ bar: 'bar' });
249+
});
250+
251+
it('should ignore stray periods', () => {
252+
assert.equal(
253+
getModel(store.getState(), 'test.foo.'),
254+
'foo');
255+
});
256+
257+
it('should ignore ending empty brackets', () => {
258+
assert.equal(
259+
getModel(store.getState(), 'test.foo[]'),
260+
'foo');
261+
});
262+
263+
it('should work when given a number index as path', () => {
264+
const arrayStore = createStore(combineForms([
265+
{ foo: 'foo' },
266+
]));
267+
268+
assert.deepEqual(
269+
getModel(arrayStore.getState(), 0),
270+
{ foo: 'foo' });
271+
});
272+
273+
it('should work with an array path', () => {
274+
assert.equal(
275+
getModel(store.getState(), ['test', 'foo']),
276+
'foo');
277+
278+
assert.equal(
279+
getModel(store.getState(), ['test', 'deep', 'bar']),
280+
'bar');
281+
});
282+
});
163283
});

0 commit comments

Comments
 (0)