@dhis2-ui/select 10.16.2 → 10.16.3-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 (274) hide show
  1. package/package.json +17 -16
  2. package/src/index.js +9 -0
  3. package/src/locales/ar/translations.json +7 -0
  4. package/src/locales/ar_IQ/translations.json +7 -0
  5. package/src/locales/ckb/translations.json +7 -0
  6. package/src/locales/cs/translations.json +7 -0
  7. package/src/locales/da/translations.json +7 -0
  8. package/src/locales/en/translations.json +11 -0
  9. package/src/locales/en_US/translations.json +9 -0
  10. package/src/locales/es/translations.json +7 -0
  11. package/src/locales/es_419/translations.json +7 -0
  12. package/src/locales/fr/translations.json +7 -0
  13. package/src/locales/hi_IN/translations.json +7 -0
  14. package/src/locales/id/translations.json +7 -0
  15. package/src/locales/index.js +80 -0
  16. package/src/locales/km/translations.json +7 -0
  17. package/src/locales/lo/translations.json +7 -0
  18. package/src/locales/my/translations.json +7 -0
  19. package/src/locales/nb/translations.json +7 -0
  20. package/src/locales/nl/translations.json +7 -0
  21. package/src/locales/prs/translations.json +7 -0
  22. package/src/locales/ps/translations.json +7 -0
  23. package/src/locales/pt/translations.json +7 -0
  24. package/src/locales/pt_BR/translations.json +7 -0
  25. package/src/locales/ru/translations.json +7 -0
  26. package/src/locales/sv/translations.json +7 -0
  27. package/src/locales/tet/translations.json +7 -0
  28. package/src/locales/tg/translations.json +7 -0
  29. package/src/locales/uk/translations.json +7 -0
  30. package/src/locales/ur/translations.json +7 -0
  31. package/src/locales/uz_Latn/translations.json +7 -0
  32. package/src/locales/uz_UZ_Cyrl/translations.json +7 -0
  33. package/src/locales/uz_UZ_Latn/translations.json +7 -0
  34. package/src/locales/vi/translations.json +7 -0
  35. package/src/locales/zh/translations.json +9 -0
  36. package/src/locales/zh_CN/translations.json +7 -0
  37. package/src/multi-select/__tests__/multi-select.test.js +23 -0
  38. package/src/multi-select/__tests__/selection-list.test.js +102 -0
  39. package/src/multi-select/features/accepts_blur_cb/index.js +14 -0
  40. package/src/multi-select/features/accepts_blur_cb.feature +8 -0
  41. package/src/multi-select/features/accepts_focus_cb/index.js +14 -0
  42. package/src/multi-select/features/accepts_focus_cb.feature +6 -0
  43. package/src/multi-select/features/accepts_initial_focus/index.js +5 -0
  44. package/src/multi-select/features/accepts_initial_focus.feature +5 -0
  45. package/src/multi-select/features/accepts_loading/index.js +22 -0
  46. package/src/multi-select/features/accepts_loading.feature +14 -0
  47. package/src/multi-select/features/accepts_max_height/index.js +31 -0
  48. package/src/multi-select/features/accepts_max_height.feature +11 -0
  49. package/src/multi-select/features/accepts_placeholder/index.js +25 -0
  50. package/src/multi-select/features/accepts_placeholder.feature +10 -0
  51. package/src/multi-select/features/accepts_prefix/index.js +19 -0
  52. package/src/multi-select/features/accepts_prefix.feature +10 -0
  53. package/src/multi-select/features/allows_invalid_options/index.js +27 -0
  54. package/src/multi-select/features/allows_invalid_options.feature +12 -0
  55. package/src/multi-select/features/allows_selecting/index.js +81 -0
  56. package/src/multi-select/features/allows_selecting.feature +44 -0
  57. package/src/multi-select/features/can_be_cleared/index.js +22 -0
  58. package/src/multi-select/features/can_be_cleared.feature +6 -0
  59. package/src/multi-select/features/can_be_disabled/index.js +36 -0
  60. package/src/multi-select/features/can_be_disabled.feature +32 -0
  61. package/src/multi-select/features/can_be_empty/index.js +28 -0
  62. package/src/multi-select/features/can_be_empty.feature +16 -0
  63. package/src/multi-select/features/can_be_filtered/index.js +23 -0
  64. package/src/multi-select/features/can_be_filtered.feature +14 -0
  65. package/src/multi-select/features/can_be_opened_and_closed/index.js +32 -0
  66. package/src/multi-select/features/can_be_opened_and_closed.feature +41 -0
  67. package/src/multi-select/features/common/index.js +49 -0
  68. package/src/multi-select/features/duplicate_option_values/index.js +21 -0
  69. package/src/multi-select/features/duplicate_option_values.feature +7 -0
  70. package/src/multi-select/features/menu_width_matches_input/index.js +53 -0
  71. package/src/multi-select/features/menu_width_matches_input.feature +11 -0
  72. package/src/multi-select/features/position/index.js +160 -0
  73. package/src/multi-select/features/position.feature +46 -0
  74. package/src/multi-select/features/shows_selections/index.js +18 -0
  75. package/src/multi-select/features/shows_selections.feature +9 -0
  76. package/src/multi-select/filterable-menu.js +43 -0
  77. package/src/multi-select/index.js +1 -0
  78. package/src/multi-select/input.js +129 -0
  79. package/src/multi-select/menu.js +91 -0
  80. package/src/multi-select/multi-select.e2e.stories.js +407 -0
  81. package/src/multi-select/multi-select.js +148 -0
  82. package/src/multi-select/multi-select.prod.stories.js +408 -0
  83. package/src/multi-select/selection-list.js +79 -0
  84. package/src/multi-select-field/__tests__/multi-select-field.test.js +29 -0
  85. package/src/multi-select-field/features/accepts_help_text/index.js +9 -0
  86. package/src/multi-select-field/features/accepts_help_text.feature +5 -0
  87. package/src/multi-select-field/features/accepts_label/index.js +9 -0
  88. package/src/multi-select-field/features/accepts_label.feature +5 -0
  89. package/src/multi-select-field/features/accepts_validation_text/index.js +9 -0
  90. package/src/multi-select-field/features/accepts_validation_text.feature +5 -0
  91. package/src/multi-select-field/features/can_be_required/index.js +11 -0
  92. package/src/multi-select-field/features/can_be_required.feature +5 -0
  93. package/src/multi-select-field/features/has_default_clear_text/index.js +16 -0
  94. package/src/multi-select-field/features/has_default_clear_text.feature +6 -0
  95. package/src/multi-select-field/features/has_default_empty_text/index.js +13 -0
  96. package/src/multi-select-field/features/has_default_empty_text.feature +6 -0
  97. package/src/multi-select-field/features/has_default_filter_nomatch_text/index.js +17 -0
  98. package/src/multi-select-field/features/has_default_filter_nomatch_text.feature +7 -0
  99. package/src/multi-select-field/features/has_default_filter_placeholder/index.js +15 -0
  100. package/src/multi-select-field/features/has_default_filter_placeholder.feature +6 -0
  101. package/src/multi-select-field/features/has_default_loading_text/index.js +13 -0
  102. package/src/multi-select-field/features/has_default_loading_text.feature +6 -0
  103. package/src/multi-select-field/index.js +1 -0
  104. package/src/multi-select-field/multi-select-field.e2e.stories.js +45 -0
  105. package/src/multi-select-field/multi-select-field.js +178 -0
  106. package/src/multi-select-field/multi-select-field.prod.stories.js +137 -0
  107. package/src/multi-select-option/index.js +1 -0
  108. package/src/multi-select-option/multi-select-option.js +70 -0
  109. package/src/select/__tests__/select.test.js +31 -0
  110. package/src/select/debounce/debounce.js +30 -0
  111. package/src/select/debounce/debounce.spec.js +35 -0
  112. package/src/select/empty.js +28 -0
  113. package/src/select/filter-input.js +42 -0
  114. package/src/select/filterable-menu.js +106 -0
  115. package/src/select/index.js +14 -0
  116. package/src/select/input-clear-button.js +66 -0
  117. package/src/select/input-placeholder.js +30 -0
  118. package/src/select/input-prefix.js +32 -0
  119. package/src/select/input-wrapper.js +114 -0
  120. package/src/select/loading.js +33 -0
  121. package/src/select/menu-wrapper.js +52 -0
  122. package/src/select/no-match.js +28 -0
  123. package/src/select/option-helpers.js +34 -0
  124. package/src/select/select.js +256 -0
  125. package/src/simple-single-select/__stories__/DefaultPosition.js +37 -0
  126. package/src/simple-single-select/__stories__/Dense.js +17 -0
  127. package/src/simple-single-select/__stories__/Empty.js +15 -0
  128. package/src/simple-single-select/__stories__/EmptyWithEmptyNode.js +27 -0
  129. package/src/simple-single-select/__stories__/EmptyWithEmptyText.js +16 -0
  130. package/src/simple-single-select/__stories__/FlippedPosition.js +36 -0
  131. package/src/simple-single-select/__stories__/InfiniteLoading.js +65 -0
  132. package/src/simple-single-select/__stories__/Loading.js +15 -0
  133. package/src/simple-single-select/__stories__/ShiftedIntoView.js +35 -0
  134. package/src/simple-single-select/__stories__/WithClearButton.js +26 -0
  135. package/src/simple-single-select/__stories__/WithCustomLowMaxHeight.js +17 -0
  136. package/src/simple-single-select/__stories__/WithCustomOptions.js +78 -0
  137. package/src/simple-single-select/__stories__/WithDisabledOption.js +25 -0
  138. package/src/simple-single-select/__stories__/WithFilterField.js +30 -0
  139. package/src/simple-single-select/__stories__/WithInitialFocus.js +29 -0
  140. package/src/simple-single-select/__stories__/WithManyOptions.js +19 -0
  141. package/src/simple-single-select/__stories__/WithMultipleSelectsAndScrollableParent.js +65 -0
  142. package/src/simple-single-select/__stories__/WithNoMatchText.js +25 -0
  143. package/src/simple-single-select/__stories__/WithOnBlur.js +22 -0
  144. package/src/simple-single-select/__stories__/WithOnFocus.js +22 -0
  145. package/src/simple-single-select/__stories__/WithOptionsAndDisabled.js +17 -0
  146. package/src/simple-single-select/__stories__/WithOptionsAndLoading.js +23 -0
  147. package/src/simple-single-select/__stories__/WithOptionsAndLoadingText.js +24 -0
  148. package/src/simple-single-select/__stories__/WithPlaceholder.js +18 -0
  149. package/src/simple-single-select/__stories__/WithPlaceholderAndSelection.js +20 -0
  150. package/src/simple-single-select/__stories__/WithPrefix.js +17 -0
  151. package/src/simple-single-select/__stories__/WithPrefixAndSelection.js +20 -0
  152. package/src/simple-single-select/__stories__/WithRTL.js +29 -0
  153. package/src/simple-single-select/__stories__/WithScrollingParent.js +51 -0
  154. package/src/simple-single-select/__stories__/WithSelection.js +19 -0
  155. package/src/simple-single-select/__stories__/WithSelectionAndDisabled.js +20 -0
  156. package/src/simple-single-select/__stories__/WithServerSideFilteringDemo.js +245 -0
  157. package/src/simple-single-select/__stories__/WithSimpleFilteringDemo.js +50 -0
  158. package/src/simple-single-select/__stories__/WithoutOptionsAndLoading.js +16 -0
  159. package/src/simple-single-select/__stories__/WithoutSelection.js +17 -0
  160. package/src/simple-single-select/__stories__/options.js +96 -0
  161. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/CustomDataProvider.js +70 -0
  162. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/dataElements.js +4271 -0
  163. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/index.js +1 -0
  164. package/src/simple-single-select/features/keyboard-interactions.test.e2e.js +581 -0
  165. package/src/simple-single-select/features/menu-positioning.test.e2e.js +187 -0
  166. package/src/simple-single-select/index.js +2 -0
  167. package/src/simple-single-select/is-option-hidden.js +21 -0
  168. package/src/simple-single-select/menu/empty.js +27 -0
  169. package/src/simple-single-select/menu/filter.js +61 -0
  170. package/src/simple-single-select/menu/index.js +1 -0
  171. package/src/simple-single-select/menu/loading.js +38 -0
  172. package/src/simple-single-select/menu/menu.js +171 -0
  173. package/src/simple-single-select/menu/no-match.js +28 -0
  174. package/src/simple-single-select/menu/option.js +161 -0
  175. package/src/simple-single-select/menu/options-list.js +107 -0
  176. package/src/simple-single-select/selected-value/clear-button.js +71 -0
  177. package/src/simple-single-select/selected-value/container.js +146 -0
  178. package/src/simple-single-select/selected-value/index.js +1 -0
  179. package/src/simple-single-select/selected-value/placeholder.js +24 -0
  180. package/src/simple-single-select/selected-value/prefix.js +26 -0
  181. package/src/simple-single-select/selected-value/selected-value.js +174 -0
  182. package/src/simple-single-select/shared-prop-types.js +8 -0
  183. package/src/simple-single-select/simple-single-select.e2e.stories.js +216 -0
  184. package/src/simple-single-select/simple-single-select.js +389 -0
  185. package/src/simple-single-select/simple-single-select.prod.stories.js +41 -0
  186. package/src/simple-single-select/simple-single-select.test.js +1136 -0
  187. package/src/simple-single-select/use-handle-key-press/index.js +2 -0
  188. package/src/simple-single-select/use-handle-key-press/use-focus-option.js +24 -0
  189. package/src/simple-single-select/use-handle-key-press/use-handle-key-press-on-combobox.js +259 -0
  190. package/src/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +147 -0
  191. package/src/simple-single-select/use-handle-key-press/use-handle-typing.js +79 -0
  192. package/src/simple-single-select/use-handle-key-press/use-highlight-first-option-on-previous-page.js +62 -0
  193. package/src/simple-single-select/use-handle-key-press/use-highlight-first-visible-option.js +38 -0
  194. package/src/simple-single-select/use-handle-key-press/use-highlight-last-option-on-next-page.js +60 -0
  195. package/src/simple-single-select/use-handle-key-press/use-highlight-last-visible-option.js +52 -0
  196. package/src/simple-single-select/use-handle-key-press/use-page-down.js +50 -0
  197. package/src/simple-single-select/use-handle-key-press/use-page-up.js +50 -0
  198. package/src/simple-single-select/use-handle-key-press/utils.js +23 -0
  199. package/src/simple-single-select-field/index.js +1 -0
  200. package/src/simple-single-select-field/simple-single-select-field.js +198 -0
  201. package/src/simple-single-select-field/simple-single-select-field.prod.stories.js +188 -0
  202. package/src/simple-single-select-field/simple-single-select-field.test.js +144 -0
  203. package/src/single-select/__tests__/selection.test.js +102 -0
  204. package/src/single-select/__tests__/single-select.test.js +23 -0
  205. package/src/single-select/features/accepts_blur_cb/index.js +14 -0
  206. package/src/single-select/features/accepts_blur_cb.feature +8 -0
  207. package/src/single-select/features/accepts_focus_cb/index.js +14 -0
  208. package/src/single-select/features/accepts_focus_cb.feature +6 -0
  209. package/src/single-select/features/accepts_initial_focus/index.js +5 -0
  210. package/src/single-select/features/accepts_initial_focus.feature +5 -0
  211. package/src/single-select/features/accepts_loading/index.js +22 -0
  212. package/src/single-select/features/accepts_loading.feature +14 -0
  213. package/src/single-select/features/accepts_max_height/index.js +31 -0
  214. package/src/single-select/features/accepts_max_height.feature +11 -0
  215. package/src/single-select/features/accepts_placeholder/index.js +25 -0
  216. package/src/single-select/features/accepts_placeholder.feature +10 -0
  217. package/src/single-select/features/accepts_prefix/index.js +19 -0
  218. package/src/single-select/features/accepts_prefix.feature +10 -0
  219. package/src/single-select/features/allows_invalid_options/index.js +28 -0
  220. package/src/single-select/features/allows_invalid_options.feature +12 -0
  221. package/src/single-select/features/allows_selecting/index.js +38 -0
  222. package/src/single-select/features/allows_selecting.feature +21 -0
  223. package/src/single-select/features/can_be_cleared/index.js +22 -0
  224. package/src/single-select/features/can_be_cleared.feature +6 -0
  225. package/src/single-select/features/can_be_disabled/index.js +39 -0
  226. package/src/single-select/features/can_be_disabled.feature +32 -0
  227. package/src/single-select/features/can_be_empty/index.js +28 -0
  228. package/src/single-select/features/can_be_empty.feature +16 -0
  229. package/src/single-select/features/can_be_filtered/index.js +23 -0
  230. package/src/single-select/features/can_be_filtered.feature +14 -0
  231. package/src/single-select/features/can_be_opened_and_closed/index.js +32 -0
  232. package/src/single-select/features/can_be_opened_and_closed.feature +41 -0
  233. package/src/single-select/features/common/index.js +44 -0
  234. package/src/single-select/features/duplicate_option_values/index.js +26 -0
  235. package/src/single-select/features/duplicate_option_values.feature +7 -0
  236. package/src/single-select/features/menu_width_matches_input/index.js +53 -0
  237. package/src/single-select/features/menu_width_matches_input.feature +11 -0
  238. package/src/single-select/features/position/index.js +111 -0
  239. package/src/single-select/features/position.feature +26 -0
  240. package/src/single-select/features/shows_selections/index.js +9 -0
  241. package/src/single-select/features/shows_selections.feature +5 -0
  242. package/src/single-select/filterable-menu.js +41 -0
  243. package/src/single-select/index.js +1 -0
  244. package/src/single-select/input.js +101 -0
  245. package/src/single-select/menu.js +75 -0
  246. package/src/single-select/selection.js +60 -0
  247. package/src/single-select/single-select.e2e.stories.js +376 -0
  248. package/src/single-select/single-select.js +146 -0
  249. package/src/single-select/single-select.prod.stories.js +358 -0
  250. package/src/single-select-field/__tests__/single-select-field.test.js +29 -0
  251. package/src/single-select-field/features/accepts_help_text/index.js +9 -0
  252. package/src/single-select-field/features/accepts_help_text.feature +5 -0
  253. package/src/single-select-field/features/accepts_label/index.js +9 -0
  254. package/src/single-select-field/features/accepts_label.feature +5 -0
  255. package/src/single-select-field/features/accepts_validation_text/index.js +9 -0
  256. package/src/single-select-field/features/accepts_validation_text.feature +5 -0
  257. package/src/single-select-field/features/can_be_required/index.js +11 -0
  258. package/src/single-select-field/features/can_be_required.feature +5 -0
  259. package/src/single-select-field/features/has_default_clear_text/index.js +16 -0
  260. package/src/single-select-field/features/has_default_clear_text.feature +6 -0
  261. package/src/single-select-field/features/has_default_empty_text/index.js +13 -0
  262. package/src/single-select-field/features/has_default_empty_text.feature +6 -0
  263. package/src/single-select-field/features/has_default_filter_nomatch_text/index.js +17 -0
  264. package/src/single-select-field/features/has_default_filter_nomatch_text.feature +7 -0
  265. package/src/single-select-field/features/has_default_filter_placeholder/index.js +15 -0
  266. package/src/single-select-field/features/has_default_filter_placeholder.feature +6 -0
  267. package/src/single-select-field/features/has_default_loading_text/index.js +13 -0
  268. package/src/single-select-field/features/has_default_loading_text.feature +6 -0
  269. package/src/single-select-field/index.js +1 -0
  270. package/src/single-select-field/single-select-field.e2e.stories.js +45 -0
  271. package/src/single-select-field/single-select-field.js +178 -0
  272. package/src/single-select-field/single-select-field.prod.stories.js +146 -0
  273. package/src/single-select-option/index.js +1 -0
  274. package/src/single-select-option/single-select-option.js +84 -0
