Ajoute un test pour le debounce du currency input

pull/512/head
Johan Girod 2019-04-10 14:48:41 +02:00
parent e13f48d535
commit f51d4e03ee
2 changed files with 49 additions and 16 deletions

View File

@ -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) && <>&nbsp;</>}

View File

@ -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(<CurrencyInput />)).to.have.length(1)
})
it('should accept both . and , as decimal separator', () => {
let onChange = spy()
const input = getInput(<CurrencyInput value={0} onChange={onChange} />)
@ -21,6 +22,7 @@ describe('CurrencyInput', () => {
match.hasNested('target.value', '12.1')
)
})
it('should not accept negative number', () => {
let onChange = spy()
const input = getInput(<CurrencyInput value={0} onChange={onChange} />)
@ -65,4 +67,23 @@ describe('CurrencyInput', () => {
.text()
).to.includes('€')
})
it('should debounce onChange call', () => {
const clock = useFakeTimers()
let onChange = spy()
const input = getInput(
<CurrencyInput value={0} onChange={onChange} debounce={1000} />
)
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()
})
})