ywana-core8 0.1.103 → 0.2.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/index.css +4941 -324
- package/dist/index.js +42338 -0
- package/dist/index.js.map +1 -0
- package/dist/index.modern.js +37458 -31678
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +39634 -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 +254 -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,423 +0,0 @@
|
|
1
|
-
import React from 'react'
|
2
|
-
import { TokenField } from './tokenfield'
|
3
|
-
|
4
|
-
// Pruebas unitarias para el componente TokenField mejorado
|
5
|
-
describe('Enhanced TokenField Component', () => {
|
6
|
-
// Mock de los componentes dependientes
|
7
|
-
const mockIcon = jest.fn()
|
8
|
-
const mockText = jest.fn()
|
9
|
-
const mockDropDown = jest.fn()
|
10
|
-
|
11
|
-
beforeEach(() => {
|
12
|
-
jest.clearAllMocks()
|
13
|
-
|
14
|
-
// Mock de componentes
|
15
|
-
jest.doMock('./icon', () => ({ Icon: mockIcon }))
|
16
|
-
jest.doMock('./text', () => ({ Text: mockText }))
|
17
|
-
jest.doMock('./textfield', () => ({ DropDown: mockDropDown }))
|
18
|
-
|
19
|
-
// Mock de console.warn
|
20
|
-
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
21
|
-
})
|
22
|
-
|
23
|
-
afterEach(() => {
|
24
|
-
console.warn.mockRestore()
|
25
|
-
})
|
26
|
-
|
27
|
-
// TokenField Component Tests
|
28
|
-
describe('TokenField Component', () => {
|
29
|
-
test('component exports correctly', () => {
|
30
|
-
expect(TokenField).toBeDefined()
|
31
|
-
expect(typeof TokenField).toBe('function')
|
32
|
-
})
|
33
|
-
|
34
|
-
test('component has correct PropTypes', () => {
|
35
|
-
expect(TokenField.propTypes).toBeDefined()
|
36
|
-
expect(TokenField.propTypes.id).toBeDefined()
|
37
|
-
expect(TokenField.propTypes.label).toBeDefined()
|
38
|
-
expect(TokenField.propTypes.tokens).toBeDefined()
|
39
|
-
expect(TokenField.propTypes.readOnly).toBeDefined()
|
40
|
-
expect(TokenField.propTypes.options).toBeDefined()
|
41
|
-
expect(TokenField.propTypes.predictive).toBeDefined()
|
42
|
-
expect(TokenField.propTypes.onChange).toBeDefined()
|
43
|
-
expect(TokenField.propTypes.disabled).toBeDefined()
|
44
|
-
expect(TokenField.propTypes.maxTokens).toBeDefined()
|
45
|
-
expect(TokenField.propTypes.minTokens).toBeDefined()
|
46
|
-
expect(TokenField.propTypes.allowDuplicates).toBeDefined()
|
47
|
-
expect(TokenField.propTypes.validateToken).toBeDefined()
|
48
|
-
expect(TokenField.propTypes.tokenSeparators).toBeDefined()
|
49
|
-
})
|
50
|
-
|
51
|
-
test('component has correct defaultProps', () => {
|
52
|
-
expect(TokenField.defaultProps).toBeDefined()
|
53
|
-
expect(TokenField.defaultProps.tokens).toEqual([])
|
54
|
-
expect(TokenField.defaultProps.predictive).toBe(true)
|
55
|
-
expect(TokenField.defaultProps.disabled).toBe(false)
|
56
|
-
expect(TokenField.defaultProps.required).toBe(false)
|
57
|
-
expect(TokenField.defaultProps.placeholder).toBe("Add token...")
|
58
|
-
expect(TokenField.defaultProps.minTokens).toBe(0)
|
59
|
-
expect(TokenField.defaultProps.allowDuplicates).toBe(true)
|
60
|
-
expect(TokenField.defaultProps.tokenSeparators).toEqual([',', ';', '\n'])
|
61
|
-
expect(TokenField.defaultProps.size).toBe('medium')
|
62
|
-
expect(TokenField.defaultProps.variant).toBe('default')
|
63
|
-
})
|
64
|
-
|
65
|
-
test('validates props correctly', () => {
|
66
|
-
const validateProps = (tokens, maxTokens, minTokens) => {
|
67
|
-
if (!Array.isArray(tokens)) {
|
68
|
-
console.warn('TokenField: tokens prop must be an array')
|
69
|
-
}
|
70
|
-
if (maxTokens && tokens.length > maxTokens) {
|
71
|
-
console.warn(`TokenField: tokens count (${tokens.length}) exceeds maxTokens (${maxTokens})`)
|
72
|
-
}
|
73
|
-
if (minTokens && tokens.length < minTokens) {
|
74
|
-
console.warn(`TokenField: tokens count (${tokens.length}) is below minTokens (${minTokens})`)
|
75
|
-
}
|
76
|
-
}
|
77
|
-
|
78
|
-
// Invalid tokens prop
|
79
|
-
validateProps('not an array', null, 0)
|
80
|
-
expect(console.warn).toHaveBeenCalledWith('TokenField: tokens prop must be an array')
|
81
|
-
|
82
|
-
console.warn.mockClear()
|
83
|
-
|
84
|
-
// Exceeds max tokens
|
85
|
-
validateProps(['token1', 'token2', 'token3'], 2, 0)
|
86
|
-
expect(console.warn).toHaveBeenCalledWith('TokenField: tokens count (3) exceeds maxTokens (2)')
|
87
|
-
|
88
|
-
console.warn.mockClear()
|
89
|
-
|
90
|
-
// Below min tokens
|
91
|
-
validateProps(['token1'], null, 2)
|
92
|
-
expect(console.warn).toHaveBeenCalledWith('TokenField: tokens count (1) is below minTokens (2)')
|
93
|
-
|
94
|
-
console.warn.mockClear()
|
95
|
-
|
96
|
-
// Valid props
|
97
|
-
validateProps(['token1', 'token2'], 3, 1)
|
98
|
-
expect(console.warn).not.toHaveBeenCalled()
|
99
|
-
})
|
100
|
-
|
101
|
-
test('validates token correctly', () => {
|
102
|
-
const validateTokenValue = (tokenValue, allowDuplicates, tokens, maxTokens, validateToken) => {
|
103
|
-
if (!tokenValue || (typeof tokenValue === 'string' && tokenValue.trim() === '')) {
|
104
|
-
return { isValid: false, error: 'Token cannot be empty' }
|
105
|
-
}
|
106
|
-
|
107
|
-
// Check duplicates
|
108
|
-
if (!allowDuplicates && tokens.includes(tokenValue)) {
|
109
|
-
return { isValid: false, error: 'Duplicate token not allowed' }
|
110
|
-
}
|
111
|
-
|
112
|
-
// Check max tokens
|
113
|
-
if (maxTokens && tokens.length >= maxTokens) {
|
114
|
-
return { isValid: false, error: `Maximum ${maxTokens} tokens allowed` }
|
115
|
-
}
|
116
|
-
|
117
|
-
// Custom validation
|
118
|
-
if (validateToken) {
|
119
|
-
const customValidation = validateToken(tokenValue, tokens)
|
120
|
-
if (customValidation && !customValidation.isValid) {
|
121
|
-
return customValidation
|
122
|
-
}
|
123
|
-
}
|
124
|
-
|
125
|
-
return { isValid: true }
|
126
|
-
}
|
127
|
-
|
128
|
-
// Empty token
|
129
|
-
expect(validateTokenValue('', true, [], null, null))
|
130
|
-
.toEqual({ isValid: false, error: 'Token cannot be empty' })
|
131
|
-
|
132
|
-
// Duplicate token
|
133
|
-
expect(validateTokenValue('token1', false, ['token1'], null, null))
|
134
|
-
.toEqual({ isValid: false, error: 'Duplicate token not allowed' })
|
135
|
-
|
136
|
-
// Max tokens reached
|
137
|
-
expect(validateTokenValue('token3', true, ['token1', 'token2'], 2, null))
|
138
|
-
.toEqual({ isValid: false, error: 'Maximum 2 tokens allowed' })
|
139
|
-
|
140
|
-
// Custom validation failure
|
141
|
-
const customValidator = (token) => ({ isValid: false, error: 'Custom error' })
|
142
|
-
expect(validateTokenValue('token1', true, [], null, customValidator))
|
143
|
-
.toEqual({ isValid: false, error: 'Custom error' })
|
144
|
-
|
145
|
-
// Valid token
|
146
|
-
expect(validateTokenValue('token1', true, [], null, null))
|
147
|
-
.toEqual({ isValid: true })
|
148
|
-
})
|
149
|
-
|
150
|
-
test('handles remove correctly', () => {
|
151
|
-
const mockOnChange = jest.fn()
|
152
|
-
const mockOnTokenRemove = jest.fn()
|
153
|
-
|
154
|
-
const remove = (index, disabled, readOnly, tokens, minTokens, id, onChange, onTokenRemove) => {
|
155
|
-
if (disabled || readOnly) return
|
156
|
-
|
157
|
-
const next = tokens.slice()
|
158
|
-
const removedToken = next.splice(index, 1)[0]
|
159
|
-
|
160
|
-
// Check minimum tokens
|
161
|
-
if (minTokens && next.length < minTokens) {
|
162
|
-
console.warn(`TokenField: Cannot remove token. Minimum ${minTokens} tokens required.`)
|
163
|
-
return
|
164
|
-
}
|
165
|
-
|
166
|
-
if (onChange) onChange(id, next)
|
167
|
-
if (onTokenRemove) onTokenRemove(removedToken, index)
|
168
|
-
}
|
169
|
-
|
170
|
-
const tokens = ['token1', 'token2', 'token3']
|
171
|
-
|
172
|
-
// Normal remove
|
173
|
-
remove(1, false, false, tokens, 0, 'field1', mockOnChange, mockOnTokenRemove)
|
174
|
-
expect(mockOnChange).toHaveBeenCalledWith('field1', ['token1', 'token3'])
|
175
|
-
expect(mockOnTokenRemove).toHaveBeenCalledWith('token2', 1)
|
176
|
-
|
177
|
-
mockOnChange.mockClear()
|
178
|
-
mockOnTokenRemove.mockClear()
|
179
|
-
|
180
|
-
// Disabled remove
|
181
|
-
remove(1, true, false, tokens, 0, 'field1', mockOnChange, mockOnTokenRemove)
|
182
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
183
|
-
|
184
|
-
// ReadOnly remove
|
185
|
-
remove(1, false, true, tokens, 0, 'field1', mockOnChange, mockOnTokenRemove)
|
186
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
187
|
-
|
188
|
-
// Min tokens prevent remove
|
189
|
-
remove(0, false, false, ['token1'], 1, 'field1', mockOnChange, mockOnTokenRemove)
|
190
|
-
expect(console.warn).toHaveBeenCalledWith('TokenField: Cannot remove token. Minimum 1 tokens required.')
|
191
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
192
|
-
})
|
193
|
-
|
194
|
-
test('handles add token correctly', () => {
|
195
|
-
const mockOnChange = jest.fn()
|
196
|
-
const mockOnTokenAdd = jest.fn()
|
197
|
-
const mockOnValidationError = jest.fn()
|
198
|
-
|
199
|
-
const addToken = (tokenValue, disabled, readOnly, tokens, maxTokens, allowDuplicates, validateToken, id, onChange, onTokenAdd, onValidationError) => {
|
200
|
-
if (disabled || readOnly) return false
|
201
|
-
|
202
|
-
// Validation logic
|
203
|
-
if (!tokenValue || tokenValue.trim() === '') {
|
204
|
-
const error = 'Token cannot be empty'
|
205
|
-
if (onValidationError) onValidationError(error, tokenValue)
|
206
|
-
return false
|
207
|
-
}
|
208
|
-
|
209
|
-
if (!allowDuplicates && tokens.includes(tokenValue)) {
|
210
|
-
const error = 'Duplicate token not allowed'
|
211
|
-
if (onValidationError) onValidationError(error, tokenValue)
|
212
|
-
return false
|
213
|
-
}
|
214
|
-
|
215
|
-
if (maxTokens && tokens.length >= maxTokens) {
|
216
|
-
const error = `Maximum ${maxTokens} tokens allowed`
|
217
|
-
if (onValidationError) onValidationError(error, tokenValue)
|
218
|
-
return false
|
219
|
-
}
|
220
|
-
|
221
|
-
const next = Array.isArray(tokens) ? tokens.concat(tokenValue) : [tokenValue]
|
222
|
-
if (onChange) onChange(id, next)
|
223
|
-
if (onTokenAdd) onTokenAdd(tokenValue, tokens.length)
|
224
|
-
|
225
|
-
return true
|
226
|
-
}
|
227
|
-
|
228
|
-
// Normal add
|
229
|
-
expect(addToken('newToken', false, false, ['token1'], null, true, null, 'field1', mockOnChange, mockOnTokenAdd, mockOnValidationError))
|
230
|
-
.toBe(true)
|
231
|
-
expect(mockOnChange).toHaveBeenCalledWith('field1', ['token1', 'newToken'])
|
232
|
-
expect(mockOnTokenAdd).toHaveBeenCalledWith('newToken', 1)
|
233
|
-
|
234
|
-
mockOnChange.mockClear()
|
235
|
-
mockOnTokenAdd.mockClear()
|
236
|
-
|
237
|
-
// Disabled add
|
238
|
-
expect(addToken('newToken', true, false, ['token1'], null, true, null, 'field1', mockOnChange, mockOnTokenAdd, mockOnValidationError))
|
239
|
-
.toBe(false)
|
240
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
241
|
-
|
242
|
-
// Duplicate add
|
243
|
-
expect(addToken('token1', false, false, ['token1'], null, false, null, 'field1', mockOnChange, mockOnTokenAdd, mockOnValidationError))
|
244
|
-
.toBe(false)
|
245
|
-
expect(mockOnValidationError).toHaveBeenCalledWith('Duplicate token not allowed', 'token1')
|
246
|
-
|
247
|
-
// Max tokens reached
|
248
|
-
expect(addToken('newToken', false, false, ['token1', 'token2'], 2, true, null, 'field1', mockOnChange, mockOnTokenAdd, mockOnValidationError))
|
249
|
-
.toBe(false)
|
250
|
-
expect(mockOnValidationError).toHaveBeenCalledWith('Maximum 2 tokens allowed', 'newToken')
|
251
|
-
})
|
252
|
-
|
253
|
-
test('handles keyboard events correctly', () => {
|
254
|
-
const mockAddToken = jest.fn().mockReturnValue(true)
|
255
|
-
const mockRemove = jest.fn()
|
256
|
-
const mockSetValue = jest.fn()
|
257
|
-
|
258
|
-
const onEnter = (event, disabled, readOnly, tokenSeparators, value, tokens, addToken, remove, setValue) => {
|
259
|
-
if (disabled || readOnly) return
|
260
|
-
|
261
|
-
// Handle separators
|
262
|
-
if (tokenSeparators.includes(event.key) || event.key === 'Enter') {
|
263
|
-
event.preventDefault()
|
264
|
-
event.stopPropagation()
|
265
|
-
|
266
|
-
const token = event.target.value.trim()
|
267
|
-
if (token && token.length > 0) {
|
268
|
-
if (addToken(token)) {
|
269
|
-
setValue('')
|
270
|
-
}
|
271
|
-
}
|
272
|
-
return
|
273
|
-
}
|
274
|
-
|
275
|
-
// Handle backspace to remove last token
|
276
|
-
if (value === '' && tokens.length > 0 && event.key === 'Backspace') {
|
277
|
-
event.preventDefault()
|
278
|
-
remove(tokens.length - 1)
|
279
|
-
return
|
280
|
-
}
|
281
|
-
}
|
282
|
-
|
283
|
-
const mockEvent = {
|
284
|
-
preventDefault: jest.fn(),
|
285
|
-
stopPropagation: jest.fn(),
|
286
|
-
target: { value: 'newToken' },
|
287
|
-
key: 'Enter'
|
288
|
-
}
|
289
|
-
|
290
|
-
// Enter key
|
291
|
-
onEnter(mockEvent, false, false, [',', ';', '\n'], 'currentValue', ['token1'], mockAddToken, mockRemove, mockSetValue)
|
292
|
-
expect(mockEvent.preventDefault).toHaveBeenCalled()
|
293
|
-
expect(mockEvent.stopPropagation).toHaveBeenCalled()
|
294
|
-
expect(mockAddToken).toHaveBeenCalledWith('newToken')
|
295
|
-
expect(mockSetValue).toHaveBeenCalledWith('')
|
296
|
-
|
297
|
-
mockAddToken.mockClear()
|
298
|
-
mockEvent.preventDefault.mockClear()
|
299
|
-
|
300
|
-
// Backspace with empty value
|
301
|
-
const backspaceEvent = { ...mockEvent, key: 'Backspace', target: { value: '' } }
|
302
|
-
onEnter(backspaceEvent, false, false, [',', ';', '\n'], '', ['token1'], mockAddToken, mockRemove, mockSetValue)
|
303
|
-
expect(backspaceEvent.preventDefault).toHaveBeenCalled()
|
304
|
-
expect(mockRemove).toHaveBeenCalledWith(0)
|
305
|
-
|
306
|
-
// Disabled state
|
307
|
-
onEnter(mockEvent, true, false, [',', ';', '\n'], 'currentValue', ['token1'], mockAddToken, mockRemove, mockSetValue)
|
308
|
-
expect(mockAddToken).not.toHaveBeenCalled()
|
309
|
-
})
|
310
|
-
|
311
|
-
test('filters options correctly', () => {
|
312
|
-
const getFilteredOptions = (options, tokens, searchable, value, sortable) => {
|
313
|
-
if (!options) return []
|
314
|
-
|
315
|
-
const tks = tokens || []
|
316
|
-
const usedValues = tks.map(token => token)
|
317
|
-
let filteredOptions = options.filter(option => !usedValues.includes(option.value))
|
318
|
-
|
319
|
-
if (searchable && value) {
|
320
|
-
filteredOptions = filteredOptions.filter(option =>
|
321
|
-
option.label?.toLowerCase().includes(value.toLowerCase()) ||
|
322
|
-
option.value?.toString().toLowerCase().includes(value.toLowerCase())
|
323
|
-
)
|
324
|
-
}
|
325
|
-
|
326
|
-
if (sortable) {
|
327
|
-
filteredOptions.sort((a, b) => {
|
328
|
-
if (!a.label || !b.label) return 0
|
329
|
-
try {
|
330
|
-
return a.label.localeCompare(b.label)
|
331
|
-
} catch (error) {
|
332
|
-
return 0
|
333
|
-
}
|
334
|
-
})
|
335
|
-
}
|
336
|
-
|
337
|
-
return filteredOptions
|
338
|
-
}
|
339
|
-
|
340
|
-
const options = [
|
341
|
-
{ label: 'Apple', value: 'apple' },
|
342
|
-
{ label: 'Banana', value: 'banana' },
|
343
|
-
{ label: 'Cherry', value: 'cherry' }
|
344
|
-
]
|
345
|
-
|
346
|
-
// Filter used tokens
|
347
|
-
expect(getFilteredOptions(options, ['apple'], false, '', false))
|
348
|
-
.toEqual([
|
349
|
-
{ label: 'Banana', value: 'banana' },
|
350
|
-
{ label: 'Cherry', value: 'cherry' }
|
351
|
-
])
|
352
|
-
|
353
|
-
// Search filter
|
354
|
-
expect(getFilteredOptions(options, [], true, 'app', false))
|
355
|
-
.toEqual([{ label: 'Apple', value: 'apple' }])
|
356
|
-
|
357
|
-
// Sort options
|
358
|
-
const unsortedOptions = [
|
359
|
-
{ label: 'Zebra', value: 'zebra' },
|
360
|
-
{ label: 'Apple', value: 'apple' }
|
361
|
-
]
|
362
|
-
expect(getFilteredOptions(unsortedOptions, [], false, '', true))
|
363
|
-
.toEqual([
|
364
|
-
{ label: 'Apple', value: 'apple' },
|
365
|
-
{ label: 'Zebra', value: 'zebra' }
|
366
|
-
])
|
367
|
-
})
|
368
|
-
|
369
|
-
test('generates CSS classes correctly', () => {
|
370
|
-
const generateClasses = (size, variant, disabled, readOnly, required, isFocused, error, className) => {
|
371
|
-
return [
|
372
|
-
'tokenField',
|
373
|
-
`tokenField--${size}`,
|
374
|
-
`tokenField--${variant}`,
|
375
|
-
disabled && 'tokenField--disabled',
|
376
|
-
readOnly && 'tokenField--readonly',
|
377
|
-
required && 'tokenField--required',
|
378
|
-
isFocused && 'tokenField--focused',
|
379
|
-
error && 'tokenField--error',
|
380
|
-
className
|
381
|
-
].filter(Boolean).join(' ')
|
382
|
-
}
|
383
|
-
|
384
|
-
expect(generateClasses('medium', 'default', false, false, false, false, null, ''))
|
385
|
-
.toBe('tokenField tokenField--medium tokenField--default')
|
386
|
-
|
387
|
-
expect(generateClasses('large', 'outlined', true, true, true, true, 'Error message', 'custom'))
|
388
|
-
.toBe('tokenField tokenField--large tokenField--outlined tokenField--disabled tokenField--readonly tokenField--required tokenField--focused tokenField--error custom')
|
389
|
-
})
|
390
|
-
|
391
|
-
test('handles clear all correctly', () => {
|
392
|
-
const mockOnChange = jest.fn()
|
393
|
-
const mockOnClear = jest.fn()
|
394
|
-
const mockSetValue = jest.fn()
|
395
|
-
|
396
|
-
const handleClear = (disabled, readOnly, minTokens, id, onChange, onClear, setValue) => {
|
397
|
-
if (disabled || readOnly || minTokens > 0) return
|
398
|
-
|
399
|
-
if (onChange) onChange(id, [])
|
400
|
-
if (onClear) onClear()
|
401
|
-
setValue('')
|
402
|
-
}
|
403
|
-
|
404
|
-
// Normal clear
|
405
|
-
handleClear(false, false, 0, 'field1', mockOnChange, mockOnClear, mockSetValue)
|
406
|
-
expect(mockOnChange).toHaveBeenCalledWith('field1', [])
|
407
|
-
expect(mockOnClear).toHaveBeenCalled()
|
408
|
-
expect(mockSetValue).toHaveBeenCalledWith('')
|
409
|
-
|
410
|
-
mockOnChange.mockClear()
|
411
|
-
mockOnClear.mockClear()
|
412
|
-
mockSetValue.mockClear()
|
413
|
-
|
414
|
-
// Disabled clear
|
415
|
-
handleClear(true, false, 0, 'field1', mockOnChange, mockOnClear, mockSetValue)
|
416
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
417
|
-
|
418
|
-
// Min tokens prevent clear
|
419
|
-
handleClear(false, false, 1, 'field1', mockOnChange, mockOnClear, mockSetValue)
|
420
|
-
expect(mockOnChange).not.toHaveBeenCalled()
|
421
|
-
})
|
422
|
-
})
|
423
|
-
})
|