import React from 'react'; import InputNumber, { InputNumber as BaseInputNumber } from '../index'; import { mount } from 'enzyme'; import sinon from 'sinon'; import keyCode from '@douyinfe/semi-foundation/utils/keyCode'; import * as _ from 'lodash'; import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants'; import { numbers } from '@douyinfe/semi-foundation/inputNumber/constants'; import { Form, withField, useFormApi } from '../../index'; const log = (...args) => console.log(...args); const times = (n = 0, fn) => { if (typeof n === 'number' && typeof fn === 'function') { for (let i = 0; i < n; i++) { fn(i); } } }; describe(`InputNumber`, () => { /** * test appearance */ it(`with 'defaultValue', 'showClear', 'size', 'suffix', 'ref'`, () => { const defaultValue = 1020; const sizeEntries = [ ['default', `${BASE_CLASS_PREFIX}-input-default`], ['large', `${BASE_CLASS_PREFIX}-input-large`], ['small', `${BASE_CLASS_PREFIX}-input-small`], ]; const showClear = true; sizeEntries.forEach(([size, className]) => { const inputNumber = mount(); expect(inputNumber.find('input').hasClass(className)).toBe(true); }); const inputNumberWithoutBtn = mount(); expect(inputNumberWithoutBtn.find('button').length).toBe(0); /** * ref object */ const refObject = { current: undefined }; const inputNumberWithRefObject = mount(); expect(inputNumberWithRefObject.find('input').getDOMNode()).toBe(refObject.current); /** * ref function */ let refNode = null; const refFn = sinon.spy(node => (refNode = node)); const inputNumberWithRefFn = mount(); expect(refFn.calledOnce).toBe(true); expect(inputNumberWithRefFn.find('input').getDOMNode()).toBe(refNode); }); /** * test events */ it(`with 'value', 'onBlur', 'onChange', 'onInput', 'onFocus', 'onKeyDown'`, () => { const onChange = sinon.spy(log); const oldValue = 1020; const newValue = 1301; const newValidStr = '1309'; const newInvalidValue = `1301fd`; const emptyValue = ''; const event = { target: { value: newInvalidValue, }, }; const onBlur = sinon.spy(); const onFocus = sinon.spy(); const onKeyDown = sinon.spy(); const inputNumber = mount( ); inputNumber.find('input').simulate('change', event); expect(onChange.calledOnce).toBe(true); expect(onChange.calledWithMatch(event.target.value)).toBe(true); /** * set an invalid value and blur */ inputNumber.find('input').simulate('focus'); inputNumber.setProps({ value: newInvalidValue }); inputNumber.find('input').simulate('blur'); expect(onBlur.calledOnce).toBe(true); expect(inputNumber.find('input').instance().value).toBe(oldValue.toString()); /** * empty */ inputNumber.setProps({ value: emptyValue }); expect(inputNumber.find('input').getDOMNode().value).toBe(''); /** * focusing and set a valid value */ inputNumber.find('input').simulate('focus'); inputNumber.setProps({ value: newValue }); inputNumber.find('input').simulate('blur'); expect(inputNumber.find('input').instance().value).toBe(newValue.toString()); /** * focusing and set a invalid value */ inputNumber.find('input').simulate('focus'); inputNumber.setProps({ value: newInvalidValue }); inputNumber.find('input').simulate('blur'); expect(inputNumber.find('input').instance().value).toBe(newValue.toString()); /** * focusing and set a valid value string */ inputNumber.find('input').simulate('focus'); inputNumber.setProps({ value: newValidStr }); inputNumber.find('input').simulate('blur'); expect(inputNumber.find('input').instance().value).toBe(newValidStr); /** * press up arrow button and down arrow button * * @summary this testing not worked in jest */ const upArrowPressedCount = 3; const downArrowPressedCount = 1; _.times(upArrowPressedCount, () => { inputNumber.find('input').simulate('keydown', { keyCode: keyCode.UP }); // inputNumber.find('input').simulate('keypress', { key: 'ArrowUp' }); }); _.times(downArrowPressedCount, () => { inputNumber.find('input').simulate('keydown', { keyCode: keyCode.DOWN }); // inputNumber.find('input').simulate('keypress', { key: 'ArrowDown' }); }); // expect(inputNumber.find('input').instance().value).toBe( // String(Number(newValidStr) + upArrowPressedCount - downArrowPressedCount) // ); expect(onKeyDown.called).toBe(true); }); /** * test limits */ it(`with 'max', 'min', 'value', 'onChange', 'precision', 'parser', 'formatter'`, () => { const oldValue = 1020.245; const newValue = 1302.921; const min = 1000; const max = 1300; const event = { target: { value: newValue, }, }; const precision = 2; const formatter = value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ','); const parser = value => value.replace(/\$\s?|(,*)/g, ''); const onChange = sinon.spy(); const onBlur = sinon.spy(); const inputNumber = mount( ); const inputElem = inputNumber.find('input'); inputElem.simulate('change', event); expect(onChange.calledTwice).toBe(true); expect(onChange.getCall(1).args[0]).toEqual(Number(newValue.toFixed(precision))); // expect(onChange.calledWithMatch(Number(newValue.toFixed(precision)))).toBe(true); expect(inputElem.instance().value).toBe(formatter(newValue)); inputElem.simulate('blur'); expect(onBlur.calledOnce).toBe(true); inputNumber.setProps({ value: newValue }); expect(inputElem.instance().value).toBe(formatter(max.toFixed(precision))); inputNumber.setProps({ value: min - 100 }); expect(inputElem.instance().value).toBe(formatter(min.toFixed(precision))); }); /** * test buttons */ it(`click add/minus button, 'onUpClick', 'onDownClick'`, async () => { const defaultValue = 1000; const onUpClick = sinon.spy(); const onDownClick = sinon.spy(); const inputNumber = mount( ); const inputElem = inputNumber.find('input'); const btns = inputNumber.find(`.${BASE_CLASS_PREFIX}-input-number-suffix-btns .${BASE_CLASS_PREFIX}-input-number-button`); const addBtn = btns.first(); const minusBtn = btns.last(); const addCount = 3; const minusCount = 1; _.times(addCount, () => addBtn.simulate('mousedown', { button: numbers.MOUSE_BUTTON_LEFT })); _.times(minusCount, () => minusBtn.simulate('mousedown', { button: numbers.MOUSE_BUTTON_LEFT })); expect(inputElem.instance().value).toBe(String(defaultValue + addCount - minusCount)); expect(onUpClick.called).toBe(true); expect(onDownClick.called).toBe(true); }); it(`click inner add/minus button, 'onUpClick', 'onDownClick'`, async () => { const defaultValue = 1000; const onUpClick = sinon.spy(); const onDownClick = sinon.spy(); const inputNumber = mount( ); const inputElem = inputNumber.find('input'); const inputWrapper = inputNumber.find(`.${BASE_CLASS_PREFIX}-input-number`); inputWrapper.simulate('mouseEnter'); const btns = inputNumber.find(`.${BASE_CLASS_PREFIX}-input-number-suffix-btns .${BASE_CLASS_PREFIX}-input-number-button`); const addBtn = btns.first(); const minusBtn = btns.last(); const addCount = 3; const minusCount = 1; _.times(addCount, () => addBtn.simulate('mousedown', { button: numbers.MOUSE_BUTTON_LEFT })); _.times(minusCount, () => minusBtn.simulate('mousedown', { button: numbers.MOUSE_BUTTON_LEFT })); expect(inputElem.instance().value).toBe(String(defaultValue + addCount - minusCount)); expect(onUpClick.called).toBe(true); expect(onDownClick.called).toBe(true); }); it('shiftStep prop', () => { // shiftStep test const inputNumber = mount(); expect(inputNumber.props().shiftStep).toEqual(100); inputNumber.setProps({ shiftStep: 5 }); inputNumber.update(); expect(inputNumber.props().shiftStep).toEqual(5); }); /** * test input focus, click button focus & default behavior without keepFocus prop */ it('keepFocus prop', async () => { const defaultValue = 1; const onBlur = sinon.spy(); const onFocus = sinon.spy(); const inputNumber = mount( ); const inputElem = inputNumber.find('input'); const btns = inputNumber.find(`.${BASE_CLASS_PREFIX}-input-number-suffix-btns .${BASE_CLASS_PREFIX}-input-number-button`); const addBtn = btns.first(); const minusBtn = btns.last(); // default focus expect(inputNumber.find(`.${BASE_CLASS_PREFIX}-input-wrapper-focus`).length).toBe(0); // click button focus const addCount = 3; const minusCount = 1; _.times(addCount, () => addBtn.simulate('mousedown', { button: numbers.MOUSE_BUTTON_LEFT })); _.times(addCount, () => addBtn.simulate('mouseup')); _.times(minusCount, () => minusBtn.simulate('mousedown', { button: numbers.MOUSE_BUTTON_LEFT })); _.times(minusCount, () => minusBtn.simulate('mouseup')); expect(inputElem.instance().value).toBe(String(defaultValue + addCount - minusCount)); expect(inputNumber.find(BaseInputNumber).state('focusing')).toBeTruthy(); inputNumber.find('input').simulate('blur'); expect(inputNumber.find(BaseInputNumber).state('focusing')).toBeFalsy(); // default behavior without keepFocus prop inputNumber.setProps({ keepFocus: false }); inputNumber.update(); addBtn.simulate('mousedown'); addBtn.simulate('mouseup'); expect(inputNumber.find(BaseInputNumber).state('focusing')).toBeFalsy(); }); it('controlled value out of range', () => { const max = 100; const event = { target: { value: max + 1, }, }; const onChange = sinon.spy(); const onNumberChange = sinon.spy(); const inputNumber = mount(); inputNumber.find('input').simulate('change', event); expect(onChange.calledOnce).toBe(true); expect(onChange.calledWithMatch(event.target.value)).toBe(true); // 受控超出范围时不应调用onNumberChange expect(onNumberChange.called).toBe(false); expect(inputNumber.find(BaseInputNumber).state('number')).toBe(max); }); it('controlled value given NaN', () => { const initValue = 1; const newValue = NaN; const voidString = ""; const inputNumber = mount(); expect(inputNumber.find('input').instance().value).toBe(String(initValue)); expect(inputNumber.find(BaseInputNumber).state('number')).toBe(initValue); inputNumber.setProps({ value: newValue }); expect(inputNumber.find('input').instance().value).toBe(voidString); expect(inputNumber.find(BaseInputNumber).state('number')).toBe(null); }); it('fix number minus bug', () => { const initValue = 0.9; const inputNumber = mount(); const btns = inputNumber.find(`.${BASE_CLASS_PREFIX}-input-number-suffix-btns .${BASE_CLASS_PREFIX}-input-number-button`); const inputElem = inputNumber.find('input'); const addBtn = btns.first(); addBtn.simulate('mousedown', { button: numbers.MOUSE_BUTTON_LEFT }); expect(inputElem.instance().value).toBe("1"); }) // Fix controlled setValue not processed by parser and formatter it('fix controlled setValue', () => { const onNumberChange = sinon.spy(); const CustomInput = withField(InputNumber, { onKeyChangeFnName: 'onNumberChange' }); const App = (
console.log(v)}> `${value}`.replace(/\D/g, '')} onNumberChange={onNumberChange} /> ); const inputNumber = mount(App); const inputElem = inputNumber.find('input'); const event = { target: { value: 'abc' }}; inputElem.simulate('change', event); expect(onNumberChange.calledOnce).toBe(false); expect(inputElem.instance().value).toBe(''); const newEvent = { target: { value: '123' }}; inputElem.simulate('change', newEvent); expect(onNumberChange.calledOnce).toBe(true); expect(inputElem.instance().value).toBe('123'); }); /** * test buttons right click */ it(`right click add/minus button`, async () => { const defaultValue = 1000; const onUpClick = sinon.spy(); const onDownClick = sinon.spy(); const MOUSE_BUTTON_RIGHT = 2; const inputNumber = mount( ); const inputElem = inputNumber.find('input'); const btns = inputNumber.find(`.${BASE_CLASS_PREFIX}-input-number-suffix-btns .${BASE_CLASS_PREFIX}-input-number-button`); const addBtn = btns.first(); const minusBtn = btns.last(); _.times(1, () => addBtn.simulate('mousedown', { button: MOUSE_BUTTON_RIGHT })); _.times(3, () => minusBtn.simulate('mousedown', { button: MOUSE_BUTTON_RIGHT })); expect(inputElem.instance().value).toBe(String(defaultValue)); expect(onUpClick.called).toBe(false); expect(onDownClick.called).toBe(false); }); it('fix controlled min value didMount', () => { const spyChange = sinon.spy(); const inputNumber = mount( ); expect(spyChange.calledOnce).toBe(true); }); it('fix controlled min value didUpdate', () => { const spyChange = sinon.spy(); const value = undefined; const inputNumber = mount( ); inputNumber.setProps({ value: 0 }); expect(spyChange.calledOnce).toBe(true); expect(spyChange.getCall(0).args[0]).toEqual(1); }); it('fix controlled min value form field', () => { const spyChange = sinon.spy(); let formApi = null; let getFormApi = api => { formApi = api; }; const inputNumber = mount(
); expect(spyChange.calledOnce).toBe(true); expect(spyChange.getCall(0).args[0]).toEqual(1); expect(formApi.getValue('minControlled')).toBe(1); }); });