mtrl 0.3.0 → 0.3.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/.env +15 -0
- package/CONTRIBUTING.md +8 -8
- package/DOCS.md +3 -3
- package/README.md +43 -20
- package/TESTING.md +128 -18
- package/dist/index.js +14865 -0
- package/git-user-stats.js +545 -0
- package/index.ts +9 -69
- package/package.json +10 -3
- package/src/components/badge/api.ts +15 -1
- package/src/components/badge/badge.ts +43 -4
- package/src/components/badge/config.ts +40 -8
- package/src/components/badge/index.ts +64 -3
- package/src/components/badge/types.ts +175 -33
- package/src/components/button/api.ts +63 -1
- package/src/components/button/button.ts +39 -3
- package/src/components/button/config.ts +21 -4
- package/src/components/button/index.ts +26 -1
- package/src/components/button/types.ts +7 -1
- package/src/components/card/api.ts +78 -9
- package/src/components/card/card.ts +58 -3
- package/src/components/card/config.ts +41 -11
- package/src/components/card/features.ts +39 -12
- package/src/components/card/index.ts +84 -19
- package/src/components/card/types.ts +218 -29
- package/src/components/carousel/carousel.ts +92 -28
- package/src/components/carousel/constants.ts +107 -21
- package/src/components/carousel/index.ts +31 -13
- package/src/components/checkbox/checkbox.ts +83 -16
- package/src/components/checkbox/index.ts +43 -1
- package/src/components/checkbox/types.ts +219 -32
- package/src/components/chips/api.ts +194 -0
- package/src/components/{chip → chips/chip}/api.ts +42 -2
- package/src/components/chips/chip/chip.ts +131 -0
- package/src/components/{chip → chips/chip}/config.ts +3 -3
- package/src/components/chips/chip/index.ts +3 -0
- package/src/components/chips/chips.md +481 -0
- package/src/components/chips/chips.ts +75 -0
- package/src/components/chips/config.ts +109 -0
- package/src/components/chips/constants.ts +61 -0
- package/src/components/chips/features/chip-items.ts +33 -0
- package/src/components/chips/features/container.ts +77 -0
- package/src/components/chips/features/controller.ts +448 -0
- package/src/components/chips/features/index.ts +5 -0
- package/src/components/chips/features/label.ts +108 -0
- package/src/components/chips/index.ts +11 -0
- package/src/components/chips/schema.ts +61 -0
- package/src/components/{chip → chips}/types.ts +203 -92
- package/src/components/dialog/dialog.ts +99 -16
- package/src/components/dialog/index.ts +97 -1
- package/src/components/dialog/types.ts +375 -69
- package/src/components/divider/config.ts +90 -6
- package/src/components/divider/divider.ts +32 -2
- package/src/components/divider/features.ts +26 -0
- package/src/components/divider/index.ts +30 -0
- package/src/components/divider/types.ts +86 -9
- package/src/components/extended-fab/api.ts +53 -1
- package/src/components/extended-fab/config.ts +29 -1
- package/src/components/extended-fab/extended-fab.ts +28 -0
- package/src/components/extended-fab/index.ts +36 -0
- package/src/components/extended-fab/types.ts +458 -13
- package/src/components/fab/api.ts +42 -2
- package/src/components/fab/config.ts +29 -1
- package/src/components/fab/fab.ts +16 -2
- package/src/components/fab/index.ts +35 -0
- package/src/components/fab/types.ts +374 -10
- package/src/components/list/api.ts +12 -2
- package/src/components/list/config.ts +21 -0
- package/src/components/list/features.ts +6 -0
- package/src/components/list/index.ts +56 -1
- package/src/components/list/list-item.ts +46 -2
- package/src/components/list/list.ts +73 -2
- package/src/components/list/types.ts +172 -0
- package/src/components/list/utils.ts +26 -2
- package/src/components/menu/api.ts +217 -20
- package/src/components/menu/config.ts +27 -0
- package/src/components/menu/features/visibility.ts +55 -6
- package/src/components/menu/index.ts +64 -0
- package/src/components/menu/menu-item.ts +46 -3
- package/src/components/menu/menu.ts +77 -1
- package/src/components/menu/types.ts +404 -39
- package/src/components/navigation/index.ts +4 -1
- package/src/components/navigation/types.ts +33 -0
- package/src/components/sheet/config.ts +1 -2
- package/src/components/sheet/features/gestures.ts +1 -1
- package/src/components/sheet/features/position.ts +1 -2
- package/src/components/sheet/features/state.ts +1 -1
- package/src/components/sheet/index.ts +10 -2
- package/src/components/sheet/sheet.ts +1 -2
- package/src/components/sheet/types.ts +29 -1
- package/src/components/slider/api.ts +1 -1
- package/src/components/slider/config.ts +1 -1
- package/src/components/slider/features/controller.ts +1 -1
- package/src/components/slider/features/handlers.ts +1 -1
- package/src/components/slider/features/states.ts +1 -1
- package/src/components/slider/index.ts +12 -5
- package/src/components/slider/schema.ts +1 -1
- package/src/components/slider/types.ts +31 -0
- package/src/components/snackbar/index.ts +7 -1
- package/src/components/snackbar/types.ts +25 -0
- package/src/components/switch/index.ts +5 -1
- package/src/components/switch/types.ts +13 -0
- package/src/components/tabs/tab-api.ts +1 -1
- package/src/components/tabs/types.ts +1 -1
- package/src/components/textfield/index.ts +7 -1
- package/src/components/textfield/types.ts +36 -0
- package/src/components/tooltip/api.ts +6 -2
- package/src/components/tooltip/config.ts +9 -28
- package/src/components/tooltip/index.ts +10 -1
- package/src/components/tooltip/types.ts +38 -3
- package/src/index.ts +129 -31
- package/src/styles/abstract/_mixins.scss +23 -9
- package/src/styles/abstract/_variables.scss +14 -4
- package/src/styles/components/_card.scss +1 -1
- package/src/styles/components/_chip.scss +323 -113
- package/src/styles/components/_tabs.scss +1 -1
- package/src/components/checkbox/constants.ts +0 -37
- package/src/components/chip/chip-set.ts +0 -225
- package/src/components/chip/chip.ts +0 -118
- package/src/components/chip/constants.ts +0 -28
- package/src/components/chip/index.ts +0 -12
- package/src/components/list/constants.ts +0 -116
- package/src/components/sheet/constants.ts +0 -20
- package/src/components/slider/constants.ts +0 -32
- package/src/components/snackbar/constants.ts +0 -26
- package/src/components/tooltip/constants.ts +0 -27
- package/test/components/button.test.js +0 -170
- package/test/components/checkbox.test.js +0 -238
- package/test/components/list.test.js +0 -105
- package/test/components/menu.test.js +0 -385
- package/test/components/navigation.test.js +0 -227
- package/test/components/snackbar.test.js +0 -234
- package/test/components/switch.test.js +0 -186
- package/test/components/textfield.test.js +0 -314
- package/test/core/emitter.test.js +0 -141
- package/test/core/ripple.test.js +0 -66
- package/test/setup.js +0 -371
- package/tsconfig.json +0 -22
- package/typedoc.json +0 -28
- package/typedoc.simple.json +0 -14
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
// test/components/textfield.test.js
|
|
2
|
-
import { describe, test, expect, mock } from 'bun:test'
|
|
3
|
-
import { TEXTFIELD_VARIANTS, TEXTFIELD_SIZES, TEXTFIELD_TYPES } from '../../src/components/textfield/constants'
|
|
4
|
-
|
|
5
|
-
// Use our mock implementation directly
|
|
6
|
-
const createTextfield = (config = {}) => {
|
|
7
|
-
// Create base element
|
|
8
|
-
const element = document.createElement('div')
|
|
9
|
-
element.className = `mtrl-textfield ${config.class || ''}`
|
|
10
|
-
|
|
11
|
-
// Add variant class if provided
|
|
12
|
-
if (config.variant) {
|
|
13
|
-
element.classList.add(`mtrl-textfield--${config.variant}`)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Add size class if provided
|
|
17
|
-
if (config.size) {
|
|
18
|
-
element.classList.add(`mtrl-textfield--${config.size}`)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Create input element
|
|
22
|
-
const input = document.createElement(config.type === TEXTFIELD_TYPES.MULTILINE ? 'textarea' : 'input')
|
|
23
|
-
input.className = 'mtrl-textfield-input'
|
|
24
|
-
input.type = config.type || TEXTFIELD_TYPES.TEXT
|
|
25
|
-
input.value = config.value || ''
|
|
26
|
-
input.placeholder = config.placeholder || ''
|
|
27
|
-
|
|
28
|
-
if (config.name) input.name = config.name
|
|
29
|
-
if (config.maxLength) input.maxLength = config.maxLength
|
|
30
|
-
if (config.required) input.required = true
|
|
31
|
-
if (config.disabled) input.disabled = true
|
|
32
|
-
|
|
33
|
-
element.appendChild(input)
|
|
34
|
-
|
|
35
|
-
// Create label if provided
|
|
36
|
-
let label = null
|
|
37
|
-
if (config.label) {
|
|
38
|
-
label = document.createElement('label')
|
|
39
|
-
label.className = 'mtrl-textfield-label'
|
|
40
|
-
label.textContent = config.label
|
|
41
|
-
element.appendChild(label)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Create the mock component with API
|
|
45
|
-
return {
|
|
46
|
-
element,
|
|
47
|
-
config,
|
|
48
|
-
input,
|
|
49
|
-
label,
|
|
50
|
-
|
|
51
|
-
getValue: () => input.value,
|
|
52
|
-
|
|
53
|
-
setValue: (value) => {
|
|
54
|
-
input.value = value || ''
|
|
55
|
-
return this
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
setLabel: (text) => {
|
|
59
|
-
if (label) {
|
|
60
|
-
label.textContent = text
|
|
61
|
-
}
|
|
62
|
-
return this
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
getLabel: () => label?.textContent || '',
|
|
66
|
-
|
|
67
|
-
setAttribute: (name, value) => {
|
|
68
|
-
input.setAttribute(name, value)
|
|
69
|
-
return this
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
getAttribute: (name) => input.getAttribute(name),
|
|
73
|
-
|
|
74
|
-
removeAttribute: (name) => {
|
|
75
|
-
input.removeAttribute(name)
|
|
76
|
-
return this
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
on: (event, handler) => {
|
|
80
|
-
input.addEventListener(event, handler)
|
|
81
|
-
return this
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
off: (event, handler) => {
|
|
85
|
-
input.removeEventListener(event, handler)
|
|
86
|
-
return this
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
enable: () => {
|
|
90
|
-
input.disabled = false
|
|
91
|
-
return this
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
disable: () => {
|
|
95
|
-
input.disabled = true
|
|
96
|
-
return this
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
destroy: () => {
|
|
100
|
-
if (element.parentNode) {
|
|
101
|
-
element.remove()
|
|
102
|
-
}
|
|
103
|
-
return this
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
describe('Textfield Component', () => {
|
|
109
|
-
test('should create a textfield element', () => {
|
|
110
|
-
const textfield = createTextfield()
|
|
111
|
-
expect(textfield.element).toBeDefined()
|
|
112
|
-
expect(textfield.element.tagName).toBe('DIV')
|
|
113
|
-
expect(textfield.element.className).toContain('mtrl-textfield')
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
test('should apply variant class', () => {
|
|
117
|
-
// Test filled variant
|
|
118
|
-
const filledTextField = createTextfield({
|
|
119
|
-
variant: TEXTFIELD_VARIANTS.FILLED
|
|
120
|
-
})
|
|
121
|
-
expect(filledTextField.element.className).toContain('mtrl-textfield--filled')
|
|
122
|
-
|
|
123
|
-
// Test outlined variant
|
|
124
|
-
const outlinedTextField = createTextfield({
|
|
125
|
-
variant: TEXTFIELD_VARIANTS.OUTLINED
|
|
126
|
-
})
|
|
127
|
-
expect(outlinedTextField.element.className).toContain('mtrl-textfield--outlined')
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
test('should apply size class', () => {
|
|
131
|
-
// Test small size
|
|
132
|
-
const smallTextField = createTextfield({
|
|
133
|
-
size: TEXTFIELD_SIZES.SMALL
|
|
134
|
-
})
|
|
135
|
-
expect(smallTextField.element.className).toContain('mtrl-textfield--small')
|
|
136
|
-
|
|
137
|
-
// Test large size
|
|
138
|
-
const largeTextField = createTextfield({
|
|
139
|
-
size: TEXTFIELD_SIZES.LARGE
|
|
140
|
-
})
|
|
141
|
-
expect(largeTextField.element.className).toContain('mtrl-textfield--large')
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
test('should set initial value', () => {
|
|
145
|
-
const initialValue = 'Hello World'
|
|
146
|
-
const textfield = createTextfield({
|
|
147
|
-
value: initialValue
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
expect(textfield.getValue()).toBe(initialValue)
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
test('should update value', () => {
|
|
154
|
-
const textfield = createTextfield()
|
|
155
|
-
const newValue = 'Updated Value'
|
|
156
|
-
|
|
157
|
-
textfield.setValue(newValue)
|
|
158
|
-
expect(textfield.getValue()).toBe(newValue)
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
test('should set and get label', () => {
|
|
162
|
-
const initialLabel = 'Username'
|
|
163
|
-
const textfield = createTextfield({
|
|
164
|
-
label: initialLabel
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
expect(textfield.getLabel()).toBe(initialLabel)
|
|
168
|
-
|
|
169
|
-
// Update label
|
|
170
|
-
const newLabel = 'New Label'
|
|
171
|
-
textfield.setLabel(newLabel)
|
|
172
|
-
expect(textfield.getLabel()).toBe(newLabel)
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
test('should handle attributes', () => {
|
|
176
|
-
const textfield = createTextfield()
|
|
177
|
-
|
|
178
|
-
// Set attribute
|
|
179
|
-
textfield.setAttribute('data-test', 'test-value')
|
|
180
|
-
expect(textfield.getAttribute('data-test')).toBe('test-value')
|
|
181
|
-
|
|
182
|
-
// Remove attribute
|
|
183
|
-
textfield.removeAttribute('data-test')
|
|
184
|
-
expect(textfield.getAttribute('data-test')).toBeNull()
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
test('should support disabled state', () => {
|
|
188
|
-
// Create initially enabled
|
|
189
|
-
const textfield = createTextfield()
|
|
190
|
-
|
|
191
|
-
// Check API methods
|
|
192
|
-
expect(typeof textfield.disable).toBe('function')
|
|
193
|
-
expect(typeof textfield.enable).toBe('function')
|
|
194
|
-
|
|
195
|
-
// Disable and check state
|
|
196
|
-
textfield.disable()
|
|
197
|
-
expect(textfield.input.disabled).toBe(true)
|
|
198
|
-
|
|
199
|
-
// Enable and check state
|
|
200
|
-
textfield.enable()
|
|
201
|
-
expect(textfield.input.disabled).toBe(false)
|
|
202
|
-
|
|
203
|
-
// Test initially disabled through config
|
|
204
|
-
const disabledTextfield = createTextfield({ disabled: true })
|
|
205
|
-
expect(disabledTextfield.input.disabled).toBe(true)
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
test('should support different input types', () => {
|
|
209
|
-
// Test regular text input
|
|
210
|
-
const textInput = createTextfield({
|
|
211
|
-
type: TEXTFIELD_TYPES.TEXT
|
|
212
|
-
})
|
|
213
|
-
expect(textInput.input.type).toBe('text')
|
|
214
|
-
|
|
215
|
-
// Test password input
|
|
216
|
-
const passwordInput = createTextfield({
|
|
217
|
-
type: TEXTFIELD_TYPES.PASSWORD
|
|
218
|
-
})
|
|
219
|
-
expect(passwordInput.input.type).toBe('password')
|
|
220
|
-
|
|
221
|
-
// Test email input
|
|
222
|
-
const emailInput = createTextfield({
|
|
223
|
-
type: TEXTFIELD_TYPES.EMAIL
|
|
224
|
-
})
|
|
225
|
-
expect(emailInput.input.type).toBe('email')
|
|
226
|
-
|
|
227
|
-
// Test multiline input (textarea)
|
|
228
|
-
const multilineInput = createTextfield({
|
|
229
|
-
type: TEXTFIELD_TYPES.MULTILINE
|
|
230
|
-
})
|
|
231
|
-
expect(multilineInput.input.tagName).toBe('TEXTAREA')
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
test('should register event handlers', () => {
|
|
235
|
-
const textfield = createTextfield()
|
|
236
|
-
|
|
237
|
-
// Create a mock handler
|
|
238
|
-
const mockHandler = mock(() => {})
|
|
239
|
-
|
|
240
|
-
// Register handler
|
|
241
|
-
textfield.on('input', mockHandler)
|
|
242
|
-
|
|
243
|
-
// Trigger an input event
|
|
244
|
-
const inputEvent = new Event('input')
|
|
245
|
-
textfield.input.dispatchEvent(inputEvent)
|
|
246
|
-
|
|
247
|
-
// Check that handler was called
|
|
248
|
-
expect(mockHandler.mock.calls.length).toBeGreaterThan(0)
|
|
249
|
-
|
|
250
|
-
// Unregister handler and trigger again
|
|
251
|
-
textfield.off('input', mockHandler)
|
|
252
|
-
textfield.input.dispatchEvent(inputEvent)
|
|
253
|
-
|
|
254
|
-
// Handler call count should not increase
|
|
255
|
-
expect(mockHandler.mock.calls.length).toBe(1)
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
test('should apply custom class', () => {
|
|
259
|
-
const customClass = 'custom-textfield'
|
|
260
|
-
const textfield = createTextfield({
|
|
261
|
-
class: customClass
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
expect(textfield.element.className).toContain(customClass)
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
test('should set placeholder', () => {
|
|
268
|
-
const placeholder = 'Enter text here'
|
|
269
|
-
const textfield = createTextfield({
|
|
270
|
-
placeholder
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
expect(textfield.input.placeholder).toBe(placeholder)
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
test('should set required attribute', () => {
|
|
277
|
-
const textfield = createTextfield({
|
|
278
|
-
required: true
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
expect(textfield.input.required).toBe(true)
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
test('should set name attribute', () => {
|
|
285
|
-
const name = 'username'
|
|
286
|
-
const textfield = createTextfield({
|
|
287
|
-
name
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
expect(textfield.input.name).toBe(name)
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
test('should set maxLength attribute', () => {
|
|
294
|
-
const maxLength = 50
|
|
295
|
-
const textfield = createTextfield({
|
|
296
|
-
maxLength
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
expect(textfield.input.maxLength).toBe(maxLength)
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
test('should properly clean up resources on destroy', () => {
|
|
303
|
-
const textfield = createTextfield()
|
|
304
|
-
|
|
305
|
-
const parentElement = document.createElement('div')
|
|
306
|
-
parentElement.appendChild(textfield.element)
|
|
307
|
-
|
|
308
|
-
// Destroy the component
|
|
309
|
-
textfield.destroy()
|
|
310
|
-
|
|
311
|
-
// Check if element was removed
|
|
312
|
-
expect(parentElement.children.length).toBe(0)
|
|
313
|
-
})
|
|
314
|
-
})
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
// test/core/state/emitter.test.js
|
|
2
|
-
import { describe, test, expect, mock } from 'bun:test'
|
|
3
|
-
import { createEmitter } from '../../src/core/state/emitter'
|
|
4
|
-
|
|
5
|
-
describe('Event Emitter', () => {
|
|
6
|
-
test('should create an emitter with expected methods', () => {
|
|
7
|
-
const emitter = createEmitter()
|
|
8
|
-
expect(emitter).toBeDefined()
|
|
9
|
-
expect(emitter.on).toBeInstanceOf(Function)
|
|
10
|
-
expect(emitter.off).toBeInstanceOf(Function)
|
|
11
|
-
expect(emitter.emit).toBeInstanceOf(Function)
|
|
12
|
-
expect(emitter.clear).toBeInstanceOf(Function)
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
test('should register event handlers with on()', () => {
|
|
16
|
-
const emitter = createEmitter()
|
|
17
|
-
const handler = mock(() => {})
|
|
18
|
-
|
|
19
|
-
const unsubscribe = emitter.on('test', handler)
|
|
20
|
-
|
|
21
|
-
expect(unsubscribe).toBeInstanceOf(Function)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
test('should invoke handlers when event is emitted', () => {
|
|
25
|
-
const emitter = createEmitter()
|
|
26
|
-
const handler1 = mock(() => {})
|
|
27
|
-
const handler2 = mock(() => {})
|
|
28
|
-
const eventData = { foo: 'bar' }
|
|
29
|
-
|
|
30
|
-
emitter.on('test', handler1)
|
|
31
|
-
emitter.on('test', handler2)
|
|
32
|
-
|
|
33
|
-
emitter.emit('test', eventData)
|
|
34
|
-
|
|
35
|
-
expect(handler1).toHaveBeenCalledTimes(1)
|
|
36
|
-
expect(handler1).toHaveBeenCalledWith(eventData)
|
|
37
|
-
|
|
38
|
-
expect(handler2).toHaveBeenCalledTimes(1)
|
|
39
|
-
expect(handler2).toHaveBeenCalledWith(eventData)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test('should remove handlers with off()', () => {
|
|
43
|
-
const emitter = createEmitter()
|
|
44
|
-
const handler = mock(() => {})
|
|
45
|
-
|
|
46
|
-
emitter.on('test', handler)
|
|
47
|
-
emitter.off('test', handler)
|
|
48
|
-
|
|
49
|
-
emitter.emit('test')
|
|
50
|
-
|
|
51
|
-
expect(handler).not.toHaveBeenCalled()
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test('should remove specific handlers while keeping others', () => {
|
|
55
|
-
const emitter = createEmitter()
|
|
56
|
-
const handler1 = mock(() => {})
|
|
57
|
-
const handler2 = mock(() => {})
|
|
58
|
-
|
|
59
|
-
emitter.on('test', handler1)
|
|
60
|
-
emitter.on('test', handler2)
|
|
61
|
-
|
|
62
|
-
emitter.off('test', handler1)
|
|
63
|
-
|
|
64
|
-
emitter.emit('test')
|
|
65
|
-
|
|
66
|
-
expect(handler1).not.toHaveBeenCalled()
|
|
67
|
-
expect(handler2).toHaveBeenCalledTimes(1)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
test('should unsubscribe handlers using the returned function', () => {
|
|
71
|
-
const emitter = createEmitter()
|
|
72
|
-
const handler = mock(() => {})
|
|
73
|
-
|
|
74
|
-
const unsubscribe = emitter.on('test', handler)
|
|
75
|
-
unsubscribe()
|
|
76
|
-
|
|
77
|
-
emitter.emit('test')
|
|
78
|
-
|
|
79
|
-
expect(handler).not.toHaveBeenCalled()
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
test('should support multiple event types', () => {
|
|
83
|
-
const emitter = createEmitter()
|
|
84
|
-
const handler1 = mock(() => {})
|
|
85
|
-
const handler2 = mock(() => {})
|
|
86
|
-
|
|
87
|
-
emitter.on('event1', handler1)
|
|
88
|
-
emitter.on('event2', handler2)
|
|
89
|
-
|
|
90
|
-
emitter.emit('event1')
|
|
91
|
-
|
|
92
|
-
expect(handler1).toHaveBeenCalledTimes(1)
|
|
93
|
-
expect(handler2).not.toHaveBeenCalled()
|
|
94
|
-
|
|
95
|
-
emitter.emit('event2')
|
|
96
|
-
|
|
97
|
-
expect(handler1).toHaveBeenCalledTimes(1)
|
|
98
|
-
expect(handler2).toHaveBeenCalledTimes(1)
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
test('should clear all event handlers', () => {
|
|
102
|
-
const emitter = createEmitter()
|
|
103
|
-
const handler1 = mock(() => {})
|
|
104
|
-
const handler2 = mock(() => {})
|
|
105
|
-
|
|
106
|
-
emitter.on('event1', handler1)
|
|
107
|
-
emitter.on('event2', handler2)
|
|
108
|
-
|
|
109
|
-
emitter.clear()
|
|
110
|
-
|
|
111
|
-
emitter.emit('event1')
|
|
112
|
-
emitter.emit('event2')
|
|
113
|
-
|
|
114
|
-
expect(handler1).not.toHaveBeenCalled()
|
|
115
|
-
expect(handler2).not.toHaveBeenCalled()
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
test('should pass multiple arguments to handlers', () => {
|
|
119
|
-
const emitter = createEmitter()
|
|
120
|
-
const handler = mock(() => {})
|
|
121
|
-
|
|
122
|
-
emitter.on('test', handler)
|
|
123
|
-
|
|
124
|
-
const arg1 = { id: 1 }
|
|
125
|
-
const arg2 = 'string'
|
|
126
|
-
const arg3 = [1, 2, 3]
|
|
127
|
-
|
|
128
|
-
emitter.emit('test', arg1, arg2, arg3)
|
|
129
|
-
|
|
130
|
-
expect(handler).toHaveBeenCalledWith(arg1, arg2, arg3)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
test('should do nothing when emitting event with no handlers', () => {
|
|
134
|
-
const emitter = createEmitter()
|
|
135
|
-
|
|
136
|
-
// This should not throw
|
|
137
|
-
expect(() => {
|
|
138
|
-
emitter.emit('nonexistent')
|
|
139
|
-
}).not.toThrow()
|
|
140
|
-
})
|
|
141
|
-
})
|
package/test/core/ripple.test.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
// test/core/ripple.test.js
|
|
2
|
-
import { describe, test, expect, mock } from 'bun:test'
|
|
3
|
-
import { createRipple } from '../../src/core/build/ripple'
|
|
4
|
-
|
|
5
|
-
describe('Ripple Effect', () => {
|
|
6
|
-
test('should create a ripple controller', () => {
|
|
7
|
-
const ripple = createRipple()
|
|
8
|
-
expect(ripple).toBeDefined()
|
|
9
|
-
expect(typeof ripple.mount).toBe('function')
|
|
10
|
-
expect(typeof ripple.unmount).toBe('function')
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
test('should mount ripple effect to an element', () => {
|
|
14
|
-
const ripple = createRipple()
|
|
15
|
-
const element = document.createElement('div')
|
|
16
|
-
|
|
17
|
-
// Mount ripple to element
|
|
18
|
-
ripple.mount(element)
|
|
19
|
-
|
|
20
|
-
// Position should now be relative for proper ripple positioning
|
|
21
|
-
expect(element.style.position).toBe('relative')
|
|
22
|
-
expect(element.style.overflow).toBe('hidden')
|
|
23
|
-
|
|
24
|
-
// We can only verify that addEventListener was called in this mocked environment
|
|
25
|
-
// Not checking element.__handlers which may not be available in all environments
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test('should not fail when mounting to a null element', () => {
|
|
29
|
-
const ripple = createRipple()
|
|
30
|
-
expect(() => ripple.mount(null)).not.toThrow()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
test('should create ripple element on mousedown', () => {
|
|
34
|
-
// Skip this test as it requires more advanced DOM mocking
|
|
35
|
-
// than we currently have available
|
|
36
|
-
console.log('Skipping "should create ripple element on mousedown" test - requires advanced DOM mocking')
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
test('should add document cleanup event listeners', () => {
|
|
40
|
-
// Skip this test as it requires more advanced DOM mocking
|
|
41
|
-
// than we currently have available
|
|
42
|
-
console.log('Skipping "should add document cleanup event listeners" test - requires advanced DOM mocking')
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
test('should remove ripple elements on unmount', () => {
|
|
46
|
-
const ripple = createRipple()
|
|
47
|
-
const element = document.createElement('div')
|
|
48
|
-
|
|
49
|
-
// Add a mock ripple element
|
|
50
|
-
const rippleElement = document.createElement('div')
|
|
51
|
-
rippleElement.className = 'ripple'
|
|
52
|
-
element.appendChild(rippleElement)
|
|
53
|
-
|
|
54
|
-
// Mount and then unmount
|
|
55
|
-
ripple.mount(element)
|
|
56
|
-
ripple.unmount(element)
|
|
57
|
-
|
|
58
|
-
// After unmount, ripple elements should be removed
|
|
59
|
-
expect(element.children.length).toBe(0)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
test('should not fail when unmounting a null element', () => {
|
|
63
|
-
const ripple = createRipple()
|
|
64
|
-
expect(() => ripple.unmount(null)).not.toThrow()
|
|
65
|
-
})
|
|
66
|
-
})
|