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

Commit

Permalink
Ensuring that debounced update function is canceled upon reset + unit…
Browse files Browse the repository at this point in the history
… tests. Fixes #884
  • Loading branch information
davidkpiano committed Jul 26, 2017
1 parent 396045f commit 4641c38
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 4 deletions.
7 changes: 7 additions & 0 deletions src/components/control-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,13 @@ function createControlClass(s = defaultStrategy) {
return;
}
case 'validate':
case 'reset':
if (intent.type === 'reset') {
this.setViewValue(modelValue);
if (this.handleUpdate.cancel) {
this.handleUpdate.cancel();
}
}
if (containsEvent(validateOn, 'change')) {
this.validate({ clearIntents: intent });
}
Expand Down
2 changes: 1 addition & 1 deletion src/reducers/form-actions-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import getFormValue from '../utils/get-form-value';
const resetFieldState = (field, customInitialFieldState) => {
if (!isPlainObject(field)) return field;

const intents = [{ type: 'validate' }];
const intents = [{ type: 'reset' }];
let resetValue = getMeta(field, 'initialValue');
const loadedValue = getMeta(field, 'loadedValue');

Expand Down
5 changes: 5 additions & 0 deletions src/utils/debounce.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,10 @@ export default function debounce(func, delay) {
if (laterFunc) laterFunc();
};

debouncedFunc.cancel = () => {
clearTimeout(timeout);
laterFunc = undefined;
};

return debouncedFunc;
}
60 changes: 60 additions & 0 deletions test/control-component-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2144,6 +2144,66 @@ Object.keys(testContexts).forEach((testKey) => {
assert.equal(get(store.getState().test, 'foo'), 'debounced');
assert.equal(input.value, 'debounced');
});

it('should cancel debounced changes when control is reset', (done) => {
const initialState = getInitialState({ foo: 'bar' });
const store = testCreateStore({
test: modelReducer('test', initialState),
testForm: formReducer('test', initialState),
});

const control = testRender(
<Control.text
model="test.foo"
debounce={10}
/>, store);

const input = TestUtils.findRenderedDOMComponentWithTag(control, 'input');
input.value = 'debounced';

TestUtils.Simulate.change(input);

store.dispatch(actions.reset('test'));

setTimeout(() => {
assert.equal(get(store.getState().test, 'foo'), 'bar');
assert.equal(input.value, 'bar');
done();
}, 20);
});

it('should cancel debounced changes when control is reset then unmounted', (done) => {
const initialState = getInitialState({ foo: 'bar' });
const store = testCreateStore({
test: modelReducer('test', initialState),
testForm: formReducer('test', initialState),
});

const container = document.createElement('div');

const control = ReactDOM.render(
<Provider store={store}>
<Control.text
model="test.foo"
debounce={10}
/>
</Provider>,
container);

const input = TestUtils.findRenderedDOMComponentWithTag(control, 'input');
input.value = 'debounced';

TestUtils.Simulate.change(input);

store.dispatch(actions.reset('test'));
ReactDOM.unmountComponentAtNode(container);

setTimeout(() => {
assert.equal(get(store.getState().test, 'foo'), 'bar');
assert.equal(input.value, 'bar');
done();
}, 20);
});
});

describe('persist prop', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/field-actions-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ Object.keys(testContexts).forEach((testKey) => {

const resetState = reducer(undefined, actions.reset('test'));

assert.include(resetState.$form.intents, { type: 'validate' });
assert.include(resetState.$form.intents, { type: 'reset' });

assert.include(resetState.button.$form.intents, { type: 'validate' },
'should intend to revalidate subfields');
assert.include(resetState.button.$form.intents, { type: 'reset' },
'should intend to revalidate subfields (handled with reset)');
});
});

Expand Down

0 comments on commit 4641c38

Please sign in to comment.