@dhis2-ui/select 10.16.1 → 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 (278) hide show
  1. package/build/cjs/select/select.js +5 -2
  2. package/build/cjs/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +2 -2
  3. package/build/es/select/select.js +5 -2
  4. package/build/es/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +2 -2
  5. package/package.json +17 -16
  6. package/src/index.js +9 -0
  7. package/src/locales/ar/translations.json +7 -0
  8. package/src/locales/ar_IQ/translations.json +7 -0
  9. package/src/locales/ckb/translations.json +7 -0
  10. package/src/locales/cs/translations.json +7 -0
  11. package/src/locales/da/translations.json +7 -0
  12. package/src/locales/en/translations.json +11 -0
  13. package/src/locales/en_US/translations.json +9 -0
  14. package/src/locales/es/translations.json +7 -0
  15. package/src/locales/es_419/translations.json +7 -0
  16. package/src/locales/fr/translations.json +7 -0
  17. package/src/locales/hi_IN/translations.json +7 -0
  18. package/src/locales/id/translations.json +7 -0
  19. package/src/locales/index.js +80 -0
  20. package/src/locales/km/translations.json +7 -0
  21. package/src/locales/lo/translations.json +7 -0
  22. package/src/locales/my/translations.json +7 -0
  23. package/src/locales/nb/translations.json +7 -0
  24. package/src/locales/nl/translations.json +7 -0
  25. package/src/locales/prs/translations.json +7 -0
  26. package/src/locales/ps/translations.json +7 -0
  27. package/src/locales/pt/translations.json +7 -0
  28. package/src/locales/pt_BR/translations.json +7 -0
  29. package/src/locales/ru/translations.json +7 -0
  30. package/src/locales/sv/translations.json +7 -0
  31. package/src/locales/tet/translations.json +7 -0
  32. package/src/locales/tg/translations.json +7 -0
  33. package/src/locales/uk/translations.json +7 -0
  34. package/src/locales/ur/translations.json +7 -0
  35. package/src/locales/uz_Latn/translations.json +7 -0
  36. package/src/locales/uz_UZ_Cyrl/translations.json +7 -0
  37. package/src/locales/uz_UZ_Latn/translations.json +7 -0
  38. package/src/locales/vi/translations.json +7 -0
  39. package/src/locales/zh/translations.json +9 -0
  40. package/src/locales/zh_CN/translations.json +7 -0
  41. package/src/multi-select/__tests__/multi-select.test.js +23 -0
  42. package/src/multi-select/__tests__/selection-list.test.js +102 -0
  43. package/src/multi-select/features/accepts_blur_cb/index.js +14 -0
  44. package/src/multi-select/features/accepts_blur_cb.feature +8 -0
  45. package/src/multi-select/features/accepts_focus_cb/index.js +14 -0
  46. package/src/multi-select/features/accepts_focus_cb.feature +6 -0
  47. package/src/multi-select/features/accepts_initial_focus/index.js +5 -0
  48. package/src/multi-select/features/accepts_initial_focus.feature +5 -0
  49. package/src/multi-select/features/accepts_loading/index.js +22 -0
  50. package/src/multi-select/features/accepts_loading.feature +14 -0
  51. package/src/multi-select/features/accepts_max_height/index.js +31 -0
  52. package/src/multi-select/features/accepts_max_height.feature +11 -0
  53. package/src/multi-select/features/accepts_placeholder/index.js +25 -0
  54. package/src/multi-select/features/accepts_placeholder.feature +10 -0
  55. package/src/multi-select/features/accepts_prefix/index.js +19 -0
  56. package/src/multi-select/features/accepts_prefix.feature +10 -0
  57. package/src/multi-select/features/allows_invalid_options/index.js +27 -0
  58. package/src/multi-select/features/allows_invalid_options.feature +12 -0
  59. package/src/multi-select/features/allows_selecting/index.js +81 -0
  60. package/src/multi-select/features/allows_selecting.feature +44 -0
  61. package/src/multi-select/features/can_be_cleared/index.js +22 -0
  62. package/src/multi-select/features/can_be_cleared.feature +6 -0
  63. package/src/multi-select/features/can_be_disabled/index.js +36 -0
  64. package/src/multi-select/features/can_be_disabled.feature +32 -0
  65. package/src/multi-select/features/can_be_empty/index.js +28 -0
  66. package/src/multi-select/features/can_be_empty.feature +16 -0
  67. package/src/multi-select/features/can_be_filtered/index.js +23 -0
  68. package/src/multi-select/features/can_be_filtered.feature +14 -0
  69. package/src/multi-select/features/can_be_opened_and_closed/index.js +32 -0
  70. package/src/multi-select/features/can_be_opened_and_closed.feature +41 -0
  71. package/src/multi-select/features/common/index.js +49 -0
  72. package/src/multi-select/features/duplicate_option_values/index.js +21 -0
  73. package/src/multi-select/features/duplicate_option_values.feature +7 -0
  74. package/src/multi-select/features/menu_width_matches_input/index.js +53 -0
  75. package/src/multi-select/features/menu_width_matches_input.feature +11 -0
  76. package/src/multi-select/features/position/index.js +160 -0
  77. package/src/multi-select/features/position.feature +46 -0
  78. package/src/multi-select/features/shows_selections/index.js +18 -0
  79. package/src/multi-select/features/shows_selections.feature +9 -0
  80. package/src/multi-select/filterable-menu.js +43 -0
  81. package/src/multi-select/index.js +1 -0
  82. package/src/multi-select/input.js +129 -0
  83. package/src/multi-select/menu.js +91 -0
  84. package/src/multi-select/multi-select.e2e.stories.js +407 -0
  85. package/src/multi-select/multi-select.js +148 -0
  86. package/src/multi-select/multi-select.prod.stories.js +408 -0
  87. package/src/multi-select/selection-list.js +79 -0
  88. package/src/multi-select-field/__tests__/multi-select-field.test.js +29 -0
  89. package/src/multi-select-field/features/accepts_help_text/index.js +9 -0
  90. package/src/multi-select-field/features/accepts_help_text.feature +5 -0
  91. package/src/multi-select-field/features/accepts_label/index.js +9 -0
  92. package/src/multi-select-field/features/accepts_label.feature +5 -0
  93. package/src/multi-select-field/features/accepts_validation_text/index.js +9 -0
  94. package/src/multi-select-field/features/accepts_validation_text.feature +5 -0
  95. package/src/multi-select-field/features/can_be_required/index.js +11 -0
  96. package/src/multi-select-field/features/can_be_required.feature +5 -0
  97. package/src/multi-select-field/features/has_default_clear_text/index.js +16 -0
  98. package/src/multi-select-field/features/has_default_clear_text.feature +6 -0
  99. package/src/multi-select-field/features/has_default_empty_text/index.js +13 -0
  100. package/src/multi-select-field/features/has_default_empty_text.feature +6 -0
  101. package/src/multi-select-field/features/has_default_filter_nomatch_text/index.js +17 -0
  102. package/src/multi-select-field/features/has_default_filter_nomatch_text.feature +7 -0
  103. package/src/multi-select-field/features/has_default_filter_placeholder/index.js +15 -0
  104. package/src/multi-select-field/features/has_default_filter_placeholder.feature +6 -0
  105. package/src/multi-select-field/features/has_default_loading_text/index.js +13 -0
  106. package/src/multi-select-field/features/has_default_loading_text.feature +6 -0
  107. package/src/multi-select-field/index.js +1 -0
  108. package/src/multi-select-field/multi-select-field.e2e.stories.js +45 -0
  109. package/src/multi-select-field/multi-select-field.js +178 -0
  110. package/src/multi-select-field/multi-select-field.prod.stories.js +137 -0
  111. package/src/multi-select-option/index.js +1 -0
  112. package/src/multi-select-option/multi-select-option.js +70 -0
  113. package/src/select/__tests__/select.test.js +31 -0
  114. package/src/select/debounce/debounce.js +30 -0
  115. package/src/select/debounce/debounce.spec.js +35 -0
  116. package/src/select/empty.js +28 -0
  117. package/src/select/filter-input.js +42 -0
  118. package/src/select/filterable-menu.js +106 -0
  119. package/src/select/index.js +14 -0
  120. package/src/select/input-clear-button.js +66 -0
  121. package/src/select/input-placeholder.js +30 -0
  122. package/src/select/input-prefix.js +32 -0
  123. package/src/select/input-wrapper.js +114 -0
  124. package/src/select/loading.js +33 -0
  125. package/src/select/menu-wrapper.js +52 -0
  126. package/src/select/no-match.js +28 -0
  127. package/src/select/option-helpers.js +34 -0
  128. package/src/select/select.js +256 -0
  129. package/src/simple-single-select/__stories__/DefaultPosition.js +37 -0
  130. package/src/simple-single-select/__stories__/Dense.js +17 -0
  131. package/src/simple-single-select/__stories__/Empty.js +15 -0
  132. package/src/simple-single-select/__stories__/EmptyWithEmptyNode.js +27 -0
  133. package/src/simple-single-select/__stories__/EmptyWithEmptyText.js +16 -0
  134. package/src/simple-single-select/__stories__/FlippedPosition.js +36 -0
  135. package/src/simple-single-select/__stories__/InfiniteLoading.js +65 -0
  136. package/src/simple-single-select/__stories__/Loading.js +15 -0
  137. package/src/simple-single-select/__stories__/ShiftedIntoView.js +35 -0
  138. package/src/simple-single-select/__stories__/WithClearButton.js +26 -0
  139. package/src/simple-single-select/__stories__/WithCustomLowMaxHeight.js +17 -0
  140. package/src/simple-single-select/__stories__/WithCustomOptions.js +78 -0
  141. package/src/simple-single-select/__stories__/WithDisabledOption.js +25 -0
  142. package/src/simple-single-select/__stories__/WithFilterField.js +30 -0
  143. package/src/simple-single-select/__stories__/WithInitialFocus.js +29 -0
  144. package/src/simple-single-select/__stories__/WithManyOptions.js +19 -0
  145. package/src/simple-single-select/__stories__/WithMultipleSelectsAndScrollableParent.js +65 -0
  146. package/src/simple-single-select/__stories__/WithNoMatchText.js +25 -0
  147. package/src/simple-single-select/__stories__/WithOnBlur.js +22 -0
  148. package/src/simple-single-select/__stories__/WithOnFocus.js +22 -0
  149. package/src/simple-single-select/__stories__/WithOptionsAndDisabled.js +17 -0
  150. package/src/simple-single-select/__stories__/WithOptionsAndLoading.js +23 -0
  151. package/src/simple-single-select/__stories__/WithOptionsAndLoadingText.js +24 -0
  152. package/src/simple-single-select/__stories__/WithPlaceholder.js +18 -0
  153. package/src/simple-single-select/__stories__/WithPlaceholderAndSelection.js +20 -0
  154. package/src/simple-single-select/__stories__/WithPrefix.js +17 -0
  155. package/src/simple-single-select/__stories__/WithPrefixAndSelection.js +20 -0
  156. package/src/simple-single-select/__stories__/WithRTL.js +29 -0
  157. package/src/simple-single-select/__stories__/WithScrollingParent.js +51 -0
  158. package/src/simple-single-select/__stories__/WithSelection.js +19 -0
  159. package/src/simple-single-select/__stories__/WithSelectionAndDisabled.js +20 -0
  160. package/src/simple-single-select/__stories__/WithServerSideFilteringDemo.js +245 -0
  161. package/src/simple-single-select/__stories__/WithSimpleFilteringDemo.js +50 -0
  162. package/src/simple-single-select/__stories__/WithoutOptionsAndLoading.js +16 -0
  163. package/src/simple-single-select/__stories__/WithoutSelection.js +17 -0
  164. package/src/simple-single-select/__stories__/options.js +96 -0
  165. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/CustomDataProvider.js +70 -0
  166. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/dataElements.js +4271 -0
  167. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/index.js +1 -0
  168. package/src/simple-single-select/features/keyboard-interactions.test.e2e.js +581 -0
  169. package/src/simple-single-select/features/menu-positioning.test.e2e.js +187 -0
  170. package/src/simple-single-select/index.js +2 -0
  171. package/src/simple-single-select/is-option-hidden.js +21 -0
  172. package/src/simple-single-select/menu/empty.js +27 -0
  173. package/src/simple-single-select/menu/filter.js +61 -0
  174. package/src/simple-single-select/menu/index.js +1 -0
  175. package/src/simple-single-select/menu/loading.js +38 -0
  176. package/src/simple-single-select/menu/menu.js +171 -0
  177. package/src/simple-single-select/menu/no-match.js +28 -0
  178. package/src/simple-single-select/menu/option.js +161 -0
  179. package/src/simple-single-select/menu/options-list.js +107 -0
  180. package/src/simple-single-select/selected-value/clear-button.js +71 -0
  181. package/src/simple-single-select/selected-value/container.js +146 -0
  182. package/src/simple-single-select/selected-value/index.js +1 -0
  183. package/src/simple-single-select/selected-value/placeholder.js +24 -0
  184. package/src/simple-single-select/selected-value/prefix.js +26 -0
  185. package/src/simple-single-select/selected-value/selected-value.js +174 -0
  186. package/src/simple-single-select/shared-prop-types.js +8 -0
  187. package/src/simple-single-select/simple-single-select.e2e.stories.js +216 -0
  188. package/src/simple-single-select/simple-single-select.js +389 -0
  189. package/src/simple-single-select/simple-single-select.prod.stories.js +41 -0
  190. package/src/simple-single-select/simple-single-select.test.js +1136 -0
  191. package/src/simple-single-select/use-handle-key-press/index.js +2 -0
  192. package/src/simple-single-select/use-handle-key-press/use-focus-option.js +24 -0
  193. package/src/simple-single-select/use-handle-key-press/use-handle-key-press-on-combobox.js +259 -0
  194. package/src/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +147 -0
  195. package/src/simple-single-select/use-handle-key-press/use-handle-typing.js +79 -0
  196. package/src/simple-single-select/use-handle-key-press/use-highlight-first-option-on-previous-page.js +62 -0
  197. package/src/simple-single-select/use-handle-key-press/use-highlight-first-visible-option.js +38 -0
  198. package/src/simple-single-select/use-handle-key-press/use-highlight-last-option-on-next-page.js +60 -0
  199. package/src/simple-single-select/use-handle-key-press/use-highlight-last-visible-option.js +52 -0
  200. package/src/simple-single-select/use-handle-key-press/use-page-down.js +50 -0
  201. package/src/simple-single-select/use-handle-key-press/use-page-up.js +50 -0
  202. package/src/simple-single-select/use-handle-key-press/utils.js +23 -0
  203. package/src/simple-single-select-field/index.js +1 -0
  204. package/src/simple-single-select-field/simple-single-select-field.js +198 -0
  205. package/src/simple-single-select-field/simple-single-select-field.prod.stories.js +188 -0
  206. package/src/simple-single-select-field/simple-single-select-field.test.js +144 -0
  207. package/src/single-select/__tests__/selection.test.js +102 -0
  208. package/src/single-select/__tests__/single-select.test.js +23 -0
  209. package/src/single-select/features/accepts_blur_cb/index.js +14 -0
  210. package/src/single-select/features/accepts_blur_cb.feature +8 -0
  211. package/src/single-select/features/accepts_focus_cb/index.js +14 -0
  212. package/src/single-select/features/accepts_focus_cb.feature +6 -0
  213. package/src/single-select/features/accepts_initial_focus/index.js +5 -0
  214. package/src/single-select/features/accepts_initial_focus.feature +5 -0
  215. package/src/single-select/features/accepts_loading/index.js +22 -0
  216. package/src/single-select/features/accepts_loading.feature +14 -0
  217. package/src/single-select/features/accepts_max_height/index.js +31 -0
  218. package/src/single-select/features/accepts_max_height.feature +11 -0
  219. package/src/single-select/features/accepts_placeholder/index.js +25 -0
  220. package/src/single-select/features/accepts_placeholder.feature +10 -0
  221. package/src/single-select/features/accepts_prefix/index.js +19 -0
  222. package/src/single-select/features/accepts_prefix.feature +10 -0
  223. package/src/single-select/features/allows_invalid_options/index.js +28 -0
  224. package/src/single-select/features/allows_invalid_options.feature +12 -0
  225. package/src/single-select/features/allows_selecting/index.js +38 -0
  226. package/src/single-select/features/allows_selecting.feature +21 -0
  227. package/src/single-select/features/can_be_cleared/index.js +22 -0
  228. package/src/single-select/features/can_be_cleared.feature +6 -0
  229. package/src/single-select/features/can_be_disabled/index.js +39 -0
  230. package/src/single-select/features/can_be_disabled.feature +32 -0
  231. package/src/single-select/features/can_be_empty/index.js +28 -0
  232. package/src/single-select/features/can_be_empty.feature +16 -0
  233. package/src/single-select/features/can_be_filtered/index.js +23 -0
  234. package/src/single-select/features/can_be_filtered.feature +14 -0
  235. package/src/single-select/features/can_be_opened_and_closed/index.js +32 -0
  236. package/src/single-select/features/can_be_opened_and_closed.feature +41 -0
  237. package/src/single-select/features/common/index.js +44 -0
  238. package/src/single-select/features/duplicate_option_values/index.js +26 -0
  239. package/src/single-select/features/duplicate_option_values.feature +7 -0
  240. package/src/single-select/features/menu_width_matches_input/index.js +53 -0
  241. package/src/single-select/features/menu_width_matches_input.feature +11 -0
  242. package/src/single-select/features/position/index.js +111 -0
  243. package/src/single-select/features/position.feature +26 -0
  244. package/src/single-select/features/shows_selections/index.js +9 -0
  245. package/src/single-select/features/shows_selections.feature +5 -0
  246. package/src/single-select/filterable-menu.js +41 -0
  247. package/src/single-select/index.js +1 -0
  248. package/src/single-select/input.js +101 -0
  249. package/src/single-select/menu.js +75 -0
  250. package/src/single-select/selection.js +60 -0
  251. package/src/single-select/single-select.e2e.stories.js +376 -0
  252. package/src/single-select/single-select.js +146 -0
  253. package/src/single-select/single-select.prod.stories.js +358 -0
  254. package/src/single-select-field/__tests__/single-select-field.test.js +29 -0
  255. package/src/single-select-field/features/accepts_help_text/index.js +9 -0
  256. package/src/single-select-field/features/accepts_help_text.feature +5 -0
  257. package/src/single-select-field/features/accepts_label/index.js +9 -0
  258. package/src/single-select-field/features/accepts_label.feature +5 -0
  259. package/src/single-select-field/features/accepts_validation_text/index.js +9 -0
  260. package/src/single-select-field/features/accepts_validation_text.feature +5 -0
  261. package/src/single-select-field/features/can_be_required/index.js +11 -0
  262. package/src/single-select-field/features/can_be_required.feature +5 -0
  263. package/src/single-select-field/features/has_default_clear_text/index.js +16 -0
  264. package/src/single-select-field/features/has_default_clear_text.feature +6 -0
  265. package/src/single-select-field/features/has_default_empty_text/index.js +13 -0
  266. package/src/single-select-field/features/has_default_empty_text.feature +6 -0
  267. package/src/single-select-field/features/has_default_filter_nomatch_text/index.js +17 -0
  268. package/src/single-select-field/features/has_default_filter_nomatch_text.feature +7 -0
  269. package/src/single-select-field/features/has_default_filter_placeholder/index.js +15 -0
  270. package/src/single-select-field/features/has_default_filter_placeholder.feature +6 -0
  271. package/src/single-select-field/features/has_default_loading_text/index.js +13 -0
  272. package/src/single-select-field/features/has_default_loading_text.feature +6 -0
  273. package/src/single-select-field/index.js +1 -0
  274. package/src/single-select-field/single-select-field.e2e.stories.js +45 -0
  275. package/src/single-select-field/single-select-field.js +178 -0
  276. package/src/single-select-field/single-select-field.prod.stories.js +146 -0
  277. package/src/single-select-option/index.js +1 -0
  278. package/src/single-select-option/single-select-option.js +84 -0
