Browse Source

fix: Typography `icons` should ignore React.Fragment (#30869)

* feat: fix-text

* feat: 优化代码

* chore: add test

* chore: 打算重构 test

* chore: 重构 test

* chore: 重构 test

* chore: 重构 test

* feat: review

* feat: review

* feat: add test

* feat: add test

* fix: test

* fix: tsx

* fix: 优化

* fix: 优化

* fix: map 当前处理

* fix: getNode function

* fix: 优化方法

* fix: ci

* fix: aria-label
pull/30881/head
叶枫 4 years ago
committed by GitHub
parent
commit
f288aff9fe
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      components/typography/Base.tsx
  2. 197
      components/typography/__tests__/copy.test.tsx

31
components/typography/Base.tsx

@ -93,6 +93,13 @@ function wrapperDecorations(
return currentContent; return currentContent;
} }
function getNode(dom: React.ReactNode, defaultNode: React.ReactNode, needDom?: boolean) {
if (dom === true || dom === undefined) {
return defaultNode;
}
return dom || (needDom && defaultNode);
}
interface InternalBlockProps extends BlockProps { interface InternalBlockProps extends BlockProps {
component: string; component: string;
} }
@ -391,23 +398,27 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
const prefixCls = this.getPrefixCls(); const prefixCls = this.getPrefixCls();
const { tooltips } = copyable as CopyConfig; const { tooltips, icon } = copyable as CopyConfig;
let tooltipNodes = toArray(tooltips) as React.ReactNode[];
if (tooltipNodes.length === 0) { const tooltipNodes = Array.isArray(tooltips) ? tooltips : [tooltips];
tooltipNodes = [this.copyStr, this.copiedStr]; const iconNodes = Array.isArray(icon) ? icon : [icon];
}
const title = copied ? tooltipNodes[1] : tooltipNodes[0]; const title = copied
const ariaLabel = typeof title === 'string' ? title : ''; ? getNode(tooltipNodes[1], this.copiedStr)
const icons = toArray((copyable as CopyConfig).icon); : getNode(tooltipNodes[0], this.copyStr);
const systemStr = copied ? this.copiedStr : this.copyStr;
const ariaLabel = typeof title === 'string' ? title : systemStr;
return ( return (
<Tooltip key="copy" title={tooltips === false ? '' : title}> <Tooltip key="copy" title={title}>
<TransButton <TransButton
className={classNames(`${prefixCls}-copy`, copied && `${prefixCls}-copy-success`)} className={classNames(`${prefixCls}-copy`, copied && `${prefixCls}-copy-success`)}
onClick={this.onCopyClick} onClick={this.onCopyClick}
aria-label={ariaLabel} aria-label={ariaLabel}
> >
{copied ? icons[1] || <CheckOutlined /> : icons[0] || <CopyOutlined />} {copied
? getNode(iconNodes[1], <CheckOutlined />, true)
: getNode(iconNodes[0], <CopyOutlined />, true)}
</TransButton> </TransButton>
</Tooltip> </Tooltip>
); );

197
components/typography/__tests__/copy.test.tsx

