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