ywana-core8 0.1.103 → 0.2.2
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/index.css +4941 -324
- package/dist/index.js +42339 -0
- package/dist/index.js.map +1 -0
- package/dist/index.modern.js +37459 -31678
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +39635 -34010
- package/dist/index.umd.js.map +1 -1
- package/package.json +26 -29
- package/src/Test.stories.jsx +28 -0
- package/src/desktop/Desktop.stories.jsx +110 -0
- package/src/desktop/WindowContext.js +135 -0
- package/src/desktop/WindowManager.js +355 -0
- package/src/desktop/desktop.css +55 -4
- package/src/desktop/desktop.js +312 -6
- package/src/desktop/index.js +7 -0
- package/src/desktop/window.css +229 -36
- package/src/desktop/window.js +255 -20
- package/src/desktop.backup/desktop.css +6 -0
- package/src/desktop.backup/desktop.js +13 -0
- package/src/desktop.backup/window.css +58 -0
- package/src/desktop.backup/window.js +27 -0
- package/src/html/Accordion.stories.jsx +178 -0
- package/src/html/Button.stories.jsx +175 -0
- package/src/html/Checkbox.stories.jsx +131 -0
- package/src/html/Chip.stories.jsx +189 -0
- package/src/html/Color.stories.jsx +234 -0
- package/src/html/Form.stories.jsx +271 -0
- package/src/html/Icon.stories.jsx +233 -0
- package/src/html/Progress.stories.jsx +247 -0
- package/src/html/Radio.stories.jsx +289 -0
- package/src/html/StyleTest.stories.jsx +81 -0
- package/src/html/Switch.stories.jsx +329 -0
- package/src/html/Tab.stories.jsx +239 -0
- package/src/html/Table.stories.jsx +188 -0
- package/src/html/Table2.stories.jsx +238 -0
- package/src/html/TextField2.stories.jsx +337 -0
- package/src/html/Tree.stories.jsx +285 -0
- package/src/html/accordion.example.js +0 -74
- package/src/html/accordion.js +1 -6
- package/src/html/button.js +2 -13
- package/src/html/checkbox.js +1 -9
- package/src/html/chip.js +2 -19
- package/src/html/color.js +1 -14
- package/src/html/form.js +4 -15
- package/src/html/header2.js +1 -12
- package/src/html/icon.js +1 -7
- package/src/html/index.js +1 -1
- package/src/html/list.js +1 -19
- package/src/html/menu.js +9 -5
- package/src/html/progress.js +5 -53
- package/src/html/property.js +9 -25
- package/src/html/radio.js +2 -16
- package/src/html/section.js +1 -6
- package/src/html/selector.js +2 -19
- package/src/html/switch.css +134 -100
- package/src/html/switch.example.js +46 -36
- package/src/html/switch.js +43 -192
- package/src/html/tab.js +3 -24
- package/src/html/text.js +1 -12
- package/src/html/textfield2.js +5 -42
- package/src/html/thumbnail.js +1 -12
- package/src/html/tokenfield.js +2 -21
- package/src/html/tree.js +3 -35
- package/src/index.js +1 -0
- package/__previewjs__/Wrapper.tsx +0 -14
- package/build-doc.sh +0 -10
- package/db/db.json +0 -89
- package/db/routes.json +0 -0
- package/dist/index.cjs +0 -36722
- package/dist/index.cjs.map +0 -1
- package/dist/index.css.map +0 -1
- package/doc/README.md +0 -196
- package/doc/evalulations/ACCORDION_EVALUATION.md +0 -583
- package/doc/evalulations/CHECKBOX_EVALUATION.md +0 -273
- package/doc/evalulations/CHIP_EVALUATION.md +0 -542
- package/doc/evalulations/COLOR_EVALUATION.md +0 -524
- package/doc/evalulations/COMPONENTS_EVALUATION.md +0 -477
- package/doc/evalulations/FORM_EVALUATION.md +0 -459
- package/doc/evalulations/HEADER_EVALUATION.md +0 -436
- package/doc/evalulations/ICON_EVALUATION.md +0 -254
- package/doc/evalulations/LIST_EVALUATION.md +0 -574
- package/doc/evalulations/PROGRESS_EVALUATION.md +0 -450
- package/doc/evalulations/RADIO_EVALUATION.md +0 -439
- package/doc/evalulations/RADIO_VISUAL_FIX.md +0 -183
- package/doc/evalulations/SECTION_IMPROVEMENTS.md +0 -153
- package/doc/evalulations/SWITCH_EVALUATION.md +0 -335
- package/doc/evalulations/SWITCH_VISUAL_FIX.md +0 -232
- package/doc/evalulations/TAB_EVALUATION.md +0 -626
- package/doc/evalulations/TEXTFIELD_EVALUATION.md +0 -747
- package/doc/evalulations/TOOLTIP_FIX.md +0 -157
- package/doc/evalulations/TREE_EVALUATION.md +0 -708
- package/doc/index.html +0 -0
- package/doc/package-lock.json +0 -17298
- package/doc/package.json +0 -34
- package/doc/public/index.html +0 -24
- package/doc/scripts/generate-examples.js +0 -129
- package/doc/src/App.css +0 -171
- package/doc/src/App.js +0 -114
- package/doc/src/components/ExamplePage.js +0 -129
- package/doc/src/components/WelcomePage.js +0 -84
- package/doc/src/index.css +0 -246
- package/doc/src/index.js +0 -17
- package/doc/src/theme.css +0 -256
- package/jest.config.js +0 -24
- package/preview.config.js +0 -38
- package/publish.sh +0 -6
- package/src/desktop/dektop.test.js +0 -11
- package/src/domain/CollectionAPI.test.js +0 -19
- package/src/domain/ContentEditor.test.js +0 -52
- package/src/domain2/CollectionAPI.test.js +0 -19
- package/src/domain2/CollectionContext.test.js +0 -71
- package/src/domain2/CollectionPage.test.js +0 -112
- package/src/domain2/DynamicForm.test.js +0 -47
- package/src/html/accordion.test.js +0 -37
- package/src/html/accordion.unit.test.js +0 -334
- package/src/html/button.example.new.js +0 -416
- package/src/html/button.test.js +0 -422
- package/src/html/checkbox.test.js +0 -285
- package/src/html/chip.test.js +0 -425
- package/src/html/color.example.js.backup +0 -527
- package/src/html/color.test.js +0 -377
- package/src/html/components.example.js.backup +0 -492
- package/src/html/components_enhanced.test.js +0 -581
- package/src/html/form.example.js.backup +0 -385
- package/src/html/form.test.js +0 -369
- package/src/html/header2.example.js.backup +0 -411
- package/src/html/header2.test.js +0 -377
- package/src/html/icon.example.js.backup +0 -268
- package/src/html/icon.test.js +0 -231
- package/src/html/label.test.js +0 -0
- package/src/html/list.example.js.backup +0 -404
- package/src/html/list.test.js +0 -383
- package/src/html/progress.example.js.backup +0 -424
- package/src/html/progress.test.js +0 -313
- package/src/html/property.example.js.backup +0 -553
- package/src/html/property.test.js +0 -371
- package/src/html/radio.example.js.backup +0 -389
- package/src/html/radio.test.js +0 -318
- package/src/html/section.example.js.backup +0 -99
- package/src/html/section.test.js +0 -131
- package/src/html/selector.test.js +0 -20
- package/src/html/switch.example.js.backup +0 -461
- package/src/html/switch.test.js +0 -355
- package/src/html/tab.example.js.backup +0 -446
- package/src/html/tab.test.js +0 -25
- package/src/html/tab_enhanced.test.js +0 -504
- package/src/html/table.test.js +0 -70
- package/src/html/table2.test.js +0 -582
- package/src/html/text.test.js +0 -15
- package/src/html/textfield.test.js +0 -51
- package/src/html/textfield2.example.js.backup +0 -1370
- package/src/html/textfield2.test.js +0 -950
- package/src/html/tokenfield.example.js.backup +0 -503
- package/src/html/tokenfield.test.js +0 -423
- package/src/html/tree.example.js.backup +0 -475
- package/src/html/tree.test.js +0 -43
- package/src/html/tree_enhanced.test.js +0 -495
- package/src/http/token.test.js +0 -50
- package/src/incubator/pdfViewer.js +0 -33
- package/src/incubator/wizard.test.js +0 -127
- package/src/site/site.test.js +0 -230
- package/src/site/view.test.js +0 -41
- package/src/widgets/calendar/Calendar.test.js +0 -28
- package/src/widgets/explorer/Explorer.test.js +0 -121
- package/src/widgets/ide/editor.test.js +0 -33
- package/src/widgets/kanban/Kanban.test.js +0 -78
- package/src/widgets/login/LoginBox.test.js +0 -12
- package/src/widgets/login/ResetPasswordBox.test.js +0 -34
- package/src/widgets/login/validations.test.js +0 -51
- package/src/widgets/planner/Planner.test.js +0 -60
- package/src/widgets/upload/Upload.test.js +0 -32
- package/table2.test.js +0 -454
package/src/html/list.test.js
DELETED
@@ -1,383 +0,0 @@
|
|
1
|
-
import React from 'react'
|
2
|
-
import { List } from './list'
|
3
|
-
|
4
|
-
// Pruebas unitarias para el componente List mejorado
|
5
|
-
describe('List Component', () => {
|
6
|
-
// Mock de los componentes dependientes
|
7
|
-
const mockIcon = jest.fn()
|
8
|
-
const mockText = jest.fn()
|
9
|
-
const mockCircularProgress = jest.fn()
|
10
|
-
const mockTextField = jest.fn()
|
11
|
-
|
12
|
-
beforeEach(() => {
|
13
|
-
jest.clearAllMocks()
|
14
|
-
|
15
|
-
// Mock de componentes
|
16
|
-
jest.doMock('./icon', () => ({ Icon: mockIcon }))
|
17
|
-
jest.doMock('./text', () => ({ Text: mockText }))
|
18
|
-
jest.doMock('./progress', () => ({ CircularProgress: mockCircularProgress }))
|
19
|
-
jest.doMock('./textfield', () => ({ TextField: mockTextField }))
|
20
|
-
|
21
|
-
// Mock de console.warn
|
22
|
-
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
23
|
-
})
|
24
|
-
|
25
|
-
afterEach(() => {
|
26
|
-
console.warn.mockRestore()
|
27
|
-
})
|
28
|
-
|
29
|
-
test('component exports correctly', () => {
|
30
|
-
expect(List).toBeDefined()
|
31
|
-
expect(typeof List).toBe('function')
|
32
|
-
})
|
33
|
-
|
34
|
-
test('component has correct PropTypes', () => {
|
35
|
-
expect(List.propTypes).toBeDefined()
|
36
|
-
expect(List.propTypes.items).toBeDefined()
|
37
|
-
expect(List.propTypes.selected).toBeDefined()
|
38
|
-
expect(List.propTypes.onSelect).toBeDefined()
|
39
|
-
expect(List.propTypes.groupBy).toBeDefined()
|
40
|
-
expect(List.propTypes.loading).toBeDefined()
|
41
|
-
expect(List.propTypes.searchable).toBeDefined()
|
42
|
-
expect(List.propTypes.sortable).toBeDefined()
|
43
|
-
expect(List.propTypes.multiSelect).toBeDefined()
|
44
|
-
expect(List.propTypes.dense).toBeDefined()
|
45
|
-
expect(List.propTypes.disabled).toBeDefined()
|
46
|
-
expect(List.propTypes.animated).toBeDefined()
|
47
|
-
})
|
48
|
-
|
49
|
-
test('component has correct defaultProps', () => {
|
50
|
-
expect(List.defaultProps).toBeDefined()
|
51
|
-
expect(List.defaultProps.items).toEqual([])
|
52
|
-
expect(List.defaultProps.loading).toBe(false)
|
53
|
-
expect(List.defaultProps.empty).toBe(false)
|
54
|
-
expect(List.defaultProps.searchable).toBe(false)
|
55
|
-
expect(List.defaultProps.sortable).toBe(false)
|
56
|
-
expect(List.defaultProps.multiSelect).toBe(false)
|
57
|
-
expect(List.defaultProps.dense).toBe(false)
|
58
|
-
expect(List.defaultProps.disabled).toBe(false)
|
59
|
-
expect(List.defaultProps.animated).toBe(true)
|
60
|
-
expect(List.defaultProps.role).toBe('list')
|
61
|
-
})
|
62
|
-
|
63
|
-
test('warns when items is not an array', () => {
|
64
|
-
const validateItems = (items) => {
|
65
|
-
if (!Array.isArray(items)) {
|
66
|
-
console.warn('List component: items prop must be an array')
|
67
|
-
}
|
68
|
-
}
|
69
|
-
|
70
|
-
validateItems('not an array')
|
71
|
-
expect(console.warn).toHaveBeenCalledWith('List component: items prop must be an array')
|
72
|
-
|
73
|
-
console.warn.mockClear()
|
74
|
-
validateItems([])
|
75
|
-
expect(console.warn).not.toHaveBeenCalled()
|
76
|
-
})
|
77
|
-
|
78
|
-
test('handles selection correctly', () => {
|
79
|
-
const mockOnSelect = jest.fn()
|
80
|
-
|
81
|
-
const handleSelect = (id, event, multiSelect, selected, onSelect, onMultiSelect) => {
|
82
|
-
if (multiSelect && event?.ctrlKey) {
|
83
|
-
const currentSelected = Array.isArray(selected) ? selected : [selected].filter(Boolean)
|
84
|
-
const newSelected = currentSelected.includes(id)
|
85
|
-
? currentSelected.filter(s => s !== id)
|
86
|
-
: [...currentSelected, id]
|
87
|
-
|
88
|
-
if (onMultiSelect) {
|
89
|
-
onMultiSelect(newSelected)
|
90
|
-
} else if (onSelect) {
|
91
|
-
onSelect(newSelected)
|
92
|
-
}
|
93
|
-
} else {
|
94
|
-
if (onSelect) onSelect(id)
|
95
|
-
}
|
96
|
-
}
|
97
|
-
|
98
|
-
// Single select
|
99
|
-
handleSelect('item1', {}, false, null, mockOnSelect, null)
|
100
|
-
expect(mockOnSelect).toHaveBeenCalledWith('item1')
|
101
|
-
|
102
|
-
mockOnSelect.mockClear()
|
103
|
-
|
104
|
-
// Multi-select with Ctrl
|
105
|
-
const mockOnMultiSelect = jest.fn()
|
106
|
-
handleSelect('item1', { ctrlKey: true }, true, [], mockOnSelect, mockOnMultiSelect)
|
107
|
-
expect(mockOnMultiSelect).toHaveBeenCalledWith(['item1'])
|
108
|
-
})
|
109
|
-
|
110
|
-
test('filters items by search correctly', () => {
|
111
|
-
const items = [
|
112
|
-
{ id: 1, line1: 'Apple', line2: 'Fruit' },
|
113
|
-
{ id: 2, line1: 'Banana', line2: 'Yellow fruit' },
|
114
|
-
{ id: 3, line1: 'Carrot', line2: 'Vegetable' }
|
115
|
-
]
|
116
|
-
|
117
|
-
const filterItems = (items, searchTerm, searchBy) => {
|
118
|
-
if (!searchTerm.trim()) return items
|
119
|
-
|
120
|
-
return items.filter(item => {
|
121
|
-
const searchText = searchBy
|
122
|
-
.map(field => item[field] || '')
|
123
|
-
.join(' ')
|
124
|
-
.toLowerCase()
|
125
|
-
return searchText.includes(searchTerm.toLowerCase())
|
126
|
-
})
|
127
|
-
}
|
128
|
-
|
129
|
-
expect(filterItems(items, '', ['line1', 'line2'])).toEqual(items)
|
130
|
-
expect(filterItems(items, 'apple', ['line1', 'line2'])).toEqual([items[0]])
|
131
|
-
expect(filterItems(items, 'fruit', ['line1', 'line2'])).toEqual([items[0], items[1]])
|
132
|
-
expect(filterItems(items, 'yellow', ['line1', 'line2'])).toEqual([items[1]])
|
133
|
-
expect(filterItems(items, 'xyz', ['line1', 'line2'])).toEqual([])
|
134
|
-
})
|
135
|
-
|
136
|
-
test('sorts items correctly', () => {
|
137
|
-
const items = [
|
138
|
-
{ id: 1, name: 'Charlie', age: 30 },
|
139
|
-
{ id: 2, name: 'Alice', age: 25 },
|
140
|
-
{ id: 3, name: 'Bob', age: 35 }
|
141
|
-
]
|
142
|
-
|
143
|
-
const sortItems = (items, sortConfig) => {
|
144
|
-
if (!sortConfig.key) return items
|
145
|
-
|
146
|
-
return [...items].sort((a, b) => {
|
147
|
-
const aValue = a[sortConfig.key] || ''
|
148
|
-
const bValue = b[sortConfig.key] || ''
|
149
|
-
|
150
|
-
if (sortConfig.direction === 'asc') {
|
151
|
-
return aValue.toString().localeCompare(bValue.toString())
|
152
|
-
} else {
|
153
|
-
return bValue.toString().localeCompare(aValue.toString())
|
154
|
-
}
|
155
|
-
})
|
156
|
-
}
|
157
|
-
|
158
|
-
// Sort by name ascending
|
159
|
-
const sortedAsc = sortItems(items, { key: 'name', direction: 'asc' })
|
160
|
-
expect(sortedAsc[0].name).toBe('Alice')
|
161
|
-
expect(sortedAsc[1].name).toBe('Bob')
|
162
|
-
expect(sortedAsc[2].name).toBe('Charlie')
|
163
|
-
|
164
|
-
// Sort by name descending
|
165
|
-
const sortedDesc = sortItems(items, { key: 'name', direction: 'desc' })
|
166
|
-
expect(sortedDesc[0].name).toBe('Charlie')
|
167
|
-
expect(sortedDesc[1].name).toBe('Bob')
|
168
|
-
expect(sortedDesc[2].name).toBe('Alice')
|
169
|
-
})
|
170
|
-
|
171
|
-
test('handles sort configuration correctly', () => {
|
172
|
-
const handleSort = (key, currentConfig) => {
|
173
|
-
const direction = currentConfig.key === key && currentConfig.direction === 'asc' ? 'desc' : 'asc'
|
174
|
-
return { key, direction }
|
175
|
-
}
|
176
|
-
|
177
|
-
// First click on a column
|
178
|
-
expect(handleSort('name', { key: null, direction: 'asc' }))
|
179
|
-
.toEqual({ key: 'name', direction: 'asc' })
|
180
|
-
|
181
|
-
// Second click on same column
|
182
|
-
expect(handleSort('name', { key: 'name', direction: 'asc' }))
|
183
|
-
.toEqual({ key: 'name', direction: 'desc' })
|
184
|
-
|
185
|
-
// Third click on same column
|
186
|
-
expect(handleSort('name', { key: 'name', direction: 'desc' }))
|
187
|
-
.toEqual({ key: 'name', direction: 'asc' })
|
188
|
-
|
189
|
-
// Click on different column
|
190
|
-
expect(handleSort('age', { key: 'name', direction: 'desc' }))
|
191
|
-
.toEqual({ key: 'age', direction: 'asc' })
|
192
|
-
})
|
193
|
-
|
194
|
-
test('generates CSS classes correctly', () => {
|
195
|
-
const generateClasses = (dense, disabled, animated, loading, className) => {
|
196
|
-
return [
|
197
|
-
'list',
|
198
|
-
dense && 'list--dense',
|
199
|
-
disabled && 'list--disabled',
|
200
|
-
animated && 'list--animated',
|
201
|
-
loading && 'list--loading',
|
202
|
-
className
|
203
|
-
].filter(Boolean).join(' ')
|
204
|
-
}
|
205
|
-
|
206
|
-
expect(generateClasses(false, false, false, false, ''))
|
207
|
-
.toBe('list')
|
208
|
-
|
209
|
-
expect(generateClasses(true, false, true, false, 'custom'))
|
210
|
-
.toBe('list list--dense list--animated custom')
|
211
|
-
|
212
|
-
expect(generateClasses(false, true, false, true, ''))
|
213
|
-
.toBe('list list--disabled list--loading')
|
214
|
-
})
|
215
|
-
|
216
|
-
test('generates accessibility attributes correctly', () => {
|
217
|
-
const generateAriaAttributes = (ariaLabel, disabled, loading, role) => {
|
218
|
-
return {
|
219
|
-
'aria-label': ariaLabel || 'List',
|
220
|
-
'aria-disabled': disabled,
|
221
|
-
'aria-busy': loading,
|
222
|
-
role: role
|
223
|
-
}
|
224
|
-
}
|
225
|
-
|
226
|
-
const result1 = generateAriaAttributes(null, false, false, 'list')
|
227
|
-
expect(result1['aria-label']).toBe('List')
|
228
|
-
expect(result1['aria-disabled']).toBe(false)
|
229
|
-
expect(result1['aria-busy']).toBe(false)
|
230
|
-
expect(result1.role).toBe('list')
|
231
|
-
|
232
|
-
const result2 = generateAriaAttributes('Custom List', true, true, 'listbox')
|
233
|
-
expect(result2['aria-label']).toBe('Custom List')
|
234
|
-
expect(result2['aria-disabled']).toBe(true)
|
235
|
-
expect(result2['aria-busy']).toBe(true)
|
236
|
-
expect(result2.role).toBe('listbox')
|
237
|
-
})
|
238
|
-
|
239
|
-
test('groups items correctly', () => {
|
240
|
-
const items = [
|
241
|
-
{ id: 1, name: 'Apple', category: 'Fruit' },
|
242
|
-
{ id: 2, name: 'Banana', category: 'Fruit' },
|
243
|
-
{ id: 3, name: 'Carrot', category: 'Vegetable' },
|
244
|
-
{ id: 4, name: 'Broccoli', category: 'Vegetable' }
|
245
|
-
]
|
246
|
-
|
247
|
-
const groupItems = (items, groupBy) => {
|
248
|
-
return items.reduce((groups, item) => {
|
249
|
-
let group = groups.find(g => g.name === item[groupBy])
|
250
|
-
if (!group) {
|
251
|
-
group = { name: item[groupBy], items: [] }
|
252
|
-
groups.push(group)
|
253
|
-
}
|
254
|
-
group.items.push(item)
|
255
|
-
return groups
|
256
|
-
}, [])
|
257
|
-
}
|
258
|
-
|
259
|
-
const grouped = groupItems(items, 'category')
|
260
|
-
expect(grouped).toHaveLength(2)
|
261
|
-
expect(grouped[0].name).toBe('Fruit')
|
262
|
-
expect(grouped[0].items).toHaveLength(2)
|
263
|
-
expect(grouped[1].name).toBe('Vegetable')
|
264
|
-
expect(grouped[1].items).toHaveLength(2)
|
265
|
-
})
|
266
|
-
|
267
|
-
test('handles group collapse/expand correctly', () => {
|
268
|
-
const handleGroupToggle = (groupName, collapsedGroups) => {
|
269
|
-
const next = new Set(collapsedGroups)
|
270
|
-
if (next.has(groupName)) {
|
271
|
-
next.delete(groupName)
|
272
|
-
} else {
|
273
|
-
next.add(groupName)
|
274
|
-
}
|
275
|
-
return next
|
276
|
-
}
|
277
|
-
|
278
|
-
const initial = new Set()
|
279
|
-
const afterCollapse = handleGroupToggle('group1', initial)
|
280
|
-
expect(afterCollapse.has('group1')).toBe(true)
|
281
|
-
|
282
|
-
const afterExpand = handleGroupToggle('group1', afterCollapse)
|
283
|
-
expect(afterExpand.has('group1')).toBe(false)
|
284
|
-
})
|
285
|
-
})
|
286
|
-
|
287
|
-
// ListItem tests
|
288
|
-
describe('ListItem Component', () => {
|
289
|
-
test('determines selection state correctly', () => {
|
290
|
-
const isSelected = (id, selected) => {
|
291
|
-
return Array.isArray(selected) ? selected.includes(id) : selected === id
|
292
|
-
}
|
293
|
-
|
294
|
-
expect(isSelected('item1', 'item1')).toBe(true)
|
295
|
-
expect(isSelected('item1', 'item2')).toBe(false)
|
296
|
-
expect(isSelected('item1', ['item1', 'item2'])).toBe(true)
|
297
|
-
expect(isSelected('item1', ['item2', 'item3'])).toBe(false)
|
298
|
-
expect(isSelected('item1', [])).toBe(false)
|
299
|
-
})
|
300
|
-
|
301
|
-
test('handles keyboard navigation correctly', () => {
|
302
|
-
const mockOnSelect = jest.fn()
|
303
|
-
|
304
|
-
const handleKeyDown = (event, disabled, onSelect, id) => {
|
305
|
-
if (disabled) return false
|
306
|
-
|
307
|
-
switch (event.key) {
|
308
|
-
case 'Enter':
|
309
|
-
case ' ':
|
310
|
-
if (onSelect) onSelect(id, event)
|
311
|
-
return true
|
312
|
-
default:
|
313
|
-
return false
|
314
|
-
}
|
315
|
-
}
|
316
|
-
|
317
|
-
// Test Enter key
|
318
|
-
expect(handleKeyDown({ key: 'Enter' }, false, mockOnSelect, 'item1')).toBe(true)
|
319
|
-
expect(mockOnSelect).toHaveBeenCalledWith('item1', { key: 'Enter' })
|
320
|
-
|
321
|
-
mockOnSelect.mockClear()
|
322
|
-
|
323
|
-
// Test Space key
|
324
|
-
expect(handleKeyDown({ key: ' ' }, false, mockOnSelect, 'item1')).toBe(true)
|
325
|
-
expect(mockOnSelect).toHaveBeenCalledWith('item1', { key: ' ' })
|
326
|
-
|
327
|
-
mockOnSelect.mockClear()
|
328
|
-
|
329
|
-
// Test disabled state
|
330
|
-
expect(handleKeyDown({ key: 'Enter' }, true, mockOnSelect, 'item1')).toBe(false)
|
331
|
-
expect(mockOnSelect).not.toHaveBeenCalled()
|
332
|
-
|
333
|
-
// Test other keys
|
334
|
-
expect(handleKeyDown({ key: 'Tab' }, false, mockOnSelect, 'item1')).toBe(false)
|
335
|
-
})
|
336
|
-
|
337
|
-
test('generates item CSS classes correctly', () => {
|
338
|
-
const generateItemClasses = (isSelected, isDisabled, dense, animated, multiSelect) => {
|
339
|
-
return [
|
340
|
-
'list__item',
|
341
|
-
isSelected && 'list__item--selected',
|
342
|
-
isDisabled && 'list__item--disabled',
|
343
|
-
dense && 'list__item--dense',
|
344
|
-
animated && 'list__item--animated',
|
345
|
-
multiSelect && 'list__item--multi-select'
|
346
|
-
].filter(Boolean).join(' ')
|
347
|
-
}
|
348
|
-
|
349
|
-
expect(generateItemClasses(false, false, false, false, false))
|
350
|
-
.toBe('list__item')
|
351
|
-
|
352
|
-
expect(generateItemClasses(true, false, true, true, true))
|
353
|
-
.toBe('list__item list__item--selected list__item--dense list__item--animated list__item--multi-select')
|
354
|
-
|
355
|
-
expect(generateItemClasses(false, true, false, false, false))
|
356
|
-
.toBe('list__item list__item--disabled')
|
357
|
-
})
|
358
|
-
|
359
|
-
test('generates item accessibility attributes correctly', () => {
|
360
|
-
const generateItemAriaAttributes = (isSelected, isDisabled, line1) => {
|
361
|
-
return {
|
362
|
-
'aria-selected': isSelected,
|
363
|
-
'aria-disabled': isDisabled,
|
364
|
-
'aria-label': typeof line1 === 'string' ? line1 : 'List item',
|
365
|
-
role: 'option',
|
366
|
-
tabIndex: isDisabled ? -1 : 0
|
367
|
-
}
|
368
|
-
}
|
369
|
-
|
370
|
-
const result1 = generateItemAriaAttributes(true, false, 'Test Item')
|
371
|
-
expect(result1['aria-selected']).toBe(true)
|
372
|
-
expect(result1['aria-disabled']).toBe(false)
|
373
|
-
expect(result1['aria-label']).toBe('Test Item')
|
374
|
-
expect(result1.role).toBe('option')
|
375
|
-
expect(result1.tabIndex).toBe(0)
|
376
|
-
|
377
|
-
const result2 = generateItemAriaAttributes(false, true, { type: 'span', children: 'Complex' })
|
378
|
-
expect(result2['aria-selected']).toBe(false)
|
379
|
-
expect(result2['aria-disabled']).toBe(true)
|
380
|
-
expect(result2['aria-label']).toBe('List item')
|
381
|
-
expect(result2.tabIndex).toBe(-1)
|
382
|
-
})
|
383
|
-
})
|