@@ -0,0 +1,144 @@
1
+ import '@testing-library/jest-dom'
2
+ import { Field } from '@dhis2-ui/field'
3
+ import { render } from '@testing-library/react'
4
+ import React from 'react'
5
+ import { SimpleSingleSelect } from '../simple-single-select/simple-single-select.js'
6
+ import { SimpleSingleSelectField } from './simple-single-select-field.js'
7
+
8
+ jest.mock('../simple-single-select/simple-single-select.js', () => ({
9
+ SimpleSingleSelect: jest.fn(() => <div />),
10
+ }))
11
+
12
+ jest.mock('@dhis2-ui/field', () => ({
13
+ Field: jest.fn(({ children }) => children),
14
+ }))
15
+
16
+ describe('<SimpleSingleSelectField />', () => {
17
+ afterEach(() => {
18
+ Field.mockClear()
19
+ SimpleSingleSelect.mockClear()
20
+ })
21
+
22
+ it('should forward props to the SimpleSingleSelect component', () => {
23
+ const options = []
24
+ const optionComponent = () => null
25
+ const onChange = jest.fn()
26
+ const onBlur = () => null
27
+ const onEndReached = () => null
28
+ const onFilterChange = () => null
29
+ const onFocus = () => null
30
+
31
+ render(
32
+ <SimpleSingleSelectField
33
+ label="Label text"
34
+ // Props that'll be passed to SimpleSingleSelect
35
+ name="foo"
36
+ options={options}
37
+ onChange={onChange}
38
+ autoFocus={false}
39
+ className=""
40
+ clearText=""
41
+ clearable={false}
42
+ optionComponent={optionComponent}
43
+ dataTest=""
44
+ dense={false}
45
+ disabled={false}
46
+ empty=""
47
+ filterHelpText=""
48
+ filterLabel=""
49
+ filterPlaceholder=""
50
+ filterValue=""
51
+ filterable={false}
52
+ loading={false}
53
+ menuLoadingText=""
54
+ menuMaxHeight=""
55
+ noMatchText=""
56
+ optionUpdateStrategy="off"
57
+ placeholder=""
58
+ prefix=""
59
+ tabIndex=""
60
+ valid={true}
61
+ value=""
62
+ valueLabel=""
63
+ onBlur={onBlur}
64
+ onEndReached={onEndReached}
65
+ onFilterChange={onFilterChange}
66
+ onFocus={onFocus}
67
+ />
68
+ )
69
+
70
+ expect(SimpleSingleSelect.mock.calls[0][0].name).toBe('foo')
71
+ expect(SimpleSingleSelect.mock.calls[0][0].options).toBe(options)
72
+ SimpleSingleSelect.mock.calls[0][0].onChange({ value: 'test' })
73
+ expect(onChange).toHaveBeenCalledWith('test')
74
+ expect(SimpleSingleSelect.mock.calls[0][0].autoFocus).toBe(false)
75
+ expect(SimpleSingleSelect.mock.calls[0][0].className).toBe('')
76
+ expect(SimpleSingleSelect.mock.calls[0][0].clearText).toBe('')
77
+ expect(SimpleSingleSelect.mock.calls[0][0].clearable).toBe(false)
78
+ expect(SimpleSingleSelect.mock.calls[0][0].optionComponent).toBe(
79
+ optionComponent
80
+ )
81
+ expect(SimpleSingleSelect.mock.calls[0][0].dataTest).toBe('')
82
+ expect(SimpleSingleSelect.mock.calls[0][0].dense).toBe(false)
83
+ expect(SimpleSingleSelect.mock.calls[0][0].disabled).toBe(false)
84
+ expect(SimpleSingleSelect.mock.calls[0][0].empty).toBe('')
85
+ expect(SimpleSingleSelect.mock.calls[0][0].filterHelpText).toBe('')
86
+ expect(SimpleSingleSelect.mock.calls[0][0].filterLabel).toBe('')
87
+ expect(SimpleSingleSelect.mock.calls[0][0].filterPlaceholder).toBe('')
88
+ expect(SimpleSingleSelect.mock.calls[0][0].filterValue).toBe('')
89
+ expect(SimpleSingleSelect.mock.calls[0][0].filterable).toBe(false)
90
+ expect(SimpleSingleSelect.mock.calls[0][0].labelledBy).toBe('foo-label')
91
+ expect(SimpleSingleSelect.mock.calls[0][0].loading).toBe(false)
92
+ expect(SimpleSingleSelect.mock.calls[0][0].menuLoadingText).toBe('')
93
+ expect(SimpleSingleSelect.mock.calls[0][0].menuMaxHeight).toBe('')
94
+ expect(SimpleSingleSelect.mock.calls[0][0].noMatchText).toBe('')
95
+ expect(SimpleSingleSelect.mock.calls[0][0].optionUpdateStrategy).toBe(
96
+ 'off'
97
+ )
98
+ expect(SimpleSingleSelect.mock.calls[0][0].placeholder).toBe('')
99
+ expect(SimpleSingleSelect.mock.calls[0][0].prefix).toBe('')
100
+ expect(SimpleSingleSelect.mock.calls[0][0].tabIndex).toBe('')
101
+ expect(SimpleSingleSelect.mock.calls[0][0].valid).toBe(true)
102
+ expect(SimpleSingleSelect.mock.calls[0][0].value).toBe('')
103
+ expect(SimpleSingleSelect.mock.calls[0][0].valueLabel).toBe('')
104
+ expect(SimpleSingleSelect.mock.calls[0][0].onBlur).toBe(onBlur)
105
+ expect(SimpleSingleSelect.mock.calls[0][0].onEndReached).toBe(
106
+ onEndReached
107
+ )
108
+ expect(SimpleSingleSelect.mock.calls[0][0].onFilterChange).toBe(
109
+ onFilterChange
110
+ )
111
+ expect(SimpleSingleSelect.mock.calls[0][0].onFocus).toBe(onFocus)
112
+ })
113
+
114
+ it('should pass the right props to the Field component', () => {
115
+ render(
116
+ <SimpleSingleSelectField
117
+ label="Label text"
118
+ className="class name"
119
+ dataTest="data test"
120
+ disabled={true}
121
+ required={true}
122
+ helpText="Help text"
123
+ validationText="Validation text"
124
+ valid={true}
125
+ // Props required by SimpleSingleSelect
126
+ name="foo"
127
+ options={[]}
128
+ onChange={() => null}
129
+ />
130
+ )
131
+
132
+ expect(Field.mock.calls[0][0].className).toBe('class name')
133
+ expect(Field.mock.calls[0][0].dataTest).toBe('data test')
134
+ expect(Field.mock.calls[0][0].disabled).toBe(true)
135
+ expect(Field.mock.calls[0][0].required).toBe(true)
136
+ expect(Field.mock.calls[0][0].labelId).toBe('foo-label')
137
+ expect(Field.mock.calls[0][0].label).toBe('Label text')
138
+ expect(Field.mock.calls[0][0].helpText).toBe('Help text')
139
+ expect(Field.mock.calls[0][0].validationText).toBe('Validation text')
140
+ expect(Field.mock.calls[0][0].error).toBe(undefined)
141
+ expect(Field.mock.calls[0][0].warning).toBe(undefined)
142
+ expect(Field.mock.calls[0][0].valid).toBe(true)
143
+ })
144
+ })
@@ -0,0 +1,102 @@
1
+ import { render } from '@testing-library/react'
2
+ import React from 'react'
3
+ import { SingleSelectOption } from '../../single-select-option/index.js'
4
+ import { Selection } from '../selection.js'
5
+ import '@testing-library/jest-dom'
6
+
7
+ describe('<Selection />', () => {
8
+ const env = process.env
9
+
10
+ beforeEach(() => {
11
+ // Ensure process.env is also reset for cached modules
12
+ jest.resetModules()
13
+ process.env = { ...env }
14
+
15
+ // Allow spying on console.error and silence rendering errors
16
+ jest.spyOn(console, 'error').mockImplementation(() => {})
17
+ })
18
+
19
+ afterEach(() => {
20
+ // Restore process.env to original state
21
+ process.env = env
22
+
23
+ // Restore all mocks back to original values
24
+ jest.restoreAllMocks()
25
+ })
26
+
27
+ describe('production', () => {
28
+ it('should not throw an error for a selection that is not in the options', () => {
29
+ process.env.NODE_ENV = 'production'
30
+ const options = <SingleSelectOption key="1" label="one" value="1" />
31
+ const selected = 'value'
32
+
33
+ expect(() => {
34
+ render(
35
+ <Selection
36
+ selected={selected}
37
+ options={options}
38
+ disabled={false}
39
+ onChange={() => {}}
40
+ />
41
+ )
42
+ }).not.toThrow()
43
+ })
44
+
45
+ it('should show the selection for a selection that is not in the options', () => {
46
+ process.env.NODE_ENV = 'production'
47
+ const options = <SingleSelectOption key="1" label="one" value="1" />
48
+ const selected = 'value'
49
+
50
+ const { getByText } = render(
51
+ <Selection
52
+ selected={selected}
53
+ options={options}
54
+ disabled={false}
55
+ onChange={() => {}}
56
+ />
57
+ )
58
+
59
+ expect(getByText(selected)).toBeInTheDocument()
60
+ })
61
+
62
+ it('log an error for a selection that is not in the options', () => {
63
+ process.env.NODE_ENV = 'production'
64
+ const options = <SingleSelectOption key="1" label="one" value="1" />
65
+ const selected = 'value'
66
+
67
+ render(
68
+ <Selection
69
+ selected={selected}
70
+ options={options}
71
+ disabled={false}
72
+ onChange={() => {}}
73
+ />
74
+ )
75
+
76
+ expect(console.error).toHaveBeenCalledWith(
77
+ 'There is no option with the value: "value". Make sure that the value passed to the selected prop matches the value of an existing option.'
78
+ )
79
+ })
80
+ })
81
+
82
+ describe('not production', () => {
83
+ it('should throw an error for a selection that is not in the options', () => {
84
+ process.env.NODE_ENV = 'development'
85
+ const options = <SingleSelectOption key="1" label="one" value="1" />
86
+ const selected = 'value'
87
+
88
+ expect(() => {
89
+ render(
90
+ <Selection
91
+ selected={selected}
92
+ options={options}
93
+ disabled={false}
94
+ onChange={() => {}}
95
+ />
96
+ )
97
+ }).toThrow(
98
+ 'There is no option with the value: "value". Make sure that the value passed to the selected prop matches the value of an existing option.'
99
+ )
100
+ })
101
+ })
102
+ })
@@ -0,0 +1,23 @@
1
+ import { render, fireEvent, screen } from '@testing-library/react'
2
+ import React from 'react'
3
+ import { SingleSelect } from '../single-select.js'
4
+
5
+ describe('<SingleSelect />', () => {
6
+ it('should call the onKeyDown callback when provided', () => {
7
+ const onKeyDown = jest.fn()
8
+
9
+ render(<SingleSelect placeholder="placeholder" onKeyDown={onKeyDown} />)
10
+
11
+ fireEvent.keyDown(
12
+ screen.getByTestId('dhis2-uicore-singleselect-placeholder'),
13
+ { key: 'Enter', code: 'Enter', charCode: 13 }
14
+ )
15
+
16
+ expect(onKeyDown).toHaveBeenCalledWith(
17
+ { selected: '' },
18
+ expect.objectContaining({})
19
+ )
20
+
21
+ expect(onKeyDown).toHaveBeenCalledTimes(1)
22
+ })
23
+ })
@@ -0,0 +1,14 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a SingleSelect with onBlur handler is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With on blur')
5
+ })
6
+
7
+ Then('the onBlur handler is called', () => {
8
+ cy.window().should((win) => {
9
+ expect(win.onBlur).to.be.calledOnce
10
+ expect(win.onBlur).to.be.calledWith({
11
+ selected: '',
12
+ })
13
+ })
14
+ })
@@ -0,0 +1,8 @@
1
+ Feature: Calls onBlur cb when blurred
2
+
3
+ Scenario: Blurring a SingleSelect through clicking away
4
+ Given a SingleSelect with onBlur handler is rendered
5
+ And the SingleSelect input is clicked
6
+ And the SingleSelect has focus
7
+ When the user clicks the backdrop layer
8
+ Then the onBlur handler is called
@@ -0,0 +1,14 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a SingleSelect with onFocus handler is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With on focus')
5
+ })
6
+
7
+ Then('the onFocus handler is called', () => {
8
+ cy.window().should((win) => {
9
+ expect(win.onFocus).to.be.calledOnce
10
+ expect(win.onFocus).to.be.calledWith({
11
+ selected: '',
12
+ })
13
+ })
14
+ })
@@ -0,0 +1,6 @@
1
+ Feature: Calls onFocus cb when focused
2
+
3
+ Scenario: Focusing a SingleSelect through clicking
4
+ Given a SingleSelect with onFocus handler is rendered
5
+ When the SingleSelect input is clicked
6
+ Then the onFocus handler is called
@@ -0,0 +1,5 @@
1
+ import { Given } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a SingleSelect with initial focus is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With initial focus')
5
+ })
@@ -0,0 +1,5 @@
1
+ Feature: Focusing the SingleSelect on mount
2
+
3
+ Scenario: The SingleSelect renders with focus
4
+ Given a SingleSelect with initial focus is rendered
5
+ Then the SingleSelect has focus
@@ -0,0 +1,22 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a SingleSelect with options and a loading flag is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With options and loading')
5
+ })
6
+
7
+ Given(
8
+ 'a SingleSelect with options, a loading flag and a loading text is rendered',
9
+ () => {
10
+ cy.visitStory('SingleSelect', 'With options, loading and loading text')
11
+ }
12
+ )
13
+
14
+ Then('the loading spinner is displayed', () => {
15
+ cy.get('[data-test="dhis2-uicore-circularloader"]').should('be.visible')
16
+ })
17
+
18
+ Then('the loading text is displayed', () => {
19
+ cy.get('[data-test="dhis2-uicore-singleselect-loading"]')
20
+ .contains('Loading options')
21
+ .should('be.visible')
22
+ })
@@ -0,0 +1,14 @@
1
+ Feature: Loading status
2
+
3
+ Scenario: The user opens a loading SingleSelect
4
+ Given a SingleSelect with options and a loading flag is rendered
5
+ When the SingleSelect input is clicked
6
+ Then the loading spinner is displayed
7
+ And the options are displayed
8
+
9
+ Scenario: The user opens a loading SingleSelect with a loading text
10
+ Given a SingleSelect with options, a loading flag and a loading text is rendered
11
+ When the SingleSelect input is clicked
12
+ Then the loading spinner is displayed
13
+ And the loading text is displayed
14
+ And the options are displayed
@@ -0,0 +1,31 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a SingleSelect with more than ten options is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With more than ten options')
5
+ })
6
+
7
+ Given(
8
+ 'a SingleSelect with more than three options and a 100px max-height is rendered',
9
+ () => {
10
+ cy.visitStory(
11
+ 'SingleSelect',
12
+ 'With more than three options and a 100 px max-height'
13
+ )
14
+ }
15
+ )
16
+
17
+ Then('has the default max-height', () => {
18
+ cy.get('[data-test="dhis2-uicore-select-menu-menuwrapper"]').should(
19
+ 'have.css',
20
+ 'max-height',
21
+ '280px'
22
+ )
23
+ })
24
+
25
+ Then('has a max-height of 100px', () => {
26
+ cy.get('[data-test="dhis2-uicore-select-menu-menuwrapper"]').should(
27
+ 'have.css',
28
+ 'max-height',
29
+ '100px'
30
+ )
31
+ })
@@ -0,0 +1,11 @@
1
+ Feature: Setting a max-height
2
+
3
+ Scenario: The SingleSelect does not have an explicit max-height set
4
+ Given a SingleSelect with more than ten options is rendered
5
+ And the SingleSelect is open
6
+ Then has the default max-height
7
+
8
+ Scenario: The SingleSelect a max-height of 100px set
9
+ Given a SingleSelect with more than three options and a 100px max-height is rendered
10
+ And the SingleSelect is open
11
+ Then has a max-height of 100px
@@ -0,0 +1,25 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a SingleSelect with a placeholder and no selection is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With placeholder')
5
+ })
6
+
7
+ Given('a SingleSelect with a placeholder and a selection is rendered', () => {
8
+ cy.visitStory('SingleSelect', 'With placeholder and selection')
9
+ })
10
+
11
+ Then('the placeholder is shown', () => {
12
+ cy.get('[data-test="dhis2-uicore-singleselect-placeholder"]')
13
+ .contains('Placeholder text')
14
+ .should('be.visible')
15
+ })
16
+
17
+ Then('the placeholder is not rendered', () => {
18
+ cy.get('[data-test="dhis2-uicore-singleselect-placeholder"]').should(
19
+ 'not.exist'
20
+ )
21
+ })
22
+
23
+ Then('the selection is displayed', () => {
24
+ cy.contains('option one').should('be.visible')
25
+ })
@@ -0,0 +1,10 @@
1
+ Feature: Placeholder text
2
+
3
+ Scenario: A placeholder text with no selection
4
+ Given a SingleSelect with a placeholder and no selection is rendered
5
+ Then the placeholder is shown
6
+
7
+ Scenario: A placeholder text with a selection
8
+ Given a SingleSelect with a placeholder and a selection is rendered
9
+ Then the placeholder is not rendered
10
+ And the selection is displayed
@@ -0,0 +1,19 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a SingleSelect with a prefix and no selection is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With prefix')
5
+ })
6
+
7
+ Given('a SingleSelect with a prefix and a selection is rendered', () => {
8
+ cy.visitStory('SingleSelect', 'With prefix and selection')
9
+ })
10
+
11
+ Then('the prefix is shown', () => {
12
+ cy.get('[data-test="dhis2-uicore-singleselect-prefix"]')
13
+ .contains('Prefix text')
14
+ .should('be.visible')
15
+ })
16
+
17
+ Then('the selection is shown', () => {
18
+ cy.contains('option one').should('be.visible')
19
+ })
@@ -0,0 +1,10 @@
1
+ Feature: Placeholder text
2
+
3
+ Scenario: A prefix text with no selection
4
+ Given a SingleSelect with a prefix and no selection is rendered
5
+ Then the prefix is shown
6
+
7
+ Scenario: A prefix text with a selection
8
+ Given a SingleSelect with a prefix and a selection is rendered
9
+ Then the prefix is shown
10
+ And the selection is shown
@@ -0,0 +1,28 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a SingleSelect with invalid options is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With invalid options')
5
+ })
6
+
7
+ Given('a SingleSelect with invalid filterable options is rendered', () => {
8
+ cy.visitStory('SingleSelect', 'With invalid filterable options')
9
+ })
10
+
11
+ When('the user enters a filter string', () => {
12
+ cy.get('[data-test="dhis2-uicore-singleselect-filterinput"]')
13
+ .click()
14
+ .focused()
15
+ .type('invalid')
16
+ })
17
+
18
+ Then('the invalid options are displayed', () => {
19
+ cy.contains('invalid one').should('be.visible')
20
+ cy.contains('invalid two').should('be.visible')
21
+ cy.contains('invalid three').should('be.visible')
22
+ })
23
+
24
+ Then('the invalid options are not rendered', () => {
25
+ cy.contains('invalid one').should('not.exist')
26
+ cy.contains('invalid two').should('not.exist')
27
+ cy.contains('invalid three').should('not.exist')
28
+ })
@@ -0,0 +1,12 @@
1
+ Feature: Invalid SingleSelect options
2
+
3
+ Scenario: Rendering a SingleSelect with invalid options
4
+ Given a SingleSelect with invalid options is rendered
5
+ And the SingleSelect is open
6
+ Then the invalid options are displayed
7
+
8
+ Scenario: Rendering a SingleSelect with invalid filterable options
9
+ Given a SingleSelect with invalid filterable options is rendered
10
+ And the SingleSelect is open
11
+ When the user enters a filter string
12
+ Then the invalid options are not rendered
@@ -0,0 +1,38 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given(
4
+ 'a SingleSelect with a disabled option and onChange handler is rendered',
5
+ () => {
6
+ cy.visitStory('SingleSelect', 'With disabled option and on change')
7
+ }
8
+ )
9
+
10
+ Given(
11
+ 'a SingleSelect with custom options and onChange handler is rendered',
12
+ () => {
13
+ cy.visitStory('SingleSelect', 'With custom options and on change')
14
+ }
15
+ )
16
+
17
+ When('an option is clicked', () => {
18
+ cy.contains('option one').click()
19
+ })
20
+
21
+ When('the disabled option is clicked', () => {
22
+ cy.contains('disabled option').click()
23
+ })
24
+
25
+ Then('the clicked option is selected', () => {
26
+ cy.window().should((win) => {
27
+ expect(win.onChange).to.be.calledOnce
28
+ expect(win.onChange).to.be.calledWith({
29
+ selected: '1',
30
+ })
31
+ })
32
+ })
33
+
34
+ Then('the onchange handler is not called', () => {
35
+ cy.window().should((win) => {
36
+ expect(win.onChange).to.not.be.called
37
+ })
38
+ })
@@ -0,0 +1,21 @@
1
+ Feature: Selecting options
2
+
3
+ Scenario: The user clicks an option to select it
4
+ Given a SingleSelect with options and onChange handler is rendered
5
+ And the SingleSelect is open
6
+ When an option is clicked
7
+ Then the clicked option is selected
8
+ And the options are not rendered
9
+
10
+ Scenario: The user clicks a custom option to select it
11
+ Given a SingleSelect with custom options and onChange handler is rendered
12
+ And the SingleSelect is open
13
+ When an option is clicked
14
+ Then the clicked option is selected
15
+ And the options are not rendered
16
+
17
+ Scenario: The user clicks a disabled option
18
+ Given a SingleSelect with a disabled option and onChange handler is rendered
19
+ And the SingleSelect is open
20
+ When the disabled option is clicked
21
+ Then the onchange handler is not called
@@ -0,0 +1,22 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given(
4
+ 'a clearable SingleSelect with a selection and onchange handler is rendered',
5
+ () => {
6
+ cy.visitStory(
7
+ 'SingleSelect',
8
+ 'With clear button, selection and on change'
9
+ )
10
+ }
11
+ )
12
+
13
+ When('the clear button is clicked', () => {
14
+ cy.get('[data-test="dhis2-uicore-singleselect-clear"]').click()
15
+ })
16
+
17
+ Then('the SingleSelect is cleared', () => {
18
+ cy.window().should((win) => {
19
+ expect(win.onChange).to.be.calledOnce
20
+ expect(win.onChange).to.be.calledWith({ selected: '' })
21
+ })
22
+ })
@@ -0,0 +1,6 @@
1
+ Feature: Clearing the SingleSelect
2
+
3
+ Scenario: The user clicks the clear button to clear the SingleSelect
4
+ Given a clearable SingleSelect with a selection and onchange handler is rendered
5
+ When the clear button is clicked
6
+ Then the SingleSelect is cleared
@@ -0,0 +1,39 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a disabled SingleSelect with options is rendered', () => {
4
+ cy.visitStory('SingleSelect', 'With options and disabled')
5
+ })
6
+
7
+ Given(
8
+ 'a disabled SingleSelect with options and a selection is rendered',
9
+ () => {
10
+ cy.visitStory('SingleSelect', 'With options, a selection and disabled')
11
+ }
12
+ )
13
+
14
+ Given('the SingleSelect is closed', () => {
15
+ cy.contains('option one').should('not.exist')
16
+ cy.contains('option two').should('not.exist')
17
+ cy.contains('option three').should('not.exist')
18
+ })
19
+
20
+ Given('the SingleSelect is focused', () => {
21
+ cy.get('[data-test="dhis2-uicore-select-input"]').focus()
22
+ cy.focused().should('have.attr', 'data-test', 'dhis2-uicore-select-input')
23
+ })
24
+
25
+ When('the down arrowkey is pressed on the focused element', () => {
26
+ cy.focused().type('{downarrow}')
27
+ })
28
+
29
+ When('the spacebar is pressed on the focused element', () => {
30
+ cy.focused().type(' ')
31
+ })
32
+
33
+ When('the up arrowkey is pressed on the focused element', () => {
34
+ cy.focused().type('{uparrow}')
35
+ })
36
+
37
+ Then('the selection is displayed', () => {
38
+ cy.contains('option one').should('be.visible')
39
+ })