@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
@@ -29,7 +29,7 @@ test('radio group renders correct children', () => {
29
29
  );
30
30
 
31
31
  const radios = screen.getAllByRole('radio');
32
- const groupContainer = radios[0].parentNode.parentNode;
32
+ const groupContainer = radios[0].parentElement?.parentElement;
33
33
  expect(radios.length).toEqual(items.length);
34
34
  expect(groupContainer).toHaveClass('ds_radios', 'ds_field-group');
35
35
  });
@@ -53,7 +53,7 @@ test('inline radio group', () => {
53
53
 
54
54
 
55
55
  const radio = screen.getAllByRole('radio')[0];
56
- const groupContainer = radio.parentNode.parentNode;
56
+ const groupContainer = radio.parentElement?.parentElement;
57
57
  expect(groupContainer).toHaveClass('ds_field-group--inline');
58
58
  });
59
59
 
@@ -78,7 +78,7 @@ test('radio group passes all expected item params', () => {
78
78
  );
79
79
 
80
80
  const radio = screen.getByRole('radio');
81
- const radioContainer = radio.parentNode;
81
+ const radioContainer = radio.parentElement;
82
82
  const hintText = screen.getByText('hint text');
83
83
 
84
84
  expect(radio).toHaveAttribute('checked');
@@ -101,7 +101,7 @@ test('individual radio renders correctly', () => {
101
101
  );
102
102
 
103
103
  const radio = screen.getByRole('radio');
104
- const radioContainer = radio.parentNode;
104
+ const radioContainer = radio.parentElement;
105
105
  const label = screen.getByText('Pension Credit');
106
106
 
107
107
  expect(radioContainer).toHaveClass('ds_radio');
@@ -171,7 +171,7 @@ test('small radio', () => {
171
171
  );
172
172
 
173
173
  const radio = screen.getByRole('radio');
174
- const radioContainer = radio.parentNode;
174
+ const radioContainer = radio.parentElement;
175
175
 
176
176
  expect(radioContainer).toHaveClass('ds_radio--small');
177
177
  });
@@ -185,7 +185,7 @@ test('passing additional props', () => {
185
185
  );
186
186
 
187
187
  const radios = screen.getAllByRole('radio');
188
- const groupContainer = radios[0]?.parentNode?.parentNode;
188
+ const groupContainer = radios[0]?.parentElement?.parentElement;
189
189
  expect(groupContainer?.dataset.test).toEqual('foo');
190
190
  });
191
191
 
@@ -198,6 +198,6 @@ test('passing additional CSS classes', () => {
198
198
  );
199
199
 
200
200
  const radios = screen.getAllByRole('radio');
201
- const groupContainer = radios[0]?.parentNode?.parentNode;
201
+ const groupContainer = radios[0]?.parentElement?.parentElement;
202
202
  expect(groupContainer).toHaveClass('foo', 'ds_radios');
203
203
  });
@@ -29,23 +29,23 @@ test('select renders correctly', () => {
29
29
  );
30
30
 
31
31
  const select = screen.getByRole('combobox');
32
- const selectWrapper = select.parentNode;
33
- const label = selectWrapper?.previousSibling;
34
- const selectArrow = select.nextSibling;
32
+ const selectWrapper = select.parentElement;
33
+ const label = selectWrapper?.previousElementSibling;
34
+ const selectArrow = select.nextElementSibling;
35
35
 
36
36
  expect(select).toHaveClass('ds_select');
37
37
  expect(select.id).toEqual(id);
38
38
  expect(select).toHaveAttribute('name', id);
39
39
 
40
40
  expect(selectWrapper).toHaveClass('ds_select-wrapper');
41
- expect(selectWrapper.tagName).toEqual('DIV');
41
+ expect(selectWrapper?.tagName).toEqual('DIV');
42
42
 
43
43
  expect(label).toHaveClass('ds_label');
44
44
  expect(label).toHaveAttribute('for', id);
45
45
 
46
46
  expect(selectArrow).toHaveClass('ds_select-arrow');
47
47
  expect(selectArrow).toHaveAttribute('aria-hidden');
48
- expect(selectArrow.textContent).toEqual('');
48
+ expect(selectArrow?.textContent).toEqual('');
49
49
  });
