watcher_spec.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. var Vue = require('../../../src/vue')
  2. var nextTick = Vue.nextTick
  3. var Watcher = require('../../../src/watcher')
  4. describe('Watcher', function () {
  5. var vm, spy
  6. beforeEach(function () {
  7. vm = new Vue({
  8. data: {
  9. a: 1,
  10. b: {
  11. c: 2,
  12. d: 4
  13. },
  14. c: 'c'
  15. }
  16. })
  17. spy = jasmine.createSpy('watcher')
  18. })
  19. it('simple path', function (done) {
  20. var watcher = new Watcher(vm, 'b.c', spy)
  21. expect(watcher.value).toBe(2)
  22. vm.b.c = 3
  23. nextTick(function () {
  24. expect(watcher.value).toBe(3)
  25. expect(spy).toHaveBeenCalledWith(3, 2)
  26. vm.b = { c: 4 } // swapping the object
  27. nextTick(function () {
  28. expect(watcher.value).toBe(4)
  29. expect(spy).toHaveBeenCalledWith(4, 3)
  30. done()
  31. })
  32. })
  33. })
  34. it('bracket access path', function (done) {
  35. var watcher = new Watcher(vm, 'b["c"]', spy)
  36. expect(watcher.value).toBe(2)
  37. vm.b.c = 3
  38. nextTick(function () {
  39. expect(watcher.value).toBe(3)
  40. expect(spy).toHaveBeenCalledWith(3, 2)
  41. vm.b = { c: 4 } // swapping the object
  42. nextTick(function () {
  43. expect(watcher.value).toBe(4)
  44. expect(spy).toHaveBeenCalledWith(4, 3)
  45. done()
  46. })
  47. })
  48. })
  49. it('dynamic path', function (done) {
  50. var watcher = new Watcher(vm, 'b[c]', spy)
  51. expect(watcher.value).toBe(2)
  52. vm.b.c = 3
  53. nextTick(function () {
  54. expect(watcher.value).toBe(3)
  55. expect(spy).toHaveBeenCalledWith(3, 2)
  56. vm.c = 'd' // changing the dynamic segment in path
  57. nextTick(function () {
  58. expect(watcher.value).toBe(4)
  59. expect(spy).toHaveBeenCalledWith(4, 3)
  60. done()
  61. })
  62. })
  63. })
  64. it('simple expression', function (done) {
  65. var watcher = new Watcher(vm, 'a + b.c', spy)
  66. expect(watcher.value).toBe(3)
  67. vm.b.c = 3
  68. nextTick(function () {
  69. expect(watcher.value).toBe(4)
  70. expect(spy.calls.count()).toBe(1)
  71. expect(spy).toHaveBeenCalledWith(4, 3)
  72. // change two dependencies at once
  73. vm.a = 2
  74. vm.b.c = 4
  75. nextTick(function () {
  76. expect(watcher.value).toBe(6)
  77. // should trigger only once callback,
  78. // because it was in the same event loop.
  79. expect(spy.calls.count()).toBe(2)
  80. expect(spy).toHaveBeenCalledWith(6, 4)
  81. done()
  82. })
  83. })
  84. })
  85. it('ternary expression', function (done) {
  86. // we're actually testing for the dependency re-calculation here
  87. var watcher = new Watcher(vm, 'a > 1 ? b.c : b.d', spy)
  88. expect(watcher.value).toBe(4)
  89. vm.a = 2
  90. nextTick(function () {
  91. expect(watcher.value).toBe(2)
  92. expect(spy).toHaveBeenCalledWith(2, 4)
  93. vm.b.c = 3
  94. nextTick(function () {
  95. expect(watcher.value).toBe(3)
  96. expect(spy).toHaveBeenCalledWith(3, 2)
  97. done()
  98. })
  99. })
  100. })
  101. it('non-existent path, $add later', function (done) {
  102. var watcher = new Watcher(vm, 'd.e', spy)
  103. var watcher2 = new Watcher(vm, 'b.e', spy)
  104. expect(watcher.value).toBeUndefined()
  105. expect(watcher2.value).toBeUndefined()
  106. vm.$scope.$add('d', { e: 123 })
  107. vm.b.$add('e', 234)
  108. nextTick(function () {
  109. expect(watcher.value).toBe(123)
  110. expect(watcher2.value).toBe(234)
  111. expect(spy).toHaveBeenCalledWith(123, undefined)
  112. expect(spy).toHaveBeenCalledWith(234, undefined)
  113. done()
  114. })
  115. })
  116. it('$delete', function (done) {
  117. var watcher = new Watcher(vm, 'b.c', spy)
  118. expect(watcher.value).toBe(2)
  119. vm.$scope.$delete('b')
  120. nextTick(function () {
  121. expect(watcher.value).toBeUndefined()
  122. expect(spy).toHaveBeenCalledWith(undefined, 2)
  123. done()
  124. })
  125. })
  126. it('swapping $data', function (done) {
  127. var watcher = new Watcher(vm, 'b.c', spy)
  128. expect(watcher.value).toBe(2)
  129. vm.$data = { b: { c: 3}}
  130. nextTick(function () {
  131. expect(watcher.value).toBe(3)
  132. expect(spy).toHaveBeenCalledWith(3, 2)
  133. done()
  134. })
  135. })
  136. it('path containing $data', function (done) {
  137. var watcher = new Watcher(vm, '$data.b.c', spy)
  138. expect(watcher.value).toBe(2)
  139. vm.b = { c: 3 }
  140. nextTick(function () {
  141. expect(watcher.value).toBe(3)
  142. expect(spy).toHaveBeenCalledWith(3, 2)
  143. vm.$data = { b: {c: 4}}
  144. nextTick(function () {
  145. expect(watcher.value).toBe(4)
  146. expect(spy).toHaveBeenCalledWith(4, 3)
  147. done()
  148. })
  149. })
  150. })
  151. it('watching $data', function (done) {
  152. var oldData = vm.$data
  153. var watcher = new Watcher(vm, '$data', spy)
  154. expect(watcher.value).toBe(oldData)
  155. vm.a = 2
  156. nextTick(function () {
  157. expect(spy).toHaveBeenCalledWith(oldData, oldData)
  158. var newData = {}
  159. vm.$data = newData
  160. nextTick(function() {
  161. expect(spy).toHaveBeenCalledWith(newData, oldData)
  162. expect(watcher.value).toBe(newData)
  163. done()
  164. })
  165. })
  166. })
  167. it('callback context', function (done) {
  168. var context = {}
  169. var watcher = new Watcher(vm, 'b.c', function () {
  170. spy.apply(this, arguments)
  171. expect(this).toBe(context)
  172. }, context)
  173. vm.b.c = 3
  174. nextTick(function () {
  175. expect(spy).toHaveBeenCalledWith(3, 2)
  176. done()
  177. })
  178. })
  179. it('filters', function (done) {
  180. vm.$options.filters.test = function (val, multi) {
  181. return val * multi
  182. }
  183. vm.$options.filters.test2 = function (val, str) {
  184. return val + str
  185. }
  186. var watcher = new Watcher(vm, 'b.c', spy, null, [
  187. { name: 'test', args: [3] },
  188. { name: 'test2', args: ['yo']}
  189. ])
  190. expect(watcher.value).toBe('6yo')
  191. vm.b.c = 3
  192. nextTick(function () {
  193. expect(watcher.value).toBe('9yo')
  194. expect(spy).toHaveBeenCalledWith('9yo', '6yo')
  195. done()
  196. })
  197. })
  198. it('setter', function (done) {
  199. vm.$options.filters.test = {
  200. write: function (val, oldVal, arg) {
  201. return val > arg ? val : oldVal
  202. }
  203. }
  204. var watcher = new Watcher(vm, 'b["c"]', spy, null, [
  205. { name: 'test', args: [5] }
  206. ], true)
  207. expect(watcher.value).toBe(2)
  208. watcher.set(4) // shoud not change the value
  209. nextTick(function () {
  210. expect(vm.b.c).toBe(2)
  211. expect(watcher.value).toBe(2)
  212. expect(spy.calls.count()).toBe(0)
  213. watcher.set(6)
  214. nextTick(function () {
  215. expect(vm.b.c).toBe(6)
  216. expect(watcher.value).toBe(6)
  217. expect(spy).toHaveBeenCalledWith(6, 2)
  218. done()
  219. })
  220. })
  221. })
  222. it('set non-existent values', function (done) {
  223. var watcher = new Watcher(vm, 'd.e.f', spy)
  224. expect(watcher.value).toBeUndefined()
  225. watcher.set(123)
  226. nextTick(function () {
  227. expect(vm.d.e.f).toBe(123)
  228. expect(watcher.value).toBe(123)
  229. expect(spy).toHaveBeenCalledWith(123, undefined)
  230. done()
  231. })
  232. })
  233. it('teardown', function (done) {
  234. var watcher = new Watcher(vm, 'b.c', spy)
  235. watcher.teardown()
  236. vm.b.c = 3
  237. nextTick(function () {
  238. expect(watcher.active).toBe(false)
  239. expect(spy.calls.count()).toBe(0)
  240. done()
  241. })
  242. })
  243. })