@nypl/design-system-react-components 0.25.2 → 0.25.6

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 (238) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/README.md +47 -11
  3. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +4 -0
  4. package/dist/components/Breadcrumbs/BreadcrumbsTypes.d.ts +1 -0
  5. package/dist/components/Button/Button.d.ts +9 -8
  6. package/dist/components/Button/ButtonTypes.d.ts +2 -1
  7. package/dist/components/Card/Card.d.ts +36 -52
  8. package/dist/components/Card/CardTypes.d.ts +0 -15
  9. package/dist/components/Checkbox/Checkbox.d.ts +8 -9
  10. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +2 -2
  11. package/dist/components/DatePicker/DatePicker.d.ts +36 -36
  12. package/dist/components/Fieldset/Fieldset.d.ts +25 -0
  13. package/dist/components/HelperErrorText/HelperErrorText.d.ts +4 -0
  14. package/dist/components/HorizontalRule/HorizontalRule.d.ts +10 -3
  15. package/dist/components/Icons/Icon.d.ts +4 -0
  16. package/dist/components/Icons/IconSvgs.d.ts +11 -0
  17. package/dist/components/Icons/IconTypes.d.ts +11 -0
  18. package/dist/components/Image/Image.d.ts +19 -9
  19. package/dist/components/Image/ImageTypes.d.ts +20 -0
  20. package/dist/components/Link/Link.d.ts +4 -0
  21. package/dist/components/List/List.d.ts +7 -1
  22. package/dist/components/Notification/Notification.d.ts +6 -4
  23. package/dist/components/Pagination/Pagination.d.ts +16 -13
  24. package/dist/components/Pagination/Pagination.stories.d.ts +2 -0
  25. package/dist/components/ProgressIndicator/ProgressIndicator.d.ts +29 -0
  26. package/dist/components/ProgressIndicator/ProgressIndicatorTypes.d.ts +8 -0
  27. package/dist/components/RadioGroup/RadioGroup.d.ts +2 -2
  28. package/dist/components/SearchBar/SearchBar.d.ts +3 -3
  29. package/dist/components/SkeletonLoader/SkeletonLoader.d.ts +18 -14
  30. package/dist/components/Slider/Slider.d.ts +57 -0
  31. package/dist/components/Tabs/Tabs.d.ts +1 -1
  32. package/dist/components/TextInput/TextInput.d.ts +10 -0
  33. package/dist/design-system-react-components.cjs.development.js +3058 -936
  34. package/dist/design-system-react-components.cjs.development.js.map +1 -1
  35. package/dist/design-system-react-components.cjs.production.min.js +1 -1
  36. package/dist/design-system-react-components.cjs.production.min.js.map +1 -1
  37. package/dist/design-system-react-components.esm.js +3049 -921
  38. package/dist/design-system-react-components.esm.js.map +1 -1
  39. package/dist/index.d.ts +12 -6
  40. package/dist/resources.scss +180 -170
  41. package/dist/styles.css +1 -1
  42. package/dist/theme/components/breadcrumb.d.ts +9 -0
  43. package/dist/theme/components/button.d.ts +22 -8
  44. package/dist/theme/components/card.d.ts +168 -0
  45. package/dist/theme/components/checkbox.d.ts +5 -1
  46. package/dist/theme/components/checkboxGroup.d.ts +12 -0
  47. package/dist/theme/components/datePicker.d.ts +16 -0
  48. package/dist/theme/components/fieldset.d.ts +27 -0
  49. package/dist/theme/components/global.d.ts +23 -13
  50. package/dist/theme/components/globalMixins.d.ts +9 -1
  51. package/dist/theme/components/heading.d.ts +5 -0
  52. package/dist/theme/components/image.d.ts +31 -0
  53. package/dist/theme/components/label.d.ts +5 -3
  54. package/dist/theme/components/link.d.ts +4 -0
  55. package/dist/theme/components/list.d.ts +5 -1
  56. package/dist/theme/components/notification.d.ts +4 -14
  57. package/dist/theme/components/pagination.d.ts +19 -0
  58. package/dist/theme/components/progressIndicator.d.ts +50 -0
  59. package/dist/theme/components/radioGroup.d.ts +12 -0
  60. package/dist/theme/components/select.d.ts +11 -2
  61. package/dist/theme/components/skeletonLoader.d.ts +98 -0
  62. package/dist/theme/components/slider.d.ts +51 -0
  63. package/dist/theme/components/textInput.d.ts +8 -0
  64. package/dist/theme/foundations/breakpoints.d.ts +8 -8
  65. package/dist/theme/foundations/global.d.ts +6 -1
  66. package/package.json +72 -84
  67. package/src/__tests__/setup.ts +2 -2
  68. package/src/components/Accordion/Accordion.stories.mdx +39 -42
  69. package/src/components/Autosuggest/Autosuggest.stories.mdx +3 -3
  70. package/src/components/Autosuggest/Autosuggest.stories.tsx +1 -0
  71. package/src/components/Autosuggest/_Autosuggest.scss +5 -5
  72. package/src/components/Breadcrumbs/Breadcrumbs.stories.mdx +24 -8
  73. package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +33 -0
  74. package/src/components/Breadcrumbs/Breadcrumbs.tsx +5 -1
  75. package/src/components/Breadcrumbs/BreadcrumbsTypes.tsx +1 -0
  76. package/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap +298 -1
  77. package/src/components/Button/Button.stories.mdx +15 -10
  78. package/src/components/Button/Button.test.tsx +21 -7
  79. package/src/components/Button/Button.tsx +18 -33
  80. package/src/components/Button/ButtonTypes.tsx +1 -0
  81. package/src/components/Button/__snapshots__/Button.test.tsx.snap +41 -10
  82. package/src/components/Card/Card.stories.mdx +296 -259
  83. package/src/components/Card/Card.test.tsx +156 -84
  84. package/src/components/Card/Card.tsx +195 -145
  85. package/src/components/Card/CardTypes.tsx +0 -17
  86. package/src/components/Card/__snapshots__/Card.test.tsx.snap +410 -0
  87. package/src/components/CardEdition/CardEdition.stories.tsx +15 -47
  88. package/src/components/CardEdition/_CardEdition.scss +22 -23
  89. package/src/components/Chakra/Box.stories.mdx +14 -15
  90. package/src/components/Chakra/Center.stories.mdx +15 -8
  91. package/src/components/Chakra/Grid.stories.mdx +16 -7
  92. package/src/components/Chakra/Stack.stories.mdx +35 -18
  93. package/src/components/Checkbox/Checkbox.stories.mdx +33 -11
  94. package/src/components/Checkbox/Checkbox.test.tsx +30 -3
  95. package/src/components/Checkbox/Checkbox.tsx +27 -27
  96. package/src/components/Checkbox/__snapshots__/Checkbox.test.tsx.snap +90 -2
  97. package/src/components/CheckboxGroup/CheckboxGroup.stories.mdx +82 -2
  98. package/src/components/CheckboxGroup/CheckboxGroup.test.tsx +1 -1
  99. package/src/components/CheckboxGroup/CheckboxGroup.tsx +14 -15
  100. package/src/components/CheckboxGroup/__snapshots__/CheckboxGroup.test.tsx.snap +44 -80
  101. package/src/components/DatePicker/DatePicker.stories.mdx +163 -62
  102. package/src/components/DatePicker/DatePicker.test.tsx +248 -65
  103. package/src/components/DatePicker/DatePicker.tsx +158 -130
  104. package/src/components/DatePicker/_DatePicker.scss +33 -67
  105. package/src/components/DatePicker/__snapshots__/DatePicker.test.tsx.snap +818 -0
  106. package/src/components/Fieldset/Fieldset.stories.mdx +55 -0
  107. package/src/components/Fieldset/Fieldset.test.tsx +125 -0
  108. package/src/components/Fieldset/Fieldset.tsx +52 -0
  109. package/src/components/Fieldset/__snapshots__/Fieldset.test.tsx.snap +68 -0
  110. package/src/components/Form/Form.stories.mdx +4 -5
  111. package/src/components/Form/Form.tsx +1 -0
  112. package/src/components/Grid/SimpleGrid.stories.mdx +32 -39
  113. package/src/components/Grid/SimpleGrid.test.tsx +4 -4
  114. package/src/components/Heading/Heading.stories.mdx +3 -4
  115. package/src/components/HelperErrorText/HelperErrorText.stories.mdx +1 -1
  116. package/src/components/HelperErrorText/HelperErrorText.tsx +5 -1
  117. package/src/components/Hero/HeroTypes.tsx +1 -0
  118. package/src/components/Hero/__snapshots__/Hero.test.tsx.snap +7 -7
  119. package/src/components/HorizontalRule/HorizontalRule.stories.mdx +6 -5
  120. package/src/components/HorizontalRule/HorizontalRule.test.tsx +17 -0
  121. package/src/components/HorizontalRule/HorizontalRule.tsx +21 -4
  122. package/src/components/HorizontalRule/__snapshots__/HorizontalRule.test.tsx.snap +5 -5
  123. package/src/components/Icons/Icon.stories.mdx +11 -3
  124. package/src/components/Icons/Icon.test.tsx +18 -0
  125. package/src/components/Icons/Icon.tsx +6 -0
  126. package/src/components/Icons/IconSvgs.tsx +22 -0
  127. package/src/components/Icons/IconTypes.tsx +11 -0
  128. package/src/components/Image/Image.stories.mdx +220 -0
  129. package/src/components/Image/Image.test.tsx +131 -29
  130. package/src/components/Image/Image.tsx +84 -56
  131. package/src/components/Image/ImageTypes.ts +22 -0
  132. package/src/components/Image/__snapshots__/Image.test.tsx.snap +190 -0
  133. package/src/components/Input/Input.stories.tsx +20 -64
  134. package/src/components/Input/_Input.scss +23 -14
  135. package/src/components/Link/Link.tsx +4 -1
  136. package/src/components/List/List.stories.mdx +1 -1
  137. package/src/components/List/List.tsx +11 -4
  138. package/src/components/Modal/Modal.stories.mdx +3 -3
  139. package/src/components/Modal/_Modal.scss +2 -2
  140. package/src/components/Notification/Notification.stories.mdx +1 -3
  141. package/src/components/Notification/Notification.tsx +24 -9
  142. package/src/components/Notification/__snapshots__/Notification.test.tsx.snap +2 -0
  143. package/src/components/Pagination/Pagination.stories.mdx +26 -27
  144. package/src/components/Pagination/Pagination.stories.tsx +11 -16
  145. package/src/components/Pagination/Pagination.test.tsx +276 -146
  146. package/src/components/Pagination/Pagination.tsx +174 -154
  147. package/src/components/Pagination/__snapshots__/Pagination.test.tsx.snap +285 -0
  148. package/src/components/ProgressIndicator/ProgressIndicator.stories.mdx +292 -0
  149. package/src/components/ProgressIndicator/ProgressIndicator.test.tsx +225 -0
  150. package/src/components/ProgressIndicator/ProgressIndicator.tsx +126 -0
  151. package/src/components/ProgressIndicator/ProgressIndicatorTypes.ts +8 -0
  152. package/src/components/ProgressIndicator/__snapshots__/ProgressIndicator.test.tsx.snap +357 -0
  153. package/src/components/Radio/__snapshots__/Radio.test.tsx.snap +3 -0
  154. package/src/components/RadioGroup/RadioGroup.stories.mdx +3 -4
  155. package/src/components/RadioGroup/RadioGroup.tsx +11 -16
  156. package/src/components/RadioGroup/__snapshots__/RadioGroup.test.tsx.snap +39 -71
  157. package/src/components/SearchBar/SearchBar.Test.tsx +66 -21
  158. package/src/components/SearchBar/SearchBar.stories.mdx +114 -10
  159. package/src/components/SearchBar/SearchBar.tsx +15 -5
  160. package/src/components/Select/SelectTypes.tsx +1 -0
  161. package/src/components/SkeletonLoader/SkeletonLoader.stories.mdx +28 -59
  162. package/src/components/SkeletonLoader/SkeletonLoader.test.tsx +97 -177
  163. package/src/components/SkeletonLoader/SkeletonLoader.tsx +74 -71
  164. package/src/components/SkeletonLoader/__snapshots__/SkeletonLoader.test.tsx.snap +739 -0
  165. package/src/components/Slider/Slider.stories.mdx +529 -0
  166. package/src/components/Slider/Slider.test.tsx +653 -0
  167. package/src/components/Slider/Slider.tsx +303 -0
  168. package/src/components/Slider/__snapshots__/Slider.test.tsx.snap +1946 -0
  169. package/src/components/StyleGuide/Bidirectionality.stories.mdx +1 -1
  170. package/src/components/StyleGuide/Breakpoints.stories.mdx +21 -7
  171. package/src/components/StyleGuide/Buttons.stories.mdx +69 -15
  172. package/src/components/StyleGuide/ColorCard.tsx +0 -1
  173. package/src/components/StyleGuide/DesignTokens.stories.mdx +170 -0
  174. package/src/components/StyleGuide/Iconography.stories.mdx +51 -62
  175. package/src/components/Tabs/Tabs.tsx +5 -5
  176. package/src/components/Template/Template.stories.mdx +11 -16
  177. package/src/components/TextInput/TextInput.stories.mdx +1 -1
  178. package/src/components/TextInput/TextInput.tsx +23 -6
  179. package/src/components/TextInput/TextInputTypes.tsx +2 -0
  180. package/src/components/VideoPlayer/VideoPlayer.stories.mdx +2 -3
  181. package/src/docs/Chakra.stories.mdx +2 -2
  182. package/src/index.ts +20 -12
  183. package/src/resources.scss +5 -5
  184. package/src/styles/base/{_02-breakpoints.scss → _01-breakpoints.scss} +9 -10
  185. package/src/styles/base/{_03-mixins.scss → _02-mixins.scss} +16 -5
  186. package/src/styles/base/{_04-base.scss → _03-base.scss} +7 -2
  187. package/src/styles/base/{_05-focus.scss → _04-focus.scss} +0 -15
  188. package/src/styles/base/_place-holder.scss +14 -3
  189. package/src/styles/{03-space → space}/_space-inline.scss +14 -14
  190. package/src/styles/{03-space → space}/_space-inset.scss +10 -10
  191. package/src/styles/space/_space-stack.scss +116 -0
  192. package/src/styles.scss +13 -55
  193. package/src/theme/components/breadcrumb.ts +10 -0
  194. package/src/theme/components/button.ts +18 -12
  195. package/src/theme/components/card.ts +174 -0
  196. package/src/theme/components/checkbox.ts +7 -2
  197. package/src/theme/components/checkboxGroup.ts +8 -0
  198. package/src/theme/components/datePicker.ts +17 -0
  199. package/src/theme/components/fieldset.ts +18 -0
  200. package/src/theme/components/global.ts +26 -15
  201. package/src/theme/components/globalMixins.ts +9 -1
  202. package/src/theme/components/heading.ts +5 -0
  203. package/src/theme/components/image.ts +116 -0
  204. package/src/theme/components/label.ts +3 -10
  205. package/src/theme/components/link.ts +4 -0
  206. package/src/theme/components/list.ts +6 -3
  207. package/src/theme/components/notification.ts +12 -14
  208. package/src/theme/components/pagination.ts +20 -0
  209. package/src/theme/components/progressIndicator.ts +62 -0
  210. package/src/theme/components/radioGroup.ts +8 -0
  211. package/src/theme/components/select.ts +5 -2
  212. package/src/theme/components/skeletonLoader.ts +107 -0
  213. package/src/theme/components/slider.ts +79 -0
  214. package/src/theme/components/textInput.ts +2 -0
  215. package/src/theme/foundations/breakpoints.ts +8 -8
  216. package/src/theme/foundations/global.ts +6 -1
  217. package/src/theme/index.ts +22 -4
  218. package/src/utils/componentCategories.ts +4 -3
  219. package/dist/components/Image/Image.stories.d.ts +0 -18
  220. package/dist/theme/components/customCheckboxGroup.d.ts +0 -18
  221. package/dist/theme/components/customRadioGroup.d.ts +0 -18
  222. package/src/components/Button/_Button.scss +0 -32
  223. package/src/components/Card/_Card.scss +0 -308
  224. package/src/components/Image/Image.stories.tsx +0 -54
  225. package/src/components/Image/_Image.scss +0 -38
  226. package/src/components/Pagination/_Pagination.scss +0 -40
  227. package/src/components/SkeletonLoader/_SkeletonLoader.scss +0 -142
  228. package/src/styles/01-colors/_colors-brand.scss +0 -62
  229. package/src/styles/01-colors/_colors-utility.scss +0 -67
  230. package/src/styles/02-typography/_type-scale.css +0 -11
  231. package/src/styles/02-typography/_type-weight.css +0 -7
  232. package/src/styles/02-typography/_typefaces.css +0 -4
  233. package/src/styles/03-space/_space-stack.scss +0 -116
  234. package/src/styles/03-space/_space.css +0 -30
  235. package/src/styles/base/_card-grid.scss +0 -77
  236. package/src/styles/base/_typography.scss +0 -11
  237. package/src/theme/components/customCheckboxGroup.ts +0 -12
  238. package/src/theme/components/customRadioGroup.ts +0 -12
