@scottish-government/designsystem-react 0.3.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.
- package/@types/common/AbstractNotificationBanner.d.ts +17 -0
- package/@types/components/Table.d.ts +8 -0
- package/@types/components/TaskList.d.ts +1 -1
- package/dist/common/abstract-notification-banner.jsx +63 -0
- package/dist/components/accordion/accordion.jsx +2 -3
- package/dist/components/breadcrumbs/breadcrumbs.jsx +2 -2
- package/dist/components/cookie-banner/cookie-banner.jsx +21 -0
- package/dist/components/notification-banner/notification-banner.jsx +7 -34
- package/dist/components/page-metadata/page-metadata.jsx +2 -3
- package/dist/components/table/table.jsx +24 -0
- package/dist/components/task-list/task-list.jsx +6 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/common/abstract-notification-banner.test.tsx +126 -0
- package/src/common/abstract-notification-banner.tsx +87 -0
- package/src/common/conditional-wrapper.test.tsx +1 -1
- package/src/common/screen-reader-text.test.tsx +1 -1
- package/src/common/wrapper-tag.test.tsx +3 -3
- package/src/components/accordion/accordion.test.tsx +40 -40
- package/src/components/accordion/accordion.tsx +4 -2
- package/src/components/aspect-box/aspect-box.test.tsx +7 -7
- package/src/components/breadcrumbs/breadcrumbs.tsx +0 -2
- package/src/components/checkbox/checkbox.test.tsx +8 -8
- package/src/components/confirmation-message/confirmation-message.test.tsx +1 -1
- package/src/components/cookie-banner/cookie-banner.test.tsx +25 -0
- package/src/components/cookie-banner/cookie-banner.tsx +36 -0
- package/src/components/details/details.test.tsx +7 -7
- package/src/components/inset-text/inset-text.test.tsx +1 -1
- package/src/components/notification-banner/notification-banner.test.tsx +13 -73
- package/src/components/notification-banner/notification-banner.tsx +13 -41
- package/src/components/notification-panel/notification-panel.test.tsx +6 -6
- package/src/components/page-header/page-header.test.tsx +2 -2
- package/src/components/page-metadata/page-metadata.test.tsx +12 -12
- package/src/components/page-metadata/page-metadata.tsx +4 -2
- package/src/components/pagination/pagination.test.tsx +28 -30
- package/src/components/phase-banner/phase-banner.test.tsx +8 -8
- package/src/components/question/question.test.tsx +3 -3
- package/src/components/radio-button/radio-button.test.tsx +7 -7
- package/src/components/select/select.test.tsx +9 -9
- package/src/components/sequential-navigation/sequential-navigation.test.tsx +4 -4
- package/src/components/side-navigation/side-navigation.test.tsx +1 -1
- package/src/components/site-header/site-header.test.tsx +22 -22
- package/src/components/site-search/site-search.test.tsx +9 -9
- package/src/components/skip-links/skip-links.test.tsx +3 -3
- package/src/components/summary-card/summary-card.test.tsx +2 -2
- package/src/components/summary-list/summary-list.test.tsx +35 -16
- package/src/components/table/table.test.tsx +77 -0
- package/src/components/table/table.tsx +36 -0
- package/src/components/task-list/task-list.test.tsx +81 -83
- package/src/components/task-list/task-list.tsx +9 -5
- package/src/components/text-input/text-input.test.tsx +6 -6
- package/src/components/textarea/textarea.test.tsx +2 -2
- package/src/components/warning-text/warning-text.test.tsx +1 -1
- package/vitest-setup.ts +1 -1
- 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.
|
|
18
|
-
const textElement = summaryElement.
|
|
17
|
+
const detailsElement = summaryElement.parentElement;
|
|
18
|
+
const textElement = summaryElement.nextElementSibling;
|
|
19
19
|
|
|
20
20
|
expect(detailsElement).toHaveClass('ds_details');
|
|
21
|
-
expect(detailsElement
|
|
21
|
+
expect(detailsElement?.tagName).toEqual('DETAILS');
|
|
22
22
|
expect(summaryElement).toHaveClass('ds_details__summary');
|
|
23
|
-
expect(summaryElement
|
|
23
|
+
expect(summaryElement?.tagName).toEqual('SUMMARY');
|
|
24
24
|
expect(textElement).toHaveClass('ds_details__text');
|
|
25
|
-
expect(textElement
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
<
|
|
26
|
+
<AbstractNotificationBanner
|
|
28
27
|
className={[
|
|
29
|
-
'ds_notification',
|
|
30
28
|
'ds_reversed',
|
|
31
29
|
className
|
|
32
30
|
].join(' ')}
|
|
33
|
-
|
|
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
|
-
|
|
38
|
-
|
|
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.
|
|
17
|
-
const notificationPanel = notificationPanelHeading.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
3
|
-
import 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
|
-
<
|
|
11
|
+
<Metadata.Item name={name}>
|
|
12
12
|
{value}
|
|
13
|
-
</
|
|
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
|
-
<
|
|
33
|
+
<Metadata.Item name={name}>
|
|
34
34
|
{value}
|
|
35
|
-
</
|
|
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
|
-
<
|
|
46
|
+
<Metadata.Item data-test="bar" name="Last updated">
|
|
47
47
|
21/04/2020
|
|
48
|
-
</
|
|
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
|
-
<
|
|
61
|
+
<Metadata.Item className="bar" name="Last updated">
|
|
62
62
|
21/04/2020
|
|
63
|
-
</
|
|
63
|
+
</Metadata.Item>
|
|
64
64
|
</Metadata>
|
|
65
65
|
)
|
|
66
66
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
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.
|
|
93
|
-
const prevIcon = prevLabel.
|
|
94
|
-
const prevItem = prevLink?.
|
|
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.
|
|
97
|
-
const nextIcon = nextLabel.
|
|
98
|
-
const nextItem = nextLink?.
|
|
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.
|
|
102
|
-
const firstPageItem = firstPageLink?.
|
|
101
|
+
const firstPageLink = firstPageLabel.parentElement;
|
|
102
|
+
const firstPageItem = firstPageLink?.parentElement;
|
|
103
103
|
const lastPageLabel = within(paginationList).getByText(totalPages);
|
|
104
|
-
const lastPageLink = lastPageLabel.
|
|
105
|
-
const lastPageItem = lastPageLink?.
|
|
104
|
+
const lastPageLink = lastPageLabel.parentElement;
|
|
105
|
+
const lastPageItem = lastPageLink?.parentElement;
|
|
106
106
|
|
|
107
|
-
const firstPageEllipsisItem = firstPageItem?.
|
|
107
|
+
const firstPageEllipsisItem = firstPageItem?.nextElementSibling;
|
|
108
108
|
const firstPageEllipsis = firstPageEllipsisItem?.children[0];
|
|
109
|
-
const lastPageEllipsisItem = lastPageItem?.
|
|
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?.
|
|
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?.
|
|
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?.
|
|
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?.
|
|
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?.
|
|
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
|
|
173
|
+
expect(firstPageEllipsisItem?.tagName).toEqual('LI');
|
|
174
174
|
expect(firstPageEllipsis).toHaveClass('ds_pagination__link', 'ds_pagination__link--ellipsis');
|
|
175
|
-
expect(firstPageEllipsis
|
|
176
|
-
expect(firstPageEllipsis
|
|
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
|
|
180
|
+
expect(lastPageEllipsisItem?.tagName).toEqual('LI');
|
|
181
181
|
expect(lastPageEllipsis).toHaveClass('ds_pagination__link', 'ds_pagination__link--ellipsis');
|
|
182
|
-
expect(lastPageEllipsis
|
|
183
|
-
expect(lastPageEllipsis
|
|
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
|
|
187
|
+
expect(currentPageLink?.textContent).toEqual(currentPage.toString());
|
|
188
188
|
|
|
189
189
|
// expect one link either side of the current (default padding)
|
|
190
|
-
expect(currentPageItem
|
|
191
|
-
expect(currentPageItem
|
|
190
|
+
expect(currentPageItem?.previousElementSibling?.querySelector('a')).toHaveAttribute('aria-label', 'Page 9');
|
|
191
|
+
expect(currentPageItem?.previousElementSibling?.previousElementSibling?.querySelector('a')).toBeNull();
|
|
192
192
|
|
|
193
|
-
expect(currentPageItem
|
|
194
|
-
expect(currentPageItem
|
|
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?.
|
|
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
|
|
24
|
-
expect(phaseBannerContent
|
|
25
|
-
expect(phaseBannerText
|
|
26
|
-
expect(phaseBannerText
|
|
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
|
|
53
|
+
expect(phaseBannerTag?.tagName).toEqual('SPAN');
|
|
54
54
|
expect(phaseBannerTag).toHaveClass('ds_tag', 'ds_phase-banner__tag');
|
|
55
|
-
expect(phaseBannerTag
|
|
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
|
|
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
|
|
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
|
|