@domql/element 3.4.5 → 3.4.9
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/event/__tests__/applyAnimationFrame.test.js +114 -0
- package/event/__tests__/applyEvent.test.js +159 -0
- package/event/__tests__/applyEventUpdate.test.js +198 -0
- package/event/__tests__/applyEventsOnNode.test.js +216 -0
- package/event/__tests__/canRenderTag.test.js +50 -0
- package/event/__tests__/index.test.js +39 -0
- package/event/__tests__/initAnimationFrame.test.js +156 -0
- package/event/__tests__/registerFrameListener.test.js +97 -0
- package/event/__tests__/store.test.js +93 -0
- package/event/__tests__/triggerEventOn.test.js +195 -0
- package/event/__tests__/triggerEventOnUpdate.test.js +207 -0
- package/event/animationFrame.js +92 -0
- package/event/can.js +8 -0
- package/event/index.js +5 -0
- package/event/on.js +71 -0
- package/event/store.js +6 -0
- package/methods/set.js +73 -0
- package/methods/v2.js +83 -0
- package/mixins/attr.js +32 -0
- package/mixins/classList.js +62 -0
- package/mixins/content.js +65 -0
- package/mixins/data.js +26 -0
- package/mixins/html.js +19 -0
- package/mixins/index.js +23 -0
- package/mixins/registry.js +46 -0
- package/mixins/scope.js +23 -0
- package/mixins/state.js +18 -0
- package/mixins/style.js +25 -0
- package/mixins/text.js +31 -0
- package/package.json +13 -8
- package/render/__tests__/appendNode.test.js +53 -0
- package/render/__tests__/assignNode.test.js +151 -0
- package/render/__tests__/cacheNode.test.js +168 -0
- package/render/__tests__/createHTMLNode.test.js +118 -0
- package/render/__tests__/createNode.test.js +9 -0
- package/render/__tests__/detectTag.test.js +99 -0
- package/render/__tests__/index.test.js +56 -0
- package/render/__tests__/insertNodeAfter.test.js +111 -0
- package/render/__tests__/insertNodeBefore.test.js +65 -0
- package/render/append.js +61 -0
- package/render/cache.js +68 -0
- package/render/create.js +3 -0
- package/render/index.js +5 -0
- package/utils/applyParam.js +33 -0
- package/utils/extendUtils.js +135 -0
- package/utils/index.js +4 -0
- package/utils/propEvents.js +36 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { applyAnimationFrame } from '../animationFrame'
|
|
2
|
+
|
|
3
|
+
describe('applyAnimationFrame', () => {
|
|
4
|
+
let mockElement
|
|
5
|
+
let mockFrameListeners
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
// Reset frameListeners
|
|
9
|
+
mockFrameListeners = new Set()
|
|
10
|
+
|
|
11
|
+
// Create a mock element with the required structure
|
|
12
|
+
mockElement = {
|
|
13
|
+
props: {},
|
|
14
|
+
on: {},
|
|
15
|
+
__ref: {
|
|
16
|
+
root: {
|
|
17
|
+
data: {
|
|
18
|
+
frameListeners: mockFrameListeners
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('error handling', () => {
|
|
26
|
+
test('should throw error when element is null', () => {
|
|
27
|
+
expect(() => {
|
|
28
|
+
applyAnimationFrame(null)
|
|
29
|
+
}).toThrow('Element is invalid')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('should throw error when element is undefined', () => {
|
|
33
|
+
expect(() => {
|
|
34
|
+
applyAnimationFrame(undefined)
|
|
35
|
+
}).toThrow('Element is invalid')
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
describe('early returns', () => {
|
|
40
|
+
test('should not modify frameListeners when ref.root is undefined', () => {
|
|
41
|
+
// Arrange
|
|
42
|
+
mockElement.__ref.root = undefined
|
|
43
|
+
|
|
44
|
+
// Act
|
|
45
|
+
applyAnimationFrame(mockElement)
|
|
46
|
+
|
|
47
|
+
// Assert
|
|
48
|
+
expect(mockFrameListeners.size).toBe(0)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('should not modify frameListeners when ref.root.data is undefined', () => {
|
|
52
|
+
// Arrange
|
|
53
|
+
mockElement.__ref.root.data = undefined
|
|
54
|
+
|
|
55
|
+
// Act
|
|
56
|
+
applyAnimationFrame(mockElement)
|
|
57
|
+
|
|
58
|
+
// Assert
|
|
59
|
+
expect(mockFrameListeners.size).toBe(0)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
describe('frame listener registration', () => {
|
|
64
|
+
test('should add element to frameListeners when on.frame exists', () => {
|
|
65
|
+
// Arrange
|
|
66
|
+
mockElement.on.frame = () => {}
|
|
67
|
+
expect(mockFrameListeners.size).toBe(0)
|
|
68
|
+
|
|
69
|
+
// Act
|
|
70
|
+
applyAnimationFrame(mockElement)
|
|
71
|
+
|
|
72
|
+
// Assert
|
|
73
|
+
expect(mockFrameListeners.size).toBe(1)
|
|
74
|
+
expect(mockFrameListeners.has(mockElement)).toBe(true)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('should not modify frameListeners when neither on.frame nor props.onFrame exist', () => {
|
|
78
|
+
// Arrange
|
|
79
|
+
expect(mockFrameListeners.size).toBe(0)
|
|
80
|
+
|
|
81
|
+
// Act
|
|
82
|
+
applyAnimationFrame(mockElement)
|
|
83
|
+
|
|
84
|
+
// Assert
|
|
85
|
+
expect(mockFrameListeners.size).toBe(0)
|
|
86
|
+
expect(mockFrameListeners.has(mockElement)).toBe(false)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('should not modify frameListeners when frameListeners is undefined', () => {
|
|
90
|
+
// Arrange
|
|
91
|
+
mockElement.on.frame = () => {}
|
|
92
|
+
mockElement.__ref.root.data.frameListeners = undefined
|
|
93
|
+
|
|
94
|
+
// Act
|
|
95
|
+
applyAnimationFrame(mockElement)
|
|
96
|
+
|
|
97
|
+
// Assert - Verify no error is thrown and original state is maintained
|
|
98
|
+
expect(mockElement.__ref.root.data.frameListeners).toBeUndefined()
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('should add element to frameListeners only once when both on.frame exist', () => {
|
|
102
|
+
// Arrange
|
|
103
|
+
mockElement.on.frame = () => {}
|
|
104
|
+
expect(mockFrameListeners.size).toBe(0)
|
|
105
|
+
|
|
106
|
+
// Act
|
|
107
|
+
applyAnimationFrame(mockElement)
|
|
108
|
+
|
|
109
|
+
// Assert
|
|
110
|
+
expect(mockFrameListeners.size).toBe(1)
|
|
111
|
+
expect(mockFrameListeners.has(mockElement)).toBe(true)
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
})
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
import { applyEvent } from '../on'
|
|
3
|
+
|
|
4
|
+
describe('applyEvent', () => {
|
|
5
|
+
let mockElement
|
|
6
|
+
let mockParam
|
|
7
|
+
let mockState
|
|
8
|
+
let mockContext
|
|
9
|
+
let mockOptions
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// Create a mock element with state and context
|
|
13
|
+
mockElement = {
|
|
14
|
+
state: { elementState: 'default' },
|
|
15
|
+
context: { elementContext: 'default' }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Create a spy function for param
|
|
19
|
+
mockParam = jest.fn().mockReturnValue('eventResult')
|
|
20
|
+
|
|
21
|
+
// Create mock state and context
|
|
22
|
+
mockState = { customState: 'test' }
|
|
23
|
+
mockContext = { customContext: 'test' }
|
|
24
|
+
mockOptions = { option1: 'value1' }
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('should call param with provided element and default state/context', () => {
|
|
28
|
+
// Act
|
|
29
|
+
const result = applyEvent(mockParam, mockElement)
|
|
30
|
+
|
|
31
|
+
// Assert
|
|
32
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
33
|
+
mockElement,
|
|
34
|
+
mockElement.state,
|
|
35
|
+
mockElement.context,
|
|
36
|
+
undefined
|
|
37
|
+
)
|
|
38
|
+
expect(result).toBe('eventResult')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('should use provided state instead of element state', () => {
|
|
42
|
+
// Act
|
|
43
|
+
const result = applyEvent(mockParam, mockElement, mockState)
|
|
44
|
+
|
|
45
|
+
// Assert
|
|
46
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
47
|
+
mockElement,
|
|
48
|
+
mockState,
|
|
49
|
+
mockElement.context,
|
|
50
|
+
undefined
|
|
51
|
+
)
|
|
52
|
+
expect(result).toBe('eventResult')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('should use provided context instead of element context', () => {
|
|
56
|
+
// Act
|
|
57
|
+
const result = applyEvent(mockParam, mockElement, null, mockContext)
|
|
58
|
+
|
|
59
|
+
// Assert
|
|
60
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
61
|
+
mockElement,
|
|
62
|
+
mockElement.state,
|
|
63
|
+
mockContext,
|
|
64
|
+
undefined
|
|
65
|
+
)
|
|
66
|
+
expect(result).toBe('eventResult')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('should pass through options parameter', () => {
|
|
70
|
+
// Act
|
|
71
|
+
const result = applyEvent(mockParam, mockElement, null, null, mockOptions)
|
|
72
|
+
|
|
73
|
+
// Assert
|
|
74
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
75
|
+
mockElement,
|
|
76
|
+
mockElement.state,
|
|
77
|
+
mockElement.context,
|
|
78
|
+
mockOptions
|
|
79
|
+
)
|
|
80
|
+
expect(result).toBe('eventResult')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('should handle undefined element state and context', () => {
|
|
84
|
+
// Arrange
|
|
85
|
+
const elementWithoutStateContext = {}
|
|
86
|
+
|
|
87
|
+
// Act
|
|
88
|
+
const result = applyEvent(mockParam, elementWithoutStateContext)
|
|
89
|
+
|
|
90
|
+
// Assert
|
|
91
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
92
|
+
elementWithoutStateContext,
|
|
93
|
+
undefined,
|
|
94
|
+
undefined,
|
|
95
|
+
undefined
|
|
96
|
+
)
|
|
97
|
+
expect(result).toBe('eventResult')
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('should handle all custom parameters', () => {
|
|
101
|
+
// Act
|
|
102
|
+
const result = applyEvent(
|
|
103
|
+
mockParam,
|
|
104
|
+
mockElement,
|
|
105
|
+
mockState,
|
|
106
|
+
mockContext,
|
|
107
|
+
mockOptions
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
// Assert
|
|
111
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
112
|
+
mockElement,
|
|
113
|
+
mockState,
|
|
114
|
+
mockContext,
|
|
115
|
+
mockOptions
|
|
116
|
+
)
|
|
117
|
+
expect(result).toBe('eventResult')
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('should handle null state and use element state', () => {
|
|
121
|
+
// Act
|
|
122
|
+
const result = applyEvent(mockParam, mockElement, null)
|
|
123
|
+
|
|
124
|
+
// Assert
|
|
125
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
126
|
+
mockElement,
|
|
127
|
+
mockElement.state,
|
|
128
|
+
mockElement.context,
|
|
129
|
+
undefined
|
|
130
|
+
)
|
|
131
|
+
expect(result).toBe('eventResult')
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
test('should handle null context and use element context', () => {
|
|
135
|
+
// Act
|
|
136
|
+
const result = applyEvent(mockParam, mockElement, mockState, null)
|
|
137
|
+
|
|
138
|
+
// Assert
|
|
139
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
140
|
+
mockElement,
|
|
141
|
+
mockState,
|
|
142
|
+
mockElement.context,
|
|
143
|
+
undefined
|
|
144
|
+
)
|
|
145
|
+
expect(result).toBe('eventResult')
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test('should preserve param return value', () => {
|
|
149
|
+
// Arrange
|
|
150
|
+
const expectedReturn = { custom: 'return value' }
|
|
151
|
+
mockParam.mockReturnValue(expectedReturn)
|
|
152
|
+
|
|
153
|
+
// Act
|
|
154
|
+
const result = applyEvent(mockParam, mockElement)
|
|
155
|
+
|
|
156
|
+
// Assert
|
|
157
|
+
expect(result).toBe(expectedReturn)
|
|
158
|
+
})
|
|
159
|
+
})
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
import { applyEventUpdate } from '../on'
|
|
3
|
+
|
|
4
|
+
describe('applyEventUpdate', () => {
|
|
5
|
+
let mockElement
|
|
6
|
+
let mockParam
|
|
7
|
+
let mockUpdatedObj
|
|
8
|
+
let mockState
|
|
9
|
+
let mockContext
|
|
10
|
+
let mockOptions
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
// Setup mock element with default state and context
|
|
14
|
+
mockElement = {
|
|
15
|
+
state: { elementState: 'default' },
|
|
16
|
+
context: { elementContext: 'default' }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Create mock event handler
|
|
20
|
+
mockParam = jest.fn().mockReturnValue('eventResult')
|
|
21
|
+
|
|
22
|
+
// Setup other test parameters
|
|
23
|
+
mockUpdatedObj = { updated: 'value' }
|
|
24
|
+
mockState = { customState: 'test' }
|
|
25
|
+
mockContext = { customContext: 'test' }
|
|
26
|
+
mockOptions = { option1: 'value1' }
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('should call param with all provided parameters', () => {
|
|
30
|
+
// Act
|
|
31
|
+
const result = applyEventUpdate(
|
|
32
|
+
mockParam,
|
|
33
|
+
mockUpdatedObj,
|
|
34
|
+
mockElement,
|
|
35
|
+
mockState,
|
|
36
|
+
mockContext,
|
|
37
|
+
mockOptions
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
// Assert
|
|
41
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
42
|
+
mockUpdatedObj,
|
|
43
|
+
mockElement,
|
|
44
|
+
mockState,
|
|
45
|
+
mockContext,
|
|
46
|
+
mockOptions
|
|
47
|
+
)
|
|
48
|
+
expect(result).toBe('eventResult')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('should use element state when state is not provided', () => {
|
|
52
|
+
// Act
|
|
53
|
+
const result = applyEventUpdate(
|
|
54
|
+
mockParam,
|
|
55
|
+
mockUpdatedObj,
|
|
56
|
+
mockElement,
|
|
57
|
+
null,
|
|
58
|
+
mockContext,
|
|
59
|
+
mockOptions
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
// Assert
|
|
63
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
64
|
+
mockUpdatedObj,
|
|
65
|
+
mockElement,
|
|
66
|
+
mockElement.state,
|
|
67
|
+
mockContext,
|
|
68
|
+
mockOptions
|
|
69
|
+
)
|
|
70
|
+
expect(result).toBe('eventResult')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('should use element context when context is not provided', () => {
|
|
74
|
+
// Act
|
|
75
|
+
const result = applyEventUpdate(
|
|
76
|
+
mockParam,
|
|
77
|
+
mockUpdatedObj,
|
|
78
|
+
mockElement,
|
|
79
|
+
mockState,
|
|
80
|
+
null,
|
|
81
|
+
mockOptions
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
// Assert
|
|
85
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
86
|
+
mockUpdatedObj,
|
|
87
|
+
mockElement,
|
|
88
|
+
mockState,
|
|
89
|
+
mockElement.context,
|
|
90
|
+
mockOptions
|
|
91
|
+
)
|
|
92
|
+
expect(result).toBe('eventResult')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('should handle undefined state and context in element', () => {
|
|
96
|
+
// Arrange
|
|
97
|
+
const elementWithoutStateContext = {}
|
|
98
|
+
|
|
99
|
+
// Act
|
|
100
|
+
const result = applyEventUpdate(
|
|
101
|
+
mockParam,
|
|
102
|
+
mockUpdatedObj,
|
|
103
|
+
elementWithoutStateContext,
|
|
104
|
+
null,
|
|
105
|
+
null,
|
|
106
|
+
mockOptions
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
// Assert
|
|
110
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
111
|
+
mockUpdatedObj,
|
|
112
|
+
elementWithoutStateContext,
|
|
113
|
+
undefined,
|
|
114
|
+
undefined,
|
|
115
|
+
mockOptions
|
|
116
|
+
)
|
|
117
|
+
expect(result).toBe('eventResult')
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('should handle missing options parameter', () => {
|
|
121
|
+
// Act
|
|
122
|
+
const result = applyEventUpdate(
|
|
123
|
+
mockParam,
|
|
124
|
+
mockUpdatedObj,
|
|
125
|
+
mockElement,
|
|
126
|
+
mockState,
|
|
127
|
+
mockContext
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
// Assert
|
|
131
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
132
|
+
mockUpdatedObj,
|
|
133
|
+
mockElement,
|
|
134
|
+
mockState,
|
|
135
|
+
mockContext,
|
|
136
|
+
undefined
|
|
137
|
+
)
|
|
138
|
+
expect(result).toBe('eventResult')
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test('should preserve function context (this binding)', () => {
|
|
142
|
+
// Arrange
|
|
143
|
+
mockParam = jest.fn(function () {
|
|
144
|
+
return this === mockElement
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
// Act
|
|
148
|
+
const result = applyEventUpdate(
|
|
149
|
+
mockParam,
|
|
150
|
+
mockUpdatedObj,
|
|
151
|
+
mockElement,
|
|
152
|
+
mockState,
|
|
153
|
+
mockContext
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
// Assert
|
|
157
|
+
expect(result).toBe(true)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
test('should handle empty updatedObj', () => {
|
|
161
|
+
// Act
|
|
162
|
+
const result = applyEventUpdate(
|
|
163
|
+
mockParam,
|
|
164
|
+
{},
|
|
165
|
+
mockElement,
|
|
166
|
+
mockState,
|
|
167
|
+
mockContext
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
// Assert
|
|
171
|
+
expect(mockParam).toHaveBeenCalledWith(
|
|
172
|
+
{},
|
|
173
|
+
mockElement,
|
|
174
|
+
mockState,
|
|
175
|
+
mockContext,
|
|
176
|
+
undefined
|
|
177
|
+
)
|
|
178
|
+
expect(result).toBe('eventResult')
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
test('should pass through return value from param', () => {
|
|
182
|
+
// Arrange
|
|
183
|
+
const expectedReturn = { custom: 'return value' }
|
|
184
|
+
mockParam.mockReturnValue(expectedReturn)
|
|
185
|
+
|
|
186
|
+
// Act
|
|
187
|
+
const result = applyEventUpdate(
|
|
188
|
+
mockParam,
|
|
189
|
+
mockUpdatedObj,
|
|
190
|
+
mockElement,
|
|
191
|
+
mockState,
|
|
192
|
+
mockContext
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
// Assert
|
|
196
|
+
expect(result).toBe(expectedReturn)
|
|
197
|
+
})
|
|
198
|
+
})
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
import { applyEventsOnNode } from '../on'
|
|
3
|
+
|
|
4
|
+
describe('applyEventsOnNode', () => {
|
|
5
|
+
let mockElement
|
|
6
|
+
let mockNode
|
|
7
|
+
let mockEventHandler
|
|
8
|
+
let mockOptions
|
|
9
|
+
let addEventListenerSpy
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// Create mock event handler (sync)
|
|
13
|
+
mockEventHandler = jest.fn().mockReturnValue('eventResult')
|
|
14
|
+
|
|
15
|
+
// Create mock node with addEventListener
|
|
16
|
+
mockNode = {
|
|
17
|
+
addEventListener: jest.fn((eventName, handler) => {
|
|
18
|
+
// Store the handler for testing
|
|
19
|
+
mockNode.handlers = mockNode.handlers || {}
|
|
20
|
+
mockNode.handlers[eventName] = handler
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
addEventListenerSpy = jest.spyOn(mockNode, 'addEventListener')
|
|
25
|
+
|
|
26
|
+
// Create mock element
|
|
27
|
+
mockElement = {
|
|
28
|
+
node: mockNode,
|
|
29
|
+
state: { testState: 'state' },
|
|
30
|
+
context: { testContext: 'context' },
|
|
31
|
+
on: {},
|
|
32
|
+
props: {}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
mockOptions = { option1: 'value1' }
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
jest.clearAllMocks()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
describe('event registration', () => {
|
|
43
|
+
test('should register click event listener', () => {
|
|
44
|
+
// Arrange
|
|
45
|
+
mockElement.on.click = mockEventHandler
|
|
46
|
+
|
|
47
|
+
// Act
|
|
48
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
49
|
+
|
|
50
|
+
// Assert
|
|
51
|
+
expect(addEventListenerSpy).toHaveBeenCalledWith(
|
|
52
|
+
'click',
|
|
53
|
+
expect.any(Function)
|
|
54
|
+
)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('should handle multiple events', () => {
|
|
58
|
+
// Arrange
|
|
59
|
+
mockElement.on = {
|
|
60
|
+
click: mockEventHandler,
|
|
61
|
+
mouseover: mockEventHandler,
|
|
62
|
+
onSubmit: mockEventHandler
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Act
|
|
66
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
67
|
+
|
|
68
|
+
// Assert
|
|
69
|
+
expect(addEventListenerSpy).toHaveBeenCalledTimes(3)
|
|
70
|
+
expect(addEventListenerSpy).toHaveBeenCalledWith(
|
|
71
|
+
'click',
|
|
72
|
+
expect.any(Function)
|
|
73
|
+
)
|
|
74
|
+
expect(addEventListenerSpy).toHaveBeenCalledWith(
|
|
75
|
+
'mouseover',
|
|
76
|
+
expect.any(Function)
|
|
77
|
+
)
|
|
78
|
+
expect(addEventListenerSpy).toHaveBeenCalledWith(
|
|
79
|
+
'onSubmit', // Issue: The test expected 'submit' but the implementation uses 'onSubmit' as is
|
|
80
|
+
expect.any(Function)
|
|
81
|
+
)
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
describe('excluded events', () => {
|
|
86
|
+
const excludedEvents = [
|
|
87
|
+
'init',
|
|
88
|
+
'beforeClassAssign',
|
|
89
|
+
'render',
|
|
90
|
+
'renderRouter',
|
|
91
|
+
'attachNode',
|
|
92
|
+
'stateInit',
|
|
93
|
+
'stateCreated',
|
|
94
|
+
'beforeStateUpdate',
|
|
95
|
+
'stateUpdate',
|
|
96
|
+
'beforeUpdate',
|
|
97
|
+
'done',
|
|
98
|
+
'create',
|
|
99
|
+
'complete',
|
|
100
|
+
'frame',
|
|
101
|
+
'update'
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
test.each(excludedEvents)(
|
|
105
|
+
'should not register listener for %s event',
|
|
106
|
+
eventName => {
|
|
107
|
+
// Arrange
|
|
108
|
+
mockElement.on[eventName] = mockEventHandler
|
|
109
|
+
|
|
110
|
+
// Act
|
|
111
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
112
|
+
|
|
113
|
+
// Assert
|
|
114
|
+
expect(addEventListenerSpy).not.toHaveBeenCalled()
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
describe('event handling', () => {
|
|
120
|
+
test('should call handler with correct parameters when event triggered', () => {
|
|
121
|
+
// Arrange
|
|
122
|
+
mockElement.on.click = mockEventHandler
|
|
123
|
+
const mockEvent = { type: 'click' }
|
|
124
|
+
|
|
125
|
+
// Act
|
|
126
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
127
|
+
|
|
128
|
+
// Get and call the registered handler
|
|
129
|
+
mockNode.handlers.click(mockEvent)
|
|
130
|
+
|
|
131
|
+
// Assert
|
|
132
|
+
expect(mockEventHandler).toHaveBeenCalledWith(
|
|
133
|
+
mockEvent,
|
|
134
|
+
mockElement,
|
|
135
|
+
mockElement.state,
|
|
136
|
+
mockElement.context,
|
|
137
|
+
mockOptions
|
|
138
|
+
)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test('should maintain correct this context in handler', () => {
|
|
142
|
+
// Arrange
|
|
143
|
+
mockElement.on.click = function () {
|
|
144
|
+
expect(this).toBe(mockElement)
|
|
145
|
+
}
|
|
146
|
+
const mockEvent = { type: 'click' }
|
|
147
|
+
|
|
148
|
+
// Act
|
|
149
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
150
|
+
mockNode.handlers.click(mockEvent)
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
describe('error handling', () => {
|
|
155
|
+
test('should not register listener for non-function handlers', () => {
|
|
156
|
+
// Arrange
|
|
157
|
+
mockElement.on.click = 'not a function'
|
|
158
|
+
|
|
159
|
+
// Act
|
|
160
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
161
|
+
|
|
162
|
+
// Assert
|
|
163
|
+
expect(addEventListenerSpy).not.toHaveBeenCalled()
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
test('should handle handler error thrown synchronously', () => {
|
|
167
|
+
// Arrange
|
|
168
|
+
const error = new Error('Handler error')
|
|
169
|
+
mockElement.on.click = jest.fn(() => {
|
|
170
|
+
throw error
|
|
171
|
+
})
|
|
172
|
+
const mockEvent = { type: 'click' }
|
|
173
|
+
|
|
174
|
+
// Act
|
|
175
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
176
|
+
|
|
177
|
+
// Assert
|
|
178
|
+
expect(() => mockNode.handlers.click(mockEvent)).toThrow('Handler error')
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
describe('edge cases', () => {
|
|
183
|
+
test('should handle missing state and context', () => {
|
|
184
|
+
// Arrange
|
|
185
|
+
mockElement = {
|
|
186
|
+
node: mockNode,
|
|
187
|
+
on: { click: mockEventHandler }
|
|
188
|
+
}
|
|
189
|
+
const mockEvent = { type: 'click' }
|
|
190
|
+
|
|
191
|
+
// Act
|
|
192
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
193
|
+
mockNode.handlers.click(mockEvent)
|
|
194
|
+
|
|
195
|
+
// Assert
|
|
196
|
+
expect(mockEventHandler).toHaveBeenCalledWith(
|
|
197
|
+
mockEvent,
|
|
198
|
+
mockElement,
|
|
199
|
+
undefined,
|
|
200
|
+
undefined,
|
|
201
|
+
mockOptions
|
|
202
|
+
)
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
test('should handle empty on object', () => {
|
|
206
|
+
// Arrange
|
|
207
|
+
mockElement.on = {}
|
|
208
|
+
|
|
209
|
+
// Act
|
|
210
|
+
applyEventsOnNode(mockElement, mockOptions)
|
|
211
|
+
|
|
212
|
+
// Assert
|
|
213
|
+
expect(addEventListenerSpy).not.toHaveBeenCalled()
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
})
|