@nypl/design-system-react-components 0.23.4 → 0.25.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 (307) hide show
  1. package/CHANGELOG.md +98 -1
  2. package/README.md +46 -11
  3. package/dist/components/Accordion/Accordion.d.ts +14 -14
  4. package/dist/components/Autosuggest/Autosuggest.stories.d.ts +1 -0
  5. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +11 -14
  6. package/dist/components/Breadcrumbs/BreadcrumbsTypes.d.ts +6 -0
  7. package/dist/components/Button/Button.d.ts +6 -13
  8. package/dist/components/Button/ButtonTypes.d.ts +5 -3
  9. package/dist/components/Card/Card.d.ts +59 -10
  10. package/dist/components/Card/CardTypes.d.ts +19 -0
  11. package/dist/components/CardEdition/CardEdition.d.ts +21 -0
  12. package/dist/components/{StyleGuide/Colors.stories.d.ts → CardEdition/CardEdition.stories.d.ts} +5 -2
  13. package/dist/components/Checkbox/Checkbox.d.ts +21 -16
  14. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +43 -0
  15. package/dist/components/CheckboxGroup/CheckboxGroupLayoutTypes.d.ts +4 -0
  16. package/dist/components/DatePicker/DatePicker.d.ts +79 -0
  17. package/dist/components/DatePicker/DatePickerTypes.d.ts +5 -0
  18. package/dist/components/Form/Form.d.ts +16 -8
  19. package/dist/components/Form/FormTypes.d.ts +2 -0
  20. package/dist/components/Grid/GridTypes.d.ts +9 -0
  21. package/dist/components/Grid/SimpleGrid.d.ts +14 -0
  22. package/dist/components/Heading/Heading.d.ts +9 -11
  23. package/dist/components/Heading/{HeadingDisplaySizes.d.ts → HeadingTypes.d.ts} +8 -0
  24. package/dist/components/HelperErrorText/HelperErrorText.stories.d.ts +2 -1
  25. package/dist/components/Hero/Hero.d.ts +19 -14
  26. package/dist/components/Hero/HeroTypes.d.ts +10 -5
  27. package/dist/components/Icons/Icon.d.ts +13 -16
  28. package/dist/components/Icons/IconSvgs.d.ts +4 -0
  29. package/dist/components/Icons/IconTypes.d.ts +78 -60
  30. package/dist/components/Image/Image.stories.d.ts +2 -1
  31. package/dist/components/Label/Label.d.ts +10 -26
  32. package/dist/components/Link/Link.d.ts +8 -12
  33. package/dist/components/List/List.stories.d.ts +1 -0
  34. package/dist/components/Radio/Radio.d.ts +30 -24
  35. package/dist/components/RadioGroup/RadioGroup.d.ts +40 -0
  36. package/dist/components/RadioGroup/RadioGroupLayoutTypes.d.ts +4 -0
  37. package/dist/components/SearchBar/SearchBar.d.ts +45 -27
  38. package/dist/components/Select/Select.d.ts +34 -35
  39. package/dist/components/Select/SelectTypes.d.ts +4 -0
  40. package/dist/components/SkeletonLoader/SkeletonLoader.d.ts +1 -1
  41. package/dist/components/SkeletonLoader/SkeletonLoaderTypes.d.ts +2 -2
  42. package/dist/components/StatusBadge/StatusBadge.d.ts +8 -6
  43. package/dist/components/StatusBadge/StatusBadgeTypes.d.ts +5 -0
  44. package/dist/components/Tabs/Tabs.d.ts +25 -0
  45. package/dist/components/Template/Template.d.ts +91 -0
  46. package/dist/components/Text/Text.d.ts +16 -0
  47. package/dist/components/Text/TextTypes.d.ts +6 -0
  48. package/dist/components/TextInput/TextInput.d.ts +37 -30
  49. package/dist/components/TextInput/TextInputTypes.d.ts +5 -0
  50. package/dist/design-system-react-components.cjs.development.js +4102 -917
  51. package/dist/design-system-react-components.cjs.development.js.map +1 -1
  52. package/dist/design-system-react-components.cjs.production.min.js +1 -1
  53. package/dist/design-system-react-components.cjs.production.min.js.map +1 -1
  54. package/dist/design-system-react-components.esm.js +4023 -920
  55. package/dist/design-system-react-components.esm.js.map +1 -1
  56. package/dist/index.d.ts +23 -5
  57. package/dist/resources.scss +133 -24
  58. package/dist/styles.css +1 -1
  59. package/dist/theme/components/accordion.d.ts +25 -0
  60. package/dist/theme/components/breadcrumb.d.ts +90 -0
  61. package/dist/theme/components/button.d.ts +109 -0
  62. package/dist/theme/components/checkbox.d.ts +91 -0
  63. package/dist/theme/components/customCheckboxGroup.d.ts +18 -0
  64. package/dist/theme/components/customRadioGroup.d.ts +18 -0
  65. package/dist/theme/components/global.d.ts +55 -0
  66. package/dist/theme/components/globalMixins.d.ts +15 -0
  67. package/dist/theme/components/heading.d.ts +110 -0
  68. package/dist/theme/components/hero.d.ts +492 -0
  69. package/dist/theme/components/icon.d.ts +13 -0
  70. package/dist/theme/components/label.d.ts +16 -0
  71. package/dist/theme/components/link.d.ts +45 -0
  72. package/dist/theme/components/radio.d.ts +95 -0
  73. package/dist/theme/components/searchBar.d.ts +20 -0
  74. package/dist/theme/components/select.d.ts +58 -0
  75. package/dist/theme/components/statusBadge.d.ts +25 -0
  76. package/dist/theme/components/tabs.d.ts +85 -0
  77. package/dist/theme/components/template.d.ts +105 -0
  78. package/dist/theme/components/text.d.ts +20 -0
  79. package/dist/theme/components/textInput.d.ts +105 -0
  80. package/dist/theme/foundations/breakpoints.d.ts +23 -0
  81. package/dist/theme/foundations/colors.d.ts +3 -0
  82. package/dist/theme/foundations/global.d.ts +23 -0
  83. package/dist/theme/foundations/shadows.d.ts +4 -0
  84. package/dist/theme/foundations/spacing.d.ts +77 -0
  85. package/dist/theme/foundations/typography.d.ts +8 -0
  86. package/dist/theme/index.d.ts +20 -0
  87. package/dist/theme/provider.d.ts +5 -0
  88. package/dist/theme/types.d.ts +1 -0
  89. package/dist/utils/utils.d.ts +6 -0
  90. package/package.json +9 -2
  91. package/src/components/Accordion/Accordion.stories.mdx +233 -33
  92. package/src/components/Accordion/Accordion.test.tsx +135 -19
  93. package/src/components/Accordion/Accordion.tsx +81 -56
  94. package/src/components/Autosuggest/Autosuggest.stories.mdx +4 -3
  95. package/src/components/Autosuggest/Autosuggest.stories.tsx +1 -1
  96. package/src/components/Autosuggest/_Autosuggest.scss +2 -2
  97. package/src/components/Breadcrumbs/Breadcrumbs.stories.mdx +57 -56
  98. package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +31 -25
  99. package/src/components/Breadcrumbs/Breadcrumbs.tsx +71 -73
  100. package/src/components/Breadcrumbs/BreadcrumbsTypes.tsx +6 -0
  101. package/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap +100 -0
  102. package/src/components/Button/Button.stories.mdx +125 -138
  103. package/src/components/Button/Button.test.tsx +65 -11
  104. package/src/components/Button/Button.tsx +72 -68
  105. package/src/components/Button/ButtonTypes.tsx +4 -2
  106. package/src/components/Button/_Button.scss +7 -92
  107. package/src/components/Button/__snapshots__/Button.test.tsx.snap +58 -3
  108. package/src/components/Card/Card.stories.mdx +694 -0
  109. package/src/components/Card/Card.test.tsx +97 -102
  110. package/src/components/Card/Card.tsx +182 -31
  111. package/src/components/Card/CardTypes.tsx +21 -0
  112. package/src/components/Card/_Card.scss +234 -49
  113. package/src/components/{Card/Card.stories.tsx → CardEdition/CardEdition.stories.tsx} +32 -22
  114. package/src/components/CardEdition/CardEdition.test.tsx +395 -0
  115. package/src/components/CardEdition/CardEdition.tsx +60 -0
  116. package/src/components/CardEdition/_CardEdition.scss +138 -0
  117. package/src/components/Chakra/Box.stories.mdx +57 -0
  118. package/src/components/Chakra/Center.stories.mdx +99 -0
  119. package/src/components/Chakra/Grid.stories.mdx +79 -0
  120. package/src/components/Chakra/Stack.stories.mdx +93 -0
  121. package/src/components/Checkbox/Checkbox.stories.mdx +57 -35
  122. package/src/components/Checkbox/Checkbox.test.tsx +117 -147
  123. package/src/components/Checkbox/Checkbox.tsx +76 -50
  124. package/src/components/Checkbox/__snapshots__/Checkbox.test.tsx.snap +325 -0
  125. package/src/components/CheckboxGroup/CheckboxGroup.stories.mdx +249 -0
  126. package/src/components/CheckboxGroup/CheckboxGroup.test.tsx +345 -0
  127. package/src/components/CheckboxGroup/CheckboxGroup.tsx +148 -0
  128. package/src/components/CheckboxGroup/CheckboxGroupLayoutTypes.tsx +4 -0
  129. package/src/components/CheckboxGroup/__snapshots__/CheckboxGroup.test.tsx.snap +1360 -0
  130. package/src/components/DatePicker/DatePicker.stories.mdx +284 -0
  131. package/src/components/DatePicker/DatePicker.test.tsx +657 -0
  132. package/src/components/DatePicker/DatePicker.tsx +396 -0
  133. package/src/components/DatePicker/DatePickerTypes.tsx +5 -0
  134. package/src/components/DatePicker/_DatePicker.scss +76 -0
  135. package/src/components/Form/Form.stories.mdx +130 -27
  136. package/src/components/Form/Form.test.tsx +78 -36
  137. package/src/components/Form/Form.tsx +53 -19
  138. package/src/components/Form/FormTypes.tsx +3 -0
  139. package/src/components/Form/__snapshots__/Form.test.tsx.snap +38 -0
  140. package/src/components/Grid/GridTypes.tsx +9 -0
  141. package/src/components/Grid/SimpleGrid.stories.mdx +275 -0
  142. package/src/components/Grid/SimpleGrid.test.tsx +66 -0
  143. package/src/components/Grid/SimpleGrid.tsx +37 -0
  144. package/src/components/Grid/__snapshots__/SimpleGrid.test.tsx.snap +8 -0
  145. package/src/components/Heading/Heading.stories.mdx +63 -33
  146. package/src/components/Heading/Heading.test.tsx +24 -16
  147. package/src/components/Heading/Heading.tsx +54 -38
  148. package/src/components/Heading/{HeadingDisplaySizes.tsx → HeadingTypes.tsx} +9 -0
  149. package/src/components/HelperErrorText/HelperErrorText.stories.tsx +2 -1
  150. package/src/components/HelperErrorText/_HelperErrorText.scss +1 -1
  151. package/src/components/Hero/Hero.stories.mdx +195 -85
  152. package/src/components/Hero/Hero.test.tsx +544 -113
  153. package/src/components/Hero/Hero.tsx +80 -93
  154. package/src/components/Hero/HeroTypes.tsx +17 -5
  155. package/src/components/Hero/__snapshots__/Hero.test.tsx.snap +307 -0
  156. package/src/components/HorizontalRule/HorizontalRule.stories.mdx +6 -1
  157. package/src/components/HorizontalRule/_HorizontalRule.scss +1 -1
  158. package/src/components/Icons/Icon.stories.mdx +89 -74
  159. package/src/components/Icons/Icon.test.tsx +30 -22
  160. package/src/components/Icons/Icon.tsx +63 -61
  161. package/src/components/Icons/IconSvgs.tsx +8 -0
  162. package/src/components/Icons/IconTypes.tsx +80 -60
  163. package/src/components/Image/Image.stories.tsx +2 -1
  164. package/src/components/Input/_Input.scss +2 -2
  165. package/src/components/Label/Label.stories.mdx +77 -0
  166. package/src/components/Label/Label.test.tsx +43 -12
  167. package/src/components/Label/Label.tsx +28 -45
  168. package/src/components/Label/__snapshots__/Label.test.tsx.snap +41 -0
  169. package/src/components/Link/Link.stories.mdx +47 -41
  170. package/src/components/Link/Link.test.tsx +33 -44
  171. package/src/components/Link/Link.tsx +114 -100
  172. package/src/components/List/List.stories.mdx +7 -3
  173. package/src/components/List/List.stories.tsx +14 -9
  174. package/src/components/List/List.test.tsx +12 -8
  175. package/src/components/List/List.tsx +9 -7
  176. package/src/components/List/_List.scss +3 -3
  177. package/src/components/Modal/Modal.stories.mdx +7 -3
  178. package/src/components/Modal/_Modal.scss +1 -1
  179. package/src/components/Notification/Notification.stories.mdx +99 -65
  180. package/src/components/Notification/Notification.test.tsx +3 -16
  181. package/src/components/Notification/Notification.tsx +12 -12
  182. package/src/components/Notification/_Notification.scss +5 -4
  183. package/src/components/Notification/__snapshots__/Notification.test.tsx.snap +1 -1
  184. package/src/components/Pagination/Pagination.stories.mdx +7 -1
  185. package/src/components/Pagination/Pagination.test.tsx +16 -10
  186. package/src/components/Radio/Radio.stories.mdx +57 -46
  187. package/src/components/Radio/Radio.test.tsx +92 -138
  188. package/src/components/Radio/Radio.tsx +70 -69
  189. package/src/components/Radio/__snapshots__/Radio.test.tsx.snap +250 -0
  190. package/src/components/RadioGroup/RadioGroup.stories.mdx +247 -0
  191. package/src/components/RadioGroup/RadioGroup.test.tsx +327 -0
  192. package/src/components/RadioGroup/RadioGroup.tsx +154 -0
  193. package/src/components/RadioGroup/RadioGroupLayoutTypes.tsx +4 -0
  194. package/src/components/RadioGroup/__snapshots__/RadioGroup.test.tsx.snap +1101 -0
  195. package/src/components/SearchBar/SearchBar.Test.tsx +151 -16
  196. package/src/components/SearchBar/SearchBar.stories.mdx +196 -224
  197. package/src/components/SearchBar/SearchBar.tsx +151 -46
  198. package/src/components/Select/Select.stories.mdx +193 -168
  199. package/src/components/Select/Select.test.tsx +129 -324
  200. package/src/components/Select/Select.tsx +120 -160
  201. package/src/components/Select/SelectTypes.tsx +4 -0
  202. package/src/components/SkeletonLoader/SkeletonLoader.stories.mdx +18 -29
  203. package/src/components/SkeletonLoader/SkeletonLoader.test.tsx +7 -7
  204. package/src/components/SkeletonLoader/SkeletonLoader.tsx +4 -2
  205. package/src/components/SkeletonLoader/SkeletonLoaderTypes.tsx +2 -2
  206. package/src/components/SkeletonLoader/_SkeletonLoader.scss +3 -3
  207. package/src/components/StatusBadge/StatusBadge.stories.mdx +91 -0
  208. package/src/components/StatusBadge/StatusBadge.test.tsx +35 -7
  209. package/src/components/StatusBadge/StatusBadge.tsx +24 -25
  210. package/src/components/StatusBadge/StatusBadgeTypes.tsx +5 -0
  211. package/src/components/StatusBadge/__snapshots__/StatusBadge.test.tsx.snap +28 -0
  212. package/src/components/StyleGuide/Bidirectionality.stories.mdx +112 -90
  213. package/src/components/StyleGuide/Buttons.stories.mdx +98 -100
  214. package/src/components/StyleGuide/Colors.stories.mdx +336 -0
  215. package/src/components/StyleGuide/Forms.stories.mdx +85 -0
  216. package/src/components/StyleGuide/Iconography.stories.mdx +86 -93
  217. package/src/components/StyleGuide/Spacing.stories.mdx +0 -1
  218. package/src/components/StyleGuide/Typography.stories.mdx +164 -166
  219. package/src/components/StyleGuide/UIDocCard.tsx +4 -4
  220. package/src/components/Tabs/Tabs.stories.mdx +221 -0
  221. package/src/components/Tabs/Tabs.test.tsx +264 -0
  222. package/src/components/Tabs/Tabs.tsx +220 -0
  223. package/src/components/Template/Template.stories.mdx +574 -0
  224. package/src/components/Template/Template.test.tsx +124 -0
  225. package/src/components/Template/Template.tsx +226 -0
  226. package/src/components/Text/Text.stories.mdx +70 -0
  227. package/src/components/Text/Text.test.tsx +63 -0
  228. package/src/components/Text/Text.tsx +55 -0
  229. package/src/components/Text/TextTypes.tsx +6 -0
  230. package/src/components/Text/__snapshots__/Text.test.tsx.snap +33 -0
  231. package/src/components/TextInput/TextInput.stories.mdx +90 -90
  232. package/src/components/TextInput/TextInput.test.tsx +103 -83
  233. package/src/components/TextInput/TextInput.tsx +108 -91
  234. package/src/components/TextInput/TextInputTypes.tsx +6 -0
  235. package/src/components/VideoPlayer/VideoPlayer.stories.mdx +2 -1
  236. package/src/components/VideoPlayer/VideoPlayer.tsx +4 -2
  237. package/src/components/VideoPlayer/_VideoPlayer.scss +1 -1
  238. package/src/docs/Chakra.stories.mdx +341 -0
  239. package/src/docs/Intro.stories.mdx +31 -24
  240. package/src/index.ts +70 -5
  241. package/src/styles/01-colors/_colors-brand.scss +6 -4
  242. package/src/styles/01-colors/_colors-utility.scss +14 -15
  243. package/src/styles/03-space/_space-inline.scss +47 -7
  244. package/src/styles/03-space/_space-inset.scss +33 -5
  245. package/src/styles/03-space/_space-stack.scss +48 -8
  246. package/src/styles/base/_02-breakpoints.scss +5 -4
  247. package/src/styles/base/_04-base.scss +2 -1
  248. package/src/styles/base/_place-holder.scss +1 -1
  249. package/src/styles/base/_typography.scss +1 -29
  250. package/src/styles.scss +22 -25
  251. package/src/theme/components/accordion.ts +30 -0
  252. package/src/theme/components/breadcrumb.ts +77 -0
  253. package/src/theme/components/button.ts +125 -0
  254. package/src/theme/components/checkbox.ts +107 -0
  255. package/src/theme/components/customCheckboxGroup.ts +12 -0
  256. package/src/theme/components/customRadioGroup.ts +12 -0
  257. package/src/theme/components/global.ts +71 -0
  258. package/src/theme/components/globalMixins.ts +16 -0
  259. package/src/theme/components/heading.ts +72 -0
  260. package/src/theme/components/hero.ts +239 -0
  261. package/src/theme/components/icon.ts +79 -0
  262. package/src/theme/components/label.ts +17 -0
  263. package/src/theme/components/link.ts +47 -0
  264. package/src/theme/components/radio.ts +106 -0
  265. package/src/theme/components/searchBar.ts +21 -0
  266. package/src/theme/components/select.ts +50 -0
  267. package/src/theme/components/statusBadge.ts +27 -0
  268. package/src/theme/components/tabs.ts +79 -0
  269. package/src/theme/components/template.ts +114 -0
  270. package/src/theme/components/text.ts +31 -0
  271. package/src/theme/components/textInput.ts +61 -0
  272. package/src/theme/foundations/breakpoints.ts +24 -0
  273. package/src/theme/foundations/colors.ts +208 -0
  274. package/src/theme/foundations/global.ts +26 -0
  275. package/src/theme/foundations/shadows.ts +5 -0
  276. package/src/theme/foundations/spacing.ts +85 -0
  277. package/src/theme/foundations/typography.ts +35 -0
  278. package/src/theme/index.ts +88 -0
  279. package/src/theme/provider.tsx +9 -0
  280. package/src/theme/types.ts +1 -0
  281. package/src/utils/componentCategories.ts +56 -21
  282. package/src/utils/utils.ts +13 -0
  283. package/dist/components/Accordion/Accordion.stories.d.ts +0 -5
  284. package/dist/components/Card/Card.stories.d.ts +0 -27
  285. package/dist/components/Label/Label.stories.d.ts +0 -12
  286. package/dist/components/StatusBadge/StatusBadge.stories.d.ts +0 -8
  287. package/dist/components/Template/Template.stories.d.ts +0 -29
  288. package/src/components/Accordion/Accordion.stories.tsx +0 -65
  289. package/src/components/Accordion/_Accordion.scss +0 -81
  290. package/src/components/Breadcrumbs/_Breadcrumbs.scss +0 -97
  291. package/src/components/Checkbox/_Checkbox.scss +0 -97
  292. package/src/components/Form/_Form.scss +0 -28
  293. package/src/components/Heading/_Heading.scss +0 -163
  294. package/src/components/Hero/_Hero.scss +0 -256
  295. package/src/components/Icons/_Icons.scss +0 -116
  296. package/src/components/Label/Label.stories.tsx +0 -30
  297. package/src/components/Label/_Label.scss +0 -22
  298. package/src/components/Link/_Link.scss +0 -73
  299. package/src/components/Radio/_Radio.scss +0 -84
  300. package/src/components/SearchBar/_SearchBar.scss +0 -16
  301. package/src/components/Select/_Select.scss +0 -82
  302. package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -33
  303. package/src/components/StatusBadge/_StatusBadge.scss +0 -23
  304. package/src/components/StyleGuide/Colors.stories.tsx +0 -288
  305. package/src/components/Template/Template.stories.tsx +0 -85
  306. package/src/components/Template/_Template.scss +0 -63
  307. package/src/components/TextInput/_TextInput.scss +0 -59