@ -0,0 +1,197 @@
import React from 'react';
import { mount } from 'enzyme';
import { SmileOutlined, LikeOutlined } from '@ant-design/icons';
import Base from '../Base';
describe('Typography copy', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
afterEach(() => {
errorSpy.mockReset();
});
describe('Base', () => {
describe('copyable', () => {
function copyTest({
name,
icon,
tooltips,
iconClassNames = [],
iconTexts = [],
tooltipTexts = [],
tooltipLength,
}: {
name: string;
icon?: boolean | React.ReactNode;
tooltips?: boolean | React.ReactNode;
iconClassNames?: string[];
iconTexts?: string[];
tooltipTexts?: string[];
tooltipLength?: number;
}) {
it(name, async () => {
jest.useFakeTimers();
const wrapper = mount(
<Base component="p" copyable={{ icon, tooltips }}>
test copy
</Base>,
);
if (iconClassNames[0] !== undefined) {
expect(wrapper.exists(iconClassNames[0])).toBeTruthy();
}
if (iconTexts[0] !== undefined) {
expect(wrapper.find('.ant-typography-copy').at(0).text()).toBe(iconTexts[0]);
}
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
if (tooltipTexts[0] !== undefined) {
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltipTexts[0]);
}
if (tooltipLength !== undefined) {
expect(wrapper.find('.ant-tooltip-inner').length).toBe(tooltipLength);
}
wrapper.find('.ant-typography-copy').first().simulate('click');
jest.useRealTimers();
if (iconClassNames[1] !== undefined) {
expect(wrapper.exists(iconClassNames[1])).toBeTruthy();
}
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
wrapper.update();
wrapper.find('.ant-typography-copy').first().simulate('mouseenter');
if (tooltipTexts[1] !== undefined) {
expect(wrapper.find('.ant-tooltip-inner').text()).toBe(tooltipTexts[1]);
}
if (iconTexts[1] !== undefined) {
expect(wrapper.find('.ant-typography-copy').at(0).text()).toBe(iconTexts[1]);
}
jest.useFakeTimers();
wrapper.find('.ant-typography-copy').first().simulate('click');
jest.runAllTimers();
wrapper.update();
wrapper.unmount();
jest.useRealTimers();
});
}
const dom = (
<>
<span>1</span>2
</>
);
const dom2 = (
<>
<span>3</span>4
</>
);
const copy = '.anticon-copy';
const check = '.anticon-check';
copyTest({
name: 'icon basic copy',
iconClassNames: [copy, check],
tooltipTexts: ['Copy', 'Copied'],
});
copyTest({ name: 'icon true', icon: true, iconClassNames: [copy, check] });
copyTest({ name: 'icon two true', icon: [true, true], iconClassNames: [copy, check] });
copyTest({ name: 'icon false', icon: false, iconClassNames: [copy, check] });
copyTest({ name: 'icon custom text', icon: ['a', 'b'], iconTexts: ['a', 'b'] });
copyTest({ name: 'icon custom element', icon: [dom, dom2], iconTexts: ['12', '34'] });
copyTest({
name: 'icon custom icon',
icon: <SmileOutlined />,
iconClassNames: ['.anticon-smile', check],
});
copyTest({
name: 'icon custom icon2',
icon: [<SmileOutlined key="a" />, <LikeOutlined key="b" />],
iconClassNames: ['.anticon-smile', '.anticon-like'],
});
copyTest({
name: 'icon custom icon3',
icon: [
<>
<SmileOutlined />
<SmileOutlined />
</>,
<LikeOutlined key="b" />,
],
iconClassNames: ['.anticon-smile', '.anticon-like'],
});
copyTest({
name: 'icon custom icon4',
icon: (
<>
<SmileOutlined />
<LikeOutlined />
</>
),
iconClassNames: ['.anticon-smile', check],
});
copyTest({
name: 'icon custom icon5',
icon: (
<>
<SmileOutlined />
<LikeOutlined />
</>
),
iconClassNames: ['.anticon-like', check],
});
copyTest({
name: 'tooltips true',
tooltips: true,
tooltipLength: 1,
tooltipTexts: ['Copy', 'Copied'],
});
copyTest({ name: 'tooltips false', tooltips: false, tooltipLength: 0 });
copyTest({
name: 'tooltips custom text',
tooltips: ['a', 'b'],
tooltipLength: 1,
tooltipTexts: ['a', 'b'],
});
copyTest({
name: 'tooltips custom element ',
tooltips: [dom, dom2],
tooltipTexts: ['12', '34'],
});
copyTest({
name: 'tooltips first empty',
tooltips: ['', 'xxx'],
tooltipLength: 0,
});
copyTest({
name: 'tooltips first empty 2',
tooltips: [''],
tooltipLength: 0,
});
copyTest({
name: 'tooltips true true',
tooltips: [true, true],
tooltipTexts: ['Copy', 'Copied'],
});
copyTest({
name: 'tooltips true false',
tooltips: [true, false],
tooltipTexts: ['Copy', ''],
});
copyTest({
name: 'tooltips false true',
tooltips: [false, true],
tooltipLength: 0,
});
});
});
});
Loading…
Cancel
Save