@scottish-government/designsystem-react 0.3.0-beta.0 → 0.4.0

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 (55) hide show
  1. package/@types/common/AbstractNotificationBanner.d.ts +17 -0
  2. package/@types/components/Table.d.ts +8 -0
  3. package/@types/components/TaskList.d.ts +1 -1
  4. package/dist/common/abstract-notification-banner.jsx +63 -0
  5. package/dist/components/accordion/accordion.jsx +2 -3
  6. package/dist/components/breadcrumbs/breadcrumbs.jsx +2 -2
  7. package/dist/components/cookie-banner/cookie-banner.jsx +21 -0
  8. package/dist/components/notification-banner/notification-banner.jsx +7 -34
  9. package/dist/components/page-metadata/page-metadata.jsx +2 -3
  10. package/dist/components/table/table.jsx +24 -0
  11. package/dist/components/task-list/task-list.jsx +6 -7
  12. package/dist/tsconfig.tsbuildinfo +1 -1
  13. package/package.json +1 -1
  14. package/src/common/abstract-notification-banner.test.tsx +126 -0
  15. package/src/common/abstract-notification-banner.tsx +87 -0
  16. package/src/common/conditional-wrapper.test.tsx +1 -1
  17. package/src/common/screen-reader-text.test.tsx +1 -1
  18. package/src/common/wrapper-tag.test.tsx +3 -3
  19. package/src/components/accordion/accordion.test.tsx +40 -40
  20. package/src/components/accordion/accordion.tsx +4 -2
  21. package/src/components/aspect-box/aspect-box.test.tsx +7 -7
  22. package/src/components/breadcrumbs/breadcrumbs.tsx +0 -2
  23. package/src/components/checkbox/checkbox.test.tsx +8 -8
  24. package/src/components/confirmation-message/confirmation-message.test.tsx +1 -1
  25. package/src/components/cookie-banner/cookie-banner.test.tsx +25 -0
  26. package/src/components/cookie-banner/cookie-banner.tsx +36 -0
  27. package/src/components/details/details.test.tsx +7 -7
  28. package/src/components/inset-text/inset-text.test.tsx +1 -1
  29. package/src/components/notification-banner/notification-banner.test.tsx +13 -73
  30. package/src/components/notification-banner/notification-banner.tsx +13 -41
  31. package/src/components/notification-panel/notification-panel.test.tsx +6 -6
  32. package/src/components/page-header/page-header.test.tsx +2 -2
  33. package/src/components/page-metadata/page-metadata.test.tsx +12 -12
  34. package/src/components/page-metadata/page-metadata.tsx +4 -2
  35. package/src/components/pagination/pagination.test.tsx +28 -30
  36. package/src/components/phase-banner/phase-banner.test.tsx +8 -8
  37. package/src/components/question/question.test.tsx +3 -3
  38. package/src/components/radio-button/radio-button.test.tsx +7 -7
  39. package/src/components/select/select.test.tsx +9 -9
  40. package/src/components/sequential-navigation/sequential-navigation.test.tsx +4 -4
  41. package/src/components/side-navigation/side-navigation.test.tsx +1 -1
  42. package/src/components/site-header/site-header.test.tsx +22 -22
  43. package/src/components/site-search/site-search.test.tsx +9 -9
  44. package/src/components/skip-links/skip-links.test.tsx +3 -3
  45. package/src/components/summary-card/summary-card.test.tsx +2 -2
  46. package/src/components/summary-list/summary-list.test.tsx +35 -16
  47. package/src/components/table/table.test.tsx +77 -0
  48. package/src/components/table/table.tsx +36 -0
  49. package/src/components/task-list/task-list.test.tsx +81 -83
  50. package/src/components/task-list/task-list.tsx +9 -5
  51. package/src/components/text-input/text-input.test.tsx +6 -6
  52. package/src/components/textarea/textarea.test.tsx +2 -2
  53. package/src/components/warning-text/warning-text.test.tsx +1 -1
  54. package/vitest-setup.ts +1 -1
  55. package/@types/components/NotificationBanner.d.ts +0 -9
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Most of the functionality for CookieBanner is covered in AbstractNotificationBanner.
3
+ * Differences are specifically tested here.
4
+ */
5
+
6
+ import { test, expect } from 'vitest';
7
+ import { render } from '@testing-library/react';
8
+ import CookieBanner from './cookie-banner';
9
+
10
+ const text = 'We need to tell you about something';
11
+
12
+ /**
13
+ * CookieBanner has additional classNames
14
+ */
15
+ test('cookie banner renders correctly', () => {
16
+ render(
17
+ <CookieBanner>
18
+ {text}
19
+ </CookieBanner>
20
+ );
21
+
22
+ const bannerContainer = document.querySelector('.ds_notification');
23
+
24
+ expect(bannerContainer).toHaveClass('ds_notification', 'ds_notification--large', 'ds_notification--cookie', 'js-initial-cookie-content');
25
+ });
@@ -0,0 +1,36 @@
1
+
2
+ import AbstractNotificationBanner from '../../common/abstract-notification-banner';
3
+ // @ts-ignore
4
+ import DSCookieBanner from '@scottish-government/design-system/src/components/cookie-notification/cookie-notification.js';
5
+
6
+ const CookieBanner: React.FC<SGDS.Common.AbstractNotificationBanner>
7
+ & { Buttons?: React.FC<SGDS.Common.AbstractNotificationBanner.Buttons> } = ({
8
+ children,
9
+ className,
10
+ title,
11
+ ...props
12
+ }) => {
13
+
14
+ return (
15
+ <>
16
+ <AbstractNotificationBanner
17
+ className={[
18
+ 'ds_notification--large',
19
+ 'ds_notification--cookie',
20
+ 'js-initial-cookie-content',
21
+ className
22
+ ].join(' ')}
23
+ data-module="ds-cookie-notification"
24
+ title={title}
25
+ {...props}
26
+ >
27
+ {children}
28
+ </AbstractNotificationBanner>
29
+ </>
30
+ );
31
+ }
32
+
33
+ CookieBanner.displayName = 'CookieBanner';
34
+ CookieBanner.Buttons = AbstractNotificationBanner.Buttons;
35
+
36
+ export default CookieBanner;
@@ -14,15 +14,15 @@ test('details renders correctly', () => {
14
14
  );
15
15
 
16
16
  const summaryElement = screen.getByText(summaryText);
17
- const detailsElement = summaryElement.parentNode;
18
- const textElement = summaryElement.nextSibling;
17
+ const detailsElement = summaryElement.parentElement;
18
+ const textElement = summaryElement.nextElementSibling;
19
19
 
20
20
  expect(detailsElement).toHaveClass('ds_details');
21
- expect(detailsElement.tagName).toEqual('DETAILS');
21
+ expect(detailsElement?.tagName).toEqual('DETAILS');
22
22
  expect(summaryElement).toHaveClass('ds_details__summary');
23
- expect(summaryElement.tagName).toEqual('SUMMARY');
23
+ expect(summaryElement?.tagName).toEqual('SUMMARY');
24
24
  expect(textElement).toHaveClass('ds_details__text');
25
- expect(textElement.innerHTML).toEqual(content);
25
+ expect(textElement?.innerHTML).toEqual(content);
26
26
  });
