data_spec.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /**
  2. * Test property proxy, scope inheritance,
  3. * data event propagation and data sync
  4. */
  5. var Vue = require('../../src/vue')
  6. var Observer = require('../../src/observe/observer')
  7. var u = undefined
  8. Observer.pathDelimiter = '.'
  9. describe('Scope', function () {
  10. describe('basic', function () {
  11. var vm = new Vue({
  12. data: {
  13. a: 1,
  14. b: {
  15. c: 2
  16. }
  17. }
  18. })
  19. it('should copy over data properties', function () {
  20. expect(vm.$scope.a).toBe(vm.$data.a)
  21. expect(vm.$scope.b).toBe(vm.$data.b)
  22. })
  23. it('should proxy these properties', function () {
  24. expect(vm.a).toBe(vm.$scope.a)
  25. expect(vm.b).toBe(vm.$scope.b)
  26. })
  27. it('should trigger set events', function () {
  28. var spy = jasmine.createSpy('basic')
  29. vm._observer.on('set', spy)
  30. // set on scope
  31. vm.$scope.a = 2
  32. expect(spy.callCount).toBe(1)
  33. expect(spy).toHaveBeenCalledWith('a', 2, u)
  34. // set on vm
  35. vm.b.c = 3
  36. expect(spy.callCount).toBe(2)
  37. expect(spy).toHaveBeenCalledWith('b.c', 3, u)
  38. })
  39. it('should trigger add/delete events', function () {
  40. var spy = jasmine.createSpy('instantiation')
  41. vm._observer
  42. .on('add', spy)
  43. .on('delete', spy)
  44. // add on scope
  45. vm.$scope.$add('c', 123)
  46. expect(spy.callCount).toBe(1)
  47. expect(spy).toHaveBeenCalledWith('c', 123, u)
  48. // delete on scope
  49. vm.$scope.$delete('c')
  50. expect(spy.callCount).toBe(2)
  51. expect(spy).toHaveBeenCalledWith('c', u, u)
  52. // vm $add/$delete are tested in the api suite
  53. })
  54. })
  55. describe('data sync', function () {
  56. var data = {
  57. a: 1,
  58. b: {
  59. c: 2
  60. }
  61. }
  62. var vm = new Vue({
  63. syncData: true,
  64. data: data
  65. })
  66. it('should retain data reference', function () {
  67. expect(vm.$data).toBe(data)
  68. })
  69. it('should sync set', function () {
  70. // vm -> data
  71. vm.a = 2
  72. expect(data.a).toBe(2)
  73. // data -> vm
  74. data.b = {d:3}
  75. expect(vm.$scope.b).toBe(data.b)
  76. expect(vm.b).toBe(data.b)
  77. })
  78. it('should sync add', function () {
  79. // vm -> data
  80. vm.$scope.$add('c', 123)
  81. expect(data.c).toBe(123)
  82. // data -> vm
  83. data.$add('d', 456)
  84. expect(vm.$scope.d).toBe(456)
  85. expect(vm.d).toBe(456)
  86. })
  87. it('should sync delete', function () {
  88. // vm -> data
  89. vm.$scope.$delete('d')
  90. expect(data.hasOwnProperty('d')).toBe(false)
  91. // data -> vm
  92. data.$delete('c')
  93. expect(vm.$scope.hasOwnProperty('c')).toBe(false)
  94. expect(vm.hasOwnProperty('c')).toBe(false)
  95. })
  96. })
  97. describe('inheritance', function () {
  98. var parent = new Vue({
  99. data: {
  100. a: 'parent a',
  101. b: { c: 2 },
  102. c: 'parent c',
  103. arr: [{a:1},{a:2}]
  104. }
  105. })
  106. var child = new Vue({
  107. parent: parent,
  108. data: {
  109. a: 'child a'
  110. }
  111. })
  112. it('child should inherit parent data on scope', function () {
  113. expect(child.$scope.b).toBe(parent.b) // object
  114. expect(child.$scope.c).toBe(parent.c) // primitive value
  115. })
  116. it('child should not ineherit data on instance', function () {
  117. expect(child.b).toBeUndefined()
  118. expect(child.c).toBeUndefined()
  119. })
  120. it('child should shadow parent property with same key', function () {
  121. expect(parent.a).toBe('parent a')
  122. expect(child.$scope.a).toBe('child a')
  123. expect(child.a).toBe('child a')
  124. })
  125. it('setting scope properties on child should affect parent', function () {
  126. child.$scope.c = 'modified by child'
  127. expect(parent.c).toBe('modified by child')
  128. })
  129. it('events on parent should propagate down to child', function () {
  130. // when a shadowed property changed on parent scope,
  131. // the event should NOT be propagated down
  132. var spy = jasmine.createSpy('inheritance')
  133. child._observer.on('set', spy)
  134. parent.c = 'c changed'
  135. expect(spy.callCount).toBe(1)
  136. expect(spy).toHaveBeenCalledWith('c', 'c changed', u)
  137. spy = jasmine.createSpy('inheritance')
  138. child._observer.on('add', spy)
  139. parent.$scope.$add('e', 123)
  140. expect(spy.callCount).toBe(1)
  141. expect(spy).toHaveBeenCalledWith('e', 123, u)
  142. spy = jasmine.createSpy('inheritance')
  143. child._observer.on('delete', spy)
  144. parent.$scope.$delete('e')
  145. expect(spy.callCount).toBe(1)
  146. expect(spy).toHaveBeenCalledWith('e', u, u)
  147. spy = jasmine.createSpy('inheritance')
  148. child._observer.on('mutate', spy)
  149. parent.arr.reverse()
  150. expect(spy.mostRecentCall.args[0]).toBe('arr')
  151. expect(spy.mostRecentCall.args[1]).toBe(parent.arr)
  152. expect(spy.mostRecentCall.args[2].method).toBe('reverse')
  153. })
  154. it('shadowed properties change on parent should not propagate down', function () {
  155. // when a shadowed property changed on parent scope,
  156. // the event should NOT be propagated down
  157. var spy = jasmine.createSpy('inheritance')
  158. child._observer.on('set', spy)
  159. parent.a = 'a changed'
  160. expect(spy.callCount).toBe(0)
  161. })
  162. })
  163. describe('inheritance with data sync on parent data', function () {
  164. var parent = new Vue({
  165. data: {
  166. arr: [{a:1},{a:2}]
  167. }
  168. })
  169. var child = new Vue({
  170. parent: parent,
  171. syncData: true,
  172. data: parent.arr[0]
  173. })
  174. it('should trigger proper events', function () {
  175. var parentSpy = jasmine.createSpy('parent')
  176. var childSpy = jasmine.createSpy('child')
  177. parent._observer.on('set', parentSpy)
  178. child._observer.on('set', childSpy)
  179. child.a = 3
  180. // make sure data sync is working
  181. expect(parent.arr[0].a).toBe(3)
  182. expect(parentSpy.callCount).toBe(1)
  183. expect(parentSpy).toHaveBeenCalledWith('arr.0.a', 3, u)
  184. expect(childSpy.callCount).toBe(2)
  185. expect(childSpy).toHaveBeenCalledWith('a', 3, u)
  186. expect(childSpy).toHaveBeenCalledWith('arr.0.a', 3, u)
  187. })
  188. })
  189. })