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
@@ -1,504 +0,0 @@
|
|
1
|
-
import React from 'react'
|
2
|
-
import { Tabs, Tab, Stack } from './tab'
|
3
|
-
|
4
|
-
// Pruebas unitarias para los componentes Tab mejorados
|
5
|
-
describe('Enhanced Tab Components', () => {
|
6
|
-
// Mock de los componentes dependientes
|
7
|
-
const mockIcon = jest.fn()
|
8
|
-
const mockText = jest.fn()
|
9
|
-
|
10
|
-
beforeEach(() => {
|
11
|
-
jest.clearAllMocks()
|
12
|
-
|
13
|
-
// Mock de componentes
|
14
|
-
jest.doMock('./icon', () => ({ Icon: mockIcon }))
|
15
|
-
jest.doMock('./text', () => ({ Text: mockText }))
|
16
|
-
|
17
|
-
// Mock de console.warn
|
18
|
-
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
19
|
-
|
20
|
-
// Mock de localStorage
|
21
|
-
const localStorageMock = {
|
22
|
-
getItem: jest.fn(),
|
23
|
-
setItem: jest.fn(),
|
24
|
-
removeItem: jest.fn(),
|
25
|
-
clear: jest.fn(),
|
26
|
-
}
|
27
|
-
global.localStorage = localStorageMock
|
28
|
-
})
|
29
|
-
|
30
|
-
afterEach(() => {
|
31
|
-
console.warn.mockRestore()
|
32
|
-
})
|
33
|
-
|
34
|
-
// Tabs Component Tests
|
35
|
-
describe('Tabs Component', () => {
|
36
|
-
test('component exports correctly', () => {
|
37
|
-
expect(Tabs).toBeDefined()
|
38
|
-
expect(typeof Tabs).toBe('function')
|
39
|
-
})
|
40
|
-
|
41
|
-
test('component has correct PropTypes', () => {
|
42
|
-
expect(Tabs.propTypes).toBeDefined()
|
43
|
-
expect(Tabs.propTypes.children).toBeDefined()
|
44
|
-
expect(Tabs.propTypes.selected).toBeDefined()
|
45
|
-
expect(Tabs.propTypes.onChange).toBeDefined()
|
46
|
-
expect(Tabs.propTypes.fillLeft).toBeDefined()
|
47
|
-
expect(Tabs.propTypes.fillRight).toBeDefined()
|
48
|
-
expect(Tabs.propTypes.orientation).toBeDefined()
|
49
|
-
expect(Tabs.propTypes.variant).toBeDefined()
|
50
|
-
expect(Tabs.propTypes.disabled).toBeDefined()
|
51
|
-
expect(Tabs.propTypes.animated).toBeDefined()
|
52
|
-
expect(Tabs.propTypes.persistent).toBeDefined()
|
53
|
-
})
|
54
|
-
|
55
|
-
test('component has correct defaultProps', () => {
|
56
|
-
expect(Tabs.defaultProps).toBeDefined()
|
57
|
-
expect(Tabs.defaultProps.fillLeft).toBe(false)
|
58
|
-
expect(Tabs.defaultProps.fillRight).toBe(true)
|
59
|
-
expect(Tabs.defaultProps.orientation).toBe('horizontal')
|
60
|
-
expect(Tabs.defaultProps.variant).toBe('standard')
|
61
|
-
expect(Tabs.defaultProps.disabled).toBe(false)
|
62
|
-
expect(Tabs.defaultProps.animated).toBe(true)
|
63
|
-
expect(Tabs.defaultProps.persistent).toBe(false)
|
64
|
-
})
|
65
|
-
|
66
|
-
test('warns when children is empty', () => {
|
67
|
-
const validateChildren = (children) => {
|
68
|
-
if (children && !React.Children.count(children)) {
|
69
|
-
console.warn('Tabs component: children prop should contain Tab components')
|
70
|
-
}
|
71
|
-
}
|
72
|
-
|
73
|
-
validateChildren([])
|
74
|
-
expect(console.warn).toHaveBeenCalledWith('Tabs component: children prop should contain Tab components')
|
75
|
-
|
76
|
-
console.warn.mockClear()
|
77
|
-
validateChildren(null)
|
78
|
-
expect(console.warn).not.toHaveBeenCalled()
|
79
|
-
})
|
80
|
-
|
81
|
-
test('handles selection correctly', () => {
|
82
|
-
const mockOnChange = jest.fn()
|
83
|
-
|
84
|
-
const handleSelect = async (id, index, disabled, beforeChange, onChange, selected) => {
|
85
|
-
if (disabled) return
|
86
|
-
|
87
|
-
if (beforeChange) {
|
88
|
-
try {
|
89
|
-
const canChange = await beforeChange(id || index, selected)
|
90
|
-
if (canChange === false) return
|
91
|
-
} catch (error) {
|
92
|
-
console.warn('Tabs beforeChange hook error:', error)
|
93
|
-
return
|
94
|
-
}
|
95
|
-
}
|
96
|
-
|
97
|
-
if (onChange) onChange(id || index)
|
98
|
-
}
|
99
|
-
|
100
|
-
// Normal selection
|
101
|
-
handleSelect('tab1', 0, false, null, mockOnChange, null)
|
102
|
-
expect(mockOnChange).toHaveBeenCalledWith('tab1')
|
103
|
-
|
104
|
-
mockOnChange.mockClear()
|
105
|
-
|
106
|
-
// Disabled state
|
107
|
-
handleSelect('tab1', 0, true, null, mockOnChange, null)
|
108
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
109
|
-
})
|
110
|
-
|
111
|
-
test('handles beforeChange hook correctly', async () => {
|
112
|
-
const mockOnChange = jest.fn()
|
113
|
-
const mockBeforeChange = jest.fn()
|
114
|
-
|
115
|
-
const handleSelect = async (id, index, disabled, beforeChange, onChange, selected) => {
|
116
|
-
if (disabled) return
|
117
|
-
|
118
|
-
if (beforeChange) {
|
119
|
-
try {
|
120
|
-
const canChange = await beforeChange(id || index, selected)
|
121
|
-
if (canChange === false) return
|
122
|
-
} catch (error) {
|
123
|
-
console.warn('Tabs beforeChange hook error:', error)
|
124
|
-
return
|
125
|
-
}
|
126
|
-
}
|
127
|
-
|
128
|
-
if (onChange) onChange(id || index)
|
129
|
-
}
|
130
|
-
|
131
|
-
// Allow change
|
132
|
-
mockBeforeChange.mockResolvedValue(true)
|
133
|
-
await handleSelect('tab1', 0, false, mockBeforeChange, mockOnChange, 'tab0')
|
134
|
-
expect(mockBeforeChange).toHaveBeenCalledWith('tab1', 'tab0')
|
135
|
-
expect(mockOnChange).toHaveBeenCalledWith('tab1')
|
136
|
-
|
137
|
-
mockOnChange.mockClear()
|
138
|
-
mockBeforeChange.mockClear()
|
139
|
-
|
140
|
-
// Prevent change
|
141
|
-
mockBeforeChange.mockResolvedValue(false)
|
142
|
-
await handleSelect('tab1', 0, false, mockBeforeChange, mockOnChange, 'tab0')
|
143
|
-
expect(mockBeforeChange).toHaveBeenCalledWith('tab1', 'tab0')
|
144
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
145
|
-
|
146
|
-
mockOnChange.mockClear()
|
147
|
-
mockBeforeChange.mockClear()
|
148
|
-
|
149
|
-
// Error in beforeChange
|
150
|
-
mockBeforeChange.mockRejectedValue(new Error('Test error'))
|
151
|
-
await handleSelect('tab1', 0, false, mockBeforeChange, mockOnChange, 'tab0')
|
152
|
-
expect(console.warn).toHaveBeenCalledWith('Tabs beforeChange hook error:', expect.any(Error))
|
153
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
154
|
-
})
|
155
|
-
|
156
|
-
test('handles keyboard navigation correctly', () => {
|
157
|
-
const mockHandleSelect = jest.fn()
|
158
|
-
const children = [
|
159
|
-
{ props: { id: 'tab1' } },
|
160
|
-
{ props: { id: 'tab2' } },
|
161
|
-
{ props: { id: 'tab3' } }
|
162
|
-
]
|
163
|
-
|
164
|
-
const handleKeyDown = (event, disabled, selected, notNullChildren, handleSelect) => {
|
165
|
-
if (disabled) return
|
166
|
-
|
167
|
-
const currentIndex = typeof selected === 'number' ? selected :
|
168
|
-
notNullChildren.findIndex(child => child.props.id === selected)
|
169
|
-
|
170
|
-
let newIndex = currentIndex
|
171
|
-
|
172
|
-
switch (event.key) {
|
173
|
-
case 'ArrowLeft':
|
174
|
-
case 'ArrowUp':
|
175
|
-
event.preventDefault()
|
176
|
-
newIndex = currentIndex > 0 ? currentIndex - 1 : notNullChildren.length - 1
|
177
|
-
break
|
178
|
-
case 'ArrowRight':
|
179
|
-
case 'ArrowDown':
|
180
|
-
event.preventDefault()
|
181
|
-
newIndex = currentIndex < notNullChildren.length - 1 ? currentIndex + 1 : 0
|
182
|
-
break
|
183
|
-
case 'Home':
|
184
|
-
event.preventDefault()
|
185
|
-
newIndex = 0
|
186
|
-
break
|
187
|
-
case 'End':
|
188
|
-
event.preventDefault()
|
189
|
-
newIndex = notNullChildren.length - 1
|
190
|
-
break
|
191
|
-
default:
|
192
|
-
return
|
193
|
-
}
|
194
|
-
|
195
|
-
const targetChild = notNullChildren[newIndex]
|
196
|
-
if (targetChild && !targetChild.props.disabled) {
|
197
|
-
handleSelect(targetChild.props.id, newIndex)
|
198
|
-
}
|
199
|
-
}
|
200
|
-
|
201
|
-
const mockEvent = { preventDefault: jest.fn() }
|
202
|
-
|
203
|
-
// Arrow right from first tab
|
204
|
-
handleKeyDown({ ...mockEvent, key: 'ArrowRight' }, false, 0, children, mockHandleSelect)
|
205
|
-
expect(mockHandleSelect).toHaveBeenCalledWith('tab2', 1)
|
206
|
-
|
207
|
-
mockHandleSelect.mockClear()
|
208
|
-
|
209
|
-
// Arrow left from last tab (wrap around)
|
210
|
-
handleKeyDown({ ...mockEvent, key: 'ArrowLeft' }, false, 2, children, mockHandleSelect)
|
211
|
-
expect(mockHandleSelect).toHaveBeenCalledWith('tab2', 1)
|
212
|
-
|
213
|
-
mockHandleSelect.mockClear()
|
214
|
-
|
215
|
-
// Home key
|
216
|
-
handleKeyDown({ ...mockEvent, key: 'Home' }, false, 2, children, mockHandleSelect)
|
217
|
-
expect(mockHandleSelect).toHaveBeenCalledWith('tab1', 0)
|
218
|
-
|
219
|
-
mockHandleSelect.mockClear()
|
220
|
-
|
221
|
-
// End key
|
222
|
-
handleKeyDown({ ...mockEvent, key: 'End' }, false, 0, children, mockHandleSelect)
|
223
|
-
expect(mockHandleSelect).toHaveBeenCalledWith('tab3', 2)
|
224
|
-
})
|
225
|
-
|
226
|
-
test('generates CSS classes correctly', () => {
|
227
|
-
const generateClasses = (orientation, variant, scrollable, centered, disabled, animated, className) => {
|
228
|
-
return [
|
229
|
-
'tabs',
|
230
|
-
`tabs--${orientation}`,
|
231
|
-
`tabs--${variant}`,
|
232
|
-
scrollable && 'tabs--scrollable',
|
233
|
-
centered && 'tabs--centered',
|
234
|
-
disabled && 'tabs--disabled',
|
235
|
-
animated && 'tabs--animated',
|
236
|
-
className
|
237
|
-
].filter(Boolean).join(' ')
|
238
|
-
}
|
239
|
-
|
240
|
-
expect(generateClasses('horizontal', 'standard', false, false, false, false, ''))
|
241
|
-
.toBe('tabs tabs--horizontal tabs--standard')
|
242
|
-
|
243
|
-
expect(generateClasses('vertical', 'scrollable', true, true, true, true, 'custom'))
|
244
|
-
.toBe('tabs tabs--vertical tabs--scrollable tabs--scrollable tabs--centered tabs--disabled tabs--animated custom')
|
245
|
-
})
|
246
|
-
|
247
|
-
test('generates accessibility attributes correctly', () => {
|
248
|
-
const generateAriaAttributes = (ariaLabel, disabled, orientation) => {
|
249
|
-
return {
|
250
|
-
'aria-label': ariaLabel || 'Tabs',
|
251
|
-
'aria-disabled': disabled,
|
252
|
-
'aria-orientation': orientation,
|
253
|
-
role: 'tablist'
|
254
|
-
}
|
255
|
-
}
|
256
|
-
|
257
|
-
const result1 = generateAriaAttributes(null, false, 'horizontal')
|
258
|
-
expect(result1['aria-label']).toBe('Tabs')
|
259
|
-
expect(result1['aria-disabled']).toBe(false)
|
260
|
-
expect(result1['aria-orientation']).toBe('horizontal')
|
261
|
-
expect(result1.role).toBe('tablist')
|
262
|
-
|
263
|
-
const result2 = generateAriaAttributes('Custom Tabs', true, 'vertical')
|
264
|
-
expect(result2['aria-label']).toBe('Custom Tabs')
|
265
|
-
expect(result2['aria-disabled']).toBe(true)
|
266
|
-
expect(result2['aria-orientation']).toBe('vertical')
|
267
|
-
})
|
268
|
-
|
269
|
-
test('handles persistent tabs correctly', () => {
|
270
|
-
const mockOnChange = jest.fn()
|
271
|
-
|
272
|
-
// Test persistence logic
|
273
|
-
const testPersistence = (persistent, persistKey, savedValue, currentSelected) => {
|
274
|
-
if (persistent && persistKey && savedValue !== null) {
|
275
|
-
const parsedTab = isNaN(savedValue) ? savedValue : parseInt(savedValue)
|
276
|
-
if (parsedTab !== currentSelected) {
|
277
|
-
return parsedTab
|
278
|
-
}
|
279
|
-
}
|
280
|
-
return currentSelected
|
281
|
-
}
|
282
|
-
|
283
|
-
// Test loading saved tab
|
284
|
-
const result1 = testPersistence(true, 'test-tabs', '2', 0)
|
285
|
-
expect(result1).toBe(2)
|
286
|
-
|
287
|
-
// Test no change when same tab
|
288
|
-
const result2 = testPersistence(true, 'test-tabs', '1', 1)
|
289
|
-
expect(result2).toBe(1)
|
290
|
-
|
291
|
-
// Test disabled persistence
|
292
|
-
const result3 = testPersistence(false, 'test-tabs', '2', 0)
|
293
|
-
expect(result3).toBe(0)
|
294
|
-
|
295
|
-
// Test save logic
|
296
|
-
const testSave = (persistent, persistKey, selected) => {
|
297
|
-
if (persistent && persistKey && selected !== undefined) {
|
298
|
-
return `tabs-${persistKey}:${selected.toString()}`
|
299
|
-
}
|
300
|
-
return null
|
301
|
-
}
|
302
|
-
|
303
|
-
expect(testSave(true, 'test-tabs', 1)).toBe('tabs-test-tabs:1')
|
304
|
-
expect(testSave(false, 'test-tabs', 1)).toBe(null)
|
305
|
-
})
|
306
|
-
})
|
307
|
-
|
308
|
-
// Tab Component Tests
|
309
|
-
describe('Tab Component', () => {
|
310
|
-
test('component has correct PropTypes', () => {
|
311
|
-
expect(Tab.propTypes).toBeDefined()
|
312
|
-
expect(Tab.propTypes.id).toBeDefined()
|
313
|
-
expect(Tab.propTypes.icon).toBeDefined()
|
314
|
-
expect(Tab.propTypes.label).toBeDefined()
|
315
|
-
expect(Tab.propTypes.selected).toBeDefined()
|
316
|
-
expect(Tab.propTypes.disabled).toBeDefined()
|
317
|
-
expect(Tab.propTypes.closeable).toBeDefined()
|
318
|
-
expect(Tab.propTypes.badge).toBeDefined()
|
319
|
-
})
|
320
|
-
|
321
|
-
test('component has correct defaultProps', () => {
|
322
|
-
expect(Tab.defaultProps).toBeDefined()
|
323
|
-
expect(Tab.defaultProps.disabled).toBe(false)
|
324
|
-
expect(Tab.defaultProps.closeable).toBe(false)
|
325
|
-
expect(Tab.defaultProps.animated).toBe(true)
|
326
|
-
})
|
327
|
-
|
328
|
-
test('handles selection correctly', () => {
|
329
|
-
const mockOnSelect = jest.fn()
|
330
|
-
|
331
|
-
const handleSelect = (event, disabled, onSelect, id) => {
|
332
|
-
if (disabled) return
|
333
|
-
event.preventDefault()
|
334
|
-
if (onSelect) onSelect(id)
|
335
|
-
}
|
336
|
-
|
337
|
-
const mockEvent = { preventDefault: jest.fn() }
|
338
|
-
|
339
|
-
// Normal selection
|
340
|
-
handleSelect(mockEvent, false, mockOnSelect, 'tab1')
|
341
|
-
expect(mockEvent.preventDefault).toHaveBeenCalled()
|
342
|
-
expect(mockOnSelect).toHaveBeenCalledWith('tab1')
|
343
|
-
|
344
|
-
mockOnSelect.mockClear()
|
345
|
-
|
346
|
-
// Disabled state
|
347
|
-
handleSelect(mockEvent, true, mockOnSelect, 'tab1')
|
348
|
-
expect(mockOnSelect).not.toHaveBeenCalled()
|
349
|
-
})
|
350
|
-
|
351
|
-
test('handles close correctly', () => {
|
352
|
-
const mockOnClose = jest.fn()
|
353
|
-
|
354
|
-
const handleClose = (event, onClose, id) => {
|
355
|
-
event.stopPropagation()
|
356
|
-
if (onClose) onClose(id)
|
357
|
-
}
|
358
|
-
|
359
|
-
const mockEvent = { stopPropagation: jest.fn() }
|
360
|
-
|
361
|
-
handleClose(mockEvent, mockOnClose, 'tab1')
|
362
|
-
expect(mockEvent.stopPropagation).toHaveBeenCalled()
|
363
|
-
expect(mockOnClose).toHaveBeenCalledWith('tab1')
|
364
|
-
})
|
365
|
-
|
366
|
-
test('handles keyboard interaction correctly', () => {
|
367
|
-
const mockOnSelect = jest.fn()
|
368
|
-
const mockOnClose = jest.fn()
|
369
|
-
|
370
|
-
const handleKeyDown = (event, disabled, onSelect, id, closeable, onClose) => {
|
371
|
-
if (disabled) return
|
372
|
-
|
373
|
-
switch (event.key) {
|
374
|
-
case 'Enter':
|
375
|
-
case ' ':
|
376
|
-
event.preventDefault()
|
377
|
-
if (onSelect) onSelect(id)
|
378
|
-
break
|
379
|
-
case 'Delete':
|
380
|
-
case 'Backspace':
|
381
|
-
if (closeable && onClose) {
|
382
|
-
event.preventDefault()
|
383
|
-
onClose(id)
|
384
|
-
}
|
385
|
-
break
|
386
|
-
default:
|
387
|
-
break
|
388
|
-
}
|
389
|
-
}
|
390
|
-
|
391
|
-
const mockEvent = { preventDefault: jest.fn() }
|
392
|
-
|
393
|
-
// Enter key
|
394
|
-
handleKeyDown({ ...mockEvent, key: 'Enter' }, false, mockOnSelect, 'tab1', false, null)
|
395
|
-
expect(mockOnSelect).toHaveBeenCalledWith('tab1')
|
396
|
-
|
397
|
-
mockOnSelect.mockClear()
|
398
|
-
|
399
|
-
// Delete key with closeable tab
|
400
|
-
handleKeyDown({ ...mockEvent, key: 'Delete' }, false, mockOnSelect, 'tab1', true, mockOnClose)
|
401
|
-
expect(mockOnClose).toHaveBeenCalledWith('tab1')
|
402
|
-
})
|
403
|
-
|
404
|
-
test('generates CSS classes correctly', () => {
|
405
|
-
const generateClasses = (selected, disabled, closeable, animated, orientation, variant, className) => {
|
406
|
-
return [
|
407
|
-
'tab',
|
408
|
-
selected && 'selected',
|
409
|
-
disabled && 'tab--disabled',
|
410
|
-
closeable && 'tab--closeable',
|
411
|
-
animated && 'tab--animated',
|
412
|
-
`tab--${orientation}`,
|
413
|
-
`tab--${variant}`,
|
414
|
-
className
|
415
|
-
].filter(Boolean).join(' ')
|
416
|
-
}
|
417
|
-
|
418
|
-
expect(generateClasses(false, false, false, false, 'horizontal', 'standard', ''))
|
419
|
-
.toBe('tab tab--horizontal tab--standard')
|
420
|
-
|
421
|
-
expect(generateClasses(true, true, true, true, 'vertical', 'scrollable', 'custom'))
|
422
|
-
.toBe('tab selected tab--disabled tab--closeable tab--animated tab--vertical tab--scrollable custom')
|
423
|
-
})
|
424
|
-
|
425
|
-
test('generates accessibility attributes correctly', () => {
|
426
|
-
const generateAriaAttributes = (selected, disabled, id, tabIndex, label) => {
|
427
|
-
return {
|
428
|
-
'aria-selected': selected,
|
429
|
-
'aria-disabled': disabled,
|
430
|
-
'aria-controls': `tabpanel-${id || tabIndex}`,
|
431
|
-
'aria-label': typeof label === 'string' ? label : `Tab ${(tabIndex || 0) + 1}`,
|
432
|
-
role: 'tab',
|
433
|
-
tabIndex: selected ? 0 : -1,
|
434
|
-
id: `tab-${id || tabIndex}`
|
435
|
-
}
|
436
|
-
}
|
437
|
-
|
438
|
-
const result1 = generateAriaAttributes(true, false, 'tab1', 0, 'First Tab')
|
439
|
-
expect(result1['aria-selected']).toBe(true)
|
440
|
-
expect(result1['aria-disabled']).toBe(false)
|
441
|
-
expect(result1['aria-controls']).toBe('tabpanel-tab1')
|
442
|
-
expect(result1['aria-label']).toBe('First Tab')
|
443
|
-
expect(result1.role).toBe('tab')
|
444
|
-
expect(result1.tabIndex).toBe(0)
|
445
|
-
expect(result1.id).toBe('tab-tab1')
|
446
|
-
|
447
|
-
const result2 = generateAriaAttributes(false, true, null, 1, null)
|
448
|
-
expect(result2['aria-selected']).toBe(false)
|
449
|
-
expect(result2['aria-disabled']).toBe(true)
|
450
|
-
expect(result2['aria-label']).toBe('Tab 2')
|
451
|
-
expect(result2.tabIndex).toBe(-1)
|
452
|
-
})
|
453
|
-
})
|
454
|
-
|
455
|
-
// Stack Component Tests
|
456
|
-
describe('Stack Component', () => {
|
457
|
-
test('component has correct PropTypes', () => {
|
458
|
-
expect(Stack.propTypes).toBeDefined()
|
459
|
-
expect(Stack.propTypes.selected).toBeDefined()
|
460
|
-
expect(Stack.propTypes.children).toBeDefined()
|
461
|
-
expect(Stack.propTypes.lazy).toBeDefined()
|
462
|
-
expect(Stack.propTypes.keepMounted).toBeDefined()
|
463
|
-
expect(Stack.propTypes.animated).toBeDefined()
|
464
|
-
})
|
465
|
-
|
466
|
-
test('component has correct defaultProps', () => {
|
467
|
-
expect(Stack.defaultProps).toBeDefined()
|
468
|
-
expect(Stack.defaultProps.selected).toBe(0)
|
469
|
-
expect(Stack.defaultProps.lazy).toBe(false)
|
470
|
-
expect(Stack.defaultProps.keepMounted).toBe(false)
|
471
|
-
expect(Stack.defaultProps.animated).toBe(true)
|
472
|
-
})
|
473
|
-
|
474
|
-
test('handles lazy loading correctly', () => {
|
475
|
-
const handleLazyLoading = (selected, lazy, keepMounted, mountedTabs) => {
|
476
|
-
if (lazy || keepMounted) {
|
477
|
-
return new Set([...mountedTabs, selected])
|
478
|
-
}
|
479
|
-
return mountedTabs
|
480
|
-
}
|
481
|
-
|
482
|
-
const initialMounted = new Set([0])
|
483
|
-
|
484
|
-
// Add new tab to mounted set
|
485
|
-
const newMounted = handleLazyLoading(2, true, false, initialMounted)
|
486
|
-
expect(newMounted.has(0)).toBe(true)
|
487
|
-
expect(newMounted.has(2)).toBe(true)
|
488
|
-
expect(newMounted.has(1)).toBe(false)
|
489
|
-
})
|
490
|
-
|
491
|
-
test('generates CSS classes correctly', () => {
|
492
|
-
const generateClasses = (animated, className) => {
|
493
|
-
return [
|
494
|
-
'stack',
|
495
|
-
animated && 'stack--animated',
|
496
|
-
className
|
497
|
-
].filter(Boolean).join(' ')
|
498
|
-
}
|
499
|
-
|
500
|
-
expect(generateClasses(false, '')).toBe('stack')
|
501
|
-
expect(generateClasses(true, 'custom')).toBe('stack stack--animated custom')
|
502
|
-
})
|
503
|
-
})
|
504
|
-
})
|
package/src/html/table.test.js
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
import React, { useState } from 'react'
|
2
|
-
import { FORMATS } from '../domain/ContentType'
|
3
|
-
import { DataTable } from './table'
|
4
|
-
|
5
|
-
export const TableTest = (prop) => {
|
6
|
-
|
7
|
-
const [rows, setRows] = useState(
|
8
|
-
[
|
9
|
-
{ id: 1, checked: false, name: "John Smith" , description: "lorem ipsum 9", color: "#CACAFF", num: "25", thumb: "https://w7.pngwing.com/pngs/881/826/png-transparent-pikachu-ash-ketchum-pokemon-vrste-pikachu-leaf-flower-meme-thumbnail.png" },
|
10
|
-
{ id: 2, checked: false, name: "Ann Martin" , description: "lorem ipsum 2", color: "#CCFFFF", num: "1234567890.1234567890" },
|
11
|
-
{ id: 3, checked: false, name: "Ann Martin" , description: "lorem ipsum 8", color: "#CCFFFF", num: "12340.1234567890" },
|
12
|
-
{ id: 4, checked: false, name: "Zack McCracken", description: "lorem ipsum 4", color: "#CCFFFF", num: "567890.1234567890" },
|
13
|
-
{ id: 5, checked: false, name: "Ann Martin" , description: "lorem ipsum 1", color: "#CCFFFF", num: "23670.190" },
|
14
|
-
{ id: 6, checked: false, name: "John Smith" , description: "lorem ipsum 2", color: "#CCFFFF", num: "71230.10" },
|
15
|
-
{ id: 7, checked: false, name: "Ann Martin" , description: "lorem ipsum 1", color: "#CCFFFF", num: "3490.23" },
|
16
|
-
{ id: 8, checked: false, name: "Martin Freeman", description: "lorem ipsum 4", color: "#CCFFFF" , num: "890.1234567890" },
|
17
|
-
{ id: 9, checked: false, name: "Ann Martin" , description: "lorem ipsum 5", color: "#CCFFFF", num: "365", date: new Date().toString() },
|
18
|
-
]
|
19
|
-
)
|
20
|
-
|
21
|
-
function editCell(row, cell, value) {
|
22
|
-
//console.log(row, cell, value)
|
23
|
-
}
|
24
|
-
|
25
|
-
function select(row) {
|
26
|
-
const next = rows.map(r => r.id === row.id ? { ...r, selected: !r.selected } : r)
|
27
|
-
setRows(next)
|
28
|
-
}
|
29
|
-
|
30
|
-
function check(rowID, columnID, value) {
|
31
|
-
const next = rows.map(r => r.id === rowID ? { ...r, checked: value } : r)
|
32
|
-
setRows(next)
|
33
|
-
}
|
34
|
-
|
35
|
-
function checkAll(ids, checked) {
|
36
|
-
const next = rows.map(row => Object.assign({}, row, { checked }))
|
37
|
-
setRows(next)
|
38
|
-
}
|
39
|
-
|
40
|
-
const table1 = {
|
41
|
-
className: "xxx",
|
42
|
-
editable: true,
|
43
|
-
columns: [
|
44
|
-
{ id: "index" , label: "#" , type: "INDEX" },
|
45
|
-
{ id: "checked" , onChange: check },
|
46
|
-
{ id: "name" , label: "Name" , type: "String", sortable: true, filterable: true, resizable: true },
|
47
|
-
{ id: "category" , label: "Category" , type: "String", sortable: true, filterable: true, resizable: false, options: [
|
48
|
-
{ label: "A", value: "A" },
|
49
|
-
{ label: "B", value: "B" },
|
50
|
-
{ label: "C", value: "C" },
|
51
|
-
]},
|
52
|
-
{ id: "description", label: "Description", type: "String", sortable: true },
|
53
|
-
{ id: "color" , label: "Color" , type: "String", format: FORMATS.COLOR },
|
54
|
-
{ id: "date" , label: "Date" , type: "String", format: FORMATS.DATE },
|
55
|
-
{ id: "num" , label: "Num" , type: "Number", maxDecimals: 2, sortable: true},
|
56
|
-
],
|
57
|
-
rows
|
58
|
-
}
|
59
|
-
|
60
|
-
return (
|
61
|
-
<>
|
62
|
-
<div style={{ maxHeight: "20rem", overflow: "auto", margin: "2rem", display: "flex" }}>
|
63
|
-
<DataTable {...table1} onRowSelection={select} outlined multisort={true}/>
|
64
|
-
</div>
|
65
|
-
<div style={{ maxHeight: "20rem", overflow: "auto", margin: "2rem" }}>
|
66
|
-
<DataTable {...table1} onRowSelection={select} onCheckAll={checkAll} filterable={true} />
|
67
|
-
</div>
|
68
|
-
</>
|
69
|
-
)
|
70
|
-
}
|