@abstraks-dev/ui-library 1.0.1

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 (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +708 -0
  3. package/dist/__tests__/Anchor.test.js +145 -0
  4. package/dist/__tests__/ArrowRight.test.js +91 -0
  5. package/dist/__tests__/Avatar.test.js +123 -0
  6. package/dist/__tests__/Button.test.js +82 -0
  7. package/dist/__tests__/Card.test.js +198 -0
  8. package/dist/__tests__/CheckCircle.test.js +98 -0
  9. package/dist/__tests__/Checkbox.test.js +161 -0
  10. package/dist/__tests__/ChevronDown.test.js +73 -0
  11. package/dist/__tests__/Close.test.js +98 -0
  12. package/dist/__tests__/EditSquare.test.js +99 -0
  13. package/dist/__tests__/Error.test.js +74 -0
  14. package/dist/__tests__/Footer.test.js +66 -0
  15. package/dist/__tests__/Heading.test.js +227 -0
  16. package/dist/__tests__/Hero.test.js +74 -0
  17. package/dist/__tests__/Label.test.js +123 -0
  18. package/dist/__tests__/Loader.test.js +115 -0
  19. package/dist/__tests__/MenuHover.test.js +137 -0
  20. package/dist/__tests__/Paragraph.test.js +93 -0
  21. package/dist/__tests__/PlusCircle.test.js +99 -0
  22. package/dist/__tests__/Radio.test.js +153 -0
  23. package/dist/__tests__/Select.test.js +187 -0
  24. package/dist/__tests__/Tabs.test.js +162 -0
  25. package/dist/__tests__/TextArea.test.js +127 -0
  26. package/dist/__tests__/TextInput.test.js +181 -0
  27. package/dist/__tests__/Toggle.test.js +120 -0
  28. package/dist/__tests__/TrashX.test.js +99 -0
  29. package/dist/__tests__/useHeadingAccessibility.test.js +144 -0
  30. package/dist/components/Anchor.js +131 -0
  31. package/dist/components/Animation.js +129 -0
  32. package/dist/components/AnimationGroup.js +207 -0
  33. package/dist/components/AnimationToggle.js +216 -0
  34. package/dist/components/Avatar.js +153 -0
  35. package/dist/components/Button.js +218 -0
  36. package/dist/components/Card.js +222 -0
  37. package/dist/components/Checkbox.js +305 -0
  38. package/dist/components/Crud.js +564 -0
  39. package/dist/components/DragAndDrop.js +337 -0
  40. package/dist/components/Error.js +206 -0
  41. package/dist/components/Footer.js +99 -0
  42. package/dist/components/Form.js +412 -0
  43. package/dist/components/Header.js +372 -0
  44. package/dist/components/Heading.js +134 -0
  45. package/dist/components/Hero.js +181 -0
  46. package/dist/components/Label.js +256 -0
  47. package/dist/components/Loader.js +302 -0
  48. package/dist/components/MenuHover.js +114 -0
  49. package/dist/components/Paragraph.js +128 -0
  50. package/dist/components/Prompt.js +61 -0
  51. package/dist/components/Radio.js +254 -0
  52. package/dist/components/Select.js +422 -0
  53. package/dist/components/SideMenu.js +313 -0
  54. package/dist/components/Tabs.js +297 -0
  55. package/dist/components/TextArea.js +370 -0
  56. package/dist/components/TextInput.js +286 -0
  57. package/dist/components/Toggle.js +186 -0
  58. package/dist/components/crudFiles/CrudEditBase.js +150 -0
  59. package/dist/components/crudFiles/CrudViewBase.js +39 -0
  60. package/dist/components/crudFiles/crudDevelopment.js +118 -0
  61. package/dist/components/crudFiles/crudEditHandlers.js +50 -0
  62. package/dist/constants/animation.js +30 -0
  63. package/dist/icons/ArrowIcon.js +32 -0
  64. package/dist/icons/ArrowRight.js +33 -0
  65. package/dist/icons/CheckCircle.js +33 -0
  66. package/dist/icons/ChevronDown.js +28 -0
  67. package/dist/icons/Close.js +33 -0
  68. package/dist/icons/EditSquare.js +33 -0
  69. package/dist/icons/Ellipses.js +34 -0
  70. package/dist/icons/Hamburger.js +39 -0
  71. package/dist/icons/LoadingSpinner.js +42 -0
  72. package/dist/icons/PlusCircle.js +33 -0
  73. package/dist/icons/SaveIcon.js +32 -0
  74. package/dist/icons/TrashX.js +33 -0
  75. package/dist/icons/__tests__/CheckCircle.test.js +9 -0
  76. package/dist/icons/__tests__/ChevronDown.test.js +9 -0
  77. package/dist/icons/__tests__/Close.test.js +9 -0
  78. package/dist/icons/__tests__/EditSquare.test.js +9 -0
  79. package/dist/icons/__tests__/PlusCircle.test.js +9 -0
  80. package/dist/icons/__tests__/TrashX.test.js +9 -0
  81. package/dist/icons/index.js +89 -0
  82. package/dist/index.js +332 -0
  83. package/dist/setupTests.js +3 -0
  84. package/dist/styles/_variables.scss +286 -0
  85. package/dist/styles/anchor.scss +40 -0
  86. package/dist/styles/animation-accessibility.scss +96 -0
  87. package/dist/styles/animation-toggle.scss +233 -0
  88. package/dist/styles/animation.scss +3781 -0
  89. package/dist/styles/avatar.scss +285 -0
  90. package/dist/styles/button.scss +430 -0
  91. package/dist/styles/card.scss +210 -0
  92. package/dist/styles/checkbox.scss +160 -0
  93. package/dist/styles/crud.scss +474 -0
  94. package/dist/styles/dragAndDrop.scss +312 -0
  95. package/dist/styles/error.scss +232 -0
  96. package/dist/styles/footer.scss +58 -0
  97. package/dist/styles/form.scss +420 -0
  98. package/dist/styles/grid.scss +29 -0
  99. package/dist/styles/header.scss +276 -0
  100. package/dist/styles/heading.scss +118 -0
  101. package/dist/styles/hero.scss +185 -0
  102. package/dist/styles/htmlElements.scss +20 -0
  103. package/dist/styles/image.scss +9 -0
  104. package/dist/styles/label.scss +340 -0
  105. package/dist/styles/list-item.scss +5 -0
  106. package/dist/styles/loader.scss +354 -0
  107. package/dist/styles/logo.scss +19 -0
  108. package/dist/styles/main.css +9056 -0
  109. package/dist/styles/main.css.map +1 -0
  110. package/dist/styles/main.scss +0 -0
  111. package/dist/styles/menu-hover.scss +30 -0
  112. package/dist/styles/paragraph.scss +88 -0
  113. package/dist/styles/prompt.scss +51 -0
  114. package/dist/styles/radio.scss +202 -0
  115. package/dist/styles/select.scss +363 -0
  116. package/dist/styles/side-menu.scss +334 -0
  117. package/dist/styles/tabs.scss +540 -0
  118. package/dist/styles/text-area.scss +388 -0
  119. package/dist/styles/text-input.scss +171 -0
  120. package/dist/styles/toggle.scss +0 -0
  121. package/dist/styles/unordered-list.scss +8 -0
  122. package/dist/utils/ScrollHandler.js +30 -0
  123. package/dist/utils/accessibility.js +128 -0
  124. package/dist/utils/heroUtils.js +316 -0
  125. package/dist/utils/index.js +104 -0
  126. package/dist/utils/inputValidation.js +29 -0
  127. package/dist/utils/keyboardNavigation.js +536 -0
  128. package/dist/utils/labelUtils.js +708 -0
  129. package/dist/utils/loaderUtils.js +387 -0
  130. package/dist/utils/menuUtils.js +575 -0
  131. package/dist/utils/useHeadingAccessibility.js +298 -0
  132. package/dist/utils/useRadioGroup.js +260 -0
  133. package/dist/utils/useSelectAccessibility.js +426 -0
  134. package/dist/utils/useTabsAccessibility.js +278 -0
  135. package/dist/utils/useTextAreaAccessibility.js +255 -0
  136. package/dist/utils/useTextInputAccessibility.js +295 -0
  137. package/dist/utils/useTypographyAccessibility.js +168 -0
  138. package/dist/utils/useWindowSize.js +32 -0
  139. package/dist/utils/utils/ScrollHandler.js +26 -0
  140. package/dist/utils/utils/accessibility.js +133 -0
  141. package/dist/utils/utils/heroUtils.js +348 -0
  142. package/dist/utils/utils/index.js +9 -0
  143. package/dist/utils/utils/inputValidation.js +22 -0
  144. package/dist/utils/utils/keyboardNavigation.js +664 -0
  145. package/dist/utils/utils/labelUtils.js +772 -0
  146. package/dist/utils/utils/loaderUtils.js +436 -0
  147. package/dist/utils/utils/menuUtils.js +651 -0
  148. package/dist/utils/utils/useHeadingAccessibility.js +334 -0
  149. package/dist/utils/utils/useRadioGroup.js +311 -0
  150. package/dist/utils/utils/useSelectAccessibility.js +498 -0
  151. package/dist/utils/utils/useTabsAccessibility.js +316 -0
  152. package/dist/utils/utils/useTextAreaAccessibility.js +303 -0
  153. package/dist/utils/utils/useTextInputAccessibility.js +338 -0
  154. package/dist/utils/utils/useTypographyAccessibility.js +180 -0
  155. package/dist/utils/utils/useWindowSize.js +26 -0
  156. package/dist/utils/utils/validation.js +131 -0
  157. package/dist/utils/validation.js +139 -0
  158. package/package.json +90 -0
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ var _react = _interopRequireDefault(require("react"));
4
+ var _react2 = require("@testing-library/react");
5
+ var _CheckCircle = require("../icons/CheckCircle");
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
+ // Suppress console.error during tests
8
+ let consoleErrorSpy;
9
+ beforeAll(() => {
10
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
11
+ });
12
+ afterAll(() => {
13
+ consoleErrorSpy.mockRestore();
14
+ });
15
+ describe('CheckCircle Icon', () => {
16
+ test('renders with default props', () => {
17
+ const {
18
+ container
19
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_CheckCircle.CheckCircle, null));
20
+ const svg = container.querySelector('svg');
21
+ expect(svg).toBeInTheDocument();
22
+ expect(svg).toHaveClass('icon', 'check-close');
23
+ expect(svg).toHaveAttribute('width', '24');
24
+ expect(svg).toHaveAttribute('height', '24');
25
+ expect(svg).toHaveAttribute('viewBox', '0 -960 960 960');
26
+ expect(svg).toHaveAttribute('fill', '#adb5bd');
27
+ });
28
+ test('renders with custom component name', () => {
29
+ const {
30
+ container
31
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_CheckCircle.CheckCircle, {
32
+ componentName: "success-icon"
33
+ }));
34
+ const svg = container.querySelector('svg');
35
+ expect(svg).toHaveClass('icon', 'success-icon');
36
+ });
37
+ test('renders with additional className', () => {
38
+ const {
39
+ container
40
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_CheckCircle.CheckCircle, {
41
+ additionalClassName: "large-icon"
42
+ }));
43
+ const svg = container.querySelector('svg');
44
+ expect(svg).toHaveClass('icon', 'check-close', 'large-icon');
45
+ });
46
+ test('renders with custom dimensions', () => {
47
+ const {
48
+ container
49
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_CheckCircle.CheckCircle, {
50
+ dimensions: 48
51
+ }));
52
+ const svg = container.querySelector('svg');
53
+ expect(svg).toHaveAttribute('width', '48');
54
+ expect(svg).toHaveAttribute('height', '48');
55
+ });
56
+ test('renders with custom viewBox', () => {
57
+ const {
58
+ container
59
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_CheckCircle.CheckCircle, {
60
+ viewBox: "0 0 24 24"
61
+ }));
62
+ const svg = container.querySelector('svg');
63
+ expect(svg).toHaveAttribute('viewBox', '0 0 24 24');
64
+ });
65
+ test('renders with custom fill color', () => {
66
+ const {
67
+ container
68
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_CheckCircle.CheckCircle, {
69
+ fill: "#00ff00"
70
+ }));
71
+ const svg = container.querySelector('svg');
72
+ expect(svg).toHaveAttribute('fill', '#00ff00');
73
+ });
74
+ test('contains path element', () => {
75
+ const {
76
+ container
77
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_CheckCircle.CheckCircle, null));
78
+ const path = container.querySelector('path');
79
+ expect(path).toBeInTheDocument();
80
+ });
81
+ test('combines all props correctly', () => {
82
+ const {
83
+ container
84
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_CheckCircle.CheckCircle, {
85
+ componentName: "check-success",
86
+ additionalClassName: "animated bounce",
87
+ dimensions: 32,
88
+ viewBox: "0 0 32 32",
89
+ fill: "#28a745"
90
+ }));
91
+ const svg = container.querySelector('svg');
92
+ expect(svg).toHaveClass('icon', 'check-success', 'animated', 'bounce');
93
+ expect(svg).toHaveAttribute('width', '32');
94
+ expect(svg).toHaveAttribute('height', '32');
95
+ expect(svg).toHaveAttribute('viewBox', '0 0 32 32');
96
+ expect(svg).toHaveAttribute('fill', '#28a745');
97
+ });
98
+ });
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+
3
+ var _react = _interopRequireDefault(require("react"));
4
+ var _react2 = require("@testing-library/react");
5
+ var _userEvent = _interopRequireDefault(require("@testing-library/user-event"));
6
+ var _Checkbox = require("../components/Checkbox");
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
+ // Suppress console.error during tests
9
+ let consoleErrorSpy;
10
+ beforeAll(() => {
11
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
12
+ });
13
+ afterAll(() => {
14
+ consoleErrorSpy.mockRestore();
15
+ });
16
+ describe('Checkbox Component', () => {
17
+ test('renders checkbox with label', () => {
18
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
19
+ labelText: "Accept terms",
20
+ name: "terms"
21
+ }));
22
+ const checkbox = _react2.screen.getByRole('checkbox');
23
+ const label = _react2.screen.getByText('Accept terms');
24
+ expect(checkbox).toBeInTheDocument();
25
+ expect(label).toBeInTheDocument();
26
+ expect(checkbox).not.toBeChecked();
27
+ });
28
+ test('renders checkbox without label when noLabel is true', () => {
29
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
30
+ noLabel: true,
31
+ name: "test"
32
+ }));
33
+ const checkbox = _react2.screen.getByRole('checkbox');
34
+ expect(checkbox).toBeInTheDocument();
35
+
36
+ // Should not render label component
37
+ expect(_react2.screen.queryByText('label')).not.toBeInTheDocument();
38
+ });
39
+ test('shows required asterisk when required is true', () => {
40
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
41
+ labelText: "Required Field",
42
+ required: true,
43
+ name: "required"
44
+ }));
45
+ const asterisk = _react2.screen.getByText('*');
46
+ expect(asterisk).toBeInTheDocument();
47
+ });
48
+ test('toggles checked state when clicked', async () => {
49
+ const user = _userEvent.default.setup();
50
+ function Wrapper() {
51
+ const [checked, setChecked] = _react.default.useState(false);
52
+ return /*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
53
+ labelText: "Toggle me",
54
+ name: "toggle",
55
+ checked: checked,
56
+ onChange: () => setChecked(c => !c)
57
+ });
58
+ }
59
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(Wrapper, null));
60
+ const checkbox = _react2.screen.getByRole('checkbox');
61
+
62
+ // Initially unchecked
63
+ expect(checkbox).not.toBeChecked();
64
+
65
+ // Click to check
66
+ await user.click(checkbox);
67
+ expect(checkbox).toBeChecked();
68
+
69
+ // Click to uncheck
70
+ await user.click(checkbox);
71
+ expect(checkbox).not.toBeChecked();
72
+ });
73
+ test('applies correct CSS classes', () => {
74
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
75
+ labelText: "Test",
76
+ name: "test"
77
+ }));
78
+ const wrapper = _react2.screen.getByTestId('checkbox-wrapper');
79
+ const checkbox = _react2.screen.getByRole('checkbox');
80
+ expect(wrapper).toHaveClass('checkbox-wrapper');
81
+ expect(checkbox).toHaveClass('checkbox');
82
+ });
83
+ test('applies additional className to wrapper', () => {
84
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
85
+ labelText: "Test",
86
+ name: "test",
87
+ additionalClassName: "custom-checkbox"
88
+ }));
89
+ const wrapper = _react2.screen.getByTestId('checkbox-wrapper');
90
+ expect(wrapper).toHaveClass('checkbox-wrapper', 'custom-checkbox');
91
+ });
92
+ test('applies custom component name', () => {
93
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
94
+ labelText: "Test",
95
+ name: "test",
96
+ componentName: "custom-check"
97
+ }));
98
+ const wrapper = _react2.screen.getByTestId('custom-check-wrapper');
99
+ const checkbox = _react2.screen.getByRole('checkbox');
100
+ expect(wrapper).toHaveClass('custom-check-wrapper');
101
+ expect(checkbox).toHaveClass('custom-check');
102
+ });
103
+ test('sets correct name attribute', () => {
104
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
105
+ labelText: "Test",
106
+ name: "test-name"
107
+ }));
108
+ const checkbox = _react2.screen.getByRole('checkbox');
109
+ expect(checkbox).toHaveAttribute('name', 'test-name');
110
+ });
111
+ test('handles disabled state', () => {
112
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
113
+ labelText: "Disabled",
114
+ name: "disabled",
115
+ disabled: true
116
+ }));
117
+ const checkbox = _react2.screen.getByRole('checkbox');
118
+ expect(checkbox).toBeDisabled();
119
+ });
120
+ test('disabled checkbox cannot be toggled', async () => {
121
+ const user = _userEvent.default.setup();
122
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
123
+ labelText: "Disabled",
124
+ name: "disabled",
125
+ disabled: true
126
+ }));
127
+ const checkbox = _react2.screen.getByRole('checkbox');
128
+ await user.click(checkbox);
129
+ expect(checkbox).not.toBeChecked();
130
+ });
131
+ test('passes through additional props to input', () => {
132
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
133
+ labelText: "Test",
134
+ name: "test",
135
+ id: "custom-id",
136
+ "data-custom": "value"
137
+ }));
138
+ const checkbox = _react2.screen.getByRole('checkbox');
139
+ expect(checkbox).toHaveAttribute('id', 'custom-id');
140
+ expect(checkbox).toHaveAttribute('data-custom', 'value');
141
+ });
142
+ test('label is associated with checkbox via htmlFor and id', () => {
143
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
144
+ labelText: "Associated Label",
145
+ name: "associated"
146
+ }));
147
+ const checkbox = _react2.screen.getByRole('checkbox');
148
+ const label = document.querySelector('label');
149
+ expect(label).toBeInTheDocument();
150
+ expect(label).toHaveAttribute('for', checkbox.id);
151
+ expect(checkbox).toHaveAttribute('name', 'associated');
152
+ });
153
+ test('has correct data-test-id', () => {
154
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Checkbox.Checkbox, {
155
+ labelText: "Test",
156
+ name: "test"
157
+ }));
158
+ const wrapper = _react2.screen.getByTestId('checkbox-wrapper');
159
+ expect(wrapper).toHaveAttribute('data-testid', 'checkbox-wrapper');
160
+ });
161
+ });
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ var _react = _interopRequireDefault(require("react"));
4
+ var _react2 = require("@testing-library/react");
5
+ var _ChevronDown = require("../icons/ChevronDown");
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
+ // Suppress console.error during tests
8
+ let consoleErrorSpy;
9
+ beforeAll(() => {
10
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
11
+ });
12
+ afterAll(() => {
13
+ consoleErrorSpy.mockRestore();
14
+ });
15
+ describe('ChevronDown Icon', () => {
16
+ test('renders SVG element', () => {
17
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_ChevronDown.ChevronDown, null));
18
+ const svg = document.querySelector('svg');
19
+ expect(svg).toBeInTheDocument();
20
+ expect(svg.tagName).toBe('svg');
21
+ });
22
+ test('has correct default props', () => {
23
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_ChevronDown.ChevronDown, null));
24
+ const svg = document.querySelector('svg');
25
+ expect(svg).toHaveAttribute('width', '24');
26
+ expect(svg).toHaveAttribute('height', '24');
27
+ expect(svg).toHaveAttribute('viewBox', '0 0 24 24');
28
+ expect(svg).toHaveAttribute('fill', 'none');
29
+ });
30
+ test('applies custom size', () => {
31
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_ChevronDown.ChevronDown, {
32
+ size: 32
33
+ }));
34
+ const svg = document.querySelector('svg');
35
+ expect(svg).toHaveAttribute('width', '32');
36
+ expect(svg).toHaveAttribute('height', '32');
37
+ });
38
+ test('applies custom className', () => {
39
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_ChevronDown.ChevronDown, {
40
+ className: "custom-icon"
41
+ }));
42
+ const svg = document.querySelector('svg');
43
+ expect(svg).toHaveClass('custom-icon');
44
+ });
45
+ test('applies custom color to stroke', () => {
46
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_ChevronDown.ChevronDown, {
47
+ color: "#ff0000"
48
+ }));
49
+ const svg = document.querySelector('svg');
50
+ const path = svg.querySelector('path');
51
+ expect(path).toHaveAttribute('stroke', '#ff0000');
52
+ });
53
+ test('uses currentColor as default stroke', () => {
54
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_ChevronDown.ChevronDown, null));
55
+ const svg = document.querySelector('svg');
56
+ const path = svg.querySelector('path');
57
+ expect(path).toHaveAttribute('stroke', 'currentColor');
58
+ });
59
+ test('has correct stroke properties', () => {
60
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_ChevronDown.ChevronDown, null));
61
+ const svg = document.querySelector('svg');
62
+ const path = svg.querySelector('path');
63
+ expect(path).toHaveAttribute('stroke-width', '2');
64
+ expect(path).toHaveAttribute('stroke-linecap', 'round');
65
+ expect(path).toHaveAttribute('stroke-linejoin', 'round');
66
+ });
67
+ test('has correct path data', () => {
68
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_ChevronDown.ChevronDown, null));
69
+ const svg = document.querySelector('svg');
70
+ const path = svg.querySelector('path');
71
+ expect(path).toHaveAttribute('d', 'M6 9L12 15L18 9');
72
+ });
73
+ });
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ var _react = _interopRequireDefault(require("react"));
4
+ var _react2 = require("@testing-library/react");
5
+ var _Close = require("../icons/Close");
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
+ // Suppress console.error during tests
8
+ let consoleErrorSpy;
9
+ beforeAll(() => {
10
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
11
+ });
12
+ afterAll(() => {
13
+ consoleErrorSpy.mockRestore();
14
+ });
15
+ describe('Close Icon', () => {
16
+ test('renders with default props', () => {
17
+ const {
18
+ container
19
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Close.Close, null));
20
+ const svg = container.querySelector('svg');
21
+ expect(svg).toBeInTheDocument();
22
+ expect(svg).toHaveClass('icon', 'close');
23
+ expect(svg).toHaveAttribute('width', '24');
24
+ expect(svg).toHaveAttribute('height', '24');
25
+ expect(svg).toHaveAttribute('viewBox', '0 -960 960 960');
26
+ expect(svg).toHaveAttribute('fill', '#adb5bd');
27
+ });
28
+ test('renders with custom component name', () => {
29
+ const {
30
+ container
31
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Close.Close, {
32
+ componentName: "close-modal"
33
+ }));
34
+ const svg = container.querySelector('svg');
35
+ expect(svg).toHaveClass('icon', 'close-modal');
36
+ });
37
+ test('renders with additional className', () => {
38
+ const {
39
+ container
40
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Close.Close, {
41
+ additionalClassName: "modal-close"
42
+ }));
43
+ const svg = container.querySelector('svg');
44
+ expect(svg).toHaveClass('icon', 'close', 'modal-close');
45
+ });
46
+ test('renders with custom dimensions', () => {
47
+ const {
48
+ container
49
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Close.Close, {
50
+ dimensions: 16
51
+ }));
52
+ const svg = container.querySelector('svg');
53
+ expect(svg).toHaveAttribute('width', '16');
54
+ expect(svg).toHaveAttribute('height', '16');
55
+ });
56
+ test('renders with custom viewBox', () => {
57
+ const {
58
+ container
59
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Close.Close, {
60
+ viewBox: "0 0 16 16"
61
+ }));
62
+ const svg = container.querySelector('svg');
63
+ expect(svg).toHaveAttribute('viewBox', '0 0 16 16');
64
+ });
65
+ test('renders with custom fill color', () => {
66
+ const {
67
+ container
68
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Close.Close, {
69
+ fill: "#ff0000"
70
+ }));
71
+ const svg = container.querySelector('svg');
72
+ expect(svg).toHaveAttribute('fill', '#ff0000');
73
+ });
74
+ test('contains path element', () => {
75
+ const {
76
+ container
77
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Close.Close, null));
78
+ const path = container.querySelector('path');
79
+ expect(path).toBeInTheDocument();
80
+ });
81
+ test('combines all props correctly', () => {
82
+ const {
83
+ container
84
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Close.Close, {
85
+ componentName: "dialog-close",
86
+ additionalClassName: "hover-red clickable",
87
+ dimensions: 20,
88
+ viewBox: "0 0 20 20",
89
+ fill: "#333333"
90
+ }));
91
+ const svg = container.querySelector('svg');
92
+ expect(svg).toHaveClass('icon', 'dialog-close', 'hover-red', 'clickable');
93
+ expect(svg).toHaveAttribute('width', '20');
94
+ expect(svg).toHaveAttribute('height', '20');
95
+ expect(svg).toHaveAttribute('viewBox', '0 0 20 20');
96
+ expect(svg).toHaveAttribute('fill', '#333333');
97
+ });
98
+ });
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ var _react = _interopRequireDefault(require("react"));
4
+ var _react2 = require("@testing-library/react");
5
+ var _EditSquare = require("../icons/EditSquare");
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
+ // Suppress console.error during tests
8
+ let consoleErrorSpy;
9
+ beforeAll(() => {
10
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
11
+ });
12
+ afterAll(() => {
13
+ consoleErrorSpy.mockRestore();
14
+ });
15
+ describe('EditSquare', () => {
16
+ test('renders edit square icon with default props', () => {
17
+ const {
18
+ container
19
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_EditSquare.EditSquare, null));
20
+ const svg = container.querySelector('svg');
21
+ expect(svg).toBeInTheDocument();
22
+ expect(svg).toHaveClass('icon', 'edit-square');
23
+ expect(svg).toHaveAttribute('width', '24');
24
+ expect(svg).toHaveAttribute('height', '24');
25
+ expect(svg).toHaveAttribute('viewBox', '0 -960 960 960');
26
+ expect(svg).toHaveAttribute('fill', '#adb5bd');
27
+ });
28
+ test('renders with custom component name', () => {
29
+ const {
30
+ container
31
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_EditSquare.EditSquare, {
32
+ componentName: "pencil-icon"
33
+ }));
34
+ const svg = container.querySelector('svg');
35
+ expect(svg).toHaveClass('icon', 'pencil-icon');
36
+ });
37
+ test('renders with additional className', () => {
38
+ const {
39
+ container
40
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_EditSquare.EditSquare, {
41
+ additionalClassName: "small hover-orange"
42
+ }));
43
+ const svg = container.querySelector('svg');
44
+ expect(svg).toHaveClass('icon', 'edit-square', 'small', 'hover-orange');
45
+ });
46
+ test('renders with custom dimensions', () => {
47
+ const {
48
+ container
49
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_EditSquare.EditSquare, {
50
+ dimensions: 18
51
+ }));
52
+ const svg = container.querySelector('svg');
53
+ expect(svg).toHaveAttribute('width', '18');
54
+ expect(svg).toHaveAttribute('height', '18');
55
+ });
56
+ test('renders with custom viewBox', () => {
57
+ const {
58
+ container
59
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_EditSquare.EditSquare, {
60
+ viewBox: "0 0 512 512"
61
+ }));
62
+ const svg = container.querySelector('svg');
63
+ expect(svg).toHaveAttribute('viewBox', '0 0 512 512');
64
+ });
65
+ test('renders with custom fill color', () => {
66
+ const {
67
+ container
68
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_EditSquare.EditSquare, {
69
+ fill: "#6c757d"
70
+ }));
71
+ const svg = container.querySelector('svg');
72
+ expect(svg).toHaveAttribute('fill', '#6c757d');
73
+ });
74
+ test('contains path element', () => {
75
+ const {
76
+ container
77
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_EditSquare.EditSquare, null));
78
+ const path = container.querySelector('path');
79
+ expect(path).toBeInTheDocument();
80
+ expect(path).toHaveAttribute('d');
81
+ });
82
+ test('combines all props correctly', () => {
83
+ const {
84
+ container
85
+ } = (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_EditSquare.EditSquare, {
86
+ componentName: "modify-icon",
87
+ additionalClassName: "cursor-pointer blue-on-hover",
88
+ dimensions: 20,
89
+ viewBox: "0 0 64 64",
90
+ fill: "#ffc107"
91
+ }));
92
+ const svg = container.querySelector('svg');
93
+ expect(svg).toHaveClass('icon', 'modify-icon', 'cursor-pointer', 'blue-on-hover');
94
+ expect(svg).toHaveAttribute('width', '20');
95
+ expect(svg).toHaveAttribute('height', '20');
96
+ expect(svg).toHaveAttribute('viewBox', '0 0 64 64');
97
+ expect(svg).toHaveAttribute('fill', '#ffc107');
98
+ });
99
+ });
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+
3
+ var _react = _interopRequireDefault(require("react"));
4
+ var _react2 = require("@testing-library/react");
5
+ var _Error = require("../components/Error");
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
+ // Suppress console.error during tests
8
+ let consoleErrorSpy;
9
+ beforeAll(() => {
10
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
11
+ });
12
+ afterAll(() => {
13
+ consoleErrorSpy.mockRestore();
14
+ });
15
+ describe('Error Component', () => {
16
+ test('renders error with children text', () => {
17
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Error.Error, null, "This is an error message"));
18
+ const error = _react2.screen.getByTestId('error');
19
+ expect(error).toBeInTheDocument();
20
+ expect(error).toHaveTextContent('This is an error message');
21
+ expect(error.tagName).toBe('DIV');
22
+ });
23
+ test('renders with default component name', () => {
24
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Error.Error, null, "Error text"));
25
+ const error = _react2.screen.getByTestId('error');
26
+ expect(error).toHaveClass('error');
27
+ });
28
+ test('renders with custom component name', () => {
29
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Error.Error, {
30
+ componentName: "validation-error"
31
+ }, "Error text"));
32
+ const error = _react2.screen.getByTestId('validation-error');
33
+ expect(error).toHaveClass('validation-error');
34
+ });
35
+ test('renders with additional className', () => {
36
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Error.Error, {
37
+ additionalClassName: "red-text"
38
+ }, "Error text"));
39
+ const error = _react2.screen.getByTestId('error');
40
+ expect(error).toHaveClass('error', 'red-text');
41
+ });
42
+ test('handles empty children', () => {
43
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Error.Error, null));
44
+ const error = _react2.screen.getByTestId('error');
45
+ expect(error).toBeInTheDocument();
46
+ // The error container always contains icon and text spans, so check the text span is empty
47
+ const textSpan = error.querySelector('.error__text');
48
+ expect(textSpan).toBeInTheDocument();
49
+ expect(textSpan).toBeEmptyDOMElement();
50
+ });
51
+ test('renders with multiple class names', () => {
52
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Error.Error, {
53
+ componentName: "field-error",
54
+ additionalClassName: "bold italic"
55
+ }, "Field validation failed"));
56
+ const error = _react2.screen.getByTestId('field-error');
57
+ expect(error).toHaveClass('field-error', 'bold', 'italic');
58
+ expect(error).toHaveTextContent('Field validation failed');
59
+ });
60
+ test('handles long error messages', () => {
61
+ const longMessage = 'This is a very long error message that should be displayed properly even when it contains multiple sentences and detailed information about what went wrong.';
62
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Error.Error, null, longMessage));
63
+ const error = _react2.screen.getByTestId('error');
64
+ expect(error).toHaveTextContent(longMessage);
65
+ });
66
+ test('renders undefined additionalClassName gracefully', () => {
67
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Error.Error, {
68
+ additionalClassName: undefined
69
+ }, "Error text"));
70
+ const error = _react2.screen.getByTestId('error');
71
+ expect(error).toBeInTheDocument();
72
+ expect(error).toHaveTextContent('Error text');
73
+ });
74
+ });
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+
3
+ var _react = _interopRequireDefault(require("react"));
4
+ var _react2 = require("@testing-library/react");
5
+ require("@testing-library/jest-dom");
6
+ var _Footer = _interopRequireDefault(require("../components/Footer"));
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
+ // Suppress console.error during tests
9
+ let consoleErrorSpy;
10
+ beforeAll(() => {
11
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
12
+ });
13
+ afterAll(() => {
14
+ consoleErrorSpy.mockRestore();
15
+ });
16
+ describe('Footer', () => {
17
+ it('renders with default props', () => {
18
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Footer.default, {
19
+ navigation: /*#__PURE__*/_react.default.createElement("li", null, "NavItem")
20
+ }));
21
+ expect(_react2.screen.getByRole('contentinfo')).toBeInTheDocument();
22
+ expect(_react2.screen.getByText('NavItem')).toBeInTheDocument();
23
+ });
24
+ it('renders mobile navigation when width < 768', () => {
25
+ // Mock useWindowSize to return mobile width
26
+ jest.spyOn(require('../utils/useWindowSize'), 'useWindowSize').mockReturnValue({
27
+ width: 500
28
+ });
29
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Footer.default, {
30
+ navigation: /*#__PURE__*/_react.default.createElement("li", null, "MobileNav")
31
+ }));
32
+ expect(_react2.screen.getByLabelText('Mobile footer navigation')).toBeInTheDocument();
33
+ expect(_react2.screen.getByText('MobileNav')).toBeInTheDocument();
34
+ });
35
+ it('renders desktop navigation when width >= 768', () => {
36
+ jest.spyOn(require('../utils/useWindowSize'), 'useWindowSize').mockReturnValue({
37
+ width: 1024
38
+ });
39
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Footer.default, {
40
+ navigation: /*#__PURE__*/_react.default.createElement("li", null, "DesktopNav")
41
+ }));
42
+ expect(_react2.screen.getByLabelText('Desktop footer navigation')).toBeInTheDocument();
43
+ expect(_react2.screen.getByText('DesktopNav')).toBeInTheDocument();
44
+ });
45
+ it('renders auth menu when hasAuth is true (mobile)', () => {
46
+ jest.spyOn(require('../utils/useWindowSize'), 'useWindowSize').mockReturnValue({
47
+ width: 500
48
+ });
49
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Footer.default, {
50
+ hasAuth: true,
51
+ navigation: null
52
+ }));
53
+ expect(_react2.screen.getByLabelText('User navigation')).toBeInTheDocument();
54
+ expect(_react2.screen.getByText('Home')).toBeInTheDocument();
55
+ expect(_react2.screen.getByText('Search')).toBeInTheDocument();
56
+ expect(_react2.screen.getByText('Add')).toBeInTheDocument();
57
+ expect(_react2.screen.getByText('Profile')).toBeInTheDocument();
58
+ });
59
+ it('applies custom aria-label', () => {
60
+ (0, _react2.render)(/*#__PURE__*/_react.default.createElement(_Footer.default, {
61
+ navigation: /*#__PURE__*/_react.default.createElement("li", null, "Nav"),
62
+ "aria-label": "Custom Footer"
63
+ }));
64
+ expect(_react2.screen.getByRole('contentinfo')).toHaveAttribute('aria-label', 'Custom Footer');
65
+ });
66
+ });