chore: next merge master

This commit is contained in:
二货机器人 2022-09-23 10:49:38 +08:00
commit ba26b4c196
11 changed files with 104 additions and 66 deletions

View File

@ -1,6 +0,0 @@
import Divider from '..';
import mountTest from '../../../tests/shared/mountTest';
describe('Divider', () => {
mountTest(Divider);
});

View File

@ -0,0 +1,17 @@
import * as React from 'react';
import { render } from '../../../tests/utils';
import Divider from '..';
import mountTest from '../../../tests/shared/mountTest';
describe('Divider', () => {
mountTest(Divider);
it('not show children when vertical', () => {
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const { container } = render(<Divider type="vertical">Bamboo</Divider>);
expect(container.querySelector('.ant-divider-inner-text')).toBeFalsy();
errSpy.mockRestore();
});
});

View File

@ -1,6 +1,7 @@
import classNames from 'classnames'; import classNames from 'classnames';
import * as React from 'react'; import * as React from 'react';
import { ConfigContext } from '../config-provider'; import { ConfigContext } from '../config-provider';
import warning from '../_util/warning';
import useStyle from './style'; import useStyle from './style';
@ -58,9 +59,18 @@ const Divider: React.FC<DividerProps> = props => {
...(hasCustomMarginRight && { marginRight: orientationMargin }), ...(hasCustomMarginRight && { marginRight: orientationMargin }),
}; };
// Warning children not work in vertical mode
if (process.env.NODE_ENV !== 'production') {
warning(
!children || type !== 'vertical',
'Divider',
'`children` not working in `vertical` mode.',
);
}
return wrapSSR( return wrapSSR(
<div className={classString} {...restProps} role="separator"> <div className={classString} {...restProps} role="separator">
{children && ( {children && type !== 'vertical' && (
<span className={`${prefixCls}-inner-text`} style={innerStyle}> <span className={`${prefixCls}-inner-text`} style={innerStyle}>
{children} {children}
</span> </span>

View File

@ -1,9 +1,9 @@
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import React, { Component, useState } from 'react'; import React, { Component, useState } from 'react';
import { act } from 'react-dom/test-utils';
import scrollIntoView from 'scroll-into-view-if-needed'; import scrollIntoView from 'scroll-into-view-if-needed';
import classNames from 'classnames'; import classNames from 'classnames';
import Form from '..'; import Form from '..';
import type { FormInstance } from '..';
import * as Util from '../util'; import * as Util from '../util';
import Button from '../../button'; import Button from '../../button';
@ -20,7 +20,7 @@ import TreeSelect from '../../tree-select';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render, sleep } from '../../../tests/utils'; import { fireEvent, render, sleep, act } from '../../../tests/utils';
import ConfigProvider from '../../config-provider'; import ConfigProvider from '../../config-provider';
import Drawer from '../../drawer'; import Drawer from '../../drawer';
import zhCN from '../../locale/zh_CN'; import zhCN from '../../locale/zh_CN';
@ -38,10 +38,10 @@ describe('Form', () => {
rtlTest(Form); rtlTest(Form);
rtlTest(Form.Item); rtlTest(Form.Item);
scrollIntoView.mockImplementation(() => {}); (scrollIntoView as any).mockImplementation(() => {});
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
async function change(container, index, value, executeMockTimer) { async function change(container: Element, index: number, value: any, executeMockTimer: boolean) {
fireEvent.change(container.querySelectorAll('input')[index], { fireEvent.change(container.querySelectorAll('input')[index], {
target: { value }, target: { value },
}); });
@ -59,7 +59,7 @@ describe('Form', () => {
beforeEach(() => { beforeEach(() => {
jest.useRealTimers(); jest.useRealTimers();
scrollIntoView.mockReset(); (scrollIntoView as any).mockReset();
}); });
afterEach(() => { afterEach(() => {
@ -68,7 +68,7 @@ describe('Form', () => {
afterAll(() => { afterAll(() => {
errorSpy.mockRestore(); errorSpy.mockRestore();
scrollIntoView.mockRestore(); (scrollIntoView as any).mockRestore();
}); });
describe('noStyle Form.Item', () => { describe('noStyle Form.Item', () => {
@ -143,11 +143,11 @@ describe('Form', () => {
const { container } = render(<Demo />); const { container } = render(<Demo />);
await change(container, 0, '1', true); await change(container, 0, '1', true);
expect(container.querySelector('.ant-form-item-explain').textContent).toEqual('aaa'); expect(container.querySelector('.ant-form-item-explain')!.textContent).toEqual('aaa');
await change(container, 0, '2', true); await change(container, 0, '2', true);
expect(container.querySelector('.ant-form-item-explain').textContent).toEqual('ccc'); expect(container.querySelector('.ant-form-item-explain')!.textContent).toEqual('ccc');
await change(container, 0, '1', true); await change(container, 0, '1', true);
expect(container.querySelector('.ant-form-item-explain').textContent).toEqual('aaa'); expect(container.querySelector('.ant-form-item-explain')!.textContent).toEqual('aaa');
jest.useRealTimers(); jest.useRealTimers();
}); });
@ -356,9 +356,9 @@ describe('Form', () => {
}); });
describe('scrollToField', () => { describe('scrollToField', () => {
function test(name, genForm) { function test(name: string, genForm: () => { props: any; getForm: () => FormInstance }) {
it(name, () => { it(name, () => {
let callGetForm; let callGetForm: () => FormInstance = undefined!;
const Demo = () => { const Demo = () => {
const { props, getForm } = genForm(); const { props, getForm } = genForm();
@ -402,10 +402,10 @@ describe('Form', () => {
// ref // ref
test('ref', () => { test('ref', () => {
let form; let form: FormInstance;
return { return {
props: { props: {
ref: instance => { ref: (instance: FormInstance) => {
form = instance; form = instance;
}, },
}, },
@ -442,7 +442,7 @@ describe('Form', () => {
it('Form.Item should support data-*、aria-* and custom attribute', () => { it('Form.Item should support data-*、aria-* and custom attribute', () => {
const wrapper = mount( const wrapper = mount(
<Form> <Form>
<Form.Item data-text="123" aria-hidden="true" cccc="bbbb"> <Form.Item data-text="123" aria-hidden="true" {...{ cccc: 'bbbb' }}>
text text
</Form.Item> </Form.Item>
</Form>, </Form>,
@ -547,13 +547,13 @@ describe('Form', () => {
for (let i = 0; i < 3; i += 1) { for (let i = 0; i < 3; i += 1) {
await change(container, 0, 'bamboo', true); await change(container, 0, 'bamboo', true);
await change(container, 0, '', true); await change(container, 0, '', true);
expect(container.querySelector('.ant-form-item-explain').textContent).toEqual( expect(container.querySelector('.ant-form-item-explain')!.textContent).toEqual(
"'name' is required", "'name' is required",
); );
await change(container, 0, 'p', true); await change(container, 0, 'p', true);
await sleep(100); await sleep(100);
expect(container.querySelector('.ant-form-item-explain').textContent).toEqual('not a p'); expect(container.querySelector('.ant-form-item-explain')!.textContent).toEqual('not a p');
} }
/* eslint-enable */ /* eslint-enable */
@ -605,7 +605,7 @@ describe('Form', () => {
return <Input />; return <Input />;
}; };
const formRef = React.createRef(); const formRef = React.createRef<FormInstance>();
mount( mount(
<div> <div>
@ -620,13 +620,13 @@ describe('Form', () => {
</div>, </div>,
{ {
strictMode: false, strictMode: false,
}, } as any,
); );
expect(shouldNotRender).toHaveBeenCalledTimes(1); expect(shouldNotRender).toHaveBeenCalledTimes(1);
expect(shouldRender).toHaveBeenCalledTimes(1); expect(shouldRender).toHaveBeenCalledTimes(1);
formRef.current.setFieldsValue({ light: 'bamboo' }); formRef.current!.setFieldsValue({ light: 'bamboo' });
await Promise.resolve(); await Promise.resolve();
expect(shouldNotRender).toHaveBeenCalledTimes(1); expect(shouldNotRender).toHaveBeenCalledTimes(1);
expect(shouldRender).toHaveBeenCalledTimes(2); expect(shouldRender).toHaveBeenCalledTimes(2);
@ -659,7 +659,7 @@ describe('Form', () => {
await change(container, 0, '', true); await change(container, 0, '', true);
expect(container.querySelector('.ant-form-item')).toHaveClass('ant-form-item-has-error'); expect(container.querySelector('.ant-form-item')).toHaveClass('ant-form-item-has-error');
expect(container.querySelector('.ant-form-item-explain').textContent).toEqual('help'); expect(container.querySelector('.ant-form-item-explain')!.textContent).toEqual('help');
jest.useRealTimers(); jest.useRealTimers();
}); });
@ -710,7 +710,7 @@ describe('Form', () => {
it('`null` triggers warning and is treated as `undefined`', () => { it('`null` triggers warning and is treated as `undefined`', () => {
const wrapper = mount( const wrapper = mount(
<Form.Item name={null}> <Form.Item name={null!}>
<input /> <input />
</Form.Item>, </Form.Item>,
); );
@ -747,7 +747,7 @@ describe('Form', () => {
it('change `help` should not warning', () => { it('change `help` should not warning', () => {
const Demo = () => { const Demo = () => {
const [error, setError] = React.useState(null); const [error, setError] = React.useState<boolean | null>(null);
return ( return (
<Form> <Form>
@ -770,7 +770,7 @@ describe('Form', () => {
}; };
const { container } = render(<Demo />); const { container } = render(<Demo />);
fireEvent.click(container.querySelector('button')); fireEvent.click(container.querySelector('button')!);
expect(errorSpy).not.toHaveBeenCalled(); expect(errorSpy).not.toHaveBeenCalled();
}); });
@ -794,7 +794,9 @@ describe('Form', () => {
// https://github.com/ant-design/ant-design/issues/33691 // https://github.com/ant-design/ant-design/issues/33691
it('should keep upper locale in nested ConfigProvider', async () => { it('should keep upper locale in nested ConfigProvider', async () => {
const wrapper = mount( jest.useFakeTimers();
const { container } = render(
<ConfigProvider locale={zhCN}> <ConfigProvider locale={zhCN}>
<ConfigProvider> <ConfigProvider>
<Form> <Form>
@ -806,11 +808,21 @@ describe('Form', () => {
</ConfigProvider>, </ConfigProvider>,
); );
wrapper.find('form').simulate('submit'); fireEvent.submit(container.querySelector('form')!);
await sleep(100);
wrapper.update(); // Repeat enough time for validator promise sequence
await sleep(100); for (let i = 0; i < 20; i += 1) {
expect(wrapper.find('.ant-form-item-explain').first().text()).toEqual('请输入Bamboo'); // eslint-disable-next-line no-await-in-loop
await act(async () => {
await Promise.resolve();
jest.advanceTimersByTime(1000);
});
}
expect(container.querySelector('.ant-form-item-explain')?.textContent).toEqual('请输入Bamboo');
jest.clearAllTimers();
jest.useRealTimers();
}); });
it('`name` support template when label is not provided', async () => { it('`name` support template when label is not provided', async () => {
@ -886,7 +898,7 @@ describe('Form', () => {
const wrapper = mount(<App />, { const wrapper = mount(<App />, {
strictMode: false, strictMode: false,
}); } as any);
for (let i = 0; i < 5; i += 1) { for (let i = 0; i < 5; i += 1) {
wrapper.find('button').simulate('click'); wrapper.find('button').simulate('click');
} }
@ -911,7 +923,7 @@ describe('Form', () => {
const wrapper = mount(<Demo />, { const wrapper = mount(<Demo />, {
strictMode: false, strictMode: false,
}); } as any);
renderTimes = 0; renderTimes = 0;
wrapper.find('input').simulate('change', { wrapper.find('input').simulate('change', {
@ -941,7 +953,7 @@ describe('Form', () => {
}); });
it('Remove Field should also reset error', async () => { it('Remove Field should also reset error', async () => {
const Demo = ({ showA }) => ( const Demo = ({ showA }: { showA: boolean }) => (
<Form> <Form>
{showA ? ( {showA ? (
<Form.Item name="a" help="error"> <Form.Item name="a" help="error">
@ -968,7 +980,7 @@ describe('Form', () => {
it('no warning of initialValue & getValueProps & preserve', () => { it('no warning of initialValue & getValueProps & preserve', () => {
render( render(
<Form> <Form>
<Form.Item initialValue="bamboo" getValueProps={() => null} preserve={false}> <Form.Item initialValue="bamboo" getValueProps={(() => null) as any} preserve={false}>
<Input /> <Input />
</Form.Item> </Form.Item>
</Form>, </Form>,
@ -1117,15 +1129,17 @@ describe('Form', () => {
<Form> <Form>
<Form.Item <Form.Item
name="light" name="light"
_internalItemRender={{ {...{
mark: 'pro_table_render', _internalItemRender: {
render: (_, doms) => ( mark: 'pro_table_render',
<div id="_test"> render: (_: any, doms: any) => (
{doms.input} <div id="_test">
{doms.errorList} {doms.input}
{doms.extra} {doms.errorList}
</div> {doms.extra}
), </div>
),
},
}} }}
> >
<input defaultValue="should warning" /> <input defaultValue="should warning" />
@ -1173,7 +1187,7 @@ describe('Form', () => {
const wrapper = mount(<Demo />, { attachTo: document.body }); const wrapper = mount(<Demo />, { attachTo: document.body });
expect(mockFn).toHaveBeenCalled(); expect(mockFn).toHaveBeenCalled();
expect(Util.getFieldId()).toBe(itemName); expect((Util as any).getFieldId()).toBe(itemName); // Mock here
// make sure input id is parentNode // make sure input id is parentNode
expect(wrapper.find(`#${itemName}`).exists()).toBeTruthy(); expect(wrapper.find(`#${itemName}`).exists()).toBeTruthy();
@ -1244,7 +1258,7 @@ describe('Form', () => {
it('not warning when remove on validate', async () => { it('not warning when remove on validate', async () => {
jest.useFakeTimers(); jest.useFakeTimers();
let rejectFn = null; let rejectFn: Function = null!;
const { container, unmount } = render( const { container, unmount } = render(
<Form> <Form>
@ -1381,7 +1395,7 @@ describe('Form', () => {
it('should not affect Popup children style', () => { it('should not affect Popup children style', () => {
const Demo = () => ( const Demo = () => (
<Form> <Form>
<Form.Item labelCol={4} validateStatus="error"> <Form.Item validateStatus="error">
<Modal open> <Modal open>
<Select className="modal-select" /> <Select className="modal-select" />
</Modal> </Modal>
@ -1405,7 +1419,7 @@ describe('Form', () => {
Item: { useStatus }, Item: { useStatus },
} = Form; } = Form;
const CustomInput = ({ className, value }) => { const CustomInput = ({ className, value }: { className: string; value?: React.ReactNode }) => {
const { status } = useStatus(); const { status } = useStatus();
return <div className={classNames(className, `custom-input-status-${status}`)}>{value}</div>; return <div className={classNames(className, `custom-input-status-${status}`)}>{value}</div>;
}; };
@ -1447,7 +1461,7 @@ describe('Form', () => {
expect(errorSpy).toHaveBeenCalledWith( expect(errorSpy).toHaveBeenCalledWith(
expect.stringContaining('Form.Item.useStatus should be used under Form.Item component.'), expect.stringContaining('Form.Item.useStatus should be used under Form.Item component.'),
); );
fireEvent.click(container.querySelector('.submit-button')); fireEvent.click(container.querySelector('.submit-button')!);
await sleep(0); await sleep(0);
expect(container.querySelector('.custom-input-required')?.classList).toContain( expect(container.querySelector('.custom-input-required')?.classList).toContain(
'custom-input-status-error', 'custom-input-status-error',
@ -1455,9 +1469,12 @@ describe('Form', () => {
}); });
it('item customize margin', async () => { it('item customize margin', async () => {
const computeSpy = jest.spyOn(window, 'getComputedStyle').mockImplementation(() => ({ const computeSpy = jest.spyOn(window, 'getComputedStyle').mockImplementation(
marginBottom: 24, () =>
})); ({
marginBottom: 24,
} as any),
);
const { container } = render( const { container } = render(
<Form> <Form>
@ -1467,7 +1484,7 @@ describe('Form', () => {
</Form>, </Form>,
); );
fireEvent.change(container.querySelector('input'), { fireEvent.change(container.querySelector('input')!, {
target: { target: {
value: '', value: '',
}, },

View File

@ -31,7 +31,7 @@ const localeValues: Locale = {
searchPlaceholder: 'Procurar...', searchPlaceholder: 'Procurar...',
itemUnit: 'item', itemUnit: 'item',
itemsUnit: 'itens', itemsUnit: 'itens',
selectAll: 'Seleccionar Tudo', selectAll: 'Selecionar tudo',
selectInvert: 'Inverter a página actual', selectInvert: 'Inverter a página actual',
}, },
Upload: { Upload: {

View File

@ -109,9 +109,9 @@ Before `3.4.0`: The number of treeNodes can be very large, but when `checkable=t
File icon realize by using switcherIcon. You can overwrite the style to hide it: <https://codesandbox.io/s/883vo47xp8> File icon realize by using switcherIcon. You can overwrite the style to hide it: <https://codesandbox.io/s/883vo47xp8>
### Why defaultExpandedAll not working on ajax data? ### Why defaultExpandAll not working on ajax data?
`default` prefix prop only works when inited. So `defaultExpandedAll` has already executed when ajax load data. You can control `expandedKeys` or render Tree when data loaded to realize expanded all. `default` prefix prop only works when inited. So `defaultExpandAll` has already executed when ajax load data. You can control `expandedKeys` or render Tree when data loaded to realize expanded all.
### Virtual scroll limitation ### Virtual scroll limitation

View File

@ -110,9 +110,9 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Xh-oWqg9k/Tree.svg
文件图标通过 switcherIcon 来实现,如果不需要你可以覆盖对应的样式:<https://codesandbox.io/s/883vo47xp8> 文件图标通过 switcherIcon 来实现,如果不需要你可以覆盖对应的样式:<https://codesandbox.io/s/883vo47xp8>
### defaultExpandedAll 在异步加载数据时为何不生效? ### defaultExpandAll 在异步加载数据时为何不生效?
`default` 前缀属性只有在初始化时生效,因而异步加载数据时 `defaultExpandedAll` 已经执行完成。你可以通过受控 `expandedKeys` 或者在数据加载完成后渲染 Tree 来实现全部展开。 `default` 前缀属性只有在初始化时生效,因而异步加载数据时 `defaultExpandAll` 已经执行完成。你可以通过受控 `expandedKeys` 或者在数据加载完成后渲染 Tree 来实现全部展开。
### 虚拟滚动的限制 ### 虚拟滚动的限制

View File

@ -58,7 +58,7 @@ export const isImageUrl = (file: UploadFile): boolean => {
const extension = extname(url); const extension = extname(url);
if ( if (
/^data:image\//.test(url) || /^data:image\//.test(url) ||
/(webp|svg|png|gif|jpg|jpeg|jfif|bmp|dpg|ico)$/i.test(extension) /(webp|svg|png|gif|jpg|jpeg|jfif|bmp|dpg|ico|heic|heif)$/i.test(extension)
) { ) {
return true; return true;
} }

View File

@ -29,7 +29,7 @@ title: Third-Party Libraries
| Infinite Scroll | [rc-virtual-list](https://github.com/react-component/virtual-list/) [react-infinite-scroll-component](https://github.com/ankeetmaini/react-infinite-scroll-component) | | Infinite Scroll | [rc-virtual-list](https://github.com/react-component/virtual-list/) [react-infinite-scroll-component](https://github.com/ankeetmaini/react-infinite-scroll-component) |
| Map | [react-google-maps](https://github.com/tomchentw/react-google-maps) [google-map-react](https://github.com/istarkov/google-map-react) [react-amap](https://github.com/ElemeFE/react-amap) | | Map | [react-google-maps](https://github.com/tomchentw/react-google-maps) [google-map-react](https://github.com/istarkov/google-map-react) [react-amap](https://github.com/ElemeFE/react-amap) |
| Video | [react-player](https://github.com/CookPete/react-player) [video-react](https://github.com/video-react/video-react) [video.js](http://docs.videojs.com/tutorial-react.html) | | Video | [react-player](https://github.com/CookPete/react-player) [video-react](https://github.com/video-react/video-react) [video.js](http://docs.videojs.com/tutorial-react.html) |
| Context Menu | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) | | Context Menu | [react-contexify](https://github.com/fkhadra/react-contexify) |
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) | | Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
| Split View | [react-split-pane](https://github.com/tomkp/react-split-pane) | | Split View | [react-split-pane](https://github.com/tomkp/react-split-pane) |
| Image Crop | [antd-img-crop](https://github.com/nanxiaobei/antd-img-crop) [react-image-crop](https://github.com/DominicTobias/react-image-crop) | | Image Crop | [antd-img-crop](https://github.com/nanxiaobei/antd-img-crop) [react-image-crop](https://github.com/DominicTobias/react-image-crop) |

View File

@ -29,7 +29,7 @@ title: 社区精选组件
| 无限滚动 | [rc-virtual-list](https://github.com/react-component/virtual-list/) [react-infinite-scroll-component](https://github.com/ankeetmaini/react-infinite-scroll-component) | | 无限滚动 | [rc-virtual-list](https://github.com/react-component/virtual-list/) [react-infinite-scroll-component](https://github.com/ankeetmaini/react-infinite-scroll-component) |
| 地图 | [react-google-maps](https://github.com/tomchentw/react-google-maps) [google-map-react](https://github.com/istarkov/google-map-react) [react-amap 高德](https://github.com/ElemeFE/react-amap) | | 地图 | [react-google-maps](https://github.com/tomchentw/react-google-maps) [google-map-react](https://github.com/istarkov/google-map-react) [react-amap 高德](https://github.com/ElemeFE/react-amap) |
| 视频播放 | [react-player](https://github.com/CookPete/react-player) [video-react](https://github.com/video-react/video-react) [video.js](http://docs.videojs.com/tutorial-react.html) | | 视频播放 | [react-player](https://github.com/CookPete/react-player) [video-react](https://github.com/video-react/video-react) [video.js](http://docs.videojs.com/tutorial-react.html) |
| 右键菜单 | [react-contextmenu](https://github.com/vkbansal/react-contextmenu/) [react-contexify](https://github.com/fkhadra/react-contexify) | | 右键菜单 | [react-contexify](https://github.com/fkhadra/react-contexify) |
| Emoji | [emoji-mart](https://github.com/missive/emoji-mart) | | Emoji | [emoji-mart](https://github.com/missive/emoji-mart) |
| 分割面板 | [react-split-pane](https://github.com/tomkp/react-split-pane) | | 分割面板 | [react-split-pane](https://github.com/tomkp/react-split-pane) |
| 图片裁切 | [antd-img-crop](https://github.com/nanxiaobei/antd-img-crop) [react-image-crop](https://github.com/DominicTobias/react-image-crop) | | 图片裁切 | [antd-img-crop](https://github.com/nanxiaobei/antd-img-crop) [react-image-crop](https://github.com/DominicTobias/react-image-crop) |