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

Commit 35dda15

Browse files
committed
Adding tests for LocalForm, and onUpdate and onChange props to <Form>
1 parent b267a6c commit 35dda15

File tree

3 files changed

+139
-8
lines changed

3 files changed

+139
-8
lines changed

src/components/form-component.js

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ const propTypes = {
3636
dispatch: PropTypes.func,
3737
getState: PropTypes.func,
3838
}),
39+
onUpdate: PropTypes.func,
40+
onChange: PropTypes.func,
3941
};
4042

4143
const defaultStrategy = {
@@ -64,23 +66,43 @@ function createFormClass(s = defaultStrategy) {
6466
}
6567

6668
componentDidMount() {
67-
if (!containsEvent(this.props.validateOn, 'change')) return;
69+
this.handleUpdate();
70+
this.handleChange();
6871

69-
this.validate(this.props, true);
72+
if (containsEvent(this.props.validateOn, 'change')) {
73+
this.validate(this.props, true);
74+
}
7075
}
7176

7277
componentWillReceiveProps(nextProps) {
73-
if (!containsEvent(nextProps.validateOn, 'change')) return;
74-
75-
this.validate(nextProps);
78+
if (containsEvent(nextProps.validateOn, 'change')) {
79+
this.validate(nextProps);
80+
}
7681
}
7782

7883
shouldComponentUpdate(nextProps) {
7984
return deepCompareChildren(this, nextProps);
8085
}
8186

82-
componentDidUpdate() {
87+
componentDidUpdate(prevProps) {
88+
this.handleUpdate();
8389
this.handleIntents();
90+
91+
if (!shallowEqual(prevProps.modelValue, this.props.modelValue)) {
92+
this.handleChange();
93+
}
94+
}
95+
96+
handleUpdate() {
97+
if (this.props.onUpdate) {
98+
this.props.onUpdate(this.props.formValue);
99+
}
100+
}
101+
102+
handleChange() {
103+
if (this.props.onChange) {
104+
this.props.onChange(this.props.modelValue);
105+
}
84106
}
85107

86108
attachNode(node) {

src/local.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ class LocalForm extends React.Component {
88
super(props);
99

1010
this.store = props.store || createStore(combineForms({
11-
local: {},
11+
[props.model]: props.initialState,
1212
}));
1313
}
1414

1515
render() {
1616
return (
17-
<Form model="local" store={this.store} {...this.props} />
17+
<Form store={this.store} {...this.props} component="div" />
1818
);
1919
}
2020
}
@@ -25,6 +25,15 @@ LocalForm.propTypes = {
2525
dispatch: PropTypes.func,
2626
getState: PropTypes.func,
2727
}),
28+
29+
// provided props
30+
initialState: PropTypes.any,
31+
model: PropTypes.string.isRequired,
32+
};
33+
34+
LocalForm.defaultProps = {
35+
initialState: {},
36+
model: 'local',
2837
};
2938

3039
export default LocalForm;

test/local-forms-spec.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/* eslint no-return-assign:0 */
2+
import React from 'react';
3+
import { Control } from '../src';
4+
import LocalForm from '../src/local';
5+
import TestUtils from 'react-addons-test-utils';
6+
import { assert } from 'chai';
7+
8+
describe('local forms', () => {
9+
it('should exist', () => {
10+
assert.isFunction(LocalForm);
11+
});
12+
13+
describe('standard usage with onUpdate', () => {
14+
let innerFormState;
15+
16+
const form = TestUtils.renderIntoDocument(
17+
<LocalForm onUpdate={(formValue) => innerFormState = formValue}>
18+
<Control.text model=".foo" />
19+
</LocalForm>
20+
);
21+
22+
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
23+
24+
it('should initially update with the loaded form value', () => {
25+
assert.containSubset(innerFormState, {
26+
$form: {
27+
pristine: true,
28+
},
29+
});
30+
});
31+
32+
it('should behave like a normal form, with an internal Redux state', () => {
33+
input.value = 'changed';
34+
TestUtils.Simulate.change(input);
35+
36+
assert.containSubset(innerFormState, {
37+
$form: {
38+
pristine: false,
39+
},
40+
foo: {
41+
pristine: false,
42+
value: 'changed',
43+
},
44+
});
45+
});
46+
});
47+
48+
describe('standard usage with onChange', () => {
49+
let innerModelState;
50+
51+
const form = TestUtils.renderIntoDocument(
52+
<LocalForm onChange={(modelValue) => innerModelState = modelValue}>
53+
<Control.text model=".foo" />
54+
</LocalForm>
55+
);
56+
57+
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
58+
59+
it('should initially have an empty object (by default) as the model value', () => {
60+
assert.deepEqual(innerModelState, {});
61+
});
62+
63+
it('should behave like a normal form, with an internal Redux state', () => {
64+
input.value = 'changed';
65+
TestUtils.Simulate.change(input);
66+
67+
assert.deepEqual(innerModelState, {
68+
foo: 'changed',
69+
});
70+
});
71+
});
72+
73+
describe('onChange with initialState', () => {
74+
let innerModelState;
75+
76+
const form = TestUtils.renderIntoDocument(
77+
<LocalForm
78+
onChange={(modelValue) => innerModelState = modelValue}
79+
initialState={{ foo: 'bar' }}
80+
>
81+
<Control.text model=".foo" />
82+
</LocalForm>
83+
);
84+
85+
const input = TestUtils.findRenderedDOMComponentWithTag(form, 'input');
86+
87+
it('should initially have an empty object (by default) as the model value', () => {
88+
assert.deepEqual(innerModelState, { foo: 'bar' });
89+
});
90+
91+
it('should behave like a normal form, with an internal Redux state', () => {
92+
input.value = 'changed';
93+
TestUtils.Simulate.change(input);
94+
95+
assert.deepEqual(innerModelState, {
96+
foo: 'changed',
97+
});
98+
});
99+
});
100+
});

0 commit comments

Comments
 (0)