@telus-uds/components-base 0.0.2-prerelease.7 → 1.0.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 (445) hide show
  1. package/.eslintrc.js +9 -0
  2. package/.ultra.cache.json +1 -1
  3. package/CHANGELOG.md +71 -0
  4. package/README.md +4 -2
  5. package/__fixtures__/Accessible.js +33 -0
  6. package/__fixtures__/Accessible.native.js +32 -0
  7. package/__fixtures__/test-utils.js +25 -0
  8. package/__fixtures__/testTheme.js +438 -31
  9. package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
  10. package/__tests__/Button/ButtonGroup.test.jsx +6 -7
  11. package/__tests__/Checkbox/Checkbox.test.jsx +2 -2
  12. package/__tests__/Checkbox/CheckboxGroup.test.jsx +246 -0
  13. package/__tests__/ExpandCollapse/ExpandCollapse.test.jsx +2 -2
  14. package/__tests__/HorizontalScroll/HorizontalScroll.test.jsx +164 -0
  15. package/__tests__/Icon/Icon.test.jsx +3 -3
  16. package/__tests__/IconButton/IconButton.test.jsx +52 -0
  17. package/__tests__/Link/LinkBase.test.jsx +0 -14
  18. package/__tests__/Modal/Modal.test.jsx +47 -0
  19. package/__tests__/Notification/Notification.test.jsx +20 -0
  20. package/__tests__/Pagination/Pagination.test.jsx +2 -2
  21. package/__tests__/Progress/Progress.test.jsx +79 -0
  22. package/__tests__/Radio/Radio.test.jsx +2 -2
  23. package/__tests__/Radio/RadioGroup.test.jsx +220 -0
  24. package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
  25. package/__tests__/RadioCard/RadioCardGroup.test.jsx +246 -0
  26. package/__tests__/Search/Search.test.jsx +73 -0
  27. package/__tests__/Select/Select.test.jsx +3 -2
  28. package/__tests__/Skeleton/Skeleton.test.jsx +1 -1
  29. package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
  30. package/__tests__/Tabs/Tabs.test.jsx +40 -0
  31. package/__tests__/Tags/Tags.test.jsx +5 -6
  32. package/__tests__/TextInput/TextArea.test.jsx +3 -2
  33. package/__tests__/TextInput/TextInputBase.test.jsx +10 -5
  34. package/__tests__/ThemeProvider/ThemeProvider.test.jsx +77 -0
  35. package/__tests__/ThemeProvider/useThemeTokens.test.jsx +9 -5
  36. package/__tests__/ThemeProvider/utils/theme-tokens.test.js +41 -0
  37. package/__tests__/ToggleSwitch/ToggleSwitch.test.jsx +3 -2
  38. package/__tests__/utils/children.test.jsx +128 -0
  39. package/__tests__/utils/input.test.js +59 -1
  40. package/__tests__/utils/semantics.test.jsx +43 -0
  41. package/__tests__/utils/useCopy.test.js +14 -3
  42. package/babel.config.js +20 -0
  43. package/jest.config.js +6 -3
  44. package/lib/A11yInfoProvider/index.js +54 -26
  45. package/lib/A11yText/index.js +45 -17
  46. package/lib/ActivityIndicator/Spinner.js +81 -0
  47. package/lib/ActivityIndicator/Spinner.native.js +129 -91
  48. package/lib/ActivityIndicator/index.js +28 -12
  49. package/lib/ActivityIndicator/shared.js +27 -12
  50. package/lib/BaseProvider/index.js +34 -11
  51. package/lib/Box/Box.js +153 -35
  52. package/lib/Box/index.js +13 -2
  53. package/lib/Button/Button.js +38 -16
  54. package/lib/Button/ButtonBase.js +93 -79
  55. package/lib/Button/ButtonGroup.js +112 -73
  56. package/lib/Button/ButtonLink.js +45 -19
  57. package/lib/Button/index.js +31 -4
  58. package/lib/Button/propTypes.js +32 -9
  59. package/lib/Card/Card.js +38 -41
  60. package/lib/Card/CardBase.js +86 -0
  61. package/lib/Card/PressableCardBase.js +141 -0
  62. package/lib/Card/index.js +40 -2
  63. package/lib/Checkbox/Checkbox.js +158 -111
  64. package/lib/Checkbox/CheckboxGroup.js +241 -0
  65. package/lib/Checkbox/CheckboxInput.js +74 -0
  66. package/lib/Checkbox/CheckboxInput.native.js +9 -1
  67. package/lib/Checkbox/index.js +21 -2
  68. package/lib/Divider/Divider.js +59 -28
  69. package/lib/Divider/index.js +13 -2
  70. package/lib/ExpandCollapse/Accordion.js +26 -7
  71. package/lib/ExpandCollapse/Control.js +60 -31
  72. package/lib/ExpandCollapse/ExpandCollapse.js +50 -28
  73. package/lib/ExpandCollapse/Panel.js +83 -44
  74. package/lib/ExpandCollapse/index.js +25 -7
  75. package/lib/Feedback/Feedback.js +77 -43
  76. package/lib/Feedback/index.js +13 -2
  77. package/lib/Fieldset/Fieldset.js +165 -0
  78. package/lib/Fieldset/FieldsetContainer.js +46 -0
  79. package/lib/Fieldset/FieldsetContainer.native.js +38 -0
  80. package/lib/Fieldset/Legend.js +38 -0
  81. package/lib/Fieldset/Legend.native.js +48 -0
  82. package/lib/Fieldset/cssReset.js +21 -0
  83. package/lib/Fieldset/index.js +13 -0
  84. package/lib/FlexGrid/Col/Col.js +73 -41
  85. package/lib/FlexGrid/Col/index.js +13 -2
  86. package/lib/FlexGrid/FlexGrid.js +99 -49
  87. package/lib/FlexGrid/Row/Row.js +58 -30
  88. package/lib/FlexGrid/Row/index.js +13 -2
  89. package/lib/FlexGrid/helpers/index.js +9 -1
  90. package/lib/FlexGrid/index.js +13 -2
  91. package/lib/FlexGrid/providers/GutterContext.js +15 -3
  92. package/lib/HorizontalScroll/HorizontalScroll.js +200 -0
  93. package/lib/HorizontalScroll/HorizontalScrollButton.js +127 -0
  94. package/lib/HorizontalScroll/ScrollViewEnd.js +66 -0
  95. package/lib/HorizontalScroll/ScrollViewEnd.native.js +41 -0
  96. package/lib/HorizontalScroll/dictionary.js +18 -0
  97. package/lib/HorizontalScroll/index.js +35 -0
  98. package/lib/HorizontalScroll/itemPositions.js +128 -0
  99. package/lib/Icon/Icon.js +57 -48
  100. package/lib/Icon/IconText.js +54 -25
  101. package/lib/Icon/index.js +31 -4
  102. package/lib/IconButton/IconButton.js +140 -0
  103. package/lib/IconButton/index.js +13 -0
  104. package/lib/InputLabel/InputLabel.js +102 -40
  105. package/lib/InputLabel/LabelContent.js +41 -0
  106. package/lib/InputLabel/LabelContent.native.js +32 -6
  107. package/lib/InputLabel/index.js +13 -2
  108. package/lib/InputSupports/InputSupports.js +71 -52
  109. package/lib/InputSupports/index.js +13 -2
  110. package/lib/InputSupports/propTypes.js +19 -8
  111. package/lib/InputSupports/useInputSupports.js +41 -0
  112. package/lib/Link/ChevronLink.js +44 -20
  113. package/lib/Link/InlinePressable.js +56 -0
  114. package/lib/Link/InlinePressable.native.js +39 -15
  115. package/lib/Link/Link.js +36 -13
  116. package/lib/Link/LinkBase.js +98 -61
  117. package/lib/Link/TextButton.js +41 -17
  118. package/lib/Link/index.js +39 -5
  119. package/lib/List/List.js +55 -26
  120. package/lib/List/ListItem.js +79 -41
  121. package/lib/List/index.js +13 -2
  122. package/lib/Modal/Modal.js +231 -0
  123. package/lib/Modal/dictionary.js +16 -0
  124. package/lib/Modal/index.js +13 -0
  125. package/lib/Notification/Notification.js +216 -0
  126. package/lib/Notification/dictionary.js +15 -0
  127. package/lib/Notification/index.js +13 -0
  128. package/lib/Pagination/PageButton.js +61 -28
  129. package/lib/Pagination/Pagination.js +78 -43
  130. package/lib/Pagination/SideButton.js +73 -42
  131. package/lib/Pagination/dictionary.js +9 -2
  132. package/lib/Pagination/index.js +13 -2
  133. package/lib/Pagination/usePagination.js +12 -2
  134. package/lib/Progress/Progress.js +104 -0
  135. package/lib/Progress/ProgressBar.js +157 -0
  136. package/lib/Progress/ProgressBarBackground.js +61 -0
  137. package/lib/Progress/index.js +16 -0
  138. package/lib/Radio/Radio.js +116 -114
  139. package/lib/Radio/RadioButton.js +152 -0
  140. package/lib/Radio/RadioGroup.js +244 -0
  141. package/lib/Radio/RadioInput.js +76 -0
  142. package/lib/Radio/RadioInput.native.js +9 -1
  143. package/lib/Radio/index.js +21 -2
  144. package/lib/RadioCard/RadioCard.js +244 -0
  145. package/lib/RadioCard/RadioCardGroup.js +252 -0
  146. package/lib/RadioCard/index.js +21 -0
  147. package/lib/Search/Search.js +254 -0
  148. package/lib/Search/dictionary.js +19 -0
  149. package/lib/Search/index.js +13 -0
  150. package/lib/Select/Group.js +33 -0
  151. package/lib/Select/Group.native.js +16 -5
  152. package/lib/Select/Item.js +29 -0
  153. package/lib/Select/Item.native.js +14 -4
  154. package/lib/Select/Picker.js +84 -0
  155. package/lib/Select/Picker.native.js +73 -30
  156. package/lib/Select/Select.js +155 -85
  157. package/lib/Select/index.js +19 -6
  158. package/lib/SideNav/Item.js +63 -37
  159. package/lib/SideNav/ItemContent.js +41 -15
  160. package/lib/SideNav/ItemsGroup.js +55 -31
  161. package/lib/SideNav/SideNav.js +100 -73
  162. package/lib/SideNav/index.js +15 -1
  163. package/lib/Skeleton/Skeleton.js +64 -46
  164. package/lib/Skeleton/index.js +13 -2
  165. package/lib/Skeleton/skeleton.constant.js +12 -0
  166. package/lib/Skeleton/skeletonWebAnimation.js +27 -0
  167. package/lib/Skeleton/useSkeletonNativeAnimation.js +37 -0
  168. package/lib/Spacer/Spacer.js +49 -18
  169. package/lib/Spacer/index.js +13 -2
  170. package/lib/StackView/StackView.js +72 -31
  171. package/lib/StackView/StackWrap.js +43 -13
  172. package/lib/StackView/StackWrap.native.js +13 -2
  173. package/lib/StackView/StackWrapBox.js +77 -29
  174. package/lib/StackView/StackWrapGap.js +56 -26
  175. package/lib/StackView/common.js +23 -6
  176. package/lib/StackView/getStackedContent.js +47 -17
  177. package/lib/StackView/index.js +29 -5
  178. package/lib/StepTracker/Step.js +245 -0
  179. package/lib/StepTracker/StepTracker.js +202 -0
  180. package/lib/StepTracker/dictionary.js +17 -0
  181. package/lib/StepTracker/index.js +13 -0
  182. package/lib/Tabs/Tabs.js +124 -0
  183. package/lib/Tabs/TabsItem.js +238 -0
  184. package/lib/Tabs/index.js +13 -0
  185. package/lib/Tags/Tags.js +148 -99
  186. package/lib/Tags/index.js +13 -2
  187. package/lib/TextInput/TextArea.js +57 -28
  188. package/lib/TextInput/TextInput.js +50 -23
  189. package/lib/TextInput/TextInputBase.js +90 -63
  190. package/lib/TextInput/index.js +23 -3
  191. package/lib/TextInput/propTypes.js +18 -7
  192. package/lib/ThemeProvider/ThemeProvider.js +46 -18
  193. package/lib/ThemeProvider/index.js +61 -6
  194. package/lib/ThemeProvider/useSetTheme.js +19 -5
  195. package/lib/ThemeProvider/useTheme.js +13 -4
  196. package/lib/ThemeProvider/useThemeTokens.js +32 -16
  197. package/lib/ThemeProvider/utils/index.js +31 -2
  198. package/lib/ThemeProvider/utils/styles.js +50 -14
  199. package/lib/ThemeProvider/utils/theme-tokens.js +121 -12
  200. package/lib/ToggleSwitch/ToggleSwitch.js +85 -56
  201. package/lib/ToggleSwitch/index.js +13 -2
  202. package/lib/Tooltip/{Backdrop.web.js → Backdrop.js} +20 -8
  203. package/lib/Tooltip/Backdrop.native.js +39 -15
  204. package/lib/Tooltip/Tooltip.js +117 -74
  205. package/lib/Tooltip/dictionary.js +9 -2
  206. package/lib/Tooltip/getTooltipPosition.js +9 -1
  207. package/lib/Tooltip/index.js +13 -2
  208. package/lib/TooltipButton/TooltipButton.js +57 -38
  209. package/lib/TooltipButton/index.js +13 -2
  210. package/lib/Typography/Typography.js +87 -41
  211. package/lib/Typography/index.js +13 -2
  212. package/lib/ViewportProvider/ViewportProvider.js +34 -13
  213. package/lib/ViewportProvider/index.js +28 -3
  214. package/lib/ViewportProvider/useViewport.js +15 -3
  215. package/lib/ViewportProvider/useViewportListener.js +24 -10
  216. package/lib/index.js +539 -33
  217. package/lib/utils/a11y/index.js +31 -1
  218. package/lib/utils/a11y/semantics.js +173 -0
  219. package/lib/utils/a11y/textSize.js +23 -7
  220. package/lib/utils/animation/index.js +15 -2
  221. package/lib/utils/animation/useVerticalExpandAnimation.js +27 -10
  222. package/lib/utils/children.js +134 -0
  223. package/lib/utils/index.js +163 -10
  224. package/lib/utils/info/index.js +18 -6
  225. package/lib/utils/info/platform/index.js +19 -7
  226. package/lib/utils/info/platform/platform.android.js +8 -1
  227. package/lib/utils/info/platform/platform.ios.js +8 -1
  228. package/lib/utils/info/platform/platform.js +8 -0
  229. package/lib/utils/info/platform/platform.native.js +8 -1
  230. package/lib/utils/info/versions.js +15 -4
  231. package/lib/utils/input.js +53 -25
  232. package/lib/utils/pressability.js +38 -10
  233. package/lib/utils/propTypes.js +287 -141
  234. package/lib/utils/useCopy.js +40 -5
  235. package/lib/utils/useHash.js +52 -0
  236. package/lib/utils/useHash.native.js +15 -0
  237. package/lib/utils/useResponsiveProp.js +21 -9
  238. package/lib/utils/useSpacingScale.js +19 -9
  239. package/lib/utils/useUniqueId.js +12 -3
  240. package/package.json +14 -9
  241. package/release-context.json +4 -4
  242. package/src/A11yText/index.jsx +6 -4
  243. package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +5 -3
  244. package/src/ActivityIndicator/Spinner.native.jsx +5 -3
  245. package/src/Box/Box.jsx +132 -39
  246. package/src/Button/Button.jsx +10 -6
  247. package/src/Button/ButtonBase.jsx +99 -99
  248. package/src/Button/ButtonGroup.jsx +81 -69
  249. package/src/Button/ButtonLink.jsx +21 -15
  250. package/src/Button/propTypes.js +12 -2
  251. package/src/Card/Card.jsx +5 -31
  252. package/src/Card/CardBase.jsx +59 -0
  253. package/src/Card/PressableCardBase.jsx +119 -0
  254. package/src/Card/index.js +3 -0
  255. package/src/Checkbox/Checkbox.jsx +121 -112
  256. package/src/Checkbox/CheckboxGroup.jsx +206 -0
  257. package/src/Checkbox/{CheckboxInput.web.jsx → CheckboxInput.jsx} +0 -0
  258. package/src/Checkbox/index.js +2 -0
  259. package/src/Divider/Divider.jsx +7 -4
  260. package/src/ExpandCollapse/Accordion.jsx +3 -2
  261. package/src/ExpandCollapse/Control.jsx +40 -43
  262. package/src/ExpandCollapse/ExpandCollapse.jsx +26 -23
  263. package/src/ExpandCollapse/Panel.jsx +69 -63
  264. package/src/Feedback/Feedback.jsx +36 -33
  265. package/src/Fieldset/Fieldset.jsx +136 -0
  266. package/src/Fieldset/FieldsetContainer.jsx +31 -0
  267. package/src/Fieldset/FieldsetContainer.native.jsx +19 -0
  268. package/src/Fieldset/Legend.jsx +21 -0
  269. package/src/Fieldset/Legend.native.jsx +27 -0
  270. package/src/Fieldset/cssReset.js +14 -0
  271. package/src/Fieldset/index.js +3 -0
  272. package/src/FlexGrid/Col/Col.jsx +139 -132
  273. package/src/FlexGrid/FlexGrid.jsx +79 -51
  274. package/src/FlexGrid/Row/Row.jsx +55 -48
  275. package/src/HorizontalScroll/HorizontalScroll.jsx +168 -0
  276. package/src/HorizontalScroll/HorizontalScrollButton.jsx +105 -0
  277. package/src/HorizontalScroll/ScrollViewEnd.jsx +53 -0
  278. package/src/HorizontalScroll/ScrollViewEnd.native.jsx +24 -0
  279. package/src/HorizontalScroll/dictionary.js +11 -0
  280. package/src/HorizontalScroll/index.js +17 -0
  281. package/src/HorizontalScroll/itemPositions.js +101 -0
  282. package/src/Icon/Icon.jsx +43 -50
  283. package/src/Icon/IconText.jsx +23 -18
  284. package/src/Icon/index.js +2 -2
  285. package/src/IconButton/IconButton.jsx +114 -0
  286. package/src/IconButton/index.js +3 -0
  287. package/src/InputLabel/InputLabel.jsx +57 -35
  288. package/src/InputLabel/LabelContent.jsx +21 -0
  289. package/src/InputLabel/LabelContent.native.jsx +11 -2
  290. package/src/InputSupports/InputSupports.jsx +29 -45
  291. package/src/InputSupports/useInputSupports.js +30 -0
  292. package/src/Link/ChevronLink.jsx +26 -16
  293. package/src/Link/{InlinePressable.web.jsx → InlinePressable.jsx} +5 -3
  294. package/src/Link/InlinePressable.native.jsx +5 -3
  295. package/src/Link/Link.jsx +22 -16
  296. package/src/Link/LinkBase.jsx +76 -65
  297. package/src/Link/TextButton.jsx +30 -23
  298. package/src/List/List.jsx +5 -4
  299. package/src/List/ListItem.jsx +77 -82
  300. package/src/Modal/Modal.jsx +190 -0
  301. package/src/Modal/dictionary.js +9 -0
  302. package/src/Modal/index.js +3 -0
  303. package/src/Notification/Notification.jsx +164 -0
  304. package/src/Notification/dictionary.js +8 -0
  305. package/src/Notification/index.js +3 -0
  306. package/src/Pagination/PageButton.jsx +42 -35
  307. package/src/Pagination/Pagination.jsx +88 -92
  308. package/src/Pagination/SideButton.jsx +44 -41
  309. package/src/Progress/Progress.jsx +78 -0
  310. package/src/Progress/ProgressBar.jsx +123 -0
  311. package/src/Progress/ProgressBarBackground.jsx +36 -0
  312. package/src/Progress/index.js +6 -0
  313. package/src/Radio/Radio.jsx +82 -112
  314. package/src/Radio/RadioButton.jsx +142 -0
  315. package/src/Radio/RadioGroup.jsx +209 -0
  316. package/src/Radio/{RadioInput.web.jsx → RadioInput.jsx} +0 -0
  317. package/src/Radio/index.js +2 -0
  318. package/src/RadioCard/RadioCard.jsx +198 -0
  319. package/src/RadioCard/RadioCardGroup.jsx +218 -0
  320. package/src/RadioCard/index.js +5 -0
  321. package/src/Search/Search.jsx +225 -0
  322. package/src/Search/dictionary.js +12 -0
  323. package/src/Search/index.js +3 -0
  324. package/src/Select/{Group.web.jsx → Group.jsx} +0 -0
  325. package/src/Select/{Item.web.jsx → Item.jsx} +0 -0
  326. package/src/Select/Picker.jsx +74 -0
  327. package/src/Select/Picker.native.jsx +56 -49
  328. package/src/Select/Select.jsx +125 -92
  329. package/src/SideNav/Item.jsx +54 -47
  330. package/src/SideNav/ItemsGroup.jsx +50 -43
  331. package/src/SideNav/SideNav.jsx +68 -60
  332. package/src/Skeleton/Skeleton.jsx +25 -32
  333. package/src/Skeleton/skeleton.constant.js +3 -0
  334. package/src/Skeleton/skeletonWebAnimation.js +13 -0
  335. package/src/Skeleton/useSkeletonNativeAnimation.js +27 -0
  336. package/src/Spacer/Spacer.jsx +11 -4
  337. package/src/StackView/StackView.jsx +54 -23
  338. package/src/StackView/StackWrap.jsx +16 -7
  339. package/src/StackView/StackWrapBox.jsx +63 -28
  340. package/src/StackView/StackWrapGap.jsx +46 -24
  341. package/src/StackView/common.jsx +3 -2
  342. package/src/StackView/getStackedContent.jsx +8 -2
  343. package/src/StepTracker/Step.jsx +202 -0
  344. package/src/StepTracker/StepTracker.jsx +174 -0
  345. package/src/StepTracker/dictionary.js +10 -0
  346. package/src/StepTracker/index.js +3 -0
  347. package/src/Tabs/Tabs.jsx +97 -0
  348. package/src/Tabs/TabsItem.jsx +212 -0
  349. package/src/Tabs/index.js +3 -0
  350. package/src/Tags/Tags.jsx +115 -102
  351. package/src/TextInput/TextArea.jsx +5 -4
  352. package/src/TextInput/TextInput.jsx +5 -4
  353. package/src/TextInput/TextInputBase.jsx +95 -98
  354. package/src/ThemeProvider/ThemeProvider.jsx +11 -7
  355. package/src/ThemeProvider/useSetTheme.js +4 -0
  356. package/src/ThemeProvider/useThemeTokens.js +2 -2
  357. package/src/ThemeProvider/utils/styles.js +18 -5
  358. package/src/ThemeProvider/utils/theme-tokens.js +74 -5
  359. package/src/ToggleSwitch/ToggleSwitch.jsx +50 -52
  360. package/src/Tooltip/{Backdrop.web.jsx → Backdrop.jsx} +0 -0
  361. package/src/Tooltip/Tooltip.jsx +135 -131
  362. package/src/TooltipButton/TooltipButton.jsx +23 -27
  363. package/src/Typography/Typography.jsx +71 -47
  364. package/src/index.js +23 -2
  365. package/src/utils/a11y/index.js +1 -0
  366. package/src/utils/a11y/semantics.js +162 -0
  367. package/src/utils/children.jsx +119 -0
  368. package/src/utils/index.js +3 -0
  369. package/src/utils/info/platform/platform.js +1 -0
  370. package/src/utils/info/versions.js +2 -2
  371. package/src/utils/input.js +36 -25
  372. package/src/utils/pressability.js +4 -0
  373. package/src/utils/propTypes.js +199 -72
  374. package/src/utils/useCopy.js +30 -4
  375. package/src/utils/useHash.js +39 -0
  376. package/src/utils/useHash.native.js +6 -0
  377. package/stories/A11yText/A11yText.stories.jsx +6 -10
  378. package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +1 -1
  379. package/stories/Box/Box.stories.jsx +1 -1
  380. package/stories/Button/Button.stories.jsx +2 -2
  381. package/stories/Button/ButtonGroup.stories.jsx +1 -1
  382. package/stories/Button/ButtonLink.stories.jsx +1 -1
  383. package/stories/Card/Card.stories.jsx +1 -1
  384. package/stories/Checkbox/Checkbox.stories.jsx +24 -1
  385. package/stories/Divider/Divider.stories.jsx +1 -1
  386. package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +2 -2
  387. package/stories/Feedback/Feedback.stories.jsx +1 -1
  388. package/stories/FlexGrid/01 FlexGrid.stories.jsx +1 -1
  389. package/stories/FlexGrid/02 Row.stories.jsx +1 -1
  390. package/stories/FlexGrid/03 Col.stories.jsx +1 -1
  391. package/stories/Icon/Icon.stories.jsx +27 -7
  392. package/stories/IconButton/IconButton.stories.jsx +50 -0
  393. package/stories/InputLabel/InputLabel.stories.jsx +1 -1
  394. package/stories/Link/ChevronLink.stories.jsx +1 -1
  395. package/stories/Link/Link.stories.jsx +17 -21
  396. package/stories/Link/TextButton.stories.jsx +1 -1
  397. package/stories/List/List.stories.jsx +1 -1
  398. package/stories/Modal/Modal.stories.jsx +29 -0
  399. package/stories/Notification/Notification.stories.jsx +82 -0
  400. package/stories/Pagination/Pagination.stories.jsx +1 -1
  401. package/stories/Progress/Progress.stories.jsx +93 -0
  402. package/stories/Radio/Radio.stories.jsx +23 -36
  403. package/stories/RadioCard/RadioCard.stories.jsx +98 -0
  404. package/stories/Search/Search.stories.jsx +16 -0
  405. package/stories/Select/Select.stories.jsx +1 -1
  406. package/stories/SideNav/SideNav.stories.jsx +1 -1
  407. package/stories/SideNav/SideNavItem.stories.jsx +1 -1
  408. package/stories/SideNav/SideNavItemsGroup.stories.jsx +1 -1
  409. package/stories/Skeleton/Skeleton.stories.jsx +2 -2
  410. package/stories/Spacer/Spacer.stories.jsx +1 -1
  411. package/stories/StackView/StackView.stories.jsx +1 -1
  412. package/stories/StackView/StackWrap.stories.jsx +1 -1
  413. package/stories/StepTracker/StepTracker.stories.jsx +71 -0
  414. package/stories/Tabs/Tabs.stories.jsx +97 -0
  415. package/stories/Tags/Tags.stories.jsx +1 -1
  416. package/stories/TextInput/TextArea.stories.jsx +1 -1
  417. package/stories/TextInput/TextInput.stories.jsx +1 -1
  418. package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +1 -1
  419. package/stories/Tooltip/Tooltip.stories.jsx +1 -1
  420. package/stories/TooltipButton/TooltipButton.stories.jsx +1 -1
  421. package/stories/Typography/Typography.stories.jsx +1 -1
  422. package/stories/{platform-supports.web.jsx → platform-supports.jsx} +1 -1
  423. package/stories/supports.jsx +37 -3
  424. package/__fixtures__/accessible.icon.svg +0 -6
  425. package/babel.config.json +0 -8
  426. package/docs/Contributing.stories.mdx +0 -9
  427. package/docs/Fonts.stories.mdx +0 -104
  428. package/docs/Icons.stories.mdx +0 -144
  429. package/docs/Introduction.stories.mdx +0 -9
  430. package/lib/ActivityIndicator/Spinner.web.js +0 -55
  431. package/lib/Checkbox/CheckboxInput.web.js +0 -57
  432. package/lib/InputLabel/LabelContent.web.js +0 -17
  433. package/lib/Link/InlinePressable.web.js +0 -32
  434. package/lib/Radio/RadioInput.web.js +0 -59
  435. package/lib/Select/Group.web.js +0 -18
  436. package/lib/Select/Item.web.js +0 -15
  437. package/lib/Select/Picker.web.js +0 -63
  438. package/lib/config/svgr-icons-web.js +0 -9
  439. package/lib/config/svgr-icons.js +0 -52
  440. package/lib/utils/info/platform/platform.web.js +0 -1
  441. package/src/InputLabel/LabelContent.web.jsx +0 -13
  442. package/src/Select/Picker.web.jsx +0 -67
  443. package/src/config/svgr-icons-web.js +0 -11
  444. package/src/config/svgr-icons.js +0 -46
  445. package/src/utils/info/platform/platform.web.js +0 -1
