merge master

This commit is contained in:
zombiej 2019-09-29 18:11:24 +08:00
commit 867910e6f4
14 changed files with 224 additions and 151 deletions

View File

@ -9,8 +9,6 @@ import triggerEvent from '../triggerEvent';
import Wave from '../wave';
import TransButton from '../transButton';
import openAnimation from '../openAnimation';
import ResizeObserver from '../resizeObserver';
import { spyElementPrototype } from '../../__tests__/util/domHook';
describe('Test utils function', () => {
beforeAll(() => {
@ -223,47 +221,4 @@ describe('Test utils function', () => {
expect(done).toHaveBeenCalled();
});
});
describe('ResizeObserver', () => {
let domMock;
beforeAll(() => {
domMock = spyElementPrototype(HTMLDivElement, 'getBoundingClientRect', () => {
return {
width: 1128 + Math.random(),
height: 903 + Math.random(),
};
});
});
afterAll(() => {
domMock.mockRestore();
});
it('should not trigger `onResize` if size shaking', () => {
const onResize = jest.fn();
let divNode;
const wrapper = mount(
<ResizeObserver onResize={onResize}>
<div
ref={node => {
divNode = node;
}}
/>
</ResizeObserver>,
);
// First trigger
wrapper.instance().onResize([{ target: divNode }]);
onResize.mockReset();
// Repeat trigger should not trigger outer `onResize` with shaking
for (let i = 0; i < 10; i += 1) {
wrapper.instance().onResize([{ target: divNode }]);
}
expect(onResize).not.toHaveBeenCalled();
});
});
});

View File

@ -1,91 +0,0 @@
import * as React from 'react';
import { findDOMNode } from 'react-dom';
import ResizeObserver from 'resize-observer-polyfill';
type DomElement = Element | null;
interface ResizeObserverProps {
children?: React.ReactNode;
disabled?: boolean;
onResize?: () => void;
}
interface ResizeObserverState {
height: number;
width: number;
}
class ReactResizeObserver extends React.Component<ResizeObserverProps, ResizeObserverState> {
resizeObserver: ResizeObserver | null = null;
state = {
width: 0,
height: 0,
};
componentDidMount() {
this.onComponentUpdated();
}
componentDidUpdate() {
this.onComponentUpdated();
}
componentWillUnmount() {
this.destroyObserver();
}
onComponentUpdated() {
const { disabled } = this.props;
const element = findDOMNode(this) as DomElement;
if (!this.resizeObserver && !disabled && element) {
// Add resize observer
this.resizeObserver = new ResizeObserver(this.onResize);
this.resizeObserver.observe(element);
} else if (disabled) {
// Remove resize observer
this.destroyObserver();
}
}
onResize: ResizeObserverCallback = (entries: ResizeObserverEntry[]) => {
const { onResize } = this.props;
const { target } = entries[0];
const { width, height } = target.getBoundingClientRect();
/**
* Resize observer trigger when content size changed.
* In most case we just care about element size,
* let's use `boundary` instead of `contentRect` here to avoid shaking.
*/
const fixedWidth = Math.floor(width);
const fixedHeight = Math.floor(height);
if (this.state.width !== fixedWidth || this.state.height !== fixedHeight) {
this.setState({
width: fixedWidth,
height: fixedHeight,
});
if (onResize) {
onResize();
}
}
};
destroyObserver() {
if (this.resizeObserver) {
this.resizeObserver.disconnect();
this.resizeObserver = null;
}
}
render() {
const { children = null } = this.props;
return children;
}
}
export default ReactResizeObserver;

View File

