ssrTeleport.spec.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /**
  2. * @jest-environment node
  3. */
  4. import { createApp, h, Teleport } from 'vue'
  5. import { renderToString } from '../src/renderToString'
  6. import { renderToSimpleStream } from '../src/renderToStream'
  7. import { SSRContext } from '../src/render'
  8. import { ssrRenderTeleport } from '../src/helpers/ssrRenderTeleport'
  9. describe('ssrRenderTeleport', () => {
  10. test('teleport rendering (compiled)', async () => {
  11. const ctx: SSRContext = {}
  12. const html = await renderToString(
  13. createApp({
  14. data() {
  15. return { msg: 'hello' }
  16. },
  17. ssrRender(_ctx, _push, _parent) {
  18. ssrRenderTeleport(
  19. _push,
  20. _push => {
  21. _push(`<div>content</div>`)
  22. },
  23. '#target',
  24. false,
  25. _parent
  26. )
  27. }
  28. }),
  29. ctx
  30. )
  31. expect(html).toBe('<!--teleport start--><!--teleport end-->')
  32. expect(ctx.teleports!['#target']).toBe(`<div>content</div><!---->`)
  33. })
  34. test('teleport rendering (compiled + disabled)', async () => {
  35. const ctx: SSRContext = {}
  36. const html = await renderToString(
  37. createApp({
  38. data() {
  39. return { msg: 'hello' }
  40. },
  41. ssrRender(_ctx, _push, _parent) {
  42. ssrRenderTeleport(
  43. _push,
  44. _push => {
  45. _push(`<div>content</div>`)
  46. },
  47. '#target',
  48. true,
  49. _parent
  50. )
  51. }
  52. }),
  53. ctx
  54. )
  55. expect(html).toBe(
  56. '<!--teleport start--><div>content</div><!--teleport end-->'
  57. )
  58. expect(ctx.teleports!['#target']).toBe(`<!---->`)
  59. })
  60. test('teleport rendering (vnode)', async () => {
  61. const ctx: SSRContext = {}
  62. const html = await renderToString(
  63. h(
  64. Teleport,
  65. {
  66. to: `#target`
  67. },
  68. h('span', 'hello')
  69. ),
  70. ctx
  71. )
  72. expect(html).toBe('<!--teleport start--><!--teleport end-->')
  73. expect(ctx.teleports!['#target']).toBe('<span>hello</span><!---->')
  74. })
  75. test('teleport rendering (vnode + disabled)', async () => {
  76. const ctx: SSRContext = {}
  77. const html = await renderToString(
  78. h(
  79. Teleport,
  80. {
  81. to: `#target`,
  82. disabled: true
  83. },
  84. h('span', 'hello')
  85. ),
  86. ctx
  87. )
  88. expect(html).toBe(
  89. '<!--teleport start--><span>hello</span><!--teleport end-->'
  90. )
  91. expect(ctx.teleports!['#target']).toBe(`<!---->`)
  92. })
  93. test('multiple teleports with same target', async () => {
  94. const ctx: SSRContext = {}
  95. const html = await renderToString(
  96. h('div', [
  97. h(
  98. Teleport,
  99. {
  100. to: `#target`
  101. },
  102. h('span', 'hello')
  103. ),
  104. h(Teleport, { to: `#target` }, 'world')
  105. ]),
  106. ctx
  107. )
  108. expect(html).toBe(
  109. '<div><!--teleport start--><!--teleport end--><!--teleport start--><!--teleport end--></div>'
  110. )
  111. expect(ctx.teleports!['#target']).toBe(
  112. '<span>hello</span><!---->world<!---->'
  113. )
  114. })
  115. test('teleport inside async component', async () => {
  116. const ctx: SSRContext = {}
  117. const asyncComponent = {
  118. template: '<teleport to="#target"><div>content</div></teleport>',
  119. async setup() {}
  120. }
  121. const html = await renderToString(
  122. h({
  123. template: '<async-component />',
  124. components: { asyncComponent }
  125. }),
  126. ctx
  127. )
  128. expect(html).toBe('<!--teleport start--><!--teleport end-->')
  129. expect(ctx.teleports!['#target']).toBe(`<div>content</div><!---->`)
  130. })
  131. test('teleport inside async component (stream)', async () => {
  132. const ctx: SSRContext = {}
  133. const asyncComponent = {
  134. template: '<teleport to="#target"><div>content</div></teleport>',
  135. async setup() {}
  136. }
  137. let html = ''
  138. let resolve: any
  139. const p = new Promise(r => (resolve = r))
  140. renderToSimpleStream(
  141. h({
  142. template: '<async-component />',
  143. components: { asyncComponent }
  144. }),
  145. ctx,
  146. {
  147. push(chunk) {
  148. if (chunk === null) {
  149. resolve()
  150. } else {
  151. html += chunk
  152. }
  153. },
  154. destroy(err) {
  155. throw err
  156. }
  157. }
  158. )
  159. await p
  160. expect(html).toBe('<!--teleport start--><!--teleport end-->')
  161. expect(ctx.teleports!['#target']).toBe(`<div>content</div><!---->`)
  162. })
  163. })