@@ -1,178 +1,308 @@
1
1
  import * as React from "react";
2
- import { render, screen } from "@testing-library/react";
2
+ import { render, screen, within } from "@testing-library/react";
3
3
  import { axe } from "jest-axe";
4
4
  import userEvent from "@testing-library/user-event";
5
+ import renderer from "react-test-renderer";
5
6
 
6
7
  import Pagination from "./Pagination";
7
8
 
8
9
  describe("Pagination Accessibility", () => {
9
- it("passes axe accessibility test", async () => {
10
- const getPageHref = (page: number) => `page=${page}`;
10
+ const getPageHref = (page: number) => `page=${page}`;
11
+
12
+ it("passes axe accessibility on the first page", async () => {
11
13
  const { container } = render(
12
- <Pagination pageCount={20} currentPage={6} getPageHref={getPageHref} />
14
+ <Pagination pageCount={20} initialPage={1} getPageHref={getPageHref} />
15
+ );
16
+ expect(await axe(container)).toHaveNoViolations();
17
+ });
18
+ it("passes axe accessibility on a middle page", async () => {
19
+ const { container } = render(
20
+ <Pagination pageCount={20} initialPage={10} getPageHref={getPageHref} />
21
+ );
22
+ expect(await axe(container)).toHaveNoViolations();
23
+ });
24
+ it("passes axe accessibility on the last page", async () => {
25
+ const { container } = render(
26
+ <Pagination pageCount={20} initialPage={20} getPageHref={getPageHref} />
13
27
  );
14
28
  expect(await axe(container)).toHaveNoViolations();
15
29
  });
16
30
  });
17
31
 
18
- describe("Pagination with getPageHref", () => {
32
+ describe("Pagination", () => {
19
33
  const getPageHref = (page: number) => `page=${page}`;
20
34
 
21
- it("Renders a nav element with items and links", () => {
22
- const { container } = render(
23
- <Pagination pageCount={20} currentPage={6} getPageHref={getPageHref} />
24
- );
35
+ describe("Rendering", () => {
36
+ it("renders a nav element with an unordered list and links", () => {
37
+ render(
38
+ <Pagination pageCount={5} initialPage={3} getPageHref={getPageHref} />
39
+ );
40
+ const nav = screen.getByRole("navigation");
25
41
 
26
- expect(screen.getByRole("navigation")).toBeInTheDocument();
27
- expect(container.querySelector(".pagination__list")).toBeInTheDocument();
28
- // Previous/Next buttons + truncated item list = 11 total items
29
- expect(screen.getAllByRole("listitem")).toHaveLength(11);
30
- // Each element links to anotherpage.
31
- // Each link has a `role="button"` attribute.
32
- const links = screen.getAllByRole("button");
33
-
34
- // Pagination should show
35
- // Previous 1 ... 4 5 6 7 8 ... 20 Next
36
- expect(links).toHaveLength(9);
37
- // Previous Page
38
- expect(links[0]).toHaveAttribute("href", "page=5");
39
- expect(links[1]).toHaveAttribute("href", "page=1");
40
- expect(links[2]).toHaveAttribute("href", "page=4");
41
- expect(links[3]).toHaveAttribute("href", "page=5");
42
- expect(links[4]).toHaveAttribute("href", "page=6");
43
- expect(links[5]).toHaveAttribute("href", "page=7");
44
- expect(links[6]).toHaveAttribute("href", "page=8");
45
- expect(links[7]).toHaveAttribute("href", "page=20");
46
- // Next Page
47
- expect(links[8]).toHaveAttribute("href", "page=7");
48
- });
42
+ expect(nav).toBeInTheDocument();
43
+ expect(nav).toHaveAttribute("aria-label", "Pagination");
44
+ // Chakra renders other lists so we only want the list we
45
+ // created within the nav element.
46
+ const { getByRole } = within(nav);
47
+ expect(getByRole("list")).toBeInTheDocument();
48
+ // Previous/Next links + truncated item list = 7 total items
49
+ expect(screen.getAllByRole("listitem")).toHaveLength(7);
50
+ // Pagination should show:
51
+ // Previous 1 2 3 4 5 Next
52
+ expect(screen.getAllByRole("link")).toHaveLength(7);
53
+ });
49
54
 
50
- it("Previous link is disabled when on the first page item", () => {
51
- render(
52
- <Pagination pageCount={11} currentPage={1} getPageHref={getPageHref} />
53
- );
54
- const links = screen.getAllByRole("button");
55
- expect(links[0]).toHaveAttribute("aria-disabled");
56
- const linkClass = links[0].getAttribute("class");
57
- expect(linkClass).toContain("pagination__link disabled");
58
- });
55
+ it("does not render the Previous link on the first page", () => {
56
+ render(
57
+ <Pagination pageCount={5} initialPage={1} getPageHref={getPageHref} />
58
+ );
59
+ // Pagination should show:
60
+ // 1 2 3 4 5 Next
61
+ const links = screen.getAllByRole("link");
59
62
 
60
- it("Next link is disabled when on the last page item", () => {
61
- render(
62
- <Pagination pageCount={11} currentPage={11} getPageHref={getPageHref} />
63
- );
64
- const links = screen.getAllByRole("button");
65
- expect(links[9]).toHaveAttribute("aria-disabled");
66
- const linkClass = links[9].getAttribute("class");
67
- expect(linkClass).toContain("pagination__link disabled");
68
- });
63
+ expect(links).toHaveLength(6);
64
+ expect(screen.queryByText("Previous")).not.toBeInTheDocument();
65
+ expect(screen.getByText("Next")).toBeInTheDocument();
66
+ });
69
67
 
70
- it("Current page item has active class", () => {
71
- render(
72
- <Pagination pageCount={11} currentPage={5} getPageHref={getPageHref} />
73
- );
74
- const links = screen.getAllByRole("button");
75
- const linkClass = links[5].getAttribute("class");
76
- expect(linkClass).toContain("pagination__link selected");
77
- });
68
+ it("does not render the Next link on the last page", () => {
69
+ render(
70
+ <Pagination pageCount={5} initialPage={5} getPageHref={getPageHref} />
71
+ );
72
+ // Pagination should show:
73
+ // Previous 1 2 3 4 5
74
+ const links = screen.getAllByRole("link");
78
75
 
79
- it("When pagination has 1 element, pagination is not shown", () => {
80
- render(
81
- <Pagination pageCount={1} currentPage={1} getPageHref={getPageHref} />
82
- );
83
- expect(screen.queryByRole("navigation")).not.toBeInTheDocument();
84
- });
76
+ expect(links).toHaveLength(6);
77
+ expect(screen.getByText("Previous")).toBeInTheDocument();
78
+ expect(screen.queryByText("Next")).not.toBeInTheDocument();
79
+ });
85
80
 
86
- it("When pagination has 0 elements, pagination is not shown", () => {
87
- render(
88
- <Pagination pageCount={0} currentPage={1} getPageHref={getPageHref} />
89
- );
90
- expect(screen.queryByRole("navigation")).not.toBeInTheDocument();
91
- });
92
- });
81
+ it("renders an ellipsis at the end of the list", () => {
82
+ render(
83
+ <Pagination pageCount={10} initialPage={1} getPageHref={getPageHref} />
84
+ );
85
+ // Pagination should show:
86
+ // 1 2 3 4 5 ... 10 Next
87
+ const listitem = screen.getAllByRole("listitem");
93
88
 
94
- describe("Pagination with changeCallback", () => {
95
- const changeCallback = jest.fn();
89
+ expect(listitem).toHaveLength(8);
90
+ // The ellipsis is not a link
91
+ expect(screen.getAllByRole("link")).toHaveLength(7);
92
+ expect(listitem[4].textContent).toEqual("5");
93
+ expect(listitem[5].textContent).toEqual("...");
94
+ expect(listitem[6].textContent).toEqual("10");
95
+ expect(screen.getByText("...")).toBeInTheDocument();
96
+ });
96
97
 
97
- it("Renders a nav element with an unordered list of items", () => {
98
- const { container } = render(
99
- <Pagination
100
- pageCount={11}
101
- currentPage={6}
102
- onPageChange={changeCallback}
103
- />
104
- );
105
- expect(screen.getByRole("navigation")).toBeInTheDocument();
106
- expect(container.querySelector(".pagination__list")).toBeInTheDocument();
107
- expect(screen.getAllByRole("listitem")).toHaveLength(11);
108
- });
98
+ it("renders an ellipsis at the start of the list", () => {
99
+ render(
100
+ <Pagination pageCount={10} initialPage={10} getPageHref={getPageHref} />
101
+ );
102
+ // Pagination should show:
103
+ // Previous 1 ... 6 7 8 9 10
104
+ const listitem = screen.getAllByRole("listitem");
109
105
 
110
- it("Previous link is disabled when on the first page item", () => {
111
- render(
112
- <Pagination
113
- pageCount={11}
114
- currentPage={1}
115
- onPageChange={changeCallback}
116
- />
117
- );
118
- const links = screen.getAllByRole("button");
119
- expect(links[0]).toHaveAttribute("aria-disabled");
120
- const linkClass = links[0].getAttribute("class");
121
- expect(linkClass).toContain("pagination__link disabled");
122
- });
106
+ expect(listitem).toHaveLength(8);
107
+ // The ellipsis is not a link
108
+ expect(screen.getAllByRole("link")).toHaveLength(7);
109
+ expect(listitem[1].textContent).toEqual("1");
110
+ expect(listitem[2].textContent).toEqual("...");
111
+ expect(listitem[3].textContent).toEqual("6");
112
+ expect(screen.getByText("...")).toBeInTheDocument();
113
+ });
123
114
 
124
- it("Next link is disabled when on the last page item", () => {
125
- render(
126
- <Pagination
127
- pageCount={11}
128
- currentPage={11}
129
- onPageChange={changeCallback}
130
- />
131
- );
132
- const links = screen.getAllByRole("button");
133
- expect(links[9]).toHaveAttribute("aria-disabled");
134
- const linkClass = links[9].getAttribute("class");
135
- expect(linkClass).toContain("pagination__link disabled");
136
- });
115
+ it("renders two ellipsis when the current page is in the middle", () => {
116
+ render(
117
+ <Pagination pageCount={10} initialPage={5} getPageHref={getPageHref} />
118
+ );
119
+ // Pagination should show:
120
+ // Previous 1 ... 4 5 6 ... 10 Next
121
+ const listitem = screen.getAllByRole("listitem");
137
122
 
138
- it("Current page item has active class", () => {
139
- render(
140
- <Pagination
141
- pageCount={11}
142
- currentPage={5}
143
- onPageChange={changeCallback}
144
- />
145
- );
146
- const links = screen.getAllByRole("button");
147
- const linkClass = links[5].getAttribute("class");
148
- expect(linkClass).toContain("pagination__link selected");
149
- });
123
+ expect(listitem).toHaveLength(9);
124
+ // The ellipses are not links
125
+ expect(screen.getAllByRole("link")).toHaveLength(7);
126
+ expect(listitem[0].textContent).toEqual("Previous");
127
+ expect(listitem[1].textContent).toEqual("1");
128
+ expect(listitem[2].textContent).toEqual("...");
129
+ expect(listitem[3].textContent).toEqual("4");
130
+ expect(listitem[4].textContent).toEqual("5");
131
+ expect(listitem[5].textContent).toEqual("6");
132
+ expect(listitem[6].textContent).toEqual("...");
133
+ expect(listitem[7].textContent).toEqual("10");
134
+ expect(listitem[8].textContent).toEqual("Next");
135
+ expect(screen.getAllByText("...")).toHaveLength(2);
136
+ });
150
137
 
151
- it("When page item is selected, runs the onPageChange callback", () => {
152
- render(
153
- <Pagination
154
- pageCount={11}
155
- currentPage={5}
156
- onPageChange={changeCallback}
157
- />
158
- );
159
- const links = screen.getAllByRole("button");
160
- expect(changeCallback).toHaveBeenCalledTimes(0);
161
- userEvent.click(links[2]);
162
- expect(changeCallback).toHaveBeenCalledTimes(1);
163
- });
138
+ it("adds aria-current to the active page", () => {
139
+ render(
140
+ <Pagination pageCount={5} initialPage={3} getPageHref={getPageHref} />
141
+ );
142
+ // Pagination should show:
143
+ // Previous 1 2 3 4 5 Next
144
+ const links = screen.getAllByRole("link");
145
+ const page2 = links[2].getAttribute("aria-current");
146
+ const page3 = links[3].getAttribute("aria-current");
147
+ const page4 = links[4].getAttribute("aria-current");
164
148
 
165
- it("When pagination has 1 element, pagination is not shown", () => {
166
- render(
167
- <Pagination pageCount={1} currentPage={1} onPageChange={changeCallback} />
168
- );
169
- expect(screen.queryByRole("navigation")).not.toBeInTheDocument();
149
+ expect(page2).toEqual(null);
150
+ // Only the current page has `aria-current="page"` for accessibility.
151
+ expect(page3).toEqual("page");
152
+ expect(page4).toEqual(null);
153
+ });
154
+
155
+ it("When pagination has 1 element, pagination is not shown", () => {
156
+ render(
157
+ <Pagination pageCount={1} initialPage={1} getPageHref={getPageHref} />
158
+ );
159
+ expect(screen.queryByRole("navigation")).not.toBeInTheDocument();
160
+ });
161
+
162
+ it("When pagination has 0 elements, pagination is not shown", () => {
163
+ render(
164
+ <Pagination pageCount={0} initialPage={1} getPageHref={getPageHref} />
165
+ );
166
+ expect(screen.queryByRole("navigation")).not.toBeInTheDocument();
167
+ });
168
+
169
+ it("Renders the UI snapshot correctly", () => {
170
+ const firstPage = renderer
171
+ .create(
172
+ <Pagination
173
+ id="firstPage"
174
+ pageCount={10}
175
+ initialPage={1}
176
+ getPageHref={getPageHref}
177
+ />
178
+ )
179
+ .toJSON();
180
+ const lastPage = renderer
181
+ .create(
182
+ <Pagination
183
+ id="lastPage"
184
+ pageCount={10}
185
+ initialPage={10}
186
+ getPageHref={getPageHref}
187
+ />
188
+ )
189
+ .toJSON();
190
+ const middlePage = renderer
191
+ .create(
192
+ <Pagination
193
+ id="middlePage"
194
+ pageCount={10}
195
+ initialPage={5}
196
+ getPageHref={getPageHref}
197
+ />
198
+ )
199
+ .toJSON();
200
+
201
+ expect(firstPage).toMatchSnapshot();
202
+ expect(lastPage).toMatchSnapshot();
203
+ expect(middlePage).toMatchSnapshot();
204
+ });
170
205
  });
171
206
 
172
- it("When pagination has 0 elements, pagination is not shown", () => {
173
- render(
174
- <Pagination pageCount={0} currentPage={1} onPageChange={changeCallback} />
175
- );
176
- expect(screen.queryByRole("navigation")).not.toBeInTheDocument();
207
+ describe("Behavior", () => {
208
+ it("updates the links href value when getPageHref is used", () => {
209
+ const getPageHref = (page: number) => `?page=${page}`;
210
+ render(
211
+ <Pagination pageCount={10} initialPage={5} getPageHref={getPageHref} />
212
+ );
213
+ // Pagination should show:
214
+ // Previous 1 ... 4 5 6 ... 10 Next
215
+ const links = screen.getAllByRole("link");
216
+
217
+ expect(screen.getByText("Previous")).toBeInTheDocument();
218
+ expect(screen.getByText("Next")).toBeInTheDocument();
219
+
220
+ // Previous link
221
+ expect(links[0].getAttribute("href")).toEqual("?page=4");
222
+ expect(links[1].getAttribute("href")).toEqual("?page=1");
223
+ expect(links[2].getAttribute("href")).toEqual("?page=4");
224
+ expect(links[3].getAttribute("href")).toEqual("?page=5");
225
+ expect(links[4].getAttribute("href")).toEqual("?page=6");
226
+ expect(links[5].getAttribute("href")).toEqual("?page=10");
227
+ // Next link
228
+ expect(links[6].getAttribute("href")).toEqual("?page=6");
229
+ });
230
+
231
+ // In this scenario, we need to update the current page ourselves
232
+ // since we stay on the same page.
233
+ it("When page item is selected, runs the onPageChange callback", () => {
234
+ const onPageChange = (page: number) => (currentPage = page);
235
+ let currentPage = 5;
236
+ const { rerender } = render(
237
+ <Pagination
238
+ pageCount={10}
239
+ initialPage={currentPage}
240
+ onPageChange={onPageChange}
241
+ />
242
+ );
243
+ // Pagination should show:
244
+ // Previous 1 ... 4 5 6 ... 10 Next
245
+ let links = screen.getAllByRole("link");
246
+
247
+ // Links all have "#" for their href value.
248
+ // Previous link
249
+ expect(links[0].getAttribute("href")).toEqual("#");
250
+ expect(links[1].getAttribute("href")).toEqual("#");
251
+ expect(links[2].getAttribute("href")).toEqual("#");
252
+ expect(links[3].getAttribute("href")).toEqual("#");
253
+ expect(links[4].getAttribute("href")).toEqual("#");
254
+ expect(links[5].getAttribute("href")).toEqual("#");
255
+ // Next link
256
+ expect(links[6].getAttribute("href")).toEqual("#");
257
+
258
+ // Page 4
259
+ userEvent.click(links[2]);
260
+ expect(currentPage).toEqual(4);
261
+
262
+ rerender(
263
+ <Pagination
264
+ pageCount={10}
265
+ initialPage={currentPage}
266
+ onPageChange={onPageChange}
267
+ />
268
+ );
269
+ // Pagination should show:
270
+ // Previous 1 2 3 4 5 ... 10 Next
271
+ links = screen.getAllByRole("link");
272
+
273
+ // Previous link
274
+ userEvent.click(links[0]);
275
+ expect(currentPage).toEqual(3);
276
+
277
+ rerender(
278
+ <Pagination
279
+ pageCount={10}
280
+ initialPage={currentPage}
281
+ onPageChange={onPageChange}
282
+ />
283
+ );
284
+ // Pagination should show:
285
+ // Previous 1 2 3 4 5 ... 10 Next
286
+ links = screen.getAllByRole("link");
287
+
288
+ // Page 10
289
+ userEvent.click(links[6]);
290
+ expect(currentPage).toEqual(10);
291
+
292
+ rerender(
293
+ <Pagination
294
+ pageCount={10}
295
+ initialPage={currentPage}
296
+ onPageChange={onPageChange}
297
+ />
298
+ );
299
+ // Pagination should show:
300
+ // Previous 1 ... 6 7 8 9 10
301
+ links = screen.getAllByRole("link");
302
+
303
+ // Page 6
304
+ userEvent.click(links[2]);
305
+ expect(currentPage).toEqual(6);
306
+ });
177
307
  });
178
308
  });