mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
commit
2c1d5120b5
@ -55,6 +55,7 @@ export default class Wave extends React.Component<WaveProps> {
|
||||
context: ConfigConsumerProps;
|
||||
|
||||
componentDidMount() {
|
||||
this.destroyed = false;
|
||||
const node = this.containerRef.current as HTMLDivElement;
|
||||
if (!node || node.nodeType !== 1) {
|
||||
return;
|
||||
|
@ -46,3 +46,26 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/35870
|
||||
.input-group(@input-number-prefix-cls) {
|
||||
> .@{input-number-prefix-cls}-rtl:first-child {
|
||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||
}
|
||||
> .@{input-number-prefix-cls}-rtl:last-child {
|
||||
border-radius: @border-radius-base 0 0 @border-radius-base;
|
||||
}
|
||||
|
||||
&-addon {
|
||||
.@{input-number-prefix-cls}-group-rtl &:first-child {
|
||||
border-right: @border-width-base @border-style-base @input-border-color;
|
||||
border-left: 0;
|
||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||
}
|
||||
.@{input-number-prefix-cls}-group-rtl &:last-child {
|
||||
border-right: 0;
|
||||
border-left: @border-width-base @border-style-base @input-border-color;
|
||||
border-radius: @border-radius-base 0 0 @border-radius-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import Input from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
import { sleep, render, fireEvent } from '../../../tests/utils';
|
||||
import Password from '../Password';
|
||||
|
||||
describe('Input.Password', () => {
|
||||
@ -17,101 +16,96 @@ describe('Input.Password', () => {
|
||||
const ref = React.createRef();
|
||||
const onSelect = jest.fn();
|
||||
|
||||
const wrapper = mount(<Input.Password onSelect={onSelect} ref={ref} />);
|
||||
const { container } = render(<Input.Password onSelect={onSelect} ref={ref} />);
|
||||
expect(ref.current.input instanceof HTMLInputElement).toBe(true);
|
||||
wrapper.find('input').simulate('select');
|
||||
fireEvent.select(container.querySelector('input'));
|
||||
expect(onSelect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should support size', () => {
|
||||
const wrapper = mount(<Password size="large" />);
|
||||
expect(wrapper.find('.ant-input-affix-wrapper-lg')).toBeTruthy();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment, container } = render(<Password size="large" />);
|
||||
expect(container.querySelector('.ant-input-affix-wrapper-lg')).toBeTruthy();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
|
||||
});
|
||||
|
||||
it('should change type when click', () => {
|
||||
const wrapper = mount(<Input.Password />);
|
||||
wrapper.find('input').simulate('change', { target: { value: '111' } });
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
wrapper.find('.ant-input-password-icon').at(0).simulate('click');
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
wrapper.find('.ant-input-password-icon').at(0).simulate('click');
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment, container } = render(<Input.Password />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: '111' } })
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-input-password-icon'));
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-input-password-icon'));
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('visibilityToggle should work', () => {
|
||||
const wrapper = mount(<Input.Password visibilityToggle={false} />);
|
||||
expect(wrapper.find('.anticon-eye').length).toBe(0);
|
||||
wrapper.setProps({ visibilityToggle: true });
|
||||
expect(wrapper.find('.anticon-eye-invisible').length).toBe(1);
|
||||
const { container, rerender } = render(<Input.Password visibilityToggle={false} />);
|
||||
expect(container.querySelectorAll('.anticon-eye').length).toBe(0);
|
||||
rerender(<Input.Password visibilityToggle />);
|
||||
expect(container.querySelectorAll('.anticon-eye-invisible').length).toBe(1);
|
||||
|
||||
});
|
||||
|
||||
it('should not toggle visibility when disabled prop is true', () => {
|
||||
const wrapper = mount(<Input.Password disabled />);
|
||||
expect(wrapper.find('.anticon-eye-invisible').length).toBe(1);
|
||||
wrapper.find('.anticon-eye-invisible').simulate('click');
|
||||
expect(wrapper.find('.anticon-eye').length).toBe(0);
|
||||
const { container } = render(<Input.Password disabled />);
|
||||
expect(container.querySelectorAll('.anticon-eye-invisible').length).toBe(1);
|
||||
fireEvent.click(container.querySelector('.anticon-eye-invisible'));
|
||||
expect(container.querySelectorAll('.anticon-eye').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should keep focus state', () => {
|
||||
const wrapper = mount(<Input.Password defaultValue="111" autoFocus />, {
|
||||
attachTo: document.body,
|
||||
const { container, unmount } = render(<Input.Password defaultValue="111" autoFocus />, {
|
||||
container: document.body,
|
||||
});
|
||||
expect(document.activeElement).toBe(wrapper.find('input').at(0).getDOMNode());
|
||||
expect(document.activeElement).toBe(container.querySelector('input'));
|
||||
document.activeElement.setSelectionRange(2, 2);
|
||||
expect(document.activeElement.selectionStart).toBe(2);
|
||||
wrapper.find('.ant-input-password-icon').at(0).simulate('mousedown');
|
||||
wrapper.find('.ant-input-password-icon').at(0).simulate('mouseup');
|
||||
wrapper.find('.ant-input-password-icon').at(0).simulate('click');
|
||||
expect(document.activeElement).toBe(wrapper.find('input').at(0).getDOMNode());
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-password-icon'));
|
||||
fireEvent.mouseUp(container.querySelector('.ant-input-password-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-password-icon'));
|
||||
expect(document.activeElement).toBe(container.querySelector('input'));
|
||||
expect(document.activeElement.selectionStart).toBe(2);
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/20541
|
||||
it('should not show value attribute in input element', async () => {
|
||||
const wrapper = mount(<Input.Password />);
|
||||
wrapper
|
||||
.find('input')
|
||||
.at('0')
|
||||
.simulate('change', { target: { value: 'value' } });
|
||||
const { container } = render(<Input.Password />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'value' } });
|
||||
await sleep();
|
||||
expect(wrapper.find('input').at('0').getDOMNode().getAttribute('value')).toBeFalsy();
|
||||
expect(container.querySelector('input').getAttribute('value')).toBeFalsy();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/24526
|
||||
it('should not show value attribute in input element after blur it', async () => {
|
||||
const wrapper = mount(<Input.Password />);
|
||||
wrapper
|
||||
.find('input')
|
||||
.at('0')
|
||||
.simulate('change', { target: { value: 'value' } });
|
||||
const { container } = render(<Input.Password />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'value' } });
|
||||
await sleep();
|
||||
expect(wrapper.find('input').at('0').getDOMNode().getAttribute('value')).toBeFalsy();
|
||||
wrapper.find('input').at('0').simulate('blur');
|
||||
expect(container.querySelector('input').getAttribute('value')).toBeFalsy();
|
||||
fireEvent.blur(container.querySelector('input'))
|
||||
await sleep();
|
||||
expect(wrapper.find('input').at('0').getDOMNode().getAttribute('value')).toBeFalsy();
|
||||
wrapper.find('input').at('0').simulate('focus');
|
||||
expect(container.querySelector('input').getAttribute('value')).toBeFalsy();
|
||||
fireEvent.focus(container.querySelector('input'))
|
||||
await sleep();
|
||||
expect(wrapper.find('input').at('0').getDOMNode().getAttribute('value')).toBeFalsy();
|
||||
expect(container.querySelector('input').getAttribute('value')).toBeFalsy();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/20541
|
||||
it('could be unmount without errors', () => {
|
||||
expect(() => {
|
||||
const wrapper = mount(<Input.Password />);
|
||||
wrapper
|
||||
.find('input')
|
||||
.at('0')
|
||||
.simulate('change', { target: { value: 'value' } });
|
||||
wrapper.unmount();
|
||||
const { container, unmount } = render(<Input.Password />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'value' } });
|
||||
unmount();
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/pull/20544#issuecomment-569861679
|
||||
it('should not contain value attribute in input element with defaultValue', async () => {
|
||||
const wrapper = mount(<Input.Password defaultValue="value" />);
|
||||
const { container } = render(<Input.Password defaultValue="value" />);
|
||||
await sleep();
|
||||
expect(wrapper.find('input').at('0').getDOMNode().getAttribute('value')).toBeFalsy();
|
||||
expect(container.querySelector('input').getAttribute('value')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import Search from '../Search';
|
||||
import Button from '../../button';
|
||||
@ -13,29 +12,29 @@ describe('Input.Search', () => {
|
||||
rtlTest(Search);
|
||||
|
||||
it('should support custom button', () => {
|
||||
const wrapper = mount(<Search enterButton={<button type="button">ok</button>} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<Search enterButton={<button type="button">ok</button>} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support custom Button', () => {
|
||||
const wrapper = mount(<Search enterButton={<Button>ok</Button>} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<Search enterButton={<Button>ok</Button>} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support enterButton null', () => {
|
||||
expect(() => {
|
||||
mount(<Search enterButton={null} />);
|
||||
render(<Search enterButton={null} />);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should support ReactNode suffix without error', () => {
|
||||
const wrapper = mount(<Search suffix={<div>ok</div>} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<Search suffix={<div>ok</div>} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should disable enter button when disabled prop is true', () => {
|
||||
const wrapper = mount(<Search placeholder="input search text" enterButton disabled />);
|
||||
expect(wrapper.find('.ant-btn-primary[disabled]')).toHaveLength(1);
|
||||
const { container } = render(<Search placeholder="input search text" enterButton disabled />);
|
||||
expect(container.querySelectorAll('.ant-btn-primary[disabled]')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should disable search icon when disabled prop is true', () => {
|
||||
@ -124,7 +123,7 @@ describe('Input.Search', () => {
|
||||
it('should trigger onSearch when click search button of native', () => {
|
||||
const onSearch = jest.fn();
|
||||
const onButtonClick = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Search
|
||||
defaultValue="search text"
|
||||
enterButton={
|
||||
@ -135,128 +134,128 @@ describe('Input.Search', () => {
|
||||
onSearch={onSearch}
|
||||
/>,
|
||||
);
|
||||
wrapper.find('button').simulate('click');
|
||||
fireEvent.click(container.querySelector('button'));
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.objectContaining({
|
||||
type: 'click',
|
||||
preventDefault: expect.any(Function),
|
||||
}),
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'click',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
expect(onButtonClick).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should trigger onSearch when press enter', () => {
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mount(<Search defaultValue="search text" onSearch={onSearch} />);
|
||||
wrapper.find('input').simulate('keydown', { key: 'Enter', keyCode: 13 });
|
||||
const { container } = render(<Search defaultValue="search text" onSearch={onSearch} />);
|
||||
fireEvent.keyDown(container.querySelector('input'), { key: 'Enter', keyCode: 13 })
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.objectContaining({
|
||||
type: 'keydown',
|
||||
preventDefault: expect.any(Function),
|
||||
}),
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'keydown',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/34844
|
||||
it('should not trigger onSearch when press enter using chinese inputting method', () => {
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mount(<Search defaultValue="search text" onSearch={onSearch} />);
|
||||
wrapper.find('input').simulate('compositionStart');
|
||||
wrapper.find('input').simulate('keydown', { key: 'Enter', keyCode: 13 });
|
||||
const { container } = render(<Search defaultValue="search text" onSearch={onSearch} />);
|
||||
fireEvent.compositionStart(container.querySelector('input'));
|
||||
fireEvent.keyDown(container.querySelector('input'), { key: 'Enter', keyCode: 13 });
|
||||
expect(onSearch).not.toHaveBeenCalled();
|
||||
|
||||
wrapper.find('input').simulate('compositionEnd');
|
||||
wrapper.find('input').simulate('keydown', { key: 'Enter', keyCode: 13 });
|
||||
fireEvent.compositionEnd(container.querySelector('input'));
|
||||
fireEvent.keyDown(container.querySelector('input'), { key: 'Enter', keyCode: 13 });;
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.objectContaining({
|
||||
type: 'keydown',
|
||||
preventDefault: expect.any(Function),
|
||||
}),
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'keydown',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/14785
|
||||
it('should support addonAfter', () => {
|
||||
const addonAfter = <span>Addon After</span>;
|
||||
const wrapper = mount(<Search addonAfter={addonAfter} />);
|
||||
const wrapperWithEnterButton = mount(<Search enterButton addonAfter={addonAfter} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapperWithEnterButton.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<Search addonAfter={addonAfter} />);
|
||||
const {asFragment: asFragmentWithEnterButton } = render(<Search enterButton addonAfter={addonAfter} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
expect(asFragmentWithEnterButton().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/18729
|
||||
it('should trigger onSearch when click clear icon', () => {
|
||||
const onSearch = jest.fn();
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Search allowClear defaultValue="value" onSearch={onSearch} onChange={onChange} />,
|
||||
);
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(onSearch).toHaveBeenLastCalledWith('', expect.anything());
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should support loading', () => {
|
||||
const wrapper = mount(<Search loading />);
|
||||
const wrapperWithEnterButton = mount(<Search loading enterButton />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapperWithEnterButton.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<Search loading />);
|
||||
const {asFragment: asFragmentWithEnterButton } = render(<Search loading enterButton />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
expect(asFragmentWithEnterButton().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support addonAfter and suffix for loading', () => {
|
||||
const wrapper = mount(<Search loading suffix="suffix" addonAfter="addonAfter" />);
|
||||
const wrapperWithEnterButton = mount(
|
||||
const { asFragment } = render(<Search loading suffix="suffix" addonAfter="addonAfter" />);
|
||||
const {asFragment: asFragmentWithEnterButton } = render(
|
||||
<Search loading enterButton suffix="suffix" addonAfter="addonAfter" />,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapperWithEnterButton.render()).toMatchSnapshot();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
expect(asFragmentWithEnterButton().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support invalid suffix', () => {
|
||||
const wrapper = mount(<Search suffix={[]} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<Search suffix={[]} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support invalid addonAfter', () => {
|
||||
const wrapper = mount(<Search addonAfter={[]} enterButton />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<Search addonAfter={[]} enterButton />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should prevent search button mousedown event', () => {
|
||||
const ref = React.createRef();
|
||||
const wrapper = mount(<Search ref={ref} enterButton="button text" />, {
|
||||
attachTo: document.body,
|
||||
const { container } = render(<Search ref={ref} enterButton="button text" />, {
|
||||
container: document.body,
|
||||
});
|
||||
let prevented = false;
|
||||
ref.current.focus();
|
||||
expect(document.activeElement).toBe(wrapper.find('input').at(0).getDOMNode());
|
||||
wrapper.find('button').simulate('mousedown', {
|
||||
preventDefault: () => {
|
||||
prevented = true;
|
||||
},
|
||||
});
|
||||
expect(prevented).toBeTruthy();
|
||||
expect(document.activeElement).toBe(wrapper.find('input').at(0).getDOMNode());
|
||||
expect(document.activeElement).toBe(container.querySelector('input'));
|
||||
fireEvent.mouseDown(container.querySelector('button'));
|
||||
expect(document.activeElement).toBe(container.querySelector('input'));
|
||||
});
|
||||
|
||||
it('not crash when use function ref', () => {
|
||||
const ref = jest.fn();
|
||||
const wrapper = mount(<Search ref={ref} enterButton />);
|
||||
const { container } = render(<Search ref={ref} enterButton />);
|
||||
expect(() => {
|
||||
wrapper.find('button').simulate('mousedown');
|
||||
fireEvent.mouseDown(container.querySelector('button'));
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/27258
|
||||
it('Search with allowClear should have one className only', () => {
|
||||
const wrapper = mount(<Search allowClear className="className" />);
|
||||
expect(wrapper.find('.ant-input-group-wrapper').hasClass('className')).toBe(true);
|
||||
expect(wrapper.find('.ant-input-affix-wrapper').hasClass('className')).toBe(false);
|
||||
const { container } = render(<Search allowClear className="className" />);
|
||||
expect(container.querySelector('.ant-input-group-wrapper').classList.contains('className')).toBe(true);
|
||||
expect(container.querySelector('.ant-input-affix-wrapper').classList.contains('className')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -43,7 +43,7 @@ exports[`Input allowClear should change type when click 1`] = `
|
||||
|
||||
exports[`Input allowClear should change type when click 2`] = `
|
||||
<span
|
||||
class="ant-input-affix-wrapper"
|
||||
class="ant-input-affix-wrapper ant-input-affix-wrapper-focused"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
|
||||
import type { InputRef } from '../Input';
|
||||
import Input from '..';
|
||||
@ -33,7 +32,7 @@ describe('Input.Focus', () => {
|
||||
|
||||
it('start', () => {
|
||||
const ref = React.createRef<InputRef>();
|
||||
mount(<TextArea ref={ref} defaultValue="light" />);
|
||||
render(<TextArea ref={ref} defaultValue="light" />);
|
||||
ref.current!.focus({ cursor: 'start' });
|
||||
|
||||
expect(focus).toHaveBeenCalled();
|
||||
@ -42,7 +41,7 @@ describe('Input.Focus', () => {
|
||||
|
||||
it('end', () => {
|
||||
const ref = React.createRef<InputRef>();
|
||||
mount(<TextArea ref={ref} defaultValue="light" />);
|
||||
render(<TextArea ref={ref} defaultValue="light" />);
|
||||
ref.current!.focus({ cursor: 'end' });
|
||||
|
||||
expect(focus).toHaveBeenCalled();
|
||||
@ -51,7 +50,7 @@ describe('Input.Focus', () => {
|
||||
|
||||
it('all', () => {
|
||||
const ref = React.createRef<any>();
|
||||
mount(<TextArea ref={ref} defaultValue="light" />);
|
||||
render(<TextArea ref={ref} defaultValue="light" />);
|
||||
ref.current!.focus({ cursor: 'all' });
|
||||
|
||||
expect(focus).toHaveBeenCalled();
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
@ -27,32 +26,32 @@ describe('Input', () => {
|
||||
rtlTest(Input.Group);
|
||||
|
||||
it('should support maxLength', () => {
|
||||
const wrapper = mount(<Input maxLength={3} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<Input maxLength={3} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('select()', () => {
|
||||
const ref = React.createRef<InputRef>();
|
||||
mount(<Input ref={ref} />);
|
||||
render(<Input ref={ref} />);
|
||||
ref.current?.select();
|
||||
});
|
||||
|
||||
it('should support size', () => {
|
||||
const wrapper = mount(<Input size="large" />);
|
||||
expect(wrapper.find('input').hasClass('ant-input-lg')).toBe(true);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment, container } = render(<Input size="large" />);
|
||||
expect(container.querySelector('input')?.classList.contains('ant-input-lg')).toBe(true);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support size in form', () => {
|
||||
const wrapper = mount(
|
||||
const { asFragment, container } = render(
|
||||
<Form size="large">
|
||||
<Form.Item>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</Form>,
|
||||
);
|
||||
expect(wrapper.find('input').hasClass('ant-input-lg')).toBe(true);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(container.querySelector('input')?.classList.contains('ant-input-lg')).toBe(true);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('focus trigger warning', () => {
|
||||
@ -65,15 +64,13 @@ describe('Input', () => {
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
it('trigger warning', () => {
|
||||
const wrapper = mount(<Input />);
|
||||
wrapper.find('input').first().getDOMNode<HTMLInputElement>().focus();
|
||||
wrapper.setProps({
|
||||
suffix: 'light',
|
||||
});
|
||||
const { container, rerender, unmount } = render(<Input />);
|
||||
container.querySelector('input')?.focus();
|
||||
rerender(<Input suffix="light" />);
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Input] When Input is focused, dynamic add or remove prefix / suffix will make it lose focus caused by dom structure change. Read more: https://ant.design/components/input/#FAQ',
|
||||
);
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
@ -115,10 +112,10 @@ describe('Input', () => {
|
||||
const defaultValue = '11111';
|
||||
const valLength = defaultValue.length;
|
||||
const ref = React.createRef<InputRef>();
|
||||
const wrapper = mount(<Input ref={ref} autoFocus defaultValue={defaultValue} />);
|
||||
const { container } = render(<Input ref={ref} autoFocus defaultValue={defaultValue} />);
|
||||
ref.current?.setSelectionRange(valLength, valLength);
|
||||
expect(wrapper.find('input').first().getDOMNode<HTMLInputElement>().selectionStart).toEqual(5);
|
||||
expect(wrapper.find('input').first().getDOMNode<HTMLInputElement>().selectionEnd).toEqual(5);
|
||||
expect(container.querySelector('input')?.selectionStart).toEqual(5);
|
||||
expect(container.querySelector('input')?.selectionEnd).toEqual(5);
|
||||
});
|
||||
});
|
||||
|
||||
@ -230,133 +227,132 @@ describe('As Form Control', () => {
|
||||
);
|
||||
};
|
||||
|
||||
const wrapper = mount(<Demo />);
|
||||
wrapper.find('input').simulate('change', { target: { value: '111' } });
|
||||
wrapper.find('textarea').simulate('change', { target: { value: '222' } });
|
||||
expect(wrapper.find('input').prop('value')).toBe('111');
|
||||
expect(wrapper.find('textarea').prop('value')).toBe('222');
|
||||
wrapper.find('button').simulate('click');
|
||||
expect(wrapper.find('input').prop('value')).toBe('');
|
||||
expect(wrapper.find('textarea').prop('value')).toBe('');
|
||||
const { container } = render(<Demo />);
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: '111' } });
|
||||
fireEvent.change(container.querySelector('textarea')!, { target: { value: '222' } });
|
||||
expect(container.querySelector('input')?.value).toBe('111');
|
||||
expect(container.querySelector('textarea')?.value).toBe('222');
|
||||
fireEvent.click(container.querySelector('button')!);
|
||||
expect(container.querySelector('input')?.value).toBe('');
|
||||
expect(container.querySelector('textarea')?.value).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('should support showCount', () => {
|
||||
it('maxLength', () => {
|
||||
const wrapper = mount(<Input maxLength={5} showCount value="12345" />);
|
||||
expect(wrapper.find('input').prop('value')).toBe('12345');
|
||||
expect(wrapper.find('.ant-input-show-count-suffix').getDOMNode().innerHTML).toBe('5 / 5');
|
||||
const { container } = render(<Input maxLength={5} showCount value="12345" />);
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('5 / 5');
|
||||
});
|
||||
|
||||
it('control exceed maxLength', () => {
|
||||
const wrapper = mount(<Input maxLength={5} showCount value="12345678" />);
|
||||
expect(wrapper.find('input').prop('value')).toBe('12345678');
|
||||
expect(wrapper.find('.ant-input-show-count-suffix').getDOMNode().innerHTML).toBe('8 / 5');
|
||||
const { container } = render(<Input maxLength={5} showCount value="12345678" />);
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBe('12345678');
|
||||
expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('8 / 5');
|
||||
});
|
||||
|
||||
describe('emoji', () => {
|
||||
it('should minimize value between emoji length and maxLength', () => {
|
||||
const wrapper = mount(<Input maxLength={1} showCount value="👀" />);
|
||||
expect(wrapper.find('input').prop('value')).toBe('👀');
|
||||
expect(wrapper.find('.ant-input-show-count-suffix').getDOMNode().innerHTML).toBe('1 / 1');
|
||||
const { container } = render(<Input maxLength={1} showCount value="👀" />);
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBe('👀');
|
||||
expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('1 / 1');
|
||||
|
||||
const wrapper1 = mount(<Input maxLength={2} showCount value="👀" />);
|
||||
expect(wrapper1.find('.ant-input-show-count-suffix').getDOMNode().innerHTML).toBe('1 / 2');
|
||||
const { container: container1 } = render(<Input maxLength={2} showCount value="👀" />);
|
||||
expect(container1.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('1 / 2');
|
||||
});
|
||||
|
||||
it('slice emoji', () => {
|
||||
const wrapper = mount(<Input maxLength={5} showCount value="1234😂" />);
|
||||
expect(wrapper.find('input').prop('value')).toBe('1234😂');
|
||||
expect(wrapper.find('.ant-input-show-count-suffix').getDOMNode().innerHTML).toBe('5 / 5');
|
||||
const { container } = render(<Input maxLength={5} showCount value="1234😂" />);
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBe('1234😂');
|
||||
expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('5 / 5');
|
||||
});
|
||||
});
|
||||
|
||||
it('count formatter', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Input
|
||||
maxLength={5}
|
||||
showCount={{ formatter: ({ count, maxLength }) => `${count}, ${maxLength}` }}
|
||||
value="12345"
|
||||
/>,
|
||||
);
|
||||
expect(wrapper.find('input').prop('value')).toBe('12345');
|
||||
expect(wrapper.find('.ant-input-show-count-suffix').getDOMNode().innerHTML).toBe('5, 5');
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('5, 5');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Input allowClear', () => {
|
||||
it('should change type when click', () => {
|
||||
const wrapper = mount(<Input allowClear />);
|
||||
wrapper.find('input').simulate('change', { target: { value: '111' } });
|
||||
expect(wrapper.find('input').getDOMNode<HTMLInputElement>().value).toEqual('111');
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapper.find('input').getDOMNode<HTMLInputElement>().value).toEqual('');
|
||||
const { asFragment, container } = render(<Input allowClear />);
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: '111' } });
|
||||
expect(container.querySelector('input')?.value).toEqual('111');
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
expect(container.querySelector('input')?.value).toEqual('');
|
||||
});
|
||||
|
||||
it('should not show icon if value is undefined, null or empty string', () => {
|
||||
// @ts-ignore
|
||||
const wrappers = [null, undefined, ''].map(val => mount(<Input allowClear value={val} />));
|
||||
wrappers.forEach(wrapper => {
|
||||
expect(wrapper.find('input').getDOMNode<HTMLInputElement>().value).toEqual('');
|
||||
expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const wrappers = [null, undefined, ''].map(val => render(<Input allowClear value={val} />));
|
||||
wrappers.forEach(({ asFragment, container }) => {
|
||||
expect(container.querySelector('input')?.value).toEqual('');
|
||||
expect(container.querySelector('.ant-input-clear-icon-hidden')).toBeTruthy();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not show icon if defaultValue is undefined, null or empty string', () => {
|
||||
const wrappers = [null, undefined, ''].map(val =>
|
||||
// @ts-ignore
|
||||
mount(<Input allowClear defaultValue={val} />),
|
||||
render(<Input allowClear defaultValue={val} />),
|
||||
);
|
||||
wrappers.forEach(wrapper => {
|
||||
expect(wrapper.find('input').getDOMNode<HTMLInputElement>().value).toEqual('');
|
||||
expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
wrappers.forEach(({ asFragment, container }) => {
|
||||
expect(container.querySelector('input')?.value).toEqual('');
|
||||
expect(container.querySelector('.ant-input-clear-icon-hidden')).toBeTruthy();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it('should trigger event correctly', () => {
|
||||
let argumentEventObject: React.ChangeEvent<HTMLInputElement> | undefined;
|
||||
|
||||
let argumentEventObjectType;
|
||||
let argumentEventObjectValue;
|
||||
const onChange: InputProps['onChange'] = e => {
|
||||
argumentEventObject = e;
|
||||
argumentEventObjectType = e.type;
|
||||
argumentEventObjectValue = e.target.value;
|
||||
};
|
||||
const wrapper = mount(<Input allowClear defaultValue="111" onChange={onChange} />);
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(argumentEventObject?.type).toBe('click');
|
||||
const { container } = render(<Input allowClear defaultValue="111" onChange={onChange} />);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(argumentEventObjectType).toBe('click');
|
||||
expect(argumentEventObjectValue).toBe('');
|
||||
expect(wrapper.find('input').at(0).getDOMNode<HTMLInputElement>().value).toBe('');
|
||||
expect(container.querySelector('input')?.value).toBe('');
|
||||
});
|
||||
|
||||
it('should trigger event correctly on controlled mode', () => {
|
||||
let argumentEventObject: React.ChangeEvent<HTMLInputElement> | undefined;
|
||||
let argumentEventObjectType;
|
||||
let argumentEventObjectValue;
|
||||
const onChange: InputProps['onChange'] = e => {
|
||||
argumentEventObject = e;
|
||||
argumentEventObjectType = e.type;
|
||||
argumentEventObjectValue = e.target.value;
|
||||
};
|
||||
const wrapper = mount(<Input allowClear value="111" onChange={onChange} />);
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(argumentEventObject?.type).toBe('click');
|
||||
const { container } = render(<Input allowClear value="111" onChange={onChange} />);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(argumentEventObjectType).toBe('click');
|
||||
expect(argumentEventObjectValue).toBe('');
|
||||
expect(wrapper.find('input').at(0).getDOMNode<HTMLInputElement>().value).toBe('111');
|
||||
expect(container.querySelector('input')?.value).toBe('111');
|
||||
});
|
||||
|
||||
it('should focus input after clear', () => {
|
||||
const wrapper = mount(<Input allowClear defaultValue="111" />, { attachTo: document.body });
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(document.activeElement).toBe(wrapper.find('input').at(0).getDOMNode());
|
||||
wrapper.unmount();
|
||||
const { container, unmount } = render(<Input allowClear defaultValue="111" />, { container: document.body });
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(document.activeElement).toBe(container.querySelector('input'));
|
||||
unmount();
|
||||
});
|
||||
|
||||
['disabled', 'readOnly'].forEach(prop => {
|
||||
it(`should not support allowClear when it is ${prop}`, () => {
|
||||
const wrapper = mount(<Input allowClear defaultValue="111" {...{ [prop]: true }} />);
|
||||
expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy();
|
||||
const { container } = render(<Input allowClear defaultValue="111" {...{ [prop]: true }} />);
|
||||
expect(container.querySelector('.ant-input-clear-icon-hidden')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -370,17 +366,17 @@ describe('Input allowClear', () => {
|
||||
// https://github.com/ant-design/ant-design/issues/31200
|
||||
it('should not lost focus when clear input', () => {
|
||||
const onBlur = jest.fn();
|
||||
const wrapper = mount(<Input allowClear defaultValue="value" onBlur={onBlur} />, {
|
||||
attachTo: document.body,
|
||||
const { container, unmount } = render(<Input allowClear defaultValue="value" onBlur={onBlur} />, {
|
||||
container: document.body,
|
||||
});
|
||||
wrapper.find('input').getDOMNode<HTMLInputElement>().focus();
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('mouseDown');
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('mouseUp');
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('focus');
|
||||
wrapper.find('.ant-input-clear-icon').at(0).getDOMNode<HTMLInputElement>().click();
|
||||
container.querySelector('input')?.focus();
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-clear-icon')!);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
fireEvent.mouseUp(container.querySelector('.ant-input-clear-icon')!);
|
||||
fireEvent.focus(container.querySelector('.ant-input-clear-icon')!);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(onBlur).not.toBeCalled();
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/31927
|
||||
@ -398,34 +394,35 @@ describe('Input allowClear', () => {
|
||||
);
|
||||
};
|
||||
|
||||
const wrapper = mount(<App />);
|
||||
const { container, unmount } = render(<App />);
|
||||
|
||||
wrapper.find('input').getDOMNode<HTMLInputElement>().focus();
|
||||
wrapper.find('input').simulate('change', { target: { value: '111' } });
|
||||
expect(wrapper.find('input').getDOMNode<HTMLInputElement>().value).toEqual('111');
|
||||
container.querySelector('input')?.focus();
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: '111' } });
|
||||
expect(container.querySelector('input')?.value).toEqual('111');
|
||||
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(wrapper.find('input').getDOMNode<HTMLInputElement>().value).toEqual('');
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(container.querySelector('input')?.value).toEqual('');
|
||||
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('not crash when value is number', () => {
|
||||
const wrapper = mount(<Input suffix="Bamboo" value={1} />);
|
||||
expect(wrapper).toBeTruthy();
|
||||
const { container } = render(<Input suffix="Bamboo" value={1} />);
|
||||
expect(container).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should display boolean value as string', () => {
|
||||
// @ts-ignore
|
||||
const wrapper = mount(<Input value />);
|
||||
expect(wrapper.find('input').first().getDOMNode<HTMLInputElement>().value).toBe('true');
|
||||
wrapper.setProps({ value: false });
|
||||
expect(wrapper.find('input').first().getDOMNode<HTMLInputElement>().value).toBe('false');
|
||||
const { container, rerender } = render(<Input value />);
|
||||
expect(container.querySelector('input')?.value).toBe('true');
|
||||
// @ts-ignore
|
||||
rerender(<Input value={false} />);
|
||||
expect(container.querySelector('input')?.value).toBe('false');
|
||||
});
|
||||
|
||||
it('should support custom clearIcon', () => {
|
||||
const wrapper = mount(<Input allowClear={{ clearIcon: 'clear' }} />);
|
||||
expect(wrapper.find('.ant-input-clear-icon').text()).toBe('clear');
|
||||
const { container } = render(<Input allowClear={{ clearIcon: 'clear' }} />);
|
||||
expect(container.querySelector('.ant-input-clear-icon')?.textContent).toBe('clear');
|
||||
});
|
||||
});
|
||||
|
||||
@ -438,9 +435,9 @@ describe('typescript types ', () => {
|
||||
'data-testid': 'test-id',
|
||||
'data-id': '12345',
|
||||
};
|
||||
const wrapper = mount(<Input {...props} />);
|
||||
const input = wrapper.find('input').first().getDOMNode();
|
||||
expect(input.getAttribute('data-testid')).toBe('test-id');
|
||||
expect(input.getAttribute('data-id')).toBe('12345');
|
||||
const { container } = render(<Input {...props} />);
|
||||
const input = container.querySelector('input');
|
||||
expect(input?.getAttribute('data-testid')).toBe('test-id');
|
||||
expect(input?.getAttribute('data-id')).toBe('12345');
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import RcTextArea from 'rc-textarea';
|
||||
import Input from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import { sleep, render } from '../../../tests/utils';
|
||||
import { sleep, render, fireEvent, triggerResize } from '../../../tests/utils';
|
||||
|
||||
const { TextArea } = Input;
|
||||
|
||||
@ -69,34 +67,34 @@ describe('TextArea', () => {
|
||||
it('should support onPressEnter and onKeyDown', () => {
|
||||
const fakeHandleKeyDown = jest.fn();
|
||||
const fakeHandlePressEnter = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<TextArea onKeyDown={fakeHandleKeyDown} onPressEnter={fakeHandlePressEnter} />,
|
||||
);
|
||||
/** KeyCode 65 is A */
|
||||
wrapper.find('textarea').simulate('keydown', { keyCode: 65 });
|
||||
fireEvent.keyDown(container.querySelector('textarea'), { keyCode: 65 });
|
||||
expect(fakeHandleKeyDown).toHaveBeenCalledTimes(1);
|
||||
expect(fakeHandlePressEnter).toHaveBeenCalledTimes(0);
|
||||
|
||||
/** KeyCode 13 is Enter */
|
||||
wrapper.find('textarea').simulate('keydown', { keyCode: 13 });
|
||||
fireEvent.keyDown(container.querySelector('textarea'), { keyCode: 13 });
|
||||
expect(fakeHandleKeyDown).toHaveBeenCalledTimes(2);
|
||||
expect(fakeHandlePressEnter).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should support disabled', () => {
|
||||
const wrapper = mount(<TextArea disabled />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<TextArea disabled />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('maxLength', () => {
|
||||
it('should support maxLength', () => {
|
||||
const wrapper = mount(<TextArea maxLength={10} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<TextArea maxLength={10} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('maxLength should not block control', () => {
|
||||
const wrapper = mount(<TextArea maxLength={1} value="light" />);
|
||||
expect(wrapper.find('textarea').props().value).toEqual('light');
|
||||
const { container } = render(<TextArea maxLength={1} value="light" />);
|
||||
expect(container.querySelector('textarea').value).toEqual('light');
|
||||
});
|
||||
|
||||
it('should limit correctly when in control', () => {
|
||||
@ -105,20 +103,20 @@ describe('TextArea', () => {
|
||||
return <TextArea maxLength={1} value={val} onChange={e => setVal(e.target.value)} />;
|
||||
};
|
||||
|
||||
const wrapper = mount(<Demo />);
|
||||
wrapper.find('textarea').simulate('change', { target: { value: 'light' } });
|
||||
const { container } = render(<Demo />);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'light' } });
|
||||
|
||||
expect(wrapper.find('textarea').props().value).toEqual('l');
|
||||
expect(container.querySelector('textarea').value).toEqual('l');
|
||||
});
|
||||
|
||||
it('should exceed maxLength when use IME', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(<TextArea maxLength={1} onChange={onChange} />);
|
||||
wrapper.find('textarea').simulate('compositionStart');
|
||||
wrapper.find('textarea').simulate('change', { target: { value: 'zhu' } });
|
||||
wrapper.find('textarea').simulate('compositionEnd', { currentTarget: { value: '竹' } });
|
||||
wrapper.find('textarea').simulate('change', { target: { value: '竹' } });
|
||||
const { container } = render(<TextArea maxLength={1} onChange={onChange} />);
|
||||
fireEvent.compositionStart(container.querySelector('textarea'));
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'zhu' } });
|
||||
fireEvent.compositionEnd(container.querySelector('textarea'), { currentTarget: { value: '竹' } });
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: '竹' } });
|
||||
|
||||
expect(onChange).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({ target: expect.objectContaining({ value: '竹' }) }),
|
||||
@ -128,90 +126,72 @@ describe('TextArea', () => {
|
||||
// 字符输入
|
||||
it('should not cut off string when cursor position is not at the end', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<TextArea maxLength={6} defaultValue="123456" onChange={onChange} />);
|
||||
wrapper
|
||||
.find('textarea')
|
||||
.simulate('change', { target: { selectionStart: 1, value: 'w123456' } });
|
||||
wrapper
|
||||
.find('textarea')
|
||||
.simulate('change', { target: { selectionStart: 3, value: '123w456' } });
|
||||
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('123456');
|
||||
const { container } = render(<TextArea maxLength={6} defaultValue="123456" onChange={onChange} />);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { selectionStart: 1, value: 'w123456' } });
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { selectionStart: 3, value: 'w123456' } });
|
||||
expect(container.querySelector('textarea').value).toBe('123456');
|
||||
});
|
||||
|
||||
// 拼音输入
|
||||
// 1. 光标位于最后,且当前字符数未达到6个,若选中的字符 + 原字符的长度超过6个,则将最终的字符按照maxlength截断
|
||||
it('when the input method is pinyin and the cursor is at the end, should use maxLength to crop', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<TextArea maxLength={6} defaultValue="1234" onChange={onChange} />);
|
||||
wrapper.find('textarea').instance().value = '1234'; // enzyme not support change `currentTarget`
|
||||
wrapper.find('textarea').instance().selectionStart = 4;
|
||||
wrapper.find('textarea').simulate('compositionStart');
|
||||
const { container } = render(<TextArea maxLength={6} defaultValue="1234" onChange={onChange} />);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { selectionStart: 4, value: '1234' } });
|
||||
fireEvent.compositionStart(container.querySelector('textarea'));
|
||||
|
||||
wrapper
|
||||
.find('textarea')
|
||||
.simulate('change', { target: { selectionStart: 9, value: '1234z z z' } });
|
||||
wrapper
|
||||
.find('textarea')
|
||||
.simulate('change', { target: { selectionStart: 7, value: '1234组织者' } });
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { selectionStart: 9, value: '1234z z z' } });
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { selectionStart: 7, value: '1234组织者' } });
|
||||
|
||||
wrapper.find('textarea').instance().value = '1234组织者';
|
||||
wrapper.find('textarea').instance().selectionStart = 7;
|
||||
wrapper.find('textarea').simulate('compositionEnd');
|
||||
fireEvent.compositionEnd(container.querySelector('textarea'));
|
||||
|
||||
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('1234组织');
|
||||
expect(container.querySelector('textarea').value).toBe('1234组织');
|
||||
});
|
||||
|
||||
// 2. 光标位于中间或开头,且当前字符数未达到6个,若选中的字符 + 原字符的长度超过6个,则显示原有字符
|
||||
it('when the input method is Pinyin and the cursor is in the middle, should display the original string', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<TextArea maxLength={6} defaultValue="1234" onChange={onChange} />);
|
||||
wrapper.find('textarea').instance().value = '1234'; // enzyme not support change `currentTarget`
|
||||
wrapper.find('textarea').instance().selectionStart = 2;
|
||||
wrapper.find('textarea').simulate('compositionStart');
|
||||
const { container } = render(<TextArea maxLength={6} defaultValue="1234" onChange={onChange} />);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { selectionStart: 2, value: '1234' } });
|
||||
fireEvent.compositionStart(container.querySelector('textarea'));
|
||||
|
||||
wrapper
|
||||
.find('textarea')
|
||||
.simulate('change', { target: { selectionStart: 2, value: '12z z z34' } });
|
||||
wrapper
|
||||
.find('textarea')
|
||||
.simulate('change', { target: { selectionStart: 5, value: '12组织者34' } });
|
||||
|
||||
wrapper.find('textarea').instance().value = '12组织者34';
|
||||
wrapper.find('textarea').instance().selectionStart = 5;
|
||||
wrapper.find('textarea').simulate('compositionEnd');
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { selectionStart: 2, value: '12z z z34' } });
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { selectionStart: 5, value: '12组织者34' } });
|
||||
|
||||
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('1234');
|
||||
fireEvent.compositionEnd(container.querySelector('textarea'));
|
||||
|
||||
expect(container.querySelector('textarea').value).toBe('1234');
|
||||
});
|
||||
});
|
||||
|
||||
it('when prop value not in this.props, resizeTextarea should be called', async () => {
|
||||
const ref = React.createRef();
|
||||
const wrapper = mount(<TextArea aria-label="textarea" ref={ref} />);
|
||||
const { container } = render(<TextArea aria-label="textarea" ref={ref} />);
|
||||
const resizeTextarea = jest.spyOn(ref.current.resizableTextArea, 'resizeTextarea');
|
||||
wrapper.find('textarea').simulate('change', {
|
||||
target: {
|
||||
value: 'test',
|
||||
},
|
||||
});
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'test' } });
|
||||
expect(resizeTextarea).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handleKeyDown', () => {
|
||||
const onPressEnter = jest.fn();
|
||||
const onKeyDown = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<TextArea onPressEnter={onPressEnter} onKeyDown={onKeyDown} aria-label="textarea" />,
|
||||
);
|
||||
wrapper.find(RcTextArea).instance().handleKeyDown({ keyCode: 13 });
|
||||
fireEvent.keyDown(container.querySelector('textarea'), { keyCode: 13 });
|
||||
|
||||
expect(onPressEnter).toHaveBeenCalled();
|
||||
expect(onKeyDown).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trigger onResize', async () => {
|
||||
const onResize = jest.fn();
|
||||
const wrapper = mount(<TextArea onResize={onResize} autoSize />);
|
||||
const ref = React.createRef();
|
||||
render(<TextArea ref={ref} onResize={onResize} autoSize />);
|
||||
await sleep(100);
|
||||
wrapper.triggerResize();
|
||||
const target = ref.current.resizableTextArea.textArea;
|
||||
triggerResize(target);
|
||||
await Promise.resolve();
|
||||
|
||||
expect(onResize).toHaveBeenCalledWith(
|
||||
@ -236,86 +216,80 @@ describe('TextArea', () => {
|
||||
|
||||
describe('should support showCount', () => {
|
||||
it('maxLength', () => {
|
||||
const wrapper = mount(<TextArea maxLength={5} showCount value="12345" />);
|
||||
const textarea = wrapper.find('.ant-input-textarea');
|
||||
expect(wrapper.find('textarea').prop('value')).toBe('12345');
|
||||
expect(textarea.prop('data-count')).toBe('5 / 5');
|
||||
const { container } = render(<TextArea maxLength={5} showCount value="12345" />);
|
||||
expect(container.querySelector('textarea').value).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe('5 / 5');
|
||||
});
|
||||
|
||||
it('control exceed maxLength', () => {
|
||||
const wrapper = mount(<TextArea maxLength={5} showCount value="12345678" />);
|
||||
const textarea = wrapper.find('.ant-input-textarea');
|
||||
expect(wrapper.find('textarea').prop('value')).toBe('12345678');
|
||||
expect(textarea.prop('data-count')).toBe('8 / 5');
|
||||
const { container } = render(<TextArea maxLength={5} showCount value="12345678" />);
|
||||
expect(container.querySelector('textarea').value).toBe('12345678');
|
||||
expect(container.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe('8 / 5');
|
||||
});
|
||||
|
||||
describe('emoji', () => {
|
||||
it('should minimize value between emoji length and maxLength', () => {
|
||||
const wrapper = mount(<TextArea maxLength={1} showCount value="👀" />);
|
||||
const textarea = wrapper.find('.ant-input-textarea');
|
||||
expect(wrapper.find('textarea').prop('value')).toBe('👀');
|
||||
expect(textarea.prop('data-count')).toBe('1 / 1');
|
||||
const { container } = render(<TextArea maxLength={1} showCount value="👀" />);
|
||||
expect(container.querySelector('textarea').value).toBe('👀');
|
||||
expect(container.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe('1 / 1');
|
||||
|
||||
// fix: 当 maxLength 长度为 2 的时候,输入 emoji 之后 showCount 会显示 1/2,但是不能再输入了
|
||||
// zombieJ: 逻辑统一了,emoji 现在也可以正确计数了
|
||||
const wrapper1 = mount(<TextArea maxLength={2} showCount value="👀" />);
|
||||
const textarea1 = wrapper1.find('.ant-input-textarea');
|
||||
expect(textarea1.prop('data-count')).toBe('1 / 2');
|
||||
const { container: container1 } = render(<TextArea maxLength={2} showCount value="👀" />);
|
||||
expect(container1.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe('1 / 2');
|
||||
});
|
||||
|
||||
it('defaultValue should slice', () => {
|
||||
const wrapper = mount(<TextArea maxLength={1} defaultValue="🧐cut" />);
|
||||
expect(wrapper.find('textarea').prop('value')).toBe('🧐');
|
||||
const { container } = render(<TextArea maxLength={1} defaultValue="🧐cut" />);
|
||||
expect(container.querySelector('textarea').value).toBe('🧐');
|
||||
});
|
||||
|
||||
// 修改TextArea value截取规则后新增单测
|
||||
it('slice emoji', () => {
|
||||
const wrapper = mount(<TextArea maxLength={5} showCount value="1234😂" />);
|
||||
const textarea = wrapper.find('.ant-input-textarea');
|
||||
expect(wrapper.find('textarea').prop('value')).toBe('1234😂');
|
||||
expect(textarea.prop('data-count')).toBe('5 / 5');
|
||||
const { container } = render(<TextArea maxLength={5} showCount value="1234😂" />);
|
||||
expect(container.querySelector('textarea').value).toBe('1234😂');
|
||||
expect(container.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe('5 / 5');
|
||||
});
|
||||
});
|
||||
|
||||
it('className & style patch to outer', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<TextArea className="bamboo" style={{ background: 'red' }} showCount />,
|
||||
);
|
||||
|
||||
// Outer
|
||||
expect(wrapper.find('div').first().hasClass('bamboo')).toBeTruthy();
|
||||
expect(wrapper.find('div').first().props().style.background).toEqual('red');
|
||||
expect(container.querySelector('div').classList.contains('bamboo')).toBeTruthy();
|
||||
expect(container.querySelector('div').style.background).toEqual('red');
|
||||
|
||||
// Inner
|
||||
expect(wrapper.find('.ant-input').hasClass('bamboo')).toBeFalsy();
|
||||
expect(wrapper.find('.ant-input').props().style.background).toBeFalsy();
|
||||
expect(container.querySelector('.ant-input').classList.contains('bamboo')).toBeFalsy();
|
||||
expect(container.querySelector('.ant-input').style.background).toBeFalsy();
|
||||
});
|
||||
|
||||
it('count formatter', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<TextArea
|
||||
maxLength={5}
|
||||
showCount={{ formatter: ({ count, maxLength }) => `${count}, ${maxLength}` }}
|
||||
value="12345"
|
||||
/>,
|
||||
);
|
||||
const textarea = wrapper.find('.ant-input-textarea');
|
||||
expect(wrapper.find('textarea').prop('value')).toBe('12345');
|
||||
expect(textarea.prop('data-count')).toBe('5, 5');
|
||||
expect(container.querySelector('textarea').value).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe('5, 5');
|
||||
});
|
||||
});
|
||||
|
||||
it('should support size', async () => {
|
||||
const wrapper = mount(<TextArea size="large" />);
|
||||
expect(wrapper.find('textarea').hasClass('ant-input-lg')).toBe(true);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment, container } = render(<TextArea size="large" />);
|
||||
expect(container.querySelector('textarea').classList.contains('ant-input-lg')).toBe(true);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('set mouse cursor position', () => {
|
||||
const defaultValue = '11111';
|
||||
const valLength = defaultValue.length;
|
||||
const ref = React.createRef();
|
||||
mount(<TextArea autoFocus ref={ref} defaultValue={defaultValue} />);
|
||||
render(<TextArea autoFocus ref={ref} defaultValue={defaultValue} />);
|
||||
ref.current.resizableTextArea.textArea.setSelectionRange(valLength, valLength);
|
||||
expect(ref.current.resizableTextArea.textArea.selectionStart).toEqual(5);
|
||||
expect(ref.current.resizableTextArea.textArea.selectionEnd).toEqual(5);
|
||||
@ -324,110 +298,113 @@ describe('TextArea', () => {
|
||||
|
||||
describe('TextArea allowClear', () => {
|
||||
it('should change type when click', () => {
|
||||
const wrapper = mount(<TextArea allowClear />);
|
||||
wrapper.find('textarea').simulate('change', { target: { value: '111' } });
|
||||
expect(wrapper.find('textarea').getDOMNode().value).toEqual('111');
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapper.find('textarea').getDOMNode().value).toEqual('');
|
||||
const { asFragment, container } = render(<TextArea allowClear />);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: '111' } });
|
||||
expect(container.querySelector('textarea').value).toEqual('111');
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
expect(container.querySelector('textarea').value).toEqual('');
|
||||
});
|
||||
|
||||
it('should not show icon if value is undefined, null or empty string', () => {
|
||||
const wrappers = [null, undefined, ''].map(val => mount(<TextArea allowClear value={val} />));
|
||||
wrappers.forEach(wrapper => {
|
||||
expect(wrapper.find('textarea').getDOMNode().value).toEqual('');
|
||||
expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const wrappers = [null, undefined, ''].map(val => render(<TextArea allowClear value={val} />));
|
||||
wrappers.forEach(({ asFragment, container }) => {
|
||||
expect(container.querySelector('textarea').value).toEqual('');
|
||||
expect(container.querySelector('.ant-input-clear-icon-hidden')).toBeTruthy();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not show icon if defaultValue is undefined, null or empty string', () => {
|
||||
const wrappers = [null, undefined, ''].map(val =>
|
||||
mount(<TextArea allowClear defaultValue={val} />),
|
||||
render(<TextArea allowClear defaultValue={val} />),
|
||||
);
|
||||
wrappers.forEach(wrapper => {
|
||||
expect(wrapper.find('textarea').getDOMNode().value).toEqual('');
|
||||
expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy();
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
wrappers.forEach(({ asFragment, container }) => {
|
||||
expect(container.querySelector('textarea').value).toEqual('');
|
||||
expect(container.querySelector('.ant-input-clear-icon-hidden')).toBeTruthy();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it('should trigger event correctly', () => {
|
||||
let argumentEventObject;
|
||||
let argumentEventObjectType;
|
||||
let argumentEventObjectValue;
|
||||
const onChange = e => {
|
||||
argumentEventObject = e;
|
||||
argumentEventObjectType = e.type;
|
||||
argumentEventObjectValue = e.target.value;
|
||||
};
|
||||
const wrapper = mount(<TextArea allowClear defaultValue="111" onChange={onChange} />);
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(argumentEventObject.type).toBe('click');
|
||||
const { container } = render(<TextArea allowClear defaultValue="111" onChange={onChange} />);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(argumentEventObjectType).toBe('click');
|
||||
expect(argumentEventObjectValue).toBe('');
|
||||
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('');
|
||||
expect(container.querySelector('textarea').value).toBe('');
|
||||
});
|
||||
|
||||
it('should trigger event correctly on controlled mode', () => {
|
||||
let argumentEventObject;
|
||||
let argumentEventObjectType;
|
||||
let argumentEventObjectValue;
|
||||
const onChange = e => {
|
||||
argumentEventObject = e;
|
||||
argumentEventObjectType = e.type;
|
||||
argumentEventObjectValue = e.target.value;
|
||||
};
|
||||
const wrapper = mount(<TextArea allowClear value="111" onChange={onChange} />);
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(argumentEventObject.type).toBe('click');
|
||||
const { container } = render(<TextArea allowClear value="111" onChange={onChange} />);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(argumentEventObjectType).toBe('click');
|
||||
expect(argumentEventObjectValue).toBe('');
|
||||
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('111');
|
||||
expect(container.querySelector('textarea').value).toBe('111');
|
||||
});
|
||||
|
||||
it('should focus textarea after clear', () => {
|
||||
const wrapper = mount(<TextArea allowClear defaultValue="111" />, { attachTo: document.body });
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(document.activeElement).toBe(wrapper.find('textarea').at(0).getDOMNode());
|
||||
wrapper.unmount();
|
||||
const { container, unmount } = render(<TextArea allowClear defaultValue="111" />, { container: document.body });
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(document.activeElement).toBe(container.querySelector('textarea'));
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should not support allowClear when it is disabled', () => {
|
||||
const wrapper = mount(<TextArea allowClear defaultValue="111" disabled />);
|
||||
expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy();
|
||||
const { container } = render(<TextArea allowClear defaultValue="111" disabled />);
|
||||
expect(container.querySelector('.ant-input-clear-icon-hidden')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('not block input when `value` is undefined', () => {
|
||||
const wrapper = mount(<Input value={undefined} />);
|
||||
wrapper.find('input').simulate('change', { target: { value: 'Bamboo' } });
|
||||
expect(wrapper.find('input').props().value).toEqual('Bamboo');
|
||||
const { container, rerender } = render(<Input value={undefined} />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'Bamboo' } });
|
||||
expect(container.querySelector('input').value).toEqual('Bamboo');
|
||||
|
||||
// Controlled
|
||||
wrapper.setProps({ value: 'Light' });
|
||||
wrapper.find('input').simulate('change', { target: { value: 'Bamboo' } });
|
||||
expect(wrapper.find('input').props().value).toEqual('Light');
|
||||
rerender(<Input value="Light" />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'Bamboo' } });
|
||||
expect(container.querySelector('input').value).toEqual('Light');
|
||||
});
|
||||
|
||||
it('scroll to bottom when autoSize', async () => {
|
||||
const wrapper = mount(<Input.TextArea autoSize />, { attachTo: document.body });
|
||||
wrapper.find('textarea').simulate('focus');
|
||||
wrapper.find('textarea').getDOMNode().focus();
|
||||
const ref = React.createRef();
|
||||
const { container, unmount } = render(<Input.TextArea ref={ref} autoSize />, { container: document.body, legacyRoot: true });
|
||||
fireEvent.focus(container.querySelector('textarea'));
|
||||
container.querySelector('textarea').focus();
|
||||
|
||||
const setSelectionRangeFn = jest.spyOn(
|
||||
wrapper.find('textarea').getDOMNode(),
|
||||
container.querySelector('textarea'),
|
||||
'setSelectionRange',
|
||||
);
|
||||
wrapper.find('textarea').simulate('input', { target: { value: '\n1' } });
|
||||
wrapper.triggerResize();
|
||||
fireEvent.input(container.querySelector('textarea'), { target: { value: '\n1' } });
|
||||
const target = ref.current.resizableTextArea.textArea;
|
||||
triggerResize(target);
|
||||
await sleep(100);
|
||||
expect(setSelectionRangeFn).toHaveBeenCalled();
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/26308
|
||||
it('should display defaultValue when value is undefined', () => {
|
||||
const wrapper = mount(<Input.TextArea defaultValue="Light" value={undefined} />);
|
||||
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('Light');
|
||||
const { container } = render(<Input.TextArea defaultValue="Light" value={undefined} />);
|
||||
expect(container.querySelector('textarea').value).toBe('Light');
|
||||
});
|
||||
|
||||
it('onChange event should return HTMLTextAreaElement', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<Input.TextArea onChange={onChange} allowClear />);
|
||||
const { container } = render(<Input.TextArea onChange={onChange} allowClear />);
|
||||
|
||||
function isNativeElement() {
|
||||
expect(onChange).toHaveBeenCalledWith(
|
||||
@ -440,20 +417,16 @@ describe('TextArea allowClear', () => {
|
||||
}
|
||||
|
||||
// Change
|
||||
wrapper.find('textarea').simulate('change', {
|
||||
target: {
|
||||
value: 'bamboo',
|
||||
},
|
||||
});
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'bamboo' } });
|
||||
isNativeElement();
|
||||
|
||||
// Composition End
|
||||
wrapper.find('textarea').instance().value = 'light'; // enzyme not support change `currentTarget`
|
||||
wrapper.find('textarea').simulate('compositionEnd');
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'light' } });
|
||||
fireEvent.compositionEnd(container.querySelector('textarea'));
|
||||
isNativeElement();
|
||||
|
||||
// Reset
|
||||
wrapper.find('.ant-input-clear-icon').first().simulate('click');
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
isNativeElement();
|
||||
});
|
||||
|
||||
@ -472,45 +445,44 @@ describe('TextArea allowClear', () => {
|
||||
);
|
||||
};
|
||||
|
||||
const wrapper = mount(<App />);
|
||||
const { container, unmount } = render(<App />);
|
||||
container.querySelector('textarea').focus();
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: '111' } });
|
||||
expect(container.querySelector('textarea').value).toEqual('111');
|
||||
|
||||
wrapper.find('textarea').getDOMNode().focus();
|
||||
wrapper.find('textarea').simulate('change', { target: { value: '111' } });
|
||||
expect(wrapper.find('textarea').getDOMNode().value).toEqual('111');
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(container.querySelector('textarea').value).toEqual('');
|
||||
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(wrapper.find('textarea').getDOMNode().value).toEqual('');
|
||||
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/31200
|
||||
it('should not lost focus when clear input', () => {
|
||||
const onBlur = jest.fn();
|
||||
const wrapper = mount(<TextArea allowClear defaultValue="value" onBlur={onBlur} />, {
|
||||
attachTo: document.body,
|
||||
const { container, unmount } = render(<TextArea allowClear defaultValue="value" onBlur={onBlur} />, {
|
||||
container: document.body,
|
||||
});
|
||||
wrapper.find('textarea').getDOMNode().focus();
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('mouseDown');
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('mouseUp');
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('focus');
|
||||
wrapper.find('.ant-input-clear-icon').at(0).getDOMNode().click();
|
||||
container.querySelector('textarea').focus();
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.mouseUp(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.focus(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(onBlur).not.toBeCalled();
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should focus text area after clear', () => {
|
||||
const wrapper = mount(<TextArea allowClear defaultValue="111" />, { attachTo: document.body });
|
||||
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
|
||||
expect(document.activeElement).toBe(wrapper.find('textarea').at(0).getDOMNode());
|
||||
wrapper.unmount();
|
||||
const { container, unmount } = render(<TextArea allowClear defaultValue="111" />, { container: document.body });
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(document.activeElement).toBe(container.querySelector('textarea'));
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should display boolean value as string', () => {
|
||||
const wrapper = mount(<TextArea value />);
|
||||
expect(wrapper.find('textarea').first().getDOMNode().value).toBe('true');
|
||||
wrapper.setProps({ value: false });
|
||||
expect(wrapper.find('textarea').first().getDOMNode().value).toBe('false');
|
||||
const { container, rerender } = render(<TextArea value />);
|
||||
expect(container.querySelector('textarea').value).toBe('true');
|
||||
rerender(<TextArea value={false} />);
|
||||
expect(container.querySelector('textarea').value).toBe('false');
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Input from '..';
|
||||
import type { InputProps } from '../Input';
|
||||
import { render } from '../../../tests/utils';
|
||||
|
||||
describe('Input types', () => {
|
||||
it('should support data-attributes', () => {
|
||||
@ -9,9 +9,9 @@ describe('Input types', () => {
|
||||
'data-test': 'test',
|
||||
size: 'large',
|
||||
};
|
||||
const wrapper = mount(<Input {...dataProps} />);
|
||||
expect(wrapper.find('input').prop('data-test')).toBe('test');
|
||||
const wrapper2 = mount(<Input data-test="test" size="large" />);
|
||||
expect(wrapper2.find('input').prop('data-test')).toBe('test');
|
||||
const { container } = render(<Input {...dataProps} />);
|
||||
expect(container.querySelector('input')?.getAttribute('data-test')).toBe('test');
|
||||
const { container: container2 } = render(<Input data-test="test" size="large" />);
|
||||
expect(container2.querySelector('input')?.getAttribute('data-test')).toBe('test');
|
||||
});
|
||||
});
|
||||
|
@ -102,6 +102,7 @@
|
||||
.@{inputClass}-group-rtl & {
|
||||
border-right: 0;
|
||||
border-left: @border-width-base @border-style-base @input-border-color;
|
||||
border-radius: @border-radius-base 0 0 @border-radius-base;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ const Statistic: React.FC<StatisticProps & ConfigConsumerProps> = props => {
|
||||
return (
|
||||
<div className={cls} style={style} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
||||
{title && <div className={`${prefixCls}-title`}>{title}</div>}
|
||||
<Skeleton paragraph={false} loading={loading}>
|
||||
<Skeleton paragraph={false} loading={loading} className={`${prefixCls}-skeleton`}>
|
||||
<div style={valueStyle} className={`${prefixCls}-content`}>
|
||||
{prefix && <span className={`${prefixCls}-content-prefix`}>{prefix}</span>}
|
||||
{valueRender ? valueRender(valueNode) : valueNode}
|
||||
|
@ -86,7 +86,7 @@ exports[`renders ./components/statistic/demo/basic.md extend context correctly 1
|
||||
Active Users
|
||||
</div>
|
||||
<div
|
||||
class="ant-skeleton"
|
||||
class="ant-skeleton ant-statistic-skeleton"
|
||||
>
|
||||
<div
|
||||
class="ant-skeleton-content"
|
||||
|
@ -86,7 +86,7 @@ exports[`renders ./components/statistic/demo/basic.md correctly 1`] = `
|
||||
Active Users
|
||||
</div>
|
||||
<div
|
||||
class="ant-skeleton"
|
||||
class="ant-skeleton ant-statistic-skeleton"
|
||||
>
|
||||
<div
|
||||
class="ant-skeleton-content"
|
||||
|
@ -12,6 +12,10 @@
|
||||
font-size: @statistic-title-font-size;
|
||||
}
|
||||
|
||||
&-skeleton {
|
||||
padding-top: @padding-md;
|
||||
}
|
||||
|
||||
&-content {
|
||||
color: @heading-color;
|
||||
font-size: @statistic-content-font-size;
|
||||
|
@ -142,7 +142,7 @@
|
||||
"rc-progress": "~3.3.2",
|
||||
"rc-rate": "~2.9.0",
|
||||
"rc-resize-observer": "^1.2.0",
|
||||
"rc-segmented": "~2.1.0 ",
|
||||
"rc-segmented": "~2.1.0",
|
||||
"rc-select": "~14.1.1",
|
||||
"rc-slider": "~10.0.0",
|
||||
"rc-steps": "~4.1.0",
|
||||
@ -169,7 +169,7 @@
|
||||
"@testing-library/react": "^12.0.0",
|
||||
"@types/enzyme": "^3.10.5",
|
||||
"@types/gtag.js": "^0.0.10",
|
||||
"@types/jest": "^27.0.0",
|
||||
"@types/jest": "^28.0.0",
|
||||
"@types/jest-axe": "^3.5.3",
|
||||
"@types/jest-environment-puppeteer": "^5.0.0",
|
||||
"@types/jest-image-snapshot": "^4.1.0",
|
||||
|
@ -4,6 +4,8 @@ import { StrictMode } from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import type { RenderOptions } from '@testing-library/react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { _rs as onLibResize } from 'rc-resize-observer/lib/utils/observerUtil'
|
||||
import { _rs as onEsResize } from 'rc-resize-observer/es/utils/observerUtil'
|
||||
|
||||
export function setMockDate(dateString = '2017-09-18T03:30:07.795') {
|
||||
MockDate.set(dateString);
|
||||
@ -28,4 +30,14 @@ const customRender = (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>
|
||||
|
||||
export { customRender as render };
|
||||
|
||||
export const triggerResize = (target: Element) => {
|
||||
const originGetBoundingClientRect = target.getBoundingClientRect;
|
||||
|
||||
target.getBoundingClientRect = () => ({ width: 510, height: 903 }) as DOMRect;
|
||||
onLibResize([{ target } as ResizeObserverEntry]);
|
||||
onEsResize([{ target } as ResizeObserverEntry]);
|
||||
|
||||
target.getBoundingClientRect = originGetBoundingClientRect;
|
||||
}
|
||||
|
||||
export * from '@testing-library/react';
|
||||
|
Loading…
Reference in New Issue
Block a user