glass-easel 0.2.0 → 0.3.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 (197) hide show
  1. package/.eslintignore +4 -0
  2. package/dist/glass_easel.all.js +2 -2
  3. package/dist/glass_easel.all.js.map +1 -1
  4. package/dist/glass_easel.d.ts +2546 -0
  5. package/dist/glass_easel.domlike.global.js +2 -2
  6. package/dist/glass_easel.domlike.global.js.map +1 -1
  7. package/guide/zh_CN/appendix/backend_protocol.md +164 -74
  8. package/jest.unit.config.js +7 -4
  9. package/package.json +7 -5
  10. package/rollup.config.ts +101 -0
  11. package/src/backend/backend_protocol.ts +26 -345
  12. package/src/backend/composed_backend_protocol.ts +10 -264
  13. package/src/backend/current_window_backend_context.ts +478 -0
  14. package/src/backend/domlike_backend_protocol.ts +9 -498
  15. package/src/backend/empty_backend.ts +265 -0
  16. package/src/backend/empty_composed_backend.ts +245 -0
  17. package/src/backend/index.ts +18 -0
  18. package/src/backend/suggested_backend_protocol.ts +62 -11
  19. package/src/behavior.ts +131 -442
  20. package/src/class_list.ts +328 -222
  21. package/src/component.ts +349 -184
  22. package/src/component_params.ts +54 -25
  23. package/src/component_space.ts +36 -15
  24. package/src/data_path.ts +22 -34
  25. package/src/data_proxy.ts +334 -27
  26. package/src/devtool.ts +89 -0
  27. package/src/element.ts +667 -285
  28. package/src/element_iterator.ts +9 -4
  29. package/src/event.ts +39 -20
  30. package/src/external_shadow_tree.ts +2 -2
  31. package/src/func_arr.ts +55 -101
  32. package/src/global_options.ts +18 -42
  33. package/src/index.ts +72 -73
  34. package/src/mutation_observer.ts +10 -7
  35. package/src/native_node.ts +79 -35
  36. package/src/node.ts +23 -30
  37. package/src/relation.ts +101 -12
  38. package/src/render.ts +5 -3
  39. package/src/selector.ts +9 -7
  40. package/src/shadow_root.ts +96 -240
  41. package/src/template_engine.ts +10 -7
  42. package/src/text_node.ts +43 -19
  43. package/src/tmpl/index.ts +38 -30
  44. package/src/tmpl/native_rendering.ts +14 -21
  45. package/src/tmpl/proc_gen_wrapper.ts +189 -151
  46. package/src/tmpl/proc_gen_wrapper_dom.ts +10 -8
  47. package/src/tmpl/range_list_diff.ts +30 -9
  48. package/src/trait_behaviors.ts +1 -1
  49. package/src/type_symbol.ts +36 -0
  50. package/src/virtual_node.ts +26 -13
  51. package/src/warning.ts +119 -0
  52. package/tests/base/composed_backend.ts +143 -142
  53. package/tests/base/env.ts +76 -3
  54. package/tests/base/match.ts +24 -22
  55. package/tests/base/shadow_backend.ts +917 -0
  56. package/tests/core/backend.test.ts +53 -1
  57. package/tests/core/behavior.test.ts +1 -1
  58. package/tests/core/data_update.test.ts +135 -0
  59. package/tests/core/misc.test.ts +91 -21
  60. package/tests/core/placeholder.test.ts +66 -25
  61. package/tests/core/slot.test.ts +161 -23
  62. package/tests/legacy/component.test.js +152 -78
  63. package/tests/legacy/data_path.test.js +19 -19
  64. package/tests/legacy/data_proxy.test.js +14 -7
  65. package/tests/legacy/external.test.js +8 -8
  66. package/tests/legacy/mutation_observer.test.js +7 -5
  67. package/tests/legacy/slot.test.js +2 -3
  68. package/tests/legacy/virtual.test.js +258 -25
  69. package/tests/tmpl/binding_map.test.ts +201 -195
  70. package/tests/tmpl/event.test.ts +138 -23
  71. package/tests/tmpl/expression.test.ts +15 -15
  72. package/tests/tmpl/lvalue.test.ts +101 -0
  73. package/tests/tmpl/structure.test.ts +486 -43
  74. package/tests/types/chaining.test.ts +27 -30
  75. package/tests/types/createElement.test.ts +5 -4
  76. package/tests/types/definition.test.ts +11 -14
  77. package/tsconfig.json +1 -3
  78. package/dist/glass_easel.all.d.ts +0 -1
  79. package/dist/glass_easel.domlike.global.d.ts +0 -1
  80. package/dist/index.d.ts +0 -1
  81. package/dist/index.js +0 -1
  82. package/dist/types/src/backend/backend_protocol.d.ts +0 -141
  83. package/dist/types/src/backend/backend_protocol.d.ts.map +0 -1
  84. package/dist/types/src/backend/composed_backend_protocol.d.ts +0 -102
  85. package/dist/types/src/backend/composed_backend_protocol.d.ts.map +0 -1
  86. package/dist/types/src/backend/domlike_backend_protocol.d.ts +0 -100
  87. package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +0 -1
  88. package/dist/types/src/backend/mode.d.ts +0 -65
  89. package/dist/types/src/backend/mode.d.ts.map +0 -1
  90. package/dist/types/src/backend/suggested_backend_protocol.d.ts +0 -30
  91. package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +0 -1
  92. package/dist/types/src/behavior.d.ts +0 -434
  93. package/dist/types/src/behavior.d.ts.map +0 -1
  94. package/dist/types/src/class_list.d.ts +0 -83
  95. package/dist/types/src/class_list.d.ts.map +0 -1
  96. package/dist/types/src/component.d.ts +0 -325
  97. package/dist/types/src/component.d.ts.map +0 -1
  98. package/dist/types/src/component_params.d.ts +0 -236
  99. package/dist/types/src/component_params.d.ts.map +0 -1
  100. package/dist/types/src/component_space.d.ts +0 -211
  101. package/dist/types/src/component_space.d.ts.map +0 -1
  102. package/dist/types/src/data_path.d.ts +0 -5
  103. package/dist/types/src/data_path.d.ts.map +0 -1
  104. package/dist/types/src/data_proxy.d.ts +0 -107
  105. package/dist/types/src/data_proxy.d.ts.map +0 -1
  106. package/dist/types/src/data_utils.d.ts +0 -3
  107. package/dist/types/src/data_utils.d.ts.map +0 -1
  108. package/dist/types/src/element.d.ts +0 -365
  109. package/dist/types/src/element.d.ts.map +0 -1
  110. package/dist/types/src/element_iterator.d.ts +0 -43
  111. package/dist/types/src/element_iterator.d.ts.map +0 -1
  112. package/dist/types/src/event.d.ts +0 -105
  113. package/dist/types/src/event.d.ts.map +0 -1
  114. package/dist/types/src/external_shadow_tree.d.ts +0 -20
  115. package/dist/types/src/external_shadow_tree.d.ts.map +0 -1
  116. package/dist/types/src/func_arr.d.ts +0 -39
  117. package/dist/types/src/func_arr.d.ts.map +0 -1
  118. package/dist/types/src/global_options.d.ts +0 -120
  119. package/dist/types/src/global_options.d.ts.map +0 -1
  120. package/dist/types/src/index.d.ts +0 -43
  121. package/dist/types/src/index.d.ts.map +0 -1
  122. package/dist/types/src/mutation_observer.d.ts +0 -79
  123. package/dist/types/src/mutation_observer.d.ts.map +0 -1
  124. package/dist/types/src/native_node.d.ts +0 -11
  125. package/dist/types/src/native_node.d.ts.map +0 -1
  126. package/dist/types/src/node.d.ts +0 -48
  127. package/dist/types/src/node.d.ts.map +0 -1
  128. package/dist/types/src/relation.d.ts +0 -46
  129. package/dist/types/src/relation.d.ts.map +0 -1
  130. package/dist/types/src/render.d.ts +0 -3
  131. package/dist/types/src/render.d.ts.map +0 -1
  132. package/dist/types/src/selector.d.ts +0 -32
  133. package/dist/types/src/selector.d.ts.map +0 -1
  134. package/dist/types/src/shadow_root.d.ts +0 -174
  135. package/dist/types/src/shadow_root.d.ts.map +0 -1
  136. package/dist/types/src/template_engine.d.ts +0 -56
  137. package/dist/types/src/template_engine.d.ts.map +0 -1
  138. package/dist/types/src/text_node.d.ts +0 -44
  139. package/dist/types/src/text_node.d.ts.map +0 -1
  140. package/dist/types/src/tmpl/index.d.ts +0 -19
  141. package/dist/types/src/tmpl/index.d.ts.map +0 -1
  142. package/dist/types/src/tmpl/native_rendering.d.ts +0 -45
  143. package/dist/types/src/tmpl/native_rendering.d.ts.map +0 -1
  144. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +0 -89
  145. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +0 -1
  146. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +0 -50
  147. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +0 -1
  148. package/dist/types/src/tmpl/range_list_diff.d.ts +0 -19
  149. package/dist/types/src/tmpl/range_list_diff.d.ts.map +0 -1
  150. package/dist/types/src/trait_behaviors.d.ts +0 -38
  151. package/dist/types/src/trait_behaviors.d.ts.map +0 -1
  152. package/dist/types/src/virtual_node.d.ts +0 -10
  153. package/dist/types/src/virtual_node.d.ts.map +0 -1
  154. package/dist/types/tests/backend/domlike.test.d.ts +0 -2
  155. package/dist/types/tests/backend/domlike.test.d.ts.map +0 -1
  156. package/dist/types/tests/base/composed_backend.d.ts +0 -123
  157. package/dist/types/tests/base/composed_backend.d.ts.map +0 -1
  158. package/dist/types/tests/base/env.d.ts +0 -30
  159. package/dist/types/tests/base/env.d.ts.map +0 -1
  160. package/dist/types/tests/base/match.d.ts +0 -9
  161. package/dist/types/tests/base/match.d.ts.map +0 -1
  162. package/dist/types/tests/core/backend.test.d.ts +0 -2
  163. package/dist/types/tests/core/backend.test.d.ts.map +0 -1
  164. package/dist/types/tests/core/behavior.test.d.ts +0 -2
  165. package/dist/types/tests/core/behavior.test.d.ts.map +0 -1
  166. package/dist/types/tests/core/component_space.test.d.ts +0 -2
  167. package/dist/types/tests/core/component_space.test.d.ts.map +0 -1
  168. package/dist/types/tests/core/data_update.test.d.ts +0 -2
  169. package/dist/types/tests/core/data_update.test.d.ts.map +0 -1
  170. package/dist/types/tests/core/misc.test.d.ts +0 -2
  171. package/dist/types/tests/core/misc.test.d.ts.map +0 -1
  172. package/dist/types/tests/core/placeholder.test.d.ts +0 -2
  173. package/dist/types/tests/core/placeholder.test.d.ts.map +0 -1
  174. package/dist/types/tests/core/slot.test.d.ts +0 -2
  175. package/dist/types/tests/core/slot.test.d.ts.map +0 -1
  176. package/dist/types/tests/core/trait_behaviors.test.d.ts +0 -2
  177. package/dist/types/tests/core/trait_behaviors.test.d.ts.map +0 -1
  178. package/dist/types/tests/tmpl/binding_map.test.d.ts +0 -2
  179. package/dist/types/tests/tmpl/binding_map.test.d.ts.map +0 -1
  180. package/dist/types/tests/tmpl/event.test.d.ts +0 -2
  181. package/dist/types/tests/tmpl/event.test.d.ts.map +0 -1
  182. package/dist/types/tests/tmpl/expression.test.d.ts +0 -2
  183. package/dist/types/tests/tmpl/expression.test.d.ts.map +0 -1
  184. package/dist/types/tests/tmpl/lvalue.test.d.ts +0 -2
  185. package/dist/types/tests/tmpl/lvalue.test.d.ts.map +0 -1
  186. package/dist/types/tests/tmpl/native_rendering.test.d.ts +0 -2
  187. package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +0 -1
  188. package/dist/types/tests/tmpl/structure.test.d.ts +0 -2
  189. package/dist/types/tests/tmpl/structure.test.d.ts.map +0 -1
  190. package/dist/types/tests/types/chaining.test.d.ts +0 -2
  191. package/dist/types/tests/types/chaining.test.d.ts.map +0 -1
  192. package/dist/types/tests/types/createElement.test.d.ts +0 -2
  193. package/dist/types/tests/types/createElement.test.d.ts.map +0 -1
  194. package/dist/types/tests/types/definition.test.d.ts +0 -2
  195. package/dist/types/tests/types/definition.test.d.ts.map +0 -1
  196. package/webpack.config.js +0 -275
  197. /package/src/backend/{mode.ts → shared.ts} +0 -0
