@madie/madie-design-system 1.2.62 → 2.0.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/.eslintrc.js +1 -1
- package/.storybook/.babelrc +2 -1
- package/.storybook/main.js +3 -11
- package/components/AutoComplete/AutoComplete.jsx +1 -1
- package/components/Button/Button.stories.js +0 -2
- package/components/DateField/DateField.jsx +1 -1
- package/components/DateField/DateField.stories.jsx +23 -10
- package/components/DateTimeField/DateTimeField.jsx +6 -2
- package/components/DateTimeField/DateTimeField.stories.jsx +29 -19
- package/components/Instant/Instant.stories.js +14 -6
- package/components/MadieAlert/MadieAlert.stories.js +35 -29
- package/components/MadieAlert/index.jsx +5 -5
- package/components/MadieConfirmDialog/MadieConfirmDialog.stories.js +17 -27
- package/components/MadieDeleteDialog/MadieDeleteDialog.stories.js +9 -18
- package/components/MadieDialog/MadieDialog.stories.js +45 -116
- package/components/MadieDialog/index.jsx +4 -2
- package/components/MadieDiscardDialog/MadieDiscardDialog.stories.js +5 -7
- package/components/MadieSpinner/MadieSpinner.stories.js +1 -3
- package/components/MadieTooltip/MadieTooltip.stories.js +7 -2
- package/components/Modal/Modal.stories.js +18 -89
- package/components/NotificationBanner/NotificationBanner.stories.js +17 -11
- package/components/NotificationBanner/index.js +3 -3
- package/components/NumberInput/NumberInput.stories.js +51 -63
- package/components/Popover/Popover.stories.js +6 -14
- package/components/Popover/index.js +2 -2
- package/components/RadioButton/RadioButton.jsx +4 -2
- package/components/RadioButton/RadioButton.stories.jsx +6 -2
- package/components/ReadOnlyTextField/ReadOnlyTextField.stories.js +4 -3
- package/components/ReadOnlyTextField/index.jsx +1 -1
- package/components/RichTextEditor/RichTextEditor.stories.js +10 -8
- package/components/RichTextEditor/index.jsx +14 -15
- package/components/Search/Search.stories.js +2 -4
- package/components/Select/Select.stories.js +59 -160
- package/components/Select/index.jsx +1 -1
- package/components/Tabs/Tabs.stories.js +78 -210
- package/components/TextArea/TextArea.stories.js +88 -108
- package/components/TextArea/index.jsx +1 -1
- package/components/TextField/TextField.stories.js +101 -124
- package/components/TextField/index.jsx +1 -1
- package/components/TimeField/TimeField.stories.js +18 -8
- package/components/Toast/Toast.stories.js +42 -102
- package/components/TruncateText/TruncateText.stories.js +22 -17
- package/components/hooks/useGetConfig.js +2 -2
- package/components/index.js +0 -24
- package/dist/browser.js +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.js +182 -51
- package/dist/react/index.js.LICENSE.txt +27 -24
- package/dist/react/index.js.map +1 -1
- package/eslint.config.js +56 -0
- package/index.js +7 -9
- package/package.json +43 -75
- package/test/components/Accordion.test.js +1 -1
- package/test/components/AutoComplete.test.js +11 -6
- package/test/components/Button.test.js +7 -3
- package/test/components/DateField.test.js +25 -29
- package/test/components/DateTimeField.test.js +21 -25
- package/test/components/Instant.test.js +1 -1
- package/test/components/MadieAlert.test.js +22 -22
- package/test/components/MadieConfirmDialog.test.js +42 -64
- package/test/components/MadieDeleteDialog.test.js +51 -69
- package/test/components/MadieDialog.test.js +13 -13
- package/test/components/MadieDiscardDialog.test.js +28 -45
- package/test/components/MadieSpinner.test.js +12 -17
- package/test/components/Modal.test.js +115 -0
- package/test/components/Pagination.test.js +2 -2
- package/test/components/RadioButton.test.js +7 -7
- package/test/components/ReadOnlyTextField.test.js +4 -2
- package/test/components/RichTextEditor.test.js +90 -6
- package/test/components/Search.test.js +75 -0
- package/test/components/Select.test.js +97 -107
- package/test/components/Tabs.test.js +22 -24
- package/test/components/TextArea.test.js +78 -92
- package/test/components/TextField.test.js +128 -147
- package/test/components/Toast.test.js +67 -78
- package/test/components/TruncateText.test.js +75 -0
- package/test/components/index.test.js +23 -0
- package/webpack.config.js +0 -1
- package/.eslintignore +0 -5
- package/components/Alert/Alert.stories.js +0 -70
- package/components/Alert/index.js +0 -55
- package/components/Breadcrumb/Breadcrumb.md +0 -28
- package/components/Breadcrumb/Breadcrumb.stories.js +0 -76
- package/components/Breadcrumb/index.js +0 -92
- package/components/CalloutBox/CalloutBox.stories.js +0 -94
- package/components/CalloutBox/index.js +0 -109
- package/components/Card/Card.stories.js +0 -163
- package/components/Card/index.js +0 -144
- package/components/Dropdown/Dropdown.stories.js +0 -94
- package/components/Dropdown/index.js +0 -85
- package/components/Error/Collapsible.jsx +0 -93
- package/components/Error/ErrorUI.jsx +0 -31
- package/components/Error/error.js +0 -26
- package/components/FlashNotification/FlashNotificationUI.jsx +0 -91
- package/components/FlashNotification/index.js +0 -30
- package/components/Footer/Footer.stories.js +0 -20
- package/components/Footer/FooterUI.jsx +0 -137
- package/components/Footer/LegacyFooterUI.jsx +0 -204
- package/components/Footer/SocialLinks.jsx +0 -63
- package/components/Footer/Subscribe.jsx +0 -34
- package/components/Footer/footer.js +0 -30
- package/components/Infotip/Infotip.jsx +0 -75
- package/components/Infotip/Infotip.stories.js +0 -52
- package/components/Infotip/InfotipIcon.jsx +0 -41
- package/components/Infotip/index.js +0 -3
- package/components/Link/Link.stories.js +0 -82
- package/components/Link/index.js +0 -61
- package/components/Spinner/index.js +0 -9
- package/components/TextInput/TextInput.stories.js +0 -118
- package/components/TextInput/index.js +0 -137
- package/components/Tooltip/Tooltip.jsx +0 -88
- package/components/Tooltip/Tooltip.stories.js +0 -80
- package/components/Tooltip/index.js +0 -3
- package/components/Tooltip/position.js +0 -76
- package/test/components/ErrorUI.test.js +0 -32
- package/test/components/FooterUI.test.js +0 -122
- package/test/components/Infotip.test.js +0 -76
- package/test/components/Tooltip.test.js +0 -147
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import "@testing-library/jest-dom";
|
|
2
2
|
import { describe, expect, test } from "@jest/globals";
|
|
3
3
|
import MadieDiscardDialog from "../../components/MadieDiscardDialog/index";
|
|
4
|
-
import {
|
|
5
|
-
import { render, fireEvent, waitFor } from "@testing-library/react";
|
|
4
|
+
import { render, fireEvent, waitFor, screen } from "@testing-library/react";
|
|
6
5
|
|
|
7
6
|
import React, { useState } from "react";
|
|
8
7
|
|
|
@@ -26,57 +25,41 @@ const DialogTester = () => {
|
|
|
26
25
|
};
|
|
27
26
|
|
|
28
27
|
describe("MadieDiscardDialog", () => {
|
|
28
|
+
const { findByTestId, getByTestId, queryByText } = screen;
|
|
29
|
+
|
|
29
30
|
test("Dialog renders", async () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
expect(discardDialog).toBeInTheDocument();
|
|
38
|
-
await waitFor(() => {
|
|
39
|
-
expect(queryByText("You have unsaved changes.")).toBeVisible();
|
|
40
|
-
});
|
|
31
|
+
render(<DialogTester />);
|
|
32
|
+
const result = await findByTestId("dialog-tester");
|
|
33
|
+
fireEvent.click(result);
|
|
34
|
+
const discardDialog = await getByTestId("discard-dialog");
|
|
35
|
+
expect(discardDialog).toBeInTheDocument();
|
|
36
|
+
await waitFor(() => {
|
|
37
|
+
expect(queryByText("You have unsaved changes.")).toBeVisible();
|
|
41
38
|
});
|
|
42
39
|
});
|
|
43
40
|
|
|
44
41
|
test("Dialog disappears onContinue", async () => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
expect(
|
|
55
|
-
fireEvent.click(continueButton);
|
|
56
|
-
await waitFor(() => {
|
|
57
|
-
expect(
|
|
58
|
-
queryByText("You have unsaved changes.")
|
|
59
|
-
).not.toBeVisible();
|
|
60
|
-
});
|
|
42
|
+
render(<DialogTester />);
|
|
43
|
+
const result = await findByTestId("dialog-tester");
|
|
44
|
+
fireEvent.click(result);
|
|
45
|
+
const continueButton = await getByTestId(
|
|
46
|
+
"discard-dialog-continue-button",
|
|
47
|
+
);
|
|
48
|
+
expect(continueButton).toBeInTheDocument();
|
|
49
|
+
fireEvent.click(continueButton);
|
|
50
|
+
await waitFor(() => {
|
|
51
|
+
expect(queryByText("You have unsaved changes.")).not.toBeVisible();
|
|
61
52
|
});
|
|
62
53
|
});
|
|
63
54
|
test("Dialog disappears onClose", async () => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
);
|
|
73
|
-
expect(cancelButton).toBeInTheDocument();
|
|
74
|
-
fireEvent.click(cancelButton);
|
|
75
|
-
await waitFor(() => {
|
|
76
|
-
expect(
|
|
77
|
-
queryByText("You have unsaved changes.")
|
|
78
|
-
).not.toBeVisible();
|
|
79
|
-
});
|
|
55
|
+
render(<DialogTester />);
|
|
56
|
+
const result = await findByTestId("dialog-tester");
|
|
57
|
+
fireEvent.click(result);
|
|
58
|
+
const cancelButton = await getByTestId("discard-dialog-cancel-button");
|
|
59
|
+
expect(cancelButton).toBeInTheDocument();
|
|
60
|
+
fireEvent.click(cancelButton);
|
|
61
|
+
await waitFor(() => {
|
|
62
|
+
expect(queryByText("You have unsaved changes.")).not.toBeVisible();
|
|
80
63
|
});
|
|
81
64
|
});
|
|
82
65
|
});
|
|
@@ -2,28 +2,23 @@ import "@testing-library/jest-dom";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { describe, expect, test } from "@jest/globals";
|
|
4
4
|
import { act } from "react-dom/test-utils";
|
|
5
|
-
import { render } from "@testing-library/react";
|
|
5
|
+
import { render, screen } from "@testing-library/react";
|
|
6
6
|
import MadieSpinner from "../../components/MadieSpinner";
|
|
7
7
|
|
|
8
8
|
describe("MadieSpinner", () => {
|
|
9
|
+
const { findByTestId } = screen;
|
|
9
10
|
test("MadieSpinner exists and renders", async () => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
expect(await findByTestId("test-spinner")).toBeInTheDocument();
|
|
19
|
-
});
|
|
11
|
+
render(
|
|
12
|
+
<MadieSpinner
|
|
13
|
+
data-testid="test-spinner"
|
|
14
|
+
thickness={8}
|
|
15
|
+
style={{ height: 50, width: 50 }}
|
|
16
|
+
/>,
|
|
17
|
+
);
|
|
18
|
+
expect(await findByTestId("test-spinner")).toBeInTheDocument();
|
|
20
19
|
});
|
|
21
20
|
test("MadieSpinner renders with no props", async () => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
<MadieSpinner data-testid="test-spinner" />
|
|
25
|
-
);
|
|
26
|
-
expect(await findByTestId("test-spinner")).toBeInTheDocument();
|
|
27
|
-
});
|
|
21
|
+
render(<MadieSpinner data-testid="test-spinner" />);
|
|
22
|
+
expect(await findByTestId("test-spinner")).toBeInTheDocument();
|
|
28
23
|
});
|
|
29
24
|
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
|
3
|
+
import Modal from "../../components/Modal/index.jsx";
|
|
4
|
+
|
|
5
|
+
jest.mock("../../lib/SvgComponents.jsx", () => ({
|
|
6
|
+
CloseXIcon2: () => <span data-testid="close-icon">X</span>,
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
describe("Modal", () => {
|
|
10
|
+
const defaultProps = {
|
|
11
|
+
title: "Test Modal",
|
|
12
|
+
children: <div>Modal content</div>,
|
|
13
|
+
isOpen: true,
|
|
14
|
+
onRequestClose: jest.fn(),
|
|
15
|
+
appElement: "body",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
jest.clearAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("Does not catch fire", async () => {
|
|
23
|
+
render(<Modal {...defaultProps} />);
|
|
24
|
+
expect(screen.getByText("Test Modal")).toBeInTheDocument();
|
|
25
|
+
expect(screen.getByText("Modal content")).toBeInTheDocument();
|
|
26
|
+
expect(screen.getByTestId("modal-close-btn")).toBeInTheDocument();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("calls onclose when button click", () => {
|
|
30
|
+
render(<Modal {...defaultProps} />);
|
|
31
|
+
fireEvent.click(screen.getByTestId("modal-close-btn"));
|
|
32
|
+
expect(defaultProps.onRequestClose).toHaveBeenCalled();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("renders buttons", () => {
|
|
36
|
+
const primary = {
|
|
37
|
+
title: "Primary",
|
|
38
|
+
onClick: jest.fn(),
|
|
39
|
+
};
|
|
40
|
+
const secondary = {
|
|
41
|
+
title: "Secondary",
|
|
42
|
+
onClick: jest.fn(),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
render(
|
|
46
|
+
<Modal {...defaultProps} primary={primary} secondary={secondary} />,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const primaryBtn = screen.getByTestId("modal-primary-btn");
|
|
50
|
+
const secondaryBtn = screen.getByTestId("modal-secondary-btn");
|
|
51
|
+
|
|
52
|
+
expect(primaryBtn).toBeInTheDocument();
|
|
53
|
+
expect(primaryBtn).toHaveTextContent("Primary");
|
|
54
|
+
|
|
55
|
+
expect(secondaryBtn).toBeInTheDocument();
|
|
56
|
+
expect(secondaryBtn).toHaveTextContent("Secondary");
|
|
57
|
+
|
|
58
|
+
fireEvent.click(primaryBtn);
|
|
59
|
+
fireEvent.click(secondaryBtn);
|
|
60
|
+
|
|
61
|
+
expect(primary.onClick).toHaveBeenCalled();
|
|
62
|
+
expect(secondary.onClick).toHaveBeenCalled();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("falls back to onRequestClose when no onClick", () => {
|
|
66
|
+
render(<Modal {...defaultProps} secondary={{ title: "Cancel" }} />);
|
|
67
|
+
fireEvent.click(screen.getByTestId("modal-secondary-btn"));
|
|
68
|
+
expect(defaultProps.onRequestClose).toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("renders with custom width when provided", () => {
|
|
72
|
+
render(<Modal {...defaultProps} width="500px" />);
|
|
73
|
+
const modalContent = document.querySelector(".qpp-c-modal__content");
|
|
74
|
+
expect(modalContent).toHaveStyle("width: 500px");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("sets focus on close button after open", async () => {
|
|
78
|
+
render(<Modal {...defaultProps} />);
|
|
79
|
+
await waitFor(() => {
|
|
80
|
+
expect(document.activeElement).toBe(
|
|
81
|
+
screen.getByTestId("modal-close-btn"),
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("sets overflowSeparator to true when content overflows", async () => {
|
|
87
|
+
Object.defineProperty(HTMLElement.prototype, "scrollHeight", {
|
|
88
|
+
configurable: true,
|
|
89
|
+
get: () => 2000,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
Object.defineProperty(document.documentElement, "clientHeight", {
|
|
93
|
+
configurable: true,
|
|
94
|
+
get: () => 1000,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
render(
|
|
98
|
+
<Modal
|
|
99
|
+
isOpen={true}
|
|
100
|
+
onRequestClose={jest.fn()}
|
|
101
|
+
title="Test Modal"
|
|
102
|
+
appElement="body"
|
|
103
|
+
>
|
|
104
|
+
<div>Overflow content</div>
|
|
105
|
+
</Modal>,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
await waitFor(() => {
|
|
109
|
+
const header = screen
|
|
110
|
+
.getByText("Test Modal")
|
|
111
|
+
.closest(".qpp-c-modal__header");
|
|
112
|
+
expect(header).toHaveClass("qpp-c-modal__header-sep");
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -28,7 +28,7 @@ describe("Pagination", () => {
|
|
|
28
28
|
}}
|
|
29
29
|
hidePrevButton={true}
|
|
30
30
|
hideNextButton={false}
|
|
31
|
-
|
|
31
|
+
/>,
|
|
32
32
|
);
|
|
33
33
|
expect(getByTestId("NavigateNextIcon")).toBeInTheDocument();
|
|
34
34
|
});
|
|
@@ -52,7 +52,7 @@ describe("Pagination", () => {
|
|
|
52
52
|
}}
|
|
53
53
|
hidePrevButton={false}
|
|
54
54
|
hideNextButton={true}
|
|
55
|
-
|
|
55
|
+
/>,
|
|
56
56
|
);
|
|
57
57
|
expect(getByTestId("NavigateBeforeIcon")).toBeInTheDocument();
|
|
58
58
|
});
|
|
@@ -5,7 +5,7 @@ import userEvent from "@testing-library/user-event";
|
|
|
5
5
|
import RadioButton from "../../components/RadioButton/RadioButton";
|
|
6
6
|
|
|
7
7
|
describe("RadioButton Component", () => {
|
|
8
|
-
it("renders RadioButton with options and allows selection", () => {
|
|
8
|
+
it("renders RadioButton with options and allows selection", async () => {
|
|
9
9
|
const mockOnChange = jest.fn();
|
|
10
10
|
const options = [
|
|
11
11
|
{ value: "option1", label: "Option 1" },
|
|
@@ -19,7 +19,7 @@ describe("RadioButton Component", () => {
|
|
|
19
19
|
label="Radio Button"
|
|
20
20
|
options={options}
|
|
21
21
|
onChange={mockOnChange}
|
|
22
|
-
|
|
22
|
+
/>,
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
const option1 = screen.getByLabelText("Option 1");
|
|
@@ -28,7 +28,7 @@ describe("RadioButton Component", () => {
|
|
|
28
28
|
expect(option1).toBeInTheDocument();
|
|
29
29
|
expect(option2).toBeInTheDocument();
|
|
30
30
|
|
|
31
|
-
userEvent.click(option1);
|
|
31
|
+
await userEvent.click(option1);
|
|
32
32
|
expect(option1).toBeChecked();
|
|
33
33
|
expect(mockOnChange).toHaveBeenCalled();
|
|
34
34
|
});
|
|
@@ -47,7 +47,7 @@ describe("RadioButton Component", () => {
|
|
|
47
47
|
options={options}
|
|
48
48
|
value="option1"
|
|
49
49
|
disabled
|
|
50
|
-
|
|
50
|
+
/>,
|
|
51
51
|
);
|
|
52
52
|
|
|
53
53
|
const option1 = screen.getByRole("textbox");
|
|
@@ -62,7 +62,7 @@ describe("RadioButton Component", () => {
|
|
|
62
62
|
dataTestId="radio-button-helper"
|
|
63
63
|
label="Radio Button"
|
|
64
64
|
helperText="Helper text goes here"
|
|
65
|
-
|
|
65
|
+
/>,
|
|
66
66
|
);
|
|
67
67
|
|
|
68
68
|
const helperText = screen.getByText("Helper text goes here");
|
|
@@ -77,7 +77,7 @@ describe("RadioButton Component", () => {
|
|
|
77
77
|
label="Radio Button"
|
|
78
78
|
error
|
|
79
79
|
helperText="This field is required"
|
|
80
|
-
|
|
80
|
+
/>,
|
|
81
81
|
);
|
|
82
82
|
|
|
83
83
|
const errorText = screen.getByText("This field is required");
|
|
@@ -98,7 +98,7 @@ describe("RadioButton Component", () => {
|
|
|
98
98
|
label="Radio Button"
|
|
99
99
|
options={options}
|
|
100
100
|
disabled
|
|
101
|
-
|
|
101
|
+
/>,
|
|
102
102
|
);
|
|
103
103
|
|
|
104
104
|
const readOnlyField = screen.getByRole("textbox");
|
|
@@ -14,9 +14,11 @@ describe("ReadOnlyTextField", () => {
|
|
|
14
14
|
id="testName"
|
|
15
15
|
inputProps={{ "data-testid": "test-name-input" }}
|
|
16
16
|
size="small"
|
|
17
|
-
|
|
17
|
+
/>,
|
|
18
18
|
);
|
|
19
|
-
const textNode = getByRole(document.body, "textbox", {
|
|
19
|
+
const textNode = getByRole(document.body, "textbox", {
|
|
20
|
+
name: "test Name",
|
|
21
|
+
});
|
|
20
22
|
expect(textNode).toBeInTheDocument();
|
|
21
23
|
expect(textNode).toHaveAttribute("readOnly");
|
|
22
24
|
expect(textNode).toHaveTextContent("-");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {render, screen, fireEvent, waitFor} from "@testing-library/react";
|
|
2
|
+
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
|
3
3
|
import RichTextEditor from "../../components/RichTextEditor/index";
|
|
4
|
+
import userEvent from "@testing-library/user-event";
|
|
4
5
|
|
|
5
6
|
describe("RichTextEditor Component", () => {
|
|
6
7
|
const mockOnChange = jest.fn();
|
|
@@ -13,14 +14,16 @@ describe("RichTextEditor Component", () => {
|
|
|
13
14
|
content="<p>Initial Content</p>"
|
|
14
15
|
onChange={mockOnChange}
|
|
15
16
|
disabled={false}
|
|
16
|
-
|
|
17
|
+
/>,
|
|
17
18
|
);
|
|
18
19
|
|
|
19
20
|
// Check if the label is rendered
|
|
20
21
|
expect(screen.getByText("Test Label")).toBeInTheDocument();
|
|
21
22
|
|
|
22
23
|
// Check if the editor content is rendered
|
|
23
|
-
expect(
|
|
24
|
+
expect(
|
|
25
|
+
screen.getByTestId("test-label-rich-text-editor"),
|
|
26
|
+
).toBeInTheDocument();
|
|
24
27
|
});
|
|
25
28
|
|
|
26
29
|
it("calls onChange when content is updated", async () => {
|
|
@@ -31,12 +34,14 @@ describe("RichTextEditor Component", () => {
|
|
|
31
34
|
content="Initial Content"
|
|
32
35
|
onChange={mockOnChange}
|
|
33
36
|
disabled={false}
|
|
34
|
-
|
|
37
|
+
/>,
|
|
35
38
|
);
|
|
36
39
|
|
|
37
40
|
// Simulate content change
|
|
38
41
|
const editorContent = screen.getByRole("textbox");
|
|
39
|
-
fireEvent.input(editorContent, {
|
|
42
|
+
fireEvent.input(editorContent, {
|
|
43
|
+
target: { innerHTML: "Updated Content" },
|
|
44
|
+
});
|
|
40
45
|
|
|
41
46
|
// Check if onChange is called
|
|
42
47
|
await waitFor(() => {
|
|
@@ -52,11 +57,90 @@ describe("RichTextEditor Component", () => {
|
|
|
52
57
|
content="<script>alert('XSS')</script><p>Safe Content</p>"
|
|
53
58
|
onChange={mockOnChange}
|
|
54
59
|
disabled={true}
|
|
55
|
-
|
|
60
|
+
/>,
|
|
56
61
|
);
|
|
57
62
|
|
|
58
63
|
// Check if sanitized content is rendered
|
|
59
64
|
expect(screen.getByText("Safe Content")).toBeInTheDocument();
|
|
60
65
|
expect(screen.queryByText("alert('XSS')")).not.toBeInTheDocument();
|
|
61
66
|
});
|
|
67
|
+
|
|
68
|
+
it("triggers bold", async () => {
|
|
69
|
+
const user = userEvent.setup();
|
|
70
|
+
render(
|
|
71
|
+
<RichTextEditor
|
|
72
|
+
id="test-editor"
|
|
73
|
+
label="Test Editor"
|
|
74
|
+
onChange={mockOnChange}
|
|
75
|
+
content="<p>Initial content</p>"
|
|
76
|
+
/>,
|
|
77
|
+
);
|
|
78
|
+
await user.click(screen.getByRole("button", { name: "Bold" }));
|
|
79
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
80
|
+
});
|
|
81
|
+
it("triggers Italic", async () => {
|
|
82
|
+
const user = userEvent.setup();
|
|
83
|
+
render(
|
|
84
|
+
<RichTextEditor
|
|
85
|
+
id="test-editor"
|
|
86
|
+
label="Test Editor"
|
|
87
|
+
onChange={mockOnChange}
|
|
88
|
+
content="<p>Initial content</p>"
|
|
89
|
+
/>,
|
|
90
|
+
);
|
|
91
|
+
await user.click(screen.getByRole("button", { name: "Italic" }));
|
|
92
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
it("triggers Underline", async () => {
|
|
95
|
+
const user = userEvent.setup();
|
|
96
|
+
render(
|
|
97
|
+
<RichTextEditor
|
|
98
|
+
id="test-editor"
|
|
99
|
+
label="Test Editor"
|
|
100
|
+
onChange={mockOnChange}
|
|
101
|
+
content="<p>Initial content</p>"
|
|
102
|
+
/>,
|
|
103
|
+
);
|
|
104
|
+
await user.click(screen.getByRole("button", { name: "Underline" }));
|
|
105
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
106
|
+
});
|
|
107
|
+
it("triggers Ordered List", async () => {
|
|
108
|
+
const user = userEvent.setup();
|
|
109
|
+
render(
|
|
110
|
+
<RichTextEditor
|
|
111
|
+
id="test-editor"
|
|
112
|
+
label="Test Editor"
|
|
113
|
+
onChange={mockOnChange}
|
|
114
|
+
content="<p>Initial content</p>"
|
|
115
|
+
/>,
|
|
116
|
+
);
|
|
117
|
+
await user.click(screen.getByRole("button", { name: "Bold" }));
|
|
118
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
119
|
+
});
|
|
120
|
+
it("triggers Bulleted List", async () => {
|
|
121
|
+
const user = userEvent.setup();
|
|
122
|
+
render(
|
|
123
|
+
<RichTextEditor
|
|
124
|
+
id="test-editor"
|
|
125
|
+
label="Test Editor"
|
|
126
|
+
onChange={mockOnChange}
|
|
127
|
+
content="<p>Initial content</p>"
|
|
128
|
+
/>,
|
|
129
|
+
);
|
|
130
|
+
await user.click(screen.getByRole("button", { name: "Bulleted List" }));
|
|
131
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
132
|
+
});
|
|
133
|
+
it("triggers Table", async () => {
|
|
134
|
+
const user = userEvent.setup();
|
|
135
|
+
render(
|
|
136
|
+
<RichTextEditor
|
|
137
|
+
id="test-editor"
|
|
138
|
+
label="Test Editor"
|
|
139
|
+
onChange={mockOnChange}
|
|
140
|
+
content="<p>Initial content</p>"
|
|
141
|
+
/>,
|
|
142
|
+
);
|
|
143
|
+
await user.click(screen.getByRole("button", { name: "Table" }));
|
|
144
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
145
|
+
});
|
|
62
146
|
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen, fireEvent } from "@testing-library/react";
|
|
3
|
+
import { Search } from "../../components";
|
|
4
|
+
|
|
5
|
+
describe("Search Component", () => {
|
|
6
|
+
const defaultProps = {
|
|
7
|
+
id: "test-search",
|
|
8
|
+
name: "search",
|
|
9
|
+
placeholder: "Search something...",
|
|
10
|
+
inputValue: "initial",
|
|
11
|
+
inputAriaLabel: "Search field",
|
|
12
|
+
buttonAriaLabel: "Search button",
|
|
13
|
+
inputWidth: "300px",
|
|
14
|
+
onChange: jest.fn(),
|
|
15
|
+
onClick: jest.fn(),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
jest.clearAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("Does not catch fire", () => {
|
|
23
|
+
render(<Search {...defaultProps} />);
|
|
24
|
+
|
|
25
|
+
const input = screen.getByRole("searchbox");
|
|
26
|
+
expect(input).toHaveAttribute("id", "test-search");
|
|
27
|
+
expect(input).toHaveAttribute("name", "search");
|
|
28
|
+
expect(input).toHaveAttribute("placeholder", "Search something...");
|
|
29
|
+
expect(input).toHaveValue("initial");
|
|
30
|
+
expect(input).toHaveStyle("width: 300px");
|
|
31
|
+
expect(input).toHaveAttribute("aria-label", "Search field");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("calls onChange", () => {
|
|
35
|
+
render(<Search {...defaultProps} />);
|
|
36
|
+
const input = screen.getByRole("searchbox");
|
|
37
|
+
|
|
38
|
+
fireEvent.change(input, { target: { value: "new" } });
|
|
39
|
+
expect(defaultProps.onChange).toHaveBeenCalled();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("renders the button and trigger onClick", () => {
|
|
43
|
+
render(<Search {...defaultProps} />);
|
|
44
|
+
const button = screen.getByTestId("search-btn");
|
|
45
|
+
|
|
46
|
+
expect(button).toHaveAttribute("aria-label", "Search button");
|
|
47
|
+
fireEvent.click(button);
|
|
48
|
+
expect(defaultProps.onClick).toHaveBeenCalled();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("disables input and button when props set", () => {
|
|
52
|
+
render(
|
|
53
|
+
<Search
|
|
54
|
+
{...defaultProps}
|
|
55
|
+
disabled={true}
|
|
56
|
+
disableSearchBtn={true}
|
|
57
|
+
/>,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
expect(screen.getByRole("searchbox")).toBeDisabled();
|
|
61
|
+
expect(screen.getByTestId("search-btn")).toBeDisabled();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("uses default props when none are provided", () => {
|
|
65
|
+
render(<Search />);
|
|
66
|
+
expect(screen.getByRole("searchbox")).toHaveAttribute(
|
|
67
|
+
"id",
|
|
68
|
+
"search-input",
|
|
69
|
+
);
|
|
70
|
+
expect(screen.getByTestId("search-btn")).toHaveAttribute(
|
|
71
|
+
"id",
|
|
72
|
+
"search-input-submit",
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
});
|