ssrWatch.spec.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import {
  2. createSSRApp,
  3. defineComponent,
  4. h,
  5. nextTick,
  6. ref,
  7. watch,
  8. watchEffect,
  9. } from 'vue'
  10. import { type SSRContext, renderToString } from '../src'
  11. describe('ssr: watch', () => {
  12. // #6013
  13. test('should work w/ flush:sync', async () => {
  14. const App = defineComponent(() => {
  15. const count = ref(0)
  16. let msg = ''
  17. watch(
  18. count,
  19. () => {
  20. msg = 'hello world'
  21. },
  22. { flush: 'sync' },
  23. )
  24. count.value = 1
  25. expect(msg).toBe('hello world')
  26. return () => h('div', null, msg)
  27. })
  28. const app = createSSRApp(App)
  29. const ctx: SSRContext = {}
  30. const html = await renderToString(app, ctx)
  31. expect(ctx.__watcherHandles!.length).toBe(1)
  32. expect(html).toMatch('hello world')
  33. })
  34. test('should work with flush: sync and immediate: true', async () => {
  35. const text = ref('start')
  36. let msg = 'unchanged'
  37. const App = defineComponent(() => {
  38. watch(
  39. text,
  40. () => {
  41. msg = text.value
  42. },
  43. { flush: 'sync', immediate: true },
  44. )
  45. expect(msg).toBe('start')
  46. text.value = 'changed'
  47. expect(msg).toBe('changed')
  48. text.value = 'changed again'
  49. expect(msg).toBe('changed again')
  50. return () => h('div', null, msg)
  51. })
  52. const app = createSSRApp(App)
  53. const ctx: SSRContext = {}
  54. const html = await renderToString(app, ctx)
  55. expect(ctx.__watcherHandles!.length).toBe(1)
  56. expect(html).toMatch('changed again')
  57. await nextTick()
  58. expect(msg).toBe('changed again')
  59. })
  60. test('should run once with immediate: true', async () => {
  61. const text = ref('start')
  62. let msg = 'unchanged'
  63. const App = defineComponent(() => {
  64. watch(
  65. text,
  66. () => {
  67. msg = String(text.value)
  68. },
  69. { immediate: true },
  70. )
  71. text.value = 'changed'
  72. expect(msg).toBe('start')
  73. return () => h('div', null, msg)
  74. })
  75. const app = createSSRApp(App)
  76. const ctx: SSRContext = {}
  77. const html = await renderToString(app, ctx)
  78. expect(ctx.__watcherHandles).toBeUndefined()
  79. expect(html).toMatch('start')
  80. await nextTick()
  81. expect(msg).toBe('start')
  82. })
  83. test('should run once with immediate: true and flush: post', async () => {
  84. const text = ref('start')
  85. let msg = 'unchanged'
  86. const App = defineComponent(() => {
  87. watch(
  88. text,
  89. () => {
  90. msg = String(text.value)
  91. },
  92. { immediate: true, flush: 'post' },
  93. )
  94. text.value = 'changed'
  95. expect(msg).toBe('start')
  96. return () => h('div', null, msg)
  97. })
  98. const app = createSSRApp(App)
  99. const ctx: SSRContext = {}
  100. const html = await renderToString(app, ctx)
  101. expect(ctx.__watcherHandles).toBeUndefined()
  102. expect(html).toMatch('start')
  103. await nextTick()
  104. expect(msg).toBe('start')
  105. })
  106. })
  107. describe('ssr: watchEffect', () => {
  108. test('should run with flush: sync', async () => {
  109. const text = ref('start')
  110. let msg = 'unchanged'
  111. const App = defineComponent(() => {
  112. watchEffect(
  113. () => {
  114. msg = text.value
  115. },
  116. { flush: 'sync' },
  117. )
  118. expect(msg).toBe('start')
  119. text.value = 'changed'
  120. expect(msg).toBe('changed')
  121. text.value = 'changed again'
  122. expect(msg).toBe('changed again')
  123. return () => h('div', null, msg)
  124. })
  125. const app = createSSRApp(App)
  126. const ctx: SSRContext = {}
  127. const html = await renderToString(app, ctx)
  128. expect(ctx.__watcherHandles!.length).toBe(1)
  129. expect(html).toMatch('changed again')
  130. await nextTick()
  131. expect(msg).toBe('changed again')
  132. })
  133. test('should run once with default flush (pre)', async () => {
  134. const text = ref('start')
  135. let msg = 'unchanged'
  136. const App = defineComponent(() => {
  137. watchEffect(() => {
  138. msg = text.value
  139. })
  140. text.value = 'changed'
  141. expect(msg).toBe('start')
  142. return () => h('div', null, msg)
  143. })
  144. const app = createSSRApp(App)
  145. const ctx: SSRContext = {}
  146. const html = await renderToString(app, ctx)
  147. expect(ctx.__watcherHandles).toBeUndefined()
  148. expect(html).toMatch('start')
  149. await nextTick()
  150. expect(msg).toBe('start')
  151. })
  152. test('should not run for flush: post', async () => {
  153. const text = ref('start')
  154. let msg = 'unchanged'
  155. const App = defineComponent(() => {
  156. watchEffect(
  157. () => {
  158. msg = text.value
  159. },
  160. { flush: 'post' },
  161. )
  162. text.value = 'changed'
  163. expect(msg).toBe('unchanged')
  164. return () => h('div', null, msg)
  165. })
  166. const app = createSSRApp(App)
  167. const ctx: SSRContext = {}
  168. const html = await renderToString(app, ctx)
  169. expect(ctx.__watcherHandles).toBeUndefined()
  170. expect(html).toMatch('unchanged')
  171. await nextTick()
  172. expect(msg).toBe('unchanged')
  173. })
  174. })