50
50
 
51
51
  test('select with width', () => {
@@ -60,7 +60,7 @@ test('select with width', () => {
60
60
  />
61
61
  );
62
62
 
63
- const selectWrapper = screen.getByRole('combobox').parentNode;
63
+ const selectWrapper = screen.getByRole('combobox').parentElement;
64
64
  expect(selectWrapper).toHaveClass(`ds_input--${width}`);
65
65
  });
66
66
 
@@ -183,7 +183,7 @@ test('select with error message', () => {
183
183
  );
184
184
 
185
185
  const select = screen.getByRole('combobox');
186
- const selectWrapper = select.parentNode;
186
+ const selectWrapper = select.parentElement;
187
187
  const errorMessageElement = screen.getByText(errorMessage);
188
188
 
189
189
  expect(selectWrapper).toHaveClass('ds_input--error')
@@ -204,7 +204,7 @@ test('passing additional props', () => {
204
204
  );
205
205
 
206
206
  const select = screen.getByRole('combobox');
207
- const selectWrapper = select.parentNode;
207
+ const selectWrapper = select.parentElement;
208
208
  expect(selectWrapper?.dataset.test).toEqual('foo');
209
209
  });
210
210
 
@@ -219,6 +219,6 @@ test('passing additional CSS classes', () => {
219
219
  );
220
220
 
221
221
  const select = screen.getByRole('combobox');
222
- const selectWrapper = select.parentNode;
222
+ const selectWrapper = select.parentElement;
223
223
  expect(selectWrapper).toHaveClass('foo', 'ds_select-wrapper');
224
224
  });
