UNPKG

react-numeric-input

Version:

Number input component that can replace the native number input which is not yet very well supported and where it is, it does not have the same appearance across the browsers. Additionally this component offers more flexible options and can be used for an

433 lines (369 loc) 15.6 kB
/* global describe, it */ import expect from 'expect' import NumericInput from '../src/NumericInput.jsx' import React from 'react' import ReactDOM from 'react-dom' import TestUtils from 'react-dom/test-utils' const KEYCODE_UP = 38; const KEYCODE_DOWN = 40; const DELAY = NumericInput.DELAY; describe('NumericInput', function() { this.timeout(20000); it('works like inpit[type="number"] by default', () => { var widget = TestUtils.renderIntoDocument(<NumericInput />); expect(widget.refsInput.value).toEqual(''); expect(widget.refsInput.type).toEqual('text'); }); it('accepts all the props', () => { var widget = TestUtils.renderIntoDocument( <NumericInput value={5} min={4.9} max={5.3} step={0.2} precision={2} className="form-control" /> ), inputNode = widget.refsInput; // Test the precision expect(inputNode.value).toEqual('5.00'); expect(inputNode.className).toEqual('form-control'); // Test the step TestUtils.Simulate.keyDown(inputNode, { keyCode: KEYCODE_UP }); expect(inputNode.value).toEqual('5.20'); // Test the max TestUtils.Simulate.keyDown(inputNode, { keyCode: KEYCODE_UP }); expect(inputNode.value).toEqual('5.30'); // Test the min TestUtils.Simulate.keyDown(inputNode, { keyCode: KEYCODE_DOWN }); expect(inputNode.value).toEqual('5.10'); TestUtils.Simulate.keyDown(inputNode, { keyCode: KEYCODE_DOWN }); expect(inputNode.value).toEqual('4.90'); }); it('accepts value of 0', () => { var widget = TestUtils.renderIntoDocument(<NumericInput value={0}/>), inputNode = widget.refsInput; expect(inputNode.value).toEqual('0'); }); it('accepts value of "0"', () => { var widget = TestUtils.renderIntoDocument(<NumericInput value="0"/>), inputNode = widget.refsInput; expect(inputNode.value).toEqual('0'); }); it('accepts value of ""', () => { var widget = TestUtils.renderIntoDocument(<NumericInput value=""/>), inputNode = widget.refsInput; expect(inputNode.value).toEqual(''); }); it('can auto-increase', (done) => { this.timeout var widget = TestUtils.renderIntoDocument(<NumericInput/>), widgetNode = ReactDOM.findDOMNode(widget), inputNode = widgetNode.firstChild, btnUp = inputNode.nextElementSibling; TestUtils.Simulate.mouseDown(btnUp); expect(inputNode.value).toEqual('1'); setTimeout(() => { expect(inputNode.value).toEqual('2'); TestUtils.Simulate.mouseUp(btnUp); setTimeout(() => { expect(inputNode.value).toEqual('2'); done(); }, DELAY); }, DELAY); }); it('can auto-decrease', (done) => { var widget = TestUtils.renderIntoDocument(<NumericInput/>), widgetNode = ReactDOM.findDOMNode(widget), inputNode = widgetNode.firstChild, btnDown = widgetNode.lastChild; TestUtils.Simulate.mouseDown(btnDown); expect(inputNode.value).toEqual('-1'); setTimeout(() => { expect(inputNode.value).toEqual('-2'); TestUtils.Simulate.mouseUp(btnDown); setTimeout(() => { expect(inputNode.value).toEqual('-2'); done(); }, NumericInput.SPEED); }, DELAY); }); it('will stop increasing on mouseleave', (done) => { var widget = TestUtils.renderIntoDocument(<NumericInput/>), widgetNode = ReactDOM.findDOMNode(widget), inputNode = widgetNode.firstChild, btnUp = inputNode.nextElementSibling; TestUtils.Simulate.mouseDown(btnUp); expect(inputNode.value).toEqual('1'); setTimeout(() => { expect(inputNode.value).toEqual('2'); // TestUtils.Simulate.mouseLeave(widgetNode); TestUtils.Simulate.mouseLeave(btnUp); setTimeout(() => { expect(inputNode.value).toEqual('2'); done(); }, DELAY); }, DELAY); }); it('will stop decreasing on mouseleave', (done) => { var widget = TestUtils.renderIntoDocument(<NumericInput/>), widgetNode = ReactDOM.findDOMNode(widget), inputNode = widgetNode.firstChild, btnDown = widgetNode.lastChild; TestUtils.Simulate.mouseDown(btnDown); expect(inputNode.value).toEqual('-1'); setTimeout(() => { expect(inputNode.value).toEqual('-2'); // TestUtils.Simulate.mouseLeave(widgetNode); TestUtils.Simulate.mouseLeave(btnDown); setTimeout(() => { expect(inputNode.value).toEqual('-2'); done(); }, DELAY); }, DELAY); }); it('uses "format" and "parse" methods', () => { function format(n) { return `That was ${n} days ago`; } function parse(s) { return parseFloat(s.replace(/That\swas\s(\d+)\sdays\sago/gi, '$1')); } var widget = TestUtils.renderIntoDocument( <NumericInput value={5} step={2} format={format} parse={parse} /> ), widgetNode = ReactDOM.findDOMNode(widget), inputNode = widgetNode.firstChild; expect(inputNode.value).toEqual('That was 5 days ago'); TestUtils.Simulate.keyDown(inputNode, { keyCode: KEYCODE_DOWN }); expect(inputNode.value).toEqual('That was 3 days ago'); inputNode.value = 'That was 13 days ago'; TestUtils.Simulate.change(inputNode); TestUtils.Simulate.keyDown(inputNode, { keyCode: KEYCODE_UP }); expect(inputNode.value).toEqual('That was 15 days ago'); }); it('uses the "disabled" prop to disable the UI', () => { var widget = TestUtils.renderIntoDocument( <NumericInput disabled readOnly/> ), widgetNode = ReactDOM.findDOMNode(widget), inputNode = widgetNode.firstChild, btnUp = inputNode.nextElementSibling; expect(inputNode.disabled).toEqual(true); expect(inputNode.readOnly).toEqual(true); // expect(widgetNode.className).toMatch(/\bdisabled\b/); // expect(widgetNode.className).toMatch(/\breadonly\b/); TestUtils.Simulate.mouseDown(btnUp); expect(inputNode.value).toEqual(''); }); // setValue() and getValueAsNumber() --------------------------------------- it('exposes setValue() and getValueAsNumber() on the input', () => { var widget = TestUtils.renderIntoDocument(<NumericInput />); expect(widget.refsInput.getValueAsNumber()).toEqual(0); widget.refsInput.setValue(123.56); expect(widget.refsInput.getValueAsNumber()).toEqual(123.56); }); // Testing styles ---------------------------------------------------------- it('can set wrapper styles', () => { var widget = TestUtils.renderIntoDocument( <NumericInput style={{ wrap: { fontStyle: 'italic' } }}/> ), widgetNode = ReactDOM.findDOMNode(widget); expect(widgetNode.style.fontStyle).toEqual('italic'); }); it('can set input styles', () => { var widget = TestUtils.renderIntoDocument( <NumericInput style={{ input: { fontStyle: 'italic' } }}/> ), widgetNode = ReactDOM.findDOMNode(widget), inputNode = widgetNode.firstChild; expect(inputNode.style.fontStyle).toEqual('italic'); }); it('can set btnUp styles', () => { var widget = TestUtils.renderIntoDocument( <NumericInput style={{ btnUp: { fontStyle: 'italic' } }}/> ), widgetNode = ReactDOM.findDOMNode(widget), btnNode = widgetNode.firstChild.nextElementSibling; expect(btnNode.style.fontStyle).toEqual('italic'); }); it('can set btnDown styles', () => { var widget = TestUtils.renderIntoDocument( <NumericInput style={{ btnDown: { fontStyle: 'italic' } }}/> ), widgetNode = ReactDOM.findDOMNode(widget), btnNode = widgetNode.lastChild; expect(btnNode.style.fontStyle).toEqual('italic'); }); it('can set arrowDown styles', () => { var widget = TestUtils.renderIntoDocument( <NumericInput style={{ arrowDown: { fontStyle: 'italic' } }} mobile={false}/> ), widgetNode = ReactDOM.findDOMNode(widget), arrowDown = widgetNode.lastChild.firstChild; expect(arrowDown.style.fontStyle).toEqual('italic'); }); it('can set arrowUp styles', () => { var widget = TestUtils.renderIntoDocument( <NumericInput style={{ arrowUp: { fontStyle: 'italic' } }} mobile={false}/> ), widgetNode = ReactDOM.findDOMNode(widget), arrowUp = widgetNode.firstChild.nextElementSibling.firstChild; expect(arrowUp.style.fontStyle).toEqual('italic'); }); it('can set btn:state styles', () => { var disabled = false; var widget = TestUtils.renderIntoDocument( <NumericInput disabled={disabled} style={{ 'btn' : { color: 'rgb(1, 2, 3)' }, 'btn:hover' : { color: 'rgb(2, 3, 4)' }, 'btn:active' : { color: 'rgb(3, 4, 5)' }, 'btn:disabled': { color: 'rgb(4, 5, 6)' } }} mobile={false}/> ), widgetNode = ReactDOM.findDOMNode(widget), btnUpNode = widgetNode.firstChild.nextElementSibling, btnDownNode = widgetNode.lastChild; // normal expect(btnUpNode.style.color).toEqual('rgb(1, 2, 3)'); expect(btnDownNode.style.color).toEqual('rgb(1, 2, 3)'); // :hover TestUtils.Simulate.mouseEnter(btnUpNode); expect(btnUpNode.style.color).toEqual('rgb(2, 3, 4)'); TestUtils.Simulate.mouseEnter(btnDownNode); expect(btnDownNode.style.color).toEqual('rgb(2, 3, 4)'); // :active TestUtils.Simulate.mouseDown(btnUpNode); expect(btnUpNode.style.color).toEqual('rgb(3, 4, 5)'); TestUtils.Simulate.mouseDown(btnDownNode); expect(btnDownNode.style.color).toEqual('rgb(3, 4, 5)'); // :disabled widget = TestUtils.renderIntoDocument( <NumericInput disabled style={{ 'btn' : { color: 'rgb(1, 2, 3)'}, 'btn:hover' : { color: 'rgb(2, 3, 4)'}, 'btn:active' : { color: 'rgb(3, 4, 5)'}, 'btn:disabled': { color: 'rgb(4, 5, 6)'} }} mobile={false}/> ); widgetNode = ReactDOM.findDOMNode(widget); btnUpNode = widgetNode.firstChild.nextElementSibling; btnDownNode = widgetNode.lastChild; expect(btnUpNode.style.color).toEqual('rgb(4, 5, 6)'); expect(btnDownNode.style.color).toEqual('rgb(4, 5, 6)'); TestUtils.Simulate.mouseEnter(btnUpNode); expect(btnUpNode.style.color).toEqual('rgb(4, 5, 6)'); TestUtils.Simulate.mouseEnter(btnDownNode); expect(btnDownNode.style.color).toEqual('rgb(4, 5, 6)'); TestUtils.Simulate.mouseDown(btnUpNode); expect(btnUpNode.style.color).toEqual('rgb(4, 5, 6)'); TestUtils.Simulate.mouseDown(btnDownNode); expect(btnDownNode.style.color).toEqual('rgb(4, 5, 6)'); }); it ('can set mobile styles', () => { var widget = TestUtils.renderIntoDocument(<NumericInput mobile/>), widgetNode = ReactDOM.findDOMNode(widget), btnUpNode = widgetNode.firstChild.nextElementSibling, btnDownNode = widgetNode.lastChild; expect(btnUpNode.style.bottom).toEqual('2px'); expect(btnDownNode.style.left).toEqual('2px'); widget = TestUtils.renderIntoDocument(<NumericInput mobile={false}/>), widgetNode = ReactDOM.findDOMNode(widget), btnUpNode = widgetNode.firstChild.nextElementSibling, btnDownNode = widgetNode.lastChild; expect(btnUpNode.style.bottom).toEqual('50%'); expect(btnDownNode.style.top).toEqual('50%'); }); it("calls it's onChange callback properly", () => { var value = null, stringValue = ""; function onChange(valueAsNumber, valueAsString) { value = valueAsNumber stringValue = valueAsString } function format(val) { return val * 100 + 'x'; } var widget = TestUtils.renderIntoDocument( <NumericInput value={0} onChange={onChange} format={format} /> ), widgetNode = ReactDOM.findDOMNode(widget), btnUpNode = widgetNode.firstChild.nextElementSibling, inputNode = widget.refsInput; expect(inputNode.value).toEqual('0x'); expect(value).toEqual(null); TestUtils.Simulate.mouseDown(btnUpNode); expect(inputNode.value).toEqual('100x'); expect(stringValue).toEqual('100x'); expect(value).toEqual(1); }); it("calls it's onFocus and onBlur callbacks", () => { var hasFocus = null; function onFocus() { hasFocus = true; } function onBlur() { hasFocus = false; } var widget = TestUtils.renderIntoDocument( <NumericInput onFocus={onFocus} onBlur={onBlur} /> ), inputNode = widget.refsInput; expect(hasFocus).toEqual(null); TestUtils.Simulate.focus(inputNode); expect(hasFocus).toEqual(true); TestUtils.Simulate.blur(inputNode); expect(hasFocus).toEqual(false); }); it("calls it's onKeyDown callbacks and makest the event cancelable", () => { var hits = 0, widget, inputNode; function onKeyDown(e) { expect(e.target).toEqual(inputNode); if (hits > 0) { e.preventDefault() } hits++; } widget = TestUtils.renderIntoDocument( <NumericInput value={0} onKeyDown={onKeyDown} /> ); inputNode = widget.refsInput; expect(hits).toEqual(0); expect(inputNode.value).toEqual('0'); TestUtils.Simulate.keyDown(inputNode, { keyCode: KEYCODE_UP }); expect(hits).toEqual(1); expect(inputNode.value).toEqual('1'); TestUtils.Simulate.keyDown(inputNode, { keyCode: KEYCODE_UP }); expect(hits).toEqual(2); expect(inputNode.value).toEqual('1'); }); });