-
Notifications
You must be signed in to change notification settings - Fork 227
/
ChipSet.test.tsx
397 lines (359 loc) · 12.8 KB
/
ChipSet.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
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
import * as React from 'react';
import {assert} from 'chai';
import * as td from 'testdouble';
import {shallow, mount} from 'enzyme';
import ChipSet from '../../../packages/chips/ChipSet';
import {Chip, ChipProps} from '../../../packages/chips/index'; // eslint-disable-line no-unused-vars
import ChipCheckmark from '../../../packages/chips/ChipCheckmark';
import {coerceForTesting} from '../helpers/types';
suite('ChipSet');
test('creates foundation', () => {
const wrapper = mount<ChipSet>(<ChipSet><Chip /></ChipSet>);
assert.exists(wrapper.state().foundation);
});
test('updates state.selectedChipIds when the props.selectedChipIds change', () => {
const wrapper = shallow<ChipSet>(
<ChipSet>
<div id='1' />
</ChipSet>
);
const selectedChipIds = ['1'];
wrapper.setProps({selectedChipIds});
assert.isTrue(wrapper.state().selectedChipIds.indexOf('1') > -1);
});
test('filter classname is added if is filter variant', () => {
const wrapper = shallow(
<ChipSet filter>
<div id='1' />
</ChipSet>
);
wrapper.hasClass('mdc-chip-set--filter');
});
test('choice classname is added if is choice variant', () => {
const wrapper = shallow(
<ChipSet choice>
<div id='1' />
</ChipSet>
);
wrapper.hasClass('mdc-chip-set--choice');
});
test('input classname is added if is input variant', () => {
const wrapper = shallow(
<ChipSet input>
<div id='1' />
</ChipSet>
);
wrapper.hasClass('mdc-chip-set--input');
});
test('#adapter.hasClass returns true if component contains class', () => {
const wrapper = shallow<ChipSet>(
<ChipSet className='test-class-name'>
<div id='1' />
</ChipSet>
);
assert.isTrue(wrapper.instance().adapter.hasClass('test-class-name'));
});
test('#adapter.hasClass returns false if component does not contains class', () => {
const wrapper = shallow<ChipSet>(
<ChipSet>
<div id='1' />
</ChipSet>
);
assert.isFalse(wrapper.instance().adapter.hasClass('test-class-name'));
});
test('#adapter.setSelected adds selectedChipId to state', () => {
const getSelectedChipIds = td.func();
const handleSelect = coerceForTesting<(selectedChipIds: string[]) => void>(td.func());
const foundation = {getSelectedChipIds};
const wrapper = shallow<ChipSet>(
<ChipSet handleSelect={handleSelect}>
<div id='1' />
</ChipSet>
);
wrapper.setState({foundation});
td.when(getSelectedChipIds()).thenReturn(['1']);
wrapper.instance().adapter.setSelected();
assert.isTrue(wrapper.state().selectedChipIds.indexOf('1') > -1);
td.verify(handleSelect(['1']), {times: 1});
td.verify(getSelectedChipIds(), {times: 1});
});
// this is bad
test('#adapter.setSelected removes selectedChipId from state', () => {
const wrapper = shallow<ChipSet>(
<ChipSet>
<div id='1' />
</ChipSet>
);
wrapper.setState({selectedChipIds: ['1']});
wrapper.instance().adapter.setSelected();
assert.isFalse(wrapper.state().selectedChipIds.indexOf('1') > -1);
});
test(
'#foundation.select is called when #initChipSelection is called and ' +
'state.selectedChipIds has a selected Id',
() => {
const wrapper = shallow<ChipSet>(
<ChipSet>
<div id='1' />
</ChipSet>
);
wrapper.state().foundation.select = td.func();
const selectedChipIds = ['1'];
wrapper.setState({selectedChipIds});
wrapper.instance().initChipSelection();
td.verify(wrapper.state().foundation.select('1'), {times: 1});
}
);
test('#handleSelect calls foundation.handleChipSelection with selectedChipId and selected=true', () => {
const handleChipSelection = td.func();
const foundation = {handleChipSelection};
const wrapper = shallow<ChipSet>(
<ChipSet>
<div id='1' />
</ChipSet>
);
wrapper.setState({foundation});
wrapper.instance().handleSelect('1', true);
td.verify(handleChipSelection('1', true), {times: 1});
});
test('#handleSelect calls foundation.handleChipSelection with selectedChipId and selected=false', () => {
const handleChipSelection = td.func();
const foundation = {handleChipSelection};
const wrapper = shallow<ChipSet>(
<ChipSet>
<div id='1' />
</ChipSet>
);
wrapper.setState({foundation});
wrapper.instance().handleSelect('1', false);
td.verify(handleChipSelection('1', false), {times: 1});
});
test('#handleSelect calls updates parent component with selectedChipIds correctly for filter chips', () => {
type HandleSelectMethod = (prevSelectedChipIds: string[], selectedChipId: string[]) => void;
type Props = {
handleSelect: HandleSelectMethod
};
type State = {selectedChipIds: string[]};
class TestChipParentComponent extends React.Component<Props, State> {
state = {selectedChipIds: []};
componentDidUpdate(_: Props, pState: State) {
if (pState.selectedChipIds !== this.state.selectedChipIds) {
this.props.handleSelect(pState.selectedChipIds, this.state.selectedChipIds);
}
}
handleSelect = (selectedChipIds: string[]) => {
this.setState({selectedChipIds});
}
render() {
const Chip1 = <Chip id='chip1'/>;
const Chip2 = <Chip id='chip2'/>;
return (
<ChipSet
filter
selectedChipIds={this.state.selectedChipIds}
handleSelect={this.handleSelect}
>
{Chip1}
{Chip2}
</ChipSet>
);
}
}
const handleChipSelection = coerceForTesting<HandleSelectMethod>(td.func());
const wrapper = mount<TestChipParentComponent>(
<TestChipParentComponent handleSelect={handleChipSelection}/>
);
const chipSet = wrapper.childAt(0);
chipSet.children().children().first().children().simulate('click');
td.verify(handleChipSelection([], ['chip1']), {times: 1});
chipSet.children().children().last().children().simulate('click');
td.verify(handleChipSelection(['chip1'], ['chip1', 'chip2']), {times: 1});
});
test('#handleInteraction calls #foundation.handleChipInteraction', () => {
const handleChipInteraction = td.func();
const foundation = {handleChipInteraction};
const wrapper = shallow<ChipSet>(
<ChipSet>
<div id='1' />
</ChipSet>
);
wrapper.setState({foundation});
wrapper.instance().handleInteraction('1');
td.verify(handleChipInteraction('1'), {times: 1});
});
test('#handleRemove calls foundation.handleChipRemoval with chipId', () => {
const handleChipRemoval = td.func();
const foundation = {handleChipRemoval};
const wrapper = shallow<ChipSet>(
<ChipSet>
<div id='1' />
</ChipSet>
);
wrapper.setState({foundation});
wrapper.instance().handleRemove('1');
td.verify(handleChipRemoval('1'), {times: 1});
});
test('#removeChip does not call #props.updateChips if there are no chips', () => {
const updateChips = coerceForTesting<(chips: Partial<ChipProps>[]) => void>(td.func());
const wrapper = shallow<ChipSet>(<ChipSet updateChips={updateChips} />);
wrapper.instance().removeChip(td.matchers.isA(Number));
td.verify(updateChips(td.matchers.anything()), {times: 0});
});
test('#removeChip calls #props.updateChips with array of remove chip', () => {
const updateChips = coerceForTesting<(chips: Partial<ChipProps>[]) => void>(td.func());
const wrapper = shallow<ChipSet>(
<ChipSet updateChips={updateChips}>
<Chip id='1' />
</ChipSet>
);
wrapper.instance().removeChip('1');
td.verify(updateChips([]), {times: 1});
});
test('#removeChip calls #props.updateChips with array of removed chip', () => {
const updateChips = coerceForTesting<(chips: Partial<ChipProps>[]) => void>(td.func());
const wrapper = shallow<ChipSet>(
<ChipSet updateChips={updateChips}>
<Chip id='1' />
</ChipSet>
);
wrapper.instance().removeChip('1');
td.verify(updateChips([]), {times: 1});
});
test('#removeChip calls #props.updateChips with array of remaining chips', () => {
const updateChips = coerceForTesting<(chips: Partial<ChipProps>[]) => void>(td.func());
const wrapper = shallow<ChipSet>(
<ChipSet updateChips={updateChips}>
<Chip id='1' />
<Chip id='2' />
</ChipSet>
);
wrapper.instance().removeChip('1');
td.verify(updateChips([td.matchers.contains({id: '2'})]), {times: 1});
});
test('#setCheckmarkWidth sets checkmark width', () => {
const wrapper = shallow<ChipSet>(<ChipSet><Chip /></ChipSet>);
wrapper.instance().setCheckmarkWidth(coerceForTesting<ChipCheckmark>({width: 20}));
assert.equal(wrapper.instance().checkmarkWidth, 20);
});
test('#setCheckmarkWidth does not set checkmark width if checkmark width is already set', () => {
const wrapper = shallow<ChipSet>(<ChipSet><Chip /></ChipSet>);
wrapper.instance().checkmarkWidth = 20;
wrapper.instance().setCheckmarkWidth(coerceForTesting<ChipCheckmark>({width: 40}));
assert.equal(wrapper.instance().checkmarkWidth, 20);
});
test('#setCheckmarkWidth does not set checkmark width if checkmark is null', () => {
const wrapper = shallow<ChipSet>(<ChipSet><Chip id='1' /></ChipSet>);
wrapper.instance().setCheckmarkWidth(null);
assert.equal(wrapper.instance().checkmarkWidth, 0);
});
test('#computeBoundingRect returns width and height', () => {
const wrapper = shallow<ChipSet>(<ChipSet><Chip /></ChipSet>);
const chipWidth = 20;
const chipHeight = 50;
const chipElement = coerceForTesting<HTMLDivElement>({
getBoundingClientRect: () => ({width: chipWidth, height: chipHeight}),
});
const {height, width} = wrapper.instance().computeBoundingRect(chipElement);
assert.equal(height, chipHeight);
assert.equal(width, chipWidth);
});
test('#computeBoundingRect returns width and height', () => {
const wrapper = shallow<ChipSet>(<ChipSet><Chip /></ChipSet>);
const chipWidth = 20;
const chipHeight = 50;
wrapper.instance().checkmarkWidth = 20;
const chipElement = coerceForTesting<HTMLDivElement>({
getBoundingClientRect: () => ({width: chipWidth, height: chipHeight}),
});
const {height, width} = wrapper.instance().computeBoundingRect(chipElement);
assert.equal(height, chipHeight);
assert.equal(width, chipWidth + 20);
});
test('chip is rendered with selected prop as false', () => {
const wrapper = mount(
<ChipSet>
<Chip id='1' />
</ChipSet>
);
const chip = wrapper.children().props().children[0];
assert.isFalse(chip.props.selected);
});
test('chip is rendered with selected prop as true', () => {
const wrapper = mount(
<ChipSet>
<Chip id='1' />
</ChipSet>
);
wrapper.setState({selectedChipIds: ['1']});
const chip = wrapper.children().props().children[0];
assert.isTrue(chip.props.selected);
});
test('#chip.props.handleSelect calls #foundation.handleChipSelection', () => {
const foundation = {handleChipSelection: td.func()};
const wrapper = mount(
<ChipSet>
<Chip id='1' />
</ChipSet>
);
wrapper.setState({foundation});
const chip = wrapper.children().props().children[0];
chip.props.handleSelect('1', false);
td.verify(foundation.handleChipSelection('1', false), {times: 1});
});
test('chip is rendered with handleRemove method', () => {
const wrapper = mount<ChipSet>(<ChipSet><Chip /></ChipSet>);
wrapper.instance().handleRemove = coerceForTesting<(chipId: string) => void>(td.func());
wrapper.setProps({children: <Chip id='1' />});
const chip = wrapper.children().props().children[0];
chip.props.handleRemove('1');
td.verify(wrapper.instance().handleRemove('1'), {times: 1});
});
test('chip is rendered ChipCheckmark if is filter variants', () => {
const wrapper = mount(
<ChipSet filter>
<Chip id='1' />
</ChipSet>
);
const chip = wrapper.children().props().children[0];
assert.equal(chip.props.chipCheckmark.type, ChipCheckmark);
});
test('chip is rendered ChipCheckmark if is not filter variants', () => {
const wrapper = mount(
<ChipSet>
<Chip id='1' />
</ChipSet>
);
const chip = wrapper.children().props().children[0];
assert.equal(chip.props.chipCheckmark, null);
});
test('chip is rendered computeBoundingRect method prop if is filter variant', () => {
const wrapper = mount(
<ChipSet filter>
<Chip id='1' />
</ChipSet>
);
const chip = wrapper.children().props().children[0];
const chipElement = {getBoundingClientRect: td.func()};
td.when(chipElement.getBoundingClientRect()).thenReturn({
height: 1,
width: 1,
});
chip.props.computeBoundingRect(chipElement);
td.verify(chipElement.getBoundingClientRect(), {times: 1});
});
test('chip is rendered with computeBoundingRect method prop if is not filter variant', () => {
const wrapper = mount(
<ChipSet>
<Chip id='1' />
</ChipSet>
);
const chip = wrapper.children().props().children[0];
assert.equal(chip.props.computeBoundingRect, null);
});
test('#componentWillUnmount destroys foundation', () => {
const wrapper = shallow<ChipSet>(<ChipSet><Chip /></ChipSet>);
const foundation = wrapper.state().foundation;
foundation.destroy = td.func();
wrapper.unmount();
td.verify(foundation.destroy());
});