mtrl 0.0.2 → 0.0.3

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.
@@ -0,0 +1,234 @@
1
+ // test/components/snackbar.test.js
2
+ import { describe, test, expect, mock, spyOn, beforeEach, afterEach } from 'bun:test'
3
+ import createSnackbar from '../../src/components/snackbar/snackbar'
4
+ import { SNACKBAR_VARIANTS, SNACKBAR_POSITIONS } from '../../src/components/snackbar/constants'
5
+
6
+ describe('Snackbar Component', () => {
7
+ let originalBody
8
+ let mockBodyAppendChild
9
+ let mockBodyRemoveChild
10
+
11
+ beforeEach(() => {
12
+ // Mock document.body methods for testing
13
+ originalBody = document.body
14
+ mockBodyAppendChild = mock(() => {})
15
+ mockBodyRemoveChild = mock(() => {})
16
+
17
+ Object.defineProperty(document, 'body', {
18
+ value: {
19
+ appendChild: mockBodyAppendChild,
20
+ removeChild: mockBodyRemoveChild,
21
+ children: []
22
+ },
23
+ writable: true
24
+ })
25
+ })
26
+
27
+ afterEach(() => {
28
+ // Restore original document.body
29
+ Object.defineProperty(document, 'body', {
30
+ value: originalBody,
31
+ writable: true
32
+ })
33
+ })
34
+
35
+ test('should create a snackbar element', () => {
36
+ const snackbar = createSnackbar({
37
+ message: 'Test message'
38
+ })
39
+
40
+ expect(snackbar.element).toBeDefined()
41
+ expect(snackbar.element.tagName).toBe('DIV')
42
+ expect(snackbar.element.className).toContain('mtrl-snackbar')
43
+ })
44
+
45
+ test('should apply variant class', () => {
46
+ const variant = SNACKBAR_VARIANTS.ACTION
47
+ const snackbar = createSnackbar({
48
+ message: 'Test message',
49
+ variant
50
+ })
51
+
52
+ expect(snackbar.config.variant).toBe(variant)
53
+ })
54
+
55
+ test('should use basic as default variant', () => {
56
+ const snackbar = createSnackbar({
57
+ message: 'Test message'
58
+ })
59
+
60
+ expect(snackbar.config.variant).toBe(SNACKBAR_VARIANTS.BASIC)
61
+ })
62
+
63
+ test('should apply position class', () => {
64
+ const position = SNACKBAR_POSITIONS.START
65
+ const snackbar = createSnackbar({
66
+ message: 'Test message',
67
+ position
68
+ })
69
+
70
+ expect(snackbar.config.position).toBe(position)
71
+ })
72
+
73
+ test('should use center as default position', () => {
74
+ const snackbar = createSnackbar({
75
+ message: 'Test message'
76
+ })
77
+
78
+ expect(snackbar.config.position).toBe(SNACKBAR_POSITIONS.CENTER)
79
+ })
80
+
81
+ test('should set message text', () => {
82
+ const message = 'Test message'
83
+ const snackbar = createSnackbar({
84
+ message
85
+ })
86
+
87
+ expect(snackbar.config.message).toBe(message)
88
+ expect(typeof snackbar.getMessage).toBe('function')
89
+ })
90
+
91
+ test('should add action button when specified', () => {
92
+ const action = 'Undo'
93
+ const snackbar = createSnackbar({
94
+ message: 'Action completed',
95
+ action
96
+ })
97
+
98
+ expect(snackbar.actionButton).toBeDefined()
99
+ expect(snackbar.actionButton.textContent).toBe(action)
100
+ })
101
+
102
+ test('should not add action button when not specified', () => {
103
+ const snackbar = createSnackbar({
104
+ message: 'Simple message'
105
+ })
106
+
107
+ expect(snackbar.actionButton).toBeUndefined()
108
+ })
109
+
110
+ test('should set default duration when not specified', () => {
111
+ const snackbar = createSnackbar({
112
+ message: 'Test message'
113
+ })
114
+
115
+ expect(snackbar.config.duration).toBe(4000)
116
+ })
117
+
118
+ test('should respect custom duration', () => {
119
+ const duration = 2000
120
+ const snackbar = createSnackbar({
121
+ message: 'Test message',
122
+ duration
123
+ })
124
+
125
+ expect(snackbar.config.duration).toBe(duration)
126
+ })
127
+
128
+ test('should allow duration of 0 (no auto-dismiss)', () => {
129
+ const snackbar = createSnackbar({
130
+ message: 'Test message',
131
+ duration: 0
132
+ })
133
+
134
+ expect(snackbar.config.duration).toBe(0)
135
+ })
136
+
137
+ test('should register event handlers', () => {
138
+ const snackbar = createSnackbar({
139
+ message: 'Test message'
140
+ })
141
+
142
+ // Verify event API exists
143
+ expect(typeof snackbar.on).toBe('function')
144
+ expect(typeof snackbar.off).toBe('function')
145
+
146
+ // Check event handling
147
+ const handler = mock(() => {})
148
+ snackbar.on('dismiss', handler)
149
+
150
+ // Trigger dismiss event
151
+ snackbar.emit && snackbar.emit('dismiss')
152
+
153
+ if (snackbar.emit) {
154
+ expect(handler).toHaveBeenCalled()
155
+ }
156
+ })
157
+
158
+ test('should expose show and hide methods', () => {
159
+ const snackbar = createSnackbar({
160
+ message: 'Test message'
161
+ })
162
+
163
+ expect(typeof snackbar.show).toBe('function')
164
+ expect(typeof snackbar.hide).toBe('function')
165
+ })
166
+
167
+ test('should allow updating message', () => {
168
+ const initialMessage = 'Initial message'
169
+ const snackbar = createSnackbar({
170
+ message: initialMessage
171
+ })
172
+
173
+ expect(snackbar.getMessage()).toBe(initialMessage)
174
+
175
+ const updatedMessage = 'Updated message'
176
+ snackbar.setMessage(updatedMessage)
177
+
178
+ expect(snackbar.getMessage()).toBe(updatedMessage)
179
+ })
180
+
181
+ test('should have dismiss timer functionality', () => {
182
+ const snackbar = createSnackbar({
183
+ message: 'Test message'
184
+ })
185
+
186
+ expect(snackbar.timer).toBeDefined()
187
+ expect(typeof snackbar.timer.start).toBe('function')
188
+ expect(typeof snackbar.timer.stop).toBe('function')
189
+ })
190
+
191
+ test('should have an API for position management', () => {
192
+ const snackbar = createSnackbar({
193
+ message: 'Test message'
194
+ })
195
+
196
+ expect(snackbar.position).toBeDefined()
197
+
198
+ if (snackbar.position) {
199
+ expect(typeof snackbar.position.getPosition).toBe('function')
200
+ expect(typeof snackbar.position.setPosition).toBe('function')
201
+ }
202
+ })
203
+
204
+ test('should clean up resources on destroy', () => {
205
+ const snackbar = createSnackbar({
206
+ message: 'Test message'
207
+ })
208
+
209
+ expect(typeof snackbar.destroy).toBe('function')
210
+
211
+ // Mock any internal methods that might be called during destroy
212
+ if (snackbar.timer) {
213
+ snackbar.timer.stop = mock(snackbar.timer.stop)
214
+ }
215
+
216
+ // Call destroy
217
+ snackbar.destroy()
218
+
219
+ // Check if timer was stopped
220
+ if (snackbar.timer && typeof snackbar.timer.stop === 'function') {
221
+ expect(snackbar.timer.stop).toHaveBeenCalled()
222
+ }
223
+ })
224
+
225
+ test('should apply custom class', () => {
226
+ const customClass = 'custom-snackbar'
227
+ const snackbar = createSnackbar({
228
+ message: 'Test message',
229
+ class: customClass
230
+ })
231
+
232
+ expect(snackbar.element.className).toContain(customClass)
233
+ })
234
+ })
@@ -0,0 +1,186 @@
1
+ // test/components/switch.test.js
2
+ import { describe, test, expect, mock } from 'bun:test'
3
+ import createSwitch from '../../src/components/switch/switch'
4
+ import { SWITCH_LABEL_POSITION } from '../../src/components/switch/constants'
5
+
6
+ describe('Switch Component', () => {
7
+ test('should create a switch element', () => {
8
+ const switchComp = createSwitch()
9
+ expect(switchComp.element).toBeDefined()
10
+ expect(switchComp.element.tagName).toBe('DIV')
11
+ expect(switchComp.element.className).toContain('mtrl-switch')
12
+ })
13
+
14
+ test('should create input element with type checkbox', () => {
15
+ const switchComp = createSwitch()
16
+
17
+ // Check for input through direct property
18
+ expect(switchComp.input).toBeDefined()
19
+ expect(switchComp.input.type).toBe('checkbox')
20
+ })
21
+
22
+ test('should apply custom class', () => {
23
+ const customClass = 'custom-switch'
24
+ const switchComp = createSwitch({
25
+ class: customClass
26
+ })
27
+
28
+ expect(switchComp.element.className).toContain(customClass)
29
+ })
30
+
31
+ test('should add label content through config', () => {
32
+ const labelText = 'Toggle me'
33
+ const switchComp = createSwitch({
34
+ label: labelText
35
+ })
36
+
37
+ // Check config has label
38
+ expect(switchComp.config.label).toBe(labelText)
39
+ })
40
+
41
+ test('should position label correctly', () => {
42
+ // Test if the configuration is stored correctly
43
+ const startPos = SWITCH_LABEL_POSITION.START
44
+ const startSwitch = createSwitch({
45
+ label: 'Label at Start',
46
+ labelPosition: startPos
47
+ })
48
+
49
+ // Check label position in config
50
+ expect(startSwitch.config.labelPosition).toBe(startPos)
51
+
52
+ // Check class is applied
53
+ expect(startSwitch.element.className).toContain('mtrl-switch--label-start')
54
+
55
+ // Default position (end)
56
+ const endSwitch = createSwitch({
57
+ label: 'Label at End'
58
+ })
59
+
60
+ expect(endSwitch.element.className).toContain('mtrl-switch--label-end')
61
+ })
62
+
63
+ test('should handle change events', () => {
64
+ const switchComp = createSwitch()
65
+ const handleChange = mock(() => {})
66
+
67
+ // Check if the event handler is registered
68
+ switchComp.on('change', handleChange)
69
+
70
+ // Simulate change by calling the emit method if it exists
71
+ if (switchComp.emit) {
72
+ switchComp.emit('change', {})
73
+ expect(handleChange).toHaveBeenCalled()
74
+ }
75
+ })
76
+
77
+ test('should support disabled state', () => {
78
+ const switchComp = createSwitch()
79
+
80
+ // Check API methods
81
+ expect(typeof switchComp.disable).toBe('function')
82
+ expect(typeof switchComp.enable).toBe('function')
83
+
84
+ // Test the API methods without making assumptions about implementation
85
+ switchComp.disable()
86
+ switchComp.enable()
87
+
88
+ // Test initially disabled through config
89
+ const disabledSwitch = createSwitch({ disabled: true })
90
+ expect(disabledSwitch.config.disabled).toBe(true)
91
+ })
92
+
93
+ test('should support checked state', () => {
94
+ // Check API methods
95
+ const switchComp = createSwitch()
96
+ expect(typeof switchComp.check).toBe('function')
97
+ expect(typeof switchComp.uncheck).toBe('function')
98
+ expect(typeof switchComp.toggle).toBe('function')
99
+
100
+ // Initial unchecked state
101
+ const uncheckedSwitch = createSwitch()
102
+ expect(uncheckedSwitch.config.checked).toBeFalsy()
103
+
104
+ // Initial checked state
105
+ const checkedSwitch = createSwitch({ checked: true })
106
+ expect(checkedSwitch.config.checked).toBe(true)
107
+
108
+ // Verify methods execute without errors
109
+ switchComp.check()
110
+ switchComp.uncheck()
111
+ switchComp.toggle()
112
+ })
113
+
114
+ test('should set name attribute correctly', () => {
115
+ const name = 'theme-toggle'
116
+ const switchComp = createSwitch({ name })
117
+
118
+ // Check config
119
+ expect(switchComp.config.name).toBe(name)
120
+ })
121
+
122
+ test('should set value attribute correctly', () => {
123
+ const value = 'dark-mode'
124
+ const switchComp = createSwitch({ value })
125
+
126
+ // Check config
127
+ expect(switchComp.config.value).toBe(value)
128
+ })
129
+
130
+ test('should set required attribute correctly', () => {
131
+ const switchComp = createSwitch({ required: true })
132
+
133
+ // Check config
134
+ expect(switchComp.config.required).toBe(true)
135
+ })
136
+
137
+ test('should allow updating label', () => {
138
+ const initialLabel = 'Initial Label'
139
+ const switchComp = createSwitch({
140
+ label: initialLabel
141
+ })
142
+
143
+ // Check initial label in config
144
+ expect(switchComp.config.label).toBe(initialLabel)
145
+
146
+ // Check setLabel method exists
147
+ expect(typeof switchComp.setLabel).toBe('function')
148
+
149
+ // Update label
150
+ const newLabel = 'Updated Label'
151
+ switchComp.setLabel(newLabel)
152
+ })
153
+
154
+ test('should include track and thumb elements', () => {
155
+ const switchComp = createSwitch()
156
+
157
+ // Check for track - it might be directly accessible or through the DOM
158
+ const hasTrack = switchComp.track !== undefined ||
159
+ switchComp.element.querySelector('.mtrl-switch-track') !== null
160
+
161
+ expect(hasTrack).toBe(true)
162
+ })
163
+
164
+ test('should have value getter and setter', () => {
165
+ const switchComp = createSwitch()
166
+
167
+ // Check API methods
168
+ expect(typeof switchComp.getValue).toBe('function')
169
+ expect(typeof switchComp.setValue).toBe('function')
170
+
171
+ // Set a value
172
+ const testValue = 'test-value'
173
+ switchComp.setValue(testValue)
174
+ })
175
+
176
+ test('should properly clean up resources', () => {
177
+ const switchComp = createSwitch()
178
+ const parentElement = document.createElement('div')
179
+ parentElement.appendChild(switchComp.element)
180
+
181
+ // Destroy should remove the element and clean up resources
182
+ switchComp.destroy()
183
+
184
+ expect(parentElement.children.length).toBe(0)
185
+ })
186
+ })