@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.
Files changed (118) hide show
  1. package/.eslintrc.js +1 -1
  2. package/.storybook/.babelrc +2 -1
  3. package/.storybook/main.js +3 -11
  4. package/components/AutoComplete/AutoComplete.jsx +1 -1
  5. package/components/Button/Button.stories.js +0 -2
  6. package/components/DateField/DateField.jsx +1 -1
  7. package/components/DateField/DateField.stories.jsx +23 -10
  8. package/components/DateTimeField/DateTimeField.jsx +6 -2
  9. package/components/DateTimeField/DateTimeField.stories.jsx +29 -19
  10. package/components/Instant/Instant.stories.js +14 -6
  11. package/components/MadieAlert/MadieAlert.stories.js +35 -29
  12. package/components/MadieAlert/index.jsx +5 -5
  13. package/components/MadieConfirmDialog/MadieConfirmDialog.stories.js +17 -27
  14. package/components/MadieDeleteDialog/MadieDeleteDialog.stories.js +9 -18
  15. package/components/MadieDialog/MadieDialog.stories.js +45 -116
  16. package/components/MadieDialog/index.jsx +4 -2
  17. package/components/MadieDiscardDialog/MadieDiscardDialog.stories.js +5 -7
  18. package/components/MadieSpinner/MadieSpinner.stories.js +1 -3
  19. package/components/MadieTooltip/MadieTooltip.stories.js +7 -2
  20. package/components/Modal/Modal.stories.js +18 -89
  21. package/components/NotificationBanner/NotificationBanner.stories.js +17 -11
  22. package/components/NotificationBanner/index.js +3 -3
  23. package/components/NumberInput/NumberInput.stories.js +51 -63
  24. package/components/Popover/Popover.stories.js +6 -14
  25. package/components/Popover/index.js +2 -2
  26. package/components/RadioButton/RadioButton.jsx +4 -2
  27. package/components/RadioButton/RadioButton.stories.jsx +6 -2
  28. package/components/ReadOnlyTextField/ReadOnlyTextField.stories.js +4 -3
  29. package/components/ReadOnlyTextField/index.jsx +1 -1
  30. package/components/RichTextEditor/RichTextEditor.stories.js +10 -8
  31. package/components/RichTextEditor/index.jsx +14 -15
  32. package/components/Search/Search.stories.js +2 -4
  33. package/components/Select/Select.stories.js +59 -160
  34. package/components/Select/index.jsx +1 -1
  35. package/components/Tabs/Tabs.stories.js +78 -210
  36. package/components/TextArea/TextArea.stories.js +88 -108
  37. package/components/TextArea/index.jsx +1 -1
  38. package/components/TextField/TextField.stories.js +101 -124
  39. package/components/TextField/index.jsx +1 -1
  40. package/components/TimeField/TimeField.stories.js +18 -8
  41. package/components/Toast/Toast.stories.js +42 -102
  42. package/components/TruncateText/TruncateText.stories.js +22 -17
  43. package/components/hooks/useGetConfig.js +2 -2
  44. package/components/index.js +0 -24
  45. package/dist/browser.js +1 -1
  46. package/dist/index.js +1 -1
  47. package/dist/react/index.js +182 -51
  48. package/dist/react/index.js.LICENSE.txt +27 -24
  49. package/dist/react/index.js.map +1 -1
  50. package/eslint.config.js +56 -0
  51. package/index.js +7 -9
  52. package/package.json +43 -75
  53. package/test/components/Accordion.test.js +1 -1
  54. package/test/components/AutoComplete.test.js +11 -6
  55. package/test/components/Button.test.js +7 -3
  56. package/test/components/DateField.test.js +25 -29
  57. package/test/components/DateTimeField.test.js +21 -25
  58. package/test/components/Instant.test.js +1 -1
  59. package/test/components/MadieAlert.test.js +22 -22
  60. package/test/components/MadieConfirmDialog.test.js +42 -64
  61. package/test/components/MadieDeleteDialog.test.js +51 -69
  62. package/test/components/MadieDialog.test.js +13 -13
  63. package/test/components/MadieDiscardDialog.test.js +28 -45
  64. package/test/components/MadieSpinner.test.js +12 -17
  65. package/test/components/Modal.test.js +115 -0
  66. package/test/components/Pagination.test.js +2 -2
  67. package/test/components/RadioButton.test.js +7 -7
  68. package/test/components/ReadOnlyTextField.test.js +4 -2
  69. package/test/components/RichTextEditor.test.js +90 -6
  70. package/test/components/Search.test.js +75 -0
  71. package/test/components/Select.test.js +97 -107
  72. package/test/components/Tabs.test.js +22 -24
  73. package/test/components/TextArea.test.js +78 -92
  74. package/test/components/TextField.test.js +128 -147
  75. package/test/components/Toast.test.js +67 -78
  76. package/test/components/TruncateText.test.js +75 -0
  77. package/test/components/index.test.js +23 -0
  78. package/webpack.config.js +0 -1
  79. package/.eslintignore +0 -5
  80. package/components/Alert/Alert.stories.js +0 -70
  81. package/components/Alert/index.js +0 -55
  82. package/components/Breadcrumb/Breadcrumb.md +0 -28
  83. package/components/Breadcrumb/Breadcrumb.stories.js +0 -76
  84. package/components/Breadcrumb/index.js +0 -92
  85. package/components/CalloutBox/CalloutBox.stories.js +0 -94
  86. package/components/CalloutBox/index.js +0 -109
  87. package/components/Card/Card.stories.js +0 -163
  88. package/components/Card/index.js +0 -144
  89. package/components/Dropdown/Dropdown.stories.js +0 -94
  90. package/components/Dropdown/index.js +0 -85
  91. package/components/Error/Collapsible.jsx +0 -93
  92. package/components/Error/ErrorUI.jsx +0 -31
  93. package/components/Error/error.js +0 -26
  94. package/components/FlashNotification/FlashNotificationUI.jsx +0 -91
  95. package/components/FlashNotification/index.js +0 -30
  96. package/components/Footer/Footer.stories.js +0 -20
  97. package/components/Footer/FooterUI.jsx +0 -137
  98. package/components/Footer/LegacyFooterUI.jsx +0 -204
  99. package/components/Footer/SocialLinks.jsx +0 -63
  100. package/components/Footer/Subscribe.jsx +0 -34
  101. package/components/Footer/footer.js +0 -30
  102. package/components/Infotip/Infotip.jsx +0 -75
  103. package/components/Infotip/Infotip.stories.js +0 -52
  104. package/components/Infotip/InfotipIcon.jsx +0 -41
  105. package/components/Infotip/index.js +0 -3
  106. package/components/Link/Link.stories.js +0 -82
  107. package/components/Link/index.js +0 -61
  108. package/components/Spinner/index.js +0 -9
  109. package/components/TextInput/TextInput.stories.js +0 -118
  110. package/components/TextInput/index.js +0 -137
  111. package/components/Tooltip/Tooltip.jsx +0 -88
  112. package/components/Tooltip/Tooltip.stories.js +0 -80
  113. package/components/Tooltip/index.js +0 -3
  114. package/components/Tooltip/position.js +0 -76
  115. package/test/components/ErrorUI.test.js +0 -32
  116. package/test/components/FooterUI.test.js +0 -122
  117. package/test/components/Infotip.test.js +0 -76
  118. 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 { act } from "react-dom/test-utils";
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
- await act(async () => {
31
- const { findByTestId, getByTestId, queryByText } = await render(
32
- <DialogTester />
33
- );
34
- const result = await findByTestId("dialog-tester");
35
- fireEvent.click(result);
36
- const discardDialog = await getByTestId("discard-dialog");
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
- await act(async () => {
46
- const { findByTestId, getByTestId, queryByText } = await render(
47
- <DialogTester />
48
- );
49
- const result = await findByTestId("dialog-tester");
50
- fireEvent.click(result);
51
- const continueButton = await getByTestId(
52
- "discard-dialog-continue-button"
53
- );
54
- expect(continueButton).toBeInTheDocument();
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
- await act(async () => {
65
- const { findByTestId, getByTestId, queryByText } = await render(
66
- <DialogTester />
67
- );
68
- const result = await findByTestId("dialog-tester");
69
- fireEvent.click(result);
70
- const cancelButton = await getByTestId(
71
- "discard-dialog-cancel-button"
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
- await act(async () => {
11
- const { findByTestId } = 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();
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
- await act(async () => {
23
- const { findByTestId } = render(
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", { name: "test Name" });
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(screen.getByTestId("test-label-rich-text-editor")).toBeInTheDocument();
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, {target: {innerHTML: "Updated Content"}});
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
+ });