From f51d4e03eea49bdedc911d644477a12239b1b75f Mon Sep 17 00:00:00 2001 From: Johan Girod Date: Wed, 10 Apr 2019 14:48:41 +0200 Subject: [PATCH] Ajoute un test pour le debounce du currency input --- .../components/CurrencyInput/CurrencyInput.js | 36 ++++++++++++------- .../CurrencyInput/CurrencyInput.test.js | 29 ++++++++++++--- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/source/components/CurrencyInput/CurrencyInput.js b/source/components/CurrencyInput/CurrencyInput.js index 1f9d20f7d..9da7bb7de 100644 --- a/source/components/CurrencyInput/CurrencyInput.js +++ b/source/components/CurrencyInput/CurrencyInput.js @@ -16,10 +16,16 @@ class CurrencyInput extends Component { state = { value: this.props.defaultValue } - onChange = debounce(this.props.debounce, this.props.onChange) + onChange = this.props.debounce + ? debounce(this.props.debounce, this.props.onChange) + : this.props.onChange + input = React.createRef() getSnapshotBeforeUpdate = () => { - return this.input.selectionStart + if (!this.input.current) { + return + } + return this.input.current.selectionStart } componentDidMount() { this.adaptInputSize() @@ -28,17 +34,21 @@ class CurrencyInput extends Component { // Because ch mesurement in IE is not consistent with other browsers, we have to apply a multiplier // https://stackoverflow.com/questions/17825638/css3-ch-unit-inconsistent-between-ie9-and-other-browsers const widthMultiplier = isIE() ? 1.4 : 1 - if (this.input && isCurrencyPrefixed(this.props.language)) - this.input.style.width = - widthMultiplier * (this.input.value.length + 0.2) + 'ch' + + if (this.input.current && isCurrencyPrefixed(this.props.language)) + this.input.current.style.width = + widthMultiplier * (this.input.current.value.length + 0.2) + 'ch' } componentDidUpdate = (_, __, cursorPosition) => { - this.input.selectionStart = cursorPosition - this.input.selectionEnd = cursorPosition + if (!this.input.current) { + return + } + this.input.current.selectionStart = cursorPosition + this.input.current.selectionEnd = cursorPosition this.adaptInputSize() } focusInput = () => { - this.input.focus() + this.input.current.focus() } handleChange = event => { let value = event.target.value @@ -51,15 +61,17 @@ class CurrencyInput extends Component { if (value.endsWith('.')) { return } - event.target.value = value - event.persist() + + if (event.persist) { + event.persist() + } this.onChange(event) } render() { let forwardedProps = dissoc( - ['onChange', 'defaultValue', 'language', 'className', 'defaultValue'], + ['onChange', 'defaultValue', 'language', 'className', 'value'], this.props ) @@ -76,7 +88,7 @@ class CurrencyInput extends Component { className="currencyInput__input" inputMode="numeric" onChange={this.handleChange} - ref={ref => (this.input = ref)} + ref={this.input} value={this.state.value} /> {!isCurrencyPrefixed(this.props.language) && <> €} diff --git a/source/components/CurrencyInput/CurrencyInput.test.js b/source/components/CurrencyInput/CurrencyInput.test.js index 90120b297..2abaa2ce5 100644 --- a/source/components/CurrencyInput/CurrencyInput.test.js +++ b/source/components/CurrencyInput/CurrencyInput.test.js @@ -1,14 +1,15 @@ -import CurrencyInput from './CurrencyInput' -import React from 'react' -import { shallow } from 'enzyme' import { expect } from 'chai' -import { spy, match } from 'sinon' +import { shallow } from 'enzyme' +import React from 'react' +import { match, spy, useFakeTimers } from 'sinon' +import CurrencyInput from './CurrencyInput' let getInput = component => shallow(component).find('input') describe('CurrencyInput', () => { it('should render an input', () => { expect(getInput()).to.have.length(1) }) + it('should accept both . and , as decimal separator', () => { let onChange = spy() const input = getInput() @@ -21,6 +22,7 @@ describe('CurrencyInput', () => { match.hasNested('target.value', '12.1') ) }) + it('should not accept negative number', () => { let onChange = spy() const input = getInput() @@ -65,4 +67,23 @@ describe('CurrencyInput', () => { .text() ).to.includes('€') }) + + it('should debounce onChange call', () => { + const clock = useFakeTimers() + let onChange = spy() + const input = getInput( + + ) + input.simulate('change', { target: { value: '1' } }) + expect(onChange).not.to.have.been.called + clock.tick(500) + input.simulate('change', { target: { value: '12' } }) + clock.tick(600) + expect(onChange).not.to.have.been.called + clock.tick(400) + expect(onChange).to.have.been.calledWith( + match.hasNested('target.value', '12') + ) + clock.restore() + }) })