componentProxy.spec.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import { h, render, getCurrentInstance, nodeOps } from '@vue/runtime-test'
  2. import { mockWarn } from '@vue/shared'
  3. import { ComponentInternalInstance } from '../src/component'
  4. describe('component: proxy', () => {
  5. mockWarn()
  6. test('data', () => {
  7. let instance: ComponentInternalInstance
  8. let instanceProxy: any
  9. const Comp = {
  10. data() {
  11. return {
  12. foo: 1
  13. }
  14. },
  15. mounted() {
  16. instance = getCurrentInstance()!
  17. instanceProxy = this
  18. },
  19. render() {
  20. return null
  21. }
  22. }
  23. render(h(Comp), nodeOps.createElement('div'))
  24. expect(instanceProxy.foo).toBe(1)
  25. instanceProxy.foo = 2
  26. expect(instance!.data.foo).toBe(2)
  27. })
  28. test('renderContext', () => {
  29. let instance: ComponentInternalInstance
  30. let instanceProxy: any
  31. const Comp = {
  32. setup() {
  33. return {
  34. foo: 1
  35. }
  36. },
  37. mounted() {
  38. instance = getCurrentInstance()!
  39. instanceProxy = this
  40. },
  41. render() {
  42. return null
  43. }
  44. }
  45. render(h(Comp), nodeOps.createElement('div'))
  46. expect(instanceProxy.foo).toBe(1)
  47. instanceProxy.foo = 2
  48. expect(instance!.renderContext.foo).toBe(2)
  49. })
  50. test('propsProxy', () => {
  51. let instance: ComponentInternalInstance
  52. let instanceProxy: any
  53. const Comp = {
  54. props: {
  55. foo: {
  56. type: Number,
  57. default: 1
  58. }
  59. },
  60. setup() {
  61. return () => null
  62. },
  63. mounted() {
  64. instance = getCurrentInstance()!
  65. instanceProxy = this
  66. }
  67. }
  68. render(h(Comp), nodeOps.createElement('div'))
  69. expect(instanceProxy.foo).toBe(1)
  70. expect(instance!.propsProxy!.foo).toBe(1)
  71. expect(() => (instanceProxy.foo = 2)).toThrow(TypeError)
  72. expect(`Attempting to mutate prop "foo"`).toHaveBeenWarned()
  73. })
  74. test('should not expose non-declared props', () => {
  75. let instanceProxy: any
  76. const Comp = {
  77. setup() {
  78. return () => null
  79. },
  80. mounted() {
  81. instanceProxy = this
  82. }
  83. }
  84. render(h(Comp, { count: 1 }), nodeOps.createElement('div'))
  85. expect('count' in instanceProxy).toBe(false)
  86. })
  87. test('public properties', () => {
  88. let instance: ComponentInternalInstance
  89. let instanceProxy: any
  90. const Comp = {
  91. setup() {
  92. return () => null
  93. },
  94. mounted() {
  95. instance = getCurrentInstance()!
  96. instanceProxy = this
  97. }
  98. }
  99. render(h(Comp), nodeOps.createElement('div'))
  100. expect(instanceProxy.$data).toBe(instance!.data)
  101. expect(instanceProxy.$props).toBe(instance!.propsProxy)
  102. expect(instanceProxy.$attrs).toBe(instance!.attrs)
  103. expect(instanceProxy.$slots).toBe(instance!.slots)
  104. expect(instanceProxy.$refs).toBe(instance!.refs)
  105. expect(instanceProxy.$parent).toBe(instance!.parent)
  106. expect(instanceProxy.$root).toBe(instance!.root)
  107. expect(instanceProxy.$emit).toBe(instance!.emit)
  108. expect(instanceProxy.$el).toBe(instance!.vnode.el)
  109. expect(instanceProxy.$options).toBe(instance!.type)
  110. expect(() => (instanceProxy.$data = {})).toThrow(TypeError)
  111. expect(`Attempting to mutate public property "$data"`).toHaveBeenWarned()
  112. })
  113. test('sink', async () => {
  114. let instance: ComponentInternalInstance
  115. let instanceProxy: any
  116. const Comp = {
  117. setup() {
  118. return () => null
  119. },
  120. mounted() {
  121. instance = getCurrentInstance()!
  122. instanceProxy = this
  123. }
  124. }
  125. render(h(Comp), nodeOps.createElement('div'))
  126. instanceProxy.foo = 1
  127. expect(instanceProxy.foo).toBe(1)
  128. expect(instance!.sink.foo).toBe(1)
  129. })
  130. test('has check', () => {
  131. let instanceProxy: any
  132. const Comp = {
  133. render() {},
  134. props: {
  135. msg: String
  136. },
  137. data() {
  138. return {
  139. foo: 0
  140. }
  141. },
  142. setup() {
  143. return {
  144. bar: 1
  145. }
  146. },
  147. mounted() {
  148. instanceProxy = this
  149. }
  150. }
  151. render(h(Comp, { msg: 'hello' }), nodeOps.createElement('div'))
  152. // props
  153. expect('msg' in instanceProxy).toBe(true)
  154. // data
  155. expect('foo' in instanceProxy).toBe(true)
  156. // renderContext
  157. expect('bar' in instanceProxy).toBe(true)
  158. // public properties
  159. expect('$el' in instanceProxy).toBe(true)
  160. // non-existent
  161. expect('$foobar' in instanceProxy).toBe(false)
  162. expect('baz' in instanceProxy).toBe(false)
  163. // set non-existent (goes into sink)
  164. instanceProxy.baz = 1
  165. expect('baz' in instanceProxy).toBe(true)
  166. })
  167. })