@@ -0,0 +1,657 @@
1
+ import * as React from "react";
2
+ import { render, screen } from "@testing-library/react";
3
+ import { axe } from "jest-axe";
4
+ import userEvent from "@testing-library/user-event";
5
+
6
+ import DatePicker from "./DatePicker";
7
+ import { DatePickerTypes } from "./DatePickerTypes";
8
+ import { TextInputRefType } from "../TextInput/TextInput";
9
+
10
+ /** This adds a "0" padding for date values under "10". */
11
+ const str_pad = (n) => String("0" + n).slice(-2);
12
+ const monthArray = [
13
+ "January",
14
+ "February",
15
+ "March",
16
+ "April",
17
+ "May",
18
+ "June",
19
+ "July",
20
+ "August",
21
+ "September",
22
+ "October",
23
+ "November",
24
+ "December",
25
+ ];
26
+
27
+ describe("DatePicker Accessibility", () => {
28
+ it("passes axe accessibility for a single date input", async () => {
29
+ const { container } = render(
30
+ <DatePicker labelText="Select the date you want to visit NYPL" />
31
+ );
32
+ expect(await axe(container)).toHaveNoViolations();
33
+ });
34
+
35
+ it("passes axe accessibility for a date range", async () => {
36
+ const { container } = render(
37
+ <DatePicker
38
+ labelText="Select the date range you want to visit NYPL"
39
+ dateRange={true}
40
+ />
41
+ );
42
+ expect(await axe(container)).toHaveNoViolations();
43
+ });
44
+ });
45
+
46
+ describe("DatePicker", () => {
47
+ const todaysDate = new Date();
48
+ /** Returns today's year, month, and day values. */
49
+ const getTodaysValues = () => {
50
+ const year = todaysDate.getFullYear();
51
+ const month = str_pad(todaysDate.getMonth() + 1);
52
+ const day = str_pad(todaysDate.getDate());
53
+ return [year, month, day];
54
+ };
55
+ /** Returns today's date in string format based on the DatePicker type. */
56
+ const getTodaysDateDisplay = (type?) => {
57
+ const [year, month, day] = getTodaysValues();
58
+ if (DatePickerTypes.Year === type) {
59
+ return `${year}`;
60
+ } else if (DatePickerTypes.Month === type) {
61
+ return `${month}-${year}`;
62
+ }
63
+ return `${year}-${month}-${day}`;
64
+ };
65
+
66
+ describe("Single input", () => {
67
+ it("should render the basic date input field including a date", () => {
68
+ render(
69
+ <DatePicker labelText="Select the full date you want to visit NYPL" />
70
+ );
71
+ const [year, month, day] = getTodaysValues();
72
+ const date = getTodaysDateDisplay();
73
+ const input = screen.getByLabelText(
74
+ /Select the full date you want to visit NYPL/i
75
+ );
76
+
77
+ expect(input).toBeInTheDocument();
78
+ expect(input).not.toHaveAttribute("aria-label");
79
+ // Date format based on component specification yyyy-mm-dd.
80
+ expect(date).toEqual(`${year}-${month}-${day}`);
81
+ expect(screen.getByDisplayValue(date)).toBeInTheDocument();
82
+ });
83
+
84
+ it("should render with an initial date", () => {
85
+ render(
86
+ <DatePicker
87
+ labelText="Select the full date you want to visit NYPL"
88
+ initialDate="1/2/1988"
89
+ />
90
+ );
91
+ const date = screen.getByDisplayValue("1988-01-02");
92
+
93
+ expect(date).toBeInTheDocument();
94
+ });
95
+
96
+ it("should render the 'month' DatePicker type", () => {
97
+ render(
98
+ <DatePicker
99
+ dateType={DatePickerTypes.Month}
100
+ labelText="Select the month you want to visit NYPL"
101
+ />
102
+ );
103
+ const [year, month] = getTodaysValues();
104
+ const date = getTodaysDateDisplay(DatePickerTypes.Month);
105
+
106
+ expect(
107
+ screen.getByLabelText(/Select the month you want to visit NYPL/i)
108
+ ).toBeInTheDocument();
109
+ // Date format based on component specification mm-yyyy.
110
+ expect(date).toEqual(`${month}-${year}`);
111
+ expect(screen.getByDisplayValue(date)).toBeInTheDocument();
112
+ });
113
+
114
+ it("should render the 'year' DatePicker type", () => {
115
+ render(
116
+ <DatePicker
117
+ dateType={DatePickerTypes.Year}
118
+ labelText="Select the month you want to visit NYPL"
119
+ />
120
+ );
121
+ const [year] = getTodaysValues();
122
+ const date = getTodaysDateDisplay(DatePickerTypes.Year);
123
+
124
+ expect(
125
+ screen.getByLabelText(/Select the month you want to visit NYPL/i)
126
+ ).toBeInTheDocument();
127
+ // Date format based on component specification yyyy.
128
+ expect(date).toEqual(`${year}`);
129
+ expect(screen.getByDisplayValue(date)).toBeInTheDocument();
130
+ });
131
+
132
+ it("should render a custom date format", () => {
133
+ const customDateFormat1 = "yyyy/dd/MM";
134
+ const customDateFormat2 = "MM/dd/yyyy";
135
+ const { rerender } = render(
136
+ <DatePicker
137
+ labelText="Select the date you want to visit NYPL"
138
+ dateFormat={customDateFormat1}
139
+ />
140
+ );
141
+ const [year, month, day] = getTodaysValues();
142
+ const dateFormat1 = `${year}/${day}/${month}`;
143
+
144
+ expect(screen.getByDisplayValue(dateFormat1)).toBeInTheDocument();
145
+
146
+ const dateFormat2 = `${month}/${day}/${year}`;
147
+ rerender(
148
+ <DatePicker
149
+ labelText="Select the date you want to visit NYPL"
150
+ dateFormat={customDateFormat2}
151
+ />
152
+ );
153
+ expect(screen.getByDisplayValue(dateFormat2)).toBeInTheDocument();
154
+ });
155
+
156
+ it("should hide the input label but add an aria-label", () => {
157
+ render(
158
+ <DatePicker
159
+ labelText="Select the date you want to visit NYPL"
160
+ showLabel={false}
161
+ />
162
+ );
163
+ const input = screen.getByLabelText(
164
+ /Select the date you want to visit NYPL/i
165
+ );
166
+
167
+ expect(
168
+ screen.queryByDisplayValue(/Select the date you want to visit NYPL/i)
169
+ ).not.toBeInTheDocument();
170
+ expect(input).toHaveAttribute("aria-label");
171
+ });
172
+
173
+ it("should render with helper text and error text", () => {
174
+ const { rerender } = render(
175
+ <DatePicker
176
+ labelText="Select the date you want to visit NYPL"
177
+ helperText="Note that the Library may be closed on Sundays."
178
+ invalidText="Please select a valid date."
179
+ />
180
+ );
181
+
182
+ // When not errored, we expect only the helper text to appear.
183
+ expect(
184
+ screen.getByLabelText(/Select the date you want to visit NYPL/i)
185
+ ).toBeInTheDocument();
186
+ expect(
187
+ screen.getByText("Note that the Library may be closed on Sundays.")
188
+ ).toBeInTheDocument();
189
+ expect(
190
+ screen.queryByText("Please select a valid date.")
191
+ ).not.toBeInTheDocument();
192
+
193
+ rerender(
194
+ <DatePicker
195
+ labelText="Select the date you want to visit NYPL"
196
+ helperText="Note that the Library may be closed on Sundays."
197
+ invalidText="Please select a valid date."
198
+ isInvalid={true}
199
+ />
200
+ );
201
+ // When errored, we expect only the error text to appear.
202
+ expect(
203
+ screen.queryByText("Note that the Library may be closed on Sundays.")
204
+ ).not.toBeInTheDocument();
205
+ expect(
206
+ screen.getByText("Please select a valid date.")
207
+ ).toBeInTheDocument();
208
+ });
209
+
210
+ it("should render a disabled input field", () => {
211
+ render(
212
+ <DatePicker
213
+ labelText="Select the date you want to visit NYPL"
214
+ helperText="Note that the Library may be closed on Sundays."
215
+ isDisabled={true}
216
+ />
217
+ );
218
+
219
+ expect(
220
+ screen.getByLabelText(/Select the date you want to visit NYPL/i)
221
+ ).toHaveAttribute("disabled");
222
+ });
223
+
224
+ it("should render a required label", () => {
225
+ render(
226
+ <DatePicker
227
+ labelText="Select the date you want to visit NYPL"
228
+ helperText="Note that the Library may be closed on Sundays."
229
+ required={true}
230
+ />
231
+ );
232
+
233
+ expect(screen.getByText(/required/i)).toBeInTheDocument();
234
+ });
235
+
236
+ it("should pass the value to the `onChange` function", () => {
237
+ let dateObject: any = {};
238
+ const onChange = (data) => {
239
+ dateObject = data;
240
+ };
241
+ render(
242
+ <DatePicker
243
+ labelText="Select the date you want to visit NYPL"
244
+ helperText="Note that the Library may be closed on Sundays."
245
+ required={true}
246
+ onChange={onChange}
247
+ />
248
+ );
249
+
250
+ const input = screen.getByLabelText(
251
+ /Select the date you want to visit NYPL/i
252
+ );
253
+ const date = getTodaysDateDisplay();
254
+ const midMonthDay = "15";
255
+
256
+ // Let's select a new day.
257
+ userEvent.click(input);
258
+ // The popup displays.
259
+ userEvent.click(screen.getByText(midMonthDay));
260
+
261
+ const newDayValue = date.slice(0, -2) + midMonthDay;
262
+ expect(screen.getByDisplayValue(newDayValue)).toBeInTheDocument();
263
+
264
+ const { startDate } = dateObject;
265
+ const valueFromOnChange = `${startDate.getFullYear()}-${str_pad(
266
+ startDate.getMonth() + 1
267
+ )}-${str_pad(startDate.getDate())}`;
268
+ expect(newDayValue).toEqual(valueFromOnChange);
269
+ });
270
+
271
+ it("should throw a warning when refs are used but not `name` props", () => {
272
+ const warn = jest.spyOn(console, "warn");
273
+ const ref = React.createRef<TextInputRefType>();
274
+ render(
275
+ <DatePicker
276
+ labelText="Select the date you want to visit NYPL"
277
+ ref={ref}
278
+ />
279
+ );
280
+ expect(warn).toHaveBeenCalledWith(
281
+ "A `ref` or `refTo` prop was passed but not the equivalent `nameFrom` or `nameTo` prop."
282
+ );
283
+ });
284
+
285
+ it("should throw a warning when `onChange` is passed as well as a `ref` prop.", () => {
286
+ const warn = jest.spyOn(console, "warn");
287
+ const ref = React.createRef<TextInputRefType>();
288
+ const onChange = (_data) => {};
289
+ render(
290
+ <DatePicker
291
+ labelText="Select the date you want to visit NYPL"
292
+ ref={ref}
293
+ nameFrom="start-date"
294
+ onChange={onChange}
295
+ />
296
+ );
297
+ expect(warn).toHaveBeenCalledWith(
298
+ "React `ref` props were passed and an `onChange` prop as well. Use whichever is best for your app but not both."
299
+ );
300
+ });
301
+
302
+ it("should not render a required label if the 'showOptReqLabel' flag is false", () => {
303
+ render(
304
+ <DatePicker
305
+ labelText="Select the date you want to visit NYPL"
306
+ helperText="Note that the Library may be closed on Sundays."
307
+ required={true}
308
+ showOptReqLabel={false}
309
+ />
310
+ );
311
+
312
+ expect(screen.queryByText(/required/i)).not.toBeInTheDocument();
313
+ });
314
+ });
315
+
316
+ describe("Date Range", () => {
317
+ it("should render the date range with two input fields", () => {
318
+ render(
319
+ <DatePicker
320
+ dateRange={true}
321
+ labelText="Select the date range you want to visit NYPL"
322
+ />
323
+ );
324
+ const [year, month, day] = getTodaysValues();
325
+ const date = getTodaysDateDisplay();
326
+
327
+ expect(
328
+ screen.getByText(/Select the date range you want to visit NYPL/i)
329
+ ).toBeInTheDocument();
330
+ // Date format based on component specification yyyy-mm-dd.
331
+ expect(date).toEqual(`${year}-${month}-${day}`);
332
+ // There are two input fields with the date displaying.
333
+ expect(screen.getAllByDisplayValue(date)).toHaveLength(2);
334
+ });
335
+
336
+ it("should render the initial dates", () => {
337
+ render(
338
+ <DatePicker
339
+ labelText="Select the full date you want to visit NYPL"
340
+ dateRange={true}
341
+ initialDate="1/2/1988"
342
+ initialDateTo="3/4/1990"
343
+ />
344
+ );
345
+ const dateFrom = screen.getByDisplayValue("1988-01-02");
346
+ const dateTo = screen.getByDisplayValue("1990-03-04");
347
+
348
+ expect(dateFrom).toBeInTheDocument();
349
+ expect(dateTo).toBeInTheDocument();
350
+ });
351
+
352
+ it("should render two input labels and three separate helper text", () => {
353
+ render(
354
+ <DatePicker
355
+ dateRange={true}
356
+ labelText="Select the date range you want to visit NYPL"
357
+ helperText="Note that the Library may be closed on Sundays."
358
+ helperTextFrom="Note for the 'from' field."
359
+ helperTextTo="Note for the 'to' field."
360
+ invalidText="Please select a valid date range."
361
+ />
362
+ );
363
+ // There are two labels for each input.
364
+ expect(screen.getByText("From")).toBeInTheDocument();
365
+ expect(screen.getByText("To")).toBeInTheDocument();
366
+ // Helper text for the component
367
+ expect(
368
+ screen.getByText(/Note that the Library may be closed on Sundays./i)
369
+ ).toBeInTheDocument();
370
+ // Helper text for the "From" input
371
+ expect(
372
+ screen.getByText(/Note for the 'from' field./i)
373
+ ).toBeInTheDocument();
374
+ // Helper text for the "To" input
375
+ expect(screen.getByText(/Note for the 'to' field./i)).toBeInTheDocument();
376
+ });
377
+
378
+ it("should render based on other props", () => {
379
+ const { rerender } = render(
380
+ <DatePicker
381
+ dateRange={true}
382
+ labelText="Select the date range you want to visit NYPL"
383
+ helperText="Note that the Library may be closed on Sundays."
384
+ helperTextTo="Note for the 'to' field."
385
+ invalidText="Please select a valid date range."
386
+ isInvalid={true}
387
+ />
388
+ );
389
+
390
+ expect(
391
+ screen.getAllByText("Please select a valid date range.")
392
+ ).toHaveLength(2);
393
+
394
+ rerender(
395
+ <DatePicker
396
+ dateRange={true}
397
+ labelText="Select the date range you want to visit NYPL"
398
+ helperText="Note that the Library may be closed on Sundays."
399
+ helperTextTo="Note for the 'to' field."
400
+ invalidText="Please select a valid date range."
401
+ isDisabled={true}
402
+ />
403
+ );
404
+
405
+ expect(screen.getByLabelText(/From/i)).toHaveAttribute("disabled");
406
+ expect(screen.getByLabelText(/To/i)).toHaveAttribute("disabled");
407
+
408
+ rerender(
409
+ <DatePicker
410
+ dateRange={true}
411
+ labelText="Select the date range you want to visit NYPL"
412
+ helperText="Note that the Library may be closed on Sundays."
413
+ helperTextTo="Note for the 'to' field."
414
+ invalidText="Please select a valid date range."
415
+ required={true}
416
+ />
417
+ );
418
+
419
+ expect(screen.getAllByText(/required/i)).toHaveLength(2);
420
+ });
421
+
422
+ /* // REVISIT THIS TEST
423
+ it("should select two new dates", () => {
424
+ render(
425
+ <DatePicker
426
+ dateRange={true}
427
+ labelText="Select the date range you want to visit NYPL"
428
+ />
429
+ );
430
+ const fromInput = screen.getByLabelText(/From/i);
431
+ const toInput = screen.getByLabelText(/To/i);
432
+ const date = getTodaysDateDisplay();
433
+
434
+ expect(screen.getAllByDisplayValue(date)).toHaveLength(2);
435
+
436
+ // Let's select a new day.
437
+ userEvent.click(fromInput);
438
+ // The popup displays. Select a new day.
439
+ const newDateFrom =
440
+ todaysDate.getDate() > 28 ? 1 : todaysDate.getDate() + 1;
441
+ const newDateTo =
442
+ todaysDate.getDate() > 28 ? 18 : todaysDate.getDate() + 5;
443
+ const newDateToSelect = str_pad(newDateFrom);
444
+ userEvent.click(screen.getAllByText(newDateFrom)[0]);
445
+
446
+ // We selected a new day but kept everything else the same. So we just
447
+ // need to remove the older day with the new "2" selected date.
448
+ // Example: 2021-08-01 -> 2 is selected -> 2021-08-02
449
+ const newFromValue = `${date.slice(0, -2)}${newDateToSelect}`;
450
+ expect(screen.getByDisplayValue(newFromValue)).toBeInTheDocument();
451
+ // The "To" input should only have the older value now.
452
+ expect(screen.getAllByDisplayValue(date)).toHaveLength(1);
453
+
454
+ // Now select the "To" date.
455
+ userEvent.click(toInput);
456
+ // The popup displays.
457
+ userEvent.click(screen.getByText(newDateTo));
458
+
459
+ const newToValue = `${date.slice(0, -2)}${newDateTo}`;
460
+ expect(screen.getByDisplayValue(newToValue)).toBeInTheDocument();
461
+ // The original date value is no longer in display.
462
+ expect(screen.queryAllByDisplayValue(date)).toHaveLength(0);
463
+ // The "From" date value wasn't affected by this!
464
+ expect(screen.getByDisplayValue(newFromValue)).toBeInTheDocument();
465
+ });
466
+ */
467
+ });
468
+
469
+ describe("Popup Calendar", () => {
470
+ it("should render a popup calendar for the full date", () => {
471
+ render(<DatePicker labelText="Select the date you want to visit NYPL" />);
472
+ const input = screen.getByLabelText(
473
+ /Select the date you want to visit NYPL/i
474
+ );
475
+ const [year] = getTodaysValues();
476
+ const monthFullName = monthArray[todaysDate.getMonth()];
477
+
478
+ expect(
479
+ screen.queryByText(`${monthFullName} ${year}`)
480
+ ).not.toBeInTheDocument();
481
+ expect(screen.queryByText("Su")).not.toBeInTheDocument();
482
+
483
+ userEvent.click(input);
484
+
485
+ // In the display, the calendar displays "Month Year" such as
486
+ // "August 2021" for example.
487
+ expect(screen.getByText(`${monthFullName} ${year}`)).toBeInTheDocument();
488
+ // This calendar displays columns with the days of the week.
489
+ expect(screen.getByText("Su")).toBeInTheDocument();
490
+ expect(screen.getByText("Mo")).toBeInTheDocument();
491
+ expect(screen.getByText("Tu")).toBeInTheDocument();
492
+ expect(screen.getByText("We")).toBeInTheDocument();
493
+ expect(screen.getByText("Th")).toBeInTheDocument();
494
+ expect(screen.getByText("Fr")).toBeInTheDocument();
495
+ expect(screen.getByText("Sa")).toBeInTheDocument();
496
+ });
497
+
498
+ it("should select a new date from the calendar", () => {
499
+ render(<DatePicker labelText="Select the date you want to visit NYPL" />);
500
+ const input = screen.getByLabelText(
501
+ /Select the date you want to visit NYPL/i
502
+ );
503
+ const date = getTodaysDateDisplay();
504
+ const midMonthDay = "15";
505
+
506
+ expect(screen.getByDisplayValue(date)).toBeInTheDocument();
507
+
508
+ // Let's select a new day.
509
+ userEvent.click(input);
510
+ // The popup displays.
511
+ userEvent.click(screen.getByText(midMonthDay));
512
+
513
+ // We selected a new day but kept everything else the same. So we just
514
+ // need to remove the older day with the new "15" selected date.
515
+ // Example: 2021-08-01 -> 15 is selected -> 2021-08-15
516
+ const newDayValue = date.slice(0, -2) + midMonthDay;
517
+ expect(screen.getByDisplayValue(newDayValue)).toBeInTheDocument();
518
+
519
+ // Let's select a new month
520
+ userEvent.click(input);
521
+ // The popup displays.
522
+ expect(
523
+ screen.getByText(monthArray[todaysDate.getMonth()], { exact: false })
524
+ ).toBeInTheDocument();
525
+ userEvent.click(screen.getByLabelText("Next Month"));
526
+ userEvent.click(screen.getByLabelText("Next Month"));
527
+
528
+ // We are two months ahead but still selecting the midmonth day.
529
+ userEvent.click(screen.getByText(midMonthDay));
530
+ // So only the month should change accordingly. The month value from JS'
531
+ // Date object is 0-index so we have to add 3.
532
+ const newMonthValue = `${newDayValue.substr(0, 5)}${str_pad(
533
+ todaysDate.getMonth() + 3
534
+ )}${newDayValue.substr(7)}`;
535
+ expect(screen.getByDisplayValue(newMonthValue)).toBeInTheDocument();
536
+ });
537
+
538
+ it("should render a popup calendar for the month date", () => {
539
+ render(
540
+ <DatePicker
541
+ dateType={DatePickerTypes.Month}
542
+ labelText="Select the month you want to visit NYPL"
543
+ />
544
+ );
545
+ const input = screen.getByLabelText(
546
+ /Select the month you want to visit NYPL/i
547
+ );
548
+ const [year] = getTodaysValues();
549
+
550
+ expect(screen.queryByText(year)).not.toBeInTheDocument();
551
+ expect(screen.queryByText("Jan")).not.toBeInTheDocument();
552
+
553
+ userEvent.click(input);
554
+
555
+ // In the display, the calendar displays "Year" such as "2021".
556
+ expect(screen.getByText(year)).toBeInTheDocument();
557
+ // This calendar displays all 12 months but only the first three
558
+ // characters such as "Jan", "Feb", and so on.
559
+ monthArray.forEach((month) => {
560
+ expect(screen.getByText(month.slice(0, 3))).toBeInTheDocument();
561
+ });
562
+ });
563
+
564
+ it("should select a new month from the calendar", () => {
565
+ render(
566
+ <DatePicker
567
+ dateType={DatePickerTypes.Month}
568
+ labelText="Select the month you want to visit NYPL"
569
+ />
570
+ );
571
+ const input = screen.getByLabelText(
572
+ /Select the month you want to visit NYPL/i
573
+ );
574
+ const date = getTodaysDateDisplay(DatePickerTypes.Month);
575
+ let currentMonthSelected = monthArray[todaysDate.getMonth() + 1];
576
+ let currentMonthSelectedDisplay = currentMonthSelected.slice(0, 3);
577
+
578
+ expect(screen.getByDisplayValue(date)).toBeInTheDocument();
579
+ expect(
580
+ screen.queryByText(currentMonthSelectedDisplay)
581
+ ).not.toBeInTheDocument();
582
+
583
+ // Let's select a new day.
584
+ userEvent.click(input);
585
+ // The popup displays.
586
+
587
+ expect(screen.getByText(currentMonthSelectedDisplay)).toBeInTheDocument();
588
+
589
+ userEvent.click(screen.getByText("Jan"));
590
+
591
+ // We selected a new month but kept the year the same.
592
+ // Example: 08-2021 -> "Jan" -> 01-2021
593
+ expect(
594
+ screen.getByDisplayValue(`01-${date.substr(3)}`)
595
+ ).toBeInTheDocument();
596
+ });
597
+
598
+ it("should render a popup calendar for the year date", () => {
599
+ render(
600
+ <DatePicker
601
+ dateType={DatePickerTypes.Year}
602
+ labelText="Select the year you want to visit NYPL"
603
+ />
604
+ );
605
+ const input = screen.getByLabelText(
606
+ /Select the year you want to visit NYPL/i
607
+ );
608
+ const [year] = getTodaysValues();
609
+
610
+ expect(
611
+ screen.queryByText(`${(year as any) - 4} - ${(year as any) + 7}`)
612
+ ).not.toBeInTheDocument();
613
+
614
+ userEvent.click(input);
615
+
616
+ // In the display, the calendar displays a date range from four years
617
+ // before the current year to seven years after the current year. For year
618
+ // 2021, it will display 2017 - 2028.
619
+ expect(
620
+ screen.getByText(`${(year as any) - 4} - ${(year as any) + 7}`)
621
+ ).toBeInTheDocument();
622
+ // This calendar displays 12 years to select from.
623
+ // It should display the four previous years from the current year.
624
+ for (let i = 4; i > 0; i--) {
625
+ expect(screen.getByText((year as any) - i)).toBeInTheDocument();
626
+ }
627
+ // It should display the eight next years from the current year.
628
+ for (let i = 0; i < 8; i++) {
629
+ expect(screen.getByText((year as any) + i)).toBeInTheDocument();
630
+ }
631
+ });
632
+
633
+ it("should select a new year from the calendar", () => {
634
+ render(
635
+ <DatePicker
636
+ dateType={DatePickerTypes.Year}
637
+ labelText="Select the year you want to visit NYPL"
638
+ />
639
+ );
640
+ const input = screen.getByLabelText(
641
+ /Select the year you want to visit NYPL/i
642
+ );
643
+ const [year] = getTodaysValues();
644
+
645
+ expect(screen.getByDisplayValue(year)).toBeInTheDocument();
646
+
647
+ // Let's select a new day.
648
+ userEvent.click(input);
649
+ // The popup displays.
650
+
651
+ // Select a new year
652
+ userEvent.click(screen.getByText("2024"));
653
+
654
+ expect(screen.getByDisplayValue("2024")).toBeInTheDocument();
655
+ });
656
+ });
657
+ });