ssrTeleport.spec.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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(
  33. `<div>content</div><!--teleport anchor-->`
  34. )
  35. })
  36. test('teleport rendering (compiled + disabled)', async () => {
  37. const ctx: SSRContext = {}
  38. const html = await renderToString(
  39. createApp({
  40. data() {
  41. return { msg: 'hello' }
  42. },
  43. ssrRender(_ctx, _push, _parent) {
  44. ssrRenderTeleport(
  45. _push,
  46. _push => {
  47. _push(`<div>content</div>`)
  48. },
  49. '#target',
  50. true,
  51. _parent
  52. )
  53. }
  54. }),
  55. ctx
  56. )
  57. expect(html).toBe(
  58. '<!--teleport start--><div>content</div><!--teleport end-->'
  59. )
  60. expect(ctx.teleports!['#target']).toBe(`<!--teleport anchor-->`)
  61. })
  62. test('teleport rendering (vnode)', async () => {
  63. const ctx: SSRContext = {}
  64. const html = await renderToString(
  65. h(
  66. Teleport,
  67. {
  68. to: `#target`
  69. },
  70. h('span', 'hello')
  71. ),
  72. ctx
  73. )
  74. expect(html).toBe('<!--teleport start--><!--teleport end-->')
  75. expect(ctx.teleports!['#target']).toBe(
  76. '<span>hello</span><!--teleport anchor-->'
  77. )
  78. })
  79. test('teleport rendering (vnode + disabled)', async () => {
  80. const ctx: SSRContext = {}
  81. const html = await renderToString(
  82. h(
  83. Teleport,
  84. {
  85. to: `#target`,
  86. disabled: true
  87. },
  88. h('span', 'hello')
  89. ),
  90. ctx
  91. )
  92. expect(html).toBe(
  93. '<!--teleport start--><span>hello</span><!--teleport end-->'
  94. )
  95. expect(ctx.teleports!['#target']).toBe(`<!--teleport anchor-->`)
  96. })
  97. test('multiple teleports with same target', async () => {
  98. const ctx: SSRContext = {}
  99. const html = await renderToString(
  100. h('div', [
  101. h(
  102. Teleport,
  103. {
  104. to: `#target`
  105. },
  106. h('span', 'hello')
  107. ),
  108. h(Teleport, { to: `#target` }, 'world')
  109. ]),
  110. ctx
  111. )
  112. expect(html).toBe(
  113. '<div><!--teleport start--><!--teleport end--><!--teleport start--><!--teleport end--></div>'
  114. )
  115. expect(ctx.teleports!['#target']).toBe(
  116. '<span>hello</span><!--teleport anchor-->world<!--teleport anchor-->'
  117. )
  118. })
  119. test('teleport inside async component', async () => {
  120. const ctx: SSRContext = {}
  121. const asyncComponent = {
  122. template: '<teleport to="#target"><div>content</div></teleport>',
  123. async setup() {}
  124. }
  125. const html = await renderToString(
  126. h({
  127. template: '<async-component />',
  128. components: { asyncComponent }
  129. }),
  130. ctx
  131. )
  132. expect(html).toBe('<!--teleport start--><!--teleport end-->')
  133. expect(ctx.teleports!['#target']).toBe(
  134. `<div>content</div><!--teleport anchor-->`
  135. )
  136. })
  137. test('teleport inside async component (stream)', async () => {
  138. const ctx: SSRContext = {}
  139. const asyncComponent = {
  140. template: '<teleport to="#target"><div>content</div></teleport>',
  141. async setup() {}
  142. }
  143. let html = ''
  144. let resolve: any
  145. const p = new Promise(r => (resolve = r))
  146. renderToSimpleStream(
  147. h({
  148. template: '<async-component />',
  149. components: { asyncComponent }
  150. }),
  151. ctx,
  152. {
  153. push(chunk) {
  154. if (chunk === null) {
  155. resolve()
  156. } else {
  157. html += chunk
  158. }
  159. },
  160. destroy(err) {
  161. throw err
  162. }
  163. }
  164. )
  165. await p
  166. expect(html).toBe('<!--teleport start--><!--teleport end-->')
  167. expect(ctx.teleports!['#target']).toBe(
  168. `<div>content</div><!--teleport anchor-->`
  169. )
  170. })
  171. })