@jasperoosthoek/react-toolbox 0.8.0 → 0.9.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/change-log.md +330 -309
- package/dist/components/buttons/ConfirmButton.d.ts +2 -2
- package/dist/components/buttons/DeleteConfirmButton.d.ts +2 -2
- package/dist/components/buttons/IconButtons.d.ts +40 -41
- package/dist/components/errors/Errors.d.ts +1 -2
- package/dist/components/forms/FormField.d.ts +22 -0
- package/dist/components/forms/FormFields.d.ts +1 -56
- package/dist/components/forms/FormModal.d.ts +7 -34
- package/dist/components/forms/FormModalProvider.d.ts +19 -26
- package/dist/components/forms/FormProvider.d.ts +66 -0
- package/dist/components/forms/fields/FormBadgesSelection.d.ts +26 -0
- package/dist/components/forms/fields/FormCheckbox.d.ts +7 -0
- package/dist/components/forms/fields/FormDropdown.d.ts +19 -0
- package/dist/components/forms/fields/FormInput.d.ts +17 -0
- package/dist/components/forms/fields/FormSelect.d.ts +12 -0
- package/dist/components/forms/fields/index.d.ts +5 -0
- package/dist/components/indicators/CheckIndicator.d.ts +1 -2
- package/dist/components/indicators/LoadingIndicator.d.ts +4 -4
- package/dist/components/login/LoginPage.d.ts +1 -1
- package/dist/components/tables/DataTable.d.ts +2 -2
- package/dist/components/tables/DragAndDropList.d.ts +2 -2
- package/dist/components/tables/SearchBox.d.ts +2 -2
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -2
- package/dist/index.js.LICENSE.txt +0 -4
- package/dist/localization/LocalizationContext.d.ts +1 -1
- package/dist/utils/hooks.d.ts +1 -1
- package/dist/utils/timeAndDate.d.ts +5 -2
- package/dist/utils/utils.d.ts +3 -3
- package/package.json +10 -11
- package/src/__tests__/buttons.test.tsx +545 -0
- package/src/__tests__/errors.test.tsx +339 -0
- package/src/__tests__/forms.test.tsx +3021 -0
- package/src/__tests__/hooks.test.tsx +413 -0
- package/src/__tests__/indicators.test.tsx +284 -0
- package/src/__tests__/localization.test.tsx +462 -0
- package/src/__tests__/login.test.tsx +417 -0
- package/src/__tests__/setupTests.ts +328 -0
- package/src/__tests__/tables.test.tsx +609 -0
- package/src/__tests__/timeAndDate.test.tsx +308 -0
- package/src/__tests__/utils.test.tsx +422 -0
- package/src/components/forms/FormField.tsx +92 -0
- package/src/components/forms/FormFields.tsx +3 -423
- package/src/components/forms/FormModal.tsx +168 -243
- package/src/components/forms/FormModalProvider.tsx +141 -95
- package/src/components/forms/FormProvider.tsx +218 -0
- package/src/components/forms/fields/FormBadgesSelection.tsx +108 -0
- package/src/components/forms/fields/FormCheckbox.tsx +76 -0
- package/src/components/forms/fields/FormDropdown.tsx +123 -0
- package/src/components/forms/fields/FormInput.tsx +114 -0
- package/src/components/forms/fields/FormSelect.tsx +47 -0
- package/src/components/forms/fields/index.ts +6 -0
- package/src/index.ts +32 -28
- package/src/localization/LocalizationContext.tsx +156 -131
- package/src/localization/localization.ts +131 -131
- package/src/utils/hooks.ts +108 -94
- package/src/utils/timeAndDate.ts +33 -4
- package/src/utils/utils.ts +74 -66
- package/dist/components/forms/CreateEditModal.d.ts +0 -41
- package/dist/components/forms/CreateEditModalProvider.d.ts +0 -41
- package/dist/components/forms/FormFields.test.d.ts +0 -4
- package/dist/login/Login.d.ts +0 -70
- package/src/components/forms/FormFields.test.tsx +0 -107
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react';
|
|
3
|
+
import { LocalizationProvider } from '../localization/LocalizationContext';
|
|
4
|
+
import { DataTable } from '../components/tables/DataTable';
|
|
5
|
+
import { DragAndDropList } from '../components/tables/DragAndDropList';
|
|
6
|
+
import { SearchBox } from '../components/tables/SearchBox';
|
|
7
|
+
|
|
8
|
+
// Mock react-dnd for testing
|
|
9
|
+
jest.mock('react-dnd', () => ({
|
|
10
|
+
DndProvider: ({ children }: { children: React.ReactNode }) => <div data-testid="dnd-provider">{children}</div>,
|
|
11
|
+
useDrag: () => [{ isDragging: false }, (ref: any) => ref, (ref: any) => ref],
|
|
12
|
+
useDrop: () => [{ isOver: false, handlerId: 'test-handler' }, (ref: any) => ref]
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
// Test wrapper with localization context
|
|
16
|
+
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
|
17
|
+
<LocalizationProvider>
|
|
18
|
+
{children}
|
|
19
|
+
</LocalizationProvider>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
describe('Table Components Tests', () => {
|
|
23
|
+
// Mock data for testing
|
|
24
|
+
const mockData = [
|
|
25
|
+
{ id: 1, name: 'John Doe', email: 'john@example.com', age: 30 },
|
|
26
|
+
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', age: 25 },
|
|
27
|
+
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', age: 35 },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const mockColumns = [
|
|
31
|
+
{ name: 'Name', selector: 'name' },
|
|
32
|
+
{ name: 'Email', selector: 'email' },
|
|
33
|
+
{ name: 'Age', selector: 'age' },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
describe('SearchBox', () => {
|
|
37
|
+
const mockOnChange = jest.fn();
|
|
38
|
+
const mockOnClear = jest.fn();
|
|
39
|
+
const mockOnSearch = jest.fn();
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should render SearchBox without crashing', () => {
|
|
46
|
+
const { getByRole } = render(
|
|
47
|
+
<TestWrapper>
|
|
48
|
+
<SearchBox
|
|
49
|
+
value=""
|
|
50
|
+
onChange={mockOnChange}
|
|
51
|
+
/>
|
|
52
|
+
</TestWrapper>
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const searchInput = getByRole('textbox');
|
|
56
|
+
expect(searchInput).toBeInTheDocument();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should handle search input changes', () => {
|
|
60
|
+
const { getByRole } = render(
|
|
61
|
+
<TestWrapper>
|
|
62
|
+
<SearchBox
|
|
63
|
+
value=""
|
|
64
|
+
onChange={mockOnChange}
|
|
65
|
+
/>
|
|
66
|
+
</TestWrapper>
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const searchInput = getByRole('textbox');
|
|
70
|
+
fireEvent.change(searchInput, { target: { value: 'test' } });
|
|
71
|
+
|
|
72
|
+
expect(mockOnChange).toHaveBeenCalledWith('test');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should handle clear functionality', () => {
|
|
76
|
+
const { getByRole } = render(
|
|
77
|
+
<TestWrapper>
|
|
78
|
+
<SearchBox
|
|
79
|
+
value="test"
|
|
80
|
+
onChange={mockOnChange}
|
|
81
|
+
onClear={mockOnClear}
|
|
82
|
+
/>
|
|
83
|
+
</TestWrapper>
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const searchInput = getByRole('textbox');
|
|
87
|
+
expect(searchInput).toHaveValue('test');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should handle search functionality', () => {
|
|
91
|
+
const { getByRole } = render(
|
|
92
|
+
<TestWrapper>
|
|
93
|
+
<SearchBox
|
|
94
|
+
value="test"
|
|
95
|
+
onChange={mockOnChange}
|
|
96
|
+
onSearch={mockOnSearch}
|
|
97
|
+
/>
|
|
98
|
+
</TestWrapper>
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const searchInput = getByRole('textbox');
|
|
102
|
+
fireEvent.keyDown(searchInput, { key: 'Enter', code: 'Enter' });
|
|
103
|
+
|
|
104
|
+
// The SearchBox might not have onSearch implemented, so just check it doesn't crash
|
|
105
|
+
expect(searchInput).toBeInTheDocument();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('DataTable', () => {
|
|
110
|
+
it('should render DataTable without crashing', () => {
|
|
111
|
+
expect(() => {
|
|
112
|
+
render(
|
|
113
|
+
<TestWrapper>
|
|
114
|
+
<DataTable data={mockData} columns={mockColumns} />
|
|
115
|
+
</TestWrapper>
|
|
116
|
+
);
|
|
117
|
+
}).not.toThrow();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should render table with correct data', () => {
|
|
121
|
+
const { getByText } = render(
|
|
122
|
+
<TestWrapper>
|
|
123
|
+
<DataTable data={mockData} columns={mockColumns} />
|
|
124
|
+
</TestWrapper>
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
expect(getByText('John Doe')).toBeInTheDocument();
|
|
128
|
+
expect(getByText('jane@example.com')).toBeInTheDocument();
|
|
129
|
+
expect(getByText('35')).toBeInTheDocument();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should handle empty data', () => {
|
|
133
|
+
const { container } = render(
|
|
134
|
+
<TestWrapper>
|
|
135
|
+
<DataTable data={[]} columns={mockColumns} />
|
|
136
|
+
</TestWrapper>
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const rows = container.querySelectorAll('tbody tr');
|
|
140
|
+
// DataTable shows a "No information to display" row when empty
|
|
141
|
+
expect(rows.length).toBeGreaterThanOrEqual(0);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should handle row selection', () => {
|
|
145
|
+
const mockOnClickRow = jest.fn();
|
|
146
|
+
const { container } = render(
|
|
147
|
+
<TestWrapper>
|
|
148
|
+
<DataTable
|
|
149
|
+
data={mockData}
|
|
150
|
+
columns={mockColumns}
|
|
151
|
+
onClickRow={mockOnClickRow}
|
|
152
|
+
/>
|
|
153
|
+
</TestWrapper>
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const firstRow = container.querySelector('tbody tr');
|
|
157
|
+
if (firstRow) {
|
|
158
|
+
fireEvent.click(firstRow);
|
|
159
|
+
expect(mockOnClickRow).toHaveBeenCalledWith(mockData[0]);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should handle custom column rendering', () => {
|
|
164
|
+
const customColumns = [
|
|
165
|
+
{ name: 'Name', selector: 'name' },
|
|
166
|
+
{
|
|
167
|
+
name: 'Custom',
|
|
168
|
+
selector: (row: any) => `Custom: ${row.name}`,
|
|
169
|
+
className: 'custom-column'
|
|
170
|
+
}
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
const { getByText } = render(
|
|
174
|
+
<TestWrapper>
|
|
175
|
+
<DataTable data={mockData} columns={customColumns} />
|
|
176
|
+
</TestWrapper>
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
expect(getByText('Custom: John Doe')).toBeInTheDocument();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('should handle search functionality', () => {
|
|
183
|
+
const { container } = render(
|
|
184
|
+
<TestWrapper>
|
|
185
|
+
<DataTable
|
|
186
|
+
data={mockData}
|
|
187
|
+
columns={mockColumns}
|
|
188
|
+
showHeader={{ search: true }}
|
|
189
|
+
filterColumn="name"
|
|
190
|
+
/>
|
|
191
|
+
</TestWrapper>
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const searchInput = container.querySelector('input[type="text"]');
|
|
195
|
+
expect(searchInput).toBeInTheDocument();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should handle pagination', () => {
|
|
199
|
+
const largeData = Array(15).fill(null).map((_, i) => ({
|
|
200
|
+
id: i + 1,
|
|
201
|
+
name: `User ${i + 1}`,
|
|
202
|
+
email: `user${i + 1}@example.com`,
|
|
203
|
+
age: 20 + i
|
|
204
|
+
}));
|
|
205
|
+
|
|
206
|
+
const { container } = render(
|
|
207
|
+
<TestWrapper>
|
|
208
|
+
<DataTable
|
|
209
|
+
data={largeData}
|
|
210
|
+
columns={mockColumns}
|
|
211
|
+
rowsPerPage={5}
|
|
212
|
+
/>
|
|
213
|
+
</TestWrapper>
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
const rows = container.querySelectorAll('tbody tr');
|
|
217
|
+
expect(rows.length).toBeLessThanOrEqual(5);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should handle custom header content', () => {
|
|
221
|
+
const customHeader = <div data-testid="custom-header">Custom Header</div>;
|
|
222
|
+
const { getByTestId } = render(
|
|
223
|
+
<TestWrapper>
|
|
224
|
+
<DataTable
|
|
225
|
+
data={mockData}
|
|
226
|
+
columns={mockColumns}
|
|
227
|
+
showHeader={{ customHeader }}
|
|
228
|
+
/>
|
|
229
|
+
</TestWrapper>
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
expect(getByTestId('custom-header')).toBeInTheDocument();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('should handle sum calculations', () => {
|
|
236
|
+
const columnsWithSum = [
|
|
237
|
+
{ name: 'Name', selector: 'name' },
|
|
238
|
+
{
|
|
239
|
+
name: 'Age',
|
|
240
|
+
selector: 'age',
|
|
241
|
+
value: (row: any) => row.age
|
|
242
|
+
}
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
const { container } = render(
|
|
246
|
+
<TestWrapper>
|
|
247
|
+
<DataTable
|
|
248
|
+
data={mockData}
|
|
249
|
+
columns={columnsWithSum}
|
|
250
|
+
showSum={true}
|
|
251
|
+
/>
|
|
252
|
+
</TestWrapper>
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
const table = container.querySelector('table');
|
|
256
|
+
expect(table).toBeInTheDocument();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should handle loading states', () => {
|
|
260
|
+
const { container } = render(
|
|
261
|
+
<TestWrapper>
|
|
262
|
+
<DataTable
|
|
263
|
+
data={mockData}
|
|
264
|
+
columns={mockColumns}
|
|
265
|
+
loading={true}
|
|
266
|
+
/>
|
|
267
|
+
</TestWrapper>
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
const table = container.querySelector('table');
|
|
271
|
+
expect(table).toBeInTheDocument();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should handle different data types', () => {
|
|
275
|
+
const mixedData = [
|
|
276
|
+
{ id: 1, name: 'John', active: true, score: 95.5 },
|
|
277
|
+
{ id: 2, name: 'Jane', active: false, score: 87.2 },
|
|
278
|
+
{ id: 3, name: 'Bob', active: true, score: 92.1 }
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
const mixedColumns = [
|
|
282
|
+
{ name: 'ID', selector: 'id' },
|
|
283
|
+
{ name: 'Name', selector: 'name' },
|
|
284
|
+
{ name: 'Active', selector: (row: any) => row.active ? 'Yes' : 'No' },
|
|
285
|
+
{ name: 'Score', selector: 'score' }
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
const { container } = render(
|
|
289
|
+
<TestWrapper>
|
|
290
|
+
<DataTable data={mixedData} columns={mixedColumns} />
|
|
291
|
+
</TestWrapper>
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
const rows = container.querySelectorAll('tbody tr');
|
|
295
|
+
expect(rows).toHaveLength(3);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe('Filtering and Search', () => {
|
|
299
|
+
it('should filter data based on search input', () => {
|
|
300
|
+
const { getByRole, queryByText } = render(
|
|
301
|
+
<TestWrapper>
|
|
302
|
+
<DataTable
|
|
303
|
+
data={mockData}
|
|
304
|
+
columns={mockColumns}
|
|
305
|
+
showHeader={{ search: true }}
|
|
306
|
+
filterColumn="name"
|
|
307
|
+
/>
|
|
308
|
+
</TestWrapper>
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
const searchInput = getByRole('textbox');
|
|
312
|
+
fireEvent.change(searchInput, { target: { value: 'John' } });
|
|
313
|
+
|
|
314
|
+
expect(queryByText('John Doe')).toBeInTheDocument();
|
|
315
|
+
expect(queryByText('Jane Smith')).not.toBeInTheDocument();
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('should handle function-based filter column', () => {
|
|
319
|
+
const filterFn = (row: any) => `${row.name} ${row.email}`;
|
|
320
|
+
const { getByRole, queryByText } = render(
|
|
321
|
+
<TestWrapper>
|
|
322
|
+
<DataTable
|
|
323
|
+
data={mockData}
|
|
324
|
+
columns={mockColumns}
|
|
325
|
+
showHeader={{ search: true }}
|
|
326
|
+
filterColumn={filterFn}
|
|
327
|
+
/>
|
|
328
|
+
</TestWrapper>
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
const searchInput = getByRole('textbox');
|
|
332
|
+
fireEvent.change(searchInput, { target: { value: 'jane@example' } });
|
|
333
|
+
|
|
334
|
+
expect(queryByText('Jane Smith')).toBeInTheDocument();
|
|
335
|
+
expect(queryByText('John Doe')).not.toBeInTheDocument();
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('should handle multiple filter columns', () => {
|
|
339
|
+
const { getByRole, queryByText } = render(
|
|
340
|
+
<TestWrapper>
|
|
341
|
+
<DataTable
|
|
342
|
+
data={mockData}
|
|
343
|
+
columns={mockColumns}
|
|
344
|
+
showHeader={{ search: true }}
|
|
345
|
+
filterColumn={['name', 'email']}
|
|
346
|
+
/>
|
|
347
|
+
</TestWrapper>
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
const searchInput = getByRole('textbox');
|
|
351
|
+
fireEvent.change(searchInput, { target: { value: 'bob' } });
|
|
352
|
+
|
|
353
|
+
expect(queryByText('Bob Johnson')).toBeInTheDocument();
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
describe('Sorting', () => {
|
|
358
|
+
it('should handle column header clicks', () => {
|
|
359
|
+
const { getByText, container } = render(
|
|
360
|
+
<TestWrapper>
|
|
361
|
+
<DataTable data={mockData} columns={mockColumns} />
|
|
362
|
+
</TestWrapper>
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
const nameHeader = getByText('Name');
|
|
366
|
+
|
|
367
|
+
expect(() => {
|
|
368
|
+
fireEvent.click(nameHeader);
|
|
369
|
+
}).not.toThrow();
|
|
370
|
+
|
|
371
|
+
const rows = container.querySelectorAll('tbody tr');
|
|
372
|
+
expect(rows).toHaveLength(3);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('should handle multiple clicks on column headers', () => {
|
|
376
|
+
const { getByText, container } = render(
|
|
377
|
+
<TestWrapper>
|
|
378
|
+
<DataTable data={mockData} columns={mockColumns} />
|
|
379
|
+
</TestWrapper>
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
const nameHeader = getByText('Name');
|
|
383
|
+
|
|
384
|
+
expect(() => {
|
|
385
|
+
fireEvent.click(nameHeader);
|
|
386
|
+
fireEvent.click(nameHeader);
|
|
387
|
+
}).not.toThrow();
|
|
388
|
+
|
|
389
|
+
const rows = container.querySelectorAll('tbody tr');
|
|
390
|
+
expect(rows).toHaveLength(3);
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
describe('Advanced Features', () => {
|
|
395
|
+
it('should handle drag and drop', () => {
|
|
396
|
+
const mockOnMove = jest.fn();
|
|
397
|
+
|
|
398
|
+
expect(() => {
|
|
399
|
+
render(
|
|
400
|
+
<TestWrapper>
|
|
401
|
+
<DataTable
|
|
402
|
+
data={mockData}
|
|
403
|
+
columns={mockColumns}
|
|
404
|
+
onMove={mockOnMove}
|
|
405
|
+
moveId="id"
|
|
406
|
+
/>
|
|
407
|
+
</TestWrapper>
|
|
408
|
+
);
|
|
409
|
+
}).not.toThrow();
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('should handle column options dropdown', () => {
|
|
413
|
+
const mockOnSelect = jest.fn();
|
|
414
|
+
const columnsWithDropdown = [
|
|
415
|
+
{
|
|
416
|
+
name: 'Status',
|
|
417
|
+
selector: 'status',
|
|
418
|
+
optionsDropdown: {
|
|
419
|
+
onSelect: mockOnSelect,
|
|
420
|
+
selected: 'active',
|
|
421
|
+
options: {
|
|
422
|
+
all: 'All',
|
|
423
|
+
active: 'Active',
|
|
424
|
+
inactive: 'Inactive'
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
];
|
|
429
|
+
|
|
430
|
+
const dataWithStatus = mockData.map(item => ({ ...item, status: 'active' }));
|
|
431
|
+
|
|
432
|
+
const { container } = render(
|
|
433
|
+
<TestWrapper>
|
|
434
|
+
<DataTable data={dataWithStatus} columns={columnsWithDropdown} />
|
|
435
|
+
</TestWrapper>
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
const table = container.querySelector('table');
|
|
439
|
+
expect(table).toBeInTheDocument();
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it('should handle rows per page selector', () => {
|
|
443
|
+
const { getByText } = render(
|
|
444
|
+
<TestWrapper>
|
|
445
|
+
<DataTable
|
|
446
|
+
data={mockData}
|
|
447
|
+
columns={mockColumns}
|
|
448
|
+
showHeader={{ numberOfRows: true }}
|
|
449
|
+
rowsPerPageOptions={[5, 10, 20]}
|
|
450
|
+
/>
|
|
451
|
+
</TestWrapper>
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
expect(getByText('Number of rows')).toBeInTheDocument();
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
it('should handle pagination display', () => {
|
|
458
|
+
const largeData = Array(25).fill(null).map((_, i) => ({
|
|
459
|
+
id: i + 1,
|
|
460
|
+
name: `User ${i + 1}`,
|
|
461
|
+
email: `user${i + 1}@example.com`,
|
|
462
|
+
age: 20 + (i % 30)
|
|
463
|
+
}));
|
|
464
|
+
|
|
465
|
+
const { getByText } = render(
|
|
466
|
+
<TestWrapper>
|
|
467
|
+
<DataTable
|
|
468
|
+
data={largeData}
|
|
469
|
+
columns={mockColumns}
|
|
470
|
+
showHeader={{ pagination: true }}
|
|
471
|
+
rowsPerPage={10}
|
|
472
|
+
/>
|
|
473
|
+
</TestWrapper>
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
expect(getByText('1')).toBeInTheDocument();
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
describe('DragAndDropList', () => {
|
|
482
|
+
it('should render DragAndDropList without crashing', () => {
|
|
483
|
+
const TestItem = React.forwardRef<HTMLDivElement, { name: string }>(
|
|
484
|
+
({ name, ...props }, ref) => <div ref={ref} {...props}>{name}</div>
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
expect(() => {
|
|
488
|
+
render(
|
|
489
|
+
<TestWrapper>
|
|
490
|
+
<DragAndDropList
|
|
491
|
+
propsArray={mockData}
|
|
492
|
+
onDrop={() => {}}
|
|
493
|
+
component={TestItem}
|
|
494
|
+
/>
|
|
495
|
+
</TestWrapper>
|
|
496
|
+
);
|
|
497
|
+
}).not.toThrow();
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it('should handle drag and drop functionality', () => {
|
|
501
|
+
const mockOnDrop = jest.fn();
|
|
502
|
+
const TestItem = React.forwardRef<HTMLDivElement, { name: string }>(
|
|
503
|
+
({ name, ...props }, ref) => <div ref={ref} {...props}>{name}</div>
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
const { getByText } = render(
|
|
507
|
+
<TestWrapper>
|
|
508
|
+
<DragAndDropList
|
|
509
|
+
propsArray={mockData}
|
|
510
|
+
onDrop={mockOnDrop}
|
|
511
|
+
component={TestItem}
|
|
512
|
+
/>
|
|
513
|
+
</TestWrapper>
|
|
514
|
+
);
|
|
515
|
+
|
|
516
|
+
// Check if the first item is rendered
|
|
517
|
+
expect(getByText('John Doe')).toBeInTheDocument();
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
it('should handle empty data', () => {
|
|
521
|
+
const TestItem = React.forwardRef<HTMLDivElement, { name: string }>(
|
|
522
|
+
({ name, ...props }, ref) => <div ref={ref} {...props}>{name}</div>
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
const { container } = render(
|
|
526
|
+
<TestWrapper>
|
|
527
|
+
<DragAndDropList
|
|
528
|
+
propsArray={[]}
|
|
529
|
+
onDrop={() => {}}
|
|
530
|
+
component={TestItem}
|
|
531
|
+
/>
|
|
532
|
+
</TestWrapper>
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
// Component should render even with empty data
|
|
536
|
+
expect(container).toBeInTheDocument();
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
it('should handle custom item rendering', () => {
|
|
540
|
+
const customRender = React.forwardRef<HTMLDivElement, any>(
|
|
541
|
+
(props, ref) => (
|
|
542
|
+
<div ref={ref} data-testid={`item-${props.id}`} className="custom-item" {...props}>
|
|
543
|
+
{props.name} - {props.email}
|
|
544
|
+
</div>
|
|
545
|
+
)
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
const { getByTestId } = render(
|
|
549
|
+
<TestWrapper>
|
|
550
|
+
<DragAndDropList
|
|
551
|
+
propsArray={mockData}
|
|
552
|
+
onDrop={() => {}}
|
|
553
|
+
component={customRender}
|
|
554
|
+
/>
|
|
555
|
+
</TestWrapper>
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
// Check if the custom rendered items are present
|
|
559
|
+
expect(getByTestId('item-1')).toBeInTheDocument();
|
|
560
|
+
expect(getByTestId('item-1')).toHaveTextContent('John Doe - john@example.com');
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
it('should handle loading state', () => {
|
|
564
|
+
const TestItem = React.forwardRef<HTMLDivElement, { name: string }>(
|
|
565
|
+
({ name, ...props }, ref) => <div ref={ref} {...props}>{name}</div>
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
const { container } = render(
|
|
569
|
+
<TestWrapper>
|
|
570
|
+
<DragAndDropList
|
|
571
|
+
propsArray={mockData}
|
|
572
|
+
onDrop={() => {}}
|
|
573
|
+
component={TestItem}
|
|
574
|
+
/>
|
|
575
|
+
</TestWrapper>
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
// Component should render even in loading state
|
|
579
|
+
expect(container).toBeInTheDocument();
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it('should handle disabled state', () => {
|
|
583
|
+
const TestItem = React.forwardRef<HTMLDivElement, { name: string }>(
|
|
584
|
+
({ name, ...props }, ref) => <div ref={ref} {...props}>{name}</div>
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
const { container } = render(
|
|
588
|
+
<TestWrapper>
|
|
589
|
+
<DragAndDropList
|
|
590
|
+
propsArray={mockData}
|
|
591
|
+
onDrop={() => {}}
|
|
592
|
+
component={TestItem}
|
|
593
|
+
/>
|
|
594
|
+
</TestWrapper>
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
// Component should render even when disabled
|
|
598
|
+
expect(container).toBeInTheDocument();
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
describe('Component Export Verification', () => {
|
|
603
|
+
it('should export all table components as functions', () => {
|
|
604
|
+
expect(typeof DataTable).toBe('function');
|
|
605
|
+
expect(typeof DragAndDropList).toBe('function');
|
|
606
|
+
expect(typeof SearchBox).toBe('function');
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
});
|