ssr-stream.spec.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import Vue from '../../dist/vue.runtime.common.js'
  2. import { createRenderer } from '../../packages/vue-server-renderer'
  3. const { renderToStream } = createRenderer()
  4. describe('SSR: renderToStream', () => {
  5. it('should render to a stream', done => {
  6. const stream = renderToStream(new Vue({
  7. template: `
  8. <div>
  9. <p class="hi">yoyo</p>
  10. <div id="ho" :class="[testClass, { red: isRed }]"></div>
  11. <span>{{ test }}</span>
  12. <input :value="test">
  13. <b-comp></b-comp>
  14. <c-comp></c-comp>
  15. </div>
  16. `,
  17. data: {
  18. test: 'hi',
  19. isRed: true,
  20. testClass: 'a'
  21. },
  22. components: {
  23. bComp (resolve) {
  24. return resolve({
  25. render (h) {
  26. return h('test-async-2')
  27. },
  28. components: {
  29. testAsync2 (resolve) {
  30. return resolve({
  31. created () { this.$parent.$parent.testClass = 'b' },
  32. render (h) {
  33. return h('div', { class: [this.$parent.$parent.testClass] }, 'test')
  34. }
  35. })
  36. }
  37. }
  38. })
  39. },
  40. cComp: {
  41. render (h) {
  42. return h('div', { class: [this.$parent.testClass] }, 'test')
  43. }
  44. }
  45. }
  46. }))
  47. let res = ''
  48. stream.on('data', chunk => {
  49. res += chunk
  50. })
  51. stream.on('end', () => {
  52. expect(res).toContain(
  53. '<div data-server-rendered="true">' +
  54. '<p class="hi">yoyo</p> ' +
  55. '<div id="ho" class="a red"></div> ' +
  56. '<span>hi</span> ' +
  57. '<input value="hi"> ' +
  58. '<div class="b">test</div> ' +
  59. '<div class="b">test</div>' +
  60. '</div>'
  61. )
  62. done()
  63. })
  64. })
  65. it('should catch error', done => {
  66. Vue.config.silent = true
  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. Vue.config.silent = false
  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. })