-
-
Notifications
You must be signed in to change notification settings - Fork 46.6k
/
type.test.tsx
308 lines (275 loc) · 9.68 KB
/
type.test.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
import React, { Component } from 'react';
import { mount, render } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { SearchOutlined } from '@ant-design/icons';
import Button from '..';
import ConfigProvider from '../../config-provider';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { sleep } from '../../../tests/utils';
import { SizeType } from '../../config-provider/SizeContext';
describe('Button', () => {
mountTest(Button);
mountTest(() => <Button size="large" />);
mountTest(() => <Button size="small" />);
mountTest(Button.Group);
mountTest(() => <Button.Group size="large" />);
mountTest(() => <Button.Group size="small" />);
mountTest(() => <Button.Group size="middle" />);
rtlTest(Button);
rtlTest(() => <Button size="large" />);
rtlTest(() => <Button size="small" />);
rtlTest(Button.Group);
rtlTest(() => <Button.Group size="large" />);
rtlTest(() => <Button.Group size="small" />);
rtlTest(() => <Button.Group size="middle" />);
it('renders correctly', () => {
expect(<Button>Follow</Button>).toMatchRenderedSnapshot();
});
it('mount correctly', () => {
expect(() => mount(<Button>Follow</Button>)).not.toThrow();
});
it('warns if size is wrong', () => {
const mockWarn = jest.fn();
jest.spyOn(console, 'warn').mockImplementation(mockWarn);
const size = ('who am I' as any) as SizeType;
render(<Button.Group size={size} />);
expect(mockWarn).toHaveBeenCalledTimes(1);
expect(mockWarn.mock.calls[0][0]).toMatchObject({
message: 'unreachable case: "who am I"',
});
});
it('renders Chinese characters correctly', () => {
expect(<Button>按钮</Button>).toMatchRenderedSnapshot();
// should not insert space when there is icon
expect(<Button icon={<SearchOutlined />}>按钮</Button>).toMatchRenderedSnapshot();
// should not insert space when there is icon
expect(
<Button>
<SearchOutlined />
按钮
</Button>,
).toMatchRenderedSnapshot();
// should not insert space when there is icon
expect(<Button icon={<SearchOutlined />}>按钮</Button>).toMatchRenderedSnapshot();
// should not insert space when there is icon while loading
expect(
<Button icon={<SearchOutlined />} loading>
按钮
</Button>,
).toMatchRenderedSnapshot();
// should insert space while loading
expect(<Button loading>按钮</Button>).toMatchRenderedSnapshot();
// should insert space while only one nested element
expect(
<Button>
<span>按钮</span>
</Button>,
).toMatchRenderedSnapshot();
});
it('renders Chinese characters correctly in HOC', () => {
const Text = ({ children }: { children: React.ReactNode }) => <span>{children}</span>;
const wrapper = mount(
<Button>
<Text>按钮</Text>
</Button>,
);
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(true);
wrapper.setProps({
children: <Text>大按钮</Text>,
});
wrapper.update();
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(false);
wrapper.setProps({
children: <Text>按钮</Text>,
});
wrapper.update();
expect(wrapper.find('.ant-btn').hasClass('ant-btn-two-chinese-chars')).toBe(true);
});
// https://github.com/ant-design/ant-design/issues/18118
it('should not insert space to link or text button', () => {
const wrapper1 = mount(<Button type="link">按钮</Button>);
expect(wrapper1.text()).toBe('按钮');
const wrapper2 = mount(<Button type="text">按钮</Button>);
expect(wrapper2.text()).toBe('按钮');
});
it('should render empty button without errors', () => {
const wrapper = mount(
<Button>
{null}
{undefined}
</Button>,
);
expect(wrapper).toMatchSnapshot();
});
it('have static property for type detecting', () => {
const wrapper = mount(<Button>Button Text</Button>);
expect((wrapper.type() as any).__ANT_BUTTON).toBe(true);
});
it('should change loading state instantly by default', () => {
class DefaultButton extends Component {
state = {
loading: false,
};
enterLoading = () => {
this.setState({ loading: true });
};
render() {
const { loading } = this.state;
return (
<Button loading={loading} onClick={this.enterLoading}>
Button
</Button>
);
}
}
const wrapper = mount(<DefaultButton />);
wrapper.simulate('click');
expect(wrapper.find('.ant-btn-loading').length).toBe(1);
});
it('should change loading state with delay', () => {
class DefaultButton extends Component {
state = {
loading: false,
};
enterLoading = () => {
this.setState({ loading: { delay: 1000 } });
};
render() {
const { loading } = this.state;
return (
<Button loading={loading} onClick={this.enterLoading}>
Button
</Button>
);
}
}
const wrapper = mount(<DefaultButton />);
wrapper.simulate('click');
expect(wrapper.hasClass('ant-btn-loading')).toBe(false);
});
it('reset when loading back of delay', () => {
jest.useFakeTimers();
const wrapper = mount(<Button loading={{ delay: 1000 }} />);
wrapper.update();
wrapper.setProps({ loading: { delay: 2000 } });
wrapper.update();
wrapper.setProps({ loading: false });
act(() => {
jest.runAllTimers();
wrapper.update();
});
expect(wrapper.find('.ant-btn-loading')).toHaveLength(0);
jest.useRealTimers();
});
it('should not clickable when button is loading', () => {
const onClick = jest.fn();
const wrapper = mount(
<Button loading onClick={onClick}>
button
</Button>,
);
wrapper.simulate('click');
expect(onClick).not.toHaveBeenCalledWith();
});
it('should support link button', () => {
const wrapper = mount(
<Button target="_blank" href="https://ant.design">
link button
</Button>,
);
expect(wrapper.render()).toMatchSnapshot();
});
it('fixbug renders {0} , 0 and {false}', () => {
expect(<Button>{0}</Button>).toMatchRenderedSnapshot();
expect(<Button>0</Button>).toMatchRenderedSnapshot();
expect(<Button>{false}</Button>).toMatchRenderedSnapshot();
});
it('should have click wave effect', async () => {
const wrapper = mount(<Button type="primary">button</Button>);
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
await sleep(0);
expect(
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
).toBe(true);
});
it('should not have click wave effect for link type button', async () => {
const wrapper = mount(<Button type="link">button</Button>);
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
await sleep(0);
expect(
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
).toBe(false);
});
it('should not have click wave effect for text type button', async () => {
const wrapper = mount(<Button type="link">button</Button>);
wrapper.find('.ant-btn').getDOMNode<HTMLButtonElement>().click();
await sleep(0);
expect(
wrapper.find('.ant-btn').getDOMNode().hasAttribute('ant-click-animating-without-extra-node'),
).toBe(false);
});
it('should not render as link button when href is undefined', async () => {
const wrapper = mount(
<Button type="primary" href={undefined}>
button
</Button>,
);
expect(wrapper.render()).toMatchSnapshot();
});
// https://github.com/ant-design/ant-design/issues/15342
it('should merge text if children using variable', () => {
const wrapper = mount(
<Button>
{/* eslint-disable-next-line react/jsx-curly-brace-presence */}
This {'is'} a test {1}
</Button>,
);
expect(wrapper.render()).toMatchSnapshot();
});
it('should support to change loading', async () => {
const wrapper = mount(<Button>Button</Button>);
wrapper.setProps({ loading: true });
wrapper.update();
expect(wrapper.find('.ant-btn-loading').length).toBe(1);
wrapper.setProps({ loading: false });
wrapper.update();
expect(wrapper.find('.ant-btn-loading').length).toBe(0);
wrapper.setProps({ loading: { delay: 50 } });
wrapper.update();
expect(wrapper.find('.ant-btn-loading').length).toBe(0);
await sleep(50);
wrapper.update();
expect(wrapper.find('.ant-btn-loading').length).toBe(1);
wrapper.setProps({ loading: false });
await sleep(50);
wrapper.update();
expect(wrapper.find('.ant-btn-loading').length).toBe(0);
expect(() => {
wrapper.unmount();
}).not.toThrow();
});
it('should warning when pass a string as icon props', () => {
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(<Button type="primary" icon="ab" />);
expect(warnSpy).not.toHaveBeenCalled();
mount(<Button type="primary" icon="search" />);
expect(warnSpy).toHaveBeenCalledWith(
`Warning: [antd: Button] \`icon\` is using ReactNode instead of string naming in v4. Please check \`search\` at https://ant.design/components/icon`,
);
warnSpy.mockRestore();
});
it('skip check 2 words when ConfigProvider disable this', () => {
const wrapper = mount(
<ConfigProvider autoInsertSpaceInButton={false}>
<Button>test</Button>
</ConfigProvider>,
);
const btn = wrapper.find('button').instance();
Object.defineProperty(btn, 'textContent', {
get() {
throw new Error('Should not called!!!');
},
});
});
});