27
27
 
28
28
  test('passing additional props', () => {
@@ -33,7 +33,7 @@ test('passing additional props', () => {
33
33
  )
34
34
 
35
35
  const summaryElement = screen.getByText(summaryText);
36
- const detailsElement = summaryElement.parentNode;
36
+ const detailsElement = summaryElement.parentElement;
37
37
  expect(detailsElement?.dataset.test).toEqual('foo');
38
38
  });
39
39
 
@@ -45,6 +45,6 @@ test('passing additional CSS classes', () => {
45
45
  )
46
46
 
47
47
  const summaryElement = screen.getByText(summaryText);
48
- const detailsElement = summaryElement.parentNode;
48
+ const detailsElement = summaryElement.parentElement;
49
49
  expect(detailsElement).toHaveClass('foo', 'ds_details');
50
50
  });
@@ -28,7 +28,7 @@ test('passing additional props', () => {
28
28
  </InsetText>
29
29
  )
30
30
 
31
- const insetTextOuter = document.querySelector('.ds_inset-text');
31
+ const insetTextOuter = document.querySelector('.ds_inset-text') as HTMLElement;
32
32
  expect(insetTextOuter?.dataset.test).toEqual('foo');
33
33
  });
34
34
 
@@ -1,9 +1,17 @@
1
+ /**
2
+ * Most of the functionality for NotificationBanner is covered in AbstractNotificationBanner.
3
+ * Differences are specifically tested here.
4
+ */
5
+
1
6
  import { test, expect } from 'vitest';
2
7
  import { render, screen, within } from '@testing-library/react';
3
8
  import NotificationBanner from './notification-banner';
4
9
 
5
10
  const text = 'We need to tell you about something';
6
11
 