@ -182,7 +182,7 @@ describe('Affix Render', () => {
// Mock trigger resize
updateCalled.mockReset();
wrapper
.find('ReactResizeObserver')
.find('ResizeObserver')
.at(index)
.instance()
.onResize([{ target: { getBoundingClientRect: () => ({ width: 99, height: 99 }) } }]);

View File

@ -2,9 +2,9 @@ import * as React from 'react';
import { polyfill } from 'react-lifecycles-compat';
import classNames from 'classnames';
import omit from 'omit.js';
import ResizeObserver from 'rc-resize-observer';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
import ResizeObserver from '../_util/resizeObserver';
import warning from '../_util/warning';
import {
@ -35,6 +35,7 @@ export interface AffixProps {
target?: () => Window | HTMLElement | null;
prefixCls?: string;
className?: string;
children: React.ReactElement;
}
enum AffixStatus {

View File

@ -2,9 +2,9 @@ import * as React from 'react';
import omit from 'omit.js';
import classNames from 'classnames';
import { polyfill } from 'react-lifecycles-compat';
import ResizeObserver from 'rc-resize-observer';
import calculateNodeHeight from './calculateNodeHeight';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import ResizeObserver from '../_util/resizeObserver';
import raf from '../_util/raf';
export interface AutoSizeType {

View File

@ -414,7 +414,7 @@ exports[`TextArea should support disabled 1`] = `
<TextArea
disabled={true}
>
<ReactResizeObserver
<ResizeObserver
disabled={true}
onResize={[Function]}
>
@ -425,7 +425,7 @@ exports[`TextArea should support disabled 1`] = `
onKeyDown={[Function]}
style={Object {}}
/>
</ReactResizeObserver>
</ResizeObserver>
</TextArea>
`;
@ -433,7 +433,7 @@ exports[`TextArea should support maxLength 1`] = `
<TextArea
maxLength={10}
>
<ReactResizeObserver
<ResizeObserver
disabled={true}
onResize={[Function]}
>
@ -444,6 +444,6 @@ exports[`TextArea should support maxLength 1`] = `
onKeyDown={[Function]}
style={Object {}}
/>
</ReactResizeObserver>
</ResizeObserver>
</TextArea>
`;

View File

@ -5,12 +5,11 @@ import toArray from 'rc-util/lib/Children/toArray';
import copy from 'copy-to-clipboard';
import omit from 'omit.js';
import { Edit, Check, Copy } from '@ant-design/icons';
import ResizeObserver from 'rc-resize-observer';
import { withConfigConsumer, ConfigConsumerProps, configConsumerProps } from '../config-provider';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import warning from '../_util/warning';
import TransButton from '../_util/transButton';
import ResizeObserver from '../_util/resizeObserver';
import raf from '../_util/raf';
import isStyleSupport from '../_util/styleChecker';
import Tooltip from '../tooltip';

View File

@ -98,7 +98,7 @@ class Upload extends React.Component<UploadProps, UploadState> {
fileList: nextFileList,
});
// fix ie progress
if (!(window as any).FormData) {
if (!(window as any).File || process.env.TEST_IE) {
this.autoUpdateProgress(0, targetItem);
}
};

View File

@ -953,3 +953,99 @@ exports[`Upload List should non-image format file preview 1`] = `
</div>
</span>
`;
exports[`Upload List should support showRemoveIcon and showPreviewIcon 1`] = `
<span
class=""
>
<div
class="ant-upload ant-upload-select ant-upload-select-picture"
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display: none;"
type="file"
/>
<button
type="button"
>
upload
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-picture"
>
<div
class="ant-upload-list-item ant-upload-list-item-uploading"
>
<div
class="ant-upload-list-item-info"
>
<span>
<a
class="ant-upload-list-item-thumbnail"
href="https://cdn.xxx.com/aaa"
rel="noopener noreferrer"
target="_blank"
>
<img
alt="image"
class="ant-upload-list-item-image"
src="https://cdn.xxx.com/aaa"
/>
</a>
<a
class="ant-upload-list-item-name"
href="https://cdn.xxx.com/aaa"
rel="noopener noreferrer"
target="_blank"
title="image"
>
image
</a>
</span>
</div>
<div
class="ant-upload-list-item-progress"
/>
</div>
<div
class="ant-upload-list-item ant-upload-list-item-done"
>
<div
class="ant-upload-list-item-info"
>
<span>
<a
class="ant-upload-list-item-thumbnail"
href="https://cdn.xxx.com/aaa"
rel="noopener noreferrer"
target="_blank"
>
<img
alt="image"
class="ant-upload-list-item-image"
src="https://cdn.xxx.com/aaa"
/>
</a>
<a
class="ant-upload-list-item-name"
href="https://cdn.xxx.com/aaa"
rel="noopener noreferrer"
target="_blank"
title="image"
>
image
</a>
</span>
</div>
</div>
</div>
</span>
`;

View File

@ -0,0 +1,28 @@
/* eslint-disable react/no-string-refs, react/prefer-es6-class */
import React from 'react';
import { mount } from 'enzyme';
import Upload from '..';
import { setup, teardown } from './mock';
import mountTest from '../../../tests/shared/mountTest';
describe('Upload.Dragger', () => {
mountTest(Upload.Dragger);
beforeEach(() => setup());
afterEach(() => teardown());
it('support drag file with over style', () => {
const wrapper = mount(
<Upload.Dragger action="http://upload.com">
<div />
</Upload.Dragger>,
);
wrapper.find('.ant-upload-drag-container').simulate('dragover', {
target: {
files: [{ file: 'foo.png' }],
},
});
expect(wrapper.find('.ant-upload-drag').hasClass('ant-upload-drag-hover')).toBe(true);
});
});

View File

@ -10,7 +10,6 @@ import mountTest from '../../../tests/shared/mountTest';
describe('Upload', () => {
mountTest(Upload);
mountTest(Upload.Dragger);
beforeEach(() => setup());
afterEach(() => teardown());
@ -62,6 +61,61 @@ describe('Upload', () => {
});
});
it('should update progress in IE', done => {
const originSetInterval = window.setInterval;
process.env.TEST_IE = true;
Object.defineProperty(window, 'setInterval', {
value: fn => fn(),
});
const props = {
action: 'http://upload.com',
onChange: ({ file }) => {
if (file.status !== 'uploading') {
process.env.TEST_IE = undefined;
Object.defineProperty(window, 'setInterval', {
value: originSetInterval,
});
done();
}
},
};
const wrapper = mount(
<Upload {...props}>
<button type="button">upload</button>
</Upload>,
);
wrapper.find('input').simulate('change', {
target: {
files: [{ file: 'foo.png' }],
},
});
});
it('beforeUpload can be falsy', done => {
const props = {
action: 'http://upload.com',
beforeUpload: false,
onChange: ({ file }) => {
if (file.status !== 'uploading') {
done();
}
},
};
const wrapper = mount(
<Upload {...props}>
<button type="button">upload</button>
</Upload>,
);
wrapper.find('input').simulate('change', {
target: {
files: [{ file: 'foo.png' }],
},
});
});
it('upload promise return file in beforeUpload', done => {
const data = jest.fn();
const props = {

View File

@ -366,6 +366,37 @@ describe('Upload List', () => {
expect(wrapper.render()).toMatchSnapshot();
});
it('should support showRemoveIcon and showPreviewIcon', () => {
const list = [
{
name: 'image',
status: 'uploading',
uid: '-4',
url: 'https://cdn.xxx.com/aaa',
},
{
name: 'image',
status: 'done',
uid: '-5',
url: 'https://cdn.xxx.com/aaa',
},
];
const wrapper = mount(
<Upload
listType="picture"
defaultFileList={list}
showUploadList={{
showRemoveIcon: false,
showPreviewIcon: false,
}}
>
<button type="button">upload</button>
</Upload>,
);
expect(wrapper.render()).toMatchSnapshot();
});
// https://github.com/ant-design/ant-design/issues/7762
it('work with form validation', async () => {
let formRef;

View File

@ -58,16 +58,15 @@ export function removeFileItem(file: UploadFile, fileList: UploadFile[]) {
}
// ==================== Default Image Preview ====================
const extname = (url: string) => {
if (!url) {
return '';
}
const extname = (url: string = '') => {
const temp = url.split('/');
const filename = temp[temp.length - 1];
const filenameWithoutSuffix = filename.split(/#|\?/)[0];
return (/\.[^./\\]*$/.exec(filenameWithoutSuffix) || [''])[0];
};
const isImageFileType = (type: string): boolean => !!type && type.indexOf('image/') === 0;
export const isImageUrl = (file: UploadFile): boolean => {
if (isImageFileType(file.type)) {
return true;

View File

@ -122,6 +122,7 @@
"rc-pagination": "~1.20.5",
"rc-progress": "~2.5.0",
"rc-rate": "~2.5.0",
"rc-resize-observer": "^0.1.0",
"rc-select": "~10.0.0-alpha.27",
"rc-slider": "~8.6.11",
"rc-steps": "~3.5.0",