@@ -0,0 +1,246 @@
1
+ import React from 'react'
2
+ import { render, fireEvent } from '@testing-library/react-native'
3
+ import { toHaveTextContent } from '@testing-library/jest-native'
4
+
5
+ import Theme from '../../__fixtures__/Theme'
6
+ import CheckboxGroup from '../../src/Checkbox/CheckboxGroup'
7
+
8
+ const items = [
9
+ { label: 'One', id: 'one' },
10
+ { label: 'Two', id: 'two' },
11
+ { label: 'Three', id: 'three' },
12
+ { label: 'Four', id: 'four' }
13
+ ]
14
+ const checked = { checked: true }
15
+
16
+ // expect().toHaveTextContent doesn't work on arrays, expect().toContain etc doesn't match elements
17
+ const containsText = (queryResult, text) =>
18
+ queryResult.some((testInstance) => toHaveTextContent(testInstance, text).pass)
19
+
20
+ describe('CheckboxGroup', () => {
21
+ // eslint-disable-next-line no-console
22
+ const consoleError = console.error
23
+ beforeEach(() => {
24
+ // eslint-disable-next-line no-console
25
+ console.error = () => {}
26
+ })
27
+ afterEach(() => {
28
+ // eslint-disable-next-line no-console
29
+ console.error = consoleError
30
+ })
31
+
32
+ it('Throws if has `checkedIds` without `onChange`', () => {
33
+ expect(() =>
34
+ render(
35
+ <Theme>
36
+ <CheckboxGroup items={items} checkedIds={['one']} />
37
+ </Theme>
38
+ )
39
+ ).toThrow(/values.+without.+onChange/)
40
+ })
41
+ it("Doesn't throw if has `checkedIds` without `onChange` and is read only", () => {
42
+ expect(() =>
43
+ render(
44
+ <Theme>
45
+ <CheckboxGroup items={items} checkedIds={['one']} readOnly />
46
+ </Theme>
47
+ )
48
+ ).not.toThrow()
49
+ })
50
+ it('Throws if has both `checkedIds` and `initialCheckedIds`', () => {
51
+ expect(() =>
52
+ render(
53
+ <Theme>
54
+ <CheckboxGroup
55
+ items={items}
56
+ checkedIds={['one']}
57
+ initialCheckedIds={['one']}
58
+ onChange={() => {}}
59
+ />
60
+ </Theme>
61
+ )
62
+ ).toThrow(/both(?=.*initialValues)(?=.*values){2}/)
63
+ })
64
+ })
65
+
66
+ describe('CheckboxGroup (uncontrolled)', () => {
67
+ it('Selects unlimited items', async () => {
68
+ const { getByText, queryAllByA11yState } = render(
69
+ <Theme>
70
+ <CheckboxGroup items={items} />
71
+ </Theme>
72
+ )
73
+
74
+ expect(queryAllByA11yState(checked)).toHaveLength(0)
75
+
76
+ const one = getByText('One')
77
+ await fireEvent.press(one)
78
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
79
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
80
+
81
+ const two = getByText('Two')
82
+ await fireEvent.press(two)
83
+ expect(queryAllByA11yState(checked)).toHaveLength(2)
84
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
85
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
86
+
87
+ const three = getByText('Three')
88
+ await fireEvent.press(three)
89
+ expect(queryAllByA11yState(checked)).toHaveLength(3)
90
+ expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
91
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
92
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
93
+
94
+ const four = getByText('Four')
95
+ await fireEvent.press(four)
96
+ expect(queryAllByA11yState(checked)).toHaveLength(4)
97
+ expect(containsText(queryAllByA11yState(checked), 'Four')).toBeTruthy()
98
+ expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
99
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
100
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
101
+ })
102
+
103
+ it('Deselects if the selected item is pressed', async () => {
104
+ const { getByText, queryAllByA11yState } = render(
105
+ <Theme>
106
+ <CheckboxGroup items={items} />
107
+ </Theme>
108
+ )
109
+
110
+ expect(queryAllByA11yState(checked)).toHaveLength(0)
111
+
112
+ const three = getByText('Three')
113
+ await fireEvent.press(three)
114
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
115
+ expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
116
+
117
+ await fireEvent.press(three)
118
+ expect(queryAllByA11yState(checked)).toHaveLength(0)
119
+ expect(containsText(queryAllByA11yState(checked), 'Three')).not.toBeTruthy()
120
+ })
121
+
122
+ it('Is accessible as checkboxes button', async () => {
123
+ const { queryAllByA11yRole, queryAllByA11yState } = render(
124
+ <Theme>
125
+ <CheckboxGroup items={items} />
126
+ </Theme>
127
+ )
128
+
129
+ expect(queryAllByA11yRole('radiogroup')).toHaveLength(0)
130
+ expect(queryAllByA11yRole('radio')).toHaveLength(0)
131
+
132
+ const checks = queryAllByA11yRole('checkbox')
133
+ expect(checks).toHaveLength(4)
134
+
135
+ expect(queryAllByA11yState(checked)).toHaveLength(0)
136
+ await fireEvent.press(checks[0])
137
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
138
+ })
139
+
140
+ it('Auto-selects any provided initialCheckedIds', async () => {
141
+ const { getByText, queryAllByA11yState } = render(
142
+ <Theme>
143
+ <CheckboxGroup items={items} initialCheckedIds={['one', 'two']} />
144
+ </Theme>
145
+ )
146
+ expect(queryAllByA11yState(checked)).toHaveLength(2)
147
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
148
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
149
+
150
+ const three = getByText('Three')
151
+ await fireEvent.press(three)
152
+
153
+ expect(queryAllByA11yState(checked)).toHaveLength(3)
154
+ expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
155
+ expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
156
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
157
+ })
158
+ })
159
+
160
+ describe('CheckboxGroup (controlled)', () => {
161
+ it('Calls onChange handler on press in controlled mode, providing pressed id', async () => {
162
+ const handleChange = jest.fn((arg) => arg)
163
+ const { getByText } = render(
164
+ <Theme>
165
+ <CheckboxGroup items={items} checkedIds={[]} onChange={handleChange} />
166
+ </Theme>
167
+ )
168
+
169
+ expect(handleChange).toHaveBeenCalledTimes(0)
170
+
171
+ const one = getByText('One')
172
+ await fireEvent(one, 'press', { nativeEvent: 'example' })
173
+ expect(handleChange).toHaveBeenCalledTimes(1)
174
+ expect(handleChange).toHaveBeenLastCalledWith(['one'], { nativeEvent: 'example' })
175
+
176
+ const two = getByText('Two')
177
+ await fireEvent(two, 'press', { nativeEvent: 'example2' })
178
+ expect(handleChange).toHaveBeenCalledTimes(2)
179
+ expect(handleChange).toHaveBeenLastCalledWith(['two'], { nativeEvent: 'example2' })
180
+ })
181
+
182
+ it("Doesn't change its own selection if `checkedIds` is passed", async () => {
183
+ const { getByText, queryAllByA11yState } = render(
184
+ <Theme>
185
+ <CheckboxGroup items={items} checkedIds={['one']} onChange={() => {}} />
186
+ </Theme>
187
+ )
188
+
189
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
190
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
191
+
192
+ const one = getByText('One')
193
+ await fireEvent.press(one)
194
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
195
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
196
+
197
+ const two = getByText('Two')
198
+ await fireEvent.press(two)
199
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
200
+ expect(containsText(queryAllByA11yState(checked), 'Two')).not.toBeTruthy()
201
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
202
+ })
203
+ })
204
+
205
+ describe('CheckboxGroup (read-only)', () => {
206
+ it("Doesn't call onChange handler when read-only", async () => {
207
+ const handleChange = jest.fn((arg) => arg)
208
+ const { getByText } = render(
209
+ <Theme>
210
+ <CheckboxGroup items={items} checkedIds={[]} onChange={handleChange} readOnly />
211
+ </Theme>
212
+ )
213
+
214
+ expect(handleChange).toHaveBeenCalledTimes(0)
215
+
216
+ const one = getByText('One')
217
+ await fireEvent.press(one)
218
+ expect(handleChange).toHaveBeenCalledTimes(0)
219
+
220
+ const two = getByText('Two')
221
+ await fireEvent.press(two)
222
+ expect(handleChange).toHaveBeenCalledTimes(0)
223
+ })
224
+
225
+ it("Doesn't change its selection on press", async () => {
226
+ const { getByText, queryAllByA11yState } = render(
227
+ <Theme>
228
+ <CheckboxGroup items={items} checkedIds={['one']} readOnly />
229
+ </Theme>
230
+ )
231
+
232
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
233
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
234
+
235
+ const one = getByText('One')
236
+ await fireEvent.press(one)
237
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
238
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
239
+
240
+ const two = getByText('Two')
241
+ await fireEvent.press(two)
242
+ expect(queryAllByA11yState(checked)).toHaveLength(1)
243
+ expect(containsText(queryAllByA11yState(checked), 'Two')).not.toBeTruthy()
244
+ expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
245
+ })
246
+ })
@@ -64,10 +64,10 @@ describe('ExpandCollapse', () => {
64
64
  expect(onPress).toHaveBeenCalledTimes(0)
65
65
  expect(queryAllByA11yState({ expanded: true }).length).toBe(0)
66
66
 
67
- await fireEvent.press(getByText('First control'))
67
+ await fireEvent(getByText('First control'), 'press', { nativeEvent: 'example' })
68
68
  expect(queryAllByA11yState({ expanded: true }).length).toBe(1)
69
69
  expect(onPress).toHaveBeenCalledTimes(1)
70
- expect(onPress).toHaveBeenLastCalledWith(panelId)
70
+ expect(onPress).toHaveBeenLastCalledWith(panelId, { nativeEvent: 'example' })
71
71
  })