12
+ /**
13
+ * NotificationBanner has the ds_reversed class
14
+ */
7
15
  test('notification banner renders correctly', () => {
8
16
  render(
9
17
  <NotificationBanner>
@@ -11,47 +19,14 @@ test('notification banner renders correctly', () => {
11
19
  </NotificationBanner>
12
20
  );
13
21
 
14
- const bannerTitle = screen.getByRole('heading');
15
- const bannerText = bannerTitle.nextSibling;
16
- const bannerContent = bannerTitle.parentNode;
17
- const bannerWrapper = bannerContent?.parentNode;
18
- const bannerContainer = bannerWrapper?.parentNode;
19
-
20
- expect(bannerTitle.textContent).toEqual('Information');
21
- expect(bannerTitle.tagName).toEqual('H2');
22
- expect(bannerTitle).toHaveClass('visually-hidden');
23
-
24
- expect(bannerText).toHaveClass('ds_notification__text');
25
- expect(bannerText.textContent).toEqual(text);
22
+ const bannerContainer = document.querySelector('.ds_notification');
26
23
 
27
- expect(bannerContent).toHaveClass('ds_notification__content');
28
- expect(bannerWrapper).toHaveClass('ds_wrapper');
29
24
  expect(bannerContainer).toHaveClass('ds_notification', 'ds_reversed');
30
25
  });
31
26
 
32
- test('notification banner with close button', () => {
33
- render(
34
- <NotificationBanner close>
35
- {text}
36
- </NotificationBanner>
37
- );
38
-
39
- const bannerTitle = screen.getByRole('heading');
40
- const bannerContent = bannerTitle.parentNode;
41
- const closeButton = screen.getByRole('button');
42
- const closeButtonLabel = within(closeButton).getByText('Close this notification');
43
- const closeButtonIcon = within(closeButton).getByRole('img', { hidden: true });
44
-
45
- expect(bannerContent).toHaveClass('ds_notification__content--has-close');
46
- expect(closeButton).toHaveClass('ds_notification__close', 'js-close-notification');
47
- expect(closeButton).toHaveAttribute('type', 'button');
48
-
49
- expect(closeButtonLabel).toBeInTheDocument();
50
- expect(closeButtonLabel).toHaveClass('visually-hidden');
51
-
52
- expect(closeButtonIcon).toHaveClass('ds_icon', 'ds_icon--fill');
53
- });
54
-
27
+ /**
28
+ * NotificationBanner uses a boolean to toggle icon display, as only a single icon (PriorityHigh) is expected.
29
+ */
55
30
  test('notification banner with icon', () => {
56
31
  render(
57
32
  <NotificationBanner icon>
@@ -60,45 +35,10 @@ test('notification banner with icon', () => {
60
35
  );
61
36
 
62
37
  const bannerTitle = screen.getByRole('heading');
63
- const bannerIconContainer = bannerTitle.nextSibling;
38
+ const bannerIconContainer = bannerTitle.nextElementSibling as HTMLElement;
64
39
  const bannerIcon = within(bannerIconContainer).getByRole('img', { hidden: true });
65
40
 
66
41
  expect(bannerIconContainer).toHaveClass('ds_notification__icon');
67
42
  expect(bannerIcon).toHaveClass('ds_icon');
68
43
  expect(bannerIcon).toHaveAttribute('aria-hidden');
69
44
  });
70
-
71
- test('notification banner with icon modifier classes', () => {
72
- render(
73
- <NotificationBanner icon iconColour iconInverse>
74
- {text}
75
- </NotificationBanner>
76
- );
77
-
78
- const bannerTitle = screen.getByRole('heading');
79
- const bannerIconContainer = bannerTitle.nextSibling;
80
-
81
- expect(bannerIconContainer).toHaveClass('ds_notification__icon', 'ds_notification__icon--inverse', 'ds_notification__icon--colour');
82
- });
83
-
84
- test('passing additional props', () => {
85
- render(
86
- <NotificationBanner data-test="foo">
87
- {text}
88
- </NotificationBanner>
89
- )
90
-
91
- const bannerContainer = document.querySelector('.ds_notification');
92
- expect(bannerContainer?.dataset.test).toEqual('foo');
93
- });
94
-
95
- test('passing additional CSS classes', () => {
96
- render(
97
- <NotificationBanner className="foo">
98
- {text}
99
- </NotificationBanner>
100
- )
101
-
102
- const bannerContainer = document.querySelector('.ds_notification');
103
- expect(bannerContainer).toHaveClass('foo', 'ds_notification');
104
- });
@@ -1,18 +1,17 @@
1
1
  import { useEffect, useRef } from 'react';
2
-
2
+ import AbstractNotificationBanner from '../../common/abstract-notification-banner';
3
3
  // @ts-ignore
4
4
  import DSNotificationBanner from '@scottish-government/design-system/src/components/notification-banner/notification-banner';
5
- import Icon from '../../common/icon';
6
- import ScreenReaderText from '../../common/screen-reader-text';
7
5
 
8
- const NotificationBanner: React.FC<SGDS.Component.NotificationBanner> = ({
6
+ const NotificationBanner: React.FC<SGDS.Common.AbstractNotificationBanner>
7
+ & { Buttons?: React.FC<SGDS.Common.AbstractNotificationBanner.Buttons> } = ({
9
8
  children,
10
9
  className,
11
10
  close,
12
11
  icon,
13
12
  iconColour,
14
13
  iconInverse,
15
- title = 'Information',
14
+ title,
16
15
  ...props
17
16
  }) => {
18
17
  const ref = useRef(null);
@@ -24,52 +23,25 @@ const NotificationBanner: React.FC<SGDS.Component.NotificationBanner> = ({
24
23
  }, [ref]);
25
24
 
26
25
  return (
27
- <div
26
+ <AbstractNotificationBanner
28
27
  className={[
29
- 'ds_notification',
30
28
  'ds_reversed',
31
29
  className
32
30
  ].join(' ')}
33
- data-module="ds-notification"
31
+ close={close}
32
+ icon={icon ? "PriorityHigh" : undefined}
33
+ iconColour={iconColour}
34
+ iconInverse={iconInverse}
34
35
  ref={ref}
36
+ title="Information"
35
37
  {...props}
36
38
  >
37
- <div className="ds_wrapper">
38
- <div className={
39
- [
40
- 'ds_notification__content',
41
- close && 'ds_notification__content--has-close'
42
- ].join(' ')}
43
- >
44
- <h2 className="visually-hidden">{title}</h2>
45
-
46
- {icon &&
47
- <span
48
- className={[
49
- 'ds_notification__icon',
50
- iconInverse && 'ds_notification__icon--inverse',
51
- iconColour && 'ds_notification__icon--colour'
52
- ].join(' ')} aria-hidden="true">
53
- <Icon icon="PriorityHigh" />
54
- </span>
55
- }
56
-
57
- <div className="ds_notification__text">
58
- {children}
59
- </div>
60
-
61
- {close &&
62
- <button type="button" className="ds_notification__close js-close-notification">
63
- <ScreenReaderText>Close this notification</ScreenReaderText>
64
- <Icon fill icon="Close" aria-hidden="true" />
65
- </button>
66
- }
67
- </div>
68
- </div>
69
- </div>
39
+ {children}
40
+ </AbstractNotificationBanner>
70
41
  );
71
42
  };
72
43
 
73
44
  NotificationBanner.displayName = 'NotificationBanner';
45
+ NotificationBanner.Buttons = AbstractNotificationBanner.Buttons;
74
46
 
75
47
  export default NotificationBanner;
@@ -13,15 +13,15 @@ test('notification banner renders correctly', () => {
13
13
  );
14
14
 
15
15
  const notificationPanelHeading = screen.getByRole('heading');
16
- const notificationPanelContent = notificationPanelHeading.nextSibling;
17
- const notificationPanel = notificationPanelHeading.parentNode;
16
+ const notificationPanelContent = notificationPanelHeading.nextElementSibling;
17
+ const notificationPanel = notificationPanelHeading.parentElement;
18
18
 
19
19
  expect(notificationPanel).toHaveClass('ds_notification-panel');
20
20
  expect(notificationPanelHeading).toHaveClass('ds_notification-panel__title');
21
21
  expect(notificationPanelHeading.textContent).toEqual(headingText);
22
22
  expect(notificationPanelHeading.tagName).toEqual('H1');
23
23
  expect(notificationPanelContent).toHaveClass('ds_notification-panel__content');
24
- expect(notificationPanelContent.textContent).toEqual(text);
24
+ expect(notificationPanelContent?.textContent).toEqual(text);
25
25
  });
26
26
 
27
27
  test('notification banner with custom heading level', () => {
@@ -47,7 +47,7 @@ test('notification banner with aria-live', () => {
47
47
  );
48
48
 
49
49
  const notificationPanelHeading = screen.getByRole('heading');
50
- const notificationPanel = notificationPanelHeading.parentNode;
50
+ const notificationPanel = notificationPanelHeading.parentElement;
51
51
 
52
52
  expect(notificationPanel).toHaveAttribute('aria-live', ariaLive);
53
53
  });
@@ -72,7 +72,7 @@ test('passing additional props', () => {
72
72
  )
73
73
 
74
74
  const notificationPanelHeading = screen.getByRole('heading');
75
- const notificationPanel = notificationPanelHeading.parentNode;
75
+ const notificationPanel = notificationPanelHeading.parentElement;
76
76
  expect(notificationPanel?.dataset.test).toEqual('foo');
77
77
  });
78
78
 
@@ -84,6 +84,6 @@ test('passing additional CSS classes', () => {
84
84
  )
85
85
 
86
86
  const notificationPanelHeading = screen.getByRole('heading');
87
- const notificationPanel = notificationPanelHeading.parentNode;
87
+ const notificationPanel = notificationPanelHeading.parentElement;
88
88
  expect(notificationPanel).toHaveClass('foo', 'ds_notification-panel');
89
89
  });
@@ -12,7 +12,7 @@ test('notification banner renders correctly', () => {
12
12
 
13
13
  const header = screen.getByRole('banner');
14
14
  const title = within(header).getByRole('heading');
15
- const label = title.previousSibling;;
15
+ const label = title.previousElementSibling;
16
16
 
17
17
  expect(header).toHaveClass('ds_page-header');
18
18
  expect(header.tagName).toEqual('HEADER');
@@ -33,7 +33,7 @@ test('header with no label', () => {
33
33
 
34
34
  const header = screen.getByRole('banner');
35
35
  const title = within(header).getByRole('heading');
36
- const label = title.previousSibling;
36
+ const label = title.previousElementSibling;
37
37
 
38
38
  expect(label).not.toBeInTheDocument();
39
39
  });
@@ -1,6 +1,6 @@
1
1
  import { test, expect } from 'vitest';
2
- import { render, screen, within } from '@testing-library/react';
3
- import Metadata, {MetadataItem} from './page-metadata';
2
+ import { render, screen } from '@testing-library/react';
3
+ import Metadata from './page-metadata';
4
4
 
5
5
  const name = 'Directorate';
6
6
  const value = 'Equality, Inclusion and Human Rights Directorate';
@@ -8,9 +8,9 @@ const value = 'Equality, Inclusion and Human Rights Directorate';
8
8
  test('metadata renders correctly', () => {
9
9
  render(
10
10
  <Metadata>
11
- <MetadataItem name={name}>
11
+ <Metadata.Item name={name}>
12
12
  {value}
13
- </MetadataItem>
13
+ </Metadata.Item>
14
14
  </Metadata>
15
15
  );
16
16
 
@@ -30,9 +30,9 @@ test('metadata renders correctly', () => {
30
30
  test('inline metadata', () => {
31
31
  render(
32
32
  <Metadata inline>
33
- <MetadataItem name={name}>
33
+ <Metadata.Item name={name}>
34
34
  {value}
35
- </MetadataItem>
35
+ </Metadata.Item>
36
36
  </Metadata>
37
37
  );
38
38
 
@@ -43,14 +43,14 @@ test('inline metadata', () => {
43
43
  test('passing additional props', () => {
44
44
  render(
45
45
  <Metadata data-test="foo">
46
- <MetadataItem data-test="bar" name="Last updated">
46
+ <Metadata.Item data-test="bar" name="Last updated">
47
47
  21/04/2020
48
- </MetadataItem>
48
+ </Metadata.Item>
49
49
  </Metadata>
50
50
  )
51
51
 
52
- const metadata = document.querySelector('.ds_metadata');
53
- const metadataItem = document.querySelector('.ds_metadata__item');
52
+ const metadata = document.querySelector('.ds_metadata') as HTMLElement;
53
+ const metadataItem = document.querySelector('.ds_metadata__item') as HTMLElement;
54
54
  expect(metadata?.dataset.test).toEqual('foo');
55
55
  expect(metadataItem?.dataset.test).toEqual('bar');
56
56
  });
@@ -58,9 +58,9 @@ test('passing additional props', () => {
58
58
  test('passing additional CSS classes', () => {
59
59
  render(
60
60
  <Metadata className="foo">
61
- <MetadataItem className="bar" name="Last updated">
61
+ <Metadata.Item className="bar" name="Last updated">
62
62
  21/04/2020
63
- </MetadataItem>
63
+ </Metadata.Item>
64
64
  </Metadata>
65
65
  )
66
66
 
@@ -1,4 +1,4 @@
1
- export const MetadataItem: React.FC<SGDS.Component.Metadata.Item> = ({
1
+ const MetadataItem: React.FC<SGDS.Component.Metadata.Item> = ({
2
2
  children,
3
3
  className,
4
4
  name,
@@ -19,7 +19,8 @@ export const MetadataItem: React.FC<SGDS.Component.Metadata.Item> = ({
19
19
  );
20
20
  };
21
21
 
22
- const Metadata: React.FC<SGDS.Component.Metadata> = ({
22
+ const Metadata: React.FC<SGDS.Component.Metadata>
23
+ & { Item: React.FC<SGDS.Component.Metadata.Item> } = ({
23
24
  children,
24
25
  className,
25
26
  inline,
@@ -41,5 +42,6 @@ const Metadata: React.FC<SGDS.Component.Metadata> = ({
41
42
 
42
43
  Metadata.displayName = 'Metadata';
43
44
  MetadataItem.displayName = 'MetadataItem';
45
+ Metadata.Item = MetadataItem;
44
46
 
45
47
  export default Metadata;
@@ -89,28 +89,28 @@ test('pagination renders correctly', () => {
89
89
  const paginationNav = screen.getByRole('navigation');
90
90
  const paginationList = within(paginationNav).getByRole('list');
91
91
  const prevLabel = within(paginationList).getByText('Previous');
92
- const prevLink = prevLabel.parentNode;
93
- const prevIcon = prevLabel.previousSibling;
94
- const prevItem = prevLink?.parentNode;
92
+ const prevLink = prevLabel.parentElement;
93
+ const prevIcon = prevLabel.previousElementSibling;
94
+ const prevItem = prevLink?.parentElement;
95
95
  const nextLabel = within(paginationList).getByText('Next');
96
- const nextLink = nextLabel.parentNode;
97
- const nextIcon = nextLabel.nextSibling;
98
- const nextItem = nextLink?.parentNode;
96
+ const nextLink = nextLabel.parentElement;
97
+ const nextIcon = nextLabel.nextElementSibling;
98
+ const nextItem = nextLink?.parentElement;
99
99
 
100
100
  const firstPageLabel = within(paginationList).getByText('1');
101
- const firstPageLink = firstPageLabel.parentNode;
102
- const firstPageItem = firstPageLink?.parentNode;
101
+ const firstPageLink = firstPageLabel.parentElement;
102
+ const firstPageItem = firstPageLink?.parentElement;
103
103
  const lastPageLabel = within(paginationList).getByText(totalPages);
104
- const lastPageLink = lastPageLabel.parentNode;
105
- const lastPageItem = lastPageLink?.parentNode;
104
+ const lastPageLink = lastPageLabel.parentElement;
105
+ const lastPageItem = lastPageLink?.parentElement;
106
106
 
107
- const firstPageEllipsisItem = firstPageItem?.nextSibling;
107
+ const firstPageEllipsisItem = firstPageItem?.nextElementSibling;
108
108
  const firstPageEllipsis = firstPageEllipsisItem?.children[0];
109
- const lastPageEllipsisItem = lastPageItem?.previousSibling;
109
+ const lastPageEllipsisItem = lastPageItem?.previousElementSibling;
110
110
  const lastPageEllipsis = lastPageEllipsisItem?.children[0];
111
111
 
112
112
  const currentPageLink = document.querySelector('.ds_current');
113
- const currentPageItem = currentPageLink?.parentNode;
113
+ const currentPageItem = currentPageLink?.parentElement;
114
114
 
115
115
  const paginationItems = within(paginationList).getAllByRole('listitem', { hidden: true });
116
116
 
@@ -122,7 +122,7 @@ test('pagination renders correctly', () => {
122
122
 
123
123
  expect(prevItem).toHaveClass('ds_pagination__item');
124
124
  expect(prevItem?.tagName).toEqual('LI');
125
- expect(prevItem?.parentNode).toEqual(paginationList);
125
+ expect(prevItem?.parentElement).toEqual(paginationList);
126
126
  expect(prevLink).toHaveClass('ds_pagination__link', 'ds_pagination__link--text', 'ds_pagination__link--icon')
127
127
  expect(prevLink).toHaveAttribute('aria-label', 'Previous page');
128
128
  expect(prevLink).toHaveAttribute('href', `/search?page=${currentPage - 1}`);
@@ -135,7 +135,7 @@ test('pagination renders correctly', () => {
135
135
 
136
136
  expect(nextItem).toHaveClass('ds_pagination__item');
137
137
  expect(nextItem?.tagName).toEqual('LI');
138
- expect(nextItem?.parentNode).toEqual(paginationList);
138
+ expect(nextItem?.parentElement).toEqual(paginationList);
139
139
  expect(nextLink).toHaveClass('ds_pagination__link', 'ds_pagination__link--text', 'ds_pagination__link--icon')
140
140
  expect(nextLink).toHaveAttribute('aria-label', 'Next page');
141
141
  expect(nextLink).toHaveAttribute('href', `/search?page=${currentPage + 1}`);
@@ -148,7 +148,7 @@ test('pagination renders correctly', () => {
148
148
 
149
149
  expect(firstPageItem).toHaveClass('ds_pagination__item');
150
150
  expect(firstPageItem?.tagName).toEqual('LI');
151
- expect(firstPageItem?.parentNode).toEqual(paginationList);
151
+ expect(firstPageItem?.parentElement).toEqual(paginationList);
152
152
  expect(firstPageLink).toHaveClass('ds_pagination__link')
153
153
  expect(firstPageLink).toHaveAttribute('aria-label', 'Page 1');
154
154
  expect(firstPageLink).toHaveAttribute('href', `/search?page=1`);
@@ -158,7 +158,7 @@ test('pagination renders correctly', () => {
158
158
 
159
159
  expect(lastPageItem).toHaveClass('ds_pagination__item');
160
160
  expect(lastPageItem?.tagName).toEqual('LI');
161
- expect(lastPageItem?.parentNode).toEqual(paginationList);
161
+ expect(lastPageItem?.parentElement).toEqual(paginationList);
162
162
  expect(lastPageLink).toHaveClass('ds_pagination__link')
163
163
  expect(lastPageLink).toHaveAttribute('aria-label', `Page ${totalPages}`);
164
164
  expect(lastPageLink).toHaveAttribute('href', `/search?page=${totalPages}`);
@@ -170,28 +170,28 @@ test('pagination renders correctly', () => {
170
170
 
171
171
  expect(firstPageEllipsisItem).toHaveClass('ds_pagination__item');
172
172
  expect(firstPageEllipsisItem).toHaveAttribute('aria-hidden', 'true');
173
- expect(firstPageEllipsisItem.tagName).toEqual('LI');
173
+ expect(firstPageEllipsisItem?.tagName).toEqual('LI');
174
174
  expect(firstPageEllipsis).toHaveClass('ds_pagination__link', 'ds_pagination__link--ellipsis');
175
- expect(firstPageEllipsis.tagName).toEqual('SPAN');
176
- expect(firstPageEllipsis.textContent).toEqual('…');
175
+ expect(firstPageEllipsis?.tagName).toEqual('SPAN');
176
+ expect(firstPageEllipsis?.textContent).toEqual('…');
177
177
 
178
178
  expect(lastPageEllipsisItem).toHaveClass('ds_pagination__item');
179
179
  expect(lastPageEllipsisItem).toHaveAttribute('aria-hidden', 'true');
180
- expect(lastPageEllipsisItem.tagName).toEqual('LI');
180
+ expect(lastPageEllipsisItem?.tagName).toEqual('LI');
181
181
  expect(lastPageEllipsis).toHaveClass('ds_pagination__link', 'ds_pagination__link--ellipsis');
182
- expect(lastPageEllipsis.tagName).toEqual('SPAN');
183
- expect(lastPageEllipsis.textContent).toEqual('…');
182
+ expect(lastPageEllipsis?.tagName).toEqual('SPAN');
183
+ expect(lastPageEllipsis?.textContent).toEqual('…');
184
184
 
185
185
  expect(currentPageItem).toHaveClass('ds_pagination__item');
186
186
  expect(currentPageLink).toHaveClass('ds_pagination__link', 'ds_current');
187
- expect(currentPageLink.textContent).toEqual(currentPage.toString());
187
+ expect(currentPageLink?.textContent).toEqual(currentPage.toString());
188
188
 
189
189
  // expect one link either side of the current (default padding)
190
- expect(currentPageItem.previousSibling.querySelector('a')).toHaveAttribute('aria-label', 'Page 9');
191
- expect(currentPageItem.previousSibling.previousSibling.querySelector('a')).toBeNull();
190
+ expect(currentPageItem?.previousElementSibling?.querySelector('a')).toHaveAttribute('aria-label', 'Page 9');
191
+ expect(currentPageItem?.previousElementSibling?.previousElementSibling?.querySelector('a')).toBeNull();
192
192
 
193
- expect(currentPageItem.nextSibling.querySelector('a')).toHaveAttribute('aria-label', 'Page 11');
194
- expect(currentPageItem.nextSibling.nextSibling.querySelector('a')).toBeNull();
193
+ expect(currentPageItem?.nextElementSibling?.querySelector('a')).toHaveAttribute('aria-label', 'Page 11');
194
+ expect(currentPageItem?.nextElementSibling?.nextElementSibling?.querySelector('a')).toBeNull();
195
195
 
196
196
  // 9 is: previous, first, ellipsis, current page and 1 padding either side, ellipsis, last, next
197
197
  expect(paginationItems.length).toEqual(9);
@@ -243,8 +243,6 @@ test('pagination passes onclick event to child links', () => {
243
243
  />
244
244
  );
245
245
 
246
- const paginationNav = screen.getByRole('navigation');
247
-
248
246
  // pick an arbitrary link
249
247
  const link = [].slice.call(document.querySelectorAll('.ds_pagination__link'))[4];
250
248
  link.setAttribute('href', '#foo');
@@ -14,16 +14,16 @@ test('phase banner renders correctly', () => {
14
14
 
15
15
  const phaseBanner = document.querySelector('.ds_phase-banner');
16
16
  const phaseBannerContent = phaseBanner?.querySelector('.ds_phase-banner__content');
17
- const phaseBannerWrapper = phaseBannerContent?.parentNode;
17
+ const phaseBannerWrapper = phaseBannerContent?.parentElement;
18
18
  const phaseBannerText = phaseBannerContent?.querySelector('.ds_phase-banner__text');
19
19
 
20
20
  expect(phaseBanner).toBeInTheDocument();
21
21
  expect(phaseBanner?.tagName).toEqual('DIV');
22
22
  expect(phaseBannerWrapper).toHaveClass('ds_wrapper');
23
- expect(phaseBannerWrapper.tagName).toEqual('DIV');
24
- expect(phaseBannerContent.tagName).toEqual('P');
25
- expect(phaseBannerText.tagName).toEqual('SPAN');
26
- expect(phaseBannerText.textContent).toEqual(text);
23
+ expect(phaseBannerWrapper?.tagName).toEqual('DIV');
24
+ expect(phaseBannerContent?.tagName).toEqual('P');
25
+ expect(phaseBannerText?.tagName).toEqual('SPAN');
26
+ expect(phaseBannerText?.textContent).toEqual(text);
27
27
  });
28
28
 
29
29
  test('phase banner with default text', () => {
@@ -50,9 +50,9 @@ test('phase banner with phase tag', () => {
50
50
  const phaseBannerTag = phaseBanner?.querySelector('.ds_phase-banner__tag');
51
51
 
52
52
  expect(phaseBannerTag).toBeInTheDocument();
53
- expect(phaseBannerTag.tagName).toEqual('SPAN');
53
+ expect(phaseBannerTag?.tagName).toEqual('SPAN');
54
54
  expect(phaseBannerTag).toHaveClass('ds_tag', 'ds_phase-banner__tag');
55
- expect(phaseBannerTag.textContent).toEqual(phase);
55
+ expect(phaseBannerTag?.textContent).toEqual(phase);
56
56
  });
57
57
 
58
58
  test('passing additional props', () => {
@@ -62,7 +62,7 @@ test('passing additional props', () => {
62
62
  </PhaseBanner>
63
63
  )
64
64
 
65
- const phaseBanner = document.querySelector('.ds_phase-banner');
65
+ const phaseBanner = document.querySelector('.ds_phase-banner') as HTMLElement;
66
66
  expect(phaseBanner?.dataset.test).toEqual('foo');
67
67
  });
68
68
 
@@ -51,11 +51,11 @@ test('question with error', () => {
51
51
  );
52
52
 
53
53
  const questionElement = document.querySelector('.ds_question');
54
- const errorMessageElement = questionElement.querySelector('.ds_question__error-message');
54
+ const errorMessageElement = questionElement?.querySelector('.ds_question__error-message');
55
55
 
56
56
  expect(questionElement).toHaveClass('ds_question--error');
57
57
  expect(errorMessageElement).toBeInTheDocument();
58
- expect(errorMessageElement.textContent).toEqual(errorMessage);
58
+ expect(errorMessageElement?.textContent).toEqual(errorMessage);
59
59
  });
60
60
 
61
61
  test('passing additional props', () => {
@@ -64,7 +64,7 @@ test('passing additional props', () => {
64
64
  </Question>
65
65
  )
66
66
 
67
- const questionElement = document.querySelector('.ds_question');
67
+ const questionElement = document.querySelector('.ds_question') as HTMLElement;
68
68
  expect(questionElement?.dataset.test).toEqual('foo');
69
69
  });
70
70