@atlaskit/code 15.6.8 → 15.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1000 +0,0 @@
1
- // eslint-disable-file
2
- export const thousandLineExample = `// Adapted excerpt of https://github.com/JedWatson/react-select/blob/master/packages/react-select/src/__tests__/Select.test.tsx
3
- import React, { KeyboardEvent } from 'react';
4
- import { render, fireEvent, EventType } from '@testing-library/react';
5
- import userEvent from '@testing-library/user-event';
6
- import cases from 'jest-in-case';
7
-
8
- import {
9
- OPTIONS,
10
- OPTIONS_ACCENTED,
11
- OPTIONS_NUMBER_VALUE,
12
- OPTIONS_BOOLEAN_VALUE,
13
- OPTIONS_DISABLED,
14
- Option,
15
- OptionNumberValue,
16
- OptionBooleanValue,
17
- } from './constants';
18
- import Select, { FormatOptionLabelMeta } from '../Select';
19
- import { FilterOptionOption } from '../filters';
20
-
21
- import { matchers } from '@emotion/jest';
22
- import { AriaLiveMessages } from '../accessibility';
23
- import { noop } from '../utils';
24
- import { GroupBase } from '../types';
25
-
26
- expect.extend(matchers);
27
-
28
- interface BasicProps {
29
- readonly className: string;
30
- readonly classNamePrefix: string;
31
- readonly onChange: () => void;
32
- readonly onInputChange: () => void;
33
- readonly onMenuClose: () => void;
34
- readonly onMenuOpen: () => void;
35
- readonly name: string;
36
- readonly options: readonly Option[];
37
- readonly inputValue: string;
38
- readonly value: null;
39
- }
40
-
41
- const BASIC_PROPS: BasicProps = {
42
- className: 'react-select',
43
- classNamePrefix: 'react-select',
44
- onChange: jest.fn(),
45
- onInputChange: jest.fn(),
46
- onMenuClose: jest.fn(),
47
- onMenuOpen: jest.fn(),
48
- name: 'test-input-name',
49
- options: OPTIONS,
50
- inputValue: '',
51
- value: null,
52
- };
53
-
54
- test('snapshot - defaults', () => {
55
- const { container } = render(
56
- <Select
57
- onChange={noop}
58
- onInputChange={noop}
59
- onMenuOpen={noop}
60
- onMenuClose={noop}
61
- inputValue=""
62
- value={null}
63
- />
64
- );
65
- expect(container).toMatchSnapshot();
66
- });
67
-
68
- test('instanceId prop > to have instanceId as id prefix for the select components', () => {
69
- let { container } = render(
70
- <Select {...BASIC_PROPS} menuIsOpen instanceId={'custom-id'} />
71
- );
72
- expect(container.querySelector('input')!.id).toContain('custom-id');
73
- container.querySelectorAll('div.react-select__option').forEach((opt) => {
74
- expect(opt.id).toContain('custom-id');
75
- });
76
- });
77
-
78
- test('hidden input field is not present if name is not passes', () => {
79
- let { container } = render(
80
- <Select
81
- onChange={noop}
82
- onInputChange={noop}
83
- onMenuOpen={noop}
84
- onMenuClose={noop}
85
- inputValue=""
86
- value={null}
87
- options={OPTIONS}
88
- />
89
- );
90
- expect(container.querySelector('input[type="hidden"]')).toBeNull();
91
- });
92
-
93
- test('hidden input field is present if name passes', () => {
94
- let { container } = render(
95
- <Select
96
- onChange={noop}
97
- onInputChange={noop}
98
- onMenuOpen={noop}
99
- onMenuClose={noop}
100
- inputValue=""
101
- value={null}
102
- name="test-input-name"
103
- options={OPTIONS}
104
- />
105
- );
106
- expect(container.querySelector('input[type="hidden"]')).toBeTruthy();
107
- });
108
-
109
- test('single select > passing multiple values > should select the first value', () => {
110
- const props = { ...BASIC_PROPS, value: [OPTIONS[0], OPTIONS[4]] };
111
- let { container } = render(<Select {...props} />);
112
-
113
- expect(container.querySelector('.react-select__control')!.textContent).toBe(
114
- '0'
115
- );
116
- });
117
-
118
- test('isRtl boolean prop sets direction: rtl on container', () => {
119
- let { container } = render(
120
- <Select {...BASIC_PROPS} value={[OPTIONS[0]]} isRtl isClearable />
121
- );
122
- expect(container.firstChild).toHaveStyleRule('direction', 'rtl');
123
- });
124
-
125
- test('isOptionSelected() prop > single select > mark value as isSelected if isOptionSelected returns true for the option', () => {
126
- // Select all but option with label '1'
127
- let isOptionSelected = jest.fn((option) => option.label !== '1');
128
- let { container } = render(
129
- <Select {...BASIC_PROPS} isOptionSelected={isOptionSelected} menuIsOpen />
130
- );
131
- let options = container.querySelectorAll('.react-select__option');
132
-
133
- // Option label 0 to be selected
134
- expect(options[0].classList).toContain('react-select__option--is-selected');
135
- // Option label 1 to be not selected
136
- expect(options[1].classList).not.toContain(
137
- 'react-select__option--is-selected'
138
- );
139
- });
140
-
141
- test('isOptionSelected() prop > multi select > to not show the selected options in Menu for multiSelect', () => {
142
- // Select all but option with label '1'
143
- let isOptionSelected = jest.fn((option) => option.label !== '1');
144
- let { container } = render(
145
- <Select
146
- {...BASIC_PROPS}
147
- isMulti
148
- isOptionSelected={isOptionSelected}
149
- menuIsOpen
150
- />
151
- );
152
-
153
- expect(container.querySelectorAll('.react-select__option')).toHaveLength(1);
154
- expect(container.querySelector('.react-select__option')!.textContent).toBe(
155
- '1'
156
- );
157
- });
158
-
159
- cases(
160
- 'formatOptionLabel',
161
- ({ props, valueComponentSelector, expectedOptions }) => {
162
- let { container } = render(<Select {...props} />);
163
- let value = container.querySelector(valueComponentSelector);
164
- expect(value!.textContent).toBe(expectedOptions);
165
- },
166
- {
167
- 'single select > should format label of options according to text returned by formatOptionLabel':
168
- {
169
- props: {
170
- ...BASIC_PROPS,
171
- formatOptionLabel: (
172
- { label, value }: Option,
173
- { context }: FormatOptionLabelMeta<Option>
174
- ) => '{label} {value} {context}',
175
- value: OPTIONS[0],
176
- },
177
- valueComponentSelector: '.react-select__single-value',
178
- expectedOptions: '0 zero value',
179
- },
180
- 'multi select > should format label of options according to text returned by formatOptionLabel':
181
- {
182
- props: {
183
- ...BASIC_PROPS,
184
- formatOptionLabel: (
185
- { label, value }: Option,
186
- { context }: FormatOptionLabelMeta<Option>
187
- ) => '{label} {value} {context}',
188
- isMulti: true,
189
- value: OPTIONS[0],
190
- },
191
- valueComponentSelector: '.react-select__multi-value',
192
- expectedOptions: '0 zero value',
193
- },
194
- }
195
- );
196
-
197
- cases(
198
- 'name prop',
199
- ({ expectedName, props }) => {
200
- let { container } = render(<Select {...props} />);
201
- let input = container.querySelector<HTMLInputElement>('input[type=hidden]');
202
-
203
- expect(input!.name).toBe(expectedName);
204
- },
205
- {
206
- 'single select > should assign the given name': {
207
- props: { ...BASIC_PROPS, name: 'form-field-single-select' },
208
- expectedName: 'form-field-single-select',
209
- },
210
- 'multi select > should assign the given name': {
211
- props: {
212
- ...BASIC_PROPS,
213
- name: 'form-field-multi-select',
214
- isMulti: true,
215
- value: OPTIONS[2],
216
- },
217
- expectedName: 'form-field-multi-select',
218
- },
219
- }
220
- );
221
-
222
- cases(
223
- 'menuIsOpen prop',
224
- ({ props = BASIC_PROPS }) => {
225
- let { container, rerender } = render(<Select {...props} />);
226
- expect(container.querySelector('.react-select__menu')).toBeFalsy();
227
-
228
- rerender(<Select {...props} menuIsOpen />);
229
- expect(container.querySelector('.react-select__menu')).toBeTruthy();
230
-
231
- rerender(<Select {...props} />);
232
- expect(container.querySelector('.react-select__menu')).toBeFalsy();
233
- },
234
- {
235
- 'single select > should show menu if menuIsOpen is true and hide menu if menuIsOpen prop is false':
236
- {},
237
- 'multi select > should show menu if menuIsOpen is true and hide menu if menuIsOpen prop is false':
238
- {
239
- props: {
240
- ...BASIC_PROPS,
241
- isMulti: true,
242
- },
243
- },
244
- }
245
- );
246
-
247
- cases(
248
- 'filterOption() prop - default filter behavior',
249
- ({ props, searchString, expectResultsLength }) => {
250
- let { container, rerender } = render(<Select {...props} />);
251
- rerender(<Select {...props} inputValue={searchString} />);
252
- expect(container.querySelectorAll('.react-select__option')).toHaveLength(
253
- expectResultsLength
254
- );
255
- },
256
- {
257
- 'single select > should match accented char': {
258
- props: {
259
- ...BASIC_PROPS,
260
- menuIsOpen: true,
261
- options: OPTIONS_ACCENTED,
262
- },
263
- searchString: 'ecole', // should match "école"
264
- expectResultsLength: 1,
265
- },
266
- 'single select > should ignore accented char in query': {
267
- props: {
268
- ...BASIC_PROPS,
269
- menuIsOpen: true,
270
- options: OPTIONS_ACCENTED,
271
- },
272
- searchString: 'schoöl', // should match "school"
273
- expectResultsLength: 1,
274
- },
275
- }
276
- );
277
-
278
- cases(
279
- 'filterOption() prop - should filter only if function returns truthy for value',
280
- ({ props, searchString, expectResultsLength }) => {
281
- let { container, rerender } = render(<Select {...props} />);
282
- rerender(<Select {...props} inputValue={searchString} />);
283
- expect(container.querySelectorAll('.react-select__option')).toHaveLength(
284
- expectResultsLength
285
- );
286
- },
287
- {
288
- 'single select > should filter all options as per searchString': {
289
- props: {
290
- ...BASIC_PROPS,
291
- filterOption: (value: FilterOptionOption<Option>, search: string) =>
292
- value.value.indexOf(search) > -1,
293
- menuIsOpen: true,
294
- value: OPTIONS[0],
295
- },
296
- searchString: 'o',
297
- expectResultsLength: 5,
298
- },
299
- 'multi select > should filter all options other that options in value of select':
300
- {
301
- props: {
302
- ...BASIC_PROPS,
303
- filterOption: (value: FilterOptionOption<Option>, search: string) =>
304
- value.value.indexOf(search) > -1,
305
- isMulti: true,
306
- menuIsOpen: true,
307
- value: OPTIONS[0],
308
- },
309
- searchString: 'o',
310
- expectResultsLength: 4,
311
- },
312
- }
313
- );
314
-
315
- cases(
316
- 'filterOption prop is null',
317
- ({ props, searchString, expectResultsLength }) => {
318
- let { container, rerender } = render(<Select {...props} />);
319
- rerender(<Select {...props} inputValue={searchString} />);
320
- expect(container.querySelectorAll('.react-select__option')).toHaveLength(
321
- expectResultsLength
322
- );
323
- },
324
- {
325
- 'single select > should show all the options': {
326
- props: {
327
- ...BASIC_PROPS,
328
- filterOption: null,
329
- menuIsOpen: true,
330
- value: OPTIONS[0],
331
- },
332
- searchString: 'o',
333
- expectResultsLength: 17,
334
- },
335
- 'multi select > should show all the options other than selected options': {
336
- props: {
337
- ...BASIC_PROPS,
338
- filterOption: null,
339
- isMulti: true,
340
- menuIsOpen: true,
341
- value: OPTIONS[0],
342
- },
343
- searchString: 'o',
344
- expectResultsLength: 16,
345
- },
346
- }
347
- );
348
-
349
- cases(
350
- 'no option found on search based on filterOption prop',
351
- ({ props, searchString }) => {
352
- let { getByText, rerender } = render(<Select {...props} />);
353
- rerender(<Select {...props} inputValue={searchString} />);
354
- expect(getByText('No options').className).toContain(
355
- 'menu-notice--no-options'
356
- );
357
- },
358
- {
359
- 'single Select > should show NoOptionsMessage': {
360
- props: {
361
- ...BASIC_PROPS,
362
- filterOption: (value: FilterOptionOption<Option>, search: string) =>
363
- value.value.indexOf(search) > -1,
364
- menuIsOpen: true,
365
- },
366
- searchString: 'some text not in options',
367
- },
368
- 'multi select > should show NoOptionsMessage': {
369
- props: {
370
- ...BASIC_PROPS,
371
- filterOption: (value: FilterOptionOption<Option>, search: string) =>
372
- value.value.indexOf(search) > -1,
373
- menuIsOpen: true,
374
- },
375
- searchString: 'some text not in options',
376
- },
377
- }
378
- );
379
-
380
- cases(
381
- 'noOptionsMessage() function prop',
382
- ({ props, expectNoOptionsMessage, searchString }) => {
383
- let { getByText, rerender } = render(<Select {...props} />);
384
- rerender(<Select {...props} inputValue={searchString} />);
385
- expect(getByText(expectNoOptionsMessage).className).toContain(
386
- 'menu-notice--no-options'
387
- );
388
- },
389
- {
390
- 'single Select > should show NoOptionsMessage returned from noOptionsMessage function prop':
391
- {
392
- props: {
393
- ...BASIC_PROPS,
394
- filterOption: (value: FilterOptionOption<Option>, search: string) =>
395
- value.value.indexOf(search) > -1,
396
- menuIsOpen: true,
397
- noOptionsMessage: () =>
398
- 'this is custom no option message for single select',
399
- },
400
- expectNoOptionsMessage:
401
- 'this is custom no option message for single select',
402
- searchString: 'some text not in options',
403
- },
404
- 'multi select > should show NoOptionsMessage returned from noOptionsMessage function prop':
405
- {
406
- props: {
407
- ...BASIC_PROPS,
408
- filterOption: (value: FilterOptionOption<Option>, search: string) =>
409
- value.value.indexOf(search) > -1,
410
- menuIsOpen: true,
411
- noOptionsMessage: () =>
412
- 'this is custom no option message for multi select',
413
- },
414
- expectNoOptionsMessage:
415
- 'this is custom no option message for multi select',
416
- searchString: 'some text not in options',
417
- },
418
- }
419
- );
420
-
421
- cases(
422
- 'value prop',
423
- ({ props, expectedValue }) => {
424
- let value;
425
- render(
426
- <Select<Option | OptionNumberValue, boolean>
427
- {...props}
428
- components={{
429
- Control: ({ getValue }) => {
430
- value = getValue();
431
- return null;
432
- },
433
- }}
434
- />
435
- );
436
- expect(value).toEqual(expectedValue);
437
- },
438
- {
439
- 'single select > should set it as initial value': {
440
- props: {
441
- ...BASIC_PROPS,
442
- value: OPTIONS[2],
443
- },
444
- expectedValue: [{ label: '2', value: 'two' }],
445
- },
446
- 'single select > with option values as number > should set it as initial value':
447
- {
448
- props: {
449
- ...BASIC_PROPS,
450
- value: OPTIONS_NUMBER_VALUE[2],
451
- },
452
- expectedValue: [{ label: '2', value: 2 }],
453
- },
454
- 'multi select > should set it as initial value': {
455
- props: {
456
- ...BASIC_PROPS,
457
- isMulti: true,
458
- value: OPTIONS[1],
459
- },
460
- expectedValue: [{ label: '1', value: 'one' }],
461
- },
462
- 'multi select > with option values as number > should set it as initial value':
463
- {
464
- props: {
465
- ...BASIC_PROPS,
466
- isMulti: true,
467
- value: OPTIONS_NUMBER_VALUE[1],
468
- },
469
- expectedValue: [{ label: '1', value: 1 }],
470
- },
471
- }
472
- );
473
-
474
- cases(
475
- 'update the value prop',
476
- ({
477
- props = { ...BASIC_PROPS, value: OPTIONS[1] },
478
- updateValueTo,
479
- expectedInitialValue,
480
- expectedUpdatedValue,
481
- }) => {
482
- let { container, rerender } = render(
483
- <Select<Option | OptionNumberValue, boolean> {...props} />
484
- );
485
- expect(
486
- container.querySelector<HTMLInputElement>('input[type="hidden"]')!.value
487
- ).toEqual(expectedInitialValue);
488
-
489
- rerender(
490
- <Select<Option | OptionNumberValue, boolean>
491
- {...props}
492
- value={updateValueTo}
493
- />
494
- );
495
-
496
- expect(
497
- container.querySelector<HTMLInputElement>('input[type="hidden"]')!.value
498
- ).toEqual(expectedUpdatedValue);
499
- },
500
- {
501
- 'single select > should update the value when prop is updated': {
502
- updateValueTo: OPTIONS[3],
503
- expectedInitialValue: 'one',
504
- expectedUpdatedValue: 'three',
505
- },
506
- 'single select > value of options is number > should update the value when prop is updated':
507
- {
508
- props: {
509
- ...BASIC_PROPS,
510
- options: OPTIONS_NUMBER_VALUE,
511
- value: OPTIONS_NUMBER_VALUE[2],
512
- },
513
- updateValueTo: OPTIONS_NUMBER_VALUE[3],
514
- expectedInitialValue: '2',
515
- expectedUpdatedValue: '3',
516
- },
517
- 'multi select > should update the value when prop is updated': {
518
- props: {
519
- ...BASIC_PROPS,
520
- isMulti: true,
521
- value: OPTIONS[1],
522
- },
523
- updateValueTo: OPTIONS[3],
524
- expectedInitialValue: 'one',
525
- expectedUpdatedValue: 'three',
526
- },
527
- 'multi select > value of options is number > should update the value when prop is updated':
528
- {
529
- props: {
530
- ...BASIC_PROPS,
531
- delimiter: ',',
532
- isMulti: true,
533
- options: OPTIONS_NUMBER_VALUE,
534
- value: OPTIONS_NUMBER_VALUE[2],
535
- },
536
- updateValueTo: [OPTIONS_NUMBER_VALUE[3], OPTIONS_NUMBER_VALUE[2]],
537
- expectedInitialValue: '2',
538
- expectedUpdatedValue: '3,2',
539
- },
540
- }
541
- );
542
-
543
- cases(
544
- 'calls onChange on selecting an option',
545
- ({
546
- props = { ...BASIC_PROPS, menuIsOpen: true },
547
- event: [eventName, eventOptions],
548
- expectedSelectedOption,
549
- optionsSelected,
550
- focusedOption,
551
- expectedActionMetaOption,
552
- }) => {
553
- let onChangeSpy = jest.fn();
554
- props = { ...props, onChange: onChangeSpy };
555
- let { container } = render(
556
- <Select<Option | OptionNumberValue | OptionBooleanValue, boolean>
557
- {...props}
558
- />
559
- );
560
-
561
- if (focusedOption) {
562
- focusOption(container, focusedOption, props.options);
563
- }
564
-
565
- let selectOption = [
566
- ...container.querySelectorAll('div.react-select__option'),
567
- ].find((n) => n.textContent === optionsSelected.label);
568
-
569
- fireEvent[eventName](selectOption!, eventOptions);
570
- expect(onChangeSpy).toHaveBeenCalledWith(expectedSelectedOption, {
571
- action: 'select-option',
572
- option: expectedActionMetaOption,
573
- name: BASIC_PROPS.name,
574
- });
575
- },
576
- {
577
- 'single select > option is clicked > should call onChange() prop with selected option':
578
- {
579
- event: ['click' as const] as const,
580
- optionsSelected: { label: '2', value: 'two' },
581
- expectedSelectedOption: { label: '2', value: 'two' },
582
- },
583
- 'single select > option with number value > option is clicked > should call onChange() prop with selected option':
584
- {
585
- props: {
586
- ...BASIC_PROPS,
587
- menuIsOpen: true,
588
- options: OPTIONS_NUMBER_VALUE,
589
- },
590
- event: ['click' as const] as const,
591
- optionsSelected: { label: '0', value: 0 },
592
- expectedSelectedOption: { label: '0', value: 0 },
593
- },
594
- 'single select > option with boolean value > option is clicked > should call onChange() prop with selected option':
595
- {
596
- props: {
597
- ...BASIC_PROPS,
598
- menuIsOpen: true,
599
- options: OPTIONS_BOOLEAN_VALUE,
600
- },
601
- event: ['click' as const] as const,
602
- optionsSelected: { label: 'true', value: true },
603
- expectedSelectedOption: { label: 'true', value: true },
604
- },
605
- 'single select > tab key is pressed while focusing option > should call onChange() prop with selected option':
606
- {
607
- event: ['keyDown' as const, { keyCode: 9, key: 'Tab' }] as const,
608
- optionsSelected: { label: '1', value: 'one' },
609
- focusedOption: { label: '1', value: 'one' },
610
- expectedSelectedOption: { label: '1', value: 'one' },
611
- },
612
- 'single select > enter key is pressed while focusing option > should call onChange() prop with selected option':
613
- {
614
- event: ['keyDown' as const, { keyCode: 13, key: 'Enter' }] as const,
615
- optionsSelected: { label: '3', value: 'three' },
616
- focusedOption: { label: '3', value: 'three' },
617
- expectedSelectedOption: { label: '3', value: 'three' },
618
- },
619
- 'single select > space key is pressed while focusing option > should call onChange() prop with selected option':
620
- {
621
- event: ['keyDown' as const, { keyCode: 32, key: ' ' }] as const,
622
- optionsSelected: { label: '1', value: 'one' },
623
- focusedOption: { label: '1', value: 'one' },
624
- expectedSelectedOption: { label: '1', value: 'one' },
625
- },
626
- 'multi select > option is clicked > should call onChange() prop with selected option':
627
- {
628
- props: {
629
- ...BASIC_PROPS,
630
- isMulti: true,
631
- menuIsOpen: true,
632
- options: OPTIONS,
633
- },
634
- event: ['click' as const] as const,
635
- optionsSelected: { label: '2', value: 'two' },
636
- expectedSelectedOption: [{ label: '2', value: 'two' }],
637
- expectedActionMetaOption: { label: '2', value: 'two' },
638
- },
639
- 'multi select > option with number value > option is clicked > should call onChange() prop with selected option':
640
- {
641
- props: {
642
- ...BASIC_PROPS,
643
- isMulti: true,
644
- menuIsOpen: true,
645
- options: OPTIONS_NUMBER_VALUE,
646
- },
647
- event: ['click' as const] as const,
648
- optionsSelected: { label: '0', value: 0 },
649
- expectedSelectedOption: [{ label: '0', value: 0 }],
650
- expectedActionMetaOption: { label: '0', value: 0 },
651
- },
652
- 'multi select > option with boolean value > option is clicked > should call onChange() prop with selected option':
653
- {
654
- props: {
655
- ...BASIC_PROPS,
656
- isMulti: true,
657
- menuIsOpen: true,
658
- options: OPTIONS_BOOLEAN_VALUE,
659
- },
660
- event: ['click' as const] as const,
661
- optionsSelected: { label: 'true', value: true },
662
- expectedSelectedOption: [{ label: 'true', value: true }],
663
- expectedActionMetaOption: { label: 'true', value: true },
664
- },
665
- 'multi select > tab key is pressed while focusing option > should call onChange() prop with selected option':
666
- {
667
- props: {
668
- ...BASIC_PROPS,
669
- isMulti: true,
670
- menuIsOpen: true,
671
- options: OPTIONS,
672
- },
673
- event: ['keyDown' as const, { keyCode: 9, key: 'Tab' }] as const,
674
- menuIsOpen: true,
675
- optionsSelected: { label: '1', value: 'one' },
676
- focusedOption: { label: '1', value: 'one' },
677
- expectedSelectedOption: [{ label: '1', value: 'one' }],
678
- expectedActionMetaOption: { label: '1', value: 'one' },
679
- },
680
- 'multi select > enter key is pressed while focusing option > should call onChange() prop with selected option':
681
- {
682
- props: {
683
- ...BASIC_PROPS,
684
- isMulti: true,
685
- menuIsOpen: true,
686
- options: OPTIONS,
687
- },
688
- event: ['keyDown' as const, { keyCode: 13, key: 'Enter' }] as const,
689
- optionsSelected: { label: '3', value: 'three' },
690
- focusedOption: { label: '3', value: 'three' },
691
- expectedSelectedOption: [{ label: '3', value: 'three' }],
692
- expectedActionMetaOption: { label: '3', value: 'three' },
693
- },
694
- 'multi select > space key is pressed while focusing option > should call onChange() prop with selected option':
695
- {
696
- props: {
697
- ...BASIC_PROPS,
698
- isMulti: true,
699
- menuIsOpen: true,
700
- options: OPTIONS,
701
- },
702
- event: ['keyDown' as const, { keyCode: 32, key: ' ' }] as const,
703
- optionsSelected: { label: '1', value: 'one' },
704
- focusedOption: { label: '1', value: 'one' },
705
- expectedSelectedOption: [{ label: '1', value: 'one' }],
706
- expectedActionMetaOption: { label: '1', value: 'one' },
707
- },
708
- }
709
- );
710
-
711
- interface CallsOnChangeOnDeselectOptsProps
712
- extends Omit<BasicProps, 'options' | 'value'> {
713
- readonly options: readonly (
714
- | Option
715
- | OptionNumberValue
716
- | OptionBooleanValue
717
- )[];
718
- readonly value:
719
- | readonly Option[]
720
- | readonly OptionNumberValue[]
721
- | readonly OptionBooleanValue[]
722
- | Option;
723
- readonly menuIsOpen?: boolean;
724
- readonly hideSelectedOptions?: boolean;
725
- readonly isMulti?: boolean;
726
- }
727
-
728
- interface CallsOnOnDeselectChangeOpts {
729
- readonly props: CallsOnChangeOnDeselectOptsProps;
730
- readonly event: readonly [EventType] | readonly [EventType, {}];
731
- readonly menuIsOpen?: boolean;
732
- readonly optionsSelected: Option | OptionNumberValue | OptionBooleanValue;
733
- readonly focusedOption?: Option | OptionNumberValue | OptionBooleanValue;
734
- readonly expectedSelectedOption:
735
- | readonly Option[]
736
- | readonly OptionNumberValue[]
737
- | readonly OptionBooleanValue[];
738
- readonly expectedMetaOption: Option | OptionNumberValue | OptionBooleanValue;
739
- }
740
-
741
- cases<CallsOnOnDeselectChangeOpts>(
742
- 'calls onChange on de-selecting an option in multi select',
743
- ({
744
- props,
745
- event: [eventName, eventOptions],
746
- expectedSelectedOption,
747
- expectedMetaOption,
748
- optionsSelected,
749
- focusedOption,
750
- }) => {
751
- let onChangeSpy = jest.fn();
752
- props = {
753
- ...props,
754
- onChange: onChangeSpy,
755
- menuIsOpen: true,
756
- hideSelectedOptions: false,
757
- isMulti: true,
758
- };
759
- let { container } = render(
760
- <Select<Option | OptionNumberValue | OptionBooleanValue, boolean>
761
- {...props}
762
- />
763
- );
764
-
765
- let selectOption = [
766
- ...container.querySelectorAll('div.react-select__option'),
767
- ].find((n) => n.textContent === optionsSelected.label);
768
- if (focusedOption) {
769
- focusOption(container, focusedOption, props.options);
770
- }
771
- fireEvent[eventName](selectOption!, eventOptions);
772
- expect(onChangeSpy).toHaveBeenCalledWith(expectedSelectedOption, {
773
- action: 'deselect-option',
774
- option: expectedMetaOption,
775
- name: BASIC_PROPS.name,
776
- });
777
- },
778
- {
779
- 'option is clicked > should call onChange() prop with correct selected options and meta':
780
- {
781
- props: {
782
- ...BASIC_PROPS,
783
- options: OPTIONS,
784
- value: [{ label: '2', value: 'two' }],
785
- },
786
- event: ['click'],
787
- optionsSelected: { label: '2', value: 'two' },
788
- expectedSelectedOption: [],
789
- expectedMetaOption: { label: '2', value: 'two' },
790
- },
791
- 'option with number value > option is clicked > should call onChange() prop with selected option':
792
- {
793
- props: {
794
- ...BASIC_PROPS,
795
- options: OPTIONS_NUMBER_VALUE,
796
- value: [{ label: '0', value: 0 }],
797
- },
798
- event: ['click'],
799
- optionsSelected: { label: '0', value: 0 },
800
- expectedSelectedOption: [],
801
- expectedMetaOption: { label: '0', value: 0 },
802
- },
803
- 'option with boolean value > option is clicked > should call onChange() prop with selected option':
804
- {
805
- props: {
806
- ...BASIC_PROPS,
807
- options: OPTIONS_BOOLEAN_VALUE,
808
- value: [{ label: 'true', value: true }],
809
- },
810
- event: ['click'],
811
- optionsSelected: { label: 'true', value: true },
812
- expectedSelectedOption: [],
813
- expectedMetaOption: { label: 'true', value: true },
814
- },
815
- 'tab key is pressed while focusing option > should call onChange() prop with selected option':
816
- {
817
- props: {
818
- ...BASIC_PROPS,
819
- options: OPTIONS,
820
- value: [{ label: '1', value: 'one' }],
821
- },
822
- event: ['keyDown', { keyCode: 9, key: 'Tab' }],
823
- menuIsOpen: true,
824
- optionsSelected: { label: '1', value: 'one' },
825
- focusedOption: { label: '1', value: 'one' },
826
- expectedSelectedOption: [],
827
- expectedMetaOption: { label: '1', value: 'one' },
828
- },
829
- 'enter key is pressed while focusing option > should call onChange() prop with selected option':
830
- {
831
- props: {
832
- ...BASIC_PROPS,
833
- options: OPTIONS,
834
- value: { label: '3', value: 'three' },
835
- },
836
- event: ['keyDown', { keyCode: 13, key: 'Enter' }],
837
- optionsSelected: { label: '3', value: 'three' },
838
- focusedOption: { label: '3', value: 'three' },
839
- expectedSelectedOption: [],
840
- expectedMetaOption: { label: '3', value: 'three' },
841
- },
842
- 'space key is pressed while focusing option > should call onChange() prop with selected option':
843
- {
844
- props: {
845
- ...BASIC_PROPS,
846
- options: OPTIONS,
847
- value: [{ label: '1', value: 'one' }],
848
- },
849
- event: ['keyDown', { keyCode: 32, key: ' ' }],
850
- optionsSelected: { label: '1', value: 'one' },
851
- focusedOption: { label: '1', value: 'one' },
852
- expectedSelectedOption: [],
853
- expectedMetaOption: { label: '1', value: 'one' },
854
- },
855
- }
856
- );
857
-
858
- function focusOption(
859
- container: HTMLElement,
860
- option: Option | OptionNumberValue | OptionBooleanValue,
861
- options: readonly (Option | OptionNumberValue | OptionBooleanValue)[]
862
- ) {
863
- let indexOfSelectedOption = options.findIndex(
864
- (o) => o.value === option.value
865
- );
866
-
867
- for (let i = -1; i < indexOfSelectedOption; i++) {
868
- fireEvent.keyDown(container.querySelector('.react-select__menu')!, {
869
- keyCode: 40,
870
- key: 'ArrowDown',
871
- });
872
- }
873
- expect(
874
- container.querySelector('.react-select__option--is-focused')!.textContent
875
- ).toEqual(option.label);
876
- }
877
-
878
- cases(
879
- 'hitting escape on select option',
880
- ({
881
- props,
882
- event: [eventName, eventOptions],
883
- focusedOption,
884
- optionsSelected,
885
- }) => {
886
- let onChangeSpy = jest.fn();
887
- let { container } = render(
888
- <Select
889
- {...props}
890
- onChange={onChangeSpy}
891
- onInputChange={jest.fn()}
892
- onMenuClose={jest.fn()}
893
- />
894
- );
895
-
896
- let selectOption = [
897
- ...container.querySelectorAll('div.react-select__option'),
898
- ].find((n) => n.textContent === optionsSelected.label);
899
- focusOption(container, focusedOption, props.options);
900
-
901
- fireEvent[eventName](selectOption!, eventOptions);
902
- expect(onChangeSpy).not.toHaveBeenCalled();
903
- },
904
- {
905
- 'single select > should not call onChange prop': {
906
- props: {
907
- ...BASIC_PROPS,
908
- menuIsOpen: true,
909
- },
910
- optionsSelected: { label: '1', value: 'one' },
911
- focusedOption: { label: '1', value: 'one' },
912
- event: ['keyDown' as const, { keyCode: 27 }] as const,
913
- },
914
- 'multi select > should not call onChange prop': {
915
- props: {
916
- ...BASIC_PROPS,
917
- isMulti: true,
918
- menuIsOpen: true,
919
- },
920
- optionsSelected: { label: '1', value: 'one' },
921
- focusedOption: { label: '1', value: 'one' },
922
- event: ['keyDown' as const, { keyCode: 27 }] as const,
923
- },
924
- }
925
- );
926
-
927
- cases(
928
- 'click to open select',
929
- ({ props = BASIC_PROPS, expectedToFocus }) => {
930
- let { container, rerender } = render(
931
- <Select
932
- {...props}
933
- onMenuOpen={() => {
934
- rerender(<Select {...props} menuIsOpen onMenuOpen={noop} />);
935
- }}
936
- />
937
- );
938
-
939
- fireEvent.mouseDown(
940
- container.querySelector('.react-select__dropdown-indicator')!,
941
- { button: 0 }
942
- );
943
- expect(
944
- container.querySelector('.react-select__option--is-focused')!.textContent
945
- ).toEqual(expectedToFocus.label);
946
- },
947
- {
948
- 'single select > should focus the first option': {
949
- expectedToFocus: { label: '0', value: 'zero' },
950
- },
951
- 'multi select > should focus the first option': {
952
- props: {
953
- ...BASIC_PROPS,
954
- isMulti: true,
955
- },
956
- expectedToFocus: { label: '0', value: 'zero' },
957
- },
958
- }
959
- );
960
-
961
- test('clicking when focused does not open select when openMenuOnClick=false', () => {
962
- let spy = jest.fn();
963
- let { container } = render(
964
- <Select {...BASIC_PROPS} openMenuOnClick={false} onMenuOpen={spy} />
965
- );
966
-
967
- // this will get updated on input click,
968
- // though click on input is not bubbling up to control component
969
- userEvent.click(container.querySelector('input.react-select__input')!);
970
- expect(spy).not.toHaveBeenCalled();
971
- });
972
- // dummy comment
973
- // another line
974
- cases(
975
- 'focus on options > keyboard interaction with Menu',
976
- ({ props, selectedOption, nextFocusOption, keyEvent = [] }) => {
977
- let { container } = render(<Select {...props} />);
978
-
979
- let indexOfSelectedOption = props.options.indexOf(selectedOption);
980
-
981
- for (let i = -1; i < indexOfSelectedOption; i++) {
982
- fireEvent.keyDown(container.querySelector('.react-select__menu')!, {
983
- keyCode: 40,
984
- key: 'ArrowDown',
985
- });
986
- }
987
-
988
- expect(
989
- container.querySelector('.react-select__option--is-focused')!.textContent
990
- ).toEqual(selectedOption.label);
991
-
992
- for (let event of keyEvent) {
993
- fireEvent.keyDown(container.querySelector('.react-select__menu')!, event);
994
- }
995
-
996
- expect(
997
- container.querySelector('.react-select__option--is-focused')!.textContent
998
- ).toEqual(nextFocusOption.label);
999
- },
1000
- );`;