ssrTeleport.spec.ts 4.4 KB

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