@dhis2-ui/select 10.9.2 → 10.10.0-alpha.1

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.
Files changed (148) hide show
  1. package/build/cjs/index.js +18 -4
  2. package/build/cjs/locales/en/translations.json +7 -5
  3. package/build/cjs/simple-single-select/__stories__/DefaultPosition.js +38 -0
  4. package/build/cjs/simple-single-select/__stories__/Dense.js +22 -0
  5. package/build/cjs/simple-single-select/__stories__/Empty.js +20 -0
  6. package/build/cjs/simple-single-select/__stories__/EmptyWithEmptyNode.js +28 -0
  7. package/build/cjs/simple-single-select/__stories__/EmptyWithEmptyText.js +21 -0
  8. package/build/cjs/simple-single-select/__stories__/FlippedPosition.js +37 -0
  9. package/build/cjs/simple-single-select/__stories__/InfiniteLoading.js +61 -0
  10. package/build/cjs/simple-single-select/__stories__/Loading.js +20 -0
  11. package/build/cjs/simple-single-select/__stories__/ShiftedIntoView.js +28 -0
  12. package/build/cjs/simple-single-select/__stories__/WithClearButton.js +25 -0
  13. package/build/cjs/simple-single-select/__stories__/WithCustomLowMaxHeight.js +22 -0
  14. package/build/cjs/simple-single-select/__stories__/WithCustomOptions.js +48 -0
  15. package/build/cjs/simple-single-select/__stories__/WithDisabledOption.js +28 -0
  16. package/build/cjs/simple-single-select/__stories__/WithFilterField.js +36 -0
  17. package/build/cjs/simple-single-select/__stories__/WithInitialFocus.js +38 -0
  18. package/build/cjs/simple-single-select/__stories__/WithManyOptions.js +24 -0
  19. package/build/cjs/simple-single-select/__stories__/WithNoMatchText.js +30 -0
  20. package/build/cjs/simple-single-select/__stories__/WithOnBlur.js +23 -0
  21. package/build/cjs/simple-single-select/__stories__/WithOnFocus.js +23 -0
  22. package/build/cjs/simple-single-select/__stories__/WithOptionsAndDisabled.js +22 -0
  23. package/build/cjs/simple-single-select/__stories__/WithOptionsAndLoading.js +34 -0
  24. package/build/cjs/simple-single-select/__stories__/WithOptionsAndLoadingText.js +35 -0
  25. package/build/cjs/simple-single-select/__stories__/WithPlaceholder.js +23 -0
  26. package/build/cjs/simple-single-select/__stories__/WithPlaceholderAndSelection.js +25 -0
  27. package/build/cjs/simple-single-select/__stories__/WithPrefix.js +22 -0
  28. package/build/cjs/simple-single-select/__stories__/WithPrefixAndSelection.js +25 -0
  29. package/build/cjs/simple-single-select/__stories__/WithRTL.js +34 -0
  30. package/build/cjs/simple-single-select/__stories__/WithSelection.js +24 -0
  31. package/build/cjs/simple-single-select/__stories__/WithSelectionAndDisabled.js +25 -0
  32. package/build/cjs/simple-single-select/__stories__/WithoutOptionsAndLoading.js +21 -0
  33. package/build/cjs/simple-single-select/__stories__/WithoutSelection.js +22 -0
  34. package/build/cjs/simple-single-select/__stories__/options.js +77 -0
  35. package/build/cjs/simple-single-select/features/keyboard-interactions.test.e2e.js +441 -0
  36. package/build/cjs/simple-single-select/features/menu-positioning.test.e2e.js +152 -0
  37. package/build/cjs/simple-single-select/index.js +19 -0
  38. package/build/cjs/simple-single-select/is-option-hidden.js +22 -0
  39. package/build/cjs/simple-single-select/menu/empty.js +26 -0
  40. package/build/cjs/simple-single-select/menu/filter.js +60 -0
  41. package/build/cjs/simple-single-select/menu/index.js +12 -0
  42. package/build/cjs/simple-single-select/menu/loading.js +30 -0
  43. package/build/cjs/simple-single-select/menu/menu.js +158 -0
  44. package/build/cjs/simple-single-select/menu/no-match.js +28 -0
  45. package/build/cjs/simple-single-select/menu/option.js +120 -0
  46. package/build/cjs/simple-single-select/menu/options-list.js +97 -0
  47. package/build/cjs/simple-single-select/selected-value/clear-button.js +74 -0
  48. package/build/cjs/simple-single-select/selected-value/container.js +100 -0
  49. package/build/cjs/simple-single-select/selected-value/index.js +12 -0
  50. package/build/cjs/simple-single-select/selected-value/placeholder.js +30 -0
  51. package/build/cjs/simple-single-select/selected-value/prefix.js +30 -0
  52. package/build/cjs/simple-single-select/selected-value/selected-value.js +119 -0
  53. package/build/cjs/simple-single-select/shared-prop-types.js +14 -0
  54. package/build/cjs/simple-single-select/simple-single-select.e2e.stories.js +156 -0
  55. package/build/cjs/simple-single-select/simple-single-select.js +319 -0
  56. package/build/cjs/simple-single-select/simple-single-select.prod.stories.js +228 -0
  57. package/build/cjs/simple-single-select/simple-single-select.test.js +1106 -0
  58. package/build/cjs/simple-single-select/use-handle-key-press/index.js +19 -0
  59. package/build/cjs/simple-single-select/use-handle-key-press/use-focus-option.js +24 -0
  60. package/build/cjs/simple-single-select/use-handle-key-press/use-handle-key-press-on-combobox.js +177 -0
  61. package/build/cjs/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +106 -0
  62. package/build/cjs/simple-single-select/use-handle-key-press/use-handle-typing.js +81 -0
  63. package/build/cjs/simple-single-select/use-handle-key-press/use-highlight-first-option-on-previous-page.js +50 -0
  64. package/build/cjs/simple-single-select/use-handle-key-press/use-highlight-first-visible-option.js +30 -0
  65. package/build/cjs/simple-single-select/use-handle-key-press/use-highlight-last-option-on-next-page.js +50 -0
  66. package/build/cjs/simple-single-select/use-handle-key-press/use-highlight-last-visible-option.js +42 -0
  67. package/build/cjs/simple-single-select/use-handle-key-press/use-page-down.js +45 -0
  68. package/build/cjs/simple-single-select/use-handle-key-press/use-page-up.js +44 -0
  69. package/build/cjs/simple-single-select/use-handle-key-press/utils.js +46 -0
  70. package/build/cjs/simple-single-select-field/index.js +12 -0
  71. package/build/cjs/simple-single-select-field/simple-single-select-field.js +138 -0
  72. package/build/cjs/simple-single-select-field/simple-single-select-field.prod.stories.js +188 -0
  73. package/build/cjs/simple-single-select-field/simple-single-select-field.test.js +133 -0
  74. package/build/es/index.js +2 -0
  75. package/build/es/locales/en/translations.json +7 -5
  76. package/build/es/simple-single-select/__stories__/DefaultPosition.js +29 -0
  77. package/build/es/simple-single-select/__stories__/Dense.js +13 -0
  78. package/build/es/simple-single-select/__stories__/Empty.js +11 -0
  79. package/build/es/simple-single-select/__stories__/EmptyWithEmptyNode.js +19 -0
  80. package/build/es/simple-single-select/__stories__/EmptyWithEmptyText.js +12 -0
  81. package/build/es/simple-single-select/__stories__/FlippedPosition.js +28 -0
  82. package/build/es/simple-single-select/__stories__/InfiniteLoading.js +53 -0
  83. package/build/es/simple-single-select/__stories__/Loading.js +12 -0
  84. package/build/es/simple-single-select/__stories__/ShiftedIntoView.js +18 -0
  85. package/build/es/simple-single-select/__stories__/WithClearButton.js +16 -0
  86. package/build/es/simple-single-select/__stories__/WithCustomLowMaxHeight.js +13 -0
  87. package/build/es/simple-single-select/__stories__/WithCustomOptions.js +38 -0
  88. package/build/es/simple-single-select/__stories__/WithDisabledOption.js +19 -0
  89. package/build/es/simple-single-select/__stories__/WithFilterField.js +27 -0
  90. package/build/es/simple-single-select/__stories__/WithInitialFocus.js +29 -0
  91. package/build/es/simple-single-select/__stories__/WithManyOptions.js +15 -0
  92. package/build/es/simple-single-select/__stories__/WithNoMatchText.js +21 -0
  93. package/build/es/simple-single-select/__stories__/WithOnBlur.js +14 -0
  94. package/build/es/simple-single-select/__stories__/WithOnFocus.js +14 -0
  95. package/build/es/simple-single-select/__stories__/WithOptionsAndDisabled.js +13 -0
  96. package/build/es/simple-single-select/__stories__/WithOptionsAndLoading.js +25 -0
  97. package/build/es/simple-single-select/__stories__/WithOptionsAndLoadingText.js +26 -0
  98. package/build/es/simple-single-select/__stories__/WithPlaceholder.js +14 -0
  99. package/build/es/simple-single-select/__stories__/WithPlaceholderAndSelection.js +16 -0
  100. package/build/es/simple-single-select/__stories__/WithPrefix.js +13 -0
  101. package/build/es/simple-single-select/__stories__/WithPrefixAndSelection.js +16 -0
  102. package/build/es/simple-single-select/__stories__/WithRTL.js +25 -0
  103. package/build/es/simple-single-select/__stories__/WithSelection.js +15 -0
  104. package/build/es/simple-single-select/__stories__/WithSelectionAndDisabled.js +16 -0
  105. package/build/es/simple-single-select/__stories__/WithoutOptionsAndLoading.js +12 -0
  106. package/build/es/simple-single-select/__stories__/WithoutSelection.js +13 -0
  107. package/build/es/simple-single-select/__stories__/options.js +71 -0
  108. package/build/es/simple-single-select/features/keyboard-interactions.test.e2e.js +439 -0
  109. package/build/es/simple-single-select/features/menu-positioning.test.e2e.js +150 -0
  110. package/build/es/simple-single-select/index.js +2 -0
  111. package/build/es/simple-single-select/is-option-hidden.js +16 -0
  112. package/build/es/simple-single-select/menu/empty.js +19 -0
  113. package/build/es/simple-single-select/menu/filter.js +53 -0
  114. package/build/es/simple-single-select/menu/index.js +1 -0
  115. package/build/es/simple-single-select/menu/loading.js +23 -0
  116. package/build/es/simple-single-select/menu/menu.js +149 -0
  117. package/build/es/simple-single-select/menu/no-match.js +21 -0
  118. package/build/es/simple-single-select/menu/option.js +111 -0
  119. package/build/es/simple-single-select/menu/options-list.js +88 -0
  120. package/build/es/simple-single-select/selected-value/clear-button.js +68 -0
  121. package/build/es/simple-single-select/selected-value/container.js +91 -0
  122. package/build/es/simple-single-select/selected-value/index.js +1 -0
  123. package/build/es/simple-single-select/selected-value/placeholder.js +23 -0
  124. package/build/es/simple-single-select/selected-value/prefix.js +23 -0
  125. package/build/es/simple-single-select/selected-value/selected-value.js +112 -0
  126. package/build/es/simple-single-select/shared-prop-types.js +7 -0
  127. package/build/es/simple-single-select/simple-single-select.e2e.stories.js +142 -0
  128. package/build/es/simple-single-select/simple-single-select.js +310 -0
  129. package/build/es/simple-single-select/simple-single-select.prod.stories.js +36 -0
  130. package/build/es/simple-single-select/simple-single-select.test.js +1103 -0
  131. package/build/es/simple-single-select/use-handle-key-press/index.js +2 -0
  132. package/build/es/simple-single-select/use-handle-key-press/use-focus-option.js +18 -0
  133. package/build/es/simple-single-select/use-handle-key-press/use-handle-key-press-on-combobox.js +171 -0
  134. package/build/es/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +100 -0
  135. package/build/es/simple-single-select/use-handle-key-press/use-handle-typing.js +75 -0
  136. package/build/es/simple-single-select/use-handle-key-press/use-highlight-first-option-on-previous-page.js +44 -0
  137. package/build/es/simple-single-select/use-handle-key-press/use-highlight-first-visible-option.js +24 -0
  138. package/build/es/simple-single-select/use-handle-key-press/use-highlight-last-option-on-next-page.js +44 -0
  139. package/build/es/simple-single-select/use-handle-key-press/use-highlight-last-visible-option.js +36 -0
  140. package/build/es/simple-single-select/use-handle-key-press/use-page-down.js +39 -0
  141. package/build/es/simple-single-select/use-handle-key-press/use-page-up.js +38 -0
  142. package/build/es/simple-single-select/use-handle-key-press/utils.js +36 -0
  143. package/build/es/simple-single-select-field/index.js +1 -0
  144. package/build/es/simple-single-select-field/simple-single-select-field.js +131 -0
  145. package/build/es/simple-single-select-field/simple-single-select-field.prod.stories.js +172 -0
  146. package/build/es/simple-single-select-field/simple-single-select-field.test.js +130 -0
  147. package/package.json +15 -15
  148. package/types/index.d.ts +184 -1
