Skip to content

Commit

Permalink
Merge branch 'input-ranges' of https://github.com/vladaspasic/react-d…
Browse files Browse the repository at this point in the history
…ate-range into test-branch
  • Loading branch information
onurkerimov committed Dec 27, 2019
2 parents 497b130 + dbb0620 commit 205c134
Show file tree
Hide file tree
Showing 6 changed files with 5,601 additions and 365 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
verbose: true,
testURL: 'http://localhost/',
setupFiles: ['<rootDir>/setupTests.js'],
testPathIgnorePatterns: ['/node_modules/', '/dist/', '/demo/dist/'],
snapshotSerializers: ['enzyme-to-json/serializer'],
Expand Down
41 changes: 21 additions & 20 deletions src/components/DefinedRange.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import styles from '../styles';
import { defaultInputRanges, defaultStaticRanges } from '../defaultRanges';
import { rangeShape } from './DayCell';
import InputRangeField from './InputRangeField';
import cx from 'classnames';

class DefinedRanges extends Component {
Expand All @@ -24,6 +25,17 @@ class DefinedRanges extends Component {
});
}

getRangeOptionValue(option) {
const { ranges = [], focusedRange = [] } = this.props;

if (typeof option.getCurrentValue !== 'function') {
return '';
}

const selectedRange = ranges[focusedRange[0]] || {};
return option.getCurrentValue(selectedRange) || '';
}

getSelectedRange(ranges, staticRange) {
const focusedRangeIndex = ranges.findIndex(range => {
if (!range.startDate || !range.endDate || range.disabled) return false;
Expand Down Expand Up @@ -79,26 +91,15 @@ class DefinedRanges extends Component {
</div>
<div className={styles.inputRanges}>
{this.props.inputRanges.map((rangeOption, i) => (
<div className={styles.inputRange} key={i}>
<input
className={styles.inputRangeInput}
onFocus={() => this.setState({ focusedInput: i, rangeOffset: 0 })}
onBlur={() => this.setState({ rangeOffset: 0 })}
onChange={e => {
let value = parseInt(e.target.value, 10);
value = isNaN(value) ? 0 : Math.max(Math.min(99999, value), 0);
this.handleRangeChange(rangeOption.range(value, this.props));
}}
min={0}
max={99999}
value={
rangeOption.getCurrentValue
? rangeOption.getCurrentValue(ranges[this.props.focusedRange[0]] || {})
: '-'
}
/>
<span className={styles.inputRangeLabel}>{rangeOption.label}</span>
</div>
<InputRangeField
key={i}
styles={styles}
label={rangeOption.label}
onFocus={() => this.setState({ focusedInput: i, rangeOffset: 0 })}
onBlur={() => this.setState({ rangeOffset: 0 })}
onChange={value => this.handleRangeChange(rangeOption.range(value, this.props))}
value={this.getRangeOptionValue(rangeOption)}
/>
))}
</div>
{this.props.footerContent}
Expand Down
73 changes: 73 additions & 0 deletions src/components/InputRangeField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';

const MIN = 0;
const MAX = 99999;

class InputRangeField extends Component {
constructor(props, context) {
super(props, context);

this.onChange = this.onChange.bind(this);
}

shouldComponentUpdate(nextProps) {
const { value, label, placeholder } = this.props;

return (
value !== nextProps.value ||
label !== nextProps.label ||
placeholder !== nextProps.placeholder
);
}

onChange(e) {
const { onChange } = this.props;

let value = parseInt(e.target.value, 10);
value = isNaN(value) ? 0 : Math.max(Math.min(MAX, value), MIN);

onChange(value);
}

render() {
const { label, placeholder, value, styles, onBlur, onFocus } = this.props;

return (
<div className={styles.inputRange}>
<input
className={styles.inputRangeInput}
placeholder={placeholder}
value={value}
min={MIN}
max={MAX}
onChange={this.onChange}
onFocus={onFocus}
onBlur={onBlur}
/>
<span className={styles.inputRangeLabel}>{label}</span>
</div>
);
}
}

InputRangeField.propTypes = {
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
label: PropTypes.string.isRequired,
placeholder: PropTypes.string,
styles: PropTypes.shape({
inputRange: PropTypes.string,
inputRangeInput: PropTypes.string,
inputRangeLabel: PropTypes.string,
}).isRequired,
onBlur: PropTypes.func.isRequired,
onFocus: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
};

InputRangeField.defaultProps = {
value: '',
placeholder: '-',
};

export default InputRangeField;
75 changes: 75 additions & 0 deletions src/components/InputRangeField.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import { mount } from 'enzyme';

import InputRangeField from './InputRangeField';

const styles = {
inputRange: 'range',
inputRangeInput: 'input',
inputRangeLabel: 'label',
};
const toChangeEvent = value => ({ target: { value } });

describe('InputRangeField tests', () => {
test('Should parse input value to number', () => {
const onChange = jest.fn();
const wrapper = mount(
<InputRangeField
label="Input label"
styles={styles}
onChange={onChange}
onFocus={jest.fn()}
onBlur={jest.fn()}
/>
);

wrapper.find('input').simulate('change', toChangeEvent('3'));
expect(onChange).lastCalledWith(3);
wrapper.find('input').simulate('change', toChangeEvent(12));
expect(onChange).lastCalledWith(12);
wrapper.find('input').simulate('change', toChangeEvent(''));
expect(onChange).lastCalledWith(0);
wrapper.find('input').simulate('change', toChangeEvent('invalid number'));
expect(onChange).lastCalledWith(0);
wrapper.find('input').simulate('change', toChangeEvent(-12));
expect(onChange).lastCalledWith(0);
wrapper.find('input').simulate('change', toChangeEvent(99999999));
expect(onChange).lastCalledWith(99999);

expect(onChange).toHaveBeenCalledTimes(6);
expect(wrapper).toMatchSnapshot();
});

test('Should rerender when props change', () => {
const wrapper = mount(
<InputRangeField
value={12}
placeholder="Placeholder"
label="Input label"
styles={styles}
onChange={jest.fn()}
onFocus={jest.fn()}
onBlur={jest.fn()}
/>
);

expect(wrapper.find(`.${styles.inputRangeInput}`).prop('value')).toEqual(12);
expect(wrapper.find(`.${styles.inputRangeInput}`).prop('placeholder')).toEqual('Placeholder');
expect(wrapper.find(`.${styles.inputRangeLabel}`).text()).toEqual('Input label');

wrapper.setProps({ value: '32' });
expect(wrapper.find(`.${styles.inputRangeInput}`).prop('value')).toEqual('32');
expect(wrapper.find(`.${styles.inputRangeInput}`).prop('placeholder')).toEqual('Placeholder');
expect(wrapper.find(`.${styles.inputRangeLabel}`).text()).toEqual('Input label');

wrapper.setProps({ placeholder: '-' });
expect(wrapper.find(`.${styles.inputRangeInput}`).prop('value')).toEqual('32');
expect(wrapper.find(`.${styles.inputRangeInput}`).prop('placeholder')).toEqual('-');
expect(wrapper.find(`.${styles.inputRangeLabel}`).text()).toEqual('Input label');

wrapper.setProps({ label: 'Label' });
expect(wrapper.find(`.${styles.inputRangeInput}`).prop('value')).toEqual('32');
expect(wrapper.find(`.${styles.inputRangeInput}`).prop('placeholder')).toEqual('-');
expect(wrapper.find(`.${styles.inputRangeLabel}`).text()).toEqual('Label');
});
});
Loading

0 comments on commit 205c134

Please sign in to comment.