@htlkg/components 0.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.
- package/dist/composables/index.js +388 -0
- package/dist/composables/index.js.map +1 -0
- package/package.json +41 -0
- package/src/composables/index.ts +6 -0
- package/src/composables/useForm.test.ts +229 -0
- package/src/composables/useForm.ts +130 -0
- package/src/composables/useFormValidation.test.ts +189 -0
- package/src/composables/useFormValidation.ts +83 -0
- package/src/composables/useModal.property.test.ts +164 -0
- package/src/composables/useModal.ts +43 -0
- package/src/composables/useNotifications.test.ts +166 -0
- package/src/composables/useNotifications.ts +81 -0
- package/src/composables/useTable.property.test.ts +198 -0
- package/src/composables/useTable.ts +134 -0
- package/src/composables/useTabs.property.test.ts +247 -0
- package/src/composables/useTabs.ts +101 -0
- package/src/data/Chart.demo.vue +340 -0
- package/src/data/Chart.md +525 -0
- package/src/data/Chart.vue +133 -0
- package/src/data/DataList.md +80 -0
- package/src/data/DataList.test.ts +69 -0
- package/src/data/DataList.vue +46 -0
- package/src/data/SearchableSelect.md +107 -0
- package/src/data/SearchableSelect.vue +124 -0
- package/src/data/Table.demo.vue +296 -0
- package/src/data/Table.md +588 -0
- package/src/data/Table.property.test.ts +548 -0
- package/src/data/Table.test.ts +562 -0
- package/src/data/Table.unit.test.ts +544 -0
- package/src/data/Table.vue +321 -0
- package/src/data/index.ts +5 -0
- package/src/domain/BrandCard.md +81 -0
- package/src/domain/BrandCard.vue +63 -0
- package/src/domain/BrandSelector.md +84 -0
- package/src/domain/BrandSelector.vue +65 -0
- package/src/domain/ProductBadge.md +60 -0
- package/src/domain/ProductBadge.vue +47 -0
- package/src/domain/UserAvatar.md +84 -0
- package/src/domain/UserAvatar.vue +60 -0
- package/src/domain/domain-components.property.test.ts +449 -0
- package/src/domain/index.ts +4 -0
- package/src/forms/DateRange.demo.vue +273 -0
- package/src/forms/DateRange.md +337 -0
- package/src/forms/DateRange.vue +110 -0
- package/src/forms/JsonSchemaForm.demo.vue +549 -0
- package/src/forms/JsonSchemaForm.md +112 -0
- package/src/forms/JsonSchemaForm.property.test.ts +817 -0
- package/src/forms/JsonSchemaForm.test.ts +601 -0
- package/src/forms/JsonSchemaForm.unit.test.ts +801 -0
- package/src/forms/JsonSchemaForm.vue +615 -0
- package/src/forms/index.ts +3 -0
- package/src/index.ts +17 -0
- package/src/navigation/Breadcrumbs.demo.vue +142 -0
- package/src/navigation/Breadcrumbs.md +102 -0
- package/src/navigation/Breadcrumbs.test.ts +69 -0
- package/src/navigation/Breadcrumbs.vue +58 -0
- package/src/navigation/Stepper.demo.vue +337 -0
- package/src/navigation/Stepper.md +174 -0
- package/src/navigation/Stepper.vue +146 -0
- package/src/navigation/Tabs.demo.vue +293 -0
- package/src/navigation/Tabs.md +163 -0
- package/src/navigation/Tabs.test.ts +176 -0
- package/src/navigation/Tabs.vue +104 -0
- package/src/navigation/index.ts +5 -0
- package/src/overlays/Alert.demo.vue +377 -0
- package/src/overlays/Alert.md +248 -0
- package/src/overlays/Alert.test.ts +166 -0
- package/src/overlays/Alert.vue +70 -0
- package/src/overlays/Drawer.md +140 -0
- package/src/overlays/Drawer.test.ts +92 -0
- package/src/overlays/Drawer.vue +76 -0
- package/src/overlays/Modal.demo.vue +149 -0
- package/src/overlays/Modal.md +385 -0
- package/src/overlays/Modal.test.ts +128 -0
- package/src/overlays/Modal.vue +86 -0
- package/src/overlays/Notification.md +150 -0
- package/src/overlays/Notification.test.ts +96 -0
- package/src/overlays/Notification.vue +58 -0
- package/src/overlays/index.ts +4 -0
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import { nextTick } from 'vue';
|
|
4
|
+
import Table from './Table.vue';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Integration tests for Table component
|
|
8
|
+
* Tests user interactions, real-world scenarios, and component integration
|
|
9
|
+
*/
|
|
10
|
+
describe('Table integration tests', () => {
|
|
11
|
+
const mockColumns = [
|
|
12
|
+
{ name: 'ID', value: 'id' },
|
|
13
|
+
{ name: 'Name', value: 'name' },
|
|
14
|
+
{ name: 'Email', value: 'email' },
|
|
15
|
+
{ name: 'Status', value: 'status' }
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const mockItems = [
|
|
19
|
+
{ id: 1, name: 'John Doe', email: 'john@example.com', status: 'active' },
|
|
20
|
+
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', status: 'inactive' },
|
|
21
|
+
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', status: 'active' },
|
|
22
|
+
{ id: 4, name: 'Alice Williams', email: 'alice@example.com', status: 'pending' },
|
|
23
|
+
{ id: 5, name: 'Charlie Brown', email: 'charlie@example.com', status: 'active' }
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const globalStubs = {
|
|
27
|
+
uiTable: true,
|
|
28
|
+
uiPagination: true,
|
|
29
|
+
uiDropdown: true,
|
|
30
|
+
uiSmartFilterMultipleV2: true,
|
|
31
|
+
uiNoResults: true
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
describe('User List Management', () => {
|
|
35
|
+
it('should display user list with pagination', async () => {
|
|
36
|
+
const wrapper = mount(Table, {
|
|
37
|
+
props: {
|
|
38
|
+
items: mockItems,
|
|
39
|
+
columns: mockColumns,
|
|
40
|
+
currentPage: 1,
|
|
41
|
+
totalPages: 2,
|
|
42
|
+
totalItems: 5,
|
|
43
|
+
itemsPerPage: 3,
|
|
44
|
+
showPagination: true
|
|
45
|
+
},
|
|
46
|
+
global: { stubs: globalStubs }
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const vm = wrapper.vm as any;
|
|
50
|
+
expect(vm.tableItems).toHaveLength(5);
|
|
51
|
+
expect(vm.showTable).toBe(true);
|
|
52
|
+
expect(vm.showPagination).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should handle sorting by name', async () => {
|
|
56
|
+
const wrapper = mount(Table, {
|
|
57
|
+
props: {
|
|
58
|
+
items: mockItems,
|
|
59
|
+
columns: mockColumns,
|
|
60
|
+
orderedBy: '',
|
|
61
|
+
orderDirection: 'asc'
|
|
62
|
+
},
|
|
63
|
+
global: { stubs: globalStubs }
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const vm = wrapper.vm as any;
|
|
67
|
+
vm.handleOrderBy({ value: 'name', orderDirection: 'desc' });
|
|
68
|
+
await nextTick();
|
|
69
|
+
|
|
70
|
+
expect(wrapper.emitted('update:orderedBy')?.[0]).toEqual(['name']);
|
|
71
|
+
expect(wrapper.emitted('update:orderDirection')?.[0]).toEqual(['desc']);
|
|
72
|
+
expect(wrapper.emitted('order-changed')?.[0]).toEqual(['name', 'desc']);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should handle page navigation', async () => {
|
|
76
|
+
const wrapper = mount(Table, {
|
|
77
|
+
props: {
|
|
78
|
+
items: mockItems,
|
|
79
|
+
columns: mockColumns,
|
|
80
|
+
currentPage: 1,
|
|
81
|
+
totalPages: 3
|
|
82
|
+
},
|
|
83
|
+
global: { stubs: globalStubs }
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const vm = wrapper.vm as any;
|
|
87
|
+
|
|
88
|
+
// Navigate to page 2
|
|
89
|
+
vm.handleChangePage(2);
|
|
90
|
+
await nextTick();
|
|
91
|
+
|
|
92
|
+
expect(wrapper.emitted('update:currentPage')?.[0]).toEqual([2]);
|
|
93
|
+
expect(wrapper.emitted('page-changed')?.[0]).toEqual([2]);
|
|
94
|
+
|
|
95
|
+
// Navigate to page 3
|
|
96
|
+
vm.handleChangePage(3);
|
|
97
|
+
await nextTick();
|
|
98
|
+
|
|
99
|
+
expect(wrapper.emitted('update:currentPage')?.[1]).toEqual([3]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should change page size and reset to page 1', async () => {
|
|
103
|
+
const wrapper = mount(Table, {
|
|
104
|
+
props: {
|
|
105
|
+
items: mockItems,
|
|
106
|
+
columns: mockColumns,
|
|
107
|
+
currentPage: 3,
|
|
108
|
+
itemsPerPage: 10
|
|
109
|
+
},
|
|
110
|
+
global: { stubs: globalStubs }
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const vm = wrapper.vm as any;
|
|
114
|
+
vm.handleChangePageSize({ value: '25' });
|
|
115
|
+
await nextTick();
|
|
116
|
+
|
|
117
|
+
expect(wrapper.emitted('update:itemsPerPage')?.[0]).toEqual([25]);
|
|
118
|
+
expect(wrapper.emitted('update:currentPage')?.[0]).toEqual([1]);
|
|
119
|
+
expect(wrapper.emitted('items-per-page-changed')?.[0]).toEqual([25]);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('Selection Management', () => {
|
|
124
|
+
it('should select all items', async () => {
|
|
125
|
+
const wrapper = mount(Table, {
|
|
126
|
+
props: {
|
|
127
|
+
items: mockItems,
|
|
128
|
+
columns: mockColumns
|
|
129
|
+
},
|
|
130
|
+
global: { stubs: globalStubs }
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const vm = wrapper.vm as any;
|
|
134
|
+
vm.handleSelectAllItems();
|
|
135
|
+
await nextTick();
|
|
136
|
+
|
|
137
|
+
expect(vm.selectedItemIds.size).toBe(5);
|
|
138
|
+
expect(wrapper.emitted('select-all-items')).toBeDefined();
|
|
139
|
+
expect(wrapper.emitted('update:selected')).toBeDefined();
|
|
140
|
+
|
|
141
|
+
const selectedItems = wrapper.emitted('update:selected')?.[0]?.[0] as any[];
|
|
142
|
+
expect(selectedItems).toHaveLength(5);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should deselect all items', async () => {
|
|
146
|
+
const wrapper = mount(Table, {
|
|
147
|
+
props: {
|
|
148
|
+
items: mockItems,
|
|
149
|
+
columns: mockColumns
|
|
150
|
+
},
|
|
151
|
+
global: { stubs: globalStubs }
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const vm = wrapper.vm as any;
|
|
155
|
+
|
|
156
|
+
// First select all
|
|
157
|
+
vm.handleSelectAllItems();
|
|
158
|
+
await nextTick();
|
|
159
|
+
|
|
160
|
+
// Then deselect all
|
|
161
|
+
vm.handleDeselectAllItems();
|
|
162
|
+
await nextTick();
|
|
163
|
+
|
|
164
|
+
expect(vm.selectedItemIds.size).toBe(0);
|
|
165
|
+
expect(wrapper.emitted('deselect-all-items')).toBeDefined();
|
|
166
|
+
|
|
167
|
+
const selectedItems = wrapper.emitted('update:selected')?.slice(-1)[0]?.[0] as any[];
|
|
168
|
+
expect(selectedItems).toHaveLength(0);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should handle table action with selected items', async () => {
|
|
172
|
+
const wrapper = mount(Table, {
|
|
173
|
+
props: {
|
|
174
|
+
items: mockItems,
|
|
175
|
+
columns: mockColumns,
|
|
176
|
+
actions: [
|
|
177
|
+
{ name: 'Delete', id: 'delete' },
|
|
178
|
+
{ name: 'Export', id: 'export' }
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
global: { stubs: globalStubs }
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const vm = wrapper.vm as any;
|
|
185
|
+
vm.handleTableAction({ action: 'delete', items: [1, 3, 5] });
|
|
186
|
+
await nextTick();
|
|
187
|
+
|
|
188
|
+
expect(wrapper.emitted('table-action')?.[0]).toEqual([
|
|
189
|
+
{ action: 'delete', items: [1, 3, 5] }
|
|
190
|
+
]);
|
|
191
|
+
expect(vm.selectedItemIds.size).toBe(3);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should clear selection programmatically', async () => {
|
|
195
|
+
const wrapper = mount(Table, {
|
|
196
|
+
props: {
|
|
197
|
+
items: mockItems,
|
|
198
|
+
columns: mockColumns
|
|
199
|
+
},
|
|
200
|
+
global: { stubs: globalStubs }
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const vm = wrapper.vm as any;
|
|
204
|
+
|
|
205
|
+
// Select some items
|
|
206
|
+
vm.selectedItemIds = new Set([1, 2, 3]);
|
|
207
|
+
|
|
208
|
+
// Clear selection
|
|
209
|
+
vm.clearSelection();
|
|
210
|
+
await nextTick();
|
|
211
|
+
|
|
212
|
+
expect(vm.selectedItemIds.size).toBe(0);
|
|
213
|
+
expect(vm.resetSelected).toBe(true);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('Filtering and Search', () => {
|
|
218
|
+
it('should handle smart filter application', async () => {
|
|
219
|
+
const availableCategories = [
|
|
220
|
+
{
|
|
221
|
+
name: 'name',
|
|
222
|
+
label: 'Name',
|
|
223
|
+
componentType: 'uiInput' as const,
|
|
224
|
+
defaultProps: {}
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: 'status',
|
|
228
|
+
label: 'Status',
|
|
229
|
+
componentType: 'uiSelect' as const,
|
|
230
|
+
defaultProps: {}
|
|
231
|
+
}
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
const wrapper = mount(Table, {
|
|
235
|
+
props: {
|
|
236
|
+
items: mockItems,
|
|
237
|
+
columns: mockColumns,
|
|
238
|
+
availableCategories,
|
|
239
|
+
showFilters: true
|
|
240
|
+
},
|
|
241
|
+
global: { stubs: globalStubs }
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const vm = wrapper.vm as any;
|
|
245
|
+
const filters = { name: 'John', status: 'active' };
|
|
246
|
+
|
|
247
|
+
vm.handleSmartFiltersSent(filters);
|
|
248
|
+
await nextTick();
|
|
249
|
+
|
|
250
|
+
expect(vm.hasUserSearched).toBe(true);
|
|
251
|
+
expect(wrapper.emitted('smart-filters-sent')?.[0]).toEqual([filters]);
|
|
252
|
+
expect(wrapper.emitted('multiple-filters-applied')?.[0]).toEqual([filters]);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('should show search no results after filtering', async () => {
|
|
256
|
+
const wrapper = mount(Table, {
|
|
257
|
+
props: {
|
|
258
|
+
items: [],
|
|
259
|
+
columns: mockColumns,
|
|
260
|
+
loading: false
|
|
261
|
+
},
|
|
262
|
+
global: { stubs: globalStubs }
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const vm = wrapper.vm as any;
|
|
266
|
+
|
|
267
|
+
// Simulate user search
|
|
268
|
+
vm.handleSmartFiltersSent({ name: 'NonExistent' });
|
|
269
|
+
await nextTick();
|
|
270
|
+
|
|
271
|
+
expect(vm.showSearchNoResults).toBe(true);
|
|
272
|
+
expect(vm.showInitialNoResults).toBe(false);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('should clear filters', async () => {
|
|
276
|
+
const wrapper = mount(Table, {
|
|
277
|
+
props: {
|
|
278
|
+
items: mockItems,
|
|
279
|
+
columns: mockColumns
|
|
280
|
+
},
|
|
281
|
+
global: { stubs: globalStubs }
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const vm = wrapper.vm as any;
|
|
285
|
+
vm.handleSmartFiltersCleared();
|
|
286
|
+
await nextTick();
|
|
287
|
+
|
|
288
|
+
expect(wrapper.emitted('smart-filters-cleared')).toBeDefined();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('should delete individual filter', async () => {
|
|
292
|
+
const wrapper = mount(Table, {
|
|
293
|
+
props: {
|
|
294
|
+
items: mockItems,
|
|
295
|
+
columns: mockColumns
|
|
296
|
+
},
|
|
297
|
+
global: { stubs: globalStubs }
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const vm = wrapper.vm as any;
|
|
301
|
+
vm.handleSmartFilterDeleted(0);
|
|
302
|
+
await nextTick();
|
|
303
|
+
|
|
304
|
+
expect(wrapper.emitted('smart-filter-deleted')?.[0]).toEqual([0]);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
describe('Column Visibility', () => {
|
|
309
|
+
it('should hide and show columns', async () => {
|
|
310
|
+
const wrapper = mount(Table, {
|
|
311
|
+
props: {
|
|
312
|
+
items: mockItems,
|
|
313
|
+
columns: mockColumns
|
|
314
|
+
},
|
|
315
|
+
global: { stubs: globalStubs }
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
const vm = wrapper.vm as any;
|
|
319
|
+
|
|
320
|
+
// Hide column 1
|
|
321
|
+
vm.handleColumnsVisibilityChanged({ index: 1, hidden: true });
|
|
322
|
+
await nextTick();
|
|
323
|
+
|
|
324
|
+
expect(vm.hiddenColumns).toContain(1);
|
|
325
|
+
expect(vm.getHiddenColumns()).toContain(1);
|
|
326
|
+
|
|
327
|
+
// Show column 1 again
|
|
328
|
+
vm.handleColumnsVisibilityChanged({ index: 1, hidden: false });
|
|
329
|
+
await nextTick();
|
|
330
|
+
|
|
331
|
+
expect(vm.hiddenColumns).not.toContain(1);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('should handle multiple hidden columns', async () => {
|
|
335
|
+
const wrapper = mount(Table, {
|
|
336
|
+
props: {
|
|
337
|
+
items: mockItems,
|
|
338
|
+
columns: mockColumns
|
|
339
|
+
},
|
|
340
|
+
global: { stubs: globalStubs }
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
const vm = wrapper.vm as any;
|
|
344
|
+
|
|
345
|
+
// Hide multiple columns
|
|
346
|
+
vm.handleColumnsVisibilityChanged({ index: 0, hidden: true });
|
|
347
|
+
vm.handleColumnsVisibilityChanged({ index: 2, hidden: true });
|
|
348
|
+
await nextTick();
|
|
349
|
+
|
|
350
|
+
expect(vm.hiddenColumns).toHaveLength(2);
|
|
351
|
+
expect(vm.hiddenColumns).toContain(0);
|
|
352
|
+
expect(vm.hiddenColumns).toContain(2);
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
describe('Empty States', () => {
|
|
357
|
+
it('should show initial no results when no data', async () => {
|
|
358
|
+
const wrapper = mount(Table, {
|
|
359
|
+
props: {
|
|
360
|
+
items: [],
|
|
361
|
+
columns: mockColumns,
|
|
362
|
+
loading: false
|
|
363
|
+
},
|
|
364
|
+
global: { stubs: globalStubs }
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
const vm = wrapper.vm as any;
|
|
368
|
+
expect(vm.showInitialNoResults).toBe(true);
|
|
369
|
+
expect(vm.showTable).toBe(false);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it('should show loading state', async () => {
|
|
373
|
+
const wrapper = mount(Table, {
|
|
374
|
+
props: {
|
|
375
|
+
items: [],
|
|
376
|
+
columns: mockColumns,
|
|
377
|
+
loading: true
|
|
378
|
+
},
|
|
379
|
+
global: { stubs: globalStubs }
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const vm = wrapper.vm as any;
|
|
383
|
+
expect(vm.showTable).toBe(true);
|
|
384
|
+
expect(vm.showInitialNoResults).toBe(false);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('should handle no results action', async () => {
|
|
388
|
+
const wrapper = mount(Table, {
|
|
389
|
+
props: {
|
|
390
|
+
items: [],
|
|
391
|
+
columns: mockColumns,
|
|
392
|
+
loading: false,
|
|
393
|
+
noResults: {
|
|
394
|
+
title: 'No users found',
|
|
395
|
+
message: 'Create your first user',
|
|
396
|
+
actions: [{ action: 'create', text: 'Create User' }],
|
|
397
|
+
select: { name: '', value: '' }
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
global: { stubs: globalStubs }
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
const vm = wrapper.vm as any;
|
|
404
|
+
vm.handleNoResultsAction('create');
|
|
405
|
+
await nextTick();
|
|
406
|
+
|
|
407
|
+
expect(wrapper.emitted('no-results-action')?.[0]).toEqual(['create']);
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
describe('Refresh and Actions', () => {
|
|
412
|
+
it('should handle refresh action', async () => {
|
|
413
|
+
const wrapper = mount(Table, {
|
|
414
|
+
props: {
|
|
415
|
+
items: mockItems,
|
|
416
|
+
columns: mockColumns,
|
|
417
|
+
showRefresh: true
|
|
418
|
+
},
|
|
419
|
+
global: { stubs: globalStubs }
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
const vm = wrapper.vm as any;
|
|
423
|
+
vm.handleDropdownAction({ value: 'refreshData' });
|
|
424
|
+
await nextTick();
|
|
425
|
+
|
|
426
|
+
expect(wrapper.emitted('refresh:data')).toBeDefined();
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('should handle table action button click', async () => {
|
|
430
|
+
const wrapper = mount(Table, {
|
|
431
|
+
props: {
|
|
432
|
+
items: mockItems,
|
|
433
|
+
columns: mockColumns,
|
|
434
|
+
tableActionButtons: [
|
|
435
|
+
{ id: 'export', text: 'Export' },
|
|
436
|
+
{ id: 'import', text: 'Import' }
|
|
437
|
+
]
|
|
438
|
+
},
|
|
439
|
+
global: { stubs: globalStubs }
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
const vm = wrapper.vm as any;
|
|
443
|
+
vm.handleTableActionButtonClicked({ id: 'export', text: 'Export' });
|
|
444
|
+
await nextTick();
|
|
445
|
+
|
|
446
|
+
expect(wrapper.emitted('table-action-button-clicked')?.[0]).toEqual([
|
|
447
|
+
{ id: 'export', text: 'Export' }
|
|
448
|
+
]);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('should handle modal action', async () => {
|
|
452
|
+
const wrapper = mount(Table, {
|
|
453
|
+
props: {
|
|
454
|
+
items: mockItems,
|
|
455
|
+
columns: mockColumns
|
|
456
|
+
},
|
|
457
|
+
global: { stubs: globalStubs }
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const vm = wrapper.vm as any;
|
|
461
|
+
vm.handleModalAction({ modal: 'confirm-delete', action: 'confirm' });
|
|
462
|
+
await nextTick();
|
|
463
|
+
|
|
464
|
+
expect(wrapper.emitted('modal-action')?.[0]).toEqual([
|
|
465
|
+
{ modal: 'confirm-delete', action: 'confirm' }
|
|
466
|
+
]);
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
describe('State Management', () => {
|
|
471
|
+
it('should reset selection when items change', async () => {
|
|
472
|
+
const wrapper = mount(Table, {
|
|
473
|
+
props: {
|
|
474
|
+
items: mockItems,
|
|
475
|
+
columns: mockColumns
|
|
476
|
+
},
|
|
477
|
+
global: { stubs: globalStubs }
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
const vm = wrapper.vm as any;
|
|
481
|
+
vm.resetSelected = true;
|
|
482
|
+
|
|
483
|
+
// Change items
|
|
484
|
+
await wrapper.setProps({ items: mockItems.slice(0, 3) });
|
|
485
|
+
await nextTick();
|
|
486
|
+
|
|
487
|
+
expect(vm.resetSelected).toBe(false);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
it('should maintain hidden columns across updates', async () => {
|
|
491
|
+
const wrapper = mount(Table, {
|
|
492
|
+
props: {
|
|
493
|
+
items: mockItems,
|
|
494
|
+
columns: mockColumns
|
|
495
|
+
},
|
|
496
|
+
global: { stubs: globalStubs }
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
const vm = wrapper.vm as any;
|
|
500
|
+
vm.handleColumnsVisibilityChanged({ index: 1, hidden: true });
|
|
501
|
+
|
|
502
|
+
// Update items
|
|
503
|
+
await wrapper.setProps({ items: mockItems.slice(0, 2) });
|
|
504
|
+
await nextTick();
|
|
505
|
+
|
|
506
|
+
expect(vm.hiddenColumns).toContain(1);
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
describe('Complex Workflows', () => {
|
|
511
|
+
it('should handle complete user management workflow', async () => {
|
|
512
|
+
const wrapper = mount(Table, {
|
|
513
|
+
props: {
|
|
514
|
+
items: mockItems,
|
|
515
|
+
columns: mockColumns,
|
|
516
|
+
currentPage: 1,
|
|
517
|
+
totalPages: 2,
|
|
518
|
+
itemsPerPage: 3,
|
|
519
|
+
showPagination: true,
|
|
520
|
+
showFilters: true,
|
|
521
|
+
availableCategories: [
|
|
522
|
+
{
|
|
523
|
+
name: 'status',
|
|
524
|
+
label: 'Status',
|
|
525
|
+
componentType: 'uiSelect' as const,
|
|
526
|
+
defaultProps: {}
|
|
527
|
+
}
|
|
528
|
+
]
|
|
529
|
+
},
|
|
530
|
+
global: { stubs: globalStubs }
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
const vm = wrapper.vm as any;
|
|
534
|
+
|
|
535
|
+
// 1. Apply filter
|
|
536
|
+
vm.handleSmartFiltersSent({ status: 'active' });
|
|
537
|
+
await nextTick();
|
|
538
|
+
expect(wrapper.emitted('smart-filters-sent')).toBeDefined();
|
|
539
|
+
|
|
540
|
+
// 2. Sort by name
|
|
541
|
+
vm.handleOrderBy({ value: 'name', orderDirection: 'asc' });
|
|
542
|
+
await nextTick();
|
|
543
|
+
expect(wrapper.emitted('order-changed')).toBeDefined();
|
|
544
|
+
|
|
545
|
+
// 3. Select items
|
|
546
|
+
vm.handleSelectAllItems();
|
|
547
|
+
await nextTick();
|
|
548
|
+
expect(vm.selectedItemIds.size).toBeGreaterThan(0);
|
|
549
|
+
|
|
550
|
+
// 4. Perform action
|
|
551
|
+
vm.handleTableAction({ action: 'export', items: Array.from(vm.selectedItemIds) });
|
|
552
|
+
await nextTick();
|
|
553
|
+
expect(wrapper.emitted('table-action')).toBeDefined();
|
|
554
|
+
|
|
555
|
+
// 5. Change page
|
|
556
|
+
vm.handleChangePage(2);
|
|
557
|
+
await nextTick();
|
|
558
|
+
expect(wrapper.emitted('page-changed')).toBeDefined();
|
|
559
|
+
expect(vm.resetSelected).toBe(true);
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
});
|