apiTemplateRef.spec.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import {
  2. ref,
  3. nodeOps,
  4. h,
  5. render,
  6. nextTick,
  7. Ref,
  8. defineComponent
  9. } from '@vue/runtime-test'
  10. // reference: https://vue-composition-api-rfc.netlify.com/api.html#template-refs
  11. describe('api: template refs', () => {
  12. it('string ref mount', () => {
  13. const root = nodeOps.createElement('div')
  14. const el = ref(null)
  15. const Comp = {
  16. setup() {
  17. return {
  18. refKey: el
  19. }
  20. },
  21. render() {
  22. // Note: string refs are compiled into [ctx, key] tuples by the compiler
  23. // to ensure correct context.
  24. return h('div', { ref: [this, 'refKey'] as any })
  25. }
  26. }
  27. render(h(Comp), root)
  28. expect(el.value).toBe(root.children[0])
  29. })
  30. it('string ref update', async () => {
  31. const root = nodeOps.createElement('div')
  32. const fooEl = ref(null)
  33. const barEl = ref(null)
  34. const refKey = ref('foo')
  35. const Comp = {
  36. setup() {
  37. return {
  38. foo: fooEl,
  39. bar: barEl
  40. }
  41. },
  42. render() {
  43. return h('div', { ref: [this, refKey.value] as any })
  44. }
  45. }
  46. render(h(Comp), root)
  47. expect(fooEl.value).toBe(root.children[0])
  48. expect(barEl.value).toBe(null)
  49. refKey.value = 'bar'
  50. await nextTick()
  51. expect(fooEl.value).toBe(null)
  52. expect(barEl.value).toBe(root.children[0])
  53. })
  54. it('string ref unmount', async () => {
  55. const root = nodeOps.createElement('div')
  56. const el = ref(null)
  57. const toggle = ref(true)
  58. const Comp = {
  59. setup() {
  60. return {
  61. refKey: el
  62. }
  63. },
  64. render() {
  65. return toggle.value ? h('div', { ref: [this, 'refKey'] as any }) : null
  66. }
  67. }
  68. render(h(Comp), root)
  69. expect(el.value).toBe(root.children[0])
  70. toggle.value = false
  71. await nextTick()
  72. expect(el.value).toBe(null)
  73. })
  74. it('function ref mount', () => {
  75. const root = nodeOps.createElement('div')
  76. const fn = jest.fn()
  77. const Comp = defineComponent(() => () => h('div', { ref: fn }))
  78. render(h(Comp), root)
  79. expect(fn.mock.calls[0][0]).toBe(root.children[0])
  80. })
  81. it('function ref update', async () => {
  82. const root = nodeOps.createElement('div')
  83. const fn1 = jest.fn()
  84. const fn2 = jest.fn()
  85. const fn = ref(fn1)
  86. const Comp = defineComponent(() => () => h('div', { ref: fn.value }))
  87. render(h(Comp), root)
  88. expect(fn1.mock.calls).toHaveLength(1)
  89. expect(fn1.mock.calls[0][0]).toBe(root.children[0])
  90. expect(fn2.mock.calls).toHaveLength(0)
  91. fn.value = fn2
  92. await nextTick()
  93. expect(fn1.mock.calls).toHaveLength(1)
  94. expect(fn2.mock.calls).toHaveLength(1)
  95. expect(fn2.mock.calls[0][0]).toBe(root.children[0])
  96. })
  97. it('function ref unmount', async () => {
  98. const root = nodeOps.createElement('div')
  99. const fn = jest.fn()
  100. const toggle = ref(true)
  101. const Comp = defineComponent(() => () =>
  102. toggle.value ? h('div', { ref: fn }) : null
  103. )
  104. render(h(Comp), root)
  105. expect(fn.mock.calls[0][0]).toBe(root.children[0])
  106. toggle.value = false
  107. await nextTick()
  108. expect(fn.mock.calls[1][0]).toBe(null)
  109. })
  110. it('render function ref mount', () => {
  111. const root = nodeOps.createElement('div')
  112. const el = ref(null)
  113. const Comp = {
  114. setup() {
  115. return () => h('div', { ref: el })
  116. }
  117. }
  118. render(h(Comp), root)
  119. expect(el.value).toBe(root.children[0])
  120. })
  121. it('render function ref update', async () => {
  122. const root = nodeOps.createElement('div')
  123. const refs = {
  124. foo: ref(null),
  125. bar: ref(null)
  126. }
  127. const refKey = ref('foo') as Ref<keyof typeof refs>
  128. const Comp = {
  129. setup() {
  130. return () => h('div', { ref: refs[refKey.value] })
  131. }
  132. }
  133. render(h(Comp), root)
  134. expect(refs.foo.value).toBe(root.children[0])
  135. expect(refs.bar.value).toBe(null)
  136. refKey.value = 'bar'
  137. await nextTick()
  138. expect(refs.foo.value).toBe(null)
  139. expect(refs.bar.value).toBe(root.children[0])
  140. })
  141. it('render function ref unmount', async () => {
  142. const root = nodeOps.createElement('div')
  143. const el = ref(null)
  144. const toggle = ref(true)
  145. const Comp = {
  146. setup() {
  147. return () => (toggle.value ? h('div', { ref: el }) : null)
  148. }
  149. }
  150. render(h(Comp), root)
  151. expect(el.value).toBe(root.children[0])
  152. toggle.value = false
  153. await nextTick()
  154. expect(el.value).toBe(null)
  155. })
  156. })