@akinon/ai-modal-table 1.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 (185) hide show
  1. package/dist/cjs/__tests__/index.test.d.ts +2 -0
  2. package/dist/cjs/__tests__/index.test.d.ts.map +1 -0
  3. package/dist/cjs/__tests__/index.test.js +82 -0
  4. package/dist/cjs/__tests__/index.test.tsx +94 -0
  5. package/dist/cjs/ai-modal-table/__tests__/index.test.d.ts +2 -0
  6. package/dist/cjs/ai-modal-table/__tests__/index.test.d.ts.map +1 -0
  7. package/dist/cjs/ai-modal-table/__tests__/index.test.js +59 -0
  8. package/dist/cjs/ai-modal-table/__tests__/index.test.tsx +98 -0
  9. package/dist/cjs/ai-modal-table/index.d.ts +4 -0
  10. package/dist/cjs/ai-modal-table/index.d.ts.map +1 -0
  11. package/dist/cjs/ai-modal-table/index.js +54 -0
  12. package/dist/cjs/ai-table/__tests__/index.test.d.ts +2 -0
  13. package/dist/cjs/ai-table/__tests__/index.test.d.ts.map +1 -0
  14. package/dist/cjs/ai-table/__tests__/index.test.js +348 -0
  15. package/dist/cjs/ai-table/__tests__/index.test.tsx +572 -0
  16. package/dist/cjs/ai-table/components/__tests__/content.test.d.ts +2 -0
  17. package/dist/cjs/ai-table/components/__tests__/content.test.d.ts.map +1 -0
  18. package/dist/cjs/ai-table/components/__tests__/content.test.js +1349 -0
  19. package/dist/cjs/ai-table/components/__tests__/content.test.tsx +1637 -0
  20. package/dist/cjs/ai-table/components/__tests__/filters.test.d.ts +2 -0
  21. package/dist/cjs/ai-table/components/__tests__/filters.test.d.ts.map +1 -0
  22. package/dist/cjs/ai-table/components/__tests__/filters.test.js +400 -0
  23. package/dist/cjs/ai-table/components/__tests__/filters.test.tsx +534 -0
  24. package/dist/cjs/ai-table/components/__tests__/footer.test.d.ts +2 -0
  25. package/dist/cjs/ai-table/components/__tests__/footer.test.d.ts.map +1 -0
  26. package/dist/cjs/ai-table/components/__tests__/footer.test.js +465 -0
  27. package/dist/cjs/ai-table/components/__tests__/footer.test.tsx +597 -0
  28. package/dist/cjs/ai-table/components/__tests__/mapper.test.d.ts +2 -0
  29. package/dist/cjs/ai-table/components/__tests__/mapper.test.d.ts.map +1 -0
  30. package/dist/cjs/ai-table/components/__tests__/mapper.test.js +453 -0
  31. package/dist/cjs/ai-table/components/__tests__/mapper.test.tsx +601 -0
  32. package/dist/cjs/ai-table/components/__tests__/pagination.test.d.ts +2 -0
  33. package/dist/cjs/ai-table/components/__tests__/pagination.test.d.ts.map +1 -0
  34. package/dist/cjs/ai-table/components/__tests__/pagination.test.js +430 -0
  35. package/dist/cjs/ai-table/components/__tests__/pagination.test.tsx +629 -0
  36. package/dist/cjs/ai-table/components/__tests__/row-actions.test.d.ts +2 -0
  37. package/dist/cjs/ai-table/components/__tests__/row-actions.test.d.ts.map +1 -0
  38. package/dist/cjs/ai-table/components/__tests__/row-actions.test.js +382 -0
  39. package/dist/cjs/ai-table/components/__tests__/row-actions.test.tsx +507 -0
  40. package/dist/cjs/ai-table/components/content.d.ts +11 -0
  41. package/dist/cjs/ai-table/components/content.d.ts.map +1 -0
  42. package/dist/cjs/ai-table/components/content.js +309 -0
  43. package/dist/cjs/ai-table/components/filters.d.ts +10 -0
  44. package/dist/cjs/ai-table/components/filters.d.ts.map +1 -0
  45. package/dist/cjs/ai-table/components/filters.js +55 -0
  46. package/dist/cjs/ai-table/components/footer.d.ts +12 -0
  47. package/dist/cjs/ai-table/components/footer.d.ts.map +1 -0
  48. package/dist/cjs/ai-table/components/footer.js +24 -0
  49. package/dist/cjs/ai-table/components/mapper.d.ts +11 -0
  50. package/dist/cjs/ai-table/components/mapper.d.ts.map +1 -0
  51. package/dist/cjs/ai-table/components/mapper.js +21 -0
  52. package/dist/cjs/ai-table/components/pagination.d.ts +11 -0
  53. package/dist/cjs/ai-table/components/pagination.d.ts.map +1 -0
  54. package/dist/cjs/ai-table/components/pagination.js +106 -0
  55. package/dist/cjs/ai-table/components/row-actions.d.ts +14 -0
  56. package/dist/cjs/ai-table/components/row-actions.d.ts.map +1 -0
  57. package/dist/cjs/ai-table/components/row-actions.js +52 -0
  58. package/dist/cjs/ai-table/constants/index.d.ts +17 -0
  59. package/dist/cjs/ai-table/constants/index.d.ts.map +1 -0
  60. package/dist/cjs/ai-table/constants/index.js +19 -0
  61. package/dist/cjs/ai-table/i18n/index.d.ts +3 -0
  62. package/dist/cjs/ai-table/i18n/index.d.ts.map +1 -0
  63. package/dist/cjs/ai-table/i18n/index.js +14 -0
  64. package/dist/cjs/ai-table/i18n/translations/en.d.ts +8 -0
  65. package/dist/cjs/ai-table/i18n/translations/en.d.ts.map +1 -0
  66. package/dist/cjs/ai-table/i18n/translations/en.js +9 -0
  67. package/dist/cjs/ai-table/i18n/translations/tr.d.ts +8 -0
  68. package/dist/cjs/ai-table/i18n/translations/tr.d.ts.map +1 -0
  69. package/dist/cjs/ai-table/i18n/translations/tr.js +9 -0
  70. package/dist/cjs/ai-table/index.d.ts +4 -0
  71. package/dist/cjs/ai-table/index.d.ts.map +1 -0
  72. package/dist/cjs/ai-table/index.js +71 -0
  73. package/dist/cjs/ai-table/utils/data-format/__tests__/index.test.d.ts +2 -0
  74. package/dist/cjs/ai-table/utils/data-format/__tests__/index.test.d.ts.map +1 -0
  75. package/dist/cjs/ai-table/utils/data-format/__tests__/index.test.js +146 -0
  76. package/dist/cjs/ai-table/utils/data-format/__tests__/index.test.ts +184 -0
  77. package/dist/cjs/ai-table/utils/data-format/index.d.ts +7 -0
  78. package/dist/cjs/ai-table/utils/data-format/index.d.ts.map +1 -0
  79. package/dist/cjs/ai-table/utils/data-format/index.js +43 -0
  80. package/dist/cjs/ai-table/utils/render-mapper-fields/__tests__/index.test.d.ts +2 -0
  81. package/dist/cjs/ai-table/utils/render-mapper-fields/__tests__/index.test.d.ts.map +1 -0
  82. package/dist/cjs/ai-table/utils/render-mapper-fields/__tests__/index.test.js +291 -0
  83. package/dist/cjs/ai-table/utils/render-mapper-fields/__tests__/index.test.tsx +399 -0
  84. package/dist/cjs/ai-table/utils/render-mapper-fields/index.d.ts +10 -0
  85. package/dist/cjs/ai-table/utils/render-mapper-fields/index.d.ts.map +1 -0
  86. package/dist/cjs/ai-table/utils/render-mapper-fields/index.js +48 -0
  87. package/dist/cjs/index.d.ts +4 -0
  88. package/dist/cjs/index.d.ts.map +1 -0
  89. package/dist/cjs/index.js +7 -0
  90. package/dist/cjs/types/index.d.ts +134 -0
  91. package/dist/cjs/types/index.d.ts.map +1 -0
  92. package/dist/cjs/types/index.js +2 -0
  93. package/dist/esm/__tests__/index.test.d.ts +2 -0
  94. package/dist/esm/__tests__/index.test.d.ts.map +1 -0
  95. package/dist/esm/__tests__/index.test.js +80 -0
  96. package/dist/esm/__tests__/index.test.tsx +94 -0
  97. package/dist/esm/ai-modal-table/__tests__/index.test.d.ts +2 -0
  98. package/dist/esm/ai-modal-table/__tests__/index.test.d.ts.map +1 -0
  99. package/dist/esm/ai-modal-table/__tests__/index.test.js +57 -0
  100. package/dist/esm/ai-modal-table/__tests__/index.test.tsx +98 -0
  101. package/dist/esm/ai-modal-table/index.d.ts +4 -0
  102. package/dist/esm/ai-modal-table/index.d.ts.map +1 -0
  103. package/dist/esm/ai-modal-table/index.js +50 -0
  104. package/dist/esm/ai-table/__tests__/index.test.d.ts +2 -0
  105. package/dist/esm/ai-table/__tests__/index.test.d.ts.map +1 -0
  106. package/dist/esm/ai-table/__tests__/index.test.js +346 -0
  107. package/dist/esm/ai-table/__tests__/index.test.tsx +572 -0
  108. package/dist/esm/ai-table/components/__tests__/content.test.d.ts +2 -0
  109. package/dist/esm/ai-table/components/__tests__/content.test.d.ts.map +1 -0
  110. package/dist/esm/ai-table/components/__tests__/content.test.js +1347 -0
  111. package/dist/esm/ai-table/components/__tests__/content.test.tsx +1637 -0
  112. package/dist/esm/ai-table/components/__tests__/filters.test.d.ts +2 -0
  113. package/dist/esm/ai-table/components/__tests__/filters.test.d.ts.map +1 -0
  114. package/dist/esm/ai-table/components/__tests__/filters.test.js +398 -0
  115. package/dist/esm/ai-table/components/__tests__/filters.test.tsx +534 -0
  116. package/dist/esm/ai-table/components/__tests__/footer.test.d.ts +2 -0
  117. package/dist/esm/ai-table/components/__tests__/footer.test.d.ts.map +1 -0
  118. package/dist/esm/ai-table/components/__tests__/footer.test.js +463 -0
  119. package/dist/esm/ai-table/components/__tests__/footer.test.tsx +597 -0
  120. package/dist/esm/ai-table/components/__tests__/mapper.test.d.ts +2 -0
  121. package/dist/esm/ai-table/components/__tests__/mapper.test.d.ts.map +1 -0
  122. package/dist/esm/ai-table/components/__tests__/mapper.test.js +451 -0
  123. package/dist/esm/ai-table/components/__tests__/mapper.test.tsx +601 -0
  124. package/dist/esm/ai-table/components/__tests__/pagination.test.d.ts +2 -0
  125. package/dist/esm/ai-table/components/__tests__/pagination.test.d.ts.map +1 -0
  126. package/dist/esm/ai-table/components/__tests__/pagination.test.js +428 -0
  127. package/dist/esm/ai-table/components/__tests__/pagination.test.tsx +629 -0
  128. package/dist/esm/ai-table/components/__tests__/row-actions.test.d.ts +2 -0
  129. package/dist/esm/ai-table/components/__tests__/row-actions.test.d.ts.map +1 -0
  130. package/dist/esm/ai-table/components/__tests__/row-actions.test.js +380 -0
  131. package/dist/esm/ai-table/components/__tests__/row-actions.test.tsx +507 -0
  132. package/dist/esm/ai-table/components/content.d.ts +11 -0
  133. package/dist/esm/ai-table/components/content.d.ts.map +1 -0
  134. package/dist/esm/ai-table/components/content.js +305 -0
  135. package/dist/esm/ai-table/components/filters.d.ts +10 -0
  136. package/dist/esm/ai-table/components/filters.d.ts.map +1 -0
  137. package/dist/esm/ai-table/components/filters.js +51 -0
  138. package/dist/esm/ai-table/components/footer.d.ts +12 -0
  139. package/dist/esm/ai-table/components/footer.d.ts.map +1 -0
  140. package/dist/esm/ai-table/components/footer.js +20 -0
  141. package/dist/esm/ai-table/components/mapper.d.ts +11 -0
  142. package/dist/esm/ai-table/components/mapper.d.ts.map +1 -0
  143. package/dist/esm/ai-table/components/mapper.js +17 -0
  144. package/dist/esm/ai-table/components/pagination.d.ts +11 -0
  145. package/dist/esm/ai-table/components/pagination.d.ts.map +1 -0
  146. package/dist/esm/ai-table/components/pagination.js +102 -0
  147. package/dist/esm/ai-table/components/row-actions.d.ts +14 -0
  148. package/dist/esm/ai-table/components/row-actions.d.ts.map +1 -0
  149. package/dist/esm/ai-table/components/row-actions.js +48 -0
  150. package/dist/esm/ai-table/constants/index.d.ts +17 -0
  151. package/dist/esm/ai-table/constants/index.d.ts.map +1 -0
  152. package/dist/esm/ai-table/constants/index.js +16 -0
  153. package/dist/esm/ai-table/i18n/index.d.ts +3 -0
  154. package/dist/esm/ai-table/i18n/index.d.ts.map +1 -0
  155. package/dist/esm/ai-table/i18n/index.js +11 -0
  156. package/dist/esm/ai-table/i18n/translations/en.d.ts +8 -0
  157. package/dist/esm/ai-table/i18n/translations/en.d.ts.map +1 -0
  158. package/dist/esm/ai-table/i18n/translations/en.js +7 -0
  159. package/dist/esm/ai-table/i18n/translations/tr.d.ts +8 -0
  160. package/dist/esm/ai-table/i18n/translations/tr.d.ts.map +1 -0
  161. package/dist/esm/ai-table/i18n/translations/tr.js +7 -0
  162. package/dist/esm/ai-table/index.d.ts +4 -0
  163. package/dist/esm/ai-table/index.d.ts.map +1 -0
  164. package/dist/esm/ai-table/index.js +67 -0
  165. package/dist/esm/ai-table/utils/data-format/__tests__/index.test.d.ts +2 -0
  166. package/dist/esm/ai-table/utils/data-format/__tests__/index.test.d.ts.map +1 -0
  167. package/dist/esm/ai-table/utils/data-format/__tests__/index.test.js +144 -0
  168. package/dist/esm/ai-table/utils/data-format/__tests__/index.test.ts +184 -0
  169. package/dist/esm/ai-table/utils/data-format/index.d.ts +7 -0
  170. package/dist/esm/ai-table/utils/data-format/index.d.ts.map +1 -0
  171. package/dist/esm/ai-table/utils/data-format/index.js +38 -0
  172. package/dist/esm/ai-table/utils/render-mapper-fields/__tests__/index.test.d.ts +2 -0
  173. package/dist/esm/ai-table/utils/render-mapper-fields/__tests__/index.test.d.ts.map +1 -0
  174. package/dist/esm/ai-table/utils/render-mapper-fields/__tests__/index.test.js +289 -0
  175. package/dist/esm/ai-table/utils/render-mapper-fields/__tests__/index.test.tsx +399 -0
  176. package/dist/esm/ai-table/utils/render-mapper-fields/index.d.ts +10 -0
  177. package/dist/esm/ai-table/utils/render-mapper-fields/index.d.ts.map +1 -0
  178. package/dist/esm/ai-table/utils/render-mapper-fields/index.js +44 -0
  179. package/dist/esm/index.d.ts +4 -0
  180. package/dist/esm/index.d.ts.map +1 -0
  181. package/dist/esm/index.js +2 -0
  182. package/dist/esm/types/index.d.ts +134 -0
  183. package/dist/esm/types/index.d.ts.map +1 -0
  184. package/dist/esm/types/index.js +1 -0
  185. package/package.json +60 -0