72
72
  })
73
73
 
@@ -0,0 +1,164 @@
1
+ import React, { useState } from 'react'
2
+ import { Pressable, Text, View } from 'react-native'
3
+ import { fireEvent, render } from '@testing-library/react-native'
4
+ import {
5
+ getItemPositionLayoutHandler,
6
+ getItemPositionScrollTarget,
7
+ useItemPositions
8
+ } from '../../src/HorizontalScroll/itemPositions'
9
+
10
+ // ScrollViewRef.scrollTo doesn't work in Jest - unit-test the utilities instead
11
+ describe('HorizontalScroll', () => {
12
+ describe('getItemPositionScrollTarget', () => {
13
+ const positionsWithoutSpacing = {
14
+ 0: { start: 0, end: 100 },
15
+ 1: { start: 100, end: 200 },
16
+ 2: { start: 200, end: 300 }
17
+ }
18
+ const positions = {
19
+ 0: { start: 0, end: 50 },
20
+ 1: { start: 100, end: 150 },
21
+ 2: { start: 200, end: 250 }
22
+ }
23
+ it('scrolls to the start of an item rather than chopping it', () => {
24
+ const x = getItemPositionScrollTarget(150, 300, positionsWithoutSpacing)
25
+ expect(x).toBe(100)
26
+ })
27
+ it('offsets the position by a button clearance', () => {
28
+ const x = getItemPositionScrollTarget(150, 300, positionsWithoutSpacing, 20)
29
+ expect(x).toBe(80)
30
+ })
31
+ it('scrolls exactly if landing on a gap', () => {
32
+ const x = getItemPositionScrollTarget(170, 300, positions)
33
+ expect(x).toBe(170)
34
+ })
35
+ it('applies button clearance if landing on a gap', () => {
36
+ const x = getItemPositionScrollTarget(170, 300, positions, 40)
37
+ expect(x).toBe(130)
38
+ })
39
+ it('does not apply button clearance on reaching the end', () => {
40
+ const x = getItemPositionScrollTarget(300, 300, positions, 40)
41
+ expect(x).toBe(300)
42
+ })
43
+ it('does not exceed the maximum', () => {
44
+ const x = getItemPositionScrollTarget(320, 300, positions, 40)
45
+ expect(x).toBe(300)
46
+ })
47
+ it('does not go below 0', () => {
48
+ const x = getItemPositionScrollTarget(-420, 300, positions, 40)
49
+ expect(x).toBe(0)
50
+ })
51
+ })
52
+
53
+ // onLayout also doesn't work naturally in jest
54
+ describe('getItemPositionLayoutHandler', () => {
55
+ // Test component using useItemPositions with getItemPositionLayoutHandler
56
+ // that can be rerendered manually and that outputs itemPositions value
57
+ const MockComponent = () => {
58
+ const [num, setNum] = useState()
59
+ const [{ positions }] = useItemPositions()
60
+ return (
61
+ <View>
62
+ <View testID="onlayout[0]" onLayout={getItemPositionLayoutHandler(positions, 0)} />
63
+ <View testID="onlayout[1]" onLayout={getItemPositionLayoutHandler(positions, 1)} />
64
+ <Text testID="output">{JSON.stringify(positions)}</Text>
65
+ <Pressable testID="rerender" onPress={() => setNum(num + 1)}>
66
+ <Text>{num}</Text>
67
+ </Pressable>
68
+ </View>
69
+ )
70
+ }
71
+ it('gets width and x positions from onLayout events', async () => {
72
+ const { getByTestId } = render(<MockComponent />)
73
+
74
+ // onLayout doesn't work in jest but can be called directly as an event, but we
75
+ // have to pass the event object. Can't test that it gets them correctly from style
76
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
77
+ nativeEvent: {
78
+ layout: {
79
+ width: 200,
80
+ x: 0
81
+ }
82
+ }
83
+ })
84
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
85
+ nativeEvent: {
86
+ layout: {
87
+ width: 100,
88
+ x: 250
89
+ }
90
+ }
91
+ })
92
+ await fireEvent.press(getByTestId('rerender'))
93
+ expect(getByTestId('output')).toHaveTextContent(
94
+ '{"0":{"start":0,"end":200},"1":{"start":250,"end":350}}'
95
+ )
96
+ })
97
+ it('does not cause a rerender from onLayout events alone', async () => {
98
+ const { getByTestId } = render(<MockComponent />)
99
+
100
+ expect(getByTestId('output')).toHaveTextContent('{}')
101
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
102
+ nativeEvent: {
103
+ layout: {
104
+ width: 200,
105
+ x: 0
106
+ }
107
+ }
108
+ })
109
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
110
+ nativeEvent: {
111
+ layout: {
112
+ width: 100,
113
+ x: 250
114
+ }
115
+ }
116
+ })
117
+ expect(getByTestId('output')).toHaveTextContent('{}')
118
+ })
119
+ })
120
+
121
+ describe('useItemPositions', () => {
122
+ // Again we're limited in what we can test; we can't test natural onLayout
123
+ // or page load timing, but we can affirm that calling `setIsReady` after layout
124
+ // events causes a re-render that can access positions data
125
+ const IsReadyMockComponent = () => {
126
+ const [{ positions, setIsReady }] = useItemPositions()
127
+ return (
128
+ <View testID="container" onLayout={setIsReady}>
129
+ <View testID="onlayout[0]" onLayout={getItemPositionLayoutHandler(positions, 0)} />
130
+ <View testID="onlayout[1]" onLayout={getItemPositionLayoutHandler(positions, 1)} />
131
+ <Text testID="output">{JSON.stringify(positions)}</Text>
132
+ </View>
133
+ )
134
+ }
135
+ it('causes a rerender when setIsReady is called', async () => {
136
+ const { getByTestId } = render(<IsReadyMockComponent />)
137
+
138
+ expect(getByTestId('output')).toHaveTextContent('{}')
139
+ await fireEvent(getByTestId('onlayout[0]'), 'layout', {
140
+ nativeEvent: {
141
+ layout: {
142
+ width: 200,
143
+ x: 0
144
+ }
145
+ }
146
+ })
147
+ await fireEvent(getByTestId('onlayout[1]'), 'layout', {
148
+ nativeEvent: {
149
+ layout: {
150
+ width: 100,
151
+ x: 250
152
+ }
153
+ }
154
+ })
155
+ await fireEvent(getByTestId('container'), 'layout', {
156
+ nativeEvent: { layout: {} }
157
+ })
158
+
159
+ expect(getByTestId('output')).toHaveTextContent(
160
+ '{"0":{"start":0,"end":200},"1":{"start":250,"end":350}}'
161
+ )
162
+ })
163
+ })
164
+ })
@@ -16,7 +16,7 @@ describe('Icon', () => {
16
16
  it('gets default styles from theme', () => {
17
17
  const { getByTestId } = render(
18
18
  <Theme>
19
- <Icon IconSvg={InnerComponent} />
19
+ <Icon icon={InnerComponent} />
20
20
  </Theme>
21
21
  )
22
22
 
@@ -29,7 +29,7 @@ describe('Icon', () => {
29
29
  it('gets styles from variant', () => {
30
30
  const { getByTestId } = render(
31
31
  <Theme>
32
- <Icon IconSvg={InnerComponent} variant={{ size: 'small' }} />
32
+ <Icon icon={InnerComponent} variant={{ size: 'small' }} />
33
33
  </Theme>
34
34
  )
35
35
 
@@ -46,7 +46,7 @@ describe('Icon', () => {
46
46
  const props = { tokens: { size: 30 } }
47
47
  const { getByTestId } = render(
48
48
  <Theme>
49
- <Icon IconSvg={InnerComponent} {...props} />
49
+ <Icon icon={InnerComponent} {...props} />
50
50
  </Theme>
51
51
  )
52
52
 
@@ -0,0 +1,52 @@
1
+ import React from 'react'
2
+ import { fireEvent, render } from '@testing-library/react-native'
3
+
4
+ import { IconButton } from '../../src'
5
+ import Theme from '../../__fixtures__/Theme'
6
+
7
+ describe('IconButton', () => {
8
+ it('renders a link if href is passed', () => {
9
+ const { queryByRole } = render(<IconButton href="https://telus.com" icon={() => null} />, {
10
+ wrapper: Theme
11
+ })
12
+
13
+ expect(queryByRole('link')).toBeTruthy()
14
+
15
+ expect(queryByRole('button')).toBeFalsy()
16
+ })
17
+
18
+ it('renders a button if onPress is passed', () => {
19
+ const { queryByRole } = render(<IconButton onPress={() => {}} icon={() => null} />, {
20
+ wrapper: Theme
21
+ })
22
+
23
+ expect(queryByRole('button')).toBeTruthy()
24
+
25
+ expect(queryByRole('link')).toBeFalsy()
26
+ })
27
+
28
+ it('renders an accessible label', () => {
29
+ const { getByA11yLabel } = render(
30
+ <IconButton onPress={() => {}} icon={() => null} accessibilityLabel="test label" />,
31
+ {
32
+ wrapper: Theme
33
+ }
34
+ )
35
+
36
+ expect(getByA11yLabel('test label')).toBeTruthy()
37
+ })
38
+
39
+ it('calls onPress function when pressed', async () => {
40
+ const handlePress = jest.fn()
41
+ const { getByA11yLabel } = render(
42
+ <IconButton onPress={handlePress} icon={() => null} accessibilityLabel="test label" />,
43
+ {
44
+ wrapper: Theme
45
+ }
46
+ )
47
+ const iconButton = getByA11yLabel('test label')
48
+ expect(handlePress).toHaveBeenCalledTimes(0)
49
+ await fireEvent.press(iconButton)
50
+ expect(handlePress).toHaveBeenCalledTimes(1)
51
+ })
52
+ })
@@ -8,20 +8,6 @@ import LinkBase from '../../src/Link/LinkBase'
8
8
  beforeEach(() => jest.clearAllMocks())
9
9
 
10
10
  describe('LinkBase', () => {
11
- it('throws if both href and onPress are provided', async () => {
12
- jest.spyOn(console, 'error').mockImplementation()
13
- expect(() =>
14
- render(
15
- <Theme>
16
- <LinkBase href="example.com" onPress={jest.fn()}>
17
- click me
18
- </LinkBase>
19
- </Theme>
20
- )
21
- ).toThrow()
22
- expect(console.error).toHaveBeenCalledTimes(1)
23
- })
24
-
25
11
  it('throws if neither href nor onPress are provided', async () => {
26
12
  jest.spyOn(console, 'error').mockImplementation()
27
13
  expect(() =>
@@ -0,0 +1,47 @@
1
+ import React from 'react'
2
+ import { Text } from 'react-native'
3
+ import { fireEvent, render } from '@testing-library/react-native'
4
+
5
+ import { Modal } from '../../src'
6
+ import Theme from '../../__fixtures__/Theme'
7
+
8
+ describe('Modal', () => {
9
+ it('is not rendered when closed', () => {
10
+ const { queryByText } = render(
11
+ <Modal>
12
+ <Text>Test content</Text>
13
+ </Modal>,
14
+ { wrapper: Theme }
15
+ )
16
+
17
+ expect(queryByText('Test content')).toBeFalsy()
18
+ })
19
+
20
+ it('is rendered when open', () => {
21
+ const { queryByText } = render(
22
+ <Modal isOpen>
23
+ <Text>Test content</Text>
24
+ </Modal>,
25
+ { wrapper: Theme }
26
+ )
27
+
28
+ expect(queryByText('Test content')).not.toBeFalsy()
29
+ })
30
+
31
+ it('onClose callback is triggered when closing', () => {
32
+ const onClose = jest.fn()
33
+
34
+ const { getByA11yRole } = render(
35
+ <Modal isOpen onClose={onClose}>
36
+ <Text>Test content</Text>
37
+ </Modal>,
38
+ { wrapper: Theme }
39
+ )
40
+
41
+ expect(onClose).not.toHaveBeenCalled()
42
+
43
+ fireEvent.press(getByA11yRole('button'))
44
+
45
+ expect(onClose).toHaveBeenCalledTimes(1)
46
+ })
47
+ })
@@ -0,0 +1,20 @@
1
+ import React from 'react'
2
+ import { fireEvent, render } from '@testing-library/react-native'
3
+
4
+ import { Notification } from '../../src'
5
+ import Theme from '../../__fixtures__/Theme'
6
+
7
+ describe('Notification', () => {
8
+ it('is removed when dismiss button is pressed', () => {
9
+ const content = 'Notification content lands here'
10
+ const { getByRole, getByText } = render(<Notification dismissible>{content}</Notification>, {
11
+ wrapper: Theme
12
+ })
13
+
14
+ expect(() => getByText(content)).not.toThrow()
15
+
16
+ fireEvent.press(getByRole('button'))
17
+
18
+ expect(() => getByText(content)).toThrow()
19
+ })
20
+ })
@@ -114,7 +114,7 @@ describe('Pagination', () => {
114
114
 
115
115
  expect(button).toHaveProp('accessibilityRole', 'link')
116
116
  expect(button).toHaveProp('href', 'test-url')
117
- expect(button).toHaveProp('target', '_blank')
117
+ expect(button).toHaveProp('hrefAttrs', { target: '_blank' })
118
118
  })
119
119
  })
120
120
 
@@ -154,7 +154,7 @@ describe('Pagination', () => {
154
154
 
155
155
  expect(button).toHaveProp('accessibilityRole', 'link')
156
156
  expect(button).toHaveProp('href', 'test-url')
157
- expect(button).toHaveProp('target', '_blank')
157
+ expect(button).toHaveProp('hrefAttrs', { target: '_blank' })
158
158
  })
159
159
  })
160
160
  })
@@ -0,0 +1,79 @@
1
+ import React from 'react'
2
+ import { Text } from 'react-native'
3
+ import { render, within } from '@testing-library/react-native'
4
+
5
+ import { Progress } from '../../src'
6
+ import Theme from '../../__fixtures__/Theme'
7
+
8
+ const barTokens = {
9
+ backgroundColor: 'green'
10
+ }
11
+ const percentage = 75
12
+ const progressTokens = {
13
+ backgroundColor: 'white',
14
+ borderColor: 'black'
15
+ }
16
+ const a11yLabel = 'Progress bar'
17
+ const progressA11yLabel = 'This is a progress indicator'
18
+ const setup = (
19
+ { children, ...props } = {
20
+ children: (
21
+ <Progress.Bar percentage={percentage} tokens={barTokens} accessibilityLabel={a11yLabel} />
22
+ )
23
+ }
24
+ ) =>
25
+ render(
26
+ <Progress tokens={progressTokens} accessibilityLabel={progressA11yLabel} {...props}>
27
+ {children}
28
+ </Progress>,
29
+ { wrapper: Theme }
30
+ )
31
+
32
+ describe('Progress', () => {
33
+ it('renders with correct percentage and applies tokens accordingly', () => {
34
+ const { getByA11yLabel } = setup()
35
+ expect(getByA11yLabel(progressA11yLabel)).toHaveStyle(progressTokens)
36
+ expect(getByA11yLabel(a11yLabel)).toHaveStyle({
37
+ width: `${percentage}%`,
38
+ ...barTokens
39
+ })
40
+ })
41
+
42
+ it('renders arbitrary content inside the progress bar', () => {
43
+ const contentText = 'This can be an arbitrary content'
44
+ const { getByA11yLabel } = setup({
45
+ children: (
46
+ <Progress.Bar percentage={percentage} tokens={barTokens} accessibilityLabel={a11yLabel}>
47
+ <Text>{contentText}</Text>
48
+ </Progress.Bar>
49
+ )
50
+ })
51
+ expect(within(getByA11yLabel(a11yLabel)).getByText(contentText)).toBeTruthy()
52
+ })
53
+
54
+ it('renders proper accessibility attributes on the progress bar', () => {
55
+ const { getByA11yRole, getByA11yValue } = setup()
56
+ expect(getByA11yRole('progressbar')).toBeTruthy()
57
+ expect(
58
+ getByA11yValue({ min: 0, max: 100, now: percentage, text: `${percentage}%` })
59
+ ).toBeTruthy()
60
+ })
61
+
62
+ it('renders stacked progress bars', () => {
63
+ const inactiveA11yLabel = 'This bar is inactive'
64
+ const { getByA11yLabel } = setup({
65
+ children: (
66
+ <>
67
+ <Progress.Bar
68
+ percentage={percentage + 10}
69
+ variant={{ inactive: true }}
70
+ accessibilityLabel={inactiveA11yLabel}
71
+ />
72
+ <Progress.Bar percentage={percentage} accessibilityLabel={a11yLabel} />
73
+ </>
74
+ )
75
+ })
76
+ expect(within(getByA11yLabel(progressA11yLabel)).getByA11yLabel(inactiveA11yLabel)).toBeTruthy()
77
+ expect(within(getByA11yLabel(progressA11yLabel)).getByA11yLabel(a11yLabel)).toBeTruthy()
78
+ })
79
+ })