@@ -0,0 +1,1103 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, fireEvent, screen } from '@testing-library/react';
3
+ import React from 'react';
4
+ import { SimpleSingleSelect } from './simple-single-select.js';
5
+ describe('<SimpleSingleSelect />', () => {
6
+ beforeAll(() => {
7
+ const consoleError = console.error;
8
+ jest.spyOn(console, 'error').mockImplementation(function () {
9
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
10
+ args[_key] = arguments[_key];
11
+ }
12
+ const [message, dynamicContent] = args;
13
+ if (message.startsWith('Warning: An update to %s inside a test was not wrapped in act(...)') && dynamicContent === 'Popper') {
14
+ return;
15
+ }
16
+ consoleError(...args);
17
+ });
18
+ });
19
+ afterAll(() => {
20
+ console.error.mockRestore();
21
+ });
22
+ it('should accept an onBlur handler', () => {
23
+ const onBlur = jest.fn();
24
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
25
+ onBlur: onBlur,
26
+ name: "simple",
27
+ selected: {
28
+ value: 'foo',
29
+ label: 'Foo'
30
+ },
31
+ onChange: () => null,
32
+ options: [{
33
+ value: 'foo',
34
+ label: 'Foo'
35
+ }]
36
+ }));
37
+ fireEvent.blur(screen.getByRole('combobox'));
38
+
39
+ // first argument passed to onBlur is a react event
40
+ //
41
+ // Reg. eslint: Eslint complains about using hasOwnProperty,
42
+ // but accessing `.nativeEvent` directly causes react to log an error
43
+ // eslint-disable-next-line no-prototype-builtins
44
+ expect(onBlur.mock.calls[0][0].hasOwnProperty('nativeEvent')).toBe(true);
45
+ expect(onBlur).toHaveBeenCalledTimes(1);
46
+ });
47
+ it('should accept an onFocus handler', () => {
48
+ const onFocus = jest.fn();
49
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
50
+ onFocus: onFocus,
51
+ name: "simple",
52
+ selected: {
53
+ value: 'foo',
54
+ label: 'Foo'
55
+ },
56
+ onChange: () => null,
57
+ options: [{
58
+ value: 'foo',
59
+ label: 'Foo'
60
+ }]
61
+ }));
62
+ fireEvent.focus(screen.getByRole('combobox'));
63
+
64
+ // first argument passed to onFocus is a react event
65
+ //
66
+ // Reg. eslint: Eslint complains about using hasOwnProperty,
67
+ // but accessing `.nativeEvent` directly causes react to log an error
68
+ // eslint-disable-next-line no-prototype-builtins
69
+ expect(onFocus.mock.calls[0][0].hasOwnProperty('nativeEvent')).toBe(true);
70
+ expect(onFocus).toHaveBeenCalledTimes(1);
71
+ });
72
+ it('should accept autoFocus', () => {
73
+ const onFocus = jest.fn();
74
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
75
+ autoFocus: true,
76
+ onFocus: onFocus,
77
+ name: "simple",
78
+ selected: {
79
+ value: 'foo',
80
+ label: 'Foo'
81
+ },
82
+ onChange: () => null,
83
+ options: [{
84
+ value: 'foo',
85
+ label: 'Foo'
86
+ }]
87
+ }));
88
+ expect(onFocus).toHaveBeenCalledTimes(1);
89
+ });
90
+ it('should accept loading', () => {
91
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
92
+ loading: true,
93
+ name: "simple",
94
+ selected: {
95
+ value: 'foo',
96
+ label: 'Foo'
97
+ },
98
+ onChange: () => null,
99
+ options: [{
100
+ value: 'foo',
101
+ label: 'Foo'
102
+ }]
103
+ }));
104
+ fireEvent.click(screen.getByRole('combobox'));
105
+ const loadingIndicator = screen.getByRole('progressbar');
106
+ expect(loadingIndicator).toBeTruthy();
107
+ });
108
+ it('should display a loading text', () => {
109
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
110
+ loading: true,
111
+ menuLoadingText: "Loading text",
112
+ name: "simple",
113
+ selected: {
114
+ value: 'foo',
115
+ label: 'Foo'
116
+ },
117
+ onChange: () => null,
118
+ options: [{
119
+ value: 'foo',
120
+ label: 'Foo'
121
+ }]
122
+ }));
123
+ fireEvent.click(screen.getByRole('combobox'));
124
+ const loadingIndicator = screen.getByRole('progressbar');
125
+ expect(loadingIndicator).toBeTruthy();
126
+ const loadingText = screen.getByText('Loading text');
127
+ expect(loadingText).toBeTruthy();
128
+ });
129
+ it('should accept a max height', () => {
130
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
131
+ menuMaxHeight: "100px",
132
+ name: "simple",
133
+ selected: {
134
+ value: 'foo',
135
+ label: 'Foo'
136
+ },
137
+ onChange: () => null,
138
+ options: [{
139
+ value: 'foo',
140
+ label: 'Foo'
141
+ }]
142
+ }));
143
+ fireEvent.click(screen.getByRole('combobox'));
144
+ const listbox = screen.getByRole('listbox');
145
+ const menu = listbox.parentNode.parentNode.parentNode;
146
+ expect(menu.style.maxHeight).toBe('100px');
147
+ });
148
+ it('should accept a placeholder', () => {
149
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
150
+ name: "simple",
151
+ selected: null,
152
+ placeholder: "Placeholder text",
153
+ onChange: () => null,
154
+ options: [{
155
+ value: 'foo',
156
+ label: 'Foo'
157
+ }]
158
+ }));
159
+ const placeholder = screen.getByText('Placeholder text');
160
+ const dataTestValue = placeholder.attributes.getNamedItem('data-test').value;
161
+ expect(dataTestValue).toBe('dhis2-simplesingleselect-selectedvalue-placeholder');
162
+ });
163
+ it('should accept a prefix', () => {
164
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
165
+ prefix: "Prefix text",
166
+ name: "simple",
167
+ selected: {
168
+ value: 'foo',
169
+ label: 'Foo'
170
+ },
171
+ onChange: () => null,
172
+ options: [{
173
+ value: 'foo',
174
+ label: 'Foo'
175
+ }]
176
+ }));
177
+ const placeholder = screen.getByText('Prefix text');
178
+ const dataTestValue = placeholder.attributes.getNamedItem('data-test').value;
179
+ expect(dataTestValue).toBe('dhis2-simplesingleselect-selectedvalue-prefix');
180
+ });
181
+ it('should allow options to be selected', () => {
182
+ const onChange = jest.fn();
183
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
184
+ name: "simple",
185
+ selected: null,
186
+ onChange: onChange,
187
+ options: [{
188
+ value: '',
189
+ label: 'None'
190
+ }, {
191
+ value: 'foo',
192
+ label: 'Foo'
193
+ }, {
194
+ value: 'bar',
195
+ label: 'Bar'
196
+ }]
197
+ }));
198
+ fireEvent.click(screen.getByRole('combobox'));
199
+ const option = screen.getByText('Foo').parentNode;
200
+ expect(option.attributes.getNamedItem('role').value).toBe('option');
201
+ fireEvent.click(option);
202
+ expect(onChange).toHaveBeenCalledTimes(1);
203
+ expect(onChange).toHaveBeenCalledWith({
204
+ value: 'foo',
205
+ label: 'Foo'
206
+ });
207
+ });
208
+ it('should allow custom options to be selected', () => {
209
+ const onChange = jest.fn();
210
+
211
+ // eslint-disable-next-line react/prop-types
212
+ const CustomOption = _ref => {
213
+ let {
214
+ value,
215
+ label
216
+ } = _ref;
217
+ return /*#__PURE__*/React.createElement("span", {
218
+ "data-test": `custom-option-${value}`
219
+ }, label);
220
+ };
221
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
222
+ name: "simple",
223
+ selected: null,
224
+ optionComponent: CustomOption,
225
+ valueLabel: "",
226
+ onChange: onChange,
227
+ options: [{
228
+ value: '',
229
+ label: 'None'
230
+ }, {
231
+ value: 'foo',
232
+ label: 'Foo'
233
+ }]
234
+ }));
235
+ fireEvent.click(screen.getByRole('combobox'));
236
+ const optionComponent = screen.getByTestId('custom-option-foo');
237
+ const option = screen.getByTestId('custom-option-foo').parentNode;
238
+ expect(option.attributes.getNamedItem('role').value).toBe('option');
239
+ fireEvent.click(optionComponent);
240
+ expect(onChange).toHaveBeenCalledTimes(1);
241
+ expect(onChange).toHaveBeenCalledWith({
242
+ value: 'foo',
243
+ label: 'Foo'
244
+ });
245
+ });
246
+ it('should allow individual custom options to be selected', () => {
247
+ const onChange = jest.fn();
248
+
249
+ // eslint-disable-next-line react/prop-types
250
+ const CustomOption = _ref2 => {
251
+ let {
252
+ value,
253
+ label
254
+ } = _ref2;
255
+ return /*#__PURE__*/React.createElement("span", {
256
+ "data-test": `custom-option-${value}`
257
+ }, label);
258
+ };
259
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
260
+ name: "simple",
261
+ selected: null,
262
+ valueLabel: "",
263
+ onChange: onChange,
264
+ options: [{
265
+ value: '',
266
+ label: 'None'
267
+ }, {
268
+ value: 'foo',
269
+ label: 'Foo',
270
+ component: CustomOption
271
+ }]
272
+ }));
273
+ fireEvent.click(screen.getByRole('combobox'));
274
+ const optionComponent = screen.getByTestId('custom-option-foo');
275
+ const option = screen.getByTestId('custom-option-foo').parentNode;
276
+ expect(option.attributes.getNamedItem('role').value).toBe('option');
277
+ fireEvent.click(optionComponent);
278
+ expect(onChange).toHaveBeenCalledTimes(1);
279
+ expect(onChange).toHaveBeenCalledWith({
280
+ value: 'foo',
281
+ label: 'Foo'
282
+ });
283
+ });
284
+ it('should be clearable when there is a selected value', () => {
285
+ const onClear = jest.fn();
286
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
287
+ clearable: true,
288
+ clearText: "Clear simple select",
289
+ name: "simple",
290
+ selected: {
291
+ value: 'foo',
292
+ label: 'Foo'
293
+ },
294
+ valueLabel: "Foo",
295
+ onChange: () => null,
296
+ onClear: onClear,
297
+ options: [{
298
+ value: 'foo',
299
+ label: 'Foo'
300
+ }]
301
+ }));
302
+ const clearButton = screen.getByLabelText('Clear simple select');
303
+ expect(clearButton).toBeInstanceOf(HTMLElement);
304
+ fireEvent.click(clearButton);
305
+ expect(onClear).toHaveBeenCalledTimes(1);
306
+ });
307
+ it('should not be clearable when there is no selected value', () => {
308
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
309
+ clearable: true,
310
+ clearText: "Clear simple select",
311
+ name: "simple",
312
+ selected: null,
313
+ onChange: jest.fn(),
314
+ options: [{
315
+ value: '',
316
+ label: 'None'
317
+ }, {
318
+ value: 'foo',
319
+ label: 'Foo'
320
+ }]
321
+ }));
322
+ const clearButton = screen.queryByLabelText('Clear simple select');
323
+ expect(clearButton).toBeNull();
324
+ });
325
+ it('should be disabled', () => {
326
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
327
+ disabled: true,
328
+ name: "simple",
329
+ selected: {
330
+ value: 'foo',
331
+ label: 'Foo'
332
+ },
333
+ onChange: jest.fn(),
334
+ options: [{
335
+ value: 'foo',
336
+ label: 'Foo'
337
+ }]
338
+ }));
339
+ fireEvent.click(screen.getByRole('combobox'));
340
+
341
+ // Element is in the dom, but invisible, which makes it inaccessible
342
+ const listbox = screen.queryByRole('listbox');
343
+ expect(listbox).toBeNull();
344
+ const clearButton = screen.queryByLabelText('Clear simple select');
345
+ expect(clearButton).toBeNull();
346
+ });
347
+ it('should have an empty-text in the menu', () => {
348
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
349
+ empty: "Empty",
350
+ name: "simple",
351
+ selected: null,
352
+ onChange: jest.fn(),
353
+ options: []
354
+ }));
355
+ const emptyTextBeforeOpen = screen.queryByText('Empty');
356
+ expect(emptyTextBeforeOpen).toBeNull();
357
+ fireEvent.click(screen.getByRole('combobox'));
358
+ const emptyTextAfterOpen = screen.queryByText('Empty');
359
+ expect(emptyTextAfterOpen).toBeVisible();
360
+ });
361
+ it('should provide updates about the filter value', () => {
362
+ const onFilterChange = jest.fn();
363
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
364
+ filterable: true,
365
+ onFilterChange: onFilterChange,
366
+ noMatchText: "No options found",
367
+ name: "simple",
368
+ selected: {
369
+ value: 'foo',
370
+ label: 'Foo'
371
+ },
372
+ onChange: jest.fn(),
373
+ options: [{
374
+ value: 'foo',
375
+ label: 'Foo'
376
+ }]
377
+ }));
378
+ expect(screen.queryByLabelText('Search options')).toBeNull();
379
+ fireEvent.click(screen.getByRole('combobox'));
380
+ const searchInput = screen.getByLabelText('Search options');
381
+ expect(searchInput).toBeInstanceOf(HTMLInputElement);
382
+ expect(searchInput).toBeVisible();
383
+ fireEvent.change(searchInput, {
384
+ target: {
385
+ value: 'Search term'
386
+ }
387
+ });
388
+ expect(onFilterChange).toHaveBeenCalledTimes(1);
389
+ expect(onFilterChange).toHaveBeenCalledWith('Search term');
390
+ });
391
+ it('should apply a custom filter label', () => {
392
+ const onFilterChange = jest.fn();
393
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
394
+ filterable: true,
395
+ filterLabel: "Custom filter label",
396
+ onFilterChange: onFilterChange,
397
+ noMatchText: "No options found",
398
+ name: "simple",
399
+ selected: null,
400
+ valueLabel: "",
401
+ onChange: jest.fn(),
402
+ options: [{
403
+ value: '',
404
+ label: 'None'
405
+ }, {
406
+ value: 'foo',
407
+ label: 'Foo'
408
+ }]
409
+ }));
410
+ fireEvent.click(screen.getByRole('combobox'));
411
+ expect(screen.getByLabelText('Custom filter label')).not.toBeNull();
412
+ });
413
+ it('should display the selected option', () => {
414
+ const onChange = jest.fn();
415
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
416
+ name: "simple",
417
+ selected: {
418
+ value: 'bar',
419
+ label: 'Bar'
420
+ },
421
+ onChange: onChange,
422
+ options: [{
423
+ value: 'foo',
424
+ label: 'Foo'
425
+ }, {
426
+ value: 'bar',
427
+ label: 'Bar'
428
+ }]
429
+ }));
430
+ const combobox = screen.getByRole('combobox');
431
+ const withTextBar = screen.getByText('Bar', {
432
+ selector: '.selected-option-label'
433
+ });
434
+ expect(combobox).toContainElement(withTextBar);
435
+ });
436
+
437
+ /***************************
438
+ * *
439
+ * ===================== *
440
+ * Keyboard interactions *
441
+ * ===================== *
442
+ * *
443
+ **************************/
444
+ describe.each([{
445
+ key: ' '
446
+ }, {
447
+ key: 'Enter'
448
+ }, {
449
+ key: 'ArrowDown',
450
+ altKey: true
451
+ }, {
452
+ key: 'ArrowUp',
453
+ altKey: true
454
+ }])('$key ($altKey)', keyDownOptions => {
455
+ test('open the menu', () => {
456
+ const onChange = jest.fn();
457
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
458
+ name: "simple",
459
+ selected: null,
460
+ onChange: onChange,
461
+ options: [{
462
+ value: '',
463
+ label: 'None'
464
+ }, {
465
+ value: 'foo',
466
+ label: 'Foo'
467
+ }, {
468
+ value: 'bar',
469
+ label: 'Bar'
470
+ }]
471
+ }));
472
+ fireEvent.keyDown(screen.getByRole('combobox'), keyDownOptions);
473
+ expect(screen.queryByRole('listbox')).not.toBeNull();
474
+ expect(onChange).not.toHaveBeenCalled();
475
+ });
476
+ });
477
+ describe.each([{
478
+ key: ' '
479
+ }, {
480
+ key: 'Enter'
481
+ }, {
482
+ key: 'ArrowDown',
483
+ altKey: true
484
+ }, {
485
+ key: 'ArrowUp',
486
+ altKey: true
487
+ }])('disabled & $key ($altKey)', keyDownOptions => {
488
+ test('not open the menu', () => {
489
+ const onChange = jest.fn();
490
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
491
+ disabled: true,
492
+ name: "simple",
493
+ selected: null,
494
+ onChange: onChange,
495
+ options: [{
496
+ value: '',
497
+ label: 'None'
498
+ }, {
499
+ value: 'foo',
500
+ label: 'Foo'
501
+ }, {
502
+ value: 'bar',
503
+ label: 'Bar'
504
+ }]
505
+ }));
506
+ fireEvent.keyDown(screen.getByRole('combobox'), keyDownOptions);
507
+ expect(screen.queryByRole('listbox')).toBeNull();
508
+ expect(onChange).not.toHaveBeenCalled();
509
+ });
510
+ });
511
+ describe.each([{
512
+ key: ' '
513
+ }, {
514
+ key: 'Enter'
515
+ }, {
516
+ key: 'ArrowDown',
517
+ altKey: true
518
+ }, {
519
+ key: 'ArrowUp',
520
+ altKey: true
521
+ }])('$key ($altKey)', keyDownOptions => {
522
+ test('close the menu', () => {
523
+ const onChange = jest.fn();
524
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
525
+ name: "simple",
526
+ selected: null,
527
+ onChange: onChange,
528
+ options: [{
529
+ value: '',
530
+ label: 'None'
531
+ }, {
532
+ value: 'foo',
533
+ label: 'Foo'
534
+ }, {
535
+ value: 'bar',
536
+ label: 'Bar'
537
+ }]
538
+ }));
539
+ fireEvent.click(screen.getByRole('combobox'));
540
+ expect(screen.queryByRole('listbox')).not.toBeNull();
541
+ fireEvent.keyDown(screen.getByRole('combobox'), keyDownOptions);
542
+ expect(screen.queryByRole('listbox')).toBeNull();
543
+ expect(onChange).not.toHaveBeenCalled();
544
+ });
545
+ });
546
+ describe.each([{
547
+ key: 'Escape'
548
+ }, {
549
+ key: 'Enter'
550
+ }, {
551
+ key: 'ArrowDown',
552
+ altKey: true
553
+ }, {
554
+ key: 'ArrowUp',
555
+ altKey: true
556
+ }])('$key ($altKey)', keyDownOptions => {
557
+ test('close the menu and select the highlighted option after having highlighted another option', () => {
558
+ const onChange = jest.fn();
559
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
560
+ name: "simple",
561
+ selected: null,
562
+ onChange: onChange,
563
+ options: [{
564
+ value: '',
565
+ label: 'None'
566
+ }, {
567
+ value: 'foo',
568
+ label: 'Foo'
569
+ }, {
570
+ value: 'bar',
571
+ label: 'Bar'
572
+ }]
573
+ }));
574
+ fireEvent.click(screen.getByRole('combobox'));
575
+ expect(screen.queryByRole('listbox')).not.toBeNull();
576
+
577
+ // highlighting the next option
578
+ fireEvent.keyDown(screen.getByRole('combobox'), {
579
+ key: 'ArrowDown'
580
+ });
581
+ fireEvent.keyDown(screen.getByRole('combobox'), keyDownOptions);
582
+ expect(screen.queryByRole('listbox')).toBeNull();
583
+ expect(onChange).toHaveBeenCalledTimes(1);
584
+ expect(onChange).toHaveBeenCalledWith({
585
+ value: 'foo',
586
+ label: 'Foo'
587
+ });
588
+ });
589
+ });
590
+ it('should select the next option when closed and user presses ArrowDown', () => {
591
+ const onChange = jest.fn();
592
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
593
+ name: "simple",
594
+ selected: null,
595
+ onChange: onChange,
596
+ options: [{
597
+ value: '',
598
+ label: 'None'
599
+ }, {
600
+ value: 'foo',
601
+ label: 'Foo'
602
+ }, {
603
+ value: 'bar',
604
+ label: 'Bar'
605
+ }]
606
+ }));
607
+ expect(screen.queryByRole('listbox')).toBeNull();
608
+
609
+ // highlighting the next option
610
+ fireEvent.keyDown(screen.getByRole('combobox'), {
611
+ key: 'ArrowDown'
612
+ });
613
+ expect(screen.queryByRole('listbox')).toBeNull();
614
+ expect(onChange).toHaveBeenCalledTimes(1);
615
+ expect(onChange).toHaveBeenCalledWith({
616
+ value: 'foo',
617
+ label: 'Foo'
618
+ });
619
+ });
620
+ it('should not select the next option when closed, disabled and user presses ArrowDown', () => {
621
+ const onChange = jest.fn();
622
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
623
+ disabled: true,
624
+ name: "simple",
625
+ selected: null,
626
+ onChange: onChange,
627
+ options: [{
628
+ value: '',
629
+ label: 'None'
630
+ }, {
631
+ value: 'foo',
632
+ label: 'Foo'
633
+ }, {
634
+ value: 'bar',
635
+ label: 'Bar'
636
+ }]
637
+ }));
638
+ expect(screen.queryByRole('listbox')).toBeNull();
639
+
640
+ // highlighting the next option
641
+ fireEvent.keyDown(screen.getByRole('combobox'), {
642
+ key: 'ArrowDown'
643
+ });
644
+ expect(screen.queryByRole('listbox')).toBeNull();
645
+ expect(onChange).toHaveBeenCalledTimes(0);
646
+ });
647
+ it('should select the second-next option when closed, next option is disabled and user presses ArrowDown', () => {
648
+ const onChange = jest.fn();
649
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
650
+ name: "simple",
651
+ selected: null,
652
+ onChange: onChange,
653
+ options: [{
654
+ value: '',
655
+ label: 'None'
656
+ }, {
657
+ value: 'foo',
658
+ label: 'Foo',
659
+ disabled: true
660
+ }, {
661
+ value: 'bar',
662
+ label: 'Bar'
663
+ }]
664
+ }));
665
+ expect(screen.queryByRole('listbox')).toBeNull();
666
+
667
+ // highlighting the next option
668
+ fireEvent.keyDown(screen.getByRole('combobox'), {
669
+ key: 'ArrowDown'
670
+ });
671
+ expect(screen.queryByRole('listbox')).toBeNull();
672
+ expect(onChange).toHaveBeenCalledTimes(1);
673
+ expect(onChange).toHaveBeenCalledWith({
674
+ value: 'bar',
675
+ label: 'Bar'
676
+ });
677
+ });
678
+ it('should select the previous option when closed and user presses ArrowUp', () => {
679
+ const onChange = jest.fn();
680
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
681
+ name: "simple",
682
+ selected: {
683
+ value: 'bar',
684
+ label: 'Bar'
685
+ },
686
+ onChange: onChange,
687
+ options: [{
688
+ value: '',
689
+ label: 'None'
690
+ }, {
691
+ value: 'foo',
692
+ label: 'Foo'
693
+ }, {
694
+ value: 'bar',
695
+ label: 'Bar'
696
+ }]
697
+ }));
698
+ expect(screen.queryByRole('listbox')).toBeNull();
699
+
700
+ // highlighting the next option
701
+ fireEvent.keyDown(screen.getByRole('combobox'), {
702
+ key: 'ArrowUp'
703
+ });
704
+ expect(screen.queryByRole('listbox')).toBeNull();
705
+ expect(onChange).toHaveBeenCalledTimes(1);
706
+ expect(onChange).toHaveBeenCalledWith({
707
+ value: 'foo',
708
+ label: 'Foo'
709
+ });
710
+ });
711
+ it('should not select the previous option when closed, disabled and user presses ArrowUp', () => {
712
+ const onChange = jest.fn();
713
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
714
+ disabled: true,
715
+ name: "simple",
716
+ selected: {
717
+ value: 'bar',
718
+ label: 'Bar'
719
+ },
720
+ onChange: onChange,
721
+ options: [{
722
+ value: '',
723
+ label: 'None'
724
+ }, {
725
+ value: 'foo',
726
+ label: 'Foo'
727
+ }, {
728
+ value: 'bar',
729
+ label: 'Bar'
730
+ }]
731
+ }));
732
+ expect(screen.queryByRole('listbox')).toBeNull();
733
+
734
+ // highlighting the next option
735
+ fireEvent.keyDown(screen.getByRole('combobox'), {
736
+ key: 'ArrowUp'
737
+ });
738
+ expect(screen.queryByRole('listbox')).toBeNull();
739
+ expect(onChange).toHaveBeenCalledTimes(0);
740
+ });
741
+ it('should select the second-previous option when closed, previous option disabled and user presses ArrowUp', () => {
742
+ const onChange = jest.fn();
743
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
744
+ name: "simple",
745
+ selected: {
746
+ value: 'bar',
747
+ label: 'Bar'
748
+ },
749
+ onChange: onChange,
750
+ options: [{
751
+ value: '',
752
+ label: 'None'
753
+ }, {
754
+ value: 'foo',
755
+ label: 'Foo',
756
+ disabled: true
757
+ }, {
758
+ value: 'bar',
759
+ label: 'Bar'
760
+ }]
761
+ }));
762
+ expect(screen.queryByRole('listbox')).toBeNull();
763
+
764
+ // highlighting the next option
765
+ fireEvent.keyDown(screen.getByRole('combobox'), {
766
+ key: 'ArrowUp'
767
+ });
768
+ expect(screen.queryByRole('listbox')).toBeNull();
769
+ expect(onChange).toHaveBeenCalledTimes(1);
770
+ expect(onChange).toHaveBeenCalledWith({
771
+ value: '',
772
+ label: 'None'
773
+ });
774
+ });
775
+ it('should highlight the next option', () => {
776
+ const onChange = jest.fn();
777
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
778
+ name: "simple",
779
+ selected: null,
780
+ onChange: onChange,
781
+ options: [{
782
+ value: '',
783
+ label: 'None'
784
+ }, {
785
+ value: 'foo',
786
+ label: 'Foo'
787
+ }, {
788
+ value: 'bar',
789
+ label: 'Bar'
790
+ }]
791
+ }));
792
+
793
+ // open the menu
794
+ expect(screen.queryByRole('listbox')).toBeNull();
795
+ const comboBox = screen.getByRole('combobox');
796
+ fireEvent.click(comboBox);
797
+ expect(screen.queryByRole('listbox')).not.toBeNull();
798
+
799
+ // the first option should be highlighted
800
+ const highlightedOptionBefore = screen.getByRole('option', {
801
+ selected: true
802
+ });
803
+ expect(highlightedOptionBefore.attributes.getNamedItem('aria-label').value).toBe('None');
804
+
805
+ // The second option should be highlighted
806
+ fireEvent.keyDown(comboBox, {
807
+ key: 'ArrowDown'
808
+ });
809
+ const highlightedOptionAfter = screen.getByRole('option', {
810
+ selected: true
811
+ });
812
+ expect(highlightedOptionAfter.attributes.getNamedItem('aria-label').value).toBe('Foo');
813
+ });
814
+ it('should highlight the second next option when the next option is disabled', () => {
815
+ const onChange = jest.fn();
816
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
817
+ name: "simple",
818
+ selected: null,
819
+ onChange: onChange,
820
+ options: [{
821
+ value: '',
822
+ label: 'None'
823
+ }, {
824
+ value: 'foo',
825
+ label: 'Foo',
826
+ disabled: true
827
+ }, {
828
+ value: 'bar',
829
+ label: 'Bar'
830
+ }]
831
+ }));
832
+
833
+ // open the menu
834
+ expect(screen.queryByRole('listbox')).toBeNull();
835
+ const comboBox = screen.getByRole('combobox');
836
+ fireEvent.click(comboBox);
837
+ expect(screen.queryByRole('listbox')).not.toBeNull();
838
+
839
+ // the first option should be highlighted
840
+ const highlightedOptionBefore = screen.getByRole('option', {
841
+ selected: true
842
+ });
843
+ expect(highlightedOptionBefore.attributes.getNamedItem('aria-label').value).toBe('None');
844
+
845
+ // The second option should be highlighted
846
+ fireEvent.keyDown(comboBox, {
847
+ key: 'ArrowDown'
848
+ });
849
+ const highlightedOptionAfter = screen.getByRole('option', {
850
+ selected: true
851
+ });
852
+ expect(highlightedOptionAfter.attributes.getNamedItem('aria-label').value).toBe('Bar');
853
+ });
854
+ it('should highlight the previous option', () => {
855
+ const onChange = jest.fn();
856
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
857
+ name: "simple",
858
+ selected: {
859
+ value: 'bar',
860
+ label: 'Bar'
861
+ },
862
+ onChange: onChange,
863
+ options: [{
864
+ value: '',
865
+ label: 'None'
866
+ }, {
867
+ value: 'foo',
868
+ label: 'Foo'
869
+ }, {
870
+ value: 'bar',
871
+ label: 'Bar'
872
+ }]
873
+ }));
874
+
875
+ // open the menu
876
+ expect(screen.queryByRole('listbox')).toBeNull();
877
+ const comboBox = screen.getByRole('combobox');
878
+ fireEvent.click(comboBox);
879
+ expect(screen.queryByRole('listbox')).not.toBeNull();
880
+
881
+ // the last option should be highlighted
882
+ const highlightedOptionBefore = screen.getByRole('option', {
883
+ selected: true
884
+ });
885
+ expect(highlightedOptionBefore.attributes.getNamedItem('aria-label').value).toBe('Bar');
886
+
887
+ // The second option should be highlighted
888
+ fireEvent.keyDown(comboBox, {
889
+ key: 'ArrowUp'
890
+ });
891
+ const highlightedOptionAfter = screen.getByRole('option', {
892
+ selected: true
893
+ });
894
+ expect(highlightedOptionAfter.attributes.getNamedItem('aria-label').value).toBe('Foo');
895
+ });
896
+ it('should highlight the second previous option when previous option is disabled', () => {
897
+ const onChange = jest.fn();
898
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
899
+ name: "simple",
900
+ selected: {
901
+ value: 'bar',
902
+ label: 'Bar'
903
+ },
904
+ onChange: onChange,
905
+ options: [{
906
+ value: '',
907
+ label: 'None'
908
+ }, {
909
+ value: 'foo',
910
+ label: 'Foo',
911
+ disabled: true
912
+ }, {
913
+ value: 'bar',
914
+ label: 'Bar'
915
+ }]
916
+ }));
917
+
918
+ // open the menu
919
+ expect(screen.queryByRole('listbox')).toBeNull();
920
+ const comboBox = screen.getByRole('combobox');
921
+ fireEvent.click(comboBox);
922
+ expect(screen.queryByRole('listbox')).not.toBeNull();
923
+
924
+ // the last option should be highlighted
925
+ const highlightedOptionBefore = screen.getByRole('option', {
926
+ selected: true
927
+ });
928
+ expect(highlightedOptionBefore.attributes.getNamedItem('aria-label').value).toBe('Bar');
929
+
930
+ // The second option should be highlighted
931
+ fireEvent.keyDown(comboBox, {
932
+ key: 'ArrowUp'
933
+ });
934
+ const highlightedOptionAfter = screen.getByRole('option', {
935
+ selected: true
936
+ });
937
+ expect(highlightedOptionAfter.attributes.getNamedItem('aria-label').value).toBe('None');
938
+ });
939
+ it('should highlight the first option', () => {
940
+ const onChange = jest.fn();
941
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
942
+ name: "simple",
943
+ selected: {
944
+ value: 'bar',
945
+ label: 'Bar'
946
+ },
947
+ onChange: onChange,
948
+ options: [{
949
+ value: '',
950
+ label: 'None'
951
+ }, {
952
+ value: 'foo',
953
+ label: 'Foo'
954
+ }, {
955
+ value: 'bar',
956
+ label: 'Bar'
957
+ }]
958
+ }));
959
+
960
+ // open the menu
961
+ expect(screen.queryByRole('listbox')).toBeNull();
962
+ const comboBox = screen.getByRole('combobox');
963
+ fireEvent.click(comboBox);
964
+ expect(screen.queryByRole('listbox')).not.toBeNull();
965
+
966
+ // the last option should be highlighted
967
+ const highlightedOptionBefore = screen.getByRole('option', {
968
+ selected: true
969
+ });
970
+ expect(highlightedOptionBefore.attributes.getNamedItem('aria-label').value).toBe('Bar');
971
+
972
+ // The first option should be highlighted
973
+ fireEvent.keyDown(comboBox, {
974
+ key: 'Home'
975
+ });
976
+ const highlightedOptionAfter = screen.getByRole('option', {
977
+ selected: true
978
+ });
979
+ expect(highlightedOptionAfter.attributes.getNamedItem('aria-label').value).toBe('None');
980
+ });
981
+ it('should highlight the first enabled option', () => {
982
+ const onChange = jest.fn();
983
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
984
+ name: "simple",
985
+ selected: {
986
+ value: 'bar',
987
+ label: 'Bar'
988
+ },
989
+ onChange: onChange,
990
+ options: [{
991
+ value: '',
992
+ label: 'None',
993
+ disabled: true
994
+ }, {
995
+ value: 'foo',
996
+ label: 'Foo'
997
+ }, {
998
+ value: 'bar',
999
+ label: 'Bar'
1000
+ }]
1001
+ }));
1002
+
1003
+ // open the menu
1004
+ expect(screen.queryByRole('listbox')).toBeNull();
1005
+ const comboBox = screen.getByRole('combobox');
1006
+ fireEvent.click(comboBox);
1007
+ expect(screen.queryByRole('listbox')).not.toBeNull();
1008
+
1009
+ // the last option should be highlighted
1010
+ const highlightedOptionBefore = screen.getByRole('option', {
1011
+ selected: true
1012
+ });
1013
+ expect(highlightedOptionBefore.attributes.getNamedItem('aria-label').value).toBe('Bar');
1014
+
1015
+ // The first option should be highlighted
1016
+ fireEvent.keyDown(comboBox, {
1017
+ key: 'Home'
1018
+ });
1019
+ const highlightedOptionAfter = screen.getByRole('option', {
1020
+ selected: true
1021
+ });
1022
+ expect(highlightedOptionAfter.attributes.getNamedItem('aria-label').value).toBe('Foo');
1023
+ });
1024
+ it('should highlight the last option', () => {
1025
+ const onChange = jest.fn();
1026
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
1027
+ name: "simple",
1028
+ selected: null,
1029
+ onChange: onChange,
1030
+ options: [{
1031
+ value: '',
1032
+ label: 'None'
1033
+ }, {
1034
+ value: 'foo',
1035
+ label: 'Foo'
1036
+ }, {
1037
+ value: 'bar',
1038
+ label: 'Bar'
1039
+ }]
1040
+ }));
1041
+
1042
+ // open the menu
1043
+ expect(screen.queryByRole('listbox')).toBeNull();
1044
+ const comboBox = screen.getByRole('combobox');
1045
+ fireEvent.click(comboBox);
1046
+ expect(screen.queryByRole('listbox')).not.toBeNull();
1047
+
1048
+ // the first option should be highlighted
1049
+ const highlightedOptionBefore = screen.getByRole('option', {
1050
+ selected: true
1051
+ });
1052
+ expect(highlightedOptionBefore.attributes.getNamedItem('aria-label').value).toBe('None');
1053
+
1054
+ // The last option should be highlighted
1055
+ fireEvent.keyDown(comboBox, {
1056
+ key: 'End'
1057
+ });
1058
+ const highlightedOptionAfter = screen.getByRole('option', {
1059
+ selected: true
1060
+ });
1061
+ expect(highlightedOptionAfter.attributes.getNamedItem('aria-label').value).toBe('Bar');
1062
+ });
1063
+ it('should highlight the last enabled option', () => {
1064
+ const onChange = jest.fn();
1065
+ render(/*#__PURE__*/React.createElement(SimpleSingleSelect, {
1066
+ name: "simple",
1067
+ selected: null,
1068
+ onChange: onChange,
1069
+ options: [{
1070
+ value: '',
1071
+ label: 'None'
1072
+ }, {
1073
+ value: 'foo',
1074
+ label: 'Foo'
1075
+ }, {
1076
+ value: 'bar',
1077
+ label: 'Bar',
1078
+ disabled: true
1079
+ }]
1080
+ }));
1081
+
1082
+ // open the menu
1083
+ expect(screen.queryByRole('listbox')).toBeNull();
1084
+ const comboBox = screen.getByRole('combobox');
1085
+ fireEvent.click(comboBox);
1086
+ expect(screen.queryByRole('listbox')).not.toBeNull();
1087
+
1088
+ // the first option should be highlighted
1089
+ const highlightedOptionBefore = screen.getByRole('option', {
1090
+ selected: true
1091
+ });
1092
+ expect(highlightedOptionBefore.attributes.getNamedItem('aria-label').value).toBe('None');
1093
+
1094
+ // The last option should be highlighted
1095
+ fireEvent.keyDown(comboBox, {
1096
+ key: 'End'
1097
+ });
1098
+ const highlightedOptionAfter = screen.getByRole('option', {
1099
+ selected: true
1100
+ });
1101
+ expect(highlightedOptionAfter.attributes.getNamedItem('aria-label').value).toBe('Foo');
1102
+ });
1103
+ });