mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 14:13:37 +08:00
test: js => ts (#37392)
* test: js => ts * test: add test * fix: fix eslint error * test: add test case * fix: fix test error * fix: fix eslint error * fix: fix eslint error * fix: eslint error fix * fix: fallback eslint config & add test case * test: add all test case * fix: bugfix * fix: bugFix * fix: bugFix * fix: bugFix * fix: lint * fix: add React.createRef * fix: add breadcrumbName in Routes * fix: any commit for restart ci/cd * fix: remove type * fix: test fix * fix: test fix * fix: add ts-ignore for id * test: add Icon test case * test: remove ts-ignore * test: add Icon test case
This commit is contained in:
parent
f212b339c7
commit
c34caad24c
@ -8,7 +8,7 @@ describe('AutoComplete children could be focus', () => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
let container;
|
||||
let container: HTMLDivElement;
|
||||
beforeEach(() => {
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
@ -24,10 +24,8 @@ describe('AutoComplete children could be focus', () => {
|
||||
|
||||
it('focus() and onFocus', () => {
|
||||
const handleFocus = jest.fn();
|
||||
const { container: wrapper } = render(<AutoComplete onFocus={handleFocus} />, {
|
||||
attachTo: container,
|
||||
});
|
||||
wrapper.querySelector('input').focus();
|
||||
const { container: wrapper } = render(<AutoComplete onFocus={handleFocus} />, { container });
|
||||
wrapper.querySelector('input')?.focus();
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -36,14 +34,12 @@ describe('AutoComplete children could be focus', () => {
|
||||
|
||||
it('blur() and onBlur', () => {
|
||||
const handleBlur = jest.fn();
|
||||
const { container: wrapper } = render(<AutoComplete onBlur={handleBlur} />, {
|
||||
attachTo: container,
|
||||
});
|
||||
wrapper.querySelector('input').focus();
|
||||
const { container: wrapper } = render(<AutoComplete onBlur={handleBlur} />, { container });
|
||||
wrapper.querySelector('input')?.focus();
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
wrapper.querySelector('input').blur();
|
||||
wrapper.querySelector('input')?.blur();
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -61,17 +57,13 @@ describe('AutoComplete children could be focus', () => {
|
||||
});
|
||||
|
||||
it('child.ref instance should support be focused and blured', () => {
|
||||
let inputRef;
|
||||
const inputRef = React.createRef<HTMLInputElement>();
|
||||
render(
|
||||
<AutoComplete dataSource={[]}>
|
||||
<input
|
||||
ref={node => {
|
||||
inputRef = node;
|
||||
}}
|
||||
/>
|
||||
<input ref={inputRef} />
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(typeof inputRef.focus).toBe('function');
|
||||
expect(typeof inputRef.blur).toBe('function');
|
||||
expect(typeof inputRef.current?.focus).toBe('function');
|
||||
expect(typeof inputRef.current?.blur).toBe('function');
|
||||
});
|
||||
});
|
@ -10,14 +10,14 @@ describe('BackTop', () => {
|
||||
|
||||
it('should scroll to top after click it', async () => {
|
||||
const { container } = render(<BackTop visibilityHeight={-1} />);
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((_, y) => {
|
||||
window.scrollY = y;
|
||||
window.pageYOffset = y;
|
||||
document.documentElement.scrollTop = y;
|
||||
});
|
||||
window.scrollTo(0, 400);
|
||||
expect(document.documentElement.scrollTop).toBe(400);
|
||||
fireEvent.click(container.querySelector('.ant-back-top'));
|
||||
fireEvent.click(container.querySelector('.ant-back-top')!);
|
||||
await sleep(500);
|
||||
expect(document.documentElement.scrollTop).toBe(0);
|
||||
scrollToSpy.mockRestore();
|
||||
@ -26,23 +26,21 @@ describe('BackTop', () => {
|
||||
it('support onClick', async () => {
|
||||
const onClick = jest.fn();
|
||||
const { container } = render(<BackTop onClick={onClick} visibilityHeight={-1} />);
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((_, y) => {
|
||||
window.scrollY = y;
|
||||
window.pageYOffset = y;
|
||||
});
|
||||
document.dispatchEvent(new Event('scroll'));
|
||||
window.scrollTo(0, 400);
|
||||
fireEvent.click(container.querySelector('.ant-back-top'));
|
||||
fireEvent.click(container.querySelector('.ant-back-top')!);
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('invalid target', async () => {
|
||||
const onClick = jest.fn();
|
||||
const { container } = render(
|
||||
<BackTop onClick={onClick} visible target={() => ({ documentElement: {} })} />,
|
||||
);
|
||||
fireEvent.click(container.querySelector('.ant-back-top'));
|
||||
const { container } = render(<BackTop onClick={onClick} visible target={undefined} />);
|
||||
fireEvent.click(container.querySelector('.ant-back-top')!);
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -3,6 +3,7 @@ import accessibilityTest from '../../../tests/shared/accessibilityTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { render } from '../../../tests/utils';
|
||||
import type { Route } from '../Breadcrumb';
|
||||
import Breadcrumb from '../index';
|
||||
|
||||
describe('Breadcrumb', () => {
|
||||
@ -22,7 +23,7 @@ describe('Breadcrumb', () => {
|
||||
|
||||
// https://github.com/airbnb/enzyme/issues/875
|
||||
it('warns on non-Breadcrumb.Item and non-Breadcrumb.Separator children', () => {
|
||||
const MyCom = () => <div>foo</div>;
|
||||
const MyCom: React.FC = () => <div>foo</div>;
|
||||
render(
|
||||
<Breadcrumb>
|
||||
<MyCom />
|
||||
@ -74,7 +75,7 @@ describe('Breadcrumb', () => {
|
||||
});
|
||||
|
||||
it('should render a menu', () => {
|
||||
const routes = [
|
||||
const routes: Route[] = [
|
||||
{
|
||||
path: 'index',
|
||||
breadcrumbName: 'home',
|
||||
@ -103,6 +104,7 @@ describe('Breadcrumb', () => {
|
||||
},
|
||||
{
|
||||
path: 'third',
|
||||
breadcrumbName: '',
|
||||
},
|
||||
];
|
||||
const { asFragment } = render(<Breadcrumb routes={routes} />);
|
||||
@ -142,7 +144,7 @@ describe('Breadcrumb', () => {
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/25975
|
||||
it('should support Breadcrumb.Item default separator', () => {
|
||||
const MockComponent = () => (
|
||||
const MockComponent: React.FC = () => (
|
||||
<span>
|
||||
<Breadcrumb.Item>Mock Node</Breadcrumb.Item>
|
||||
</span>
|
@ -1,9 +1,10 @@
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import type { RouterProps } from 'react-router-dom';
|
||||
import { Link, MemoryRouter, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
||||
import Breadcrumb from '../index';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
const Apps = () => (
|
||||
const Apps: React.FC = () => (
|
||||
<ul className="app-list">
|
||||
<li>
|
||||
<Link to="/apps/1">Application1</Link>:<Link to="/apps/1/detail">Detail</Link>
|
||||
@ -33,7 +34,7 @@ describe('react router', () => {
|
||||
|
||||
// https://github.com/airbnb/enzyme/issues/875
|
||||
it('react router 6', () => {
|
||||
const Home = () => {
|
||||
const Home: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const pathSnippets = location.pathname.split('/').filter(i => i);
|
||||
@ -41,7 +42,7 @@ describe('react router', () => {
|
||||
const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
|
||||
return (
|
||||
<Breadcrumb.Item key={url}>
|
||||
<Link to={url}>{breadcrumbNameMap[url]}</Link>
|
||||
<Link to={url}>{breadcrumbNameMap[url as keyof typeof breadcrumbNameMap]}</Link>
|
||||
</Breadcrumb.Item>
|
||||
);
|
||||
});
|
||||
@ -50,6 +51,14 @@ describe('react router', () => {
|
||||
<Link to="/">Home</Link>
|
||||
</Breadcrumb.Item>,
|
||||
].concat(extraBreadcrumbItems);
|
||||
const componentProps = useMemo<RouterProps>(
|
||||
() => ({ component: Apps } as unknown as RouterProps),
|
||||
[],
|
||||
);
|
||||
const renderProps = useMemo<RouterProps>(
|
||||
() => ({ render: () => <span>Home Page</span> } as unknown as RouterProps),
|
||||
[],
|
||||
);
|
||||
return (
|
||||
<div className="demo">
|
||||
<div className="demo-nav">
|
||||
@ -57,8 +66,8 @@ describe('react router', () => {
|
||||
<a onClick={() => navigate('/apps')}>Application List</a>
|
||||
</div>
|
||||
<Routes>
|
||||
<Route path="/apps" component={Apps} />
|
||||
<Route render={() => <span>Home Page</span>} />
|
||||
<Route path="/apps" {...componentProps} />
|
||||
<Route {...renderProps} />
|
||||
</Routes>
|
||||
<Breadcrumb>{breadcrumbItems}</Breadcrumb>
|
||||
</div>
|
@ -19,10 +19,10 @@ describe('Checkbox', () => {
|
||||
<Checkbox onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />,
|
||||
);
|
||||
|
||||
fireEvent.mouseEnter(container.querySelector('label'));
|
||||
fireEvent.mouseEnter(container.querySelector('label')!);
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
fireEvent.mouseLeave(container.querySelector('label'));
|
||||
fireEvent.mouseLeave(container.querySelector('label')!);
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
|
@ -6,6 +6,8 @@ import Collapse from '../../collapse';
|
||||
import Input from '../../input';
|
||||
import Table from '../../table';
|
||||
import Checkbox from '../index';
|
||||
import type { CheckboxValueType } from '../Group';
|
||||
import type { CheckboxGroupProps } from '../index';
|
||||
|
||||
describe('CheckboxGroup', () => {
|
||||
mountTest(Checkbox.Group);
|
||||
@ -60,9 +62,11 @@ describe('CheckboxGroup', () => {
|
||||
|
||||
it('all children should have a name property', () => {
|
||||
const { container } = render(<Checkbox.Group name="checkboxgroup" options={['Yes', 'No']} />);
|
||||
[...container.querySelectorAll('input[type="checkbox"]')].forEach(el => {
|
||||
expect(el.getAttribute('name')).toEqual('checkboxgroup');
|
||||
});
|
||||
Array.from(container.querySelectorAll<HTMLInputElement>('input[type="checkbox"]')).forEach(
|
||||
el => {
|
||||
expect(el.getAttribute('name')).toEqual('checkboxgroup');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('passes prefixCls down to checkbox', () => {
|
||||
@ -81,10 +85,10 @@ describe('CheckboxGroup', () => {
|
||||
{ label: 'Apple', value: 'Apple' },
|
||||
{ label: 'Orange', value: 'Orange' },
|
||||
];
|
||||
const renderCheckbox = props => <Checkbox.Group {...props} />;
|
||||
const renderCheckbox = (props: CheckboxGroupProps) => <Checkbox.Group {...props} />;
|
||||
const { container, rerender } = render(renderCheckbox({ options }));
|
||||
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(0);
|
||||
rerender(renderCheckbox({ options, value: 'Apple' }));
|
||||
rerender(renderCheckbox({ options, value: 'Apple' as unknown as CheckboxValueType[] }));
|
||||
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(1);
|
||||
});
|
||||
|
||||
@ -116,7 +120,7 @@ describe('CheckboxGroup', () => {
|
||||
<Checkbox key={2} value={2} />
|
||||
</Checkbox.Group>,
|
||||
);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input')!);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith([2]);
|
||||
});
|
||||
@ -164,7 +168,7 @@ describe('CheckboxGroup', () => {
|
||||
const { container } = render(
|
||||
<Checkbox.Group>
|
||||
<Collapse bordered={false}>
|
||||
<Collapse.Panel header="test panel">
|
||||
<Collapse.Panel key="test panel" header="test panel">
|
||||
<div>
|
||||
<Checkbox value="1">item</Checkbox>
|
||||
</div>
|
||||
@ -174,11 +178,11 @@ describe('CheckboxGroup', () => {
|
||||
);
|
||||
|
||||
fireEvent.click(
|
||||
container.querySelector('.ant-collapse-item').querySelector('.ant-collapse-header'),
|
||||
container.querySelector('.ant-collapse-item')?.querySelector('.ant-collapse-header')!,
|
||||
);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input')!);
|
||||
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(1);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input')!);
|
||||
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(0);
|
||||
});
|
||||
|
||||
@ -210,12 +214,12 @@ describe('CheckboxGroup', () => {
|
||||
});
|
||||
|
||||
it('should get div ref', () => {
|
||||
const refCalls = [];
|
||||
const refCalls: HTMLDivElement[] = [];
|
||||
render(
|
||||
<Checkbox.Group
|
||||
options={['Apple', 'Pear', 'Orange']}
|
||||
ref={node => {
|
||||
refCalls.push(node);
|
||||
refCalls.push(node!);
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
@ -230,18 +234,18 @@ describe('CheckboxGroup', () => {
|
||||
<Checkbox.Group options={[1, 'Pear', 'Orange']} onChange={onChange} />,
|
||||
);
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input')!);
|
||||
expect(onChange).toHaveBeenCalledWith([1]);
|
||||
});
|
||||
|
||||
it('should store latest checkbox value if changed', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const Demo = () => {
|
||||
const [v, setV] = useState('');
|
||||
const Demo: React.FC = () => {
|
||||
const [v, setV] = useState<string>('');
|
||||
|
||||
React.useEffect(() => {
|
||||
setTimeout(setV('1'), 1000);
|
||||
setTimeout(setV('1') as unknown as TimerHandler, 1000);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@ -257,12 +261,12 @@ describe('CheckboxGroup', () => {
|
||||
};
|
||||
|
||||
const { container } = render(<Demo />);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input')!);
|
||||
expect(onChange).toHaveBeenCalledWith([]);
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input')!);
|
||||
expect(onChange).toHaveBeenCalledWith(['length1']);
|
||||
fireEvent.change(container.querySelector('.ant-input'), { target: { value: '' } });
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input'));
|
||||
fireEvent.change(container.querySelector('.ant-input')!, { target: { value: '' } });
|
||||
fireEvent.click(container.querySelector('.ant-checkbox-input')!);
|
||||
expect(onChange).toHaveBeenCalledWith(['A']);
|
||||
});
|
||||
});
|
@ -1,12 +1,13 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import type { DrawerProps } from '..';
|
||||
import Drawer from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
|
||||
const DrawerTest = ({ getContainer }) => (
|
||||
const DrawerTest: React.FC<DrawerProps> = ({ getContainer }) => (
|
||||
<div>
|
||||
<Drawer open width={400} getContainer={getContainer}>
|
||||
Here is content of Drawer
|
||||
@ -59,35 +60,37 @@ describe('Drawer', () => {
|
||||
});
|
||||
|
||||
it('getContainer return undefined', () => {
|
||||
const { container: wrapper, rerender } = render(<DrawerTest getContainer={() => undefined} />);
|
||||
const { container, rerender } = render(
|
||||
<DrawerTest getContainer={() => undefined as unknown as HTMLElement} />,
|
||||
);
|
||||
triggerMotion();
|
||||
expect(wrapper.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
|
||||
rerender(<DrawerTest getContainer={false} />);
|
||||
triggerMotion();
|
||||
expect(wrapper.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('render top drawer', () => {
|
||||
const { container: wrapper } = render(
|
||||
<Drawer open height={400} placement="top" getContainer={false}>
|
||||
const { container } = render(
|
||||
<Drawer visible height={400} placement="top" getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
|
||||
triggerMotion();
|
||||
expect(wrapper.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('have a title', () => {
|
||||
const { container: wrapper } = render(
|
||||
const { container } = render(
|
||||
<Drawer open title="Test Title" getContainer={false}>
|
||||
Here is content of Drawer
|
||||
</Drawer>,
|
||||
);
|
||||
|
||||
triggerMotion();
|
||||
expect(wrapper.firstChild).toMatchSnapshot();
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('closable is false', () => {
|
@ -1,14 +1,15 @@
|
||||
import React from 'react';
|
||||
import type { DrawerProps } from '..';
|
||||
import Drawer from '..';
|
||||
import { act, fireEvent, render } from '../../../tests/utils';
|
||||
|
||||
describe('Drawer', () => {
|
||||
const getDrawer = props => (
|
||||
<Drawer open getContainer={false} {...props}>
|
||||
Here is content of Drawer
|
||||
</Drawer>
|
||||
);
|
||||
const DrawerTest: React.FC<DrawerProps> = props => (
|
||||
<Drawer open getContainer={false} {...props}>
|
||||
Here is content of Drawer
|
||||
</Drawer>
|
||||
);
|
||||
|
||||
describe('Drawer', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
@ -18,12 +19,12 @@ describe('Drawer', () => {
|
||||
});
|
||||
|
||||
it('render correctly', () => {
|
||||
const { container, asFragment, rerender } = render(getDrawer());
|
||||
const { container, asFragment, rerender } = render(<DrawerTest />);
|
||||
expect(container.querySelector('.ant-drawer-body')).toBeTruthy();
|
||||
|
||||
rerender(getDrawer({ open: false }));
|
||||
rerender(<DrawerTest open={false} />);
|
||||
|
||||
expect(container.querySelector('.ant-drawer-body').textContent).toEqual(
|
||||
expect(container.querySelector('.ant-drawer-body')?.textContent).toEqual(
|
||||
'Here is content of Drawer',
|
||||
);
|
||||
|
||||
@ -32,33 +33,33 @@ describe('Drawer', () => {
|
||||
|
||||
it('mask trigger onClose', () => {
|
||||
const onClose = jest.fn();
|
||||
const { container } = render(getDrawer({ onClose }));
|
||||
const { container } = render(<DrawerTest onClose={onClose} />);
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-drawer-mask'));
|
||||
fireEvent.click(container.querySelector('.ant-drawer-mask')!);
|
||||
expect(onClose).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('close button trigger onClose', () => {
|
||||
const onClose = jest.fn();
|
||||
const { container } = render(getDrawer({ onClose }));
|
||||
const { container } = render(<DrawerTest onClose={onClose} />);
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-drawer-close'));
|
||||
fireEvent.click(container.querySelector('.ant-drawer-close')!);
|
||||
expect(onClose).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('maskClosable no trigger onClose', () => {
|
||||
const onClose = jest.fn();
|
||||
const { container } = render(getDrawer({ onClose, maskClosable: false }));
|
||||
const { container } = render(<DrawerTest onClose={onClose} maskClosable={false} />);
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-drawer-mask'));
|
||||
fireEvent.click(container.querySelector('.ant-drawer-mask')!);
|
||||
expect(onClose).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('dom should be removed after close when destroyOnClose is true', () => {
|
||||
const { container, rerender } = render(getDrawer({ destroyOnClose: true }));
|
||||
const { container, rerender } = render(<DrawerTest destroyOnClose />);
|
||||
expect(container.querySelector('.ant-drawer')).toBeTruthy();
|
||||
|
||||
rerender(getDrawer({ destroyOnClose: true, open: false }));
|
||||
rerender(<DrawerTest destroyOnClose open={false} />);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -67,53 +68,55 @@ describe('Drawer', () => {
|
||||
});
|
||||
|
||||
it('dom should be existed after close when destroyOnClose is false', () => {
|
||||
const { container, rerender } = render(getDrawer());
|
||||
const { container, rerender } = render(<DrawerTest />);
|
||||
expect(container.querySelector('.ant-drawer')).toBeTruthy();
|
||||
|
||||
rerender(getDrawer({ open: false }));
|
||||
rerender(<DrawerTest open={false} />);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
fireEvent.animationEnd(container.querySelector('.ant-drawer-content'));
|
||||
fireEvent.animationEnd(container.querySelector('.ant-drawer-content')!);
|
||||
|
||||
expect(container.querySelector('.ant-drawer')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('dom should be existed after close twice when getContainer is false', () => {
|
||||
const { container, rerender } = render(getDrawer({ open: true, getContainer: false }));
|
||||
const { container, rerender } = render(<DrawerTest open getContainer={false} />);
|
||||
expect(container.querySelector('.ant-drawer-content')).toBeTruthy();
|
||||
|
||||
// Hide
|
||||
rerender(getDrawer({ open: false, getContainer: false }));
|
||||
rerender(<DrawerTest open={false} getContainer={false} />);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
fireEvent.animationEnd(container.querySelector('.ant-drawer-content-wrapper'));
|
||||
fireEvent.animationEnd(container.querySelector('.ant-drawer-content-wrapper')!);
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper-hidden')).toBeTruthy();
|
||||
|
||||
// Show
|
||||
rerender(getDrawer({ open: true, getContainer: false }));
|
||||
rerender(<DrawerTest open getContainer={false} />);
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toBeTruthy();
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper-hidden')).toBeFalsy();
|
||||
|
||||
// Hide
|
||||
rerender(getDrawer({ open: false, getContainer: false }));
|
||||
rerender(<DrawerTest open={false} getContainer={false} />);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
fireEvent.animationEnd(container.querySelector('.ant-drawer-content-wrapper'));
|
||||
fireEvent.animationEnd(container.querySelector('.ant-drawer-content-wrapper')!);
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper-hidden')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('test afterVisibleChange', async () => {
|
||||
const afterVisibleChange = jest.fn();
|
||||
const { container, rerender } = render(getDrawer({ afterVisibleChange, open: true }));
|
||||
rerender(getDrawer({ afterVisibleChange, open: false }));
|
||||
const { container, rerender } = render(
|
||||
<DrawerTest open afterVisibleChange={afterVisibleChange} />,
|
||||
);
|
||||
rerender(<DrawerTest open={false} afterVisibleChange={afterVisibleChange} />);
|
||||
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
fireEvent.animationEnd(container.querySelector('.ant-drawer-content-wrapper'));
|
||||
fireEvent.animationEnd(container.querySelector('.ant-drawer-content-wrapper')!);
|
||||
|
||||
expect(afterVisibleChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
@ -121,18 +124,18 @@ describe('Drawer', () => {
|
||||
it('should support children ref', () => {
|
||||
const fn = jest.fn();
|
||||
|
||||
const refCallback = ref => {
|
||||
const refCallback = (ref: HTMLDivElement | null) => {
|
||||
expect(typeof ref).toBe('object');
|
||||
fn();
|
||||
};
|
||||
|
||||
const RefDemo = () => {
|
||||
const ref = React.useRef();
|
||||
const RefDemo: React.FC = () => {
|
||||
const ref = React.useRef<HTMLDivElement>(null);
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (open) {
|
||||
refCallback(ref.current);
|
||||
refCallback(ref.current!);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
@ -146,7 +149,7 @@ describe('Drawer', () => {
|
||||
);
|
||||
};
|
||||
const { container } = render(<RefDemo />);
|
||||
fireEvent.click(container.querySelector('a'));
|
||||
fireEvent.click(container.querySelector('a')!);
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -1,189 +0,0 @@
|
||||
import React from 'react';
|
||||
import Drawer from '..';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
|
||||
class MultiDrawer extends React.Component {
|
||||
state = { open: false, childrenDrawer: false, hasChildren: true };
|
||||
|
||||
showDrawer = () => {
|
||||
this.setState({
|
||||
open: true,
|
||||
hasChildren: true,
|
||||
});
|
||||
};
|
||||
|
||||
onClose = () => {
|
||||
this.setState({
|
||||
open: false,
|
||||
});
|
||||
};
|
||||
|
||||
showChildrenDrawer = () => {
|
||||
this.setState({
|
||||
childrenDrawer: true,
|
||||
hasChildren: true,
|
||||
});
|
||||
};
|
||||
|
||||
onChildrenDrawerClose = () => {
|
||||
this.setState({
|
||||
childrenDrawer: false,
|
||||
});
|
||||
};
|
||||
|
||||
onRemoveChildDrawer = () => {
|
||||
this.setState({
|
||||
hasChildren: false,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { childrenDrawer, open, hasChildren } = this.state;
|
||||
const { placement, push } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<Button type="primary" id="open_drawer" onClick={this.showDrawer}>
|
||||
Open drawer
|
||||
</Button>
|
||||
<Button type="primary" id="remove_drawer" onClick={this.onRemoveChildDrawer}>
|
||||
rm child drawer
|
||||
</Button>
|
||||
<Drawer
|
||||
title="Multi-level drawer"
|
||||
className="test_drawer"
|
||||
width={520}
|
||||
onClose={this.onClose}
|
||||
getContainer={false}
|
||||
placement={placement}
|
||||
open={open}
|
||||
push={push}
|
||||
>
|
||||
<Button type="primary" id="open_two_drawer" onClick={this.showChildrenDrawer}>
|
||||
Two-level drawer
|
||||
</Button>
|
||||
{hasChildren && (
|
||||
<Drawer
|
||||
title="Two-level Drawer"
|
||||
width={320}
|
||||
className="Two-level"
|
||||
getContainer={false}
|
||||
placement={placement}
|
||||
onClose={this.onChildrenDrawerClose}
|
||||
open={childrenDrawer}
|
||||
>
|
||||
<div id="two_drawer_text">This is two-level drawer</div>
|
||||
</Drawer>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
borderTop: '1px solid #e8e8e8',
|
||||
padding: '10px 16px',
|
||||
textAlign: 'right',
|
||||
left: 0,
|
||||
background: '#fff',
|
||||
borderRadius: '0 0 4px 4px',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
style={{
|
||||
marginRight: 8,
|
||||
}}
|
||||
onClick={this.onClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={this.onClose} type="primary">
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</Drawer>
|
||||
|
||||
<div className="childrenDrawer">{String(childrenDrawer)}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Drawer', () => {
|
||||
it('render right MultiDrawer', () => {
|
||||
const { container: wrapper } = render(<MultiDrawer placement="right" />);
|
||||
fireEvent.click(wrapper.querySelector('button#open_drawer'));
|
||||
fireEvent.click(wrapper.querySelector('button#open_two_drawer'));
|
||||
|
||||
expect(wrapper.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateX(-180px)',
|
||||
});
|
||||
expect(wrapper.querySelectorAll('#two_drawer_text').length).toBe(1);
|
||||
});
|
||||
|
||||
it('render left MultiDrawer', () => {
|
||||
const { container: wrapper } = render(<MultiDrawer placement="left" />);
|
||||
fireEvent.click(wrapper.querySelector('button#open_drawer'));
|
||||
fireEvent.click(wrapper.querySelector('button#open_two_drawer'));
|
||||
|
||||
expect(wrapper.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateX(180px)',
|
||||
});
|
||||
expect(wrapper.querySelectorAll('#two_drawer_text').length).toBe(1);
|
||||
fireEvent.click(wrapper.querySelector('.Two-level .ant-drawer-close'));
|
||||
expect(wrapper.querySelector('.childrenDrawer').innerHTML).toEqual('false');
|
||||
});
|
||||
|
||||
it('render top MultiDrawer', () => {
|
||||
const { container: wrapper } = render(<MultiDrawer placement="top" />);
|
||||
fireEvent.click(wrapper.querySelector('button#open_drawer'));
|
||||
fireEvent.click(wrapper.querySelector('button#open_two_drawer'));
|
||||
expect(wrapper.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateY(180px)',
|
||||
});
|
||||
expect(wrapper.querySelectorAll('#two_drawer_text').length).toBe(1);
|
||||
});
|
||||
|
||||
it('render MultiDrawer is child in unmount', () => {
|
||||
const { container: wrapper } = render(<MultiDrawer placement="top" mask={false} />);
|
||||
fireEvent.click(wrapper.querySelector('button#open_drawer'));
|
||||
fireEvent.click(wrapper.querySelector('button#open_two_drawer'));
|
||||
fireEvent.click(wrapper.querySelector('button#remove_drawer'));
|
||||
|
||||
expect(wrapper.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: '',
|
||||
});
|
||||
|
||||
fireEvent.click(wrapper.querySelector('button#open_two_drawer'));
|
||||
expect(wrapper.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateY(180px)',
|
||||
});
|
||||
expect(wrapper.querySelectorAll('#two_drawer_text').length).toBe(1);
|
||||
});
|
||||
|
||||
it('custom MultiDrawer push distance', () => {
|
||||
const { container: wrapper } = render(<MultiDrawer push={{ distance: 256 }} />);
|
||||
fireEvent.click(wrapper.querySelector('button#open_drawer'));
|
||||
fireEvent.click(wrapper.querySelector('button#open_two_drawer'));
|
||||
expect(wrapper.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateX(-256px)',
|
||||
});
|
||||
});
|
||||
|
||||
it('custom MultiDrawer push with true', () => {
|
||||
const { container: wrapper } = render(<MultiDrawer push />);
|
||||
fireEvent.click(wrapper.querySelector('button#open_drawer'));
|
||||
fireEvent.click(wrapper.querySelector('button#open_two_drawer'));
|
||||
expect(wrapper.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateX(-180px)',
|
||||
});
|
||||
});
|
||||
|
||||
it('custom MultiDrawer push with false', () => {
|
||||
const { container: wrapper } = render(<MultiDrawer push={false} />);
|
||||
fireEvent.click(wrapper.querySelector('button#open_drawer'));
|
||||
fireEvent.click(wrapper.querySelector('button#open_two_drawer'));
|
||||
expect(wrapper.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: '',
|
||||
});
|
||||
});
|
||||
});
|
193
components/drawer/__tests__/MultiDrawer.test.tsx
Normal file
193
components/drawer/__tests__/MultiDrawer.test.tsx
Normal file
@ -0,0 +1,193 @@
|
||||
import type { DrawerPopupProps } from 'rc-drawer/lib/DrawerPopup';
|
||||
import React from 'react';
|
||||
import Drawer from '..';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
|
||||
interface DrawerPropsType {
|
||||
push?: DrawerPopupProps['push'];
|
||||
placement?: DrawerPopupProps['placement'];
|
||||
}
|
||||
|
||||
interface DrawerStateType {
|
||||
open: boolean;
|
||||
hasChildren: boolean;
|
||||
childrenDrawer: boolean;
|
||||
}
|
||||
|
||||
class MultiDrawer extends React.Component<DrawerPropsType, DrawerStateType> {
|
||||
state = { open: false, childrenDrawer: false, hasChildren: true };
|
||||
|
||||
showDrawer = () => {
|
||||
this.setState({
|
||||
open: true,
|
||||
hasChildren: true,
|
||||
});
|
||||
};
|
||||
|
||||
onClose = () => {
|
||||
this.setState({
|
||||
open: false,
|
||||
});
|
||||
};
|
||||
|
||||
showChildrenDrawer = () => {
|
||||
this.setState({
|
||||
childrenDrawer: true,
|
||||
hasChildren: true,
|
||||
});
|
||||
};
|
||||
|
||||
onChildrenDrawerClose = () => {
|
||||
this.setState({
|
||||
childrenDrawer: false,
|
||||
});
|
||||
};
|
||||
|
||||
onRemoveChildDrawer = () => {
|
||||
this.setState({
|
||||
hasChildren: false,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { childrenDrawer, open, hasChildren } = this.state;
|
||||
const { placement, push } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<Button type="primary" id="open_drawer" onClick={this.showDrawer}>
|
||||
Open drawer
|
||||
</Button>
|
||||
<Button type="primary" id="remove_drawer" onClick={this.onRemoveChildDrawer}>
|
||||
rm child drawer
|
||||
</Button>
|
||||
<Drawer
|
||||
title="Multi-level drawer"
|
||||
className="test_drawer"
|
||||
width={520}
|
||||
onClose={this.onClose}
|
||||
getContainer={false}
|
||||
placement={placement}
|
||||
open={open}
|
||||
push={push}
|
||||
>
|
||||
<Button type="primary" id="open_two_drawer" onClick={this.showChildrenDrawer}>
|
||||
Two-level drawer
|
||||
</Button>
|
||||
{hasChildren && (
|
||||
<Drawer
|
||||
title="Two-level Drawer"
|
||||
width={320}
|
||||
className="Two-level"
|
||||
getContainer={false}
|
||||
placement={placement}
|
||||
onClose={this.onChildrenDrawerClose}
|
||||
open={childrenDrawer}
|
||||
>
|
||||
<div id="two_drawer_text">This is two-level drawer</div>
|
||||
</Drawer>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
borderTop: '1px solid #e8e8e8',
|
||||
padding: '10px 16px',
|
||||
textAlign: 'right',
|
||||
left: 0,
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '0 0 4px 4px',
|
||||
}}
|
||||
>
|
||||
<Button style={{ marginRight: 8 }} onClick={this.onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={this.onClose} type="primary">
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</Drawer>
|
||||
|
||||
<div className="childrenDrawer">{String(childrenDrawer)}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Drawer', () => {
|
||||
it('render right MultiDrawer', () => {
|
||||
const { container } = render(<MultiDrawer placement="right" />);
|
||||
fireEvent.click(container.querySelector('button#open_drawer')!);
|
||||
fireEvent.click(container.querySelector('button#open_two_drawer')!);
|
||||
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateX(-180px)',
|
||||
});
|
||||
expect(container.querySelectorAll('#two_drawer_text').length).toBe(1);
|
||||
});
|
||||
|
||||
it('render left MultiDrawer', () => {
|
||||
const { container } = render(<MultiDrawer placement="left" />);
|
||||
fireEvent.click(container.querySelector('button#open_drawer')!);
|
||||
fireEvent.click(container.querySelector('button#open_two_drawer')!);
|
||||
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateX(180px)',
|
||||
});
|
||||
expect(container.querySelectorAll('#two_drawer_text').length).toBe(1);
|
||||
fireEvent.click(container.querySelector('.Two-level .ant-drawer-close')!);
|
||||
expect(container.querySelector('.childrenDrawer')?.innerHTML).toEqual('false');
|
||||
});
|
||||
|
||||
it('render top MultiDrawer', () => {
|
||||
const { container } = render(<MultiDrawer placement="top" />);
|
||||
fireEvent.click(container.querySelector('button#open_drawer')!);
|
||||
fireEvent.click(container.querySelector('button#open_two_drawer')!);
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateY(180px)',
|
||||
});
|
||||
expect(container.querySelectorAll('#two_drawer_text').length).toBe(1);
|
||||
});
|
||||
|
||||
it('render MultiDrawer is child in unmount', () => {
|
||||
const mask = { mask: false };
|
||||
const { container } = render(<MultiDrawer placement="top" {...mask} />);
|
||||
fireEvent.click(container.querySelector('button#open_drawer')!);
|
||||
fireEvent.click(container.querySelector('button#open_two_drawer')!);
|
||||
fireEvent.click(container.querySelector('button#remove_drawer')!);
|
||||
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({ transform: '' });
|
||||
|
||||
fireEvent.click(container.querySelector('button#open_two_drawer')!);
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateY(180px)',
|
||||
});
|
||||
expect(container.querySelectorAll('#two_drawer_text').length).toBe(1);
|
||||
});
|
||||
|
||||
it('custom MultiDrawer push distance', () => {
|
||||
const { container } = render(<MultiDrawer push={{ distance: 256 }} />);
|
||||
fireEvent.click(container.querySelector('button#open_drawer')!);
|
||||
fireEvent.click(container.querySelector('button#open_two_drawer')!);
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateX(-256px)',
|
||||
});
|
||||
});
|
||||
|
||||
it('custom MultiDrawer push with true', () => {
|
||||
const { container } = render(<MultiDrawer push />);
|
||||
fireEvent.click(container.querySelector('button#open_drawer')!);
|
||||
fireEvent.click(container.querySelector('button#open_two_drawer')!);
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({
|
||||
transform: 'translateX(-180px)',
|
||||
});
|
||||
});
|
||||
|
||||
it('custom MultiDrawer push with false', () => {
|
||||
const { container } = render(<MultiDrawer push={false} />);
|
||||
fireEvent.click(container.querySelector('button#open_drawer')!);
|
||||
fireEvent.click(container.querySelector('button#open_two_drawer')!);
|
||||
expect(container.querySelector('.ant-drawer-content-wrapper')).toHaveStyle({ transform: '' });
|
||||
});
|
||||
});
|
@ -11,7 +11,7 @@ describe('Empty', () => {
|
||||
|
||||
it('image size should change', () => {
|
||||
const { container } = render(<Empty imageStyle={{ height: 20 }} />);
|
||||
expect(container.querySelector('.ant-empty-image').style.height).toBe('20px');
|
||||
expect(container.querySelector<HTMLDivElement>('.ant-empty-image')?.style.height).toBe('20px');
|
||||
});
|
||||
|
||||
it('description can be false', () => {
|
17
components/icon/__tests__/index.test.tsx
Normal file
17
components/icon/__tests__/index.test.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import Icon from '..';
|
||||
import { render } from '../../../tests/utils';
|
||||
|
||||
// v3 兼容性测试
|
||||
describe('Icon', () => {
|
||||
it('should render Icon', () => {
|
||||
const { container } = render(<Icon />);
|
||||
expect(container.firstChild).toBe(null);
|
||||
});
|
||||
|
||||
it('should throw Error', () => {
|
||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
render(<Icon />);
|
||||
expect(errSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import warning from '../_util/warning';
|
||||
|
||||
const Icon = () => {
|
||||
const Icon: React.FC = () => {
|
||||
warning(false, 'Icon', 'Empty Icon');
|
||||
return null;
|
||||
};
|
||||
|
@ -11,60 +11,58 @@ describe('Image', () => {
|
||||
mountTest(Image);
|
||||
rtlTest(Image);
|
||||
it('Image preview props set false', () => {
|
||||
const { container: wrapper } = render(<Image src={src} preview={false} />);
|
||||
const { container } = render(<Image src={src} preview={false} />);
|
||||
|
||||
fireEvent.click(wrapper.querySelector('.ant-image'));
|
||||
expect(wrapper.querySelector('.ant-image-preview-root')).toBe(null);
|
||||
fireEvent.click(container.querySelector('.ant-image')!);
|
||||
expect(container.querySelector('.ant-image-preview-root')).toBe(null);
|
||||
});
|
||||
it('Group preview props set false', () => {
|
||||
const { container: wrapper } = render(
|
||||
const { container } = render(
|
||||
<Image.PreviewGroup preview={false}>
|
||||
<Image src={src} />
|
||||
</Image.PreviewGroup>,
|
||||
);
|
||||
|
||||
fireEvent.click(wrapper.querySelector('.ant-image'));
|
||||
fireEvent.click(container.querySelector('.ant-image')!);
|
||||
|
||||
expect(wrapper.querySelector('.ant-image-preview-root')).toBe(null);
|
||||
expect(container.querySelector('.ant-image-preview-root')).toBe(null);
|
||||
});
|
||||
|
||||
it('Default preview props', () => {
|
||||
const { container: wrapper, baseElement } = render(
|
||||
<Image src={src} preview={{ visible: true }} />,
|
||||
);
|
||||
const { container, baseElement } = render(<Image src={src} preview={{ visible: true }} />);
|
||||
|
||||
fireEvent.click(wrapper.querySelector('.ant-image'));
|
||||
fireEvent.click(container.querySelector('.ant-image')!);
|
||||
|
||||
expect(baseElement.querySelector('.ant-image-preview-mask')).toHaveClass('ant-fade');
|
||||
expect(baseElement.querySelector('.ant-image-preview')).toHaveClass('ant-zoom');
|
||||
});
|
||||
it('Default Group preview props', () => {
|
||||
const { container: wrapper, baseElement } = render(
|
||||
const { container, baseElement } = render(
|
||||
<Image.PreviewGroup preview={{ visible: true }}>
|
||||
<Image src={src} />
|
||||
</Image.PreviewGroup>,
|
||||
);
|
||||
|
||||
fireEvent.click(wrapper.querySelector('.ant-image'));
|
||||
fireEvent.click(container.querySelector('.ant-image')!);
|
||||
|
||||
expect(baseElement.querySelector('.ant-image-preview-mask')).toHaveClass('ant-fade');
|
||||
expect(baseElement.querySelector('.ant-image-preview')).toHaveClass('ant-zoom');
|
||||
});
|
||||
it('Customize preview props', () => {
|
||||
const { container: wrapper, baseElement } = render(
|
||||
const { container, baseElement } = render(
|
||||
<Image
|
||||
src={src}
|
||||
preview={{ visible: true, transitionName: 'abc', maskTransitionName: 'def' }}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(wrapper.querySelector('.ant-image'));
|
||||
fireEvent.click(container.querySelector('.ant-image')!);
|
||||
|
||||
expect(baseElement.querySelector('.ant-image-preview')).toHaveClass('abc');
|
||||
expect(baseElement.querySelector('.ant-image-preview-mask')).toHaveClass('def');
|
||||
});
|
||||
it('Customize Group preview props', () => {
|
||||
const { container: wrapper, baseElement } = render(
|
||||
const { container, baseElement } = render(
|
||||
<Image.PreviewGroup
|
||||
preview={{ visible: true, transitionName: 'abc', maskTransitionName: 'def' }}
|
||||
>
|
||||
@ -72,22 +70,21 @@ describe('Image', () => {
|
||||
</Image.PreviewGroup>,
|
||||
);
|
||||
|
||||
fireEvent.click(wrapper.querySelector('.ant-image'));
|
||||
fireEvent.click(container.querySelector('.ant-image')!);
|
||||
|
||||
expect(baseElement.querySelector('.ant-image-preview')).toHaveClass('abc');
|
||||
expect(baseElement.querySelector('.ant-image-preview-mask')).toHaveClass('def');
|
||||
});
|
||||
it('ConfigProvider getPopupContainer', () => {
|
||||
const { container: wrapper, baseElement } = render(
|
||||
const { container, baseElement } = render(
|
||||
<>
|
||||
<div className="container" />
|
||||
<ConfigProvider getPopupContainer={() => document.querySelector('.container')}>
|
||||
<ConfigProvider getPopupContainer={() => document.querySelector('.container')!}>
|
||||
<Image src={src} />
|
||||
</ConfigProvider>
|
||||
</>,
|
||||
);
|
||||
fireEvent.click(wrapper.querySelector('.ant-image'));
|
||||
const containerElement = baseElement.querySelector('.container');
|
||||
expect(containerElement.children.length).not.toBe(0);
|
||||
fireEvent.click(container.querySelector('.ant-image')!);
|
||||
expect(baseElement.querySelector('.container')?.children.length).not.toBe(0);
|
||||
});
|
||||
});
|
@ -15,18 +15,18 @@ describe('InputNumber', () => {
|
||||
it('should return null when blur a empty input number', () => {
|
||||
const onChange = jest.fn();
|
||||
const { container } = render(<InputNumber defaultValue="1" onChange={onChange} />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: '' } });
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: '' } });
|
||||
expect(onChange).toHaveBeenLastCalledWith(null);
|
||||
});
|
||||
|
||||
it('should call onStep when press up or down button', () => {
|
||||
const onStep = jest.fn();
|
||||
const { container } = render(<InputNumber defaultValue={1} onStep={onStep} />);
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-number-handler-up'));
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-number-handler-up')!);
|
||||
expect(onStep).toHaveBeenCalledTimes(1);
|
||||
expect(onStep).toHaveBeenLastCalledWith(2, { offset: 1, type: 'up' });
|
||||
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-number-handler-down'));
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-number-handler-down')!);
|
||||
expect(onStep).toHaveBeenCalledTimes(2);
|
||||
expect(onStep).toHaveBeenLastCalledWith(1, { offset: 1, type: 'down' });
|
||||
});
|
@ -10,15 +10,15 @@ describe('prefix', () => {
|
||||
);
|
||||
it('should support className when has prefix', () => {
|
||||
const { container } = render(<InputNumber prefix="suffix" className="my-class-name" />);
|
||||
expect(container.firstChild?.className.includes('my-class-name')).toBe(true);
|
||||
expect((container.firstChild as HTMLElement)?.className.includes('my-class-name')).toBe(true);
|
||||
expect(container.querySelector('input')?.className.includes('my-class-name')).toBe(false);
|
||||
});
|
||||
|
||||
it('should trigger focus when prefix is clicked', () => {
|
||||
const { container } = render(<InputNumber prefix={<i>123</i>} />);
|
||||
|
||||
const mockFocus = jest.spyOn(container.querySelector('input'), 'focus');
|
||||
fireEvent.mouseUp(container.querySelector('i'));
|
||||
const mockFocus = jest.spyOn(container.querySelector('input')!, 'focus');
|
||||
fireEvent.mouseUp(container.querySelector('i')!);
|
||||
expect(mockFocus).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import type { InputRef } from '..';
|
||||
import Input from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
@ -13,12 +13,12 @@ describe('Input.Password', () => {
|
||||
rtlTest(Input.Password);
|
||||
|
||||
it('should get input element from ref', () => {
|
||||
const ref = React.createRef();
|
||||
const ref = React.createRef<InputRef>();
|
||||
const onSelect = jest.fn();
|
||||
|
||||
const { container } = render(<Input.Password onSelect={onSelect} ref={ref} />);
|
||||
expect(ref.current.input instanceof HTMLInputElement).toBe(true);
|
||||
fireEvent.select(container.querySelector('input'));
|
||||
expect(ref.current?.input instanceof HTMLInputElement).toBe(true);
|
||||
fireEvent.select(container.querySelector('input')!);
|
||||
expect(onSelect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -30,13 +30,13 @@ describe('Input.Password', () => {
|
||||
|
||||
it('should change type when click', () => {
|
||||
const { asFragment, container } = render(<Input.Password />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: '111' } });
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: '111' } });
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-input-password-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-password-icon')!);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-input-password-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-password-icon')!);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@ -50,7 +50,7 @@ describe('Input.Password', () => {
|
||||
it('should not toggle visibility when disabled prop is true', () => {
|
||||
const { container } = render(<Input.Password disabled />);
|
||||
expect(container.querySelectorAll('.anticon-eye-invisible').length).toBe(1);
|
||||
fireEvent.click(container.querySelector('.anticon-eye-invisible'));
|
||||
fireEvent.click(container.querySelector('.anticon-eye-invisible')!);
|
||||
expect(container.querySelectorAll('.anticon-eye').length).toBe(0);
|
||||
});
|
||||
|
||||
@ -59,43 +59,43 @@ describe('Input.Password', () => {
|
||||
container: document.body,
|
||||
});
|
||||
expect(document.activeElement).toBe(container.querySelector('input'));
|
||||
document.activeElement.setSelectionRange(2, 2);
|
||||
expect(document.activeElement.selectionStart).toBe(2);
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-password-icon'));
|
||||
fireEvent.mouseUp(container.querySelector('.ant-input-password-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-password-icon'));
|
||||
(document?.activeElement as any)?.setSelectionRange(2, 2);
|
||||
expect((document?.activeElement as any)?.selectionStart).toBe(2);
|
||||
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);
|
||||
expect((document?.activeElement as any).selectionStart).toBe(2);
|
||||
unmount();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/20541
|
||||
it('should not show value attribute in input element', async () => {
|
||||
const { container } = render(<Input.Password />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'value' } });
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: 'value' } });
|
||||
await sleep();
|
||||
expect(container.querySelector('input').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 { container } = render(<Input.Password />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'value' } });
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: 'value' } });
|
||||
await sleep();
|
||||
expect(container.querySelector('input').getAttribute('value')).toBeFalsy();
|
||||
fireEvent.blur(container.querySelector('input'));
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBeFalsy();
|
||||
fireEvent.blur(container.querySelector('input')!);
|
||||
await sleep();
|
||||
expect(container.querySelector('input').getAttribute('value')).toBeFalsy();
|
||||
fireEvent.focus(container.querySelector('input'));
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBeFalsy();
|
||||
fireEvent.focus(container.querySelector('input')!);
|
||||
await sleep();
|
||||
expect(container.querySelector('input').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 { container, unmount } = render(<Input.Password />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'value' } });
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: 'value' } });
|
||||
unmount();
|
||||
}).not.toThrow();
|
||||
});
|
||||
@ -104,6 +104,6 @@ describe('Input.Password', () => {
|
||||
it('should not contain value attribute in input element with defaultValue', async () => {
|
||||
const { container } = render(<Input.Password defaultValue="value" />);
|
||||
await sleep();
|
||||
expect(container.querySelector('input').getAttribute('value')).toBeFalsy();
|
||||
expect(container.querySelector('input')?.getAttribute('value')).toBeFalsy();
|
||||
});
|
||||
});
|
@ -4,6 +4,7 @@ import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import Button from '../../button';
|
||||
import type { InputRef } from '../Input';
|
||||
import Search from '../Search';
|
||||
|
||||
describe('Input.Search', () => {
|
||||
@ -42,24 +43,16 @@ describe('Input.Search', () => {
|
||||
const { container } = render(
|
||||
<Search defaultValue="search text" onSearch={onSearch} disabled />,
|
||||
);
|
||||
fireEvent.click(container.querySelector('button'));
|
||||
fireEvent.click(container.querySelector('button')!);
|
||||
expect(onSearch).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search icon', () => {
|
||||
const onSearch = jest.fn();
|
||||
const { container } = render(<Search defaultValue="search text" onSearch={onSearch} />);
|
||||
fireEvent.click(container.querySelector('button'));
|
||||
fireEvent.click(container.querySelector('button')!);
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'click',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
expect(onSearch).toHaveBeenCalledWith('search text', expect.anything());
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search button', () => {
|
||||
@ -67,17 +60,9 @@ describe('Input.Search', () => {
|
||||
const { container } = render(
|
||||
<Search defaultValue="search text" enterButton onSearch={onSearch} />,
|
||||
);
|
||||
fireEvent.click(container.querySelector('button'));
|
||||
fireEvent.click(container.querySelector('button')!);
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'click',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
expect(onSearch).toHaveBeenCalledWith('search text', expect.anything());
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search button with text', () => {
|
||||
@ -85,17 +70,9 @@ describe('Input.Search', () => {
|
||||
const { container } = render(
|
||||
<Search defaultValue="search text" enterButton="button text" onSearch={onSearch} />,
|
||||
);
|
||||
fireEvent.click(container.querySelector('button'));
|
||||
fireEvent.click(container.querySelector('button')!);
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'click',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
expect(onSearch).toHaveBeenCalledWith('search text', expect.anything());
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search button with customize button', () => {
|
||||
@ -107,17 +84,9 @@ describe('Input.Search', () => {
|
||||
onSearch={onSearch}
|
||||
/>,
|
||||
);
|
||||
fireEvent.click(container.querySelector('button'));
|
||||
fireEvent.click(container.querySelector('button')!);
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'click',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
expect(onSearch).toHaveBeenCalledWith('search text', expect.anything());
|
||||
});
|
||||
|
||||
it('should trigger onSearch when click search button of native', () => {
|
||||
@ -134,56 +103,32 @@ describe('Input.Search', () => {
|
||||
onSearch={onSearch}
|
||||
/>,
|
||||
);
|
||||
fireEvent.click(container.querySelector('button'));
|
||||
fireEvent.click(container.querySelector('button')!);
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'click',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
expect(onSearch).toHaveBeenCalledWith('search text', expect.anything());
|
||||
expect(onButtonClick).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should trigger onSearch when press enter', () => {
|
||||
const onSearch = jest.fn();
|
||||
const { container } = render(<Search defaultValue="search text" onSearch={onSearch} />);
|
||||
fireEvent.keyDown(container.querySelector('input'), { key: 'Enter', keyCode: 13 });
|
||||
fireEvent.keyDown(container.querySelector('input')!, { key: 'Enter', keyCode: 13 });
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
expect(onSearch).toHaveBeenCalledWith(
|
||||
'search text',
|
||||
expect.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'keydown',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
expect(onSearch).toHaveBeenCalledWith('search text', expect.anything());
|
||||
});
|
||||
|
||||
// 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 { container } = render(<Search defaultValue="search text" onSearch={onSearch} />);
|
||||
fireEvent.compositionStart(container.querySelector('input'));
|
||||
fireEvent.keyDown(container.querySelector('input'), { key: 'Enter', keyCode: 13 });
|
||||
fireEvent.compositionStart(container.querySelector('input')!);
|
||||
fireEvent.keyDown(container.querySelector('input')!, { key: 'Enter', keyCode: 13 });
|
||||
expect(onSearch).not.toHaveBeenCalled();
|
||||
|
||||
fireEvent.compositionEnd(container.querySelector('input'));
|
||||
fireEvent.keyDown(container.querySelector('input'), { 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.anything(),
|
||||
// FIXME: should use following code
|
||||
// expect.objectContaining({
|
||||
// type: 'keydown',
|
||||
// preventDefault: expect.any(Function),
|
||||
// }),
|
||||
);
|
||||
expect(onSearch).toHaveBeenCalledWith('search text', expect.anything());
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/14785
|
||||
@ -204,7 +149,7 @@ describe('Input.Search', () => {
|
||||
const { container } = render(
|
||||
<Search allowClear defaultValue="value" onSearch={onSearch} onChange={onChange} />,
|
||||
);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(onSearch).toHaveBeenLastCalledWith('', expect.anything());
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
});
|
||||
@ -236,13 +181,13 @@ describe('Input.Search', () => {
|
||||
});
|
||||
|
||||
it('should prevent search button mousedown event', () => {
|
||||
const ref = React.createRef();
|
||||
const ref = React.createRef<InputRef>();
|
||||
const { container } = render(<Search ref={ref} enterButton="button text" />, {
|
||||
container: document.body,
|
||||
});
|
||||
ref.current.focus();
|
||||
ref.current?.focus();
|
||||
expect(document.activeElement).toBe(container.querySelector('input'));
|
||||
fireEvent.mouseDown(container.querySelector('button'));
|
||||
fireEvent.mouseDown(container.querySelector('button')!);
|
||||
expect(document.activeElement).toBe(container.querySelector('input'));
|
||||
});
|
||||
|
||||
@ -250,7 +195,7 @@ describe('Input.Search', () => {
|
||||
const ref = jest.fn();
|
||||
const { container } = render(<Search ref={ref} enterButton />);
|
||||
expect(() => {
|
||||
fireEvent.mouseDown(container.querySelector('button'));
|
||||
fireEvent.mouseDown(container.querySelector('button')!);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
@ -258,10 +203,10 @@ describe('Input.Search', () => {
|
||||
it('Search with allowClear should have one className only', () => {
|
||||
const { container } = render(<Search allowClear className="className" />);
|
||||
expect(
|
||||
container.querySelector('.ant-input-group-wrapper').classList.contains('className'),
|
||||
container.querySelector('.ant-input-group-wrapper')?.classList.contains('className'),
|
||||
).toBe(true);
|
||||
expect(
|
||||
container.querySelector('.ant-input-affix-wrapper').classList.contains('className'),
|
||||
container.querySelector('.ant-input-affix-wrapper')?.classList.contains('className'),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
@ -1,8 +1,11 @@
|
||||
import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
|
||||
import type { ChangeEventHandler, TextareaHTMLAttributes } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import Input from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import type { RenderOptions } from '../../../tests/utils';
|
||||
import { fireEvent, render, sleep, triggerResize } from '../../../tests/utils';
|
||||
import type { TextAreaRef } from '../TextArea';
|
||||
|
||||
const { TextArea } = Input;
|
||||
|
||||
@ -12,27 +15,23 @@ describe('TextArea', () => {
|
||||
const originalGetComputedStyle = window.getComputedStyle;
|
||||
beforeAll(() => {
|
||||
Object.defineProperty(window, 'getComputedStyle', {
|
||||
value: node => ({
|
||||
getPropertyValue: prop => {
|
||||
if (prop === 'box-sizing') {
|
||||
return originalGetComputedStyle(node)[prop] || 'border-box';
|
||||
}
|
||||
return originalGetComputedStyle(node)[prop];
|
||||
},
|
||||
value: (node: Element) => ({
|
||||
getPropertyValue: (prop: PropertyKey) =>
|
||||
prop === 'box-sizing'
|
||||
? originalGetComputedStyle(node)[prop as unknown as number] || 'border-box'
|
||||
: originalGetComputedStyle(node)[prop as unknown as number],
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
Object.defineProperty(window, 'getComputedStyle', {
|
||||
value: originalGetComputedStyle,
|
||||
});
|
||||
Object.defineProperty(window, 'getComputedStyle', { value: originalGetComputedStyle });
|
||||
});
|
||||
|
||||
it('should auto calculate height according to content length', async () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const ref = React.createRef();
|
||||
const ref = React.createRef<TextAreaRef>();
|
||||
|
||||
const genTextArea = (props = {}) => (
|
||||
<TextArea
|
||||
@ -47,7 +46,7 @@ describe('TextArea', () => {
|
||||
|
||||
const { container, rerender } = render(genTextArea());
|
||||
|
||||
const mockFunc = jest.spyOn(ref.current.resizableTextArea, 'resizeTextarea');
|
||||
const mockFunc = jest.spyOn(ref.current?.resizableTextArea!, 'resizeTextarea');
|
||||
|
||||
rerender(genTextArea({ value: '1111\n2222\n3333' }));
|
||||
// wrapper.setProps({ value: '1111\n2222\n3333' });
|
||||
@ -59,7 +58,7 @@ describe('TextArea', () => {
|
||||
await sleep(0);
|
||||
expect(mockFunc).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(container.querySelector('textarea').style.overflow).toBeFalsy();
|
||||
expect(container.querySelector('textarea')?.style.overflow).toBeFalsy();
|
||||
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
errorSpy.mockRestore();
|
||||
@ -72,12 +71,12 @@ describe('TextArea', () => {
|
||||
<TextArea onKeyDown={fakeHandleKeyDown} onPressEnter={fakeHandlePressEnter} />,
|
||||
);
|
||||
/** KeyCode 65 is A */
|
||||
fireEvent.keyDown(container.querySelector('textarea'), { keyCode: 65 });
|
||||
fireEvent.keyDown(container.querySelector('textarea')!, { keyCode: 65 });
|
||||
expect(fakeHandleKeyDown).toHaveBeenCalledTimes(1);
|
||||
expect(fakeHandlePressEnter).toHaveBeenCalledTimes(0);
|
||||
|
||||
/** KeyCode 13 is Enter */
|
||||
fireEvent.keyDown(container.querySelector('textarea'), { keyCode: 13 });
|
||||
fireEvent.keyDown(container.querySelector('textarea')!, { keyCode: 13 });
|
||||
expect(fakeHandleKeyDown).toHaveBeenCalledTimes(2);
|
||||
expect(fakeHandlePressEnter).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
@ -95,7 +94,7 @@ describe('TextArea', () => {
|
||||
|
||||
it('maxLength should not block control', () => {
|
||||
const { container } = render(<TextArea maxLength={1} value="light" />);
|
||||
expect(container.querySelector('textarea').value).toEqual('light');
|
||||
expect(container.querySelector('textarea')?.value).toEqual('light');
|
||||
});
|
||||
|
||||
it('should limit correctly when in control', () => {
|
||||
@ -105,21 +104,21 @@ describe('TextArea', () => {
|
||||
};
|
||||
|
||||
const { container } = render(<Demo />);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'light' } });
|
||||
fireEvent.change(container.querySelector('textarea')!, { target: { value: 'light' } });
|
||||
|
||||
expect(container.querySelector('textarea').value).toEqual('l');
|
||||
expect(container.querySelector('textarea')?.value).toEqual('l');
|
||||
});
|
||||
|
||||
it('should exceed maxLength when use IME', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
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'), {
|
||||
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: '竹' } });
|
||||
fireEvent.change(container.querySelector('textarea')!, { target: { value: '竹' } });
|
||||
|
||||
expect(onChange).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({ target: expect.objectContaining({ value: '竹' }) }),
|
||||
@ -132,13 +131,13 @@ describe('TextArea', () => {
|
||||
const { container } = render(
|
||||
<TextArea maxLength={6} defaultValue="123456" onChange={onChange} />,
|
||||
);
|
||||
fireEvent.change(container.querySelector('textarea'), {
|
||||
fireEvent.change(container.querySelector('textarea')!, {
|
||||
target: { selectionStart: 1, value: 'w123456' },
|
||||
});
|
||||
fireEvent.change(container.querySelector('textarea'), {
|
||||
fireEvent.change(container.querySelector('textarea')!, {
|
||||
target: { selectionStart: 3, value: 'w123456' },
|
||||
});
|
||||
expect(container.querySelector('textarea').value).toBe('123456');
|
||||
expect(container.querySelector('textarea')?.value).toBe('123456');
|
||||
});
|
||||
|
||||
// 拼音输入
|
||||
@ -148,21 +147,21 @@ describe('TextArea', () => {
|
||||
const { container } = render(
|
||||
<TextArea maxLength={6} defaultValue="1234" onChange={onChange} />,
|
||||
);
|
||||
fireEvent.change(container.querySelector('textarea'), {
|
||||
fireEvent.change(container.querySelector('textarea')!, {
|
||||
target: { selectionStart: 4, value: '1234' },
|
||||
});
|
||||
fireEvent.compositionStart(container.querySelector('textarea'));
|
||||
fireEvent.compositionStart(container.querySelector('textarea')!);
|
||||
|
||||
fireEvent.change(container.querySelector('textarea'), {
|
||||
fireEvent.change(container.querySelector('textarea')!, {
|
||||
target: { selectionStart: 9, value: '1234z z z' },
|
||||
});
|
||||
fireEvent.change(container.querySelector('textarea'), {
|
||||
fireEvent.change(container.querySelector('textarea')!, {
|
||||
target: { selectionStart: 7, value: '1234组织者' },
|
||||
});
|
||||
|
||||
fireEvent.compositionEnd(container.querySelector('textarea'));
|
||||
fireEvent.compositionEnd(container.querySelector('textarea')!);
|
||||
|
||||
expect(container.querySelector('textarea').value).toBe('1234组织');
|
||||
expect(container.querySelector('textarea')?.value).toBe('1234组织');
|
||||
});
|
||||
|
||||
// 2. 光标位于中间或开头,且当前字符数未达到6个,若选中的字符 + 原字符的长度超过6个,则显示原有字符
|
||||
@ -171,29 +170,29 @@ describe('TextArea', () => {
|
||||
const { container } = render(
|
||||
<TextArea maxLength={6} defaultValue="1234" onChange={onChange} />,
|
||||
);
|
||||
fireEvent.change(container.querySelector('textarea'), {
|
||||
fireEvent.change(container.querySelector('textarea')!, {
|
||||
target: { selectionStart: 2, value: '1234' },
|
||||
});
|
||||
fireEvent.compositionStart(container.querySelector('textarea'));
|
||||
fireEvent.compositionStart(container.querySelector('textarea')!);
|
||||
|
||||
fireEvent.change(container.querySelector('textarea'), {
|
||||
fireEvent.change(container.querySelector('textarea')!, {
|
||||
target: { selectionStart: 2, value: '12z z z34' },
|
||||
});
|
||||
fireEvent.change(container.querySelector('textarea'), {
|
||||
fireEvent.change(container.querySelector('textarea')!, {
|
||||
target: { selectionStart: 5, value: '12组织者34' },
|
||||
});
|
||||
|
||||
fireEvent.compositionEnd(container.querySelector('textarea'));
|
||||
fireEvent.compositionEnd(container.querySelector('textarea')!);
|
||||
|
||||
expect(container.querySelector('textarea').value).toBe('1234');
|
||||
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 ref = React.createRef<TextAreaRef>();
|
||||
const { container } = render(<TextArea aria-label="textarea" ref={ref} />);
|
||||
const resizeTextarea = jest.spyOn(ref.current.resizableTextArea, 'resizeTextarea');
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'test' } });
|
||||
const resizeTextarea = jest.spyOn(ref.current?.resizableTextArea!, 'resizeTextarea');
|
||||
fireEvent.change(container.querySelector('textarea')!, { target: { value: 'test' } });
|
||||
expect(resizeTextarea).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -203,7 +202,7 @@ describe('TextArea', () => {
|
||||
const { container } = render(
|
||||
<TextArea onPressEnter={onPressEnter} onKeyDown={onKeyDown} aria-label="textarea" />,
|
||||
);
|
||||
fireEvent.keyDown(container.querySelector('textarea'), { keyCode: 13 });
|
||||
fireEvent.keyDown(container.querySelector('textarea')!, { keyCode: 13 });
|
||||
|
||||
expect(onPressEnter).toHaveBeenCalled();
|
||||
expect(onKeyDown).toHaveBeenCalled();
|
||||
@ -211,18 +210,15 @@ describe('TextArea', () => {
|
||||
|
||||
it('should trigger onResize', async () => {
|
||||
const onResize = jest.fn();
|
||||
const ref = React.createRef();
|
||||
const ref = React.createRef<TextAreaRef>();
|
||||
render(<TextArea ref={ref} onResize={onResize} autoSize />);
|
||||
await sleep(100);
|
||||
const target = ref.current.resizableTextArea.textArea;
|
||||
const target = ref.current?.resizableTextArea?.textArea!;
|
||||
triggerResize(target);
|
||||
await Promise.resolve();
|
||||
|
||||
expect(onResize).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
width: expect.any(Number),
|
||||
height: expect.any(Number),
|
||||
}),
|
||||
expect.objectContaining({ width: expect.any(Number), height: expect.any(Number) }),
|
||||
);
|
||||
});
|
||||
|
||||
@ -233,24 +229,24 @@ describe('TextArea', () => {
|
||||
);
|
||||
inputRerender(<Input value={undefined} />);
|
||||
textareaRerender(<TextArea value={undefined} />);
|
||||
expect(textareaContainer.querySelector('textarea').value).toBe(
|
||||
inputContainer.querySelector('input').value,
|
||||
expect(textareaContainer.querySelector('textarea')?.value).toBe(
|
||||
inputContainer.querySelector('input')?.value,
|
||||
);
|
||||
});
|
||||
|
||||
describe('should support showCount', () => {
|
||||
it('maxLength', () => {
|
||||
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(
|
||||
expect(container.querySelector('textarea')?.value).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-textarea')?.getAttribute('data-count')).toBe(
|
||||
'5 / 5',
|
||||
);
|
||||
});
|
||||
|
||||
it('control exceed maxLength', () => {
|
||||
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(
|
||||
expect(container.querySelector('textarea')?.value).toBe('12345678');
|
||||
expect(container.querySelector('.ant-input-textarea')?.getAttribute('data-count')).toBe(
|
||||
'8 / 5',
|
||||
);
|
||||
});
|
||||
@ -258,29 +254,29 @@ describe('TextArea', () => {
|
||||
describe('emoji', () => {
|
||||
it('should minimize value between emoji length and maxLength', () => {
|
||||
const { container } = render(<TextArea maxLength={1} showCount value="👀" />);
|
||||
expect(container.querySelector('textarea').value).toBe('👀');
|
||||
expect(container.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe(
|
||||
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 { container: container1 } = render(<TextArea maxLength={2} showCount value="👀" />);
|
||||
expect(container1.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe(
|
||||
expect(container1.querySelector('.ant-input-textarea')?.getAttribute('data-count')).toBe(
|
||||
'1 / 2',
|
||||
);
|
||||
});
|
||||
|
||||
it('defaultValue should slice', () => {
|
||||
const { container } = render(<TextArea maxLength={1} defaultValue="🧐cut" />);
|
||||
expect(container.querySelector('textarea').value).toBe('🧐');
|
||||
expect(container.querySelector('textarea')?.value).toBe('🧐');
|
||||
});
|
||||
|
||||
// 修改TextArea value截取规则后新增单测
|
||||
it('slice emoji', () => {
|
||||
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(
|
||||
expect(container.querySelector('textarea')?.value).toBe('1234😂');
|
||||
expect(container.querySelector('.ant-input-textarea')?.getAttribute('data-count')).toBe(
|
||||
'5 / 5',
|
||||
);
|
||||
});
|
||||
@ -292,12 +288,12 @@ describe('TextArea', () => {
|
||||
);
|
||||
|
||||
// Outer
|
||||
expect(container.querySelector('div').classList.contains('bamboo')).toBeTruthy();
|
||||
expect(container.querySelector('div').style.background).toEqual('red');
|
||||
expect(container.querySelector('div')?.classList.contains('bamboo')).toBeTruthy();
|
||||
expect(container.querySelector('div')?.style.background).toEqual('red');
|
||||
|
||||
// Inner
|
||||
expect(container.querySelector('.ant-input').classList.contains('bamboo')).toBeFalsy();
|
||||
expect(container.querySelector('.ant-input').style.background).toBeFalsy();
|
||||
expect(container.querySelector('.ant-input')?.classList.contains('bamboo')).toBeFalsy();
|
||||
expect(container.querySelector<HTMLDivElement>('.ant-input')?.style.background).toBeFalsy();
|
||||
});
|
||||
|
||||
it('count formatter', () => {
|
||||
@ -310,8 +306,8 @@ describe('TextArea', () => {
|
||||
value="12345"
|
||||
/>,
|
||||
);
|
||||
expect(container.querySelector('textarea').value).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-textarea').getAttribute('data-count')).toBe(
|
||||
expect(container.querySelector('textarea')?.value).toBe('12345');
|
||||
expect(container.querySelector('.ant-input-textarea')?.getAttribute('data-count')).toBe(
|
||||
'12345, 5, 5',
|
||||
);
|
||||
});
|
||||
@ -319,36 +315,40 @@ describe('TextArea', () => {
|
||||
|
||||
it('should support size', async () => {
|
||||
const { asFragment, container } = render(<TextArea size="large" />);
|
||||
expect(container.querySelector('textarea').classList.contains('ant-input-lg')).toBe(true);
|
||||
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();
|
||||
const ref = React.createRef<TextAreaRef>();
|
||||
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);
|
||||
ref.current?.resizableTextArea?.textArea.setSelectionRange(valLength, valLength);
|
||||
expect(ref.current?.resizableTextArea?.textArea.selectionStart).toEqual(5);
|
||||
expect(ref.current?.resizableTextArea?.textArea.selectionEnd).toEqual(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TextArea allowClear', () => {
|
||||
it('should change type when click', () => {
|
||||
const { asFragment, container } = render(<TextArea allowClear />);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: '111' } });
|
||||
expect(container.querySelector('textarea').value).toEqual('111');
|
||||
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'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
expect(container.querySelector('textarea').value).toEqual('');
|
||||
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 => render(<TextArea allowClear value={val} />));
|
||||
const wrappers = [null, undefined, ''].map(val =>
|
||||
render(
|
||||
<TextArea allowClear value={val as TextareaHTMLAttributes<HTMLTextAreaElement>['value']} />,
|
||||
),
|
||||
);
|
||||
wrappers.forEach(({ asFragment, container }) => {
|
||||
expect(container.querySelector('textarea').value).toEqual('');
|
||||
expect(container.querySelector('textarea')?.value).toEqual('');
|
||||
expect(container.querySelector('.ant-input-clear-icon-hidden')).toBeTruthy();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
@ -356,10 +356,15 @@ describe('TextArea allowClear', () => {
|
||||
|
||||
it('should not show icon if defaultValue is undefined, null or empty string', () => {
|
||||
const wrappers = [null, undefined, ''].map(val =>
|
||||
render(<TextArea allowClear defaultValue={val} />),
|
||||
render(
|
||||
<TextArea
|
||||
allowClear
|
||||
defaultValue={val as TextareaHTMLAttributes<HTMLTextAreaElement>['value']}
|
||||
/>,
|
||||
),
|
||||
);
|
||||
wrappers.forEach(({ asFragment, container }) => {
|
||||
expect(container.querySelector('textarea').value).toEqual('');
|
||||
expect(container.querySelector('textarea')?.value).toEqual('');
|
||||
expect(container.querySelector('.ant-input-clear-icon-hidden')).toBeTruthy();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
@ -368,36 +373,36 @@ describe('TextArea allowClear', () => {
|
||||
it('should trigger event correctly', () => {
|
||||
let argumentEventObjectType;
|
||||
let argumentEventObjectValue;
|
||||
const onChange = e => {
|
||||
const onChange: ChangeEventHandler<HTMLTextAreaElement> = e => {
|
||||
argumentEventObjectType = e.type;
|
||||
argumentEventObjectValue = e.target.value;
|
||||
};
|
||||
const { container } = render(<TextArea allowClear defaultValue="111" onChange={onChange} />);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(argumentEventObjectType).toBe('click');
|
||||
expect(argumentEventObjectValue).toBe('');
|
||||
expect(container.querySelector('textarea').value).toBe('');
|
||||
expect(container.querySelector('textarea')?.value).toBe('');
|
||||
});
|
||||
|
||||
it('should trigger event correctly on controlled mode', () => {
|
||||
let argumentEventObjectType;
|
||||
let argumentEventObjectValue;
|
||||
const onChange = e => {
|
||||
const onChange: ChangeEventHandler<HTMLTextAreaElement> = e => {
|
||||
argumentEventObjectType = e.type;
|
||||
argumentEventObjectValue = e.target.value;
|
||||
};
|
||||
const { container } = render(<TextArea allowClear value="111" onChange={onChange} />);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(argumentEventObjectType).toBe('click');
|
||||
expect(argumentEventObjectValue).toBe('');
|
||||
expect(container.querySelector('textarea').value).toBe('111');
|
||||
expect(container.querySelector('textarea')?.value).toBe('111');
|
||||
});
|
||||
|
||||
it('should focus textarea after clear', () => {
|
||||
const { container, unmount } = render(<TextArea allowClear defaultValue="111" />, {
|
||||
container: document.body,
|
||||
});
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(document.activeElement).toBe(container.querySelector('textarea'));
|
||||
unmount();
|
||||
});
|
||||
@ -409,30 +414,30 @@ describe('TextArea allowClear', () => {
|
||||
|
||||
it('not block input when `value` is undefined', () => {
|
||||
const { container, rerender } = render(<Input value={undefined} />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'Bamboo' } });
|
||||
expect(container.querySelector('input').value).toEqual('Bamboo');
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: 'Bamboo' } });
|
||||
expect(container.querySelector('input')?.value).toEqual('Bamboo');
|
||||
|
||||
// Controlled
|
||||
rerender(<Input value="Light" />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'Bamboo' } });
|
||||
expect(container.querySelector('input').value).toEqual('Light');
|
||||
fireEvent.change(container.querySelector('input')!, { target: { value: 'Bamboo' } });
|
||||
expect(container.querySelector('input')?.value).toEqual('Light');
|
||||
});
|
||||
|
||||
it('scroll to bottom when autoSize', async () => {
|
||||
const ref = React.createRef();
|
||||
const ref = React.createRef<TextAreaRef>();
|
||||
const { container, unmount } = render(<Input.TextArea ref={ref} autoSize />, {
|
||||
container: document.body,
|
||||
legacyRoot: true,
|
||||
});
|
||||
fireEvent.focus(container.querySelector('textarea'));
|
||||
container.querySelector('textarea').focus();
|
||||
} as RenderOptions);
|
||||
fireEvent.focus(container.querySelector('textarea')!);
|
||||
container.querySelector('textarea')?.focus();
|
||||
|
||||
const setSelectionRangeFn = jest.spyOn(
|
||||
container.querySelector('textarea'),
|
||||
container.querySelector('textarea')!,
|
||||
'setSelectionRange',
|
||||
);
|
||||
fireEvent.input(container.querySelector('textarea'), { target: { value: '\n1' } });
|
||||
const target = ref.current.resizableTextArea.textArea;
|
||||
fireEvent.input(container.querySelector('textarea')!, { target: { value: '\n1' } });
|
||||
const target = ref.current?.resizableTextArea?.textArea!;
|
||||
triggerResize(target);
|
||||
await sleep(100);
|
||||
expect(setSelectionRangeFn).toHaveBeenCalled();
|
||||
@ -442,7 +447,7 @@ describe('TextArea allowClear', () => {
|
||||
// https://github.com/ant-design/ant-design/issues/26308
|
||||
it('should display defaultValue when value is undefined', () => {
|
||||
const { container } = render(<Input.TextArea defaultValue="Light" value={undefined} />);
|
||||
expect(container.querySelector('textarea').value).toBe('Light');
|
||||
expect(container.querySelector('textarea')?.value).toBe('Light');
|
||||
});
|
||||
|
||||
it('onChange event should return HTMLTextAreaElement', () => {
|
||||
@ -451,25 +456,23 @@ describe('TextArea allowClear', () => {
|
||||
|
||||
function isNativeElement() {
|
||||
expect(onChange).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
target: expect.any(HTMLTextAreaElement),
|
||||
}),
|
||||
expect.objectContaining({ target: expect.any(HTMLTextAreaElement) }),
|
||||
);
|
||||
|
||||
onChange.mockReset();
|
||||
}
|
||||
|
||||
// Change
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'bamboo' } });
|
||||
fireEvent.change(container.querySelector('textarea')!, { target: { value: 'bamboo' } });
|
||||
isNativeElement();
|
||||
|
||||
// Composition End
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'light' } });
|
||||
fireEvent.compositionEnd(container.querySelector('textarea'));
|
||||
fireEvent.change(container.querySelector('textarea')!, { target: { value: 'light' } });
|
||||
fireEvent.compositionEnd(container.querySelector('textarea')!);
|
||||
isNativeElement();
|
||||
|
||||
// Reset
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
isNativeElement();
|
||||
});
|
||||
|
||||
@ -489,12 +492,12 @@ describe('TextArea allowClear', () => {
|
||||
};
|
||||
|
||||
const { container, unmount } = render(<App />);
|
||||
container.querySelector('textarea').focus();
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: '111' } });
|
||||
expect(container.querySelector('textarea').value).toEqual('111');
|
||||
container.querySelector('textarea')?.focus();
|
||||
fireEvent.change(container.querySelector('textarea')!, { target: { value: '111' } });
|
||||
expect(container.querySelector('textarea')?.value).toEqual('111');
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
expect(container.querySelector('textarea').value).toEqual('');
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(container.querySelector('textarea')?.value).toEqual('');
|
||||
|
||||
unmount();
|
||||
});
|
||||
@ -508,12 +511,12 @@ describe('TextArea allowClear', () => {
|
||||
container: document.body,
|
||||
},
|
||||
);
|
||||
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'));
|
||||
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.toHaveBeenCalled();
|
||||
unmount();
|
||||
});
|
||||
@ -522,16 +525,20 @@ describe('TextArea allowClear', () => {
|
||||
const { container, unmount } = render(<TextArea allowClear defaultValue="111" />, {
|
||||
container: document.body,
|
||||
});
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(document.activeElement).toBe(container.querySelector('textarea'));
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should display boolean value as string', () => {
|
||||
const { container, rerender } = render(<TextArea value />);
|
||||
expect(container.querySelector('textarea').value).toBe('true');
|
||||
rerender(<TextArea value={false} />);
|
||||
expect(container.querySelector('textarea').value).toBe('false');
|
||||
const { container, rerender } = render(
|
||||
<TextArea value={true as unknown as TextareaHTMLAttributes<HTMLTextAreaElement>['value']} />,
|
||||
);
|
||||
expect(container.querySelector('textarea')?.value).toBe('true');
|
||||
rerender(
|
||||
<TextArea value={false as unknown as TextareaHTMLAttributes<HTMLTextAreaElement>['value']} />,
|
||||
);
|
||||
expect(container.querySelector('textarea')?.value).toBe('false');
|
||||
});
|
||||
|
||||
it('should focus when clearBtn is clicked in controlled case', () => {
|
||||
@ -541,18 +548,17 @@ describe('TextArea allowClear', () => {
|
||||
focus: handleFocus,
|
||||
});
|
||||
|
||||
const Demo = () => {
|
||||
const Demo: React.FC = () => {
|
||||
const [value, setValue] = React.useState('');
|
||||
|
||||
return <Input.TextArea allowClear value={value} onChange={e => setValue(e.target.value)} />;
|
||||
};
|
||||
|
||||
const { container } = render(<Demo />);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: 'test' } });
|
||||
fireEvent.change(container.querySelector('textarea')!, { target: { value: 'test' } });
|
||||
expect(container.querySelector('.ant-input-clear-icon')?.className).not.toContain(
|
||||
'ant-input-clear-icon-hidden',
|
||||
);
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon'));
|
||||
fireEvent.click(container.querySelector('.ant-input-clear-icon')!);
|
||||
expect(handleFocus).toHaveBeenCalledTimes(1);
|
||||
|
||||
textareaSpy.mockRestore();
|
@ -1,9 +1,9 @@
|
||||
import React, { useState } from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
import Layout from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import Icon from '../../icon';
|
||||
import Menu from '../../menu';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
|
||||
@ -31,14 +31,14 @@ describe('Layout', () => {
|
||||
<Content>Content</Content>
|
||||
</Layout>,
|
||||
);
|
||||
expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
|
||||
expect(container.querySelector('.ant-layout')?.className.includes('ant-layout-has-sider')).toBe(
|
||||
true,
|
||||
);
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('umount from multiple siders', async () => {
|
||||
const App = () => {
|
||||
const App: React.FC = () => {
|
||||
const [hide1, setHide1] = useState(false);
|
||||
const [hide2, setHide2] = useState(false);
|
||||
return (
|
||||
@ -57,15 +57,15 @@ describe('Layout', () => {
|
||||
);
|
||||
};
|
||||
const { container } = render(<App />);
|
||||
expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
|
||||
expect(container.querySelector('.ant-layout')?.className.includes('ant-layout-has-sider')).toBe(
|
||||
true,
|
||||
);
|
||||
fireEvent.click(container.querySelectorAll('button')[0]);
|
||||
expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
|
||||
expect(container.querySelector('.ant-layout')?.className.includes('ant-layout-has-sider')).toBe(
|
||||
true,
|
||||
);
|
||||
fireEvent.click(container.querySelectorAll('button')[1]);
|
||||
expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
|
||||
expect(container.querySelector('.ant-layout')?.className.includes('ant-layout-has-sider')).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
@ -79,7 +79,7 @@ describe('Layout', () => {
|
||||
<Content>Content</Content>
|
||||
</Layout>,
|
||||
);
|
||||
expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
|
||||
expect(container.querySelector('.ant-layout')?.className.includes('ant-layout-has-sider')).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
@ -96,7 +96,7 @@ describe('Layout', () => {
|
||||
expect(
|
||||
container
|
||||
.querySelector('.ant-layout-sider')
|
||||
.className.includes('ant-layout-sider-has-trigger'),
|
||||
?.className.includes('ant-layout-sider-has-trigger'),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
@ -109,8 +109,8 @@ describe('Layout', () => {
|
||||
<Content>Content</Content>
|
||||
</Layout>,
|
||||
);
|
||||
expect(container.querySelector('.ant-layout-sider').style.width).toBe('50%');
|
||||
expect(container.querySelector('.ant-layout-sider').style.flex).toBe('0 0 50%');
|
||||
expect(container.querySelector<HTMLElement>('.ant-layout-sider')?.style.width).toBe('50%');
|
||||
expect(container.querySelector<HTMLElement>('.ant-layout-sider')?.style.flex).toBe('0 0 50%');
|
||||
});
|
||||
|
||||
describe('zeroWidth', () => {
|
||||
@ -126,7 +126,7 @@ describe('Layout', () => {
|
||||
expect(
|
||||
container
|
||||
.querySelector('.ant-layout-sider')
|
||||
.className.includes('ant-layout-sider-zero-width'),
|
||||
?.className.includes('ant-layout-sider-zero-width'),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
@ -144,12 +144,12 @@ describe('Layout', () => {
|
||||
);
|
||||
|
||||
onCollapse.mockReset();
|
||||
fireEvent.click(container.querySelector('.ant-layout-sider-zero-width-trigger'));
|
||||
fireEvent.click(container.querySelector('.ant-layout-sider-zero-width-trigger')!);
|
||||
expect(onCollapse).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('controlled', () => {
|
||||
const Demo = () => {
|
||||
const Demo: React.FC = () => {
|
||||
const [collapsed, setCollapsed] = React.useState(true);
|
||||
|
||||
return (
|
||||
@ -170,7 +170,7 @@ describe('Layout', () => {
|
||||
|
||||
const { container } = render(<Demo />);
|
||||
expect(container.querySelector('.ant-layout-sider-collapsed')).toBeTruthy();
|
||||
fireEvent.click(container.querySelector('.ant-layout-sider-zero-width-trigger'));
|
||||
fireEvent.click(container.querySelector('.ant-layout-sider-zero-width-trigger')!);
|
||||
expect(container.querySelector('.ant-layout-sider-collapsed')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
@ -179,14 +179,14 @@ describe('Layout', () => {
|
||||
it('detect ant-layout-sider-dark as default theme', async () => {
|
||||
const { container } = render(<Sider>Sider</Sider>);
|
||||
expect(
|
||||
container.querySelector('.ant-layout-sider').className.includes('ant-layout-sider-dark'),
|
||||
container.querySelector('.ant-layout-sider')?.className.includes('ant-layout-sider-dark'),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('detect ant-layout-sider-light when set light theme', async () => {
|
||||
const { container } = render(<Sider theme="light">Sider</Sider>);
|
||||
expect(
|
||||
container.querySelector('.ant-layout-sider').className.includes('ant-layout-sider-light'),
|
||||
container.querySelector('.ant-layout-sider')?.className.includes('ant-layout-sider-light'),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
@ -208,7 +208,7 @@ describe('Layout', () => {
|
||||
<Sider>Sider</Sider>
|
||||
</Layout>,
|
||||
);
|
||||
expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
|
||||
expect(container.querySelector('.ant-layout')?.className.includes('ant-layout-has-sider')).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
@ -219,30 +219,29 @@ describe('Layout', () => {
|
||||
<Sider collapsible collapsed={false}>
|
||||
<Menu mode="inline">
|
||||
<Menu.Item key="1">
|
||||
<Icon type="user" />
|
||||
<UserOutlined />
|
||||
<span>Light</span>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Sider>,
|
||||
);
|
||||
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-menu-item'));
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-menu-item')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(container.querySelectorAll('.ant-tooltip-inner').length).toBeFalsy();
|
||||
|
||||
rerender(
|
||||
<Sider collapsible collapsed>
|
||||
<Menu mode="inline">
|
||||
<Menu.Item key="1">
|
||||
<Icon type="user" />
|
||||
<UserOutlined />
|
||||
<span>Light</span>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Sider>,
|
||||
);
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-menu-item'));
|
||||
fireEvent.mouseEnter(container.querySelector('.ant-menu-item')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -290,14 +289,15 @@ describe('Sider', () => {
|
||||
<Sider collapsedWidth={0} collapsible zeroWidthTriggerStyle={{ background: '#F96' }}>
|
||||
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
|
||||
<Menu.Item key="1">
|
||||
<Icon type="user" />
|
||||
<UserOutlined />
|
||||
<span>nav 1</span>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Sider>,
|
||||
);
|
||||
expect(
|
||||
container.querySelector('.ant-layout-sider-zero-width-trigger').style.background,
|
||||
container.querySelector<HTMLDivElement>('.ant-layout-sider-zero-width-trigger')?.style
|
||||
.background,
|
||||
).toEqual('rgb(255, 153, 102)');
|
||||
});
|
||||
|
||||
@ -306,24 +306,23 @@ describe('Sider', () => {
|
||||
<Sider collapsedWidth={0} collapsible trigger={<span className="my-trigger" />}>
|
||||
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
|
||||
<Menu.Item key="1">
|
||||
<Icon type="user" />
|
||||
<UserOutlined />
|
||||
<span>nav 1</span>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</Sider>,
|
||||
);
|
||||
expect(
|
||||
container.querySelector('.ant-layout-sider-zero-width-trigger').querySelector('.my-trigger'),
|
||||
container.querySelector('.ant-layout-sider-zero-width-trigger')?.querySelector('.my-trigger'),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
['Layout', 'Header', 'Footer', 'Sider'].forEach(tag => {
|
||||
const ComponentMap = { Layout, Header, Footer, Sider };
|
||||
it(`should get ${tag} element from ref`, () => {
|
||||
const ref = React.createRef();
|
||||
const ref = React.createRef<any>();
|
||||
const onSelect = jest.fn();
|
||||
const Component = ComponentMap[tag];
|
||||
|
||||
const Component = ComponentMap[tag as keyof typeof ComponentMap];
|
||||
render(
|
||||
<Component onSelect={onSelect} ref={ref}>
|
||||
{tag}
|
@ -49,7 +49,7 @@ describe('List Item Layout', () => {
|
||||
/>,
|
||||
);
|
||||
expect(
|
||||
wrapper.querySelector('.ant-list-item').classList.contains('ant-list-item-no-flex'),
|
||||
wrapper.querySelector('.ant-list-item')?.classList.contains('ant-list-item-no-flex'),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
@ -188,17 +188,17 @@ describe('List Item Layout', () => {
|
||||
});
|
||||
|
||||
it('should ref', () => {
|
||||
const ref = React.createRef();
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
|
||||
render(<List.Item ref={ref}>Item</List.Item>);
|
||||
expect(ref.current).toHaveClass('ant-list-item');
|
||||
});
|
||||
|
||||
it('should grid ref', () => {
|
||||
const ref = React.createRef();
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
|
||||
render(
|
||||
<List grid>
|
||||
<List grid={{}}>
|
||||
<List.Item ref={ref}>Item</List.Item>,
|
||||
</List>,
|
||||
);
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import type { ListProps } from '..';
|
||||
import List from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
@ -13,12 +14,12 @@ describe('List', () => {
|
||||
|
||||
it('locale not passed to internal div', async () => {
|
||||
const locale = { emptyText: 'Custom text' };
|
||||
const renderItem = item => <List.Item>{item}</List.Item>;
|
||||
const dataSource = [];
|
||||
const renderItem: ListProps<any>['renderItem'] = item => <List.Item>{item}</List.Item>;
|
||||
const dataSource: ListProps<any>['dataSource'] = [];
|
||||
|
||||
const { container } = render(
|
||||
<List renderItem={renderItem} dataSource={dataSource} locale={locale} />,
|
||||
);
|
||||
expect(container.querySelector('div.ant-list').getAttribute('locale')).toBe(null);
|
||||
expect(container.querySelector('div.ant-list')?.getAttribute('locale')).toBe(null);
|
||||
});
|
||||
});
|
@ -6,9 +6,7 @@ import List from '..';
|
||||
|
||||
describe('List', () => {
|
||||
it('renders empty loading', () => {
|
||||
const loading = {
|
||||
spinning: true,
|
||||
};
|
||||
const loading = { spinning: true };
|
||||
const { container: wrapper } = render(
|
||||
<List loading={loading} dataSource={[]} renderItem={() => <List.Item />} />,
|
||||
);
|
@ -1,10 +1,16 @@
|
||||
import React from 'react';
|
||||
import type { ListProps } from '..';
|
||||
import List from '..';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import { noop } from '../../_util/warning';
|
||||
|
||||
interface DataSourceItem {
|
||||
name: string;
|
||||
key: React.Key;
|
||||
}
|
||||
|
||||
describe('List.pagination', () => {
|
||||
const data = [
|
||||
const data: ListProps<DataSourceItem>['dataSource'] = [
|
||||
{ key: 0, name: 'Jack' },
|
||||
{ key: 1, name: 'Lucy' },
|
||||
{ key: 2, name: 'Tom' },
|
||||
@ -13,7 +19,7 @@ describe('List.pagination', () => {
|
||||
|
||||
const pagination = { className: 'my-page', pageSize: 2 };
|
||||
|
||||
function createList(props) {
|
||||
function createList(props?: ListProps<DataSourceItem>) {
|
||||
return (
|
||||
<List
|
||||
itemLayout="vertical"
|
||||
@ -25,10 +31,10 @@ describe('List.pagination', () => {
|
||||
);
|
||||
}
|
||||
|
||||
function renderedNames(wrapper) {
|
||||
function renderedNames(container: ReturnType<typeof render>['container']) {
|
||||
return Array.prototype.map.call(
|
||||
wrapper.querySelectorAll('.ant-list-item'),
|
||||
row => row.textContent,
|
||||
container.querySelectorAll('.ant-list-item'),
|
||||
(row: HTMLDivElement) => row.textContent,
|
||||
);
|
||||
}
|
||||
|
||||
@ -39,12 +45,7 @@ describe('List.pagination', () => {
|
||||
|
||||
it('should not show pager if pagination.hideOnSinglePage is true and only 1 page', () => {
|
||||
const { container: wrapper, rerender } = render(
|
||||
createList({
|
||||
pagination: {
|
||||
pageSize: 3,
|
||||
hideOnSinglePage: true,
|
||||
},
|
||||
}),
|
||||
createList({ pagination: { pageSize: 3, hideOnSinglePage: true } }),
|
||||
);
|
||||
expect(wrapper.querySelectorAll('.ant-pagination')).toHaveLength(1);
|
||||
rerender(createList({ pagination: { pageSize: 3, hideOnSinglePage: false } }));
|
||||
@ -107,13 +108,13 @@ describe('List.pagination', () => {
|
||||
expect(wrapper.querySelectorAll('.ant-pagination')).toHaveLength(1);
|
||||
expect(wrapper.querySelectorAll('.ant-pagination-item')).toHaveLength(2);
|
||||
|
||||
fireEvent.click(wrapper.querySelector('.ant-pagination-item-2'));
|
||||
fireEvent.click(wrapper.querySelector('.ant-pagination-item-2')!);
|
||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Jerry']);
|
||||
|
||||
rerender(createList({ pagination: false }));
|
||||
expect(wrapper.querySelectorAll('.ant-pagination')).toHaveLength(0);
|
||||
|
||||
rerender(createList({ pagination: true }));
|
||||
rerender(createList({ pagination: true as ListProps<DataSourceItem>['pagination'] }));
|
||||
expect(wrapper.querySelectorAll('.ant-pagination')).toHaveLength(1);
|
||||
// Legacy code will make pageSize ping with 10, here we fixed to keep sync by current one
|
||||
expect(wrapper.querySelectorAll('.ant-pagination-item')).toHaveLength(2);
|
||||
@ -123,7 +124,7 @@ describe('List.pagination', () => {
|
||||
// https://github.com/ant-design/ant-design/issues/5259
|
||||
it('change to correct page when data source changes', () => {
|
||||
const { container: wrapper, rerender } = render(createList({ pagination: { pageSize: 1 } }));
|
||||
fireEvent.click(wrapper.querySelector('.ant-pagination-item-3'));
|
||||
fireEvent.click(wrapper.querySelector('.ant-pagination-item-3')!);
|
||||
rerender(createList({ dataSource: [data[0]] }));
|
||||
expect(wrapper.querySelector('.ant-pagination-item-1')).toHaveClass(
|
||||
'ant-pagination-item-active',
|
||||
@ -134,20 +135,20 @@ describe('List.pagination', () => {
|
||||
const { container: wrapper, rerender } = render(
|
||||
createList({ pagination: { position: 'top' } }),
|
||||
);
|
||||
expect(wrapper.querySelector('.ant-list').querySelectorAll('.ant-pagination')).toHaveLength(1);
|
||||
expect(wrapper.querySelector('.ant-list')?.querySelectorAll('.ant-pagination')).toHaveLength(1);
|
||||
|
||||
rerender(createList({ pagination: { position: 'bottom' } }));
|
||||
expect(
|
||||
wrapper.querySelector('.ant-list').lastElementChild.querySelectorAll('.ant-pagination'),
|
||||
wrapper.querySelector('.ant-list')?.lastElementChild?.querySelectorAll('.ant-pagination'),
|
||||
).toHaveLength(1);
|
||||
|
||||
rerender(createList({ pagination: { position: 'both' } }));
|
||||
expect(wrapper.querySelectorAll('.ant-pagination')).toHaveLength(2);
|
||||
expect(
|
||||
wrapper.querySelector('.ant-list').firstElementChild.querySelectorAll('.ant-pagination'),
|
||||
wrapper.querySelector('.ant-list')?.firstElementChild?.querySelectorAll('.ant-pagination'),
|
||||
).toHaveLength(1);
|
||||
expect(
|
||||
wrapper.querySelector('.ant-list').lastElementChild.querySelectorAll('.ant-pagination'),
|
||||
wrapper.querySelector('.ant-list')?.lastElementChild?.querySelectorAll('.ant-pagination'),
|
||||
).toHaveLength(1);
|
||||
});
|
||||
|
||||
@ -155,10 +156,10 @@ describe('List.pagination', () => {
|
||||
const { container: wrapper } = render(createList({ pagination: { showSizeChanger: true } }));
|
||||
expect(wrapper.querySelector('.ant-pagination')).toMatchSnapshot();
|
||||
|
||||
fireEvent.mouseDown(wrapper.querySelector('.ant-select-selector'));
|
||||
fireEvent.mouseDown(wrapper.querySelector('.ant-select-selector')!);
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-select-item-option')[2]);
|
||||
|
||||
fireEvent.mouseDown(wrapper.querySelector('.ant-select-selector'));
|
||||
fireEvent.mouseDown(wrapper.querySelector('.ant-select-selector')!);
|
||||
expect(wrapper.querySelector('.ant-pagination')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@ -178,7 +179,7 @@ describe('List.pagination', () => {
|
||||
}),
|
||||
);
|
||||
|
||||
fireEvent.mouseDown(wrapper.querySelector('.ant-select-selector'));
|
||||
fireEvent.mouseDown(wrapper.querySelector('.ant-select-selector')!);
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-select-item-option')[1]);
|
||||
expect(handlePaginationChange).toHaveBeenCalledWith(1, 10);
|
||||
});
|
||||
@ -199,10 +200,6 @@ describe('List.pagination', () => {
|
||||
});
|
||||
|
||||
it('should not crash when pagination is null', () => {
|
||||
render(
|
||||
createList({
|
||||
pagination: null,
|
||||
}),
|
||||
);
|
||||
render(createList({ pagination: null as unknown as ListProps<DataSourceItem>['pagination'] }));
|
||||
});
|
||||
});
|
@ -5,12 +5,14 @@ import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import { resetWarned } from 'rc-util/lib/warning';
|
||||
import * as React from 'react';
|
||||
import TestUtils from 'react-dom/test-utils';
|
||||
import type { ModalFuncProps } from '..';
|
||||
import Modal from '..';
|
||||
import { sleep, act } from '../../../tests/utils';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import type { ModalFunc } from '../confirm';
|
||||
import destroyFns from '../destroyFns';
|
||||
|
||||
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
||||
(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
|
||||
const { confirm } = Modal;
|
||||
|
||||
@ -20,7 +22,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
// Inject CSSMotion to replace with No transition support
|
||||
const MockCSSMotion = genCSSMotion(false);
|
||||
Object.keys(MockCSSMotion).forEach(key => {
|
||||
CSSMotion[key] = MockCSSMotion[key];
|
||||
(CSSMotion as any)[key] = (MockCSSMotion as any)[key];
|
||||
});
|
||||
|
||||
// // Mock for rc-util raf
|
||||
@ -67,11 +69,11 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
function $$(className) {
|
||||
return document.body.querySelectorAll(className);
|
||||
function $$(className: string) {
|
||||
return document.body.querySelectorAll<HTMLElement>(className);
|
||||
}
|
||||
|
||||
function open(args) {
|
||||
function open(args?: ModalFuncProps) {
|
||||
jest.useFakeTimers();
|
||||
confirm({
|
||||
title: 'Want to delete these items?',
|
||||
@ -242,23 +244,22 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
|
||||
it('allows extra props on buttons', async () => {
|
||||
open({ okButtonProps: { disabled: true }, cancelButtonProps: { 'data-test': 'baz' } });
|
||||
open({
|
||||
okButtonProps: { disabled: true },
|
||||
cancelButtonProps: { 'data-test': 'baz' } as ModalFuncProps['cancelButtonProps'],
|
||||
});
|
||||
|
||||
await sleep();
|
||||
expect($$('.ant-btn')).toHaveLength(2);
|
||||
expect($$('.ant-btn')[0].attributes['data-test'].value).toBe('baz');
|
||||
expect($$('.ant-btn')[1].disabled).toBe(true);
|
||||
expect(($$('.ant-btn')[0].attributes as any)['data-test'].value).toBe('baz');
|
||||
expect(($$('.ant-btn')[1] as HTMLButtonElement).disabled).toBe(true);
|
||||
});
|
||||
|
||||
describe('should close modals when click confirm button', () => {
|
||||
['info', 'success', 'warning', 'error'].forEach(type => {
|
||||
(['info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
it(type, async () => {
|
||||
jest.useFakeTimers();
|
||||
Modal[type]({
|
||||
title: 'title',
|
||||
content: 'content',
|
||||
});
|
||||
|
||||
Modal[type]?.({ title: 'title', content: 'content' });
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
@ -325,13 +326,13 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
|
||||
describe('should not close modals when click confirm button when onOk has argument', () => {
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
(['confirm', 'info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
it(type, async () => {
|
||||
jest.useFakeTimers();
|
||||
Modal[type]({
|
||||
Modal[type]?.({
|
||||
title: 'title',
|
||||
content: 'content',
|
||||
onOk: close => null, // eslint-disable-line no-unused-vars
|
||||
onOk: _ => null, // eslint-disable-line no-unused-vars
|
||||
});
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
@ -351,10 +352,10 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
|
||||
describe('could be update by new config', () => {
|
||||
['info', 'success', 'warning', 'error'].forEach(type => {
|
||||
(['info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
it(type, async () => {
|
||||
jest.useFakeTimers();
|
||||
const instance = Modal[type]({
|
||||
const instance = Modal[type]?.({
|
||||
title: 'title',
|
||||
content: 'content',
|
||||
});
|
||||
@ -387,17 +388,12 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
|
||||
describe('could be update by call function', () => {
|
||||
['info', 'success', 'warning', 'error'].forEach(type => {
|
||||
(['info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
it(type, () => {
|
||||
jest.useFakeTimers();
|
||||
const instance = Modal[type]({
|
||||
const instance = Modal[type]?.({
|
||||
title: 'title',
|
||||
okButtonProps: {
|
||||
loading: true,
|
||||
style: {
|
||||
color: 'red',
|
||||
},
|
||||
},
|
||||
okButtonProps: { loading: true, style: { color: 'red' } },
|
||||
});
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
@ -434,10 +430,10 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
|
||||
describe('could be destroy', () => {
|
||||
['info', 'success', 'warning', 'error'].forEach(type => {
|
||||
(['info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
jest.useFakeTimers();
|
||||
it(type, async () => {
|
||||
const instance = Modal[type]({
|
||||
const instance = Modal[type]?.({
|
||||
title: 'title',
|
||||
content: 'content',
|
||||
});
|
||||
@ -462,8 +458,8 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
// Show
|
||||
['info', 'success', 'warning', 'error'].forEach(type => {
|
||||
Modal[type]({
|
||||
(['info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
Modal[type]?.({
|
||||
title: 'title',
|
||||
content: 'content',
|
||||
});
|
||||
@ -515,9 +511,9 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
|
||||
const instances = [];
|
||||
['info', 'success', 'warning', 'error'].forEach(type => {
|
||||
const instance = Modal[type]({
|
||||
const instances: ReturnType<ModalFunc>[] = [];
|
||||
(['info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
const instance = Modal[type]?.({
|
||||
title: 'title',
|
||||
content: 'content',
|
||||
});
|
||||
@ -588,8 +584,9 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
it('ok button should trigger onOk multiple times when onOk has close argument', async () => {
|
||||
const onOk = jest.fn();
|
||||
open({
|
||||
onOk: close => {
|
||||
onOk(close?: any) {
|
||||
onOk();
|
||||
// @ts-ignore
|
||||
(() => {})(close); // do nothing
|
||||
},
|
||||
});
|
||||
@ -615,7 +612,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
expect(document.querySelectorAll('.my-btn').length).toBe(2);
|
||||
expect(document.querySelectorAll('.bamboo-smile').length).toBe(1);
|
||||
expect(document.querySelectorAll('.my-modal-confirm').length).toBe(1);
|
||||
ConfigProvider.config({ prefixCls: 'ant', iconPrefixCls: null });
|
||||
ConfigProvider.config({ prefixCls: 'ant', iconPrefixCls: undefined });
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
@ -702,12 +699,12 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
|
||||
describe('the callback close should be a method when onCancel has a close parameter', () => {
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
(['confirm', 'info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
it(`click the close icon to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
Modal[type]?.({
|
||||
closable: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
@ -732,12 +729,12 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
});
|
||||
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
(['confirm', 'info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
it(`press ESC to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
Modal[type]?.({
|
||||
keyboard: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
@ -770,12 +767,12 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
});
|
||||
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
(['confirm', 'info', 'success', 'warning', 'error'] as const).forEach(type => {
|
||||
it(`click the mask to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
Modal[type]?.({
|
||||
maskClosable: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
@ -1,4 +1,6 @@
|
||||
import React from 'react';
|
||||
import type { OptionFC } from 'rc-select/lib/Option';
|
||||
import type { PaginationProps } from '..';
|
||||
import Pagination from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
@ -11,7 +13,7 @@ describe('Pagination', () => {
|
||||
rtlTest(Pagination);
|
||||
|
||||
it('should pass disabled to prev and next buttons', () => {
|
||||
const itemRender = (current, type, originalElement) => {
|
||||
const itemRender: PaginationProps['itemRender'] = (_, type, originalElement) => {
|
||||
if (type === 'prev') {
|
||||
return <button type="button">prev</button>;
|
||||
}
|
||||
@ -23,12 +25,12 @@ describe('Pagination', () => {
|
||||
const { container } = render(
|
||||
<Pagination defaultCurrent={1} total={50} itemRender={itemRender} />,
|
||||
);
|
||||
expect(container.querySelector('button').disabled).toBe(true);
|
||||
expect(container.querySelector('button')?.disabled).toBe(true);
|
||||
});
|
||||
|
||||
it('should autometically be small when size is not specified', async () => {
|
||||
const { container } = render(<Pagination responsive />);
|
||||
expect(container.querySelector('ul').className.includes('ant-pagination-mini')).toBe(true);
|
||||
expect(container.querySelector('ul')?.className.includes('ant-pagination-mini')).toBe(true);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/24913
|
||||
@ -45,7 +47,7 @@ describe('Pagination', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.mouseDown(container.querySelector('.ant-select-selector'));
|
||||
fireEvent.mouseDown(container.querySelector('.ant-select-selector')!);
|
||||
|
||||
expect(container.querySelectorAll('.ant-select-item-option').length).toBe(4);
|
||||
fireEvent.click(container.querySelectorAll('.ant-select-item-option')[1]);
|
||||
@ -53,9 +55,10 @@ describe('Pagination', () => {
|
||||
});
|
||||
|
||||
it('should support custom selectComponentClass', () => {
|
||||
const CustomSelect = ({ className, ...props }) => (
|
||||
<Select className={`${className} custom-select`} {...props} />
|
||||
);
|
||||
const CustomSelect: React.FC<{ className?: string }> & { Option: OptionFC } = ({
|
||||
className,
|
||||
...props
|
||||
}) => <Select className={`${className} custom-select`} {...props} />;
|
||||
|
||||
CustomSelect.Option = Select.Option;
|
||||
|
@ -49,7 +49,7 @@ export const sortGradient = (gradients: StringGradients) => {
|
||||
* "100%": "#ffffff"
|
||||
* }
|
||||
*/
|
||||
export const handleGradient = (strokeColor: ProgressGradient, directionConfig: DirectionType) => {
|
||||
export const handleGradient = (strokeColor: ProgressGradient, directionConfig?: DirectionType) => {
|
||||
const {
|
||||
from = presetPrimaryColors.blue,
|
||||
to = presetPrimaryColors.blue,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import type { ProgressProps } from '..';
|
||||
import Progress from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
@ -162,7 +163,9 @@ describe('Progress', () => {
|
||||
// https://github.com/ant-design/ant-design/pull/15951#discussion_r273062969
|
||||
it('should show success status when status is invalid', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const { container: wrapper } = render(<Progress percent={100} status="invalid" />);
|
||||
const { container: wrapper } = render(
|
||||
<Progress percent={100} status={'invalid' as ProgressProps['status']} />,
|
||||
);
|
||||
expect(wrapper.querySelectorAll('.ant-progress-status-success')).toHaveLength(1);
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
@ -183,21 +186,23 @@ describe('Progress', () => {
|
||||
const { container: wrapper, rerender } = render(
|
||||
<Progress steps={5} percent={60} strokeColor="#1890ff" />,
|
||||
);
|
||||
expect(wrapper.querySelectorAll('.ant-progress-steps-item')[0].style.backgroundColor).toBe(
|
||||
'rgb(24, 144, 255)',
|
||||
);
|
||||
expect(
|
||||
wrapper.querySelectorAll<HTMLDivElement>('.ant-progress-steps-item')[0].style.backgroundColor,
|
||||
).toBe('rgb(24, 144, 255)');
|
||||
rerender(<Progress steps={5} percent={40} strokeColor="#1890ff" />);
|
||||
expect(wrapper.querySelectorAll('.ant-progress-steps-item')[2].style.backgroundColor).toBe('');
|
||||
expect(wrapper.querySelectorAll('.ant-progress-steps-item')[1].style.backgroundColor).toBe(
|
||||
'rgb(24, 144, 255)',
|
||||
);
|
||||
expect(
|
||||
wrapper.querySelectorAll<HTMLDivElement>('.ant-progress-steps-item')[2].style.backgroundColor,
|
||||
).toBe('');
|
||||
expect(
|
||||
wrapper.querySelectorAll<HTMLDivElement>('.ant-progress-steps-item')[1].style.backgroundColor,
|
||||
).toBe('rgb(24, 144, 255)');
|
||||
});
|
||||
|
||||
it('steps should support trailColor', () => {
|
||||
const { container: wrapper } = render(<Progress steps={5} percent={20} trailColor="#1890ee" />);
|
||||
expect(wrapper.querySelectorAll('.ant-progress-steps-item')[1].style.backgroundColor).toBe(
|
||||
'rgb(24, 144, 238)',
|
||||
);
|
||||
expect(
|
||||
wrapper.querySelectorAll<HTMLDivElement>('.ant-progress-steps-item')[1].style.backgroundColor,
|
||||
).toBe('rgb(24, 144, 238)');
|
||||
});
|
||||
|
||||
it('should display correct step', () => {
|
||||
@ -210,8 +215,8 @@ describe('Progress', () => {
|
||||
});
|
||||
|
||||
it('steps should have default percent 0', () => {
|
||||
const { container: wrapper } = render(<ProgressSteps />);
|
||||
expect(wrapper.firstChild).toMatchSnapshot();
|
||||
const { container } = render(<ProgressSteps steps={0} />);
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should warnning if use `progress` in success', () => {
|
@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import type { RefAttributes } from 'react';
|
||||
import type { RadioGroupProps } from '..';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
import Radio from '..';
|
||||
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
describe('Radio Group', () => {
|
||||
function createRadioGroup(props) {
|
||||
function createRadioGroup(props?: RadioGroupProps & RefAttributes<HTMLDivElement>) {
|
||||
return (
|
||||
<Radio.Group {...props}>
|
||||
<Radio value="A">A</Radio>
|
||||
@ -14,13 +15,12 @@ describe('Radio Group', () => {
|
||||
);
|
||||
}
|
||||
|
||||
function createRadioGroupByOption(props) {
|
||||
function createRadioGroupByOption(props?: RadioGroupProps & RefAttributes<HTMLDivElement>) {
|
||||
const options = [
|
||||
{ label: 'A', value: 'A' },
|
||||
{ label: 'B', value: 'B' },
|
||||
{ label: 'C', value: 'C' },
|
||||
];
|
||||
|
||||
return <Radio.Group {...props} options={options} />;
|
||||
}
|
||||
|
||||
@ -34,10 +34,10 @@ describe('Radio Group', () => {
|
||||
</Radio.Group>,
|
||||
);
|
||||
|
||||
fireEvent.mouseEnter(container.querySelector('div'));
|
||||
fireEvent.mouseEnter(container.querySelector('div')!);
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
fireEvent.mouseLeave(container.querySelector('div'));
|
||||
fireEvent.mouseLeave(container.querySelector('div')!);
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -66,7 +66,9 @@ describe('Radio Group', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChangeRadioGroup = jest.fn();
|
||||
|
||||
const RadioGroup = props => (
|
||||
const RadioGroup: React.FC<
|
||||
RadioGroupProps & { onChangeRadioGroup: RadioGroupProps['onChange'] }
|
||||
> = props => (
|
||||
<Radio.Group onChange={props.onChangeRadioGroup}>
|
||||
<Radio value="A" onChange={props.onChange}>
|
||||
A
|
||||
@ -95,7 +97,7 @@ describe('Radio Group', () => {
|
||||
it('Trigger onChange when both of radioButton and radioGroup exists', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const RadioGroup = props => (
|
||||
const RadioGroup: React.FC<RadioGroupProps> = props => (
|
||||
<Radio.Group {...props}>
|
||||
<Radio.Button value="A">A</Radio.Button>
|
||||
<Radio.Button value="B">B</Radio.Button>
|
||||
@ -117,7 +119,7 @@ describe('Radio Group', () => {
|
||||
const options = [{ label: 'Bamboo', value: 'Bamboo' }];
|
||||
const { container } = render(<Radio.Group options={options} onChange={onChange} />);
|
||||
|
||||
fireEvent.click(container.querySelector('input'));
|
||||
fireEvent.click(container.querySelector('input')!);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@ -153,7 +155,7 @@ describe('Radio Group', () => {
|
||||
const GROUP_NAME = 'GROUP_NAME';
|
||||
const { container } = render(createRadioGroup({ name: GROUP_NAME }));
|
||||
|
||||
container.querySelectorAll('input[type="radio"]').forEach(el => {
|
||||
container.querySelectorAll<HTMLInputElement>('input[type="radio"]').forEach(el => {
|
||||
expect(el.name).toEqual(GROUP_NAME);
|
||||
});
|
||||
});
|
||||
@ -168,16 +170,16 @@ describe('Radio Group', () => {
|
||||
});
|
||||
|
||||
it('should forward ref', () => {
|
||||
let radioGroupRef;
|
||||
let radioGroupRef: HTMLDivElement;
|
||||
const { container } = render(
|
||||
createRadioGroupByOption({
|
||||
ref: ref => {
|
||||
ref(ref: HTMLDivElement) {
|
||||
radioGroupRef = ref;
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(radioGroupRef).toBe(container.querySelector('.ant-radio-group'));
|
||||
expect(radioGroupRef!).toBe(container.querySelector<HTMLDivElement>('.ant-radio-group'));
|
||||
});
|
||||
|
||||
it('should support data-* or aria-* props', () => {
|
||||
@ -185,10 +187,14 @@ describe('Radio Group', () => {
|
||||
createRadioGroup({
|
||||
'data-radio-group-id': 'radio-group-id',
|
||||
'aria-label': 'radio-group',
|
||||
}),
|
||||
} as RadioGroupProps),
|
||||
);
|
||||
expect((container.firstChild as HTMLDivElement)?.getAttribute('data-radio-group-id')).toBe(
|
||||
'radio-group-id',
|
||||
);
|
||||
expect((container.firstChild as HTMLDivElement)?.getAttribute('aria-label')).toBe(
|
||||
'radio-group',
|
||||
);
|
||||
expect(container.firstChild.getAttribute('data-radio-group-id')).toBe('radio-group-id');
|
||||
expect(container.firstChild.getAttribute('aria-label')).toBe('radio-group');
|
||||
});
|
||||
|
||||
it('Radio type should not be override', () => {
|
||||
@ -241,9 +247,9 @@ describe('Radio Group', () => {
|
||||
const { container } = render(
|
||||
<Radio.Group options={['1', '2', '3']} onBlur={handleBlur} onFocus={handleFocus} />,
|
||||
);
|
||||
fireEvent.focus(container.firstChild);
|
||||
fireEvent.focus(container.firstChild!);
|
||||
expect(handleFocus).toHaveBeenCalledTimes(1);
|
||||
fireEvent.blur(container.firstChild);
|
||||
fireEvent.blur(container.firstChild!);
|
||||
expect(handleBlur).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
@ -1,4 +1,6 @@
|
||||
import type { RefAttributes } from 'react';
|
||||
import React from 'react';
|
||||
import type { RadioGroupProps } from '..';
|
||||
import Radio, { Button } from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
@ -25,16 +27,16 @@ describe('Radio Button', () => {
|
||||
<Button onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />,
|
||||
);
|
||||
|
||||
fireEvent.mouseEnter(container.querySelector('label'));
|
||||
fireEvent.mouseEnter(container.querySelector('label')!);
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
fireEvent.mouseLeave(container.querySelector('label'));
|
||||
fireEvent.mouseLeave(container.querySelector('label')!);
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Radio Group', () => {
|
||||
function createRadioGroup(props) {
|
||||
function createRadioGroup(props?: RadioGroupProps & RefAttributes<HTMLDivElement>) {
|
||||
return (
|
||||
<Radio.Group {...props}>
|
||||
<Button value="A">A</Button>
|
||||
@ -128,7 +130,7 @@ describe('Radio Group', () => {
|
||||
const options = [{ label: 'Bamboo', value: 'Bamboo' }];
|
||||
const { container } = render(<Radio.Group options={options} onChange={onChange} />);
|
||||
|
||||
fireEvent.click(container.querySelector('input'));
|
||||
fireEvent.click(container.querySelector('input')!);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@ -152,7 +154,7 @@ describe('Radio Group', () => {
|
||||
const GROUP_NAME = 'GROUP_NAME';
|
||||
const { container } = render(createRadioGroup({ name: GROUP_NAME }));
|
||||
|
||||
container.querySelectorAll('input[type="radio"]').forEach(el => {
|
||||
container.querySelectorAll<HTMLInputElement>('input[type="radio"]').forEach(el => {
|
||||
expect(el.name).toEqual(GROUP_NAME);
|
||||
});
|
||||
});
|
||||
@ -167,16 +169,16 @@ describe('Radio Group', () => {
|
||||
});
|
||||
|
||||
it('should forward ref', () => {
|
||||
let radioGroupRef;
|
||||
let radioGroupRef: HTMLDivElement;
|
||||
const { container } = render(
|
||||
createRadioGroup({
|
||||
ref: ref => {
|
||||
ref(ref: HTMLDivElement) {
|
||||
radioGroupRef = ref;
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(radioGroupRef).toBe(container.querySelector('.ant-radio-group'));
|
||||
expect(radioGroupRef!).toBe(container.querySelector('.ant-radio-group'));
|
||||
});
|
||||
|
||||
it('should support data-* or aria-* props', () => {
|
||||
@ -184,10 +186,14 @@ describe('Radio Group', () => {
|
||||
createRadioGroup({
|
||||
'data-radio-group-id': 'radio-group-id',
|
||||
'aria-label': 'radio-group',
|
||||
}),
|
||||
} as RadioGroupProps),
|
||||
);
|
||||
expect((container.firstChild as HTMLDivElement)?.getAttribute('data-radio-group-id')).toBe(
|
||||
'radio-group-id',
|
||||
);
|
||||
expect((container.firstChild as HTMLDivElement)?.getAttribute('aria-label')).toBe(
|
||||
'radio-group',
|
||||
);
|
||||
expect(container.firstChild.getAttribute('data-radio-group-id')).toBe('radio-group-id');
|
||||
expect(container.firstChild.getAttribute('aria-label')).toBe('radio-group');
|
||||
});
|
||||
|
||||
it('Radio type should not be override', () => {
|
@ -27,10 +27,10 @@ describe('Radio', () => {
|
||||
|
||||
const { container } = render(<Radio onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />);
|
||||
|
||||
fireEvent.mouseEnter(container.querySelector('label'));
|
||||
fireEvent.mouseEnter(container.querySelector('label')!);
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
fireEvent.mouseLeave(container.querySelector('label'));
|
||||
fireEvent.mouseLeave(container.querySelector('label')!);
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -63,7 +63,6 @@ exports[`Select Deprecated should ignore mode="combobox" 1`] = `
|
||||
exports[`Select Select Custom Icons should support customized icons 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-single ant-select-show-arrow"
|
||||
count="10"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import { CloseOutlined } from '@ant-design/icons';
|
||||
import type { SelectProps } from '..';
|
||||
import Select from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, render, act } from '../../../tests/utils';
|
||||
import Icon from '../../icon';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -13,8 +14,8 @@ describe('Select', () => {
|
||||
mountTest(Select);
|
||||
rtlTest(Select);
|
||||
|
||||
function toggleOpen(container) {
|
||||
fireEvent.mouseDown(container.querySelector('.ant-select-selector'));
|
||||
function toggleOpen(container: ReturnType<typeof render>['container']): void {
|
||||
fireEvent.mouseDown(container.querySelector('.ant-select-selector')!);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -42,14 +43,19 @@ describe('Select', () => {
|
||||
});
|
||||
|
||||
it('should not have default notFoundContent when mode is combobox', () => {
|
||||
const { container } = render(<Select mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE} />);
|
||||
const { container } = render(
|
||||
<Select mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE as SelectProps['mode']} />,
|
||||
);
|
||||
toggleOpen(container);
|
||||
expect(container.querySelector('.ant-empty')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not have notFoundContent when mode is combobox and notFoundContent is set', () => {
|
||||
const { container } = render(
|
||||
<Select mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE} notFoundContent="not at all" />,
|
||||
<Select
|
||||
mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE as SelectProps['mode']}
|
||||
notFoundContent="not at all"
|
||||
/>,
|
||||
);
|
||||
toggleOpen(container);
|
||||
expect(container.querySelector('.ant-select-item-option')).toBeFalsy();
|
||||
@ -58,9 +64,9 @@ describe('Select', () => {
|
||||
|
||||
it('should be controlled by open prop', () => {
|
||||
const onDropdownVisibleChange = jest.fn();
|
||||
const TestComponent = () => {
|
||||
const TestComponent: React.FC = () => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const handleChange = value => {
|
||||
const handleChange: SelectProps['onDropdownVisibleChange'] = value => {
|
||||
onDropdownVisibleChange(value);
|
||||
setOpen(value);
|
||||
};
|
||||
@ -100,24 +106,22 @@ describe('Select', () => {
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
//
|
||||
describe('Select Custom Icons', () => {
|
||||
it('should support customized icons', () => {
|
||||
const { rerender, asFragment } = render(
|
||||
<Select
|
||||
removeIcon={<Icon type="close" />}
|
||||
clearIcon={<Icon type="close" />}
|
||||
menuItemSelectedIcon={<Icon type="close" />}
|
||||
removeIcon={<CloseOutlined />}
|
||||
clearIcon={<CloseOutlined />}
|
||||
menuItemSelectedIcon={<CloseOutlined />}
|
||||
>
|
||||
<Option value="1">1</Option>
|
||||
</Select>,
|
||||
);
|
||||
rerender(
|
||||
<Select
|
||||
count={10}
|
||||
removeIcon={<Icon type="close" />}
|
||||
clearIcon={<Icon type="close" />}
|
||||
menuItemSelectedIcon={<Icon type="close" />}
|
||||
removeIcon={<CloseOutlined />}
|
||||
clearIcon={<CloseOutlined />}
|
||||
menuItemSelectedIcon={<CloseOutlined />}
|
||||
>
|
||||
<Option value="1">1</Option>
|
||||
</Select>,
|
||||
@ -132,7 +136,7 @@ describe('Select', () => {
|
||||
describe('Deprecated', () => {
|
||||
it('should ignore mode="combobox"', () => {
|
||||
const { asFragment } = render(
|
||||
<Select mode="combobox">
|
||||
<Select mode={'combobox' as SelectProps['mode']}>
|
||||
<Option value="1">1</Option>
|
||||
</Select>,
|
||||
);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user