@domql/element 2.5.200 → 3.0.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.
Files changed (140) hide show
  1. package/README.md +1 -1
  2. package/__tests__/checkIfOnUpdate.test.js +103 -0
  3. package/__tests__/children.test.js +213 -0
  4. package/__tests__/define.test.js +75 -0
  5. package/__tests__/inheritStateUpdates.test.js +79 -0
  6. package/__tests__/renderElement.test.js +131 -0
  7. package/__tests__/resetElement.test.js +44 -0
  8. package/__tests__/set.test.js +316 -0
  9. package/__tests__/throughExecProps.test.js +86 -0
  10. package/__tests__/throughInitialDefine.test.js +104 -0
  11. package/__tests__/throughInitialExec.test.js +92 -0
  12. package/__tests__/throughUpdatedDefine.test.js +92 -0
  13. package/__tests__/throughUpdatedExec.test.js +110 -0
  14. package/__tests__/tree.test.js +15 -0
  15. package/__tests__/update.test.js +253 -0
  16. package/children.js +105 -0
  17. package/create.js +125 -252
  18. package/dist/cjs/__tests__/checkIfOnUpdate.test.js +73 -0
  19. package/dist/cjs/__tests__/children.test.js +177 -0
  20. package/dist/cjs/__tests__/define.test.js +75 -0
  21. package/dist/cjs/__tests__/inheritStateUpdates.test.js +62 -0
  22. package/dist/cjs/__tests__/renderElement.test.js +138 -0
  23. package/dist/cjs/__tests__/resetElement.test.js +35 -0
  24. package/dist/cjs/__tests__/set.test.js +256 -0
  25. package/dist/cjs/__tests__/throughExecProps.test.js +62 -0
  26. package/dist/cjs/__tests__/throughInitialDefine.test.js +79 -0
  27. package/dist/cjs/__tests__/throughInitialExec.test.js +73 -0
  28. package/dist/cjs/__tests__/throughUpdatedDefine.test.js +69 -0
  29. package/dist/cjs/__tests__/throughUpdatedExec.test.js +84 -0
  30. package/dist/cjs/__tests__/tree.test.js +11 -0
  31. package/dist/cjs/__tests__/update.test.js +219 -0
  32. package/dist/cjs/children.js +87 -0
  33. package/dist/cjs/create.js +79 -177
  34. package/dist/cjs/iterate.js +29 -13
  35. package/dist/cjs/methods/set.js +27 -25
  36. package/dist/cjs/methods/v2.js +1 -5
  37. package/dist/cjs/mixins/attr.js +7 -6
  38. package/dist/cjs/mixins/index.js +0 -4
  39. package/dist/cjs/mixins/registry.js +7 -67
  40. package/dist/cjs/mixins/scope.js +1 -1
  41. package/dist/cjs/mixins/state.js +3 -4
  42. package/dist/cjs/mixins/text.js +3 -3
  43. package/dist/cjs/node.js +32 -22
  44. package/dist/cjs/set.js +112 -40
  45. package/dist/cjs/update.js +119 -64
  46. package/dist/cjs/utils/applyParam.js +2 -2
  47. package/dist/cjs/utils/index.js +8 -4
  48. package/dist/cjs/utils/onlyResolveExtends.js +4 -7
  49. package/dist/esm/__tests__/checkIfOnUpdate.test.js +73 -0
  50. package/dist/esm/__tests__/children.test.js +177 -0
  51. package/dist/esm/__tests__/define.test.js +53 -0
  52. package/dist/esm/__tests__/inheritStateUpdates.test.js +62 -0
  53. package/dist/esm/__tests__/renderElement.test.js +116 -0
  54. package/dist/esm/__tests__/resetElement.test.js +35 -0
  55. package/dist/esm/__tests__/set.test.js +256 -0
  56. package/dist/esm/__tests__/throughExecProps.test.js +62 -0
  57. package/dist/esm/__tests__/throughInitialDefine.test.js +79 -0
  58. package/dist/esm/__tests__/throughInitialExec.test.js +73 -0
  59. package/dist/esm/__tests__/throughUpdatedDefine.test.js +69 -0
  60. package/dist/esm/__tests__/throughUpdatedExec.test.js +84 -0
  61. package/dist/esm/__tests__/tree.test.js +11 -0
  62. package/dist/esm/__tests__/update.test.js +219 -0
  63. package/dist/esm/children.js +81 -0
  64. package/dist/esm/create.js +85 -188
  65. package/dist/esm/iterate.js +33 -16
  66. package/dist/esm/methods/set.js +6 -4
  67. package/dist/esm/methods/v2.js +1 -5
  68. package/dist/esm/mixins/attr.js +8 -7
  69. package/dist/esm/mixins/data.js +1 -1
  70. package/dist/esm/mixins/index.js +0 -4
  71. package/dist/esm/mixins/registry.js +7 -67
  72. package/dist/esm/mixins/scope.js +1 -1
  73. package/dist/esm/mixins/state.js +4 -5
  74. package/dist/esm/mixins/text.js +4 -7
  75. package/dist/esm/node.js +23 -23
  76. package/dist/esm/set.js +112 -40
  77. package/dist/esm/update.js +122 -68
  78. package/dist/esm/utils/applyParam.js +2 -2
  79. package/dist/esm/utils/index.js +4 -3
  80. package/dist/esm/utils/onlyResolveExtends.js +12 -8
  81. package/iterate.js +44 -26
  82. package/methods/set.js +5 -4
  83. package/methods/v2.js +5 -4
  84. package/mixins/attr.js +13 -7
  85. package/mixins/classList.js +7 -2
  86. package/mixins/data.js +1 -1
  87. package/mixins/index.js +1 -6
  88. package/mixins/registry.js +6 -53
  89. package/mixins/scope.js +1 -1
  90. package/mixins/state.js +4 -5
  91. package/mixins/text.js +4 -7
  92. package/node.js +31 -28
  93. package/package.json +7 -6
  94. package/set.js +129 -41
  95. package/update.js +169 -89
  96. package/utils/applyParam.js +7 -4
  97. package/utils/index.js +1 -3
  98. package/utils/onlyResolveExtends.js +27 -16
  99. package/cache/index.js +0 -3
  100. package/cache/options.js +0 -4
  101. package/dist/cjs/cache/index.js +0 -24
  102. package/dist/cjs/cache/options.js +0 -26
  103. package/dist/cjs/extend.js +0 -81
  104. package/dist/cjs/methods/index.js +0 -320
  105. package/dist/cjs/mixins/content.js +0 -67
  106. package/dist/cjs/props/create.js +0 -92
  107. package/dist/cjs/props/ignore.js +0 -24
  108. package/dist/cjs/props/index.js +0 -21
  109. package/dist/cjs/props/inherit.js +0 -51
  110. package/dist/cjs/props/update.js +0 -34
  111. package/dist/cjs/utils/component.js +0 -74
  112. package/dist/cjs/utils/extendUtils.js +0 -133
  113. package/dist/cjs/utils/object.js +0 -171
  114. package/dist/cjs/utils/propEvents.js +0 -39
  115. package/dist/esm/cache/index.js +0 -4
  116. package/dist/esm/cache/options.js +0 -6
  117. package/dist/esm/extend.js +0 -67
  118. package/dist/esm/methods/index.js +0 -300
  119. package/dist/esm/mixins/content.js +0 -47
  120. package/dist/esm/props/create.js +0 -72
  121. package/dist/esm/props/ignore.js +0 -4
  122. package/dist/esm/props/index.js +0 -4
  123. package/dist/esm/props/inherit.js +0 -31
  124. package/dist/esm/props/update.js +0 -14
  125. package/dist/esm/utils/component.js +0 -62
  126. package/dist/esm/utils/extendUtils.js +0 -113
  127. package/dist/esm/utils/object.js +0 -151
  128. package/dist/esm/utils/propEvents.js +0 -19
  129. package/extend.js +0 -90
  130. package/methods/index.js +0 -317
  131. package/mixins/content.js +0 -55
  132. package/props/create.js +0 -87
  133. package/props/ignore.js +0 -3
  134. package/props/index.js +0 -6
  135. package/props/inherit.js +0 -35
  136. package/props/update.js +0 -17
  137. package/utils/component.js +0 -68
  138. package/utils/extendUtils.js +0 -134
  139. package/utils/object.js +0 -172
  140. package/utils/propEvents.js +0 -19
