2
0

ssr-stream.spec.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // @vitest-environment node
  2. import Vue from 'vue'
  3. import { createRenderer } from 'web/entry-server-renderer'
  4. const { renderToStream } = createRenderer()
  5. describe('SSR: renderToStream', () => {
  6. it('should render to a stream', done => {
  7. const stream = renderToStream(new Vue({
  8. template: `
  9. <div>
  10. <p class="hi">yoyo</p>
  11. <div id="ho" :class="[testClass, { red: isRed }]"></div>
  12. <span>{{ test }}</span>
  13. <input :value="test">
  14. <b-comp></b-comp>
  15. <c-comp></c-comp>
  16. </div>
  17. `,
  18. data: {
  19. test: 'hi',
  20. isRed: true,
  21. testClass: 'a'
  22. },
  23. components: {
  24. bComp (resolve) {
  25. return resolve({
  26. render (h) {
  27. return h('test-async-2')
  28. },
  29. components: {
  30. testAsync2 (resolve) {
  31. return resolve({
  32. created () { this.$parent.$parent.testClass = 'b' },
  33. render (h) {
  34. return h('div', { class: [this.$parent.$parent.testClass] }, 'test')
  35. }
  36. })
  37. }
  38. }
  39. })
  40. },
  41. cComp: {
  42. render (h) {
  43. return h('div', { class: [this.$parent.testClass] }, 'test')
  44. }
  45. }
  46. }
  47. }))
  48. let res = ''
  49. stream.on('data', chunk => {
  50. res += chunk
  51. })
  52. stream.on('end', () => {
  53. expect(res).toContain(
  54. '<div data-server-rendered="true">' +
  55. '<p class="hi">yoyo</p> ' +
  56. '<div id="ho" class="a red"></div> ' +
  57. '<span>hi</span> ' +
  58. '<input value="hi"> ' +
  59. '<div class="b">test</div> ' +
  60. '<div class="b">test</div>' +
  61. '</div>'
  62. )
  63. done()
  64. })
  65. })
  66. it('should catch error', done => {
  67. const stream = renderToStream(new Vue({
  68. render () {
  69. throw new Error('oops')
  70. }
  71. }))
  72. stream.on('error', err => {
  73. expect(err.toString()).toMatch(/oops/)
  74. expect(`oops`).toHaveBeenWarned()
  75. done()
  76. })
  77. stream.on('data', _ => _)
  78. })
  79. it('should not mingle two components', done => {
  80. const padding = (new Array(20000)).join('x')
  81. const component1 = new Vue({
  82. template: `<div>${padding}<div></div></div>`,
  83. _scopeId: '_component1'
  84. })
  85. const component2 = new Vue({
  86. template: `<div></div>`,
  87. _scopeId: '_component2'
  88. })
  89. const stream1 = renderToStream(component1)
  90. const stream2 = renderToStream(component2)
  91. let res = ''
  92. stream1.on('data', (text) => {
  93. res += text.toString('utf-8').replace(/x/g, '')
  94. })
  95. stream1.on('end', () => {
  96. expect(res).not.toContain('_component2')
  97. done()
  98. })
  99. stream1.read(1)
  100. stream2.read(1)
  101. })
  102. it('should call context.rendered', done => {
  103. let a = 0
  104. const stream = renderToStream(new Vue({
  105. template: `
  106. <div>Hello</div>
  107. `
  108. }), {
  109. rendered: () => {
  110. a = 42
  111. }
  112. })
  113. let res = ''
  114. stream.on('data', chunk => {
  115. res += chunk
  116. })
  117. stream.on('end', () => {
  118. expect(res).toContain('<div data-server-rendered="true">Hello</div>')
  119. expect(a).toBe(42)
  120. done()
  121. })
  122. })
  123. })