@@ -0,0 +1,601 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { fireEvent, render, screen } from '@testing-library/react';
3
+ import * as React from 'react';
4
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
5
+
6
+ import type { MapperRow } from '../../../types';
7
+ import { TableMapper } from '../mapper';
8
+
9
+ vi.mock('@akinon/icons', () => ({
10
+ Icon: ({ icon, size, color, className, onClick, ...props }: any) => (
11
+ <div
12
+ data-testid={`icon-${icon}`}
13
+ data-size={size}
14
+ data-color={color}
15
+ className={className}
16
+ onClick={onClick}
17
+ {...props}
18
+ >
19
+ {icon}
20
+ </div>
21
+ )
22
+ }));
23
+
24
+ vi.mock('@akinon/ui-input', () => ({
25
+ Input: ({ onChange, value, className, size, ...props }: any) => (
26
+ <input
27
+ onChange={onChange}
28
+ value={value}
29
+ className={className}
30
+ data-size={size}
31
+ data-testid={`input-${value || 'empty'}`}
32
+ {...props}
33
+ />
34
+ )
35
+ }));
36
+
37
+ vi.mock('@akinon/ui-layout', () => ({
38
+ Flex: ({ children, gap, vertical, align, rootClassName, ...props }: any) => (
39
+ <div
40
+ data-testid={vertical ? 'flex-vertical' : 'flex-horizontal'}
41
+ data-gap={gap}
42
+ data-vertical={vertical}
43
+ data-align={align}
44
+ className={rootClassName}
45
+ {...props}
46
+ >
47
+ {children}
48
+ </div>
49
+ )
50
+ }));
51
+
52
+ describe('TableMapper', () => {
53
+ const mockHandleAddItem = vi.fn();
54
+ const mockHandleRemoveItem = vi.fn(() => vi.fn());
55
+ const mockHandleItemChange = vi.fn();
56
+
57
+ const defaultValues: MapperRow[] = [
58
+ {
59
+ key: { type: 'text', value: 'key1' },
60
+ value: { type: 'text', value: 'value1' }
61
+ },
62
+ {
63
+ key: { type: 'text', value: 'key2' },
64
+ value: { type: 'text', value: 'value2' }
65
+ },
66
+ {
67
+ key: { type: 'text', value: 'key3' },
68
+ value: { type: 'text', value: 'value3' }
69
+ }
70
+ ];
71
+
72
+ const defaultProps = {
73
+ values: defaultValues,
74
+ handleAddItem: mockHandleAddItem,
75
+ handleRemoveItem: mockHandleRemoveItem,
76
+ handleItemChange: mockHandleItemChange
77
+ };
78
+
79
+ beforeEach(() => {
80
+ vi.clearAllMocks();
81
+ });
82
+
83
+ const renderComponent = (props = {}) => {
84
+ return render(
85
+ <TableMapper
86
+ values={defaultProps.values}
87
+ handleAddItem={mockHandleAddItem}
88
+ handleRemoveItem={mockHandleRemoveItem}
89
+ handleItemChange={mockHandleItemChange}
90
+ {...props}
91
+ />
92
+ );
93
+ };
94
+
95
+ describe('Rendering', () => {
96
+ it('should render Flex container with vertical layout', () => {
97
+ renderComponent();
98
+ expect(screen.getByTestId('flex-vertical')).toBeInTheDocument();
99
+ });
100
+
101
+ it('should have correct Flex props on main container', () => {
102
+ renderComponent();
103
+ const mainFlex = screen.getByTestId('flex-vertical');
104
+ expect(mainFlex).toHaveAttribute('data-gap', '5');
105
+ expect(mainFlex).toHaveAttribute('data-vertical', 'true');
106
+ });
107
+
108
+ it('should render all rows regardless of previous state', () => {
109
+ renderComponent();
110
+ const horizontalFlexes = screen.getAllByTestId('flex-horizontal');
111
+ // Should have rows (each row with items) + icon containers
112
+ expect(horizontalFlexes.length).toBeGreaterThan(0);
113
+ });
114
+
115
+ it('should render inputs for all values', () => {
116
+ renderComponent();
117
+ const inputs = screen.getAllByRole('textbox');
118
+ expect(inputs.length).toBe(6); // 3 values * 2 inputs (key + value)
119
+ });
120
+
121
+ it('should render correct number of plus/minus icons', () => {
122
+ renderComponent();
123
+ const plusIcons = screen.getAllByTestId('icon-plus');
124
+ const minusIcons = screen.getAllByTestId('icon-minus');
125
+ expect(plusIcons).toHaveLength(3); // One per row
126
+ expect(minusIcons).toHaveLength(3); // One per row
127
+ });
128
+ });
129
+
130
+ describe('All Values Display', () => {
131
+ it('should display all values from props', () => {
132
+ renderComponent();
133
+ const inputs = screen.getAllByRole('textbox');
134
+ expect(inputs).toHaveLength(6); // 3 items * 2 inputs
135
+ });
136
+
137
+ it('should display all values in correct order', () => {
138
+ renderComponent();
139
+ const inputs = screen.getAllByRole('textbox');
140
+ expect(inputs[0]).toHaveValue('key1');
141
+ expect(inputs[1]).toHaveValue('value1');
142
+ expect(inputs[2]).toHaveValue('key2');
143
+ expect(inputs[3]).toHaveValue('value2');
144
+ expect(inputs[4]).toHaveValue('key3');
145
+ expect(inputs[5]).toHaveValue('value3');
146
+ });
147
+
148
+ it('should render correct number of rows', () => {
149
+ renderComponent();
150
+ const horizontalFlexes = screen.getAllByTestId('flex-horizontal');
151
+ // Should have: 3 rows (each with items) + 3 icon containers = at least 6
152
+ expect(horizontalFlexes.length).toBeGreaterThanOrEqual(6);
153
+ });
154
+ });
155
+
156
+ describe('Single Value', () => {
157
+ it('should display single value correctly', () => {
158
+ renderComponent({
159
+ values: [
160
+ {
161
+ key: { type: 'text', value: 'singleKey' },
162
+ value: { type: 'text', value: 'singleValue' }
163
+ }
164
+ ]
165
+ });
166
+ const inputs = screen.getAllByRole('textbox');
167
+ expect(inputs).toHaveLength(2);
168
+ expect(inputs[0]).toHaveValue('singleKey');
169
+ expect(inputs[1]).toHaveValue('singleValue');
170
+ });
171
+
172
+ it('should render add/remove icons for single value', () => {
173
+ renderComponent({
174
+ values: [
175
+ {
176
+ key: { type: 'text', value: 'singleKey' },
177
+ value: { type: 'text', value: 'singleValue' }
178
+ }
179
+ ]
180
+ });
181
+ const plusIcons = screen.getAllByTestId('icon-plus');
182
+ const minusIcons = screen.getAllByTestId('icon-minus');
183
+ expect(plusIcons).toHaveLength(1);
184
+ expect(minusIcons).toHaveLength(1);
185
+ });
186
+ });
187
+
188
+ describe('Input Changes', () => {
189
+ it('should call handleItemChange when input changes', () => {
190
+ renderComponent();
191
+ const inputs = screen.getAllByRole('textbox');
192
+
193
+ fireEvent.change(inputs[0], { target: { value: 'newKey' } });
194
+
195
+ expect(mockHandleItemChange).toHaveBeenCalledWith(
196
+ expect.objectContaining({
197
+ index: 0
198
+ })
199
+ );
200
+ });
201
+
202
+ it('should call handleItemChange for value input', () => {
203
+ renderComponent();
204
+ const inputs = screen.getAllByRole('textbox');
205
+
206
+ fireEvent.change(inputs[1], { target: { value: 'newValue' } });
207
+
208
+ expect(mockHandleItemChange).toHaveBeenCalledWith(
209
+ expect.objectContaining({
210
+ index: 0
211
+ })
212
+ );
213
+ });
214
+
215
+ it('should call handleItemChange for correct item', () => {
216
+ renderComponent();
217
+ const inputs = screen.getAllByRole('textbox');
218
+
219
+ // Update second item's key (index 2)
220
+ fireEvent.change(inputs[2], { target: { value: 'newKey2' } });
221
+
222
+ expect(mockHandleItemChange).toHaveBeenCalled();
223
+ });
224
+
225
+ it('should handle empty input values', () => {
226
+ renderComponent();
227
+ const inputs = screen.getAllByRole('textbox');
228
+
229
+ fireEvent.change(inputs[0], { target: { value: '' } });
230
+
231
+ expect(mockHandleItemChange).toHaveBeenCalled();
232
+ });
233
+
234
+ it('should handle special characters in input', () => {
235
+ renderComponent();
236
+ const inputs = screen.getAllByRole('textbox');
237
+
238
+ fireEvent.change(inputs[0], { target: { value: '@#$%^&*' } });
239
+
240
+ expect(mockHandleItemChange).toHaveBeenCalled();
241
+ });
242
+ });
243
+
244
+ describe('Add Field', () => {
245
+ it('should render plus icon for each row', () => {
246
+ renderComponent();
247
+ expect(screen.getAllByTestId('icon-plus')).toHaveLength(3); // One for each row
248
+ });
249
+
250
+ it('should have correct color on plus icon', () => {
251
+ renderComponent();
252
+ const plusIcons = screen.getAllByTestId('icon-plus');
253
+ expect(plusIcons[0]).toHaveAttribute(
254
+ 'data-color',
255
+ 'var(--color-green-500)'
256
+ );
257
+ });
258
+
259
+ it('should call handleAddItem when plus icon clicked', () => {
260
+ renderComponent();
261
+ const plusIcons = screen.getAllByTestId('icon-plus');
262
+
263
+ fireEvent.click(plusIcons[0]);
264
+
265
+ expect(mockHandleAddItem).toHaveBeenCalled();
266
+ });
267
+
268
+ it('should handle multiple plus clicks', () => {
269
+ renderComponent();
270
+ const plusIcons = screen.getAllByTestId('icon-plus');
271
+
272
+ fireEvent.click(plusIcons[0]);
273
+ fireEvent.click(plusIcons[0]);
274
+
275
+ expect(mockHandleAddItem).toHaveBeenCalledTimes(2);
276
+ });
277
+
278
+ it('should handle handleAddItem undefined', () => {
279
+ renderComponent({ handleAddItem: undefined as any });
280
+ const plusIcons = screen.getAllByTestId('icon-plus');
281
+
282
+ expect(() => {
283
+ fireEvent.click(plusIcons[0]);
284
+ }).not.toThrow();
285
+ });
286
+ });
287
+
288
+ describe('Remove Field', () => {
289
+ it('should render minus icons for each row', () => {
290
+ renderComponent();
291
+ const minusIcons = screen.getAllByTestId('icon-minus');
292
+ expect(minusIcons).toHaveLength(3);
293
+ });
294
+
295
+ it('should have correct color on minus icon', () => {
296
+ renderComponent();
297
+ const minusIcons = screen.getAllByTestId('icon-minus');
298
+ expect(minusIcons[0]).toHaveAttribute(
299
+ 'data-color',
300
+ 'var(--color-red-425)'
301
+ );
302
+ });
303
+
304
+ it('should call handleRemoveItem when rendering (to get onClick)', () => {
305
+ renderComponent();
306
+
307
+ // handleRemoveItem is called during render to get the onClick handler for each row
308
+ expect(mockHandleRemoveItem).toHaveBeenCalled();
309
+ expect(mockHandleRemoveItem.mock.calls.length).toBeGreaterThanOrEqual(3);
310
+ });
311
+
312
+ it('should handle minus icon clicks without throwing', () => {
313
+ renderComponent();
314
+ const minusIcons = screen.getAllByTestId('icon-minus');
315
+
316
+ expect(() => {
317
+ fireEvent.click(minusIcons[0]);
318
+ fireEvent.click(minusIcons[1]);
319
+ }).not.toThrow();
320
+ });
321
+ });
322
+
323
+ describe('Icons', () => {
324
+ it('should have cursor-pointer class on plus and minus icons', () => {
325
+ renderComponent();
326
+ const plusIcons = screen.getAllByTestId('icon-plus');
327
+ const minusIcons = screen.getAllByTestId('icon-minus');
328
+
329
+ expect(plusIcons[0]).toHaveClass('cursor-pointer');
330
+ expect(minusIcons[0]).toHaveClass('cursor-pointer');
331
+ });
332
+
333
+ it('should have correct size on icons', () => {
334
+ renderComponent();
335
+ const plusIcons = screen.getAllByTestId('icon-plus');
336
+ const minusIcons = screen.getAllByTestId('icon-minus');
337
+
338
+ expect(plusIcons[0]).toHaveAttribute('data-size', '20');
339
+ expect(minusIcons[0]).toHaveAttribute('data-size', '20');
340
+ });
341
+ });
342
+
343
+ describe('Empty Values', () => {
344
+ it('should render with empty array', () => {
345
+ renderComponent({ values: [] });
346
+ expect(screen.getByTestId('flex-vertical')).toBeInTheDocument();
347
+ });
348
+
349
+ it('should not render any rows with empty array', () => {
350
+ renderComponent({ values: [] });
351
+ const inputs = screen.queryAllByRole('textbox');
352
+ expect(inputs).toHaveLength(0);
353
+ });
354
+ });
355
+
356
+ describe('Prop Updates', () => {
357
+ it('should use values from props', () => {
358
+ renderComponent({
359
+ values: [
360
+ {
361
+ key: { type: 'text', value: 'initialKey' },
362
+ value: { type: 'text', value: 'initialValue' }
363
+ }
364
+ ]
365
+ });
366
+
367
+ const inputs = screen.getAllByRole('textbox');
368
+ expect(inputs[0]).toHaveValue('initialKey');
369
+ expect(inputs[1]).toHaveValue('initialValue');
370
+ });
371
+
372
+ it('should render different values when props change', () => {
373
+ const { rerender } = render(
374
+ <TableMapper
375
+ values={[
376
+ {
377
+ key: { type: 'text', value: 'key1' },
378
+ value: { type: 'text', value: 'value1' }
379
+ }
380
+ ]}
381
+ handleAddItem={mockHandleAddItem}
382
+ handleRemoveItem={mockHandleRemoveItem}
383
+ handleItemChange={mockHandleItemChange}
384
+ />
385
+ );
386
+
387
+ let inputs = screen.getAllByRole('textbox');
388
+ expect(inputs).toHaveLength(2);
389
+
390
+ rerender(
391
+ <TableMapper
392
+ values={[
393
+ {
394
+ key: { type: 'text', value: 'key1' },
395
+ value: { type: 'text', value: 'value1' }
396
+ },
397
+ {
398
+ key: { type: 'text', value: 'key2' },
399
+ value: { type: 'text', value: 'value2' }
400
+ }
401
+ ]}
402
+ handleAddItem={mockHandleAddItem}
403
+ handleRemoveItem={mockHandleRemoveItem}
404
+ handleItemChange={mockHandleItemChange}
405
+ />
406
+ );
407
+
408
+ inputs = screen.getAllByRole('textbox');
409
+ expect(inputs).toHaveLength(4);
410
+ });
411
+
412
+ it('should always render all values (controlled by parent)', () => {
413
+ renderComponent({
414
+ values: [
415
+ {
416
+ key: { type: 'text', value: 'key1' },
417
+ value: { type: 'text', value: 'value1' }
418
+ },
419
+ {
420
+ key: { type: 'text', value: 'key2' },
421
+ value: { type: 'text', value: 'value2' }
422
+ },
423
+ {
424
+ key: { type: 'text', value: 'key3' },
425
+ value: { type: 'text', value: 'value3' }
426
+ }
427
+ ]
428
+ });
429
+
430
+ const inputs = screen.getAllByRole('textbox');
431
+ expect(inputs).toHaveLength(6);
432
+ });
433
+ });
434
+
435
+ describe('Integration Tests', () => {
436
+ it('should handle edit, add, and remove operations', () => {
437
+ renderComponent();
438
+
439
+ const inputs = screen.getAllByRole('textbox');
440
+
441
+ // Edit first item
442
+ fireEvent.change(inputs[0], { target: { value: 'edited1' } });
443
+ expect(mockHandleItemChange).toHaveBeenCalled();
444
+
445
+ // Add new field
446
+ const plusIcons = screen.getAllByTestId('icon-plus');
447
+ expect(() => {
448
+ fireEvent.click(plusIcons[0]);
449
+ }).not.toThrow();
450
+ expect(mockHandleAddItem).toHaveBeenCalled();
451
+
452
+ // Remove an item
453
+ const minusIcons = screen.getAllByTestId('icon-minus');
454
+ expect(() => {
455
+ fireEvent.click(minusIcons[1]);
456
+ }).not.toThrow();
457
+ });
458
+
459
+ it('should handle rapid add operations', () => {
460
+ renderComponent();
461
+
462
+ const plusIcons = screen.getAllByTestId('icon-plus');
463
+
464
+ expect(() => {
465
+ fireEvent.click(plusIcons[0]);
466
+ fireEvent.click(plusIcons[1]);
467
+ fireEvent.click(plusIcons[2]);
468
+ }).not.toThrow();
469
+ });
470
+
471
+ it('should handle rapid remove operations', () => {
472
+ renderComponent();
473
+
474
+ const minusIcons = screen.getAllByTestId('icon-minus');
475
+
476
+ expect(() => {
477
+ fireEvent.click(minusIcons[0]);
478
+ fireEvent.click(minusIcons[1]);
479
+ fireEvent.click(minusIcons[2]);
480
+ }).not.toThrow();
481
+ });
482
+
483
+ it('should render updated values after prop changes', () => {
484
+ const { rerender } = render(
485
+ <TableMapper
486
+ values={[
487
+ {
488
+ key: { type: 'text', value: 'k1' },
489
+ value: { type: 'text', value: 'v1' }
490
+ }
491
+ ]}
492
+ handleAddItem={mockHandleAddItem}
493
+ handleRemoveItem={mockHandleRemoveItem}
494
+ handleItemChange={mockHandleItemChange}
495
+ />
496
+ );
497
+
498
+ // Re-render with new values
499
+ rerender(
500
+ <TableMapper
501
+ values={[
502
+ {
503
+ key: { type: 'text', value: 'k1' },
504
+ value: { type: 'text', value: 'v1' }
505
+ },
506
+ {
507
+ key: { type: 'text', value: 'k2' },
508
+ value: { type: 'text', value: 'v2' }
509
+ }
510
+ ]}
511
+ handleAddItem={mockHandleAddItem}
512
+ handleRemoveItem={mockHandleRemoveItem}
513
+ handleItemChange={mockHandleItemChange}
514
+ />
515
+ );
516
+
517
+ const inputs = screen.getAllByRole('textbox');
518
+ expect(inputs).toHaveLength(4);
519
+ });
520
+
521
+ it('should handle very long values', () => {
522
+ const longValue = 'a'.repeat(500);
523
+ renderComponent({
524
+ values: [
525
+ {
526
+ key: { type: 'text', value: longValue },
527
+ value: { type: 'text', value: longValue }
528
+ }
529
+ ]
530
+ });
531
+
532
+ const inputs = screen.getAllByRole('textbox');
533
+ expect(inputs[0]).toHaveValue(longValue);
534
+ expect(inputs[1]).toHaveValue(longValue);
535
+ });
536
+
537
+ it('should handle unicode characters', () => {
538
+ const unicodeKey = '你好键';
539
+ const unicodeValue = '🚀 مرحبا';
540
+
541
+ renderComponent({
542
+ values: [
543
+ {
544
+ key: { type: 'text', value: unicodeKey },
545
+ value: { type: 'text', value: unicodeValue }
546
+ }
547
+ ]
548
+ });
549
+
550
+ const inputs = screen.getAllByRole('textbox');
551
+ expect(inputs[0]).toHaveValue(unicodeKey);
552
+ expect(inputs[1]).toHaveValue(unicodeValue);
553
+ });
554
+ });
555
+
556
+ describe('Edge Cases', () => {
557
+ it('should handle many items', () => {
558
+ const manyItems: MapperRow[] = Array.from({ length: 10 }, (_, i) => ({
559
+ [`key${i}`]: { type: 'text', value: `key${i}` },
560
+ [`value${i}`]: { type: 'text', value: `value${i}` }
561
+ }));
562
+
563
+ renderComponent({ values: manyItems });
564
+
565
+ const inputs = screen.getAllByRole('textbox');
566
+ expect(inputs).toHaveLength(20); // 10 items * 2 inputs
567
+ });
568
+
569
+ it('should handle many icons', () => {
570
+ const manyItems: MapperRow[] = Array.from({ length: 10 }, (_, i) => ({
571
+ [`key${i}`]: { type: 'text', value: `key${i}` },
572
+ [`value${i}`]: { type: 'text', value: `value${i}` }
573
+ }));
574
+
575
+ renderComponent({ values: manyItems });
576
+
577
+ const plusIcons = screen.getAllByTestId('icon-plus');
578
+ const minusIcons = screen.getAllByTestId('icon-minus');
579
+ expect(plusIcons).toHaveLength(10);
580
+ expect(minusIcons).toHaveLength(10);
581
+ });
582
+
583
+ it('should handle unicode characters', () => {
584
+ const unicodeKey = '你好键';
585
+ const unicodeValue = '🚀 مرحبا';
586
+
587
+ renderComponent({
588
+ values: [
589
+ {
590
+ key: { type: 'text', value: unicodeKey },
591
+ value: { type: 'text', value: unicodeValue }
592
+ }
593
+ ]
594
+ });
595
+
596
+ const inputs = screen.getAllByRole('textbox');
597
+ expect(inputs[0]).toHaveValue(unicodeKey);
598
+ expect(inputs[1]).toHaveValue(unicodeValue);
599
+ });
600
+ });
601
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pagination.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.test.d.ts","sourceRoot":"","sources":["../../../../../src/ai-table/components/__tests__/pagination.test.tsx"],"names":[],"mappings":""}