componentAttrs.spec.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import {
  2. createComponent,
  3. getCurrentInstance,
  4. nextTick,
  5. ref,
  6. setText,
  7. template,
  8. watchEffect,
  9. } from '../src'
  10. import { setCurrentInstance } from '../src/component'
  11. import { makeRender } from './_utils'
  12. const define = makeRender<any>()
  13. describe('attribute fallthrough', () => {
  14. it('should allow attrs to fallthrough', async () => {
  15. const t0 = template('<div>')
  16. const { component: Child } = define({
  17. props: ['foo'],
  18. render() {
  19. const instance = getCurrentInstance()!
  20. const n0 = t0()
  21. watchEffect(() => setText(n0, instance.props.foo))
  22. return n0
  23. },
  24. })
  25. const foo = ref(1)
  26. const id = ref('a')
  27. const { instance, host } = define({
  28. setup() {
  29. return { foo, id }
  30. },
  31. render(_ctx: Record<string, any>) {
  32. return createComponent(
  33. Child,
  34. [
  35. {
  36. foo: () => _ctx.foo,
  37. id: () => _ctx.id,
  38. },
  39. ],
  40. null,
  41. null,
  42. true,
  43. )
  44. },
  45. }).render()
  46. const reset = setCurrentInstance(instance)
  47. expect(host.innerHTML).toBe('<div id="a">1</div>')
  48. foo.value++
  49. await nextTick()
  50. expect(host.innerHTML).toBe('<div id="a">2</div>')
  51. id.value = 'b'
  52. await nextTick()
  53. expect(host.innerHTML).toBe('<div id="b">2</div>')
  54. reset()
  55. })
  56. it('should not fallthrough if explicitly pass inheritAttrs: false', async () => {
  57. const t0 = template('<div>')
  58. const { component: Child } = define({
  59. props: ['foo'],
  60. inheritAttrs: false,
  61. render() {
  62. const instance = getCurrentInstance()!
  63. const n0 = t0()
  64. watchEffect(() => setText(n0, instance.props.foo))
  65. return n0
  66. },
  67. })
  68. const foo = ref(1)
  69. const id = ref('a')
  70. const { instance, host } = define({
  71. setup() {
  72. return { foo, id }
  73. },
  74. render(_ctx: Record<string, any>) {
  75. return createComponent(
  76. Child,
  77. [
  78. {
  79. foo: () => _ctx.foo,
  80. id: () => _ctx.id,
  81. },
  82. ],
  83. null,
  84. null,
  85. true,
  86. )
  87. },
  88. }).render()
  89. const reset = setCurrentInstance(instance)
  90. expect(host.innerHTML).toBe('<div>1</div>')
  91. foo.value++
  92. await nextTick()
  93. expect(host.innerHTML).toBe('<div>2</div>')
  94. id.value = 'b'
  95. await nextTick()
  96. expect(host.innerHTML).toBe('<div>2</div>')
  97. reset()
  98. })
  99. it('should pass through attrs in nested single root components', async () => {
  100. const t0 = template('<div>')
  101. const { component: Grandson } = define({
  102. props: ['custom-attr'],
  103. render() {
  104. const instance = getCurrentInstance()!
  105. const n0 = t0()
  106. watchEffect(() => setText(n0, instance.attrs.foo))
  107. return n0
  108. },
  109. })
  110. const { component: Child } = define({
  111. render() {
  112. const n0 = createComponent(
  113. Grandson,
  114. [
  115. {
  116. 'custom-attr': () => 'custom-attr',
  117. },
  118. ],
  119. null,
  120. null,
  121. true,
  122. )
  123. return n0
  124. },
  125. })
  126. const foo = ref(1)
  127. const id = ref('a')
  128. const { instance, host } = define({
  129. setup() {
  130. return { foo, id }
  131. },
  132. render(_ctx: Record<string, any>) {
  133. return createComponent(
  134. Child,
  135. [
  136. {
  137. foo: () => _ctx.foo,
  138. id: () => _ctx.id,
  139. },
  140. ],
  141. null,
  142. null,
  143. true,
  144. )
  145. },
  146. }).render()
  147. const reset = setCurrentInstance(instance)
  148. expect(host.innerHTML).toBe('<div foo="1" id="a">1</div>')
  149. foo.value++
  150. await nextTick()
  151. expect(host.innerHTML).toBe('<div foo="2" id="a">2</div>')
  152. id.value = 'b'
  153. await nextTick()
  154. expect(host.innerHTML).toBe('<div foo="2" id="b">2</div>')
  155. reset()
  156. })
  157. })