observer_spec.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /**
  2. * Test data observation.
  3. */
  4. var Observer = require('../../../src/observe/observer')
  5. var _ = require('../../../src/util')
  6. Observer.pathDelimiter = '.'
  7. describe('Observer', function () {
  8. var spy
  9. beforeEach(function () {
  10. spy = jasmine.createSpy('observer')
  11. })
  12. it('get', function () {
  13. Observer.emitGet = true
  14. var obj = {
  15. a: 1,
  16. b: {
  17. c: 2
  18. }
  19. }
  20. var ob = Observer.create(obj)
  21. ob.on('get', spy)
  22. var t = obj.a
  23. expect(spy).toHaveBeenCalledWith('a', undefined, undefined, undefined)
  24. expect(spy.calls.count()).toBe(1)
  25. t = obj.b.c
  26. expect(spy).toHaveBeenCalledWith('b', undefined, undefined, undefined)
  27. expect(spy).toHaveBeenCalledWith('b.c', undefined, undefined, undefined)
  28. expect(spy.calls.count()).toBe(3)
  29. Observer.emitGet = false
  30. })
  31. it('set', function () {
  32. var obj = {
  33. a: 1,
  34. b: {
  35. c: 2
  36. }
  37. }
  38. var ob = Observer.create(obj)
  39. ob.on('set', spy)
  40. obj.a = 3
  41. expect(spy).toHaveBeenCalledWith('a', 3, undefined, undefined)
  42. expect(spy.calls.count()).toBe(1)
  43. obj.b.c = 4
  44. expect(spy).toHaveBeenCalledWith('b.c', 4, undefined, undefined)
  45. expect(spy.calls.count()).toBe(2)
  46. // swap set
  47. var newB = { c: 5 }
  48. obj.b = newB
  49. expect(spy).toHaveBeenCalledWith('b', newB, undefined, undefined)
  50. expect(spy.calls.count()).toBe(3)
  51. // same value set should not emit events
  52. obj.a = 3
  53. expect(spy.calls.count()).toBe(3)
  54. })
  55. it('ignore prefix', function () {
  56. var obj = {
  57. _test: 123,
  58. $test: 234
  59. }
  60. var ob = Observer.create(obj)
  61. ob.on('set', spy)
  62. obj._test = 234
  63. obj.$test = 345
  64. expect(spy.calls.count()).toBe(0)
  65. })
  66. it('warn duplicate value', function () {
  67. spyOn(_, 'warn')
  68. var obj = {
  69. a: { b: 123 },
  70. b: null
  71. }
  72. var ob = Observer.create(obj)
  73. obj.b = obj.a
  74. expect(_.warn).toHaveBeenCalled()
  75. })
  76. it('array get', function () {
  77. Observer.emitGet = true
  78. var obj = {
  79. arr: [{a:1}, {a:2}]
  80. }
  81. var ob = Observer.create(obj)
  82. ob.on('get', spy)
  83. var t = obj.arr[0].a
  84. expect(spy).toHaveBeenCalledWith('arr', undefined, undefined, undefined)
  85. expect(spy).toHaveBeenCalledWith('arr.0.a', undefined, undefined, undefined)
  86. expect(spy.calls.count()).toBe(2)
  87. Observer.emitGet = false
  88. })
  89. it('array set', function () {
  90. var obj = {
  91. arr: [{a:1}, {a:2}]
  92. }
  93. var ob = Observer.create(obj)
  94. ob.on('set', spy)
  95. obj.arr[0].a = 2
  96. expect(spy).toHaveBeenCalledWith('arr.0.a', 2, undefined, undefined)
  97. // set events after mutation
  98. obj.arr.reverse()
  99. obj.arr[0].a = 3
  100. expect(spy).toHaveBeenCalledWith('arr.0.a', 3, undefined, undefined)
  101. })
  102. it('array push', function () {
  103. var arr = [{a:1}, {a:2}]
  104. var ob = Observer.create(arr)
  105. ob.on('mutate', spy)
  106. arr.push({a:3})
  107. expect(spy.calls.mostRecent().args[0]).toBe('')
  108. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  109. var mutation = spy.calls.mostRecent().args[2]
  110. expect(mutation).toBeDefined()
  111. expect(mutation.method).toBe('push')
  112. expect(mutation.index).toBe(2)
  113. expect(mutation.removed.length).toBe(0)
  114. expect(mutation.inserted.length).toBe(1)
  115. expect(mutation.inserted[0]).toBe(arr[2])
  116. // test index update after mutation
  117. ob.on('set', spy)
  118. arr[2].a = 4
  119. expect(spy).toHaveBeenCalledWith('2.a', 4, undefined, undefined)
  120. })
  121. it('array pop', function () {
  122. var arr = [{a:1}, {a:2}]
  123. var popped = arr[1]
  124. var ob = Observer.create(arr)
  125. ob.on('mutate', spy)
  126. arr.pop()
  127. expect(spy.calls.mostRecent().args[0]).toBe('')
  128. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  129. var mutation = spy.calls.mostRecent().args[2]
  130. expect(mutation).toBeDefined()
  131. expect(mutation.method).toBe('pop')
  132. expect(mutation.index).toBe(1)
  133. expect(mutation.inserted.length).toBe(0)
  134. expect(mutation.removed.length).toBe(1)
  135. expect(mutation.removed[0]).toBe(popped)
  136. })
  137. it('array shift', function () {
  138. var arr = [{a:1}, {a:2}]
  139. var shifted = arr[0]
  140. var ob = Observer.create(arr)
  141. ob.on('mutate', spy)
  142. arr.shift()
  143. expect(spy.calls.mostRecent().args[0]).toBe('')
  144. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  145. var mutation = spy.calls.mostRecent().args[2]
  146. expect(mutation).toBeDefined()
  147. expect(mutation.method).toBe('shift')
  148. expect(mutation.index).toBe(0)
  149. expect(mutation.inserted.length).toBe(0)
  150. expect(mutation.removed.length).toBe(1)
  151. expect(mutation.removed[0]).toBe(shifted)
  152. // test index update after mutation
  153. ob.on('set', spy)
  154. arr[0].a = 4
  155. expect(spy).toHaveBeenCalledWith('0.a', 4, undefined, undefined)
  156. })
  157. it('array unshift', function () {
  158. var arr = [{a:1}, {a:2}]
  159. var unshifted = {a:3}
  160. var ob = Observer.create(arr)
  161. ob.on('mutate', spy)
  162. arr.unshift(unshifted)
  163. expect(spy.calls.mostRecent().args[0]).toBe('')
  164. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  165. var mutation = spy.calls.mostRecent().args[2]
  166. expect(mutation).toBeDefined()
  167. expect(mutation.method).toBe('unshift')
  168. expect(mutation.index).toBe(0)
  169. expect(mutation.removed.length).toBe(0)
  170. expect(mutation.inserted.length).toBe(1)
  171. expect(mutation.inserted[0]).toBe(unshifted)
  172. // test index update after mutation
  173. ob.on('set', spy)
  174. arr[1].a = 4
  175. expect(spy).toHaveBeenCalledWith('1.a', 4, undefined, undefined)
  176. })
  177. it('array splice', function () {
  178. var arr = [{a:1}, {a:2}]
  179. var inserted = {a:3}
  180. var removed = arr[1]
  181. var ob = Observer.create(arr)
  182. ob.on('mutate', spy)
  183. arr.splice(1, 1, inserted)
  184. expect(spy.calls.mostRecent().args[0]).toBe('')
  185. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  186. var mutation = spy.calls.mostRecent().args[2]
  187. expect(mutation).toBeDefined()
  188. expect(mutation.method).toBe('splice')
  189. expect(mutation.index).toBe(1)
  190. expect(mutation.removed.length).toBe(1)
  191. expect(mutation.inserted.length).toBe(1)
  192. expect(mutation.removed[0]).toBe(removed)
  193. expect(mutation.inserted[0]).toBe(inserted)
  194. // test index update after mutation
  195. ob.on('set', spy)
  196. arr[1].a = 4
  197. expect(spy).toHaveBeenCalledWith('1.a', 4, undefined, undefined)
  198. })
  199. it('array sort', function () {
  200. var arr = [{a:1}, {a:2}]
  201. var ob = Observer.create(arr)
  202. ob.on('mutate', spy)
  203. arr.sort(function (a, b) {
  204. return a.a < b.a ? 1 : -1
  205. })
  206. expect(spy.calls.mostRecent().args[0]).toBe('')
  207. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  208. var mutation = spy.calls.mostRecent().args[2]
  209. expect(mutation).toBeDefined()
  210. expect(mutation.method).toBe('sort')
  211. expect(mutation.index).toBeUndefined()
  212. expect(mutation.removed.length).toBe(0)
  213. expect(mutation.inserted.length).toBe(0)
  214. // test index update after mutation
  215. ob.on('set', spy)
  216. arr[1].a = 4
  217. expect(spy).toHaveBeenCalledWith('1.a', 4, undefined, undefined)
  218. })
  219. it('array reverse', function () {
  220. var arr = [{a:1}, {a:2}]
  221. var ob = Observer.create(arr)
  222. ob.on('mutate', spy)
  223. arr.reverse()
  224. expect(spy.calls.mostRecent().args[0]).toBe('')
  225. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  226. var mutation = spy.calls.mostRecent().args[2]
  227. expect(mutation).toBeDefined()
  228. expect(mutation.method).toBe('reverse')
  229. expect(mutation.index).toBeUndefined()
  230. expect(mutation.removed.length).toBe(0)
  231. expect(mutation.inserted.length).toBe(0)
  232. // test index update after mutation
  233. ob.on('set', spy)
  234. arr[1].a = 4
  235. expect(spy).toHaveBeenCalledWith('1.a', 4, undefined, undefined)
  236. })
  237. it('object.$add', function () {
  238. var obj = {a:{b:1}}
  239. var ob = Observer.create(obj)
  240. ob.on('add', spy)
  241. // ignore existing keys
  242. obj.$add('a', 123)
  243. expect(spy.calls.count()).toBe(0)
  244. // add event
  245. var add = {d:2}
  246. obj.a.$add('c', add)
  247. expect(spy).toHaveBeenCalledWith('a.c', add, undefined, undefined)
  248. // check if add object is properly observed
  249. ob.on('set', spy)
  250. obj.a.c.d = 3
  251. expect(spy).toHaveBeenCalledWith('a.c.d', 3, undefined, undefined)
  252. })
  253. it('object.$delete', function () {
  254. var obj = {a:{b:1}}
  255. var ob = Observer.create(obj)
  256. ob.on('delete', spy)
  257. // ignore non-present key
  258. obj.$delete('c')
  259. expect(spy.calls.count()).toBe(0)
  260. obj.a.$delete('b')
  261. expect(spy).toHaveBeenCalledWith('a.b', undefined, undefined, undefined)
  262. })
  263. it('array.$set', function () {
  264. var arr = [{a:1}, {a:2}]
  265. var ob = Observer.create(arr)
  266. ob.on('mutate', spy)
  267. var inserted = {a:3}
  268. var removed = arr[1]
  269. arr.$set(1, inserted)
  270. expect(spy.calls.mostRecent().args[0]).toBe('')
  271. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  272. var mutation = spy.calls.mostRecent().args[2]
  273. expect(mutation).toBeDefined()
  274. expect(mutation.method).toBe('splice')
  275. expect(mutation.index).toBe(1)
  276. expect(mutation.removed.length).toBe(1)
  277. expect(mutation.inserted.length).toBe(1)
  278. expect(mutation.removed[0]).toBe(removed)
  279. expect(mutation.inserted[0]).toBe(inserted)
  280. ob.on('set', spy)
  281. arr[1].a = 4
  282. expect(spy).toHaveBeenCalledWith('1.a', 4, undefined, undefined)
  283. })
  284. it('array.$set with out of bound length', function () {
  285. var arr = [{a:1}, {a:2}]
  286. var ob = Observer.create(arr)
  287. var inserted = {a:3}
  288. arr.$set(3, inserted)
  289. expect(arr.length).toBe(4)
  290. expect(arr[2]).toBeUndefined()
  291. expect(arr[3]).toBe(inserted)
  292. })
  293. it('array.$remove', function () {
  294. var arr = [{a:1}, {a:2}]
  295. var ob = Observer.create(arr)
  296. ob.on('mutate', spy)
  297. var removed = arr.$remove(0)
  298. expect(spy.calls.mostRecent().args[0]).toBe('')
  299. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  300. var mutation = spy.calls.mostRecent().args[2]
  301. expect(mutation).toBeDefined()
  302. expect(mutation.method).toBe('splice')
  303. expect(mutation.index).toBe(0)
  304. expect(mutation.removed.length).toBe(1)
  305. expect(mutation.inserted.length).toBe(0)
  306. expect(mutation.removed[0]).toBe(removed)
  307. ob.on('set', spy)
  308. arr[0].a = 3
  309. expect(spy).toHaveBeenCalledWith('0.a', 3, undefined, undefined)
  310. })
  311. it('array.$remove object', function () {
  312. var arr = [{a:1}, {a:2}]
  313. var ob = Observer.create(arr)
  314. ob.on('mutate', spy)
  315. var removed = arr.$remove(arr[0])
  316. expect(spy.calls.mostRecent().args[0]).toBe('')
  317. expect(spy.calls.mostRecent().args[1]).toBe(arr)
  318. var mutation = spy.calls.mostRecent().args[2]
  319. expect(mutation).toBeDefined()
  320. expect(mutation.method).toBe('splice')
  321. expect(mutation.index).toBe(0)
  322. expect(mutation.removed.length).toBe(1)
  323. expect(mutation.inserted.length).toBe(0)
  324. expect(mutation.removed[0]).toBe(removed)
  325. ob.on('set', spy)
  326. arr[0].a = 3
  327. expect(spy).toHaveBeenCalledWith('0.a', 3, undefined, undefined)
  328. })
  329. it('shared observe', function () {
  330. var obj = { a: 1 }
  331. var parentA = { child1: obj }
  332. var parentB = { child2: obj }
  333. var obA = Observer.create(parentA)
  334. var obB = Observer.create(parentB)
  335. obA.on('set', spy)
  336. obB.on('set', spy)
  337. obj.a = 2
  338. expect(spy.calls.count()).toBe(2)
  339. expect(spy).toHaveBeenCalledWith('child1.a', 2, undefined, undefined)
  340. expect(spy).toHaveBeenCalledWith('child2.a', 2, undefined, undefined)
  341. // test unobserve
  342. parentA.child1 = null
  343. obj.a = 3
  344. expect(spy.calls.count()).toBe(4)
  345. expect(spy).toHaveBeenCalledWith('child1', null, undefined, undefined)
  346. expect(spy).toHaveBeenCalledWith('child2.a', 3, undefined, undefined)
  347. })
  348. })