glass-easel 0.1.0

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 (237) hide show
  1. package/README.md +40 -0
  2. package/dist/glass_easel.all.d.ts +1 -0
  3. package/dist/glass_easel.all.js +2 -0
  4. package/dist/glass_easel.all.js.map +1 -0
  5. package/dist/glass_easel.domlike.global.d.ts +1 -0
  6. package/dist/glass_easel.domlike.global.js +2 -0
  7. package/dist/glass_easel.domlike.global.js.map +1 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +1 -0
  10. package/dist/types/src/backend/backend_protocol.d.ts +119 -0
  11. package/dist/types/src/backend/backend_protocol.d.ts.map +1 -0
  12. package/dist/types/src/backend/composed_backend_protocol.d.ts +90 -0
  13. package/dist/types/src/backend/composed_backend_protocol.d.ts.map +1 -0
  14. package/dist/types/src/backend/domlike_backend_protocol.d.ts +76 -0
  15. package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +1 -0
  16. package/dist/types/src/backend/mode.d.ts +46 -0
  17. package/dist/types/src/backend/mode.d.ts.map +1 -0
  18. package/dist/types/src/backend/suggested_backend_protocol.d.ts +30 -0
  19. package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +1 -0
  20. package/dist/types/src/behavior.d.ts +428 -0
  21. package/dist/types/src/behavior.d.ts.map +1 -0
  22. package/dist/types/src/class_list.d.ts +79 -0
  23. package/dist/types/src/class_list.d.ts.map +1 -0
  24. package/dist/types/src/component.d.ts +291 -0
  25. package/dist/types/src/component.d.ts.map +1 -0
  26. package/dist/types/src/component_params.d.ts +239 -0
  27. package/dist/types/src/component_params.d.ts.map +1 -0
  28. package/dist/types/src/component_space.d.ts +164 -0
  29. package/dist/types/src/component_space.d.ts.map +1 -0
  30. package/dist/types/src/data_path.d.ts +5 -0
  31. package/dist/types/src/data_path.d.ts.map +1 -0
  32. package/dist/types/src/data_proxy.d.ts +107 -0
  33. package/dist/types/src/data_proxy.d.ts.map +1 -0
  34. package/dist/types/src/data_utils.d.ts +3 -0
  35. package/dist/types/src/data_utils.d.ts.map +1 -0
  36. package/dist/types/src/element.d.ts +275 -0
  37. package/dist/types/src/element.d.ts.map +1 -0
  38. package/dist/types/src/element_iterator.d.ts +43 -0
  39. package/dist/types/src/element_iterator.d.ts.map +1 -0
  40. package/dist/types/src/event.d.ts +104 -0
  41. package/dist/types/src/event.d.ts.map +1 -0
  42. package/dist/types/src/external_shadow_tree.d.ts +20 -0
  43. package/dist/types/src/external_shadow_tree.d.ts.map +1 -0
  44. package/dist/types/src/func_arr.d.ts +39 -0
  45. package/dist/types/src/func_arr.d.ts.map +1 -0
  46. package/dist/types/src/global_options.d.ts +111 -0
  47. package/dist/types/src/global_options.d.ts.map +1 -0
  48. package/dist/types/src/index.d.ts +43 -0
  49. package/dist/types/src/index.d.ts.map +1 -0
  50. package/dist/types/src/mutation_observer.d.ts +79 -0
  51. package/dist/types/src/mutation_observer.d.ts.map +1 -0
  52. package/dist/types/src/native_node.d.ts +8 -0
  53. package/dist/types/src/native_node.d.ts.map +1 -0
  54. package/dist/types/src/node.d.ts +49 -0
  55. package/dist/types/src/node.d.ts.map +1 -0
  56. package/dist/types/src/relation.d.ts +47 -0
  57. package/dist/types/src/relation.d.ts.map +1 -0
  58. package/dist/types/src/render.d.ts +3 -0
  59. package/dist/types/src/render.d.ts.map +1 -0
  60. package/dist/types/src/selector.d.ts +32 -0
  61. package/dist/types/src/selector.d.ts.map +1 -0
  62. package/dist/types/src/shadow_root.d.ts +136 -0
  63. package/dist/types/src/shadow_root.d.ts.map +1 -0
  64. package/dist/types/src/template_engine.d.ts +18 -0
  65. package/dist/types/src/template_engine.d.ts.map +1 -0
  66. package/dist/types/src/text_node.d.ts +32 -0
  67. package/dist/types/src/text_node.d.ts.map +1 -0
  68. package/dist/types/src/tmpl/index.d.ts +18 -0
  69. package/dist/types/src/tmpl/index.d.ts.map +1 -0
  70. package/dist/types/src/tmpl/native_rendering.d.ts +45 -0
  71. package/dist/types/src/tmpl/native_rendering.d.ts.map +1 -0
  72. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +80 -0
  73. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +1 -0
  74. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +50 -0
  75. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +1 -0
  76. package/dist/types/src/tmpl/range_list_diff.d.ts +19 -0
  77. package/dist/types/src/tmpl/range_list_diff.d.ts.map +1 -0
  78. package/dist/types/src/trait_behaviors.d.ts +38 -0
  79. package/dist/types/src/trait_behaviors.d.ts.map +1 -0
  80. package/dist/types/src/virtual_node.d.ts +10 -0
  81. package/dist/types/src/virtual_node.d.ts.map +1 -0
  82. package/dist/types/tests/backend/domlike.test.d.ts +2 -0
  83. package/dist/types/tests/backend/domlike.test.d.ts.map +1 -0
  84. package/dist/types/tests/base/env.d.ts +29 -0
  85. package/dist/types/tests/base/env.d.ts.map +1 -0
  86. package/dist/types/tests/base/match.d.ts +9 -0
  87. package/dist/types/tests/base/match.d.ts.map +1 -0
  88. package/dist/types/tests/core/backend.test.d.ts +2 -0
  89. package/dist/types/tests/core/backend.test.d.ts.map +1 -0
  90. package/dist/types/tests/core/behavior.test.d.ts +2 -0
  91. package/dist/types/tests/core/behavior.test.d.ts.map +1 -0
  92. package/dist/types/tests/core/component_space.test.d.ts +2 -0
  93. package/dist/types/tests/core/component_space.test.d.ts.map +1 -0
  94. package/dist/types/tests/core/data_update.test.d.ts +2 -0
  95. package/dist/types/tests/core/data_update.test.d.ts.map +1 -0
  96. package/dist/types/tests/core/misc.test.d.ts +2 -0
  97. package/dist/types/tests/core/misc.test.d.ts.map +1 -0
  98. package/dist/types/tests/core/placeholder.test.d.ts +2 -0
  99. package/dist/types/tests/core/placeholder.test.d.ts.map +1 -0
  100. package/dist/types/tests/core/slot.test.d.ts +2 -0
  101. package/dist/types/tests/core/slot.test.d.ts.map +1 -0
  102. package/dist/types/tests/core/trait_behaviors.test.d.ts +2 -0
  103. package/dist/types/tests/core/trait_behaviors.test.d.ts.map +1 -0
  104. package/dist/types/tests/tmpl/binding_map.test.d.ts +2 -0
  105. package/dist/types/tests/tmpl/binding_map.test.d.ts.map +1 -0
  106. package/dist/types/tests/tmpl/event.test.d.ts +2 -0
  107. package/dist/types/tests/tmpl/event.test.d.ts.map +1 -0
  108. package/dist/types/tests/tmpl/expression.test.d.ts +2 -0
  109. package/dist/types/tests/tmpl/expression.test.d.ts.map +1 -0
  110. package/dist/types/tests/tmpl/lvalue.test.d.ts +2 -0
  111. package/dist/types/tests/tmpl/lvalue.test.d.ts.map +1 -0
  112. package/dist/types/tests/tmpl/native_rendering.test.d.ts +2 -0
  113. package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +1 -0
  114. package/dist/types/tests/tmpl/structure.test.d.ts +2 -0
  115. package/dist/types/tests/tmpl/structure.test.d.ts.map +1 -0
  116. package/dist/types/tests/types/chaining.test.d.ts +2 -0
  117. package/dist/types/tests/types/chaining.test.d.ts.map +1 -0
  118. package/dist/types/tests/types/createElement.test.d.ts +2 -0
  119. package/dist/types/tests/types/createElement.test.d.ts.map +1 -0
  120. package/dist/types/tests/types/definition.test.d.ts +2 -0
  121. package/dist/types/tests/types/definition.test.d.ts.map +1 -0
  122. package/guide/zh_CN/advanced/binding_map_update.md +32 -0
  123. package/guide/zh_CN/advanced/build_args.md +28 -0
  124. package/guide/zh_CN/advanced/component_filter.md +70 -0
  125. package/guide/zh_CN/advanced/component_space.md +124 -0
  126. package/guide/zh_CN/advanced/custom_backend.md +53 -0
  127. package/guide/zh_CN/advanced/error_listener.md +32 -0
  128. package/guide/zh_CN/advanced/external_component.md +73 -0
  129. package/guide/zh_CN/advanced/template_engine.md +61 -0
  130. package/guide/zh_CN/appendix/backend_protocol.md +501 -0
  131. package/guide/zh_CN/appendix/list_diff_algorithm.md +406 -0
  132. package/guide/zh_CN/basic/beginning.md +94 -0
  133. package/guide/zh_CN/basic/component.md +156 -0
  134. package/guide/zh_CN/basic/event.md +169 -0
  135. package/guide/zh_CN/basic/lifetime.md +66 -0
  136. package/guide/zh_CN/basic/method.md +62 -0
  137. package/guide/zh_CN/basic/template.md +135 -0
  138. package/guide/zh_CN/data_management/advanced_update.md +170 -0
  139. package/guide/zh_CN/data_management/data_deep_copy.md +157 -0
  140. package/guide/zh_CN/data_management/data_observer.md +154 -0
  141. package/guide/zh_CN/data_management/property_early_init.md +31 -0
  142. package/guide/zh_CN/data_management/pure_data_pattern.md +21 -0
  143. package/guide/zh_CN/index.md +93 -0
  144. package/guide/zh_CN/interaction/behavior.md +52 -0
  145. package/guide/zh_CN/interaction/component_path.md +37 -0
  146. package/guide/zh_CN/interaction/generic.md +73 -0
  147. package/guide/zh_CN/interaction/placeholder.md +40 -0
  148. package/guide/zh_CN/interaction/relation.md +151 -0
  149. package/guide/zh_CN/interaction/slot.md +137 -0
  150. package/guide/zh_CN/interaction/template_import.md +94 -0
  151. package/guide/zh_CN/interaction/trait_behavior.md +117 -0
  152. package/guide/zh_CN/styling/external_class.md +46 -0
  153. package/guide/zh_CN/styling/style_isolation.md +54 -0
  154. package/guide/zh_CN/styling/virtual_host.md +52 -0
  155. package/guide/zh_CN/tree/element_iterator.md +54 -0
  156. package/guide/zh_CN/tree/mutation_observer.md +52 -0
  157. package/guide/zh_CN/tree/node_tree.md +142 -0
  158. package/guide/zh_CN/tree/node_tree_modification.md +78 -0
  159. package/guide/zh_CN/tree/selector.md +66 -0
  160. package/jest.config.js +6 -0
  161. package/jest.dts.config.js +9 -0
  162. package/jest.unit.config.js +14 -0
  163. package/package.json +28 -0
  164. package/src/backend/backend_protocol.ts +313 -0
  165. package/src/backend/composed_backend_protocol.ts +252 -0
  166. package/src/backend/domlike_backend_protocol.ts +370 -0
  167. package/src/backend/mode.ts +51 -0
  168. package/src/backend/suggested_backend_protocol.ts +83 -0
  169. package/src/behavior.ts +1655 -0
  170. package/src/bootstrap_dom_dev.js +22 -0
  171. package/src/class_list.ts +376 -0
  172. package/src/component.ts +1309 -0
  173. package/src/component_params.ts +461 -0
  174. package/src/component_space.ts +547 -0
  175. package/src/data_path.ts +225 -0
  176. package/src/data_proxy.ts +670 -0
  177. package/src/data_utils.ts +50 -0
  178. package/src/element.ts +1966 -0
  179. package/src/element_iterator.ts +158 -0
  180. package/src/event.ts +401 -0
  181. package/src/external_shadow_tree.ts +27 -0
  182. package/src/func_arr.ts +198 -0
  183. package/src/global_options.ts +242 -0
  184. package/src/index.ts +187 -0
  185. package/src/mutation_observer.ts +252 -0
  186. package/src/native_node.ts +74 -0
  187. package/src/node.ts +174 -0
  188. package/src/relation.ts +380 -0
  189. package/src/render.ts +25 -0
  190. package/src/selector.ts +218 -0
  191. package/src/shadow_root.ts +766 -0
  192. package/src/template_engine.ts +45 -0
  193. package/src/text_node.ts +149 -0
  194. package/src/tmpl/index.ts +199 -0
  195. package/src/tmpl/native_rendering.ts +175 -0
  196. package/src/tmpl/proc_gen_wrapper.ts +954 -0
  197. package/src/tmpl/proc_gen_wrapper_dom.ts +230 -0
  198. package/src/tmpl/range_list_diff.ts +443 -0
  199. package/src/trait_behaviors.ts +51 -0
  200. package/src/virtual_node.ts +51 -0
  201. package/tests/backend/domlike.test.ts +254 -0
  202. package/tests/base/env.ts +78 -0
  203. package/tests/base/match.ts +185 -0
  204. package/tests/core/backend.test.ts +144 -0
  205. package/tests/core/behavior.test.ts +546 -0
  206. package/tests/core/component_space.test.ts +212 -0
  207. package/tests/core/data_update.test.ts +461 -0
  208. package/tests/core/misc.test.ts +339 -0
  209. package/tests/core/placeholder.test.ts +180 -0
  210. package/tests/core/slot.test.ts +1495 -0
  211. package/tests/core/trait_behaviors.test.ts +153 -0
  212. package/tests/legacy/README.md +3 -0
  213. package/tests/legacy/behavior.test.js +293 -0
  214. package/tests/legacy/component.test.js +1247 -0
  215. package/tests/legacy/data_path.test.js +149 -0
  216. package/tests/legacy/data_proxy.test.js +759 -0
  217. package/tests/legacy/element_iterator.test.js +148 -0
  218. package/tests/legacy/event.test.js +849 -0
  219. package/tests/legacy/external.test.js +510 -0
  220. package/tests/legacy/extra_info.test.js +109 -0
  221. package/tests/legacy/generics.test.js +176 -0
  222. package/tests/legacy/mutation_observer.test.js +210 -0
  223. package/tests/legacy/relation.test.js +517 -0
  224. package/tests/legacy/selector.test.js +263 -0
  225. package/tests/legacy/slot.test.js +915 -0
  226. package/tests/legacy/virtual.test.js +394 -0
  227. package/tests/tmpl/binding_map.test.ts +208 -0
  228. package/tests/tmpl/event.test.ts +206 -0
  229. package/tests/tmpl/expression.test.ts +429 -0
  230. package/tests/tmpl/lvalue.test.ts +160 -0
  231. package/tests/tmpl/native_rendering.test.ts +155 -0
  232. package/tests/tmpl/structure.test.ts +998 -0
  233. package/tests/types/chaining.test.ts +614 -0
  234. package/tests/types/createElement.test.ts +82 -0
  235. package/tests/types/definition.test.ts +442 -0
  236. package/tsconfig.json +11 -0
  237. package/webpack.config.js +270 -0