@@ -15,9 +15,9 @@ test('sequential navigation renders correctly', () => {
15
15
 
16
16
  const sequentialNavigation = screen.getByRole('navigation');
17
17
  const prevLink = screen.getAllByRole('link')[0];
18
- const prevLinkWrapper = prevLink.parentNode;
18
+ const prevLinkWrapper = prevLink.parentElement;
19
19
  const nextLink = screen.getAllByRole('link')[1];
20
- const nextLinkWrapper = nextLink.parentNode;
20
+ const nextLinkWrapper = nextLink.parentElement;
21
21
 
22
22
  expect(sequentialNavigation).toHaveClass('ds_sequential-nav');
23
23
  expect(sequentialNavigation).toHaveAttribute('aria-label', 'Article navigation');
@@ -26,14 +26,14 @@ test('sequential navigation renders correctly', () => {
26
26
  expect(prevLink).toHaveAttribute('href', prevLinkObj.href);
27
27
  expect(prevLink.textContent).toEqual(prevLinkObj.title);
28
28
  expect(prevLinkWrapper).toHaveClass('ds_sequential-nav__item', 'ds_sequential-nav__item--prev');
29
- expect(prevLinkWrapper.tagName).toEqual('DIV');
29
+ expect(prevLinkWrapper?.tagName).toEqual('DIV');
30
30
  expect(prevLink.childNodes[0]).toHaveAttribute('data-label', 'Previous')
31
31
 
32
32
  expect(nextLink).toHaveClass('ds_sequential-nav__button', 'ds_sequential-nav__button--right');
33
33
  expect(nextLink).toHaveAttribute('href', nextLinkObj.href);
34
34
  expect(nextLink.textContent).toEqual(nextLinkObj.title);
35
35
  expect(nextLinkWrapper).toHaveClass('ds_sequential-nav__item', 'ds_sequential-nav__item--next');
36
- expect(nextLinkWrapper.tagName).toEqual('DIV');
36
+ expect(nextLinkWrapper?.tagName).toEqual('DIV');
37
37
  expect(nextLink.childNodes[0]).toHaveAttribute('data-label', 'Next')
38
38
  });
39
39
 
@@ -60,7 +60,7 @@ test('side navigation renders correctly', () => {
60
60
 
61
61
  expect(label).toHaveClass('ds_link');
62
62
  expect(label).toHaveAttribute('for', toggle.id);
63
- expect(label.textContent).toEqual('Show all Pages in this section');
63
+ expect(label?.textContent).toEqual('Show all Pages in this section');
64
64
 
65
65
  expect(rootList).toHaveAttribute('id', 'side-navigation-root');
66
66
 
@@ -37,33 +37,33 @@ test('site header renders correctly (maximal, testing markup structure)', () =>
37
37
  const siteHeaderNavigationMobile = within(siteHeader).getAllByRole('navigation')[0];
38
38
  const siteHeaderNavigationDesktop = within(siteHeader).getAllByRole('navigation')[1];
39
39
  const siteHeaderPhaseBanner = siteHeader.querySelector('.ds_phase-banner');
40
- const siteHeaderSearch = within(siteHeader).getByRole('search').parentNode;
40
+ const siteHeaderSearch = within(siteHeader).getByRole('search').parentElement;
41
41
 
42
42
  expect(siteHeader).toHaveClass('ds_site-header');
43
43
  expect(siteHeaderContentWrapper).toHaveClass('ds_wrapper');
44
44
 
45
- expect(siteHeaderBranding?.parentNode).toEqual(siteHeaderContent);
46
- expect(siteHeaderControls?.parentNode).toEqual(siteHeaderContent);
47
- expect(siteHeaderNavToggle?.parentNode).toEqual(siteHeaderContent);
48
- expect(siteHeaderNavigationMobile.parentNode).toEqual(siteHeaderContent);
49
- expect(siteHeaderSearch?.parentNode).toEqual(siteHeaderContent);
45
+ expect(siteHeaderBranding?.parentElement).toEqual(siteHeaderContent);
46
+ expect(siteHeaderControls?.parentElement).toEqual(siteHeaderContent);
47
+ expect(siteHeaderNavToggle?.parentElement).toEqual(siteHeaderContent);
48
+ expect(siteHeaderNavigationMobile.parentElement).toEqual(siteHeaderContent);
49
+ expect(siteHeaderSearch?.parentElement).toEqual(siteHeaderContent);
50
50
 
51
- expect(siteHeaderBranding?.previousSibling).toBeNull();
52
- expect(siteHeaderControls?.previousSibling).toEqual(siteHeaderBranding);
53
- expect(siteHeaderNavToggle?.previousSibling).toEqual(siteHeaderControls);
54
- expect(siteHeaderNavigationMobile.previousSibling).toEqual(siteHeaderNavToggle);
55
- expect(siteHeaderSearch?.previousSibling).toEqual(siteHeaderNavigationMobile);
51
+ expect(siteHeaderBranding?.previousElementSibling).toBeNull();
52
+ expect(siteHeaderControls?.previousElementSibling).toEqual(siteHeaderBranding);
53
+ expect(siteHeaderNavToggle?.previousElementSibling).toEqual(siteHeaderControls);
54
+ expect(siteHeaderNavigationMobile.previousElementSibling).toEqual(siteHeaderNavToggle);
55
+ expect(siteHeaderSearch?.previousElementSibling).toEqual(siteHeaderNavigationMobile);
56
56
 
57
- expect(siteHeaderNavigationDesktop.parentNode).toHaveClass('ds_wrapper');
58
- expect(siteHeaderNavigationDesktop?.parentNode?.parentNode).toHaveClass('ds_site-header__navigation');
57
+ expect(siteHeaderNavigationDesktop.parentElement).toHaveClass('ds_wrapper');
58
+ expect(siteHeaderNavigationDesktop?.parentElement?.parentElement).toHaveClass('ds_site-header__navigation');
59
59
 
60
- expect(siteHeaderNavigationDesktop?.parentNode?.parentNode?.previousSibling).toEqual(siteHeaderPhaseBanner);
60
+ expect(siteHeaderNavigationDesktop?.parentElement?.parentElement?.previousElementSibling).toEqual(siteHeaderPhaseBanner);
61
61
 
62
- expect(siteHeaderPhaseBanner?.previousSibling).toEqual(siteHeaderContentWrapper);
62
+ expect(siteHeaderPhaseBanner?.previousElementSibling).toEqual(siteHeaderContentWrapper);
63
63
 
64
- expect(siteHeaderPhaseBanner?.parentNode).toEqual(siteHeader);
65
- expect(siteHeaderNavigationDesktop?.parentNode?.parentNode?.parentNode).toEqual(siteHeader);
66
- expect(siteHeaderContentWrapper?.parentNode).toEqual(siteHeader);
64
+ expect(siteHeaderPhaseBanner?.parentElement).toEqual(siteHeader);
65
+ expect(siteHeaderNavigationDesktop?.parentElement?.parentElement?.parentElement).toEqual(siteHeader);
66
+ expect(siteHeaderContentWrapper?.parentElement).toEqual(siteHeader);
67
67
  });
68
68
 
69
69
  test('site header branding: logo only, default URL', () => {
@@ -90,8 +90,8 @@ test('site header branding: logo only, default URL', () => {
90
90
  expect(siteHeaderLogoImg).toHaveAttribute('src', logo.src);
91
91
  expect(siteHeaderLogoImg).toHaveAttribute('alt', logo.alt);
92
92
 
93
- expect(siteHeaderLogoImg.parentNode).toEqual(siteHeaderLogoLink);
94
- expect(siteHeaderLogoLink.parentNode).toEqual(siteHeaderBranding);
93
+ expect(siteHeaderLogoImg.parentElement).toEqual(siteHeaderLogoLink);
94
+ expect(siteHeaderLogoLink.parentElement).toEqual(siteHeaderBranding);
95
95
  });
96
96
 
97
97
  test('site header branding: logo and site title', () => {
@@ -115,8 +115,8 @@ test('site header branding: logo and site title', () => {
115
115
 
116
116
  expect(siteTitle?.tagName).toEqual('DIV');
117
117
  expect(siteTitle?.textContent).toEqual(siteTitleContent);
118
- expect(siteTitle?.parentNode).toEqual(siteHeaderBranding);
119
- expect(siteTitle?.previousSibling).toEqual(siteHeaderLogoLink);
118
+ expect(siteTitle?.parentElement).toEqual(siteHeaderBranding);
119
+ expect(siteTitle?.previousElementSibling).toEqual(siteHeaderLogoLink);
120
120
  });
121
121
 
122
122
  test('site header branding: custom link URL', () => {
@@ -12,27 +12,27 @@ test('site search renders correctly', () => {
12
12
  );
13
13
 
14
14
  const searchForm = screen.getByRole('search');
15
- const searchFormContainer = searchForm.parentNode;
15
+ const searchFormContainer = searchForm.parentElement;
16
16
  const searchLabel = document.querySelector('label');
17
17
  const searchInput = within(searchForm).getByRole('searchbox');
18
- const inputWrapper = searchInput.parentNode;
18
+ const inputWrapper = searchInput.parentElement;
19
19
  const searchButton = within(searchForm).getByRole('button');
20
20
 
21
21
  expect(searchFormContainer).toHaveClass('ds_site-search');
22
- expect(searchFormContainer.tagName).toEqual('DIV');
22
+ expect(searchFormContainer?.tagName).toEqual('DIV');
23
23
  expect(searchFormContainer).not.toHaveAttribute('id', 'site-search-autocomplete');
24
24
 
25
25
  expect(searchForm).toHaveClass('ds_site-search__form');
26
26
  expect(searchForm).toHaveAttribute('method', 'GET');
27
27
  expect(searchForm).toHaveAttribute('action', '/search');
28
28
 
29
- expect(searchLabel.textContent).toEqual(labelText);
29
+ expect(searchLabel?.textContent).toEqual(labelText);
30
30
  expect(searchLabel).toHaveAttribute('for', id);
31
31
  expect(searchLabel).toHaveAttribute('id', `${id}-label`);
32
32
  expect(searchLabel).toHaveClass('ds_label', 'visually-hidden');
33
33
 
34
34
  expect(inputWrapper).toHaveClass('ds_input__wrapper ds_input__wrapper--has-icon');
35
- expect(inputWrapper.tagName).toEqual('DIV');
35
+ expect(inputWrapper?.tagName).toEqual('DIV');
36
36
 
37
37
  expect(searchInput).toHaveClass('ds_input', 'ds_site-search__input');
38
38
  expect(searchInput).toHaveAttribute('id', id);
@@ -113,7 +113,7 @@ test('autocomplete', () => {
113
113
  )
114
114
 
115
115
  const searchForm = screen.getByRole('search');
116
- const searchFormContainer = searchForm.parentNode;
116
+ const searchFormContainer = searchForm.parentElement;
117
117
  const searchInput = within(searchForm).getByRole('searchbox');
118
118
  const autocompleteStatus = within(searchForm).getByRole('status');
119
119
  const suggestionsContainer = document.querySelector('.ds_autocomplete__suggestions');
@@ -134,7 +134,7 @@ test('autocomplete', () => {
134
134
  expect(searchInput).toHaveClass('js-autocomplete-input');
135
135
 
136
136
  expect(suggestionsContainer).toHaveAttribute('id', suggestionsId);
137
- expect(suggestionsContainer.tagName).toEqual('DIV');
137
+ expect(suggestionsContainer?.tagName).toEqual('DIV');
138
138
 
139
139
  expect(suggestionsList).toHaveClass('ds_autocomplete__suggestions-list');
140
140
  expect(suggestionsList).toHaveAttribute('aria-labelledby', `${id}-label`);
@@ -148,7 +148,7 @@ test('passing additional props', () => {
148
148
  );
149
149
 
150
150
  const searchForm = screen.getByRole('search');
151
- const searchFormContainer = searchForm.parentNode;
151
+ const searchFormContainer = searchForm.parentElement;
152
152
  expect(searchFormContainer?.dataset.test).toEqual('foo');
153
153
  });
154
154
 
@@ -158,6 +158,6 @@ test('passing additional CSS classes', () => {
158
158
  );
159
159
 
160
160
  const searchForm = screen.getByRole('search');
161
- const searchFormContainer = searchForm.parentNode;
161
+ const searchFormContainer = searchForm.parentElement;
162
162
  expect(searchFormContainer).toHaveClass('foo', 'ds_site-search');
163
163
  });
@@ -11,12 +11,12 @@ test('skip links renders correctly', () => {
11
11
  );
12
12
 
13
13
  const skipLinksList = screen.getByRole('list');
14
- const skipLinksContainer = skipLinksList.parentNode;
14
+ const skipLinksContainer = skipLinksList.parentElement;
15
15
  const skipLinksListItem = within(skipLinksList).getByRole('listitem');
16
16
  const skipLinksLink = within(skipLinksList).getByRole('link');
17
17
 
18
18
  expect(skipLinksContainer).toHaveClass('ds_skip-links');
19
- expect(skipLinksContainer.tagName).toEqual('DIV');
19
+ expect(skipLinksContainer?.tagName).toEqual('DIV');
20
20
 
21
21
  expect(skipLinksList).toHaveClass('ds_skip-links__list');
22
22
  expect(skipLinksList.tagName).toEqual('UL');
@@ -78,7 +78,7 @@ test('passing additional props', () => {
78
78
  );
79
79
 
80
80
  const skipLinksList = screen.getByRole('list');
81
- const skipLinksContainer = skipLinksList.parentNode;
81
+ const skipLinksContainer = skipLinksList.parentElement;
82
82
 
83
83
  expect(skipLinksContainer?.dataset.test).toEqual('foo');
84
84
  });
@@ -45,8 +45,8 @@ test('summary card renders correctly', () => {
45
45
 
46
46
  const summaryCard = screen.getByTestId('foo');
47
47
  const title = within(summaryCard).getByRole('heading');
48
- const header = title.parentElement;
49
- const content = header?.nextSibling;
48
+ const header = title.parentElement as HTMLElement;
49
+ const content = header?.nextElementSibling as HTMLElement;
50
50
  const actionsList = within(header).getByRole('list')
51
51
 
52
52
  const thisList = within(content).getByRole('list');
@@ -116,7 +116,7 @@ test('summary list item with multiple values', () => {
116
116
  const item = screen.getAllByRole('listitem')[0];
117
117
  const value = item.querySelector('.ds_summary-list__value');
118
118
  const valueList = value?.children[0];
119
- const valueListItems = valueList?.children;
119
+ const valueListItems = valueList?.children as HTMLCollection;
120
120
 
121
121
  expect(valueList).toHaveClass('ds_no-bullets');
122
122
  expect(valueList?.tagName).toEqual('UL');
@@ -143,31 +143,47 @@ test('summary list item with no value', () => {
143
143
  });
144
144
 
145
145
  test('summary list item with multiple actions', () => {
146
+ const title = 'Name';
147
+ const value = 'Jane Smith';
148
+ const actions = [
149
+ {
150
+ title: 'Change',
151
+ href: '#foo'
152
+ },
153
+ {
154
+ title: 'Delete',
155
+ onclick: onClickFn
156
+ }
157
+ ];
158
+
146
159
  render(
147
160
  <Item
148
161
  actions={items[0].actions}
149
- title={items[0].title}
150
- value={items[0].value}
162
+ title={title}
163
+ value={value}
151
164
  />
152
165
  );
153
166
 
154
167
  const item = screen.getAllByRole('listitem')[0];
155
- const actions = item.querySelector('.ds_summary-list__actions');
168
+ const actionsElement = item.querySelector('.ds_summary-list__actions');
156
169
 
157
- expect(actions.children.length).toEqual(items[0].actions.length);
158
- expect(actions.children[0].textContent).toEqual(items[0].actions[0].title);
159
- expect(actions.children[1].textContent).toEqual(items[0].actions[1].title);
170
+ expect(actionsElement?.children.length).toEqual(actions.length);
171
+ expect(actionsElement?.children[0].textContent).toEqual(actions[0].title);
172
+ expect(actionsElement?.children[1].textContent).toEqual(actions[1].title);
160
173
  });
161
174
 
162
175
  test('button action', () => {
163
176
  const describedById = 'q1-name';
177
+ const title = 'Name';
178
+ const href = undefined;
179
+ const onClick = onClickFn;
164
180
 
165
181
  render(
166
182
  <Action
167
183
  describedby={describedById}
168
- href={items[0].actions[1].href}
169
- onclick={items[0].actions[1].onclick}
170
- title={items[0].actions[1].title}
184
+ href={href}
185
+ onclick={onClick}
186
+ title={title}
171
187
  />
172
188
  );
173
189
 
@@ -178,7 +194,7 @@ test('button action', () => {
178
194
  expect(action).toHaveAttribute('type', 'button');
179
195
  expect(action).not.toHaveAttribute('href');
180
196
  expect(action.tagName).toEqual('BUTTON');
181
- expect(action.textContent).toEqual('Delete');
197
+ expect(action.textContent).toEqual(title);
182
198
 
183
199
  fireEvent.click(action);
184
200
 
@@ -187,13 +203,16 @@ test('button action', () => {
187
203
 
188
204
  test('link action', () => {
189
205
  const describedById = 'q1-name';
206
+ const title = 'Name';
207
+ const href = "#foo"
208
+ const onClick = onClickFn;
190
209
 
191
210
  render(
192
211
  <Action
193
212
  describedby={describedById}
194
- href={items[0].actions[0].href}
195
- onclick={items[0].actions[0].onclick}
196
- title={items[0].actions[0].title}
213
+ href={href}
214
+ onclick={onClick}
215
+ title={title}
197
216
  />
198
217
  );
199
218
 
@@ -201,10 +220,10 @@ test('link action', () => {
201
220
 
202
221
  expect(action).toHaveClass('ds_link');
203
222
  expect(action).toHaveAttribute('aria-describedby', describedById);
204
- expect(action).toHaveAttribute('href', items[0].actions[0].href);
223
+ expect(action).toHaveAttribute('href', href);
205
224
  expect(action).not.toHaveAttribute('type');
206
225
  expect(action.tagName).toEqual('A');
207
- expect(action.textContent).toEqual('Change');
226
+ expect(action.textContent).toEqual(title);
208
227
  });
209
228
 
210
229
  test('multiline answer', () => {
@@ -0,0 +1,77 @@
1
+ import { test, expect } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import Table from './table';
4
+
5
+ test('table renders correctly', () => {
6
+ render(
7
+ <Table>
8
+ <caption>Public holidays in 2020</caption>
9
+ <thead>
10
+ <tr>
11
+ <th scope="col">Date</th>
12
+ <th scope="col">Day</th>
13
+ <th scope="col">Holiday</th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <tr>
18
+ <td>10 April</td>
19
+ <td>Friday</td>
20
+ <td>Good Friday</td>
21
+ </tr>
22
+ </tbody>
23
+ </Table>
24
+ );
25
+
26
+ const table = screen.getByRole('table');
27
+
28
+ expect(table).toHaveClass('ds_table');
29
+ expect(table.nodeName).toEqual('TABLE');
30
+ });
31
+
32
+ test('table with smallscreen behaviour', () => {
33
+ const behaviour = 'scrolling';
34
+
35
+ render(
36
+ <Table smallscreen={behaviour}>
37
+ <caption>Public holidays in 2020</caption>
38
+ <thead>
39
+ <tr>
40
+ <th scope="col">Date</th>
41
+ <th scope="col">Day</th>
42
+ <th scope="col">Holiday</th>
43
+ </tr>
44
+ </thead>
45
+ <tbody>
46
+ <tr>
47
+ <td>10 April</td>
48
+ <td>Friday</td>
49
+ <td>Good Friday</td>
50
+ </tr>
51
+ </tbody>
52
+ </Table>
53
+ );
54
+
55
+ const table = screen.getByRole('table');
56
+
57
+ expect(table).toHaveAttribute('data-smallscreen', behaviour);
58
+ expect(table.nodeName).toEqual('TABLE');
59
+ });
60
+
61
+ test('passing additional props', () => {
62
+ render(
63
+ <Table data-test="foo"/>
64
+ );
65
+
66
+ const table = screen.getByRole('table');
67
+ expect(table?.dataset.test).toEqual('foo');
68
+ });
69
+
70
+ test('table with additional CSS class', () => {
71
+ render(
72
+ <Table className="foo"/>
73
+ );
74
+
75
+ const table = screen.getByRole('table');
76
+ expect(table).toHaveClass('foo', 'ds_table');
77
+ });
@@ -0,0 +1,36 @@
1
+ import { useEffect, useRef } from 'react';
2
+ // @ts-ignore
3
+ import DSTable from '@scottish-government/design-system/src/components/table/table';
4
+
5
+ const Table: React.FC<SGDS.Component.Table> = ({
6
+ children,
7
+ className,
8
+ smallscreen,
9
+ ...props
10
+ }) => {
11
+ const ref = useRef(null);
12
+
13
+ useEffect(() => {
14
+ if (ref.current) {
15
+ new DSTable().init();
16
+ }
17
+ }, [ref]);
18
+
19
+ return (
20
+ <table
21
+ className={[
22
+ 'ds_table',
23
+ className
24
+ ].join(' ')}
25
+ data-smallscreen={smallscreen}
26
+ ref={ref}
27
+ {...props}
28
+ >
29
+ {children}
30
+ </table>
31
+ );
32
+ };
33
+
34
+ Table.displayName = 'Table';
35
+
36
+ export default Table;