mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 02:59:58 +08:00
commit
5d37e6264d
@ -3,7 +3,7 @@ import type { InternalAffixClass } from '..';
|
|||||||
import Affix from '..';
|
import Affix from '..';
|
||||||
import accessibilityTest from '../../../tests/shared/accessibilityTest';
|
import accessibilityTest from '../../../tests/shared/accessibilityTest';
|
||||||
import rtlTest from '../../../tests/shared/rtlTest';
|
import rtlTest from '../../../tests/shared/rtlTest';
|
||||||
import { render, sleep, triggerResize } from '../../../tests/utils';
|
import { render, sleep, triggerResize, waitFakeTimer } from '../../../tests/utils';
|
||||||
import Button from '../../button';
|
import Button from '../../button';
|
||||||
import { getObserverEntities } from '../utils';
|
import { getObserverEntities } from '../utils';
|
||||||
|
|
||||||
@ -216,22 +216,31 @@ describe('Affix Render', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Trigger inner and outer element for the two <ResizeObserver>s.
|
// Trigger inner and outer element for the two <ResizeObserver>s.
|
||||||
it.each([
|
[
|
||||||
{ selector: '.ant-btn' }, // inner
|
'.ant-btn', // inner
|
||||||
{ selector: '.fixed' }, // outer
|
'.fixed', // outer
|
||||||
])('trigger listener when size change', async ({ selector }) => {
|
].forEach(selector => {
|
||||||
const updateCalled = jest.fn();
|
it(`trigger listener when size change: ${selector}`, async () => {
|
||||||
const { container } = render(
|
jest.useFakeTimers();
|
||||||
<AffixMounter offsetBottom={0} onTestUpdatePosition={updateCalled} />,
|
|
||||||
{
|
|
||||||
container: document.getElementById('mounter')!,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
updateCalled.mockReset();
|
const updateCalled = jest.fn();
|
||||||
triggerResize(container.querySelector(selector)!);
|
const { container } = render(
|
||||||
await sleep(20);
|
<AffixMounter offsetBottom={0} onTestUpdatePosition={updateCalled} />,
|
||||||
expect(updateCalled).toHaveBeenCalled();
|
{
|
||||||
|
container: document.getElementById('mounter')!,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
updateCalled.mockReset();
|
||||||
|
triggerResize(container.querySelector(selector)!);
|
||||||
|
|
||||||
|
await waitFakeTimer();
|
||||||
|
|
||||||
|
expect(updateCalled).toHaveBeenCalled();
|
||||||
|
|
||||||
|
jest.clearAllTimers();
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
import Divider from '..';
|
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
|
||||||
|
|
||||||
describe('Divider', () => {
|
|
||||||
mountTest(Divider);
|
|
||||||
});
|
|
17
components/divider/__tests__/index.test.tsx
Normal file
17
components/divider/__tests__/index.test.tsx
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
@ -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>
|
||||||
|
@ -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, waitFakeTimer } 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,15 @@ 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);
|
await waitFakeTimer();
|
||||||
expect(wrapper.find('.ant-form-item-explain').first().text()).toEqual('请输入Bamboo');
|
|
||||||
|
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 +892,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 +917,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 +947,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 +974,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 +1123,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 +1181,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 +1252,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 +1389,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>
|
||||||
@ -1401,11 +1409,13 @@ describe('Form', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Form.Item.useStatus should work', async () => {
|
it('Form.Item.useStatus should work', async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
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,17 +1457,25 @@ 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'));
|
|
||||||
await sleep(0);
|
fireEvent.click(container.querySelector('.submit-button')!);
|
||||||
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(container.querySelector('.custom-input-required')?.classList).toContain(
|
expect(container.querySelector('.custom-input-required')?.classList).toContain(
|
||||||
'custom-input-status-error',
|
'custom-input-status-error',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
jest.clearAllTimers();
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
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 +1485,7 @@ describe('Form', () => {
|
|||||||
</Form>,
|
</Form>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fireEvent.change(container.querySelector('input'), {
|
fireEvent.change(container.querySelector('input')!, {
|
||||||
target: {
|
target: {
|
||||||
value: '',
|
value: '',
|
||||||
},
|
},
|
@ -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: {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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 来实现全部展开。
|
||||||
|
|
||||||
### 虚拟滚动的限制
|
### 虚拟滚动的限制
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) |
|
||||||
|
@ -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) |
|
||||||
|
@ -64,3 +64,20 @@ export const triggerResize = (target: Element) => {
|
|||||||
|
|
||||||
target.getBoundingClientRect = originGetBoundingClientRect;
|
target.getBoundingClientRect = originGetBoundingClientRect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export async function waitFakeTimer(advanceTime = 1000) {
|
||||||
|
for (let i = 0; i < 20; i += 1) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await act(async () => {
|
||||||
|
await Promise.resolve();
|
||||||
|
|
||||||
|
if (advanceTime > 0) {
|
||||||
|
jest.advanceTimersByTime(advanceTime);
|
||||||
|
} else {
|
||||||
|
jest.runAllTimers();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from '@testing-library/react';
|
||||||
|
Loading…
Reference in New Issue
Block a user