@@ -1,22 +1,22 @@
1
- import { tmpl, domBackend } from '../base/env'
1
+ import { tmpl, domBackend, composedBackend, shadowBackend } from '../base/env'
2
2
  import { virtual as matchElementWithDom } from '../base/match'
3
3
  import * as glassEasel from '../../src'
4
4
 
5
- const componentSpace = new glassEasel.ComponentSpace()
6
- componentSpace.updateComponentOptions({
7
- writeFieldsToNode: true,
8
- writeIdToDOM: true,
9
- })
10
- componentSpace.defineComponent({
11
- is: '',
12
- })
13
-
14
5
  const domHtml = (elem: glassEasel.Element): string => {
15
6
  const domElem = elem.getBackendElement() as unknown as Element
16
7
  return domElem.innerHTML
17
8
  }
18
9
 
19
- describe('slot', () => {
10
+ const testCases = (testBackend: glassEasel.GeneralBackendContext) => {
11
+ const componentSpace = new glassEasel.ComponentSpace()
12
+ componentSpace.updateComponentOptions({
13
+ writeFieldsToNode: true,
14
+ writeIdToDOM: true,
15
+ })
16
+ componentSpace.defineComponent({
17
+ is: '',
18
+ })
19
+
20
20
  describe('dynamic slot', () => {
21
21
  describe('core', () => {
22
22
  test('should support duplicate slot', () => {
@@ -62,7 +62,7 @@ describe('slot', () => {
62
62
  const parentElem = glassEasel.Component.createWithContext(
63
63
  'root',
64
64
  parent.general(),
65
- domBackend,
65
+ testBackend,
66
66
  )
67
67
  const childElem = parentElem.getShadowRoot()!.childNodes[0]!.asInstanceOf(child)!
68
68
  const a = childElem.$.a as glassEasel.Element
@@ -192,7 +192,7 @@ describe('slot', () => {
192
192
  const parentElem = glassEasel.Component.createWithContext(
193
193
  'root',
194
194
  parent.general(),
195
- domBackend,
195
+ testBackend,
196
196
  )
197
197
  const childElem = parentElem.getShadowRoot()!.childNodes[0]!.asInstanceOf(child)!
198
198
 
@@ -378,7 +378,7 @@ describe('slot', () => {
378
378
  const parentElem = glassEasel.Component.createWithContext(
379
379
  'root',
380
380
  parent.general(),
381
- domBackend,
381
+ testBackend,
382
382
  )
383
383
  const childElem = parentElem.getShadowRoot()!.childNodes[0]!.asInstanceOf(child)!
384
384
 
@@ -447,7 +447,7 @@ describe('slot', () => {
447
447
  const parentElem = glassEasel.Component.createWithContext(
448
448
  'root',
449
449
  parent.general(),
450
- domBackend,
450
+ testBackend,
451
451
  )
452
452
  const childElem = parentElem.getShadowRoot()!.childNodes[0]!.asInstanceOf(child)!
453
453
 
@@ -583,7 +583,7 @@ describe('slot', () => {
583
583
  const parentElem = glassEasel.Component.createWithContext(
584
584
  'root',
585
585
  parent.general(),
586
- domBackend,
586
+ testBackend,
587
587
  ).asInstanceOf(parent)!
588
588
 
589
589
  glassEasel.Element.pretendAttached(parentElem)
@@ -843,7 +843,7 @@ describe('slot', () => {
843
843
  const parentElem = glassEasel.Component.createWithContext(
844
844
  'root',
845
845
  parent.general(),
846
- domBackend,
846
+ testBackend,
847
847
  ).asInstanceOf(parent)!
848
848
 
849
849
  glassEasel.Element.pretendAttached(parentElem)
@@ -1018,7 +1018,7 @@ describe('slot', () => {
1018
1018
  const parentElem = glassEasel.Component.createWithContext(
1019
1019
  'root',
1020
1020
  parent.general(),
1021
- domBackend,
1021
+ testBackend,
1022
1022
  ).asInstanceOf(parent)!
1023
1023
  const childElem = parentElem.getShadowRoot()!.childNodes[0]!.asInstanceOf(child)!
1024
1024
 
@@ -1113,7 +1113,7 @@ describe('slot', () => {
1113
1113
  })
1114
1114
  .registerComponent()
1115
1115
 
1116
- const parentElem = glassEasel.Component.createWithContext('root', parent, domBackend)
1116
+ const parentElem = glassEasel.Component.createWithContext('root', parent, testBackend)
1117
1117
  glassEasel.Element.pretendAttached(parentElem)
1118
1118
  const childElem = parentElem.getShadowRoot()!.childNodes[1]!.asInstanceOf(child)!
1119
1119
 
@@ -1308,7 +1308,7 @@ describe('slot', () => {
1308
1308
  const parentElem = glassEasel.Component.createWithContext(
1309
1309
  'root',
1310
1310
  parent.general(),
1311
- domBackend,
1311
+ testBackend,
1312
1312
  )
1313
1313
  const noneElem = parentElem.getShadowRoot()!.childNodes[0]!.asInstanceOf(none)!
1314
1314
  const recElem = parentElem.getShadowRoot()!.childNodes[1]!.asInstanceOf(rec)!
@@ -1368,7 +1368,7 @@ describe('slot', () => {
1368
1368
  const parentElem = glassEasel.Component.createWithContext(
1369
1369
  'root',
1370
1370
  parent.general(),
1371
- domBackend,
1371
+ testBackend,
1372
1372
  )
1373
1373
 
1374
1374
  expect(domHtml(parentElem)).toBe('<impl><div><div>123</div></div></impl>')
@@ -1394,6 +1394,140 @@ describe('slot', () => {
1394
1394
  expect(domHtml(parentElem)).toBe('<impl><span><div>456</div></span></impl>')
1395
1395
  matchElementWithDom(parentElem)
1396
1396
  })
1397
+
1398
+ test('should support slot as slot content', () => {
1399
+ const comp = componentSpace
1400
+ .define()
1401
+ .options({
1402
+ multipleSlots: true,
1403
+ })
1404
+ .template(
1405
+ tmpl(`
1406
+ <div>comp</div>
1407
+ <slot name="comp-slot"></slot>
1408
+ `),
1409
+ )
1410
+ .registerComponent()
1411
+
1412
+ const child = componentSpace
1413
+ .define()
1414
+ .options({
1415
+ multipleSlots: true,
1416
+ })
1417
+ .usingComponents({ comp })
1418
+ .template(
1419
+ tmpl(`
1420
+ <comp>
1421
+ <div>child</div>
1422
+ <slot name="child-slot" slot="{{s}}" />
1423
+ </comp>
1424
+ `),
1425
+ )
1426
+ .property('s', String)
1427
+ .registerComponent()
1428
+
1429
+ const parent = componentSpace
1430
+ .define()
1431
+ .usingComponents({ child })
1432
+ .template(
1433
+ tmpl(`
1434
+ <child s="{{s}}">
1435
+ <div slot="child-slot">content</div>
1436
+ </child>
1437
+ `),
1438
+ )
1439
+ .data(() => ({
1440
+ s: '',
1441
+ }))
1442
+ .registerComponent()
1443
+
1444
+ const parentElem = glassEasel.Component.createWithContext(
1445
+ 'root',
1446
+ parent.general(),
1447
+ testBackend,
1448
+ )
1449
+ expect(domHtml(parentElem)).toBe('<child><comp><div>comp</div></comp></child>')
1450
+
1451
+ parentElem.setData({
1452
+ s: 'comp-slot',
1453
+ })
1454
+ expect(domHtml(parentElem)).toBe(
1455
+ '<child><comp><div>comp</div><div>content</div></comp></child>',
1456
+ )
1457
+
1458
+ parentElem.setData({
1459
+ s: 'invalid',
1460
+ })
1461
+ expect(domHtml(parentElem)).toBe('<child><comp><div>comp</div></comp></child>')
1462
+ })
1463
+
1464
+ test('should support slot as slot content with virtual host and placeholder', () => {
1465
+ const placeholder = componentSpace
1466
+ .define()
1467
+ .options({
1468
+ multipleSlots: true,
1469
+ virtualHost: true,
1470
+ })
1471
+ .template(
1472
+ tmpl(`
1473
+ <div>placeholder</div>
1474
+ <slot name="content"></slot>
1475
+ `),
1476
+ )
1477
+ .registerComponent()
1478
+
1479
+ const child = componentSpace
1480
+ .define()
1481
+ .options({
1482
+ multipleSlots: true,
1483
+ virtualHost: true,
1484
+ })
1485
+ .usingComponents({ comp: 'comp', placeholder })
1486
+ .placeholders({ comp: 'placeholder' })
1487
+ .template(
1488
+ tmpl(`
1489
+ <comp>
1490
+ <div>child</div>
1491
+ <slot name="content" slot="content" />
1492
+ </comp>
1493
+ `),
1494
+ )
1495
+ .registerComponent()
1496
+
1497
+ const parent = componentSpace
1498
+ .define()
1499
+ .usingComponents({ child })
1500
+ .template(
1501
+ tmpl(`
1502
+ <child>
1503
+ <div slot="content">content</div>
1504
+ </child>
1505
+ `),
1506
+ )
1507
+ .registerComponent()
1508
+
1509
+ const parentElem = glassEasel.Component.createWithContext(
1510
+ 'root',
1511
+ parent.general(),
1512
+ testBackend,
1513
+ )
1514
+ expect(domHtml(parentElem)).toBe('<div>placeholder</div><div>content</div>')
1515
+
1516
+ componentSpace
1517
+ .define('comp')
1518
+ .options({
1519
+ multipleSlots: true,
1520
+ })
1521
+ .template(
1522
+ tmpl(`
1523
+ <div>comp</div>
1524
+ <slot name="content"></slot>
1525
+ `),
1526
+ )
1527
+ .registerComponent()
1528
+
1529
+ expect(domHtml(parentElem)).toBe('<comp><div>comp</div><div>content</div></comp>')
1530
+ })
1397
1531
  })
1398
1532
  })
1399
1533
 
@@ -1434,7 +1568,7 @@ describe('slot', () => {
1434
1568
  })
1435
1569
  .registerComponent()
1436
1570
 
1437
- const parentElem = glassEasel.Component.createWithContext('root', parent, domBackend)
1571
+ const parentElem = glassEasel.Component.createWithContext('root', parent, testBackend)
1438
1572
  const singleElem = (parentElem.$.s as glassEasel.Element).asInstanceOf(single)!
1439
1573
  const multiElem = (parentElem.$.m as glassEasel.Element).asInstanceOf(multi)!
1440
1574
  const dynamicElem = (parentElem.$.d as glassEasel.Element).asInstanceOf(dynamic)!
@@ -1555,4 +1689,8 @@ describe('slot', () => {
1555
1689
  )
1556
1690
  })
1557
1691
  })
1558
- })
1692
+ }
1693
+
1694
+ describe('slot (DOM backend)', () => testCases(domBackend))
1695
+ describe('slot (shadow backend)', () => testCases(shadowBackend))
1696
+ describe('slot (composed backend)', () => testCases(composedBackend))
@@ -1,34 +1,39 @@
1
1
  /* eslint-disable */
2
2
 
3
- const { tmpl, domBackend, shadowBackend, execWithWarn } = require('../base/env')
3
+ const { tmpl, domBackend, shadowBackend, execWithWarn, composedBackend, getCustomExternalTemplateEngine } = require('../base/env')
4
4
  const glassEasel = require('../../src')
5
5
 
6
- const componentSpace = new glassEasel.ComponentSpace()
7
- componentSpace.updateComponentOptions({
8
- writeFieldsToNode: true,
9
- })
10
- componentSpace.defineComponent({
11
- is: '',
12
- })
13
6
 
14
- const regBeh = (config) => {
15
- return componentSpace.defineBehavior(config)
16
- }
7
+ const testCases = function (testBackend) {
8
+ const componentSpace = new glassEasel.ComponentSpace(
9
+ undefined,
10
+ undefined,
11
+ glassEasel.getDefaultComponentSpace().styleScopeManager,
12
+ )
13
+ componentSpace.updateComponentOptions({
14
+ writeFieldsToNode: true,
15
+ })
16
+ componentSpace.defineComponent({
17
+ is: '',
18
+ })
17
19
 
18
- const regElem = (config) => {
19
- const { template, ...c } = config
20
- if (template) c.template = tmpl(template)
21
- const ret = componentSpace.defineComponent(c)
22
- componentSpace.setGlobalUsingComponent(config.is, ret)
23
- return ret
24
- }
20
+ const regBeh = (config) => {
21
+ return componentSpace.defineBehavior(config)
22
+ }
25
23
 
26
- const createElem = (is, backend) => {
27
- const def = componentSpace.getComponent(is)
28
- return glassEasel.Component.createWithContext(is || 'test', def, backend || domBackend)
29
- }
24
+ const regElem = (config) => {
25
+ const { template, ...c } = config
26
+ if (template) c.template = tmpl(template)
27
+ const ret = componentSpace.defineComponent(c)
28
+ componentSpace.setGlobalUsingComponent(config.is, ret)
29
+ return ret
30
+ }
31
+
32
+ const createElem = (is, backend) => {
33
+ const def = componentSpace.getComponent(is)
34
+ return glassEasel.Component.createWithContext(is || 'test', def, backend || testBackend)
35
+ }
30
36
 
31
- describe('Component', function () {
32
37
  describe('#register', function () {
33
38
  it('should be able to register component', function () {
34
39
  regElem({
@@ -562,7 +567,9 @@ describe('Component', function () {
562
567
  var elem = createElem('')
563
568
  expect(elem).toBeInstanceOf(glassEasel.Element)
564
569
  expect(elem.is).toBe('')
565
- expect(elem.$$).toBeInstanceOf(window.HTMLElement)
570
+ if (testBackend === domBackend) {
571
+ expect(elem.$$).toBeInstanceOf(window.HTMLElement)
572
+ }
566
573
  })
567
574
 
568
575
  it('should call lifetime methods', function () {
@@ -699,11 +706,11 @@ describe('Component', function () {
699
706
  var elem = createElem('component-attr-a')
700
707
  expect(elem.data.da).toBe(1)
701
708
  expect(elem.$.a.$$.getAttribute('attr-a')).toBe('1')
702
- expect(elem.$.a.getAttribute('attr-a')).toBe('1')
709
+ expect(elem.$.a.getAttribute('attr-a')).toBe(1)
703
710
  elem.data = { da: 2 }
704
711
  expect(elem.data.da).toBe(2)
705
712
  expect(elem.$.a.$$.getAttribute('attr-a')).toBe('2')
706
- expect(elem.$.a.getAttribute('attr-a')).toBe('2')
713
+ expect(elem.$.a.getAttribute('attr-a')).toBe(2)
707
714
  })
708
715
 
709
716
  it('should reflect to attributes', function () {
@@ -851,7 +858,10 @@ describe('Component', function () {
851
858
  template: '<div></div>',
852
859
  lifetimes: {
853
860
  created: function (e) {
854
- throw new Error('test')
861
+ throw new Error('created')
862
+ },
863
+ attached: function (e) {
864
+ throw new Error('attached')
855
865
  },
856
866
  error: function (e) {
857
867
  errorCalled++
@@ -859,12 +869,15 @@ describe('Component', function () {
859
869
  },
860
870
  },
861
871
  })
862
- createElem('component-error-lifetimes-a')
872
+ const elem = createElem('component-error-lifetimes-a')
863
873
 
864
- glassEasel.globalOptions.throwGlobalError = true
865
- console.error = oldConsoleError
866
874
  expect(errorCalled).toBe(1)
867
- expect(errorObj.message).toBe('test')
875
+ expect(errorObj.message).toBe('created')
876
+ glassEasel.Element.pretendAttached(elem)
877
+ expect(errorCalled).toBe(2)
878
+ expect(errorObj.message).toBe('attached')
879
+ console.error = oldConsoleError
880
+ glassEasel.globalOptions.throwGlobalError = true
868
881
  })
869
882
 
870
883
  describe('#ownerShadowRoot', function () {
@@ -922,53 +935,82 @@ describe('Component', function () {
922
935
  extraStyleScope: glassEasel.StyleScopeManager.globalScope(),
923
936
  },
924
937
  behaviors: ['component-class-beh'],
925
- template: '<span id="b"></span>',
938
+ template: '<span id="b" class="bb"></span>',
939
+ })
940
+ regElem({
941
+ is: 'component-class-c',
942
+ options: {
943
+ styleScope: componentSpace.styleScopeManager.register('component-class-c'),
944
+ extraStyleScope: componentSpace.styleScopeManager.register('component-class-cc'),
945
+ },
946
+ behaviors: ['component-class-beh'],
947
+ template: '<span id="c" class="cc"></span>',
926
948
  })
927
949
  })
928
950
 
929
951
  it('should allow setting classes', function () {
930
952
  var elem = createElem('component-class-a')
931
- var elem2 = createElem('component-class-b')
932
953
  expect(elem.$.a.classList.contains('aa')).toBe(true)
933
- expect(elem2.$.b.classList.contains('aa')).toBe(false)
934
954
  expect(elem.$.a.classList.contains('component-class-a--aa')).toBe(false)
935
- expect(elem2.$.b.classList.contains('component-class-b--aa')).toBe(false)
936
955
  expect(elem.$.a.class).toBe('aa')
937
956
  expect(elem.$.a.$$.getAttribute('class')).toBe('component-class-a--aa')
938
- expect(elem2.$.b.class).toBe('')
939
- expect(elem2.$.b.$$.getAttribute('class')).toBe(null)
940
957
  elem.$.a.classList.toggle('aa')
941
958
  elem.$.a.classList.toggle('a-a')
959
+ expect(elem.$.a.class).toBe('a-a')
942
960
  expect(elem.$.a.classList.contains('aa')).toBe(false)
943
961
  expect(elem.$.a.classList.contains('a-a')).toBe(true)
944
962
  expect(elem.$.a.$$.getAttribute('class')).toBe('component-class-a--a-a')
945
963
  elem.$.a.classList.toggle('aa', false)
946
964
  elem.$.a.classList.toggle('a-a', true)
965
+ expect(elem.$.a.class).toBe('a-a')
947
966
  expect(elem.$.a.classList.contains('aa')).toBe(false)
948
967
  expect(elem.$.a.classList.contains('a-a')).toBe(true)
949
968
  expect(elem.$.a.$$.getAttribute('class')).toBe('component-class-a--a-a')
950
- })
951
-
952
- it('should allow setting classes in non-DOM backend', function () {
953
- var elem = createElem('component-class-a', shadowBackend)
954
- var elem2 = createElem('component-class-b', shadowBackend)
955
- expect(elem.$.a.classList.contains('aa')).toBe(true)
956
- expect(elem2.$.b.classList.contains('aa')).toBe(false)
957
- expect(elem.$.a.classList.contains('component-class-a--aa')).toBe(false)
958
- expect(elem2.$.b.classList.contains('component-class-b--aa')).toBe(false)
959
- expect(elem.$.a.class).toBe('aa')
960
- expect(elem2.$.b.class).toBe('')
961
- elem.$.a.class = 'aa'
969
+ elem.$.a.classList.setClassNames(['aa', 'a-a'])
970
+ expect(elem.$.a.class).toBe('aa a-a')
962
971
  expect(elem.$.a.classList.contains('aa')).toBe(true)
963
- expect(elem.$.a.classList.contains('a-a')).toBe(false)
964
- elem.$.a.classList.toggle('aa', false)
965
- elem.$.a.classList.toggle('a-a', true)
966
- expect(elem.$.a.classList.contains('aa')).toBe(false)
967
972
  expect(elem.$.a.classList.contains('a-a')).toBe(true)
968
- elem.$.a.destroyBackendElement()
969
- elem.$.a.class = 'aa'
970
- expect(elem.$.a.classList.contains('aa')).toBe(true)
971
- expect(elem.$.a.classList.contains('a-a')).toBe(false)
973
+ expect(elem.$.a.$$.getAttribute('class')).toBe('component-class-a--a-a component-class-a--aa')
974
+ })
975
+
976
+ it('should allow setting classes with extra global style scope', function () {
977
+ var elem = createElem('component-class-b')
978
+ expect(elem.$.b.classList.contains('bb')).toBe(true)
979
+ expect(elem.$.b.classList.contains('component-class-b--bb')).toBe(false)
980
+ expect(elem.$.b.class).toBe('bb')
981
+ expect(elem.$.b.$$.getAttribute('class')).toBe('bb component-class-b--bb')
982
+ elem.$.b.classList.toggle('bb')
983
+ elem.$.b.classList.toggle('b-b')
984
+ expect(elem.$.b.class).toBe('b-b')
985
+ expect(elem.$.b.classList.contains('bb')).toBe(false)
986
+ expect(elem.$.b.classList.contains('b-b')).toBe(true)
987
+ expect(elem.$.b.$$.getAttribute('class')).toBe('b-b component-class-b--b-b')
988
+ elem.$.b.classList.toggle('bb', false)
989
+ elem.$.b.classList.toggle('b-b', true)
990
+ expect(elem.$.b.class).toBe('b-b')
991
+ expect(elem.$.b.classList.contains('bb')).toBe(false)
992
+ expect(elem.$.b.classList.contains('b-b')).toBe(true)
993
+ expect(elem.$.b.$$.getAttribute('class')).toBe('b-b component-class-b--b-b')
994
+ })
995
+
996
+ it('should allow setting classes with extra style scope', function () {
997
+ var elem = createElem('component-class-c')
998
+ expect(elem.$.c.classList.contains('cc')).toBe(true)
999
+ expect(elem.$.c.classList.contains('component-class-c--cc')).toBe(false)
1000
+ expect(elem.$.c.class).toBe('cc')
1001
+ expect(elem.$.c.$$.getAttribute('class')).toBe('component-class-cc--cc component-class-c--cc')
1002
+ elem.$.c.classList.toggle('cc')
1003
+ elem.$.c.classList.toggle('c-c')
1004
+ expect(elem.$.c.class).toBe('c-c')
1005
+ expect(elem.$.c.classList.contains('cc')).toBe(false)
1006
+ expect(elem.$.c.classList.contains('c-c')).toBe(true)
1007
+ expect(elem.$.c.$$.getAttribute('class')).toBe('component-class-cc--c-c component-class-c--c-c')
1008
+ elem.$.c.classList.toggle('cc', false)
1009
+ elem.$.c.classList.toggle('c-c', true)
1010
+ expect(elem.$.c.class).toBe('c-c')
1011
+ expect(elem.$.c.classList.contains('cc')).toBe(false)
1012
+ expect(elem.$.c.classList.contains('c-c')).toBe(true)
1013
+ expect(elem.$.c.$$.getAttribute('class')).toBe('component-class-cc--c-c component-class-c--c-c')
972
1014
  })
973
1015
 
974
1016
  it('should be able to disable class prefix', function () {
@@ -1017,7 +1059,7 @@ describe('Component', function () {
1017
1059
  options: {
1018
1060
  styleScope: componentSpace.styleScopeManager.register('a'),
1019
1061
  },
1020
- template: '<span id="a" class="a ^a ^^aa ~a"></span>',
1062
+ template: '<span id="a" class="a ^a1 ^^a2 ^^^a3 ^^^^a4 ~a5"></span>',
1021
1063
  })
1022
1064
  regElem({
1023
1065
  is: 'component-class-special-prefix-b',
@@ -1025,25 +1067,25 @@ describe('Component', function () {
1025
1067
  styleScope: componentSpace.styleScopeManager.register('b'),
1026
1068
  extraStyleScope: glassEasel.StyleScopeManager.globalScope(),
1027
1069
  },
1028
- template: '<component-class-special-prefix-a id="b" class="b ^b ^^b ^^^bbb ~bb" />',
1070
+ template: '<component-class-special-prefix-a id="b" class="b ^b1 ^^b2 ^^^b3 ~b4" />',
1029
1071
  })
1030
1072
  regElem({
1031
1073
  is: 'component-class-special-prefix-c',
1032
1074
  options: {
1033
1075
  styleScope: componentSpace.styleScopeManager.register('c'),
1034
1076
  },
1035
- template: '<component-class-special-prefix-b id="c" class="c ^c ~c" />',
1077
+ template: '<component-class-special-prefix-b id="c" class="c ^c1 ^^c2 ~c3" />',
1036
1078
  })
1037
1079
  var elem = createElem('component-class-special-prefix-c')
1038
- expect(elem.$.c.class).toBe('c ^c ~c')
1039
- expect(elem.$.c.$$.getAttribute('class')).toBe('c--c c')
1040
- expect(elem.$.c.shadowRoot.querySelector('.bb').$$.getAttribute('class')).toBe(
1041
- 'b b--b c--b c--bbb c--bb',
1080
+ expect(elem.$.c.class).toBe('c ^c1 ^^c2 ~c3')
1081
+ expect(elem.$.c.$$.getAttribute('class')).toBe('c--c c--c1 c--c2 c--c3')
1082
+ expect(elem.$.c.shadowRoot.querySelector('.b2').$$.getAttribute('class')).toBe(
1083
+ 'b b--b c--b1 c--b2 c--b3 c--b4',
1042
1084
  )
1043
- expect(elem.$.c.$.b.shadowRoot.querySelector('.aa').$$.getAttribute('class')).toBe(
1044
- 'a--a b--a c--aa c--a',
1085
+ expect(elem.$.c.$.b.shadowRoot.querySelector('.a2').$$.getAttribute('class')).toBe(
1086
+ 'a--a b--a1 c--a2 c--a3 c--a4 c--a5',
1045
1087
  )
1046
- expect(elem.$.c.$.b.$.a.$$.getAttribute('class')).toBe('a--a b--a c--aa c--a')
1088
+ expect(elem.$.c.$.b.$.a.$$.getAttribute('class')).toBe('a--a b--a1 c--a2 c--a3 c--a4 c--a5')
1047
1089
  })
1048
1090
 
1049
1091
  it('should adding write ID and class prefix info to DOM when required', function () {
@@ -1098,6 +1140,28 @@ describe('Component', function () {
1098
1140
  styleScope: componentSpace.styleScopeManager.register(
1099
1141
  'component-external-classes-native',
1100
1142
  ),
1143
+ templateEngine:
1144
+ testBackend === domBackend
1145
+ ? undefined
1146
+ : getCustomExternalTemplateEngine((comp) => {
1147
+ var root = comp.getBackendElement()
1148
+ var slot
1149
+ if (testBackend === shadowBackend) {
1150
+ var shadowRoot = root.getShadowRoot()
1151
+ slot = shadowRoot.createElement('div', 'div')
1152
+ slot.setSlotName('')
1153
+ shadowRoot.appendChild(slot)
1154
+ } else {
1155
+ slot = root
1156
+ }
1157
+ return {
1158
+ root,
1159
+ slot,
1160
+ getIdMap: () => ({}),
1161
+ handleEvent() {},
1162
+ setListener() {},
1163
+ }
1164
+ }),
1101
1165
  },
1102
1166
  })
1103
1167
  regElem({
@@ -1139,11 +1203,11 @@ describe('Component', function () {
1139
1203
  expect(elem.$.c1.$.b1.$.a1.$.child.$$.getAttribute('class')).toBe(
1140
1204
  'component-external-classes-a--static',
1141
1205
  )
1142
- expect(elem.$.c1.$.b1.$.a1.$$.getAttribute('class')).toBe('')
1206
+ expect(elem.$.c1.$.b1.$.a1.$$.getAttribute('class')).toBe(null)
1143
1207
  expect(elem.$.c1.$.b1.$.a2.$$.getAttribute('class')).toBe(
1144
1208
  'component-external-classes-b--static',
1145
1209
  )
1146
- expect(elem.$.c1.$.b1.$$.getAttribute('class')).toBe('')
1210
+ expect(elem.$.c1.$.b1.$$.getAttribute('class')).toBe(null)
1147
1211
  expect(elem.$.c1.$$.getAttribute('class')).toBe(null)
1148
1212
  elem.$.c1.$.b1.$.a1.setExternalClass('A1', 'B1')
1149
1213
  expect(elem.$.c1.$.b1.$.a1.$.child.$$.getAttribute('class')).toBe(
@@ -1153,7 +1217,7 @@ describe('Component', function () {
1153
1217
  expect(elem.$.c1.$.b1.$.a1.$.child.$$.getAttribute('class')).toBe(
1154
1218
  'component-external-classes-a--static',
1155
1219
  )
1156
- expect(elem.$.c1.$.b1.$.a1.$$.getAttribute('class')).toBe('')
1220
+ expect(elem.$.c1.$.b1.$.a1.$$.getAttribute('class')).toBe(null)
1157
1221
  expect(elem.$.c1.$.b1.$.a2.$$.getAttribute('class')).toBe(
1158
1222
  'component-external-classes-b--static',
1159
1223
  )
@@ -1175,10 +1239,10 @@ describe('Component', function () {
1175
1239
  )
1176
1240
  expect(elem.$.c1.$.b1.$.a1.$$.getAttribute('class')).toBe('component-external-classes-d--AAA')
1177
1241
  expect(elem.$.c1.$.b1.$.a2.$.child.$$.getAttribute('class')).toBe(
1178
- 'component-external-classes-a--static component-external-classes-d--AAA component-external-classes-b--BBB',
1242
+ 'component-external-classes-a--static component-external-classes-b--BBB component-external-classes-d--AAA',
1179
1243
  )
1180
1244
  expect(elem.$.c1.$.b1.$.a2.$$.getAttribute('class')).toBe(
1181
- 'component-external-classes-d--AAA component-external-classes-b--static',
1245
+ 'component-external-classes-b--static component-external-classes-d--AAA',
1182
1246
  )
1183
1247
  expect(elem.$.c1.$.b1.$$.getAttribute('class')).toBe('component-external-classes-d--AAA')
1184
1248
 
@@ -1188,10 +1252,10 @@ describe('Component', function () {
1188
1252
  )
1189
1253
  expect(elem.$.c1.$.b1.$.a1.$$.getAttribute('class')).toBe('component-external-classes-d--BBB')
1190
1254
  expect(elem.$.c1.$.b1.$.a2.$.child.$$.getAttribute('class')).toBe(
1191
- 'component-external-classes-a--static component-external-classes-d--BBB component-external-classes-b--BBB',
1255
+ 'component-external-classes-a--static component-external-classes-b--BBB component-external-classes-d--BBB',
1192
1256
  )
1193
1257
  expect(elem.$.c1.$.b1.$.a2.$$.getAttribute('class')).toBe(
1194
- 'component-external-classes-d--BBB component-external-classes-b--static',
1258
+ 'component-external-classes-b--static component-external-classes-d--BBB',
1195
1259
  )
1196
1260
  expect(elem.$.c1.$.b1.$$.getAttribute('class')).toBe('component-external-classes-d--BBB')
1197
1261
 
@@ -1210,10 +1274,10 @@ describe('Component', function () {
1210
1274
  )
1211
1275
  expect(elem.$.c1.$.b1.$.a1.$$.getAttribute('class')).toBe('component-external-classes-d--BBB')
1212
1276
  expect(elem.$.c1.$.b1.$.a2.$.child.$$.getAttribute('class')).toBe(
1213
- 'component-external-classes-a--static component-external-classes-d--CCC component-external-classes-c--CCCC component-external-classes-b--BBB',
1277
+ 'component-external-classes-a--static component-external-classes-b--BBB component-external-classes-d--CCC component-external-classes-c--CCCC',
1214
1278
  )
1215
1279
  expect(elem.$.c1.$.b1.$.a2.$$.getAttribute('class')).toBe(
1216
- 'component-external-classes-d--CCC component-external-classes-c--CCCC component-external-classes-b--static',
1280
+ 'component-external-classes-b--static component-external-classes-d--CCC component-external-classes-c--CCCC',
1217
1281
  )
1218
1282
  expect(elem.$.c1.$.b1.$.a3.$$.getAttribute('class')).toBe(
1219
1283
  'component-external-classes-d--BBB component-external-classes-d--CCC component-external-classes-c--CCCC',
@@ -1235,10 +1299,10 @@ describe('Component', function () {
1235
1299
  )
1236
1300
  expect(elem.$.c1.$.b1.$.a1.$$.getAttribute('class')).toBe('')
1237
1301
  expect(elem.$.c1.$.b1.$.a2.$.child.$$.getAttribute('class')).toBe(
1238
- 'component-external-classes-a--static component-external-classes-d--CCC component-external-classes-b--BBB',
1302
+ 'component-external-classes-a--static component-external-classes-b--BBB component-external-classes-d--CCC',
1239
1303
  )
1240
1304
  expect(elem.$.c1.$.b1.$.a2.$$.getAttribute('class')).toBe(
1241
- 'component-external-classes-d--CCC component-external-classes-b--static',
1305
+ 'component-external-classes-b--static component-external-classes-d--CCC',
1242
1306
  )
1243
1307
  expect(elem.$.c1.$.b1.$.a3.$$.getAttribute('class')).toBe('component-external-classes-d--CCC')
1244
1308
  expect(elem.$.c1.$.b1.$$.getAttribute('class')).toBe('component-external-classes-d--BBB')
@@ -1448,4 +1512,14 @@ describe('Component', function () {
1448
1512
  ['pd', { customProp: 'customValue' }],
1449
1513
  ])
1450
1514
  })
1515
+ }
1516
+
1517
+ describe('Component (DOM backend)', function () {
1518
+ testCases(domBackend)
1519
+ })
1520
+ describe('Component (shadow backend)', function () {
1521
+ testCases(shadowBackend)
1522
+ })
1523
+ describe('Component (composed backend)', function () {
1524
+ testCases(composedBackend)
1451
1525
  })