package/README.md CHANGED
@@ -8,7 +8,7 @@ Takes object and creates DOMQL element.
8
8
  import DOM from 'domql'
9
9
 
10
10
  const Poster = {
11
- extend: [Link, Img],
11
+ extends: [Link, Img],
12
12
  props: {
13
13
  boxSize: [100, 200],
14
14
  borderRadius: 12,
@@ -0,0 +1,103 @@
1
+ import { update } from '../update'
2
+
3
+ describe('checkIfOnUpdate via update()', () => {
4
+ let element, parent, options
5
+
6
+ beforeEach(() => {
7
+ parent = {
8
+ node: document.createElement('div'),
9
+ props: {},
10
+ state: {}
11
+ }
12
+
13
+ element = {
14
+ __ref: {
15
+ __if: undefined,
16
+ __state: null,
17
+ __hasRootState: false,
18
+ __execProps: {},
19
+ contentElementKey: 'content'
20
+ },
21
+ parent,
22
+ props: {},
23
+ state: {
24
+ update: (el, st) => {
25
+ return st
26
+ }
27
+ },
28
+ context: {
29
+ defaultExtends: {}
30
+ },
31
+ node: document.createElement('div'),
32
+ if: () => true,
33
+ previousElement: () => {
34
+ return {}
35
+ },
36
+ nextElement: () => {
37
+ return {}
38
+ },
39
+ removeContent: () => {
40
+ return true
41
+ }
42
+ }
43
+
44
+ options = {}
45
+ })
46
+
47
+ it('uses props.if when element.if missing', async () => {
48
+ delete element.if
49
+ element.props.if = () => false
50
+ await update.call(element, {}, options)
51
+ expect(element.node).toEqual(document.createElement('div'))
52
+ })
53
+
54
+ it('retains state when __hasRootState=true', async () => {
55
+ element.__ref.__hasRootState = true
56
+ element.state.critical = true
57
+ element.__ref.__if = false
58
+
59
+ await update.call(element, {}, options)
60
+
61
+ expect(element.state.critical).toBe(true)
62
+ expect(element.state.preserved).toBeUndefined()
63
+ })
64
+
65
+ it('processes nested content with parseDeep', async () => {
66
+ element.content = {
67
+ parseDeep: () => ({ parsed: true }),
68
+ existing: 'data'
69
+ }
70
+
71
+ await update.call(element, {}, options)
72
+
73
+ expect(element.content.parsed).toBe(true)
74
+ expect(element.content.existing).toBeUndefined()
75
+ })
76
+
77
+ it('reattaches after previous sibling', async () => {
78
+ const prevNode = document.createElement('span')
79
+ parent.node.appendChild(prevNode)
80
+
81
+ await update.call(element, {}, options)
82
+
83
+ const newElement = parent.node.children[0]
84
+ expect(newElement).toEqual(document.createElement('span'))
85
+ expect(newElement.previousSibling).toBe(null)
86
+ })
87
+
88
+ // it('reattaches before next sibling', async () => {
89
+ // const nextNode = document.createElement('p')
90
+ // parent.node.appendChild(nextNode)
91
+
92
+ // await update.call(element, {}, options)
93
+
94
+ // const newElement = parent.node.children[0]
95
+ // expect(newElement).toEqual(document.createElement('p'))
96
+ // expect(newElement.nextSibling).toBe(null)
97
+ // })
98
+
99
+ // it('appends to parent when no siblings exist', async () => {
100
+ // await update.call(element, {}, options)
101
+ // expect(parent.node.children).toHaveLength(0)
102
+ // })
103
+ })
@@ -0,0 +1,213 @@
1
+ import { jest } from '@jest/globals'
2
+ import { setChildren } from '../children'
3
+
4
+ describe('children', () => {
5
+ let element, node
6
+
7
+ beforeEach(() => {
8
+ element = {
9
+ __ref: {},
10
+ state: {},
11
+ props: {},
12
+ call: jest.fn(),
13
+ removeContent: jest.fn(),
14
+ content: null
15
+ }
16
+ node = {}
17
+ })
18
+
19
+ it('handles null/undefined params', async () => {
20
+ const result = await setChildren(null, element, node)
21
+ expect(result).toBeUndefined()
22
+ })
23
+
24
+ it('handles direct string children', async () => {
25
+ const result = await setChildren('Hello World', element, node)
26
+ expect(result).toEqual({ tag: 'fragment', 0: { text: 'Hello World' } })
27
+ })
28
+
29
+ it('handles numeric children', async () => {
30
+ const result = await setChildren(42, element, node)
31
+ expect(result).toEqual({ tag: 'fragment', 0: { text: 42 } })
32
+ })
33
+
34
+ it('handles array of primitive values with childrenAs prop', async () => {
35
+ const result = await setChildren(['one', 'two'], element, node)
36
+
37
+ expect(result).toEqual({
38
+ tag: 'fragment',
39
+ 0: { text: 'one' },
40
+ 1: { text: 'two' }
41
+ })
42
+ })
43
+
44
+ it('handles array of primitive values with childrenAs state', async () => {
45
+ element.props.childrenAs = 'state'
46
+ const result = await setChildren(['one', 'two'], element, node)
47
+
48
+ expect(result).toEqual({
49
+ tag: 'fragment',
50
+ 0: { state: { value: 'one' } },
51
+ 1: { state: { value: 'two' } }
52
+ })
53
+ })
54
+
55
+ it('caches children and detects changes', async () => {
56
+ const children1 = [{ id: 1 }, { id: 2 }]
57
+ const children2 = [{ id: 1 }, { id: 2 }]
58
+ const children3 = [{ id: 1 }, { id: 3 }]
59
+
60
+ // First call
61
+ await setChildren(children1, element, node)
62
+ expect(element.__ref.__childrenCache).toEqual(children1)
63
+ expect(element.__ref.__noChildrenDifference).toBeUndefined()
64
+
65
+ // Same content, different reference
66
+ await setChildren(children2, element, node)
67
+ expect(element.__ref.__noChildrenDifference).toBe(true)
68
+
69
+ // Different content
70
+ await setChildren(children3, element, node)
71
+ expect(element.__ref.__noChildrenDifference).toBeUndefined()
72
+ expect(element.__ref.__childrenCache).toEqual(children3)
73
+ })
74
+
75
+ it('handles mixed React and normal components', async () => {
76
+ const mixedChildren = [
77
+ { type: 'div', text: 'Normal' },
78
+ { $$typeof: Symbol('react') },
79
+ { type: 'span', text: 'Another' }
80
+ ]
81
+
82
+ await setChildren(mixedChildren, element, node)
83
+
84
+ expect(element.call).toHaveBeenCalledWith(
85
+ 'renderReact',
86
+ [mixedChildren[1]],
87
+ element
88
+ )
89
+ })
90
+
91
+ it('handles state-based children', async () => {
92
+ element.state = {
93
+ items: ['a', 'b'],
94
+ parse: () => ['parsed a', 'parsed b']
95
+ }
96
+
97
+ const result = await setChildren('state', element, node)
98
+ expect(result).toEqual({
99
+ tag: 'fragment',
100
+ 0: { text: 'parsed a' },
101
+ 1: { text: 'parsed b' }
102
+ })
103
+ })
104
+
105
+ it('handles async function parameters', async () => {
106
+ const asyncParam = async () => ['async1', 'async2']
107
+ const result = await setChildren(asyncParam, element, node)
108
+
109
+ expect(result).toEqual({
110
+ tag: 'fragment',
111
+ 0: { text: 'async1' },
112
+ 1: { text: 'async2' }
113
+ })
114
+ })
115
+
116
+ it('handles nested object structures', async () => {
117
+ const nestedChildren = {
118
+ header: { text: 'Title' },
119
+ content: {
120
+ nested: { text: 'Content' }
121
+ }
122
+ }
123
+
124
+ const result = await setChildren(nestedChildren, element, node)
125
+ expect(result).toEqual({
126
+ tag: 'fragment',
127
+ 0: { text: 'Title' },
128
+ 1: { nested: { text: 'Content' } }
129
+ })
130
+ })
131
+
132
+ it('handles empty arrays and objects', async () => {
133
+ let result = await setChildren([], element, node)
134
+ expect(result).toEqual({
135
+ tag: 'fragment'
136
+ })
137
+
138
+ result = await setChildren({}, element, node)
139
+ expect(result).toEqual({
140
+ tag: 'fragment'
141
+ })
142
+ })
143
+
144
+ it('handles falsy values in arrays', async () => {
145
+ const result = await setChildren(
146
+ [null, undefined, false, 0, ''],
147
+ element,
148
+ node
149
+ )
150
+ expect(result).toEqual({
151
+ tag: 'fragment',
152
+ 3: { text: 0 },
153
+ 4: { text: '' }
154
+ })
155
+ })
156
+
157
+ it('handles React components with falsy values in array', async () => {
158
+ const mixedChildren = [
159
+ null,
160
+ { $$typeof: Symbol('react') },
161
+ undefined,
162
+ { $$typeof: Symbol('react') },
163
+ false
164
+ ]
165
+
166
+ await setChildren(mixedChildren, element, node)
167
+
168
+ expect(element.call).toHaveBeenCalledWith(
169
+ 'renderReact',
170
+ [mixedChildren[1], mixedChildren[3]],
171
+ element
172
+ )
173
+ })
174
+
175
+ it('handles nested state parsing', async () => {
176
+ element.state = {
177
+ nested: {
178
+ items: ['c', 'd']
179
+ }
180
+ }
181
+ element.state.nested.__proto__.parse = () => ['parsed c', 'parsed d']
182
+
183
+ const result = await setChildren('nested', element, node)
184
+ expect(result).toEqual({
185
+ tag: 'fragment',
186
+ 0: { state: ['c', 'd'] }
187
+ })
188
+ })
189
+
190
+ it('handles mixed state and regular objects', async () => {
191
+ element.state = {
192
+ header: { parse: () => 'Header' },
193
+ footer: { parse: () => 'Footer' }
194
+ }
195
+
196
+ const result = await setChildren(
197
+ {
198
+ header: 'header',
199
+ content: { text: 'Content' },
200
+ footer: 'footer'
201
+ },
202
+ element,
203
+ node
204
+ )
205
+
206
+ expect(result).toEqual({
207
+ tag: 'fragment',
208
+ 0: { text: 'header' },
209
+ 1: { text: 'Content' },
210
+ 2: { text: 'footer' }
211
+ })
212
+ })
213
+ })
@@ -0,0 +1,75 @@
1
+ import define from '../define'
2
+ import { REGISTRY } from '../mixins'
3
+
4
+ describe('default function (registry updater)', () => {
5
+ let originalRegistry
6
+
7
+ beforeEach(() => {
8
+ // Save the original REGISTRY to restore after each test
9
+ originalRegistry = { ...REGISTRY }
10
+ })
11
+
12
+ afterEach(() => {
13
+ // Restore the original REGISTRY after each test
14
+ Object.keys(REGISTRY).forEach(key => {
15
+ REGISTRY[key] = originalRegistry[key]
16
+ })
17
+ })
18
+
19
+ it('should add new params to REGISTRY when overwrite is true', () => {
20
+ const params = { newKey: 'newValue', anotherKey: 'anotherValue' }
21
+ const options = { overwrite: true }
22
+
23
+ define(params, options)
24
+
25
+ expect(REGISTRY.newKey).toBe('newValue')
26
+ expect(REGISTRY.anotherKey).toBe('anotherValue')
27
+ })
28
+
29
+ it('should not modify REGISTRY when trying to overwrite existing keys without overwrite option', () => {
30
+ const params = { attr: 'newValue', text: 'newText' }
31
+
32
+ try {
33
+ define(params)
34
+ } catch (e) {
35
+ // Ignore the error
36
+ }
37
+
38
+ expect(REGISTRY.attr).toBe(originalRegistry.attr)
39
+ expect(REGISTRY.text).toBe(originalRegistry.text)
40
+ })
41
+
42
+ it('should overwrite existing keys when overwrite is true', () => {
43
+ const params = { attr: 'newValue', text: 'newText' }
44
+ const options = { overwrite: true }
45
+
46
+ define(params, options)
47
+
48
+ expect(REGISTRY.attr).toBe('newValue')
49
+ expect(REGISTRY.text).toBe('newText')
50
+ })
51
+
52
+ it('should handle empty params object without errors', () => {
53
+ const params = {}
54
+ const options = { overwrite: true }
55
+
56
+ expect(() => define(params, options)).not.toThrow()
57
+ expect(REGISTRY).toEqual(originalRegistry)
58
+ })
59
+
60
+ it('should handle empty options object without errors', () => {
61
+ const params = { newKey: 'newValue' }
62
+
63
+ expect(() => define(params, {})).not.toThrow()
64
+ expect(REGISTRY.newKey).toBe('newValue')
65
+ })
66
+
67
+ it('should not add new keys when params is empty', () => {
68
+ const params = {}
69
+ const options = { overwrite: true }
70
+
71
+ define(params, options)
72
+
73
+ expect(REGISTRY).toEqual(originalRegistry)
74
+ })
75
+ })
@@ -0,0 +1,79 @@
1
+ import { update } from '../update'
2
+
3
+ describe('update() with inheritStateUpdates', () => {
4
+ let element, options
5
+
6
+ beforeEach(() => {
7
+ element = {
8
+ __ref: {
9
+ __state: null,
10
+ __hasRootState: false,
11
+ __execProps: {},
12
+ __props: []
13
+ },
14
+ state: {
15
+ calculated: 42,
16
+ set: () => {
17
+ return true
18
+ }
19
+ },
20
+ parent: {
21
+ state: { baseState: true },
22
+ props: {}
23
+ },
24
+ props: {},
25
+ key: 'testKey'
26
+ }
27
+ options = {}
28
+ })
29
+
30
+ // Test 1: Continue update when state inheritance succeeds
31
+ it('processes full update flow when state is inherited', async () => {
32
+ await update.call(element, { props: { newProp: true } }, options)
33
+ expect(element.props.newProp).toBe(true)
34
+ expect(element.state.baseState).toBe(true) // Inherited from parent
35
+ })
36
+
37
+ // Test 2: Preserve existing state when inheritance blocked
38
+ it('maintains state when preventInheritedStateUpdate=true', async () => {
39
+ options.preventInheritedStateUpdate = true
40
+ element.state = { existing: 'state' }
41
+
42
+ await update.call(element, {}, options)
43
+ expect(element.state).toEqual({ baseState: true })
44
+ })
45
+
46
+ // Test 3: Execute state functions when forced
47
+ it('overwrites state with function result', async () => {
48
+ element.__ref.__state = () => ({ calculated: 42 })
49
+ options.execStateFunction = true
50
+ options.stateFunctionOverwrite = true
51
+
52
+ await update.call(element, {}, options)
53
+ expect(element.state.calculated).toEqual(42)
54
+ })
55
+
56
+ // Test 4: Block updates via beforeStateUpdate event
57
+ it('preserves state when beforeStateUpdate rejects', async () => {
58
+ element.props.onBeforeStateUpdate = () => false
59
+ await update.call(element, { props: { shouldChange: true } }, options)
60
+ expect(element.state).toEqual({ baseState: true })
61
+ expect(element.props.shouldChange).toBe(true)
62
+ })
63
+
64
+ // Test 5: Handle parent state changes
65
+ it('reflects parent state updates', async () => {
66
+ element.parent.state = { updatedParentState: true }
67
+ await update.call(element, {}, options)
68
+ expect(element.state.updatedParentState).toBe(true)
69
+ })
70
+
71
+ // Test 6: Maintain local state when root state exists
72
+ it('preserves local state when __hasRootState=true', async () => {
73
+ element.__ref.__hasRootState = true
74
+ element.state = { local: 'data' }
75
+
76
+ await update.call(element, {}, options)
77
+ expect(element.state.local).toBe('data')
78
+ })
79
+ })
@@ -0,0 +1,131 @@
1
+ import { jest } from '@jest/globals'
2
+
3
+ describe('create()', () => {
4
+ let props
5
+ let parent
6
+
7
+ const OLD_ENV = process.env
8
+
9
+ beforeEach(() => {
10
+ props = {
11
+ __ref: { __if: false, path: [], __skipCreate: true },
12
+ key: 'testKey',
13
+ context: {
14
+ defaultExtends: {},
15
+ define: ['test']
16
+ },
17
+ scope: 'props',
18
+ define: ['test']
19
+ }
20
+ parent = {
21
+ testKey: 'parentTestKey',
22
+ key: 'parentKey'
23
+ }
24
+ jest.resetModules()
25
+ process.env = { ...OLD_ENV }
26
+ })
27
+
28
+ afterAll(() => {
29
+ process.env = OLD_ENV
30
+ })
31
+
32
+ test('should execute onlyResolveExtends when __skipCreate is true', async () => {
33
+ props.__ref.__skipCreate = true
34
+ props.scope = undefined
35
+ const { create } = await import('../create')
36
+ await create(props, parent, 'passedKey', {
37
+ onlyResolveExtends: true,
38
+ define: ['test']
39
+ })
40
+ expect(parent.__ref).toBeUndefined()
41
+ expect(parent.passedKey).toBe(props.__ref.parent.passedKey)
42
+ })
43
+
44
+ test('should execute onlyResolveExtends when __ref.__if is true', async () => {
45
+ props.__ref.__if = true
46
+ props.scope = 'state'
47
+ const { create } = await import('../create')
48
+ await create(props, parent, 'passedKey', {
49
+ onlyResolveExtends: true,
50
+ define: ['test']
51
+ })
52
+ expect(parent.__ref).toBeUndefined()
53
+ expect(parent.passedKey).toBe(props.__ref.parent.passedKey)
54
+ })
55
+
56
+ test('should execute onlyResolveExtends when scope is not state', async () => {
57
+ process.env.NODE_ENV = 'prod'
58
+ props.__ref = undefined
59
+ const { create } = await import('../create')
60
+ await create(props, parent, 'passedKey', { onlyResolveExtends: true })
61
+ expect(parent.__ref).toBeUndefined()
62
+ expect(parent.passedKey).toBe(props.__ref.parent.passedKey)
63
+ })
64
+
65
+ test('should execute catch statement when __ref is undefined', async () => {
66
+ process.env.NODE_ENV = 'prod'
67
+ props.__ref = undefined
68
+ const { create } = await import('../create')
69
+ await create(props, parent, 'passedKey')
70
+ expect(parent.__ref).toBeUndefined()
71
+ expect(parent.passedKey).toBe(props.__ref.parent.passedKey)
72
+ })
73
+
74
+ test('should attaches element to parent when ref.__if is false', async () => {
75
+ process.env.NODE_ENV = 'prod'
76
+ const { create } = await import('../create')
77
+ await create(props, parent, 'passedKey')
78
+ expect(parent.__ref).toBeUndefined()
79
+ expect(parent.passedKey).toBe(props.__ref.parent.passedKey)
80
+ })
81
+
82
+ test('should attach element to parent when ref.__if is true', async () => {
83
+ process.env.NODE_ENV = 'prod'
84
+ props.__if = true
85
+ const { create } = await import('../create')
86
+ await create(props, parent, 'passedKey')
87
+ expect(parent.testKey).toBe('parentTestKey')
88
+ expect(parent.passedKey).toBe(props.__ref.parent.passedKey)
89
+ })
90
+
91
+ test('skips createNestedChild when __uniqId exists', async () => {
92
+ process.env.NODE_ENV = 'prod'
93
+ props.__ref = { __uniqId: 'existing-id', path: [] }
94
+ const { create } = await import('../create')
95
+ await create(props, {}, 'passedKey')
96
+ expect(props.__ref.__uniqId).toBeDefined()
97
+ })
98
+
99
+ test('skips createNestedChild when infinite loop detected', async () => {
100
+ process.env.NODE_ENV = 'prod'
101
+ props.__ref = { path: ['loop-path'], __uniqId: undefined }
102
+ const { create } = await import('../create')
103
+ await create(props, {}, 'passedKey')
104
+ expect(props.__ref.__uniqId).toBeDefined()
105
+ })
106
+
107
+ test('should modifies path containing ComponentsGrid', async () => {
108
+ process.env.NODE_ENV = 'prod'
109
+ props.__ref = { path: ['ComponentsGrid', 'x', 'y', 'z'] }
110
+ const { create } = await import('../create')
111
+ await create(props, {}, ['ComponentsGrid', 'x', 'y', 'z'])
112
+ expect(props.__ref.path).toEqual(['ComponentsGrid,x,y,z'])
113
+ })
114
+
115
+ test('should modifies path containing demoComponent', async () => {
116
+ process.env.NODE_ENV = 'prod'
117
+ props.__ref = { path: ['demoComponent', 'a', 'b', 'c'] }
118
+ const { create } = await import('../create')
119
+ await create(props, {}, ['demoComponent', 'a', 'b', 'c'])
120
+ expect(props.__ref.path).toEqual(['demoComponent,a,b,c'])
121
+ })
122
+
123
+ test('uses element.key when key property is missing', async () => {
124
+ process.env.NODE_ENV = 'prod'
125
+ props.__ref = { __if: false, path: [] }
126
+ props.key = 'fallbackKey'
127
+ const { create } = await import('../create')
128
+ await create(props, parent, null)
129
+ expect(props.__ref.parent.fallbackKey).toBeDefined()
130
+ })
131
+ })
@@ -0,0 +1,44 @@
1
+ import { resetContent } from '../set'
2
+
3
+ describe('resetContent', () => {
4
+ let element, ref
5
+
6
+ beforeEach(() => {
7
+ ref = {
8
+ contentElementKey: 'content'
9
+ }
10
+ element = {
11
+ __ref: ref,
12
+ content: { node: document.createElement('div') },
13
+ node: document.createElement('div'),
14
+ context: {}
15
+ }
16
+ })
17
+
18
+ it('should update contentElementKey from options', async () => {
19
+ await resetContent({}, element, { contentElementKey: 'mainContent' })
20
+
21
+ expect(ref.contentElementKey).toBe('mainContent')
22
+ expect(element.mainContent).toBeDefined()
23
+ })
24
+
25
+ it('should merge options correctly', async () => {
26
+ await resetContent({}, element, { customOption: true })
27
+
28
+ expect(element.content).toEqual(
29
+ expect.objectContaining({
30
+ // Verify options merging through observable behavior
31
+ // (this assertion pattern would need actual create() implementation details)
32
+ })
33
+ )
34
+ })
35
+
36
+ it('should maintain context through reset', async () => {
37
+ const originalContext = element.context
38
+
39
+ await resetContent({}, element, {})
40
+
41
+ expect(element.context).toBe(originalContext)
42
+ expect(element.content.context).toBe(originalContext)
43
+ })
44
+ })