@@ -0,0 +1,102 @@
1
+ import { render } from '@testing-library/react'
2
+ import React from 'react'
3
+ import { MultiSelectOption } from '../../multi-select-option/index.js'
4
+ import { SelectionList } from '../selection-list.js'
5
+ import '@testing-library/jest-dom'
6
+
7
+ describe('<SelectionList />', () => {
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 = <MultiSelectOption key="1" label="one" value="1" />
31
+ const selected = ['value']
32
+
33
+ expect(() => {
34
+ render(
35
+ <SelectionList
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 = <MultiSelectOption key="1" label="one" value="1" />
48
+ const selected = ['value']
49
+
50
+ const { getByText } = render(
51
+ <SelectionList
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 = <MultiSelectOption key="1" label="one" value="1" />
65
+ const selected = ['value']
66
+
67
+ render(
68
+ <SelectionList
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 all the values passed to the selected prop match 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 = <MultiSelectOption key="1" label="one" value="1" />
86
+ const selected = ['value']
87
+
88
+ expect(() => {
89
+ render(
90
+ <SelectionList
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 all the values passed to the selected prop match the value of an existing option.'
99
+ )
100
+ })
101
+ })
102
+ })
@@ -0,0 +1,14 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a MultiSelect with onBlur handler is rendered', () => {
4
+ cy.visitStory('MultiSelect', '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 MultiSelect through clicking away
4
+ Given a MultiSelect with onBlur handler is rendered
5
+ And the MultiSelect input is clicked
6
+ And the MultiSelect 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 MultiSelect with onFocus handler is rendered', () => {
4
+ cy.visitStory('MultiSelect', '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 MultiSelect through clicking
4
+ Given a MultiSelect with onFocus handler is rendered
5
+ When the MultiSelect 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 MultiSelect with initial focus is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'With initial focus')
5
+ })
@@ -0,0 +1,5 @@
1
+ Feature: Focusing the MultiSelect on mount
2
+
3
+ Scenario: The MultiSelect renders with focus
4
+ Given a MultiSelect with initial focus is rendered
5
+ Then the MultiSelect has focus
@@ -0,0 +1,22 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a MultiSelect with options and a loading flag is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'With options and loading')
5
+ })
6
+
7
+ Given(
8
+ 'a MultiSelect with options, a loading flag and a loading text is rendered',
9
+ () => {
10
+ cy.visitStory('MultiSelect', '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-multiselect-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 MultiSelect
4
+ Given a MultiSelect with options and a loading flag is rendered
5
+ When the MultiSelect input is clicked
6
+ Then the loading spinner is displayed
7
+ And the options are displayed
8
+
9
+ Scenario: The user opens a loading MultiSelect with a loading text
10
+ Given a MultiSelect with options, a loading flag and a loading text is rendered
11
+ When the MultiSelect 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 MultiSelect with more than ten options is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'With more than ten options')
5
+ })
6
+
7
+ Given(
8
+ 'a MultiSelect with more than three options and a 100px max-height is rendered',
9
+ () => {
10
+ cy.visitStory(
11
+ 'MultiSelect',
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 MultiSelect does not have an explicit max-height set
4
+ Given a MultiSelect with more than ten options is rendered
5
+ And the MultiSelect is open
6
+ Then has the default max-height
7
+
8
+ Scenario: The MultiSelect a max-height of 100px set
9
+ Given a MultiSelect with more than three options and a 100px max-height is rendered
10
+ And the MultiSelect 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 MultiSelect with a placeholder and no selection is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'With placeholder')
5
+ })
6
+
7
+ Given('a MultiSelect with a placeholder and a selection is rendered', () => {
8
+ cy.visitStory('MultiSelect', 'With placeholder and selection')
9
+ })
10
+
11
+ Then('the placeholder is shown', () => {
12
+ cy.get('[data-test="dhis2-uicore-multiselect-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-multiselect-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 MultiSelect 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 MultiSelect 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 MultiSelect with a prefix and no selection is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'With prefix')
5
+ })
6
+
7
+ Given('a MultiSelect with a prefix and a selection is rendered', () => {
8
+ cy.visitStory('MultiSelect', 'With prefix and selection')
9
+ })
10
+
11
+ Then('the prefix is shown', () => {
12
+ cy.get('[data-test="dhis2-uicore-multiselect-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 MultiSelect 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 MultiSelect with a prefix and a selection is rendered
9
+ Then the prefix is shown
10
+ And the selection is shown
@@ -0,0 +1,27 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a MultiSelect with invalid options is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'With invalid options')
5
+ })
6
+
7
+ Given('a MultiSelect with invalid filterable options is rendered', () => {
8
+ cy.visitStory('MultiSelect', 'With invalid filterable options')
9
+ })
10
+
11
+ When('the user enters a filter string', () => {
12
+ cy.get('[data-test="dhis2-uicore-multiselect-filterinput"] input').type(
13
+ 'invalid'
14
+ )
15
+ })
16
+
17
+ Then('the invalid options are displayed', () => {
18
+ cy.contains('invalid one').should('be.visible')
19
+ cy.contains('invalid two').should('be.visible')
20
+ cy.contains('invalid three').should('be.visible')
21
+ })
22
+
23
+ Then('the invalid options are not rendered', () => {
24
+ cy.contains('invalid one').should('not.exist')
25
+ cy.contains('invalid two').should('not.exist')
26
+ cy.contains('invalid three').should('not.exist')
27
+ })
@@ -0,0 +1,12 @@
1
+ Feature: Invalid MultiSelect options
2
+
3
+ Scenario: Rendering a MultiSelect with invalid options
4
+ Given a MultiSelect with invalid options is rendered
5
+ And the MultiSelect is open
6
+ Then the invalid options are displayed
7
+
8
+ Scenario: Rendering a MultiSelect with invalid filterable options
9
+ Given a MultiSelect with invalid filterable options is rendered
10
+ And the MultiSelect is open
11
+ When the user enters a filter string
12
+ Then the invalid options are not rendered
@@ -0,0 +1,81 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given(
4
+ 'a MultiSelect with a disabled option and onChange handler is rendered',
5
+ () => {
6
+ cy.visitStory('MultiSelect', 'With disabled option and on change')
7
+ }
8
+ )
9
+
10
+ Given(
11
+ 'a MultiSelect with custom options and onChange handler is rendered',
12
+ () => {
13
+ cy.visitStory('MultiSelect', '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 selected option is clicked', () => {
22
+ cy.get(
23
+ '[data-test="dhis2-uicore-multiselectoption"]:contains("option one")'
24
+ ).click()
25
+ })
26
+
27
+ When('another option is clicked', () => {
28
+ cy.contains('option two').click()
29
+ })
30
+
31
+ When("the chip's X is clicked", () => {
32
+ cy.get('[data-test="dhis2-uicore-chip-remove"]').click()
33
+ })
34
+
35
+ When('the disabled option is clicked', () => {
36
+ cy.contains('disabled option').click()
37
+ })
38
+
39
+ When('the selected option is clicked again', () => {
40
+ cy.get(
41
+ '[data-test="dhis2-uicore-multiselectoption"]:contains("option one")'
42
+ ).click()
43
+ })
44
+
45
+ Then('the clicked option is selected', () => {
46
+ cy.window().should((win) => {
47
+ expect(win.onChange).to.be.calledOnce
48
+ expect(win.onChange).to.be.calledWith({
49
+ selected: ['1'],
50
+ })
51
+ })
52
+ })
53
+
54
+ Then('the clicked option is selected as well', () => {
55
+ cy.window().should((win) => {
56
+ expect(win.onChange).to.be.calledOnce
57
+ expect(win.onChange).to.be.calledWith({
58
+ selected: ['1', '2'],
59
+ })
60
+ })
61
+ })
62
+
63
+ Then('the selected option is deselected', () => {
64
+ cy.window().should((win) => {
65
+ expect(win.onChange).to.be.calledOnce
66
+ expect(win.onChange).to.be.calledWith({ selected: [] })
67
+ })
68
+ })
69
+
70
+ Then('the onchange handler is not called', () => {
71
+ cy.window().should((win) => {
72
+ expect(win.onChange).to.not.be.called
73
+ })
74
+ })
75
+
76
+ Then('the previously selected option is deselected', () => {
77
+ cy.window().should((win) => {
78
+ expect(win.onChange).to.be.calledTwice
79
+ expect(win.onChange).to.be.calledWith({ selected: [] })
80
+ })
81
+ })
@@ -0,0 +1,44 @@
1
+ Feature: Selecting options
2
+
3
+ Scenario: The user clicks an option to select it
4
+ Given a MultiSelect with options and onChange handler is rendered
5
+ And the MultiSelect is open
6
+ When an option is clicked
7
+ Then the clicked option is selected
8
+
9
+ Scenario: The user clicks a custom option to select it
10
+ Given a MultiSelect with custom options and onChange handler is rendered
11
+ And the MultiSelect is open
12
+ When an option is clicked
13
+ Then the clicked option is selected
14
+
15
+ Scenario: The user clicks another option to select it
16
+ Given a MultiSelect with options, a selection and onChange handler is rendered
17
+ And the MultiSelect is open
18
+ When another option is clicked
19
+ Then the clicked option is selected as well
20
+
21
+ Scenario: The user clicks an option to deselect it
22
+ Given a MultiSelect with options, a selection and onChange handler is rendered
23
+ And the MultiSelect is open
24
+ When the selected option is clicked
25
+ Then the selected option is deselected
26
+
27
+ Scenario: The user clicks a chip's X to deselect it
28
+ Given a MultiSelect with options, a selection and onChange handler is rendered
29
+ When the chip's X is clicked
30
+ Then the selected option is deselected
31
+
32
+ Scenario: The user clicks a disabled option
33
+ Given a MultiSelect with a disabled option and onChange handler is rendered
34
+ And the MultiSelect is open
35
+ When the disabled option is clicked
36
+ Then the onchange handler is not called
37
+
38
+ Scenario: The user clicks an option twice to select and deselect it
39
+ Given a MultiSelect is rendered to which options can be added
40
+ And the MultiSelect is open
41
+ When an option is clicked
42
+ Then the clicked option is selected
43
+ When the selected option is clicked again
44
+ Then the previously selected option is deselected
@@ -0,0 +1,22 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given(
4
+ 'a clearable MultiSelect with a selection and onchange handler is rendered',
5
+ () => {
6
+ cy.visitStory(
7
+ 'MultiSelect',
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-multiselect-clear"]').click()
15
+ })
16
+
17
+ Then('the MultiSelect 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 MultiSelect
2
+
3
+ Scenario: The user clicks the clear button to clear the MultiSelect
4
+ Given a clearable MultiSelect with a selection and onchange handler is rendered
5
+ When the clear button is clicked
6
+ Then the MultiSelect is cleared
@@ -0,0 +1,36 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a disabled MultiSelect with options is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'With options and disabled')
5
+ })
6
+
7
+ Given('a disabled MultiSelect with options and a selection is rendered', () => {
8
+ cy.visitStory('MultiSelect', 'With options, a selection and disabled')
9
+ })
10
+
11
+ Given('the MultiSelect is closed', () => {
12
+ cy.contains('option one').should('not.exist')
13
+ cy.contains('option two').should('not.exist')
14
+ cy.contains('option three').should('not.exist')
15
+ })
16
+
17
+ Given('the MultiSelect is focused', () => {
18
+ cy.get('[data-test="dhis2-uicore-select-input"]').focus()
19
+ cy.focused().should('have.attr', 'data-test', 'dhis2-uicore-select-input')
20
+ })
21
+
22
+ When('the down arrowkey is pressed on the focused element', () => {
23
+ cy.focused().type('{downarrow}')
24
+ })
25
+
26
+ When('the spacebar is pressed on the focused element', () => {
27
+ cy.focused().type(' ')
28
+ })
29
+
30
+ When('the up arrowkey is pressed on the focused element', () => {
31
+ cy.focused().type('{uparrow}')
32
+ })
33
+
34
+ Then('the selection is displayed', () => {
35
+ cy.contains('option one').should('be.visible')
36
+ })
@@ -0,0 +1,32 @@
1
+ Feature: Disabled MultiSelect
2
+
3
+ Scenario: The disabled singleselect has a selection
4
+ Given a disabled MultiSelect with options and a selection is rendered
5
+ Then the selection is displayed
6
+
7
+ Scenario: The user clicks a disabled MultiSelect
8
+ Given a disabled MultiSelect with options is rendered
9
+ And the MultiSelect is closed
10
+ When the MultiSelect input is clicked
11
+ Then the options are not rendered
12
+
13
+ Scenario: The user presses the down arrowkey
14
+ Given a disabled MultiSelect with options is rendered
15
+ And the MultiSelect is closed
16
+ And the MultiSelect is focused
17
+ When the down arrowkey is pressed on the focused element
18
+ Then the options are not rendered
19
+
20
+ Scenario: The user presses the up arrowkey
21
+ Given a disabled MultiSelect with options is rendered
22
+ And the MultiSelect is closed
23
+ And the MultiSelect is focused
24
+ When the up arrowkey is pressed on the focused element
25
+ Then the options are not rendered
26
+
27
+ Scenario: The user presses the spacebar
28
+ Given a disabled MultiSelect with options is rendered
29
+ And the MultiSelect is closed
30
+ And the MultiSelect is focused
31
+ When the spacebar is pressed on the focused element
32
+ Then the options are not rendered
@@ -0,0 +1,28 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('an empty MultiSelect is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'Empty')
5
+ })
6
+
7
+ Given('an empty MultiSelect with custom empty text is rendered', () => {
8
+ cy.visitStory('MultiSelect', 'Empty with empty text')
9
+ })
10
+
11
+ Given('an empty MultiSelect with custom empty component is rendered', () => {
12
+ cy.visitStory('MultiSelect', 'Empty with empty component')
13
+ })
14
+
15
+ Then('an empty menu is displayed', () => {
16
+ cy.get('[data-test="dhis2-uicore-layer"]').should('exist')
17
+ })
18
+
19
+ Then('the custom empty text is displayed', () => {
20
+ cy.get('[data-test="dhis2-uicore-multiselect-empty"]')
21
+ .contains('Custom empty text')
22
+ .should('be.visible')
23
+ })
24
+
25
+ Then('the custom empty component is displayed', () => {
26
+ cy.contains('Custom empty component').should('be.visible')
27
+ cy.get('.custom-empty').should('exist')
28
+ })
@@ -0,0 +1,16 @@
1
+ Feature: Loading status
2
+
3
+ Scenario: The user opens an empty MultiSelect
4
+ Given an empty MultiSelect is rendered
5
+ When the MultiSelect input is clicked
6
+ Then an empty menu is displayed
7
+
8
+ Scenario: The user opens an empty MultiSelect with custom empty text
9
+ Given an empty MultiSelect with custom empty text is rendered
10
+ When the MultiSelect input is clicked
11
+ Then the custom empty text is displayed
12
+
13
+ Scenario: The user opens an empty MultiSelect with a custom empty component
14
+ Given an empty MultiSelect with custom empty component is rendered
15
+ When the MultiSelect input is clicked
16
+ Then the custom empty component is displayed
@@ -0,0 +1,23 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a filterable MultiSelect with options is rendered', () => {
4
+ cy.visitStory('MultiSelect', 'With filter field')
5
+ })
6
+
7
+ When('the user enters a filter string', () => {
8
+ cy.focused().type('one')
9
+ })
10
+
11
+ When("the user enters a filter string that doesn't match any options", () => {
12
+ cy.focused().type('does not exist')
13
+ })
14
+
15
+ Then('the matching options are displayed', () => {
16
+ cy.contains('option one').should('be.visible')
17
+ cy.contains('option two').should('not.exist')
18
+ cy.contains('option three').should('not.exist')
19
+ })
20
+
21
+ Then('the no match text is displayed', () => {
22
+ cy.contains('No match found').should('be.visible')
23
+ })