mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
chore: merge master
This commit is contained in:
commit
eda63041ff
2
.github/workflows/preview-build.yml
vendored
2
.github/workflows/preview-build.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only --ignore-scripts --legacy-peer-deps
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
- name: hack for single file
|
||||
run: |
|
||||
|
2
.github/workflows/site-deploy.yml
vendored
2
.github/workflows/site-deploy.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only --ignore-scripts --legacy-peer-deps
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
- name: hack for single file
|
||||
run: |
|
||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
||||
key: lock-${{ github.sha }}
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only --ignore-scripts --legacy-peer-deps
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
- name: hack for single file
|
||||
run: |
|
||||
|
2
.github/workflows/ui.yml
vendored
2
.github/workflows/ui.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
node-version: '16'
|
||||
|
||||
- name: create package-lock.json
|
||||
run: npm i --package-lock-only --ignore-scripts --legacy-peer-deps
|
||||
run: npm i --package-lock-only --ignore-scripts
|
||||
|
||||
- name: hack for single file
|
||||
run: |
|
||||
|
@ -1323,89 +1323,38 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/loop-banner.md extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-banner"
|
||||
data-show="true"
|
||||
role="alert"
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-banner"
|
||||
data-show="true"
|
||||
role="alert"
|
||||
>
|
||||
<span
|
||||
aria-label="exclamation-circle"
|
||||
class="anticon anticon-exclamation-circle ant-alert-icon"
|
||||
role="img"
|
||||
>
|
||||
<span
|
||||
aria-label="exclamation-circle"
|
||||
class="anticon anticon-exclamation-circle ant-alert-icon"
|
||||
role="img"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="exclamation-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="exclamation-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<div
|
||||
class="ant-alert-content"
|
||||
>
|
||||
<div
|
||||
class="ant-alert-message"
|
||||
>
|
||||
<div
|
||||
class="x0 x1 x2 x3 "
|
||||
>
|
||||
<div
|
||||
style="transition:width 150ms linear;height:auto;width:auto"
|
||||
>
|
||||
<div
|
||||
class="x1 x4 x5 x6"
|
||||
style="opacity:1;transform:translateY(0px);position:relative"
|
||||
>
|
||||
<div>
|
||||
Notice message one
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-banner"
|
||||
data-show="true"
|
||||
role="alert"
|
||||
>
|
||||
<span
|
||||
aria-label="exclamation-circle"
|
||||
class="anticon anticon-exclamation-circle ant-alert-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="exclamation-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<div
|
||||
class="ant-alert-content"
|
||||
>
|
||||
<div
|
||||
class="ant-alert-message"
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
</svg>
|
||||
</span>
|
||||
<div
|
||||
class="ant-alert-content"
|
||||
>
|
||||
<div
|
||||
class="ant-alert-message"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/smooth-closed.md extend context correctly 1`] = `
|
||||
|
@ -1323,89 +1323,38 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/loop-banner.md correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-banner"
|
||||
data-show="true"
|
||||
role="alert"
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-banner"
|
||||
data-show="true"
|
||||
role="alert"
|
||||
>
|
||||
<span
|
||||
aria-label="exclamation-circle"
|
||||
class="anticon anticon-exclamation-circle ant-alert-icon"
|
||||
role="img"
|
||||
>
|
||||
<span
|
||||
aria-label="exclamation-circle"
|
||||
class="anticon anticon-exclamation-circle ant-alert-icon"
|
||||
role="img"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="exclamation-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="exclamation-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<div
|
||||
class="ant-alert-content"
|
||||
>
|
||||
<div
|
||||
class="ant-alert-message"
|
||||
>
|
||||
<div
|
||||
class="x0 x1 x2 x3 "
|
||||
>
|
||||
<div
|
||||
style="transition:width 150ms linear;height:auto;width:auto"
|
||||
>
|
||||
<div
|
||||
class="x1 x4 x5 x6"
|
||||
style="opacity:1;transform:translateY(0px);position:relative"
|
||||
>
|
||||
<div>
|
||||
Notice message one
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-banner"
|
||||
data-show="true"
|
||||
role="alert"
|
||||
>
|
||||
<span
|
||||
aria-label="exclamation-circle"
|
||||
class="anticon anticon-exclamation-circle ant-alert-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="exclamation-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<div
|
||||
class="ant-alert-content"
|
||||
>
|
||||
<div
|
||||
class="ant-alert-message"
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
</svg>
|
||||
</span>
|
||||
<div
|
||||
class="ant-alert-content"
|
||||
>
|
||||
<div
|
||||
class="ant-alert-message"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/smooth-closed.md correctly 1`] = `
|
||||
|
@ -17,30 +17,16 @@ Show a loop banner by using with [react-text-loop-next](https://npmjs.com/packag
|
||||
import { Alert } from 'antd';
|
||||
import React from 'react';
|
||||
import Marquee from 'react-fast-marquee';
|
||||
import { TextLoop } from 'react-text-loop-next';
|
||||
|
||||
const App: React.FC = () => (
|
||||
<>
|
||||
<Alert
|
||||
banner
|
||||
message={
|
||||
<TextLoop mask>
|
||||
<div>Notice message one</div>
|
||||
<div>Notice message two</div>
|
||||
<div>Notice message three</div>
|
||||
<div>Notice message four</div>
|
||||
</TextLoop>
|
||||
}
|
||||
/>
|
||||
<Alert
|
||||
banner
|
||||
message={
|
||||
<Marquee pauseOnHover gradient={false}>
|
||||
I can be a React component, multiple React components, or just some text.
|
||||
</Marquee>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
<Alert
|
||||
banner
|
||||
message={
|
||||
<Marquee pauseOnHover gradient={false}>
|
||||
I can be a React component, multiple React components, or just some text.
|
||||
</Marquee>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
export default App;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import AutoComplete from '..';
|
||||
import { render } from '../../../tests/utils';
|
||||
|
||||
describe('AutoComplete children could be focus', () => {
|
||||
beforeAll(() => {
|
||||
@ -23,25 +23,35 @@ describe('AutoComplete children could be focus', () => {
|
||||
|
||||
it('focus() and onFocus', () => {
|
||||
const handleFocus = jest.fn();
|
||||
const wrapper = mount(<AutoComplete onFocus={handleFocus} />, { attachTo: container });
|
||||
wrapper.find('input').instance().focus();
|
||||
jest.runAllTimers();
|
||||
const { container: wrapper } = render(<AutoComplete onFocus={handleFocus} />, {
|
||||
attachTo: container,
|
||||
});
|
||||
wrapper.querySelector('input').focus();
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(handleFocus).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('blur() and onBlur', () => {
|
||||
const handleBlur = jest.fn();
|
||||
const wrapper = mount(<AutoComplete onBlur={handleBlur} />, { attachTo: container });
|
||||
wrapper.find('input').instance().focus();
|
||||
jest.runAllTimers();
|
||||
wrapper.find('input').instance().blur();
|
||||
jest.runAllTimers();
|
||||
const { container: wrapper } = render(<AutoComplete onBlur={handleBlur} />, {
|
||||
attachTo: container,
|
||||
});
|
||||
wrapper.querySelector('input').focus();
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
wrapper.querySelector('input').blur();
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
expect(handleBlur).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('child.ref should work', () => {
|
||||
const mockRef = jest.fn();
|
||||
mount(
|
||||
render(
|
||||
<AutoComplete dataSource={[]}>
|
||||
<input ref={mockRef} />
|
||||
</AutoComplete>,
|
||||
@ -51,7 +61,7 @@ describe('AutoComplete children could be focus', () => {
|
||||
|
||||
it('child.ref instance should support be focused and blured', () => {
|
||||
let inputRef;
|
||||
mount(
|
||||
render(
|
||||
<AutoComplete dataSource={[]}>
|
||||
<input
|
||||
ref={node => {
|
||||
|
@ -1,30 +1,29 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import AutoComplete from '..';
|
||||
import Input from '../../input';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import Input from '../../input';
|
||||
|
||||
describe('AutoComplete', () => {
|
||||
mountTest(AutoComplete);
|
||||
rtlTest(AutoComplete);
|
||||
|
||||
it('AutoComplete with custom Input render perfectly', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<AutoComplete dataSource={['12345', '23456', '34567']}>
|
||||
<textarea />
|
||||
</AutoComplete>,
|
||||
);
|
||||
|
||||
expect(wrapper.find('textarea').length).toBe(1);
|
||||
wrapper.find('textarea').simulate('change', { target: { value: '123' } });
|
||||
expect(container.querySelectorAll('textarea').length).toBe(1);
|
||||
fireEvent.change(container.querySelector('textarea'), { target: { value: '123' } });
|
||||
|
||||
// should not filter data source defaultly
|
||||
expect(wrapper.find('.ant-select-item-option').length).toBe(3);
|
||||
expect(container.querySelectorAll('.ant-select-item-option').length).toBe(3);
|
||||
});
|
||||
|
||||
it('AutoComplete should work when dataSource is object array', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<AutoComplete
|
||||
dataSource={[
|
||||
{ text: 'text', value: 'value' },
|
||||
@ -34,17 +33,17 @@ describe('AutoComplete', () => {
|
||||
<input />
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(wrapper.find('input').length).toBe(1);
|
||||
wrapper.find('input').simulate('change', { target: { value: 'a' } });
|
||||
expect(container.querySelectorAll('input').length).toBe(1);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: 'a' } });
|
||||
|
||||
// should not filter data source defaultly
|
||||
expect(wrapper.find('.ant-select-item-option').length).toBe(2);
|
||||
expect(container.querySelectorAll('.ant-select-item-option').length).toBe(2);
|
||||
});
|
||||
|
||||
it('AutoComplete throws error when contains invalid dataSource', () => {
|
||||
const spy = jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||
|
||||
mount(
|
||||
render(
|
||||
<AutoComplete dataSource={[() => {}]}>
|
||||
<textarea />
|
||||
</AutoComplete>,
|
||||
@ -54,25 +53,27 @@ describe('AutoComplete', () => {
|
||||
});
|
||||
|
||||
it('legacy dataSource should accept react element option', () => {
|
||||
const wrapper = mount(<AutoComplete open dataSource={[<span key="key">ReactNode</span>]} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
const { asFragment } = render(
|
||||
<AutoComplete open dataSource={[<span key="key">ReactNode</span>]} />,
|
||||
);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('legacy AutoComplete.Option should be compatiable', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<AutoComplete>
|
||||
<AutoComplete.Option value="111">111</AutoComplete.Option>
|
||||
<AutoComplete.Option value="222">222</AutoComplete.Option>
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(wrapper.find('input').length).toBe(1);
|
||||
wrapper.find('input').simulate('change', { target: { value: '1' } });
|
||||
expect(wrapper.find('.ant-select-item-option').length).toBe(2);
|
||||
expect(container.querySelectorAll('input').length).toBe(1);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: '1' } });
|
||||
expect(container.querySelectorAll('.ant-select-item-option').length).toBe(2);
|
||||
});
|
||||
|
||||
it('should not warning when getInputElement is null', () => {
|
||||
jest.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
mount(<AutoComplete placeholder="input here" allowClear />);
|
||||
render(<AutoComplete placeholder="input here" allowClear />);
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.warn).not.toBeCalled();
|
||||
// eslint-disable-next-line no-console
|
||||
@ -80,11 +81,11 @@ describe('AutoComplete', () => {
|
||||
});
|
||||
|
||||
it('should not override custom input className', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<AutoComplete>
|
||||
<Input className="custom" />
|
||||
</AutoComplete>,
|
||||
);
|
||||
expect(wrapper.find('input').hasClass('custom')).toBe(true);
|
||||
expect(container.querySelector('input').classList.contains('custom')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -1,16 +1,14 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
import BackTop from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import BackTop from '..';
|
||||
import { fireEvent, render, sleep } from '../../../tests/utils';
|
||||
|
||||
describe('BackTop', () => {
|
||||
mountTest(BackTop);
|
||||
rtlTest(BackTop);
|
||||
|
||||
it('should scroll to top after click it', async () => {
|
||||
const wrapper = mount(<BackTop visibilityHeight={-1} />);
|
||||
const { container } = render(<BackTop visibilityHeight={-1} />);
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
window.scrollY = y;
|
||||
window.pageYOffset = y;
|
||||
@ -18,7 +16,7 @@ describe('BackTop', () => {
|
||||
});
|
||||
window.scrollTo(0, 400);
|
||||
expect(document.documentElement.scrollTop).toBe(400);
|
||||
wrapper.find('.ant-back-top').simulate('click');
|
||||
fireEvent.click(container.querySelector('.ant-back-top'));
|
||||
await sleep(500);
|
||||
expect(document.documentElement.scrollTop).toBe(0);
|
||||
scrollToSpy.mockRestore();
|
||||
@ -26,24 +24,24 @@ describe('BackTop', () => {
|
||||
|
||||
it('support onClick', async () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = mount(<BackTop onClick={onClick} visibilityHeight={-1} />);
|
||||
const { container } = render(<BackTop onClick={onClick} visibilityHeight={-1} />);
|
||||
const scrollToSpy = jest.spyOn(window, 'scrollTo').mockImplementation((x, y) => {
|
||||
window.scrollY = y;
|
||||
window.pageYOffset = y;
|
||||
});
|
||||
document.dispatchEvent(new Event('scroll'));
|
||||
window.scrollTo(0, 400);
|
||||
wrapper.find('.ant-back-top').simulate('click');
|
||||
fireEvent.click(container.querySelector('.ant-back-top'));
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
scrollToSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('invalid target', async () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<BackTop onClick={onClick} visible target={() => ({ documentElement: {} })} />,
|
||||
);
|
||||
wrapper.find('.ant-back-top').simulate('click');
|
||||
fireEvent.click(container.querySelector('.ant-back-top'));
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
import EyeOutlined from '@ant-design/icons/EyeOutlined';
|
||||
import classNames from 'classnames';
|
||||
import RcImage, { ImageProps } from 'rc-image';
|
||||
import * as React from 'react';
|
||||
import { useContext } from 'react';
|
||||
import EyeOutlined from '@ant-design/icons/EyeOutlined';
|
||||
import RcImage, { ImageProps } from 'rc-image';
|
||||
import classNames from 'classnames';
|
||||
import defaultLocale from '../locale/en_US';
|
||||
import PreviewGroup, { icons } from './PreviewGroup';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import defaultLocale from '../locale/en_US';
|
||||
import { getTransitionName } from '../_util/motion';
|
||||
// CSSINJS
|
||||
import PreviewGroup, { icons } from './PreviewGroup';
|
||||
import useStyle from './style';
|
||||
|
||||
export interface CompositionImage<P> extends React.FC<P> {
|
||||
@ -20,11 +20,10 @@ const Image: CompositionImage<ImageProps> = ({
|
||||
rootClassName,
|
||||
...otherProps
|
||||
}) => {
|
||||
const { getPrefixCls } = useContext(ConfigContext);
|
||||
const { getPrefixCls, locale: contextLocale = defaultLocale } = useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('image', customizePrefixCls);
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
|
||||
const { locale: contextLocale = defaultLocale } = useContext(ConfigContext);
|
||||
const imageLocale = contextLocale.Image || defaultLocale.Image;
|
||||
// Style
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
@ -1,8 +1,8 @@
|
||||
import Pagination from 'rc-pagination/lib/locale/it_IT';
|
||||
import DatePicker from '../date-picker/locale/it_IT';
|
||||
import TimePicker from '../time-picker/locale/it_IT';
|
||||
import Calendar from '../calendar/locale/it_IT';
|
||||
import DatePicker from '../date-picker/locale/it_IT';
|
||||
import type { Locale } from '../locale-provider';
|
||||
import TimePicker from '../time-picker/locale/it_IT';
|
||||
|
||||
const localeValues: Locale = {
|
||||
locale: 'it',
|
||||
@ -23,8 +23,8 @@ const localeValues: Locale = {
|
||||
selectInvert: 'Inverti selezione nella pagina corrente',
|
||||
sortTitle: 'Ordina',
|
||||
triggerDesc: 'Clicca per ordinare in modo discendente',
|
||||
triggerAsc: 'Clicca per ordinare in modo ascendente',
|
||||
cancelSort: 'Clicca per eliminare i filtri',
|
||||
triggerAsc: 'Clicca per ordinare in modo ascendente',
|
||||
cancelSort: "Clicca per eliminare l'ordinamento",
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
|
@ -162,6 +162,167 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Menu all types must be available in the "items" syntax 1`] = `
|
||||
Array [
|
||||
<ul
|
||||
class="ant-menu ant-menu-root ant-menu-inline ant-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-controls="rc-menu-uuid-test-submenu-popup"
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
class="ant-menu-submenu-title"
|
||||
data-menu-id="rc-menu-uuid-test-submenu"
|
||||
role="menuitem"
|
||||
style="padding-left: 24px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
Submenu
|
||||
</span>
|
||||
<i
|
||||
class="ant-menu-submenu-arrow"
|
||||
/>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-menu ant-menu-sub ant-menu-inline"
|
||||
data-menu-list="true"
|
||||
id="rc-menu-uuid-test-submenu-popup"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-submenu-item1"
|
||||
role="menuitem"
|
||||
style="padding-left: 48px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
SubmenuItem 1
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-submenu-item2"
|
||||
role="menuitem"
|
||||
style="padding-left: 48px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
SubmenuItem 2
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-item-divider"
|
||||
/>
|
||||
<li
|
||||
class="ant-menu-item-group"
|
||||
>
|
||||
<div
|
||||
class="ant-menu-item-group-title"
|
||||
title="Group"
|
||||
>
|
||||
Group
|
||||
</div>
|
||||
<ul
|
||||
class="ant-menu-item-group-list"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-group-item"
|
||||
role="menuitem"
|
||||
style="padding-left: 24px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
GroupItem
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-item-divider"
|
||||
/>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-controls="rc-menu-uuid-test-group-submenu-popup"
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
class="ant-menu-submenu-title"
|
||||
data-menu-id="rc-menu-uuid-test-group-submenu"
|
||||
role="menuitem"
|
||||
style="padding-left: 24px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
GroupSubmenu
|
||||
</span>
|
||||
<i
|
||||
class="ant-menu-submenu-arrow"
|
||||
/>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-menu ant-menu-sub ant-menu-inline"
|
||||
data-menu-list="true"
|
||||
id="rc-menu-uuid-test-group-submenu-popup"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-group-submenu-item1"
|
||||
role="menuitem"
|
||||
style="padding-left: 48px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
GroupSubmenuItem 1
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-group-submenu-item2"
|
||||
role="menuitem"
|
||||
style="padding-left: 48px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
GroupSubmenuItem 2
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>,
|
||||
<div
|
||||
aria-hidden="true"
|
||||
style="display: none;"
|
||||
/>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Menu rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
Array [
|
||||
<ul
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React, { useState } from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import {
|
||||
MailOutlined,
|
||||
InboxOutlined,
|
||||
AppstoreOutlined,
|
||||
InboxOutlined,
|
||||
MailOutlined,
|
||||
PieChartOutlined,
|
||||
UserOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { mount } from 'enzyme';
|
||||
import React, { useState } from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import Menu from '..';
|
||||
import Layout from '../../layout';
|
||||
import Tooltip from '../../tooltip';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import Layout from '../../layout';
|
||||
import Tooltip from '../../tooltip';
|
||||
import collapseMotion from '../../_util/motion';
|
||||
import { noop } from '../../_util/warning';
|
||||
|
||||
@ -960,4 +960,46 @@ describe('Menu', () => {
|
||||
|
||||
expect(wrapper.exists('.bamboo')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('all types must be available in the "items" syntax', () => {
|
||||
const wrapper = mount(
|
||||
<Menu
|
||||
mode="inline"
|
||||
defaultOpenKeys={['submenu', 'group-submenu']}
|
||||
items={[
|
||||
{
|
||||
key: 'submenu',
|
||||
label: 'Submenu',
|
||||
children: [
|
||||
{ key: 'submenu-item1', label: 'SubmenuItem 1' },
|
||||
{ key: 'submenu-item2', label: 'SubmenuItem 2' },
|
||||
],
|
||||
},
|
||||
{ key: 'divider', type: 'divider' },
|
||||
{
|
||||
key: 'group',
|
||||
type: 'group',
|
||||
label: 'Group',
|
||||
children: [
|
||||
{
|
||||
key: 'group-item',
|
||||
label: 'GroupItem',
|
||||
},
|
||||
{ key: 'group-divider', type: 'divider' },
|
||||
{
|
||||
key: 'group-submenu',
|
||||
label: 'GroupSubmenu',
|
||||
children: [
|
||||
{ key: 'group-submenu-item1', label: 'GroupSubmenuItem 1' },
|
||||
{ key: 'group-submenu-item2', label: 'GroupSubmenuItem 2' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
39
components/menu/__tests__/type.test.tsx
Normal file
39
components/menu/__tests__/type.test.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import Menu from '..';
|
||||
|
||||
describe('Menu.typescript', () => {
|
||||
it('Menu.items', () => {
|
||||
const menu = (
|
||||
<Menu
|
||||
items={[
|
||||
{ key: 'item', title: 'Item' },
|
||||
{
|
||||
key: 'submenu',
|
||||
theme: 'light',
|
||||
children: [
|
||||
{ key: 'submenu-item', title: 'SubmenuItem' },
|
||||
{ key: 'submenu-submenu', theme: 'light', children: [] },
|
||||
{ key: 'submenu-divider', type: 'divider' },
|
||||
{ key: 'submenu-group', type: 'group' },
|
||||
null,
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'group',
|
||||
type: 'group',
|
||||
children: [
|
||||
{ key: 'group-item', label: 'GroupItem' },
|
||||
{ key: 'group-submenu', theme: 'light', children: [] },
|
||||
{ key: 'group-divider', type: 'divider' },
|
||||
{ key: 'group-group', type: 'group' },
|
||||
null,
|
||||
],
|
||||
},
|
||||
{ key: 'divider', type: 'divider' },
|
||||
null,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(menu).toBeTruthy();
|
||||
});
|
||||
});
|
@ -1,14 +1,14 @@
|
||||
import * as React from 'react';
|
||||
import { ItemGroup } from 'rc-menu';
|
||||
import type {
|
||||
MenuItemType as RcMenuItemType,
|
||||
MenuDividerType as RcMenuDividerType,
|
||||
SubMenuType as RcSubMenuType,
|
||||
MenuItemGroupType as RcMenuItemGroupType,
|
||||
MenuItemType as RcMenuItemType,
|
||||
SubMenuType as RcSubMenuType,
|
||||
} from 'rc-menu/lib/interface';
|
||||
import SubMenu from '../SubMenu';
|
||||
import * as React from 'react';
|
||||
import MenuDivider from '../MenuDivider';
|
||||
import MenuItem from '../MenuItem';
|
||||
import SubMenu from '../SubMenu';
|
||||
|
||||
interface MenuItemType extends RcMenuItemType {
|
||||
danger?: boolean;
|
||||
@ -23,7 +23,7 @@ interface SubMenuType extends Omit<RcSubMenuType, 'children'> {
|
||||
}
|
||||
|
||||
interface MenuItemGroupType extends Omit<RcMenuItemGroupType, 'children'> {
|
||||
children?: MenuItemType[];
|
||||
children?: ItemType[];
|
||||
key?: React.Key;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,6 @@ Segmented Controls. This component is available since `antd@4.20.0`.
|
||||
| defaultValue | Default selected value | string \| number | | |
|
||||
| disabled | Disable all segments | boolean | false | |
|
||||
| onChange | The callback function that is triggered when the state changes | function(value: string \| number) | | |
|
||||
| options | Set children optional | string\[] \| number\[] \| Array<{ label: string value: string icon? ReactNode disabled?: boolean className?: string }> | [] | |
|
||||
| options | Set children optional | string\[] \| number\[] \| Array<{ label: ReactNode value: string icon? ReactNode disabled?: boolean className?: string }> | [] | |
|
||||
| size | The size of the Segmented. | `large` \| `middle` \| `small` | - | |
|
||||
| value | Currently selected value | string \| number | | |
|
||||
|
@ -25,6 +25,6 @@ cover: https://gw.alipayobjects.com/zos/bmw-prod/a3ff040f-24ba-43e0-92e9-c845df1
|
||||
| defaultValue | 默认选中的值 | string \| number | | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| onChange | 选项变化时的回调函数 | function(value: string \| number) | | |
|
||||
| options | 数据化配置选项内容 | string\[] \| number\[] \| Array<{ label: string value: string icon? ReactNode disabled?: boolean className?: string }> | [] | |
|
||||
| options | 数据化配置选项内容 | string\[] \| number\[] \| Array<{ label: ReactNode value: string icon? ReactNode disabled?: boolean className?: string }> | [] | |
|
||||
| size | 控件尺寸 | `large` \| `middle` \| `small` | - | |
|
||||
| value | 当前选中的值 | string \| number | | |
|
||||
|
@ -31,6 +31,10 @@
|
||||
return Math.round(hue);
|
||||
};
|
||||
var getSaturation = function(hsv, i, isLight) {
|
||||
// grey color don't change saturation
|
||||
if (hsv.h === 0 && hsv.s === 0) {
|
||||
return hsv.s;
|
||||
}
|
||||
var saturation;
|
||||
if (isLight) {
|
||||
saturation = hsv.s - saturationStep * i;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { SmileOutlined, LikeOutlined } from '@ant-design/icons';
|
||||
import { LikeOutlined, SmileOutlined } from '@ant-design/icons';
|
||||
import * as copyObj from 'copy-to-clipboard';
|
||||
import React from 'react';
|
||||
import { fireEvent, render, waitFor } from '../../../tests/utils';
|
||||
|
||||
import Base from '../Base';
|
||||
|
||||
@ -33,57 +33,69 @@ describe('Typography copy', () => {
|
||||
}) {
|
||||
it(name, async () => {
|
||||
jest.useFakeTimers();
|
||||
const wrapper = mount(
|
||||
const { container: wrapper, unmount } = render(
|
||||
<Base component="p" copyable={{ icon, tooltips }}>
|
||||
test copy
|
||||
</Base>,
|
||||
);
|
||||
if (iconClassNames[0] !== undefined) {
|
||||
expect(wrapper.exists(iconClassNames[0])).toBeTruthy();
|
||||
expect(wrapper.querySelector(iconClassNames[0])).not.toBeNull();
|
||||
}
|
||||
if (iconTexts[0] !== undefined) {
|
||||
expect(wrapper.find('.ant-typography-copy').at(0).text()).toBe(iconTexts[0]);
|
||||
expect(wrapper.querySelectorAll('.ant-typography-copy')[0].textContent).toBe(
|
||||
iconTexts[0],
|
||||
);
|
||||
}
|
||||
|
||||
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
|
||||
fireEvent.mouseEnter(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
if (tooltipTexts[0] !== undefined) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltipTexts[0]);
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner')?.textContent).toBe(
|
||||
tooltipTexts[0],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (tooltipLength !== undefined) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBe(tooltipLength);
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelectorAll('.ant-tooltip-inner').length).toBe(tooltipLength);
|
||||
});
|
||||
}
|
||||
|
||||
wrapper.find('.ant-typography-copy').first().simulate('click');
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
jest.useRealTimers();
|
||||
if (iconClassNames[1] !== undefined) {
|
||||
expect(wrapper.exists(iconClassNames[1])).toBeTruthy();
|
||||
expect(wrapper.querySelector(iconClassNames[1])).not.toBeNull();
|
||||
}
|
||||
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
|
||||
wrapper.update();
|
||||
fireEvent.mouseEnter(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
|
||||
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
|
||||
fireEvent.mouseEnter(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
|
||||
if (tooltipTexts[1] !== undefined) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltipTexts[1]);
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner')?.textContent).toBe(
|
||||
tooltipTexts[1],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (iconTexts[1] !== undefined) {
|
||||
expect(wrapper.find('.ant-typography-copy').at(0).text()).toBe(iconTexts[1]);
|
||||
expect(wrapper.querySelectorAll('.ant-typography-copy')[0].textContent).toBe(
|
||||
iconTexts[1],
|
||||
);
|
||||
}
|
||||
|
||||
jest.useFakeTimers();
|
||||
wrapper.find('.ant-typography-copy').first().simulate('click');
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
}
|
||||
|
||||
const dom = (
|
||||
<>
|
||||
<span>1</span>2
|
||||
@ -197,14 +209,14 @@ describe('Typography copy', () => {
|
||||
|
||||
it('copy click event stopPropagation', () => {
|
||||
const onDivClick = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container: wrapper } = render(
|
||||
<div onClick={onDivClick}>
|
||||
<Base component="p" copyable>
|
||||
test copy
|
||||
</Base>
|
||||
</div>,
|
||||
);
|
||||
wrapper.find('.ant-typography-copy').first().simulate('click');
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
expect(onDivClick).not.toBeCalled();
|
||||
});
|
||||
|
||||
@ -212,12 +224,13 @@ describe('Typography copy', () => {
|
||||
function onCopy(e: React.MouseEvent<HTMLDivElement>) {
|
||||
expect(e).not.toBeUndefined();
|
||||
}
|
||||
const wrapper = mount(
|
||||
|
||||
const { container: wrapper } = render(
|
||||
<Base component="p" copyable={{ onCopy }}>
|
||||
test copy
|
||||
</Base>,
|
||||
);
|
||||
wrapper.find('.ant-typography-copy').first().simulate('click');
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
});
|
||||
|
||||
it('copy to clipboard', done => {
|
||||
@ -237,13 +250,13 @@ describe('Typography copy', () => {
|
||||
</Base>
|
||||
);
|
||||
};
|
||||
const wrapper = mount(<Test />);
|
||||
const copyBtn = wrapper.find('.ant-typography-copy').first();
|
||||
copyBtn.simulate('click');
|
||||
const { container: wrapper } = render(<Test />);
|
||||
const copyBtn = wrapper.querySelectorAll('.ant-typography-copy')[0];
|
||||
fireEvent.click(copyBtn);
|
||||
expect(spy.mock.calls[0][0]).toEqual(originText);
|
||||
setTimeout(() => {
|
||||
spy.mockReset();
|
||||
copyBtn.simulate('click');
|
||||
fireEvent.click(copyBtn);
|
||||
expect(spy.mock.calls[0][0]).toEqual(nextText);
|
||||
done();
|
||||
}, 500);
|
||||
|
@ -1,11 +1,8 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
|
||||
import React from 'react';
|
||||
import { fireEvent, render, sleep, triggerResize, waitFor } from '../../../tests/utils';
|
||||
import Base from '../Base';
|
||||
import Typography from '../Typography';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import * as styleChecker from '../../_util/styleChecker';
|
||||
|
||||
jest.mock('copy-to-clipboard');
|
||||
|
||||
@ -53,47 +50,59 @@ describe('Typography.Ellipsis', () => {
|
||||
'Bamboo is Little Light Bamboo is Little Light Bamboo is Little Light Bamboo is Little Light Bamboo is Little Light';
|
||||
|
||||
it('should trigger update', async () => {
|
||||
const ref = React.createRef();
|
||||
const onEllipsis = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Base ellipsis={{ onEllipsis }} component="p" editable>
|
||||
const {
|
||||
container: wrapper,
|
||||
rerender,
|
||||
unmount,
|
||||
} = render(
|
||||
<Base ellipsis={{ onEllipsis }} component="p" editable ref={ref}>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
// First resize
|
||||
wrapper.triggerResize();
|
||||
triggerResize(ref.current);
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.text()).toEqual('Bamboo is Little ...');
|
||||
|
||||
expect(wrapper.firstChild.textContent).toEqual('Bamboo is Little ...');
|
||||
expect(onEllipsis).toHaveBeenCalledWith(true);
|
||||
onEllipsis.mockReset();
|
||||
|
||||
// Second resize
|
||||
wrapper.setProps({ ellipsis: { rows: 2, onEllipsis } });
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.text()).toEqual('Bamboo is Little Light Bamboo is Litt...');
|
||||
rerender(
|
||||
<Base ellipsis={{ rows: 2, onEllipsis }} component="p" editable>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
expect(wrapper.textContent).toEqual('Bamboo is Little Light Bamboo is Litt...');
|
||||
expect(onEllipsis).not.toHaveBeenCalled();
|
||||
|
||||
// Third resize
|
||||
wrapper.setProps({ ellipsis: { rows: 99, onEllipsis } });
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('p').text()).toEqual(fullStr);
|
||||
rerender(
|
||||
<Base ellipsis={{ rows: 99, onEllipsis }} component="p" editable>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
expect(wrapper.querySelector('p').textContent).toEqual(fullStr);
|
||||
expect(onEllipsis).toHaveBeenCalledWith(false);
|
||||
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('support css multiple lines', async () => {
|
||||
const wrapper = mount(
|
||||
const { container: wrapper } = render(
|
||||
<Base ellipsis={{ rows: 2 }} component="p">
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
expect(wrapper.exists('.ant-typography-ellipsis-multiple-line')).toBeTruthy();
|
||||
expect(wrapper.find(Typography).prop('style').WebkitLineClamp).toEqual(2);
|
||||
expect(
|
||||
wrapper.querySelectorAll('.ant-typography-ellipsis-multiple-line').length,
|
||||
).toBeGreaterThan(0);
|
||||
expect(
|
||||
wrapper.querySelector('.ant-typography-ellipsis-multiple-line').style.WebkitLineClamp,
|
||||
).toEqual('2');
|
||||
});
|
||||
|
||||
it('string with parentheses', async () => {
|
||||
@ -105,71 +114,87 @@ describe('Typography.Ellipsis', () => {
|
||||
design language for background applications, is refined by Ant UED Team.
|
||||
Ant Design, a design language for background applications, is refined by
|
||||
Ant UED Team.`;
|
||||
const ref = React.createRef();
|
||||
const onEllipsis = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Base ellipsis={{ onEllipsis }} component="p" editable>
|
||||
const { container: wrapper, unmount } = render(
|
||||
<Base ellipsis={{ onEllipsis }} component="p" editable ref={ref}>
|
||||
{parenthesesStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
wrapper.triggerResize();
|
||||
triggerResize(ref.current);
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.text()).toEqual('Ant Design, a des...');
|
||||
const ellipsisSpan = wrapper.find('span[aria-hidden]').last();
|
||||
expect(ellipsisSpan.text()).toEqual('...');
|
||||
|
||||
expect(wrapper.firstChild.textContent).toEqual('Ant Design, a des...');
|
||||
const ellipsisSpans = wrapper.querySelectorAll('span[aria-hidden]');
|
||||
expect(ellipsisSpans[ellipsisSpans.length - 1].textContent).toEqual('...');
|
||||
onEllipsis.mockReset();
|
||||
|
||||
wrapper.unmount();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should middle ellipsis', async () => {
|
||||
const suffix = '--suffix';
|
||||
const wrapper = mount(
|
||||
<Base ellipsis={{ rows: 1, suffix }} component="p">
|
||||
const ref = React.createRef();
|
||||
const { container: wrapper, unmount } = render(
|
||||
<Base ellipsis={{ rows: 1, suffix }} component="p" ref={ref}>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
wrapper.triggerResize();
|
||||
triggerResize(ref.current);
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('p').text()).toEqual('Bamboo is...--suffix');
|
||||
wrapper.unmount();
|
||||
|
||||
expect(wrapper.querySelector('p').textContent).toEqual('Bamboo is...--suffix');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should front or middle ellipsis', async () => {
|
||||
const suffix = '--The information is very important';
|
||||
const wrapper = mount(
|
||||
<Base ellipsis={{ rows: 1, suffix }} component="p">
|
||||
const ref = React.createRef();
|
||||
const {
|
||||
container: wrapper,
|
||||
rerender,
|
||||
unmount,
|
||||
} = render(
|
||||
<Base ellipsis={{ rows: 1, suffix }} component="p" ref={ref}>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
wrapper.triggerResize();
|
||||
triggerResize(ref.current);
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('p').text()).toEqual('...--The information is very important');
|
||||
|
||||
wrapper.setProps({ ellipsis: { rows: 2, suffix } });
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('p').text()).toEqual('Ba...--The information is very important');
|
||||
expect(wrapper.querySelector('p').textContent).toEqual(
|
||||
'...--The information is very important',
|
||||
);
|
||||
|
||||
wrapper.setProps({ ellipsis: { rows: 99, suffix } });
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('p').text()).toEqual(fullStr + suffix);
|
||||
rerender(
|
||||
<Base ellipsis={{ rows: 2, suffix }} component="p">
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
expect(wrapper.querySelector('p').textContent).toEqual(
|
||||
'Ba...--The information is very important',
|
||||
);
|
||||
|
||||
wrapper.unmount();
|
||||
rerender(
|
||||
<Base ellipsis={{ rows: 99, suffix }} component="p">
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
expect(wrapper.querySelector('p').textContent).toEqual(fullStr + suffix);
|
||||
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('connect children', async () => {
|
||||
const bamboo = 'Bamboo';
|
||||
const is = ' is ';
|
||||
|
||||
const wrapper = mount(
|
||||
<Base ellipsis component="p" editable>
|
||||
const ref = React.createRef();
|
||||
const { container: wrapper } = render(
|
||||
<Base ellipsis component="p" editable ref={ref}>
|
||||
{bamboo}
|
||||
{is}
|
||||
<code>Little</code>
|
||||
@ -177,54 +202,49 @@ describe('Typography.Ellipsis', () => {
|
||||
</Base>,
|
||||
);
|
||||
|
||||
wrapper.triggerResize();
|
||||
triggerResize(ref.current);
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.text()).toEqual('Bamboo is Little...');
|
||||
expect(wrapper.textContent).toEqual('Bamboo is Little...');
|
||||
});
|
||||
|
||||
it('should expandable work', async () => {
|
||||
const onExpand = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container: wrapper } = render(
|
||||
<Base ellipsis={{ expandable: true, onExpand }} component="p" copyable editable>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
|
||||
wrapper.find('.ant-typography-expand').simulate('click');
|
||||
fireEvent.click(wrapper.querySelector('.ant-typography-expand'));
|
||||
expect(onExpand).toHaveBeenCalled();
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('p').text()).toEqual(fullStr);
|
||||
expect(wrapper.querySelector('p').textContent).toEqual(fullStr);
|
||||
});
|
||||
|
||||
it('should have custom expand style', async () => {
|
||||
const symbol = 'more';
|
||||
const wrapper = mount(
|
||||
const { container: wrapper } = render(
|
||||
<Base ellipsis={{ expandable: true, symbol }} component="p">
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-typography-expand').text()).toEqual('more');
|
||||
expect(wrapper.querySelector('.ant-typography-expand').textContent).toEqual('more');
|
||||
});
|
||||
|
||||
it('can use css ellipsis', () => {
|
||||
const wrapper = mount(<Base ellipsis component="p" />);
|
||||
expect(wrapper.find('.ant-typography-ellipsis-single-line').length).toBeTruthy();
|
||||
const { container: wrapper } = render(<Base ellipsis component="p" />);
|
||||
expect(wrapper.querySelectorAll('.ant-typography-ellipsis-single-line').length).toBeGreaterThan(
|
||||
0,
|
||||
);
|
||||
});
|
||||
|
||||
it('should calculate padding', () => {
|
||||
const wrapper = mount(
|
||||
const { container: wrapper } = render(
|
||||
<Base ellipsis component="p" style={{ paddingTop: '12px', paddingBottom: '12px' }} />,
|
||||
);
|
||||
expect(wrapper.find('.ant-typography-ellipsis-single-line').length).toBeTruthy();
|
||||
expect(wrapper.querySelectorAll('.ant-typography-ellipsis-single-line').length).toBeGreaterThan(
|
||||
0,
|
||||
);
|
||||
});
|
||||
|
||||
describe('should tooltip support', () => {
|
||||
@ -245,40 +265,52 @@ describe('Typography.Ellipsis', () => {
|
||||
domSpy.mockRestore();
|
||||
});
|
||||
|
||||
function getWrapper(tooltip) {
|
||||
return mount(
|
||||
<Base ellipsis={{ tooltip }} component="p">
|
||||
async function getWrapper(tooltip) {
|
||||
const ref = React.createRef();
|
||||
const wrapper = render(
|
||||
<Base ellipsis={{ tooltip }} component="p" ref={ref}>
|
||||
{fullStr}
|
||||
</Base>,
|
||||
);
|
||||
triggerResize(ref.current);
|
||||
await sleep(20);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
it('boolean', async () => {
|
||||
const wrapper = getWrapper(true);
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('Tooltip').prop('title')).toEqual(fullStr);
|
||||
const { container, baseElement } = await getWrapper(true);
|
||||
fireEvent.mouseEnter(container.firstChild);
|
||||
await waitFor(() => {
|
||||
expect(baseElement.querySelector('.ant-tooltip-open')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('customize', async () => {
|
||||
const wrapper = getWrapper('Bamboo is Light');
|
||||
await sleep(20);
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('Tooltip').prop('title')).toEqual('Bamboo is Light');
|
||||
const { container, baseElement } = await getWrapper('Bamboo is Light');
|
||||
fireEvent.mouseEnter(container.firstChild);
|
||||
await waitFor(() => {
|
||||
expect(baseElement.querySelector('.ant-tooltip-open')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('js ellipsis should show aria-label', () => {
|
||||
const titleWrapper = mount(<Base title="bamboo" ellipsis={{ expandable: true }} />);
|
||||
expect(titleWrapper.find('.ant-typography').prop('aria-label')).toEqual('bamboo');
|
||||
const { container: titleWrapper } = render(
|
||||
<Base title="bamboo" ellipsis={{ expandable: true }} />,
|
||||
);
|
||||
expect(titleWrapper.querySelector('.ant-typography').getAttribute('aria-label')).toEqual(
|
||||
'bamboo',
|
||||
);
|
||||
|
||||
const tooltipWrapper = mount(<Base ellipsis={{ expandable: true, tooltip: 'little' }} />);
|
||||
expect(tooltipWrapper.find('.ant-typography').prop('aria-label')).toEqual('little');
|
||||
const { container: tooltipWrapper } = render(
|
||||
<Base ellipsis={{ expandable: true, tooltip: 'little' }} />,
|
||||
);
|
||||
expect(tooltipWrapper.querySelector('.ant-typography').getAttribute('aria-label')).toEqual(
|
||||
'little',
|
||||
);
|
||||
});
|
||||
|
||||
it('should display tooltip if line clamp', () => {
|
||||
it('should display tooltip if line clamp', async () => {
|
||||
mockRectSpy = spyElementPrototypes(HTMLElement, {
|
||||
scrollHeight: {
|
||||
get() {
|
||||
@ -299,12 +331,19 @@ describe('Typography.Ellipsis', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const wrapper = mount(
|
||||
<Base ellipsis={{ tooltip: 'This is tooltip', rows: 2 }}>
|
||||
const ref = React.createRef();
|
||||
const { container: wrapper, baseElement } = render(
|
||||
<Base ellipsis={{ tooltip: 'This is tooltip', rows: 2 }} ref={ref}>
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team.
|
||||
</Base>,
|
||||
);
|
||||
expect(wrapper.find('EllipsisTooltip').prop('isEllipsis')).toBeTruthy();
|
||||
triggerResize(ref.current);
|
||||
await sleep(20);
|
||||
|
||||
fireEvent.mouseEnter(wrapper.firstChild);
|
||||
await waitFor(() => {
|
||||
expect(baseElement.querySelector('.ant-tooltip-open')).not.toBeNull();
|
||||
});
|
||||
mockRectSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,12 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import Paragraph from '../Paragraph';
|
||||
|
||||
test('Callback on enter key is triggered', () => {
|
||||
const onEditStart = jest.fn();
|
||||
const onCopy = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
const { container: wrapper } = render(
|
||||
<Paragraph
|
||||
copyable={{
|
||||
onCopy,
|
||||
@ -23,8 +22,8 @@ test('Callback on enter key is triggered', () => {
|
||||
jest.spyOn(window, 'setTimeout').mockReturnValue(timer);
|
||||
jest.spyOn(window, 'clearTimeout');
|
||||
// must copy first, because editing button will hide copy button
|
||||
wrapper.find('.ant-typography-copy').at(0).simulate('keyup', { keyCode: KeyCode.ENTER });
|
||||
wrapper.find('.anticon-edit').at(0).simulate('keyup', { keyCode: KeyCode.ENTER });
|
||||
fireEvent.keyUp(wrapper.querySelectorAll('.ant-typography-copy')[0], { keyCode: KeyCode.ENTER });
|
||||
fireEvent.keyUp(wrapper.querySelectorAll('.anticon-edit')[0], { keyCode: KeyCode.ENTER });
|
||||
|
||||
expect(onEditStart.mock.calls.length).toBe(1);
|
||||
expect(onCopy.mock.calls.length).toBe(1);
|
||||
|
@ -1,19 +1,17 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { SmileOutlined, LikeOutlined, HighlightOutlined, CheckOutlined } from '@ant-design/icons';
|
||||
import { CheckOutlined, HighlightOutlined, LikeOutlined, SmileOutlined } from '@ant-design/icons';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import { resetWarned } from 'rc-util/lib/warning';
|
||||
import { spyElementPrototype } from 'rc-util/lib/test/domHook';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import Title from '../Title';
|
||||
import React from 'react';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, render, sleep, waitFor } from '../../../tests/utils';
|
||||
import Base from '../Base';
|
||||
import Link from '../Link';
|
||||
import Paragraph from '../Paragraph';
|
||||
import Text from '../Text';
|
||||
import Base from '../Base';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import Title from '../Title';
|
||||
import Typography from '../Typography';
|
||||
import { sleep, render } from '../../../tests/utils';
|
||||
|
||||
jest.mock('copy-to-clipboard');
|
||||
|
||||
@ -79,7 +77,7 @@ describe('Typography', () => {
|
||||
|
||||
describe('Title', () => {
|
||||
it('warning if `level` not correct', () => {
|
||||
mount(<Title level={false} />);
|
||||
render(<Title level={false} />);
|
||||
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Typography.Title] Title only accept `1 | 2 | 3 | 4 | 5` as `level` value. And `5` need 4.6.0+ version.',
|
||||
@ -93,47 +91,57 @@ describe('Typography', () => {
|
||||
it(name, async () => {
|
||||
jest.useFakeTimers();
|
||||
const onCopy = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container: wrapper, unmount } = render(
|
||||
<Base component="p" copyable={{ text, onCopy, icon, tooltips, format }}>
|
||||
test copy
|
||||
</Base>,
|
||||
);
|
||||
|
||||
if (icon) {
|
||||
expect(wrapper.find('.anticon-smile').length).toBeTruthy();
|
||||
expect(wrapper.querySelectorAll('.anticon-smile').length).toBeGreaterThan(0);
|
||||
} else {
|
||||
expect(wrapper.find('.anticon-copy').length).toBeTruthy();
|
||||
expect(wrapper.querySelectorAll('.anticon-copy').length).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
|
||||
fireEvent.mouseEnter(wrapper.querySelector('.ant-typography-copy'));
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
if (tooltips === undefined || tooltips === true) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe('Copy');
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe('Copy');
|
||||
});
|
||||
} else if (tooltips === false) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelectorAll('.ant-tooltip-inner').length).toBe(0);
|
||||
});
|
||||
} else if (tooltips[0] === '' && tooltips[1] === '') {
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelectorAll('.ant-tooltip-inner').length).toBe(0);
|
||||
});
|
||||
} else if (tooltips[0] === '' && tooltips[1]) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelectorAll('.ant-tooltip-inner').length).toBe(0);
|
||||
});
|
||||
} else if (tooltips[1] === '' && tooltips[0]) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltips[0]);
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe(tooltips[0]);
|
||||
});
|
||||
} else {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltips[0]);
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe(tooltips[0]);
|
||||
});
|
||||
}
|
||||
|
||||
wrapper.find('.ant-typography-copy').first().simulate('click');
|
||||
fireEvent.click(wrapper.querySelector('.ant-typography-copy'));
|
||||
jest.useRealTimers();
|
||||
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
|
||||
// tooltips 为 ['', 'xxx'] 时,切换时需要延时 mousenEnterDelay 的时长
|
||||
fireEvent.mouseEnter(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
// tooltips 为 ['', 'xxx'] 时,切换时需要延时 mouseEnterDelay 的时长
|
||||
if (tooltips && tooltips[0] === '' && tooltips[1]) {
|
||||
await sleep(150);
|
||||
}
|
||||
|
||||
expect(copy.lastStr).toEqual(target);
|
||||
expect(copy.lastOptions.format).toEqual(format);
|
||||
wrapper.update();
|
||||
expect(onCopy).toHaveBeenCalled();
|
||||
|
||||
let copiedIcon = '.anticon-check';
|
||||
@ -143,31 +151,43 @@ describe('Typography', () => {
|
||||
copiedIcon = '.anticon-check';
|
||||
}
|
||||
|
||||
expect(wrapper.find(copiedIcon).length).toBeTruthy();
|
||||
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
|
||||
expect(wrapper.querySelectorAll(copiedIcon).length).toBeGreaterThan(0);
|
||||
fireEvent.mouseEnter(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
|
||||
if (tooltips === undefined || tooltips === true) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe('Copied');
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe('Copied');
|
||||
});
|
||||
} else if (tooltips === false) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelectorAll('.ant-tooltip-inner').length).toBe(0);
|
||||
});
|
||||
} else if (tooltips[0] === '' && tooltips[1] === '') {
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelectorAll('.ant-tooltip-inner').length).toBe(0);
|
||||
});
|
||||
} else if (tooltips[0] === '' && tooltips[1]) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltips[1]);
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe(tooltips[1]);
|
||||
});
|
||||
} else if (tooltips[1] === '' && tooltips[0]) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe('');
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe('');
|
||||
});
|
||||
} else {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltips[1]);
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe(tooltips[1]);
|
||||
});
|
||||
}
|
||||
|
||||
jest.useFakeTimers();
|
||||
wrapper.find('.ant-typography-copy').first().simulate('click');
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-copy')[0]);
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
// Will set back when 3 seconds pass
|
||||
expect(wrapper.find(copiedIcon).length).toBeFalsy();
|
||||
wrapper.unmount();
|
||||
await sleep(3000);
|
||||
expect(wrapper.querySelectorAll(copiedIcon).length).toBe(0);
|
||||
unmount();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
}
|
||||
@ -221,15 +241,15 @@ describe('Typography', () => {
|
||||
submitFunc,
|
||||
expectFunc,
|
||||
) {
|
||||
it(name, () => {
|
||||
it(name, async () => {
|
||||
jest.useFakeTimers();
|
||||
const onStart = jest.fn();
|
||||
const onChange = jest.fn();
|
||||
|
||||
const className = 'test';
|
||||
const style = {};
|
||||
const style = { padding: 'unset' };
|
||||
|
||||
const wrapper = mount(
|
||||
const { container: wrapper } = render(
|
||||
<Paragraph
|
||||
editable={{ onChange, onStart, icon, tooltip, triggerType, enterIcon }}
|
||||
className={className}
|
||||
@ -241,64 +261,71 @@ describe('Typography', () => {
|
||||
|
||||
if (triggerType === undefined || triggerType.indexOf('icon') !== -1) {
|
||||
if (icon) {
|
||||
expect(wrapper.find('.anticon-highlight').length).toBeTruthy();
|
||||
expect(wrapper.querySelectorAll('.anticon-highlight').length).toBeGreaterThan(0);
|
||||
} else {
|
||||
expect(wrapper.find('.anticon-edit').length).toBeTruthy();
|
||||
expect(wrapper.querySelectorAll('.anticon-edit').length).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
if (triggerType === undefined || triggerType.indexOf('text') === -1) {
|
||||
wrapper.simulate('click');
|
||||
fireEvent.click(wrapper.firstChild);
|
||||
expect(onStart).not.toHaveBeenCalled();
|
||||
}
|
||||
wrapper.find('.ant-typography-edit').first().simulate('mouseenter');
|
||||
fireEvent.mouseEnter(wrapper.querySelectorAll('.ant-typography-edit')[0]);
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
if (tooltip === undefined || tooltip === true) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe('Edit');
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe('Edit');
|
||||
});
|
||||
} else if (tooltip === false) {
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelectorAll('.ant-tooltip-inner').length).toBe(0);
|
||||
});
|
||||
} else {
|
||||
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltip);
|
||||
await waitFor(() => {
|
||||
expect(wrapper.querySelector('.ant-tooltip-inner').textContent).toBe(tooltip);
|
||||
});
|
||||
}
|
||||
|
||||
wrapper.find('.ant-typography-edit').first().simulate('click');
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-edit')[0]);
|
||||
|
||||
expect(onStart).toHaveBeenCalled();
|
||||
if (triggerType !== undefined && triggerType.indexOf('text') !== -1) {
|
||||
wrapper.find('textarea').simulate('keyDown', { keyCode: KeyCode.ESC });
|
||||
wrapper.find('textarea').simulate('keyUp', { keyCode: KeyCode.ESC });
|
||||
fireEvent.keyDown(wrapper.querySelector('textarea'), { keyCode: KeyCode.ESC });
|
||||
fireEvent.keyUp(wrapper.querySelector('textarea'), { keyCode: KeyCode.ESC });
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerType !== undefined && triggerType.indexOf('text') !== -1) {
|
||||
if (triggerType.indexOf('icon') === -1) {
|
||||
expect(wrapper.find('.anticon-highlight').length).toBeFalsy();
|
||||
expect(wrapper.find('.anticon-edit').length).toBeFalsy();
|
||||
expect(wrapper.querySelectorAll('.anticon-highlight').length).toBe(0);
|
||||
expect(wrapper.querySelectorAll('.anticon-edit').length).toBe(0);
|
||||
}
|
||||
wrapper.simulate('click');
|
||||
fireEvent.click(wrapper.firstChild);
|
||||
expect(onStart).toHaveBeenCalled();
|
||||
}
|
||||
|
||||
// Should have className
|
||||
const props = wrapper.find('div').first().props();
|
||||
expect(props.style).toEqual(style);
|
||||
const props = wrapper.querySelectorAll('div')[0];
|
||||
expect(props.getAttribute('style')).toContain('padding: unset');
|
||||
expect(props.className.includes(className)).toBeTruthy();
|
||||
|
||||
wrapper.find('textarea').simulate('change', {
|
||||
fireEvent.change(wrapper.querySelector('textarea'), {
|
||||
target: { value: 'Bamboo' },
|
||||
});
|
||||
|
||||
if (enterIcon === undefined) {
|
||||
expect(
|
||||
wrapper.find('span.ant-typography-edit-content-confirm').first().props().className,
|
||||
wrapper.querySelectorAll('span.ant-typography-edit-content-confirm')[0].className,
|
||||
).toContain('anticon-enter');
|
||||
} else if (enterIcon === null) {
|
||||
expect(wrapper.find('span.ant-typography-edit-content-confirm').length).toBe(0);
|
||||
expect(
|
||||
wrapper.querySelectorAll('span.ant-typography-edit-content-confirm').length,
|
||||
).toBe(0);
|
||||
} else {
|
||||
expect(
|
||||
wrapper.find('span.ant-typography-edit-content-confirm').first().props().className,
|
||||
wrapper.querySelectorAll('span.ant-typography-edit-content-confirm')[0].className,
|
||||
).not.toContain('anticon-enter');
|
||||
}
|
||||
|
||||
@ -319,21 +346,21 @@ describe('Typography', () => {
|
||||
|
||||
testStep({ name: 'by key up' }, wrapper => {
|
||||
// Not trigger when inComposition
|
||||
wrapper.find('textarea').simulate('compositionStart');
|
||||
wrapper.find('textarea').simulate('keyDown', { keyCode: KeyCode.ENTER });
|
||||
wrapper.find('textarea').simulate('compositionEnd');
|
||||
wrapper.find('textarea').simulate('keyUp', { keyCode: KeyCode.ENTER });
|
||||
fireEvent.compositionStart(wrapper.querySelector('textarea'));
|
||||
fireEvent.keyDown(wrapper.querySelector('textarea'), { keyCode: KeyCode.ENTER });
|
||||
fireEvent.compositionEnd(wrapper.querySelector('textarea'));
|
||||
fireEvent.keyUp(wrapper.querySelector('textarea'), { keyCode: KeyCode.ENTER });
|
||||
|
||||
// Now trigger
|
||||
wrapper.find('textarea').simulate('keyDown', { keyCode: KeyCode.ENTER });
|
||||
wrapper.find('textarea').simulate('keyUp', { keyCode: KeyCode.ENTER });
|
||||
fireEvent.keyDown(wrapper.querySelector('textarea'), { keyCode: KeyCode.ENTER });
|
||||
fireEvent.keyUp(wrapper.querySelector('textarea'), { keyCode: KeyCode.ENTER });
|
||||
});
|
||||
|
||||
testStep(
|
||||
{ name: 'by esc key' },
|
||||
wrapper => {
|
||||
wrapper.find('textarea').simulate('keyDown', { keyCode: KeyCode.ESC });
|
||||
wrapper.find('textarea').simulate('keyUp', { keyCode: KeyCode.ESC });
|
||||
fireEvent.keyDown(wrapper.querySelector('textarea'), { keyCode: KeyCode.ESC });
|
||||
fireEvent.keyUp(wrapper.querySelector('textarea'), { keyCode: KeyCode.ESC });
|
||||
},
|
||||
onChange => {
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
@ -342,7 +369,7 @@ describe('Typography', () => {
|
||||
);
|
||||
|
||||
testStep({ name: 'by blur' }, wrapper => {
|
||||
wrapper.find('textarea').simulate('blur');
|
||||
fireEvent.blur(wrapper.querySelector('textarea'));
|
||||
});
|
||||
|
||||
testStep({ name: 'customize edit icon', icon: <HighlightOutlined /> });
|
||||
@ -359,47 +386,51 @@ describe('Typography', () => {
|
||||
|
||||
it('should trigger onEnd when type Enter', () => {
|
||||
const onEnd = jest.fn();
|
||||
const wrapper = mount(<Paragraph editable={{ onEnd }}>Bamboo</Paragraph>);
|
||||
wrapper.find('.ant-typography-edit').first().simulate('click');
|
||||
wrapper.find('textarea').simulate('keyDown', { keyCode: KeyCode.ENTER });
|
||||
wrapper.find('textarea').simulate('keyUp', { keyCode: KeyCode.ENTER });
|
||||
const { container: wrapper } = render(<Paragraph editable={{ onEnd }}>Bamboo</Paragraph>);
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-edit')[0]);
|
||||
fireEvent.keyDown(wrapper.querySelector('textarea'), { keyCode: KeyCode.ENTER });
|
||||
fireEvent.keyUp(wrapper.querySelector('textarea'), { keyCode: KeyCode.ENTER });
|
||||
expect(onEnd).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should trigger onCancel when type ESC', () => {
|
||||
const onCancel = jest.fn();
|
||||
const wrapper = mount(<Paragraph editable={{ onCancel }}>Bamboo</Paragraph>);
|
||||
wrapper.find('.ant-typography-edit').first().simulate('click');
|
||||
wrapper.find('textarea').simulate('keyDown', { keyCode: KeyCode.ESC });
|
||||
wrapper.find('textarea').simulate('keyUp', { keyCode: KeyCode.ESC });
|
||||
const { container: wrapper } = render(
|
||||
<Paragraph editable={{ onCancel }}>Bamboo</Paragraph>,
|
||||
);
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-edit')[0]);
|
||||
fireEvent.keyDown(wrapper.querySelector('textarea'), { keyCode: KeyCode.ESC });
|
||||
fireEvent.keyUp(wrapper.querySelector('textarea'), { keyCode: KeyCode.ESC });
|
||||
expect(onCancel).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should only trigger focus on the first time', () => {
|
||||
let triggerTimes = 0;
|
||||
const mockFocus = spyElementPrototype(HTMLElement, 'focus', () => {
|
||||
const { container: wrapper } = render(<Paragraph editable>Bamboo</Paragraph>);
|
||||
const editIcon = wrapper.querySelectorAll('.ant-typography-edit')[0];
|
||||
|
||||
editIcon.addEventListener('focus', () => {
|
||||
triggerTimes += 1;
|
||||
});
|
||||
|
||||
const wrapper = mount(<Paragraph editable>Bamboo</Paragraph>);
|
||||
|
||||
wrapper.find('.ant-typography-edit').first().simulate('click');
|
||||
fireEvent.focus(editIcon);
|
||||
expect(triggerTimes).toEqual(1);
|
||||
|
||||
wrapper.find('textarea').simulate('change', {
|
||||
fireEvent.click(editIcon);
|
||||
expect(triggerTimes).toEqual(1);
|
||||
|
||||
fireEvent.change(wrapper.querySelector('textarea'), {
|
||||
target: { value: 'good' },
|
||||
});
|
||||
|
||||
expect(triggerTimes).toEqual(1);
|
||||
|
||||
mockFocus.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
it('should focus at the end of textarea', () => {
|
||||
const wrapper = mount(<Paragraph editable>content</Paragraph>);
|
||||
wrapper.find('.ant-typography-edit').first().simulate('click');
|
||||
const textareaNode = wrapper.find('textarea').getDOMNode();
|
||||
const { container: wrapper } = render(<Paragraph editable>content</Paragraph>);
|
||||
fireEvent.click(wrapper.querySelectorAll('.ant-typography-edit')[0]);
|
||||
const textareaNode = wrapper.querySelector('textarea');
|
||||
expect(textareaNode.selectionStart).toBe(7);
|
||||
expect(textareaNode.selectionEnd).toBe(7);
|
||||
});
|
||||
@ -407,7 +438,7 @@ describe('Typography', () => {
|
||||
|
||||
it('warning if use setContentRef', () => {
|
||||
const refFunc = () => {};
|
||||
mount(<Typography setContentRef={refFunc} />);
|
||||
render(<Typography setContentRef={refFunc} />);
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
'Warning: [antd: Typography] `setContentRef` is deprecated. Please use `ref` instead.',
|
||||
);
|
||||
@ -423,21 +454,21 @@ describe('Typography', () => {
|
||||
it('should get HTMLHeadingElement ref from Title', () => {
|
||||
const ref = React.createRef();
|
||||
|
||||
mount(<Title level={1} ref={ref} />);
|
||||
render(<Title level={1} ref={ref} />);
|
||||
expect(ref.current instanceof HTMLHeadingElement).toBe(true);
|
||||
});
|
||||
|
||||
it('should get HTMLDivElement ref from Paragraph', () => {
|
||||
const ref = React.createRef();
|
||||
|
||||
mount(<Paragraph ref={ref} />);
|
||||
render(<Paragraph ref={ref} />);
|
||||
expect(ref.current instanceof HTMLDivElement).toBe(true);
|
||||
});
|
||||
|
||||
it('should get HTMLSpanElement ref from Text', () => {
|
||||
const ref = React.createRef();
|
||||
|
||||
mount(<Text ref={ref} />);
|
||||
render(<Text ref={ref} />);
|
||||
expect(ref.current instanceof HTMLSpanElement).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -527,7 +527,7 @@
|
||||
// .@{upload-prefix-cls}-animate-inline-enter,
|
||||
// .@{upload-prefix-cls}-animate-inline-leave {
|
||||
// animation-duration: @animation-duration-slow;
|
||||
// animation-fill-mode: @ease-in-out-circ;
|
||||
// animation-timing-function: @ease-in-out-circ;
|
||||
// }
|
||||
|
||||
// .@{upload-prefix-cls}-animate-inline-appear,
|
||||
|
@ -31,7 +31,7 @@ const genMotionStyle: GenerateStyle<UploadToken> = token => {
|
||||
[`${componentCls}-wrapper`]: {
|
||||
[`${inlineCls}-appear, ${inlineCls}-enter, ${inlineCls}-leave`]: {
|
||||
animationDuration: token.motionDurationSlow,
|
||||
animationFillMode: token.motionEaseInOutCirc,
|
||||
animationTimingFunction: token.motionEaseInOutCirc,
|
||||
},
|
||||
|
||||
[`${inlineCls}-appear, ${inlineCls}-enter`]: {
|
||||
|
13
package.json
13
package.json
@ -117,7 +117,7 @@
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/cssinjs": "^0.0.0-alpha.34",
|
||||
"@ant-design/icons": "^4.7.0",
|
||||
"@ant-design/react-slick": "~0.28.1",
|
||||
"@ant-design/react-slick": "~0.29.1",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@ctrl/tinycolor": "^3.4.0",
|
||||
"classnames": "^2.2.6",
|
||||
@ -128,11 +128,11 @@
|
||||
"rc-cascader": "~3.6.0",
|
||||
"rc-checkbox": "~2.3.0",
|
||||
"rc-collapse": "~3.3.0",
|
||||
"rc-dialog": "~8.8.2",
|
||||
"rc-dialog": "~8.9.0",
|
||||
"rc-drawer": "~4.4.2",
|
||||
"rc-dropdown": "~4.0.0",
|
||||
"rc-field-form": "~1.26.1",
|
||||
"rc-image": "~5.6.0",
|
||||
"rc-image": "~5.7.0",
|
||||
"rc-input": "~0.0.1-alpha.5",
|
||||
"rc-input-number": "~7.3.0",
|
||||
"rc-mentions": "~1.8.0",
|
||||
@ -162,9 +162,9 @@
|
||||
"shallowequal": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/bisheng-plugin": "^3.2.0",
|
||||
"@ant-design/bisheng-plugin": "^3.3.0-alpha.4",
|
||||
"@ant-design/hitu": "^0.0.0-alpha.13",
|
||||
"@ant-design/tools": "^15.0.2",
|
||||
"@ant-design/tools": "^15.0.3",
|
||||
"@docsearch/css": "^3.0.0",
|
||||
"@qixian.cs/github-contributors-list": "^1.0.3",
|
||||
"@stackblitz/sdk": "^1.3.0",
|
||||
@ -195,7 +195,7 @@
|
||||
"antd-img-crop": "^4.0.0",
|
||||
"array-move": "^4.0.0",
|
||||
"babel-plugin-add-react-displayname": "^0.0.5",
|
||||
"bisheng": "^3.5.0",
|
||||
"bisheng": "^3.7.0-alpha.4",
|
||||
"bisheng-plugin-description": "^0.1.4",
|
||||
"bisheng-plugin-react": "^1.2.0",
|
||||
"bisheng-plugin-toc": "^0.4.4",
|
||||
@ -277,7 +277,6 @@
|
||||
"react-router-dom": "^6.0.2",
|
||||
"react-sortable-hoc": "^2.0.0",
|
||||
"react-sticky": "^6.0.3",
|
||||
"react-text-loop-next": "0.0.3",
|
||||
"react-window": "^1.8.5",
|
||||
"remark": "^14.0.1",
|
||||
"remark-cli": "^10.0.0",
|
||||
|
Loading…
Reference in New Issue
Block a user