apiCreateDynamicComponent.spec.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { ref, shallowRef } from '@vue/reactivity'
  2. import { nextTick, resolveDynamicComponent } from '@vue/runtime-dom'
  3. import {
  4. createComponentWithFallback,
  5. createDynamicComponent,
  6. defineVaporComponent,
  7. renderEffect,
  8. setHtml,
  9. setInsertionState,
  10. template,
  11. } from '../src'
  12. import { makeRender } from './_utils'
  13. const define = makeRender()
  14. describe('api: createDynamicComponent', () => {
  15. const A = () => document.createTextNode('AAA')
  16. const B = () => document.createTextNode('BBB')
  17. test('direct value', async () => {
  18. const val = shallowRef<any>(A)
  19. const { html } = define({
  20. setup() {
  21. return createDynamicComponent(() => val.value)
  22. },
  23. }).render()
  24. expect(html()).toBe('AAA<!--dynamic-component-->')
  25. val.value = B
  26. await nextTick()
  27. expect(html()).toBe('BBB<!--dynamic-component-->')
  28. // fallback
  29. val.value = 'foo'
  30. await nextTick()
  31. expect(html()).toBe('<foo></foo><!--dynamic-component-->')
  32. })
  33. test('global registration', async () => {
  34. const val = shallowRef('foo')
  35. const { app, html, mount } = define({
  36. setup() {
  37. return createDynamicComponent(() => val.value)
  38. },
  39. }).create()
  40. app.component('foo', A)
  41. app.component('bar', B)
  42. mount()
  43. expect(html()).toBe('AAA<!--dynamic-component-->')
  44. val.value = 'bar'
  45. await nextTick()
  46. expect(html()).toBe('BBB<!--dynamic-component-->')
  47. // fallback
  48. val.value = 'baz'
  49. await nextTick()
  50. expect(html()).toBe('<baz></baz><!--dynamic-component-->')
  51. })
  52. test('render fallback with insertionState', async () => {
  53. const { html, mount } = define({
  54. setup() {
  55. const html = ref('hi')
  56. const n1 = template('<div></div>', true)() as any
  57. setInsertionState(n1)
  58. const n0 = createComponentWithFallback(
  59. resolveDynamicComponent('button') as any,
  60. ) as any
  61. renderEffect(() => setHtml(n0, html.value))
  62. return n1
  63. },
  64. }).create()
  65. mount()
  66. expect(html()).toBe('<div><button>hi</button></div>')
  67. })
  68. test('switch dynamic component children', async () => {
  69. const CompA = defineVaporComponent({
  70. setup() {
  71. return template('<div>A</div>')()
  72. },
  73. })
  74. const CompB = defineVaporComponent({
  75. setup() {
  76. return template('<div>B</div>')()
  77. },
  78. })
  79. const current = shallowRef(CompA)
  80. const { html } = define({
  81. setup() {
  82. const t1 = template('<div></div>')
  83. const n2 = t1() as any
  84. setInsertionState(n2)
  85. createDynamicComponent(() => current.value)
  86. return n2
  87. },
  88. }).render()
  89. expect(html()).toBe('<div><div>A</div><!--dynamic-component--></div>')
  90. current.value = CompB
  91. await nextTick()
  92. expect(html()).toBe('<div><div>B</div><!--dynamic-component--></div>')
  93. })
  94. test('render fallback with insertionState', async () => {
  95. const { html, mount } = define({
  96. setup() {
  97. const html = ref('hi')
  98. const n1 = template('<div></div>', true)() as any
  99. setInsertionState(n1)
  100. const n0 = createComponentWithFallback(
  101. resolveDynamicComponent('button') as any,
  102. ) as any
  103. renderEffect(() => setHtml(n0, html.value))
  104. return n1
  105. },
  106. }).create()
  107. mount()
  108. expect(html()).toBe('<div><button>hi</button></div>')
  109. })
  110. })