inject.spec.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. import Vue from 'vue'
  2. import { isNative } from 'core/util/env'
  3. describe('Options provide/inject', () => {
  4. let injected
  5. const injectedComp = {
  6. inject: ['foo', 'bar'],
  7. render () {},
  8. created () {
  9. injected = [this.foo, this.bar]
  10. }
  11. }
  12. beforeEach(() => {
  13. injected = null
  14. })
  15. it('should work', () => {
  16. new Vue({
  17. template: `<child/>`,
  18. provide: {
  19. foo: 1,
  20. bar: false
  21. },
  22. components: {
  23. child: {
  24. template: `<injected-comp/>`,
  25. components: {
  26. injectedComp
  27. }
  28. }
  29. }
  30. }).$mount()
  31. expect(injected).toEqual([1, false])
  32. })
  33. it('should use closest parent', () => {
  34. new Vue({
  35. template: `<child/>`,
  36. provide: {
  37. foo: 1,
  38. bar: null
  39. },
  40. components: {
  41. child: {
  42. provide: {
  43. foo: 3
  44. },
  45. template: `<injected-comp/>`,
  46. components: {
  47. injectedComp
  48. }
  49. }
  50. }
  51. }).$mount()
  52. expect(injected).toEqual([3, null])
  53. })
  54. it('provide function', () => {
  55. new Vue({
  56. template: `<child/>`,
  57. data: {
  58. a: 1,
  59. b: false
  60. },
  61. provide () {
  62. return {
  63. foo: this.a,
  64. bar: this.b
  65. }
  66. },
  67. components: {
  68. child: {
  69. template: `<injected-comp/>`,
  70. components: {
  71. injectedComp
  72. }
  73. }
  74. }
  75. }).$mount()
  76. expect(injected).toEqual([1, false])
  77. })
  78. it('inject with alias', () => {
  79. const injectAlias = {
  80. inject: {
  81. baz: 'foo',
  82. qux: 'bar'
  83. },
  84. render () {},
  85. created () {
  86. injected = [this.baz, this.qux]
  87. }
  88. }
  89. new Vue({
  90. template: `<child/>`,
  91. provide: {
  92. foo: false,
  93. bar: 2
  94. },
  95. components: {
  96. child: {
  97. template: `<inject-alias/>`,
  98. components: {
  99. injectAlias
  100. }
  101. }
  102. }
  103. }).$mount()
  104. expect(injected).toEqual([false, 2])
  105. })
  106. it('inject before resolving data/props', () => {
  107. const vm = new Vue({
  108. provide: {
  109. foo: 1
  110. }
  111. })
  112. const child = new Vue({
  113. parent: vm,
  114. inject: ['foo'],
  115. data () {
  116. return {
  117. bar: this.foo + 1
  118. }
  119. },
  120. props: {
  121. baz: {
  122. default () {
  123. return this.foo + 2
  124. }
  125. }
  126. }
  127. })
  128. expect(child.foo).toBe(1)
  129. expect(child.bar).toBe(2)
  130. expect(child.baz).toBe(3)
  131. })
  132. if (typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys)) {
  133. it('with Symbol keys', () => {
  134. const s = Symbol()
  135. const vm = new Vue({
  136. template: `<child/>`,
  137. provide: {
  138. [s]: 123
  139. },
  140. components: {
  141. child: {
  142. inject: { s },
  143. template: `<div>{{ s }}</div>`
  144. }
  145. }
  146. }).$mount()
  147. expect(vm.$el.textContent).toBe('123')
  148. })
  149. }
  150. // Github issue #5223
  151. it('should work with reactive array', done => {
  152. const vm = new Vue({
  153. template: `<div><child></child></div>`,
  154. data () {
  155. return {
  156. foo: []
  157. }
  158. },
  159. provide () {
  160. return {
  161. foo: this.foo
  162. }
  163. },
  164. components: {
  165. child: {
  166. inject: ['foo'],
  167. template: `<span>{{foo.length}}</span>`
  168. }
  169. }
  170. }).$mount()
  171. expect(vm.$el.innerHTML).toEqual(`<span>0</span>`)
  172. vm.foo.push(vm.foo.length)
  173. vm.$nextTick(() => {
  174. expect(vm.$el.innerHTML).toEqual(`<span>1</span>`)
  175. vm.foo.pop()
  176. vm.$nextTick(() => {
  177. expect(vm.$el.innerHTML).toEqual(`<span>0</span>`)
  178. done()
  179. })
  180. })
  181. })
  182. it('should warn when injections has been modified', () => {
  183. const key = 'foo'
  184. const vm = new Vue({
  185. provide: {
  186. foo: 1
  187. }
  188. })
  189. const child = new Vue({
  190. parent: vm,
  191. inject: ['foo']
  192. })
  193. expect(child.foo).toBe(1)
  194. child.foo = 2
  195. expect(
  196. `Avoid mutating a injections directly since the value will be ` +
  197. `overwritten whenever the provided component re-renders. ` +
  198. `injections being mutated: "${key}"`).toHaveBeenWarned()
  199. })
  200. })