inject.spec.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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. // Github issue #5194
  133. it('should work with functional', () => {
  134. new Vue({
  135. template: `<child/>`,
  136. provide: {
  137. foo: 1,
  138. bar: false
  139. },
  140. components: {
  141. child: {
  142. functional: true,
  143. inject: ['foo', 'bar'],
  144. render (h, context) {
  145. const { injections } = context
  146. injected = [injections.foo, injections.bar]
  147. }
  148. }
  149. }
  150. }).$mount()
  151. expect(injected).toEqual([1, false])
  152. })
  153. if (typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys)) {
  154. it('with Symbol keys', () => {
  155. const s = Symbol()
  156. const vm = new Vue({
  157. template: `<child/>`,
  158. provide: {
  159. [s]: 123
  160. },
  161. components: {
  162. child: {
  163. inject: { s },
  164. template: `<div>{{ s }}</div>`
  165. }
  166. }
  167. }).$mount()
  168. expect(vm.$el.textContent).toBe('123')
  169. })
  170. }
  171. // Github issue #5223
  172. it('should work with reactive array', done => {
  173. const vm = new Vue({
  174. template: `<div><child></child></div>`,
  175. data () {
  176. return {
  177. foo: []
  178. }
  179. },
  180. provide () {
  181. return {
  182. foo: this.foo
  183. }
  184. },
  185. components: {
  186. child: {
  187. inject: ['foo'],
  188. template: `<span>{{foo.length}}</span>`
  189. }
  190. }
  191. }).$mount()
  192. expect(vm.$el.innerHTML).toEqual(`<span>0</span>`)
  193. vm.foo.push(vm.foo.length)
  194. vm.$nextTick(() => {
  195. expect(vm.$el.innerHTML).toEqual(`<span>1</span>`)
  196. vm.foo.pop()
  197. vm.$nextTick(() => {
  198. expect(vm.$el.innerHTML).toEqual(`<span>0</span>`)
  199. done()
  200. })
  201. })
  202. })
  203. it('should warn when injections has been modified', () => {
  204. const key = 'foo'
  205. const vm = new Vue({
  206. provide: {
  207. foo: 1
  208. }
  209. })
  210. const child = new Vue({
  211. parent: vm,
  212. inject: ['foo']
  213. })
  214. expect(child.foo).toBe(1)
  215. child.foo = 2
  216. expect(
  217. `Avoid mutating an injected value directly since the changes will be ` +
  218. `overwritten whenever the provided component re-renders. ` +
  219. `injection being mutated: "${key}"`).toHaveBeenWarned()
  220. })
  221. it('should warn when injections cannot be found', () => {
  222. const vm = new Vue({})
  223. new Vue({
  224. parent: vm,
  225. inject: ['foo', 'bar'],
  226. created () {}
  227. })
  228. expect(`Injection "foo" not found`).toHaveBeenWarned()
  229. expect(`Injection "bar" not found`).toHaveBeenWarned()
  230. })
  231. it('should not warn when injections can be found', () => {
  232. const vm = new Vue({
  233. provide: {
  234. foo: 1,
  235. bar: false,
  236. baz: undefined
  237. }
  238. })
  239. new Vue({
  240. parent: vm,
  241. inject: ['foo', 'bar', 'baz'],
  242. created () {}
  243. })
  244. expect(`Injection "foo" not found`).not.toHaveBeenWarned()
  245. expect(`Injection "bar" not found`).not.toHaveBeenWarned()
  246. expect(`Injection "baz" not found`).not.toHaveBeenWarned()
  247. })
  248. })