@@ -0,0 +1,759 @@
1
+ /* eslint-disable */
2
+
3
+ const { tmpl, domBackend, shadowBackend } = require('../base/env')
4
+ const glassEasel = require('../../src')
5
+
6
+ const componentSpace = new glassEasel.ComponentSpace()
7
+ componentSpace.updateComponentOptions({
8
+ writeFieldsToNode: true,
9
+ })
10
+ componentSpace.defineComponent({
11
+ is: '',
12
+ })
13
+
14
+ const regBeh = (config) => {
15
+ return componentSpace.defineBehavior(config)
16
+ }
17
+
18
+ const regElem = (config) => {
19
+ const { template, ...c } = config
20
+ if (template) c.template = tmpl(template)
21
+ return componentSpace.defineComponent(c)
22
+ }
23
+
24
+ const createElem = (is, backend) => {
25
+ const def = componentSpace.getComponent(is)
26
+ return glassEasel.Component.createWithContext(is || 'test', def, backend || domBackend)
27
+ }
28
+
29
+ describe('DataProxy', function(){
30
+
31
+ it('should allow independent usage', function(){
32
+ var callOrder = []
33
+ var da = {
34
+ a: 1,
35
+ }
36
+ var g = glassEasel.DataGroup.create(da, function(data, combinedChanges){
37
+ callOrder.push([data, combinedChanges])
38
+ })
39
+ g.replaceDataOnPath(['a'], 2)
40
+ g.applyDataUpdates()
41
+ expect(g.data).toStrictEqual({a: 2})
42
+ var db = {
43
+ b: 1,
44
+ }
45
+ g.replaceWholeData(db)
46
+ expect(g.data).toBe(db)
47
+ g.replaceDataOnPath(['b'], 2)
48
+ g.applyDataUpdates()
49
+ expect(g.data).toStrictEqual({b: 2})
50
+ })
51
+
52
+ it('should separate template data', function(){
53
+ regElem({
54
+ is: 'data-proxy-separate-a',
55
+ template: '<div id="c" prop-abc="{{a}} {{b}} {{c}}" />',
56
+ data: {
57
+ a: 1,
58
+ b: 2,
59
+ c: 3,
60
+ }
61
+ })
62
+ var elem = createElem('data-proxy-separate-a')
63
+ expect(elem.$.c.$$.getAttribute('prop-abc')).toBe('1 2 3')
64
+ elem.data.a = 4
65
+ elem.setData({
66
+ b: 5
67
+ })
68
+ expect(elem.$.c.$$.getAttribute('prop-abc')).toBe('1 5 3')
69
+ })
70
+
71
+ it('should support inner data filter', function(){
72
+ regElem({
73
+ is: 'data-proxy-inner-data-exclude-a',
74
+ options: {
75
+ pureDataPattern: /^_/
76
+ },
77
+ template: '<div id="c" prop-abc="{{a}} {{_b}} {{_c}} {{d}} {{_e}}" />',
78
+ data: {
79
+ a: 1,
80
+ _b: 2,
81
+ },
82
+ observers: {
83
+ '_b': function() {
84
+ this.setData({
85
+ d: this.data._b * 10,
86
+ _e: this.data._b * 100,
87
+ })
88
+ },
89
+ }
90
+ })
91
+ var elem = createElem('data-proxy-inner-data-exclude-a')
92
+ expect(elem.data.a).toBe(1)
93
+ expect(elem.data._b).toBe(2)
94
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('1 ')
95
+ elem.setData({
96
+ a: 10,
97
+ _b: 20,
98
+ _c: 30,
99
+ })
100
+ expect(elem.data.a).toBe(10)
101
+ expect(elem.data._b).toBe(20)
102
+ expect(elem.data._c).toBe(30)
103
+ expect(elem.data.d).toBe(200)
104
+ expect(elem.data._e).toBe(2000)
105
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('10 200 ')
106
+ })
107
+
108
+ it('should support inner data filter on properties', function(){
109
+ var observerTriggered = []
110
+ regElem({
111
+ is: 'data-proxy-inner-data-exclude-b',
112
+ options: {
113
+ pureDataPattern: /^_/
114
+ },
115
+ template: '<div id="c" prop-abc="{{a}} {{_b}}" />',
116
+ properties: {
117
+ a: {
118
+ type: Number,
119
+ value: 1,
120
+ observer: function() {
121
+ observerTriggered.push('a1')
122
+ }
123
+ },
124
+ _b: {
125
+ type: Number,
126
+ value: 2,
127
+ observer: function() {
128
+ observerTriggered.push('b1')
129
+ }
130
+ },
131
+ },
132
+ observers: {
133
+ a: function() {
134
+ observerTriggered.push('a2')
135
+ },
136
+ _b: function() {
137
+ observerTriggered.push('b2')
138
+ },
139
+ }
140
+ })
141
+ var elem = createElem('data-proxy-inner-data-exclude-b')
142
+ expect(elem.data.a).toBe(1)
143
+ expect(elem.data._b).toBe(2)
144
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('1 ')
145
+ elem.setData({
146
+ a: 10,
147
+ _b: 20,
148
+ })
149
+ expect(elem.data.a).toBe(10)
150
+ expect(elem.data._b).toBe(20)
151
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('10 ')
152
+ expect(observerTriggered).toStrictEqual(['a2', 'b2', 'a1'])
153
+ })
154
+
155
+ it('should support inner data filter (when separating template data disabled)', function(){
156
+ regElem({
157
+ is: 'data-proxy-inner-data-exclude-c',
158
+ options: {
159
+ dataDeepCopy: glassEasel.DeepCopyKind.None,
160
+ pureDataPattern: /^_/
161
+ },
162
+ template: '<div id="c" prop-abc="{{a}} {{_b}} {{_c}} {{d}} {{_e}}" />',
163
+ data: {
164
+ a: 1,
165
+ _b: 2,
166
+ },
167
+ observers: {
168
+ '_b': function() {
169
+ this.setData({
170
+ d: (this.data._b || 40) * 10,
171
+ _e: (this.data._b || 40) * 100,
172
+ })
173
+ },
174
+ }
175
+ })
176
+ var elem = createElem('data-proxy-inner-data-exclude-c')
177
+ expect(elem.data.a).toBe(1)
178
+ expect(elem.data._b).toBe(2)
179
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('1 ')
180
+ elem.setData({
181
+ a: 10,
182
+ _b: 20,
183
+ _c: 30,
184
+ })
185
+ expect(elem.data.a).toBe(10)
186
+ expect(elem.data._b).toBe(20)
187
+ expect(elem.data._c).toBe(30)
188
+ expect(elem.data.d).toBe(200)
189
+ expect(elem.data._e).toBe(2000)
190
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('10 200 ')
191
+ })
192
+
193
+ it('should support inner data filter on properties (when separating template data disabled)', function(){
194
+ var observerTriggered = []
195
+ regElem({
196
+ is: 'data-proxy-inner-data-exclude-d',
197
+ options: {
198
+ dataDeepCopy: glassEasel.DeepCopyKind.None,
199
+ pureDataPattern: /^_/
200
+ },
201
+ template: '<div id="c" prop-abc="{{a}} {{_b}}" />',
202
+ properties: {
203
+ a: {
204
+ type: Number,
205
+ value: 1,
206
+ observer: function() {
207
+ observerTriggered.push('a1')
208
+ }
209
+ },
210
+ _b: {
211
+ type: Number,
212
+ value: 2,
213
+ observer: function() {
214
+ observerTriggered.push('b1')
215
+ }
216
+ },
217
+ },
218
+ observers: {
219
+ a: function() {
220
+ observerTriggered.push('a2')
221
+ },
222
+ _b: function() {
223
+ observerTriggered.push('b2')
224
+ },
225
+ }
226
+ })
227
+ var elem = createElem('data-proxy-inner-data-exclude-d')
228
+ expect(elem.data.a).toBe(1)
229
+ expect(elem.data._b).toBe(2)
230
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('1 ')
231
+ elem.setData({
232
+ a: 10,
233
+ _b: 20,
234
+ })
235
+ expect(elem.data.a).toBe(10)
236
+ expect(elem.data._b).toBe(20)
237
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('10 ')
238
+ expect(observerTriggered).toStrictEqual(['a2', 'b2', 'a1'])
239
+ })
240
+
241
+ it('should not separate template data if options specified', function(){
242
+ regElem({
243
+ is: 'data-proxy-separate-b',
244
+ options: {
245
+ dataDeepCopy: glassEasel.DeepCopyKind.None,
246
+ },
247
+ template: '<div id="c" prop-abc="{{a}} {{b}} {{c}}" />',
248
+ data: {
249
+ a: 1,
250
+ b: 2,
251
+ c: 3,
252
+ }
253
+ })
254
+ var elem = createElem('data-proxy-separate-b')
255
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('1 2 3')
256
+ elem.data.a = 4
257
+ elem.setData({
258
+ b: 5
259
+ })
260
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('4 5 3')
261
+ })
262
+
263
+ it('should not copy when property passing if options specified', function(){
264
+ regElem({
265
+ is: 'data-proxy-prop-passing-deep-copy',
266
+ options: {
267
+ propertyPassingDeepCopy: glassEasel.DeepCopyKind.None,
268
+ },
269
+ template: '<div id="c" prop-abc="{{a.b}}" />',
270
+ properties: {
271
+ a: {
272
+ value: {
273
+ b: 1,
274
+ },
275
+ },
276
+ }
277
+ })
278
+ var elem = createElem('data-proxy-prop-passing-deep-copy')
279
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('1')
280
+ var dataGroup = glassEasel.Component.getDataProxy(elem)
281
+ var c = 4
282
+ dataGroup.replaceDataOnPath(['a', 'b'], c)
283
+ c = 5
284
+ dataGroup.applyDataUpdates()
285
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('4')
286
+ d = {b: c}
287
+ dataGroup.replaceProperty('a', d)
288
+ d.b = 6
289
+ dataGroup.applyDataUpdates()
290
+ expect(elem.$.c.getAttribute('prop-abc')).toBe('6')
291
+ })
292
+
293
+ describe('#scheduleReplace #setChanges #getChanges', function(){
294
+
295
+ it('should support global observer', function(){
296
+ regElem({
297
+ is: 'data-proxy-a',
298
+ properties: {
299
+ prop1: String,
300
+ },
301
+ data: {
302
+ data1: {
303
+ arr: [10, 100]
304
+ }
305
+ },
306
+ observers: [{
307
+ observer: function(newVal) {
308
+ if(observesLeft === 2) {
309
+ expect(newVal).toBe(this.data)
310
+ } else {
311
+ expect(newVal).toBe(this.data)
312
+ }
313
+ observesLeft--
314
+ }
315
+ }]
316
+ })
317
+ var elem = createElem('data-proxy-a')
318
+ var observesLeft = 2
319
+ elem.prop1 = 123
320
+ elem.setData({
321
+ 'data1.arr[1]': '200'
322
+ })
323
+ expect(observesLeft).toBe(0)
324
+ })
325
+
326
+ it('should do replace in correct order', function(){
327
+ regElem({
328
+ is: 'data-proxy-replace',
329
+ data: {
330
+ data1: []
331
+ }
332
+ })
333
+ var elem = createElem('data-proxy-replace')
334
+ elem.groupUpdates(function() {
335
+ elem.replaceDataOnPath(['data2'], {
336
+ f1: {}
337
+ })
338
+ elem.replaceDataOnPath(['data2'], {
339
+ f2: {
340
+ sf1: {
341
+ obj: {}
342
+ },
343
+ sf2: {
344
+ arr: ['a']
345
+ }
346
+ }
347
+ })
348
+ elem.replaceDataOnPath(['data2', 'f3'], {})
349
+ elem.replaceDataOnPath(['data2', 'f2', 'sf1'], true)
350
+ elem.replaceDataOnPath(['data2', 'f2', 'sf2', 'arr', 2], 'c')
351
+ elem.replaceDataOnPath(['data2', 'f2', 'sf2', 'arr', 1], 'b')
352
+ })
353
+ expect(elem.data).toStrictEqual({
354
+ data1: [],
355
+ data2: {
356
+ f2: {
357
+ sf1: true,
358
+ sf2: {
359
+ arr: ['a', 'b', 'c']
360
+ }
361
+ },
362
+ f3: {}
363
+ }
364
+ })
365
+ })
366
+
367
+ it('should be able to set all data changes', function(){
368
+ regElem({
369
+ is: 'data-proxy-replace-set',
370
+ })
371
+ var elem = createElem('data-proxy-replace-set')
372
+ elem.replaceDataOnPath(['data3'], true)
373
+ glassEasel.Component.getDataProxy(elem).setChanges([
374
+ [['data2'], {f1: {}}],
375
+ [['data2'], {
376
+ f2: {
377
+ sf1: {
378
+ obj: {}
379
+ }
380
+ }
381
+ }],
382
+ [['data2'], {f3: {}}],
383
+ [['data2', 'f2', 'sf1'], true],
384
+ ])
385
+ elem.replaceDataOnPath(['data4'], 123)
386
+ elem.applyDataUpdates()
387
+ expect(elem.data).toStrictEqual({
388
+ data4: 123,
389
+ data2: {
390
+ f2: { sf1: true },
391
+ f3: {}
392
+ }
393
+ })
394
+ })
395
+
396
+ it('should be able to get and set all data changes', function(){
397
+ regElem({
398
+ is: 'data-proxy-replace-set',
399
+ })
400
+ var elem = createElem('data-proxy-replace-set')
401
+ elem.replaceDataOnPath(['a'], 1)
402
+ elem.replaceDataOnPath(['b'], 2)
403
+ var changes = glassEasel.Component.getDataProxy(elem).getChanges()
404
+ glassEasel.Component.getDataProxy(elem).setChanges(changes.slice(1))
405
+ elem.applyDataUpdates()
406
+ expect(elem.data.a).toBe(undefined)
407
+ expect(elem.data.b).toBe(2)
408
+ })
409
+
410
+ })
411
+
412
+ describe('#addObserver', function(){
413
+
414
+ it('should trigger data observers', function(){
415
+ var beh = regBeh({
416
+ observers: {
417
+ 'data2.arr.**': function(newVal){
418
+ actualOrder.push(7)
419
+ expect(newVal).toBe(this.data.data2 && this.data.data2.arr)
420
+ }
421
+ }
422
+ })
423
+ regElem({
424
+ is: 'data-proxy-observer',
425
+ behaviors: [beh],
426
+ properties: {
427
+ prop1: {
428
+ type: Number,
429
+ observer: function(newVal){
430
+ actualOrder.push(0)
431
+ }
432
+ }
433
+ },
434
+ observers: {
435
+ 'data2': function f1(newVal){
436
+ actualOrder.push(1)
437
+ expect(newVal).toBe(this.data.data2)
438
+ },
439
+ 'data2.**': function f2(newVal){
440
+ actualOrder.push(2)
441
+ expect(newVal).toBe(this.data.data2)
442
+ },
443
+ 'data2.arr.**': function f3(newVal){
444
+ actualOrder.push(3)
445
+ expect(newVal).toBe(this.data.data2 && this.data.data2.arr)
446
+ },
447
+ 'data2.arr[0].sf1, data2.arr[1].**': function f4(newVal1, newVal2){
448
+ actualOrder.push(4)
449
+ expect(newVal1).toBe(this.data.data2 && this.data.data2.arr[0] && this.data.data2.arr[0].sf1)
450
+ expect(newVal2).toBe(this.data.data2 && this.data.data2.arr[1])
451
+ },
452
+ 'data2.arr[0]': function f5(newVal){
453
+ actualOrder.push(5)
454
+ expect(newVal).toBe(this.data.data2 && this.data.data2.arr[0])
455
+ },
456
+ 'data2.**, not.exists, prop1': function f6(newVal1, newVal2, newVal3){
457
+ actualOrder.push(6)
458
+ expect(newVal1).toBe(this.data.data2)
459
+ expect(newVal2).toBe(undefined)
460
+ expect(newVal3).toBe(this.data.prop1)
461
+ },
462
+ }
463
+ })
464
+ var elem = createElem('data-proxy-observer')
465
+ var actualOrder = null
466
+
467
+ actualOrder = []
468
+ elem.setData({
469
+ prop1: '123',
470
+ data1: null
471
+ })
472
+ expect(elem.data.prop1).toBe(123)
473
+ expect(actualOrder).toStrictEqual([6, 0])
474
+
475
+ actualOrder = []
476
+ elem.setData({
477
+ data2: {
478
+ arr: [{ sf2: 'b' }]
479
+ }
480
+ })
481
+ expect(actualOrder).toStrictEqual([7, 1, 2, 3, 4, 5, 6])
482
+
483
+ actualOrder = []
484
+ elem.setData({
485
+ 'data2.arr[0]': {
486
+ sf1: 'a'
487
+ }
488
+ })
489
+ expect(actualOrder).toStrictEqual([7, 2, 3, 4, 5, 6])
490
+
491
+ actualOrder = []
492
+ elem.setData({
493
+ 'data2.arr[0].sf1': 'a'
494
+ })
495
+ expect(actualOrder).toStrictEqual([7, 2, 3, 4, 6])
496
+
497
+ actualOrder = []
498
+ elem.setData({
499
+ 'data2.arr[1].sf2': 'b'
500
+ })
501
+ expect(actualOrder).toStrictEqual([7, 2, 3, 4, 6])
502
+
503
+ actualOrder = []
504
+ elem.setData({
505
+ prop1: 456,
506
+ 'data2.arr[1]': null
507
+ })
508
+ expect(actualOrder).toStrictEqual([7, 2, 3, 4, 6, 0])
509
+
510
+ actualOrder = []
511
+ elem.setData({
512
+ 'data2.arr[2].sf2': 'b'
513
+ })
514
+ expect(actualOrder).toStrictEqual([7, 2, 3, 6])
515
+ })
516
+
517
+ it('should trigger data observers before applied to templates', function(){
518
+ regElem({
519
+ is: 'data-proxy-observer-b',
520
+ template: '<div id="a" prop-a="{{prop1}}">',
521
+ properties: {
522
+ prop1: {
523
+ type: Number,
524
+ value: 123,
525
+ observer: function(){
526
+ actualOrder.push(0)
527
+ expect(elem.data.prop1).toBe(456)
528
+ expect(elem.$.a.getAttribute('prop-a')).toBe('456')
529
+ }
530
+ }
531
+ },
532
+ observers: {
533
+ '**': function(){
534
+ actualOrder.push(1)
535
+ expect(elem.data.prop1).toBe(456)
536
+ expect(elem.$.a.getAttribute('prop-a')).toBe('123')
537
+ }
538
+ }
539
+ })
540
+ var actualOrder = []
541
+ var elem = createElem('data-proxy-observer-b')
542
+ elem.setData({
543
+ prop1: 456
544
+ })
545
+ expect(actualOrder).toStrictEqual([1, 0])
546
+ })
547
+
548
+ it('should support setData in observers', function(){
549
+ regElem({
550
+ is: 'data-proxy-observer-c',
551
+ template: '<div id="a" prop-a="{{propA}}" prop-b="{{dataB}}">',
552
+ properties: {
553
+ propA: {
554
+ type: Number,
555
+ value: 0,
556
+ public: true,
557
+ observer: function() {
558
+ actualOrder.push(1)
559
+ expect(this.data.propA).toBe(123)
560
+ expect(this.data.dataB).toBe(456)
561
+ expect(this.$.a.getAttribute('prop-a')).toBe('123')
562
+ expect(this.$.a.getAttribute('prop-b')).toBe('456')
563
+ expect(elem.data.dataE).toBe(true)
564
+ }
565
+ }
566
+ },
567
+ observers: {
568
+ propA: function(propA) {
569
+ if (this.propA === 0) return
570
+ actualOrder.push(6)
571
+ expect(propA).toBe(123)
572
+ this.setData({
573
+ dataB: 456
574
+ })
575
+ }
576
+ }
577
+ })
578
+ regElem({
579
+ is: 'data-proxy-observer-d',
580
+ template: '<data-proxy-observer-c id="a" prop-a="{{propC}}" />',
581
+ properties: {
582
+ propC: {
583
+ type: String,
584
+ value: '0',
585
+ observer: function(){
586
+ actualOrder.push(2)
587
+ expect(this.data.propC).toBe('123')
588
+ expect(this.data.dataD).toBe('DDD')
589
+ expect(elem.data.dataE).toBe(true)
590
+ }
591
+ }
592
+ },
593
+ data: {
594
+ dataF: null,
595
+ },
596
+ observers: {
597
+ dataF: function(){
598
+ actualOrder.push(5)
599
+ },
600
+ dataD: function(){
601
+ expect(elem.data.dataE).toBe(false)
602
+ this.setData({
603
+ propC: '123',
604
+ dataE: true,
605
+ dataF: null,
606
+ })
607
+ actualOrder.push(3)
608
+ expect(elem.data.dataE).toBe(true)
609
+ },
610
+ dataE: function(){
611
+ this.setData({
612
+ dataF: null,
613
+ })
614
+ actualOrder.push(4)
615
+ }
616
+ }
617
+ })
618
+ var actualOrder = []
619
+ var elem = createElem('data-proxy-observer-d')
620
+ elem.setData({
621
+ dataD: 'DDD',
622
+ dataE: false,
623
+ dataF: null,
624
+ })
625
+ expect(actualOrder).toStrictEqual([5, 3, 4, 5, 6, 1, 2])
626
+ })
627
+
628
+ it('should treat arrays and objects as the same', function(){
629
+ regElem({
630
+ is: 'data-proxy-observer-obj-arr',
631
+ observers: [{
632
+ fields: 'arr[0]',
633
+ observer: function() {
634
+ actualOrder.push(1)
635
+ }
636
+ }]
637
+ })
638
+ var elem = createElem('data-proxy-observer-obj-arr')
639
+ var actualOrder = null
640
+ actualOrder = []
641
+ elem.setData({
642
+ 'arr.0': 1
643
+ })
644
+ expect(actualOrder).toStrictEqual([1])
645
+ actualOrder = []
646
+ elem.setData({
647
+ 'arr[0]': 1
648
+ })
649
+ expect(actualOrder).toStrictEqual([1])
650
+ })
651
+
652
+ it('should allow multiple listeners on one path', function(){
653
+ var callOrder = []
654
+ var beh = regBeh({
655
+ observers: [{
656
+ fields: 'a',
657
+ observer: 'b1',
658
+ }],
659
+ methods: {
660
+ b1: function(){
661
+ callOrder.push(1)
662
+ }
663
+ },
664
+ })
665
+ regElem({
666
+ is: 'data-proxy-multi-observer-on-field',
667
+ behaviors: [beh],
668
+ observers: {
669
+ a: function(){
670
+ callOrder.push(2)
671
+ }
672
+ },
673
+ })
674
+ var elem = createElem('data-proxy-multi-observer-on-field')
675
+ elem.setData({
676
+ a: 1
677
+ })
678
+ expect(callOrder).toStrictEqual([1, 2])
679
+ })
680
+ })
681
+
682
+ it('should support recursive data fields', function(){
683
+ regElem({
684
+ is: 'data-proxy-rec-data-fields',
685
+ options: {
686
+ dataDeepCopy: glassEasel.DeepCopyKind.SimpleWithRecursion,
687
+ },
688
+ })
689
+ var elem = createElem('data-proxy-rec-data-fields')
690
+ var a = {
691
+ b: null,
692
+ c: 1,
693
+ }
694
+ a.b = a
695
+ elem.setData({
696
+ a: a,
697
+ })
698
+ expect(elem.data.a.c).toBe(1)
699
+ expect(elem.data.a.b.c).toBe(1)
700
+ expect(elem.data.a.b.b.c).toBe(1)
701
+ })
702
+
703
+ it('should support recursive property fields', function(){
704
+ regElem({
705
+ is: 'data-proxy-rec-data-fields',
706
+ options: {
707
+ dataDeepCopy: glassEasel.DeepCopyKind.SimpleWithRecursion,
708
+ propertyPassingDeepCopy: glassEasel.DeepCopyKind.SimpleWithRecursion,
709
+ },
710
+ properties: {
711
+ a: Object,
712
+ },
713
+ })
714
+ var elem = createElem('data-proxy-rec-data-fields')
715
+ var dataGroup = glassEasel.Component.getDataProxy(elem)
716
+ var a = {
717
+ b: null,
718
+ c: 1,
719
+ }
720
+ a.b = a
721
+ dataGroup.replaceProperty('a', a)
722
+ dataGroup.applyDataUpdates()
723
+ expect(elem.data.a.c).toBe(1)
724
+ expect(elem.data.a.b.c).toBe(1)
725
+ expect(elem.data.a.b.b.c).toBe(1)
726
+ })
727
+
728
+ it('should support attributes reflection and ID prefixes', function(){
729
+ regElem({
730
+ is: 'data-proxy-data-reflect-child',
731
+ options: {
732
+ reflectToAttributes: true,
733
+ },
734
+ properties: {
735
+ pA: {
736
+ type: String,
737
+ reflectIdPrefix: true,
738
+ },
739
+ pB: Number,
740
+ },
741
+ })
742
+ regElem({
743
+ is: 'data-proxy-data-reflect-parent',
744
+ options: {
745
+ idPrefixGenerator: function(){
746
+ return 'rid'
747
+ },
748
+ },
749
+ template: '<data-proxy-data-reflect-child id="a" p-a="123" p-b="456" />'
750
+ })
751
+ var elem = createElem('data-proxy-data-reflect-parent')
752
+ var child = elem.$.a
753
+ expect(child.data.pA).toBe('123')
754
+ expect(child.$$.getAttribute('p-a')).toBe('rid--123')
755
+ expect(child.data.pB).toBe(456)
756
+ expect(child.$$.getAttribute('p-b')).toBe('456')
757
+ })
758
+
759
+ })