observer.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. describe('UNIT: Observer', function () {
  2. var Observer = require('seed/src/observer'),
  3. Emitter = require('emitter')
  4. describe('Observing Object', function () {
  5. it('should attach hidden observer and values to the object', function () {
  6. var obj = {}, ob = new Emitter()
  7. ob.proxies = {}
  8. Observer.observe(obj, 'test', ob)
  9. assert.ok(obj.__observer__ instanceof Emitter)
  10. assert.ok(obj.__observer__.values)
  11. })
  12. it('should emit set events with correct path', setTestFactory({
  13. obj: { a: 1, b: { c: 2 } },
  14. expects: [
  15. { key: 'test.a', val: 1 },
  16. { key: 'test.b.c', val: 3 }
  17. ],
  18. path: 'test'
  19. }))
  20. it('should emit multiple events when a nested object is set', setTestFactory({
  21. obj: { a: 1, b: { c: 2 } },
  22. expects: [
  23. { key: 'test.b', val: { c: 3 } },
  24. { key: 'test.b.c', val: 3, skip: true }
  25. ],
  26. path: 'test'
  27. }))
  28. it('should emit get events on tip values', getTestFactory({
  29. obj: { a: 1, b: { c: 2 } },
  30. expects: [
  31. 'test.a',
  32. 'test.b.c'
  33. ],
  34. path: 'test'
  35. }))
  36. it('should emit set when first observing', function () {
  37. var obj = { a: 1, b: { c: 2} },
  38. ob = new Emitter(), i = 0
  39. ob.proxies = {}
  40. var expects = [
  41. { key: 'test.a', val: obj.a },
  42. { key: 'test.b', val: obj.b },
  43. { key: 'test.b.c', val: obj.b.c }
  44. ]
  45. ob.on('set', function (key, val) {
  46. var exp = expects[i]
  47. assert.strictEqual(key, exp.key)
  48. assert.strictEqual(val, exp.val)
  49. i++
  50. })
  51. Observer.observe(obj, 'test', ob)
  52. assert.strictEqual(i, expects.length)
  53. })
  54. it('should emit set when watching an already observed object', function () {
  55. var obj = { a: 1, b: { c: 2} },
  56. ob1 = new Emitter(),
  57. ob2 = new Emitter(),
  58. i = 0
  59. ob1.proxies = {}
  60. ob2.proxies = {}
  61. Observer.observe(obj, 'test', ob1) // watch first time
  62. var expects = [
  63. { key: 'test.a', val: obj.a },
  64. { key: 'test.b', val: obj.b },
  65. { key: 'test.b.c', val: obj.b.c }
  66. ]
  67. ob2.on('set', function (key, val) {
  68. var exp = expects[i]
  69. assert.strictEqual(key, exp.key)
  70. assert.strictEqual(val, exp.val)
  71. i++
  72. })
  73. Observer.observe(obj, 'test', ob2) // watch again
  74. assert.strictEqual(i, expects.length)
  75. })
  76. })
  77. describe('Observing Array', function () {
  78. var arr = [],
  79. ob = new Emitter()
  80. ob.proxies = {}
  81. Observer.observe(arr, 'test', ob)
  82. it('should attach the hidden observer', function () {
  83. assert.ok(arr.__observer__ instanceof Emitter)
  84. })
  85. it('should overwrite the native array mutator methods', function () {
  86. ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) {
  87. assert.notStrictEqual(arr[method], Array.prototype[method])
  88. })
  89. })
  90. it('should emit set for .length when it mutates', function () {
  91. var emitted = false
  92. ob.once('set', function (key, val) {
  93. assert.strictEqual(key, 'test.length')
  94. assert.strictEqual(val, 1)
  95. emitted = true
  96. })
  97. arr.push(1)
  98. assert.ok(emitted)
  99. })
  100. describe('Mutator Methods', function () {
  101. it('push', function () {
  102. var arg1 = 123,
  103. arg2 = 234,
  104. emitted = false
  105. ob.once('mutate', function (key, array, mutation) {
  106. assert.strictEqual(key, 'test')
  107. assert.strictEqual(array, arr)
  108. assert.strictEqual(array.length, 3)
  109. assert.strictEqual(mutation.method, 'push')
  110. assert.strictEqual(mutation.args.length, 2)
  111. assert.strictEqual(mutation.args[0], arg1)
  112. assert.strictEqual(mutation.args[1], arg2)
  113. assert.strictEqual(mutation.result, arr.length)
  114. emitted = true
  115. })
  116. var r = arr.push(arg1, arg2)
  117. assert.ok(emitted)
  118. assert.strictEqual(r, arr.length)
  119. })
  120. it('pop', function () {
  121. var emitted = false,
  122. expected = arr[arr.length - 1]
  123. ob.once('mutate', function (key, array, mutation) {
  124. assert.strictEqual(key, 'test')
  125. assert.strictEqual(array, arr)
  126. assert.strictEqual(array.length, 2)
  127. assert.strictEqual(mutation.method, 'pop')
  128. assert.strictEqual(mutation.args.length, 0)
  129. assert.strictEqual(mutation.result, expected)
  130. emitted = true
  131. })
  132. var r = arr.pop()
  133. assert.ok(emitted)
  134. assert.strictEqual(r, expected)
  135. })
  136. it('shift', function () {
  137. var emitted = false,
  138. expected = arr[0]
  139. ob.once('mutate', function (key, array, mutation) {
  140. assert.strictEqual(key, 'test')
  141. assert.strictEqual(array, arr)
  142. assert.strictEqual(array.length, 1)
  143. assert.strictEqual(mutation.method, 'shift')
  144. assert.strictEqual(mutation.args.length, 0)
  145. assert.strictEqual(mutation.result, expected)
  146. emitted = true
  147. })
  148. var r = arr.shift()
  149. assert.ok(emitted)
  150. assert.strictEqual(r, expected)
  151. })
  152. it('unshift', function () {
  153. var emitted = false,
  154. arg1 = 456,
  155. arg2 = 678
  156. ob.once('mutate', function (key, array, mutation) {
  157. assert.strictEqual(key, 'test')
  158. assert.strictEqual(array, arr)
  159. assert.strictEqual(array.length, 3)
  160. assert.strictEqual(mutation.method, 'unshift')
  161. assert.strictEqual(mutation.args.length, 2)
  162. assert.strictEqual(mutation.args[0], arg1)
  163. assert.strictEqual(mutation.args[1], arg2)
  164. assert.strictEqual(mutation.result, arr.length)
  165. emitted = true
  166. })
  167. var r = arr.unshift(arg1, arg2)
  168. assert.ok(emitted)
  169. assert.strictEqual(r, arr.length)
  170. })
  171. it('splice', function () {
  172. var emitted = false,
  173. arg1 = 789,
  174. arg2 = 910,
  175. expected = arr[1]
  176. ob.once('mutate', function (key, array, mutation) {
  177. assert.strictEqual(key, 'test')
  178. assert.strictEqual(array, arr)
  179. assert.strictEqual(array.length, 4)
  180. assert.strictEqual(mutation.method, 'splice')
  181. assert.strictEqual(mutation.args.length, 4)
  182. assert.strictEqual(mutation.args[0], 1)
  183. assert.strictEqual(mutation.args[1], 1)
  184. assert.strictEqual(mutation.args[2], arg1)
  185. assert.strictEqual(mutation.args[3], arg2)
  186. assert.strictEqual(mutation.result.length, 1)
  187. assert.strictEqual(mutation.result[0], expected)
  188. emitted = true
  189. })
  190. var r = arr.splice(1, 1, arg1, arg2)
  191. assert.ok(emitted)
  192. assert.strictEqual(r.length, 1)
  193. assert.strictEqual(r[0], expected)
  194. })
  195. it('sort', function () {
  196. var emitted = false,
  197. sorter = function (a, b) {
  198. return a > b ? -1 : 1
  199. },
  200. copy = arr.slice().sort(sorter)
  201. ob.once('mutate', function (key, array, mutation) {
  202. assert.strictEqual(key, 'test')
  203. assert.strictEqual(array, arr)
  204. assert.strictEqual(mutation.method, 'sort')
  205. assert.strictEqual(mutation.args.length, 1)
  206. assert.strictEqual(mutation.result, arr)
  207. for (var i = 0; i < copy.length; i++) {
  208. assert.strictEqual(array[i], copy[i])
  209. }
  210. emitted = true
  211. })
  212. var r = arr.sort(sorter)
  213. assert.ok(emitted)
  214. assert.strictEqual(r, arr)
  215. })
  216. it('reverse', function () {
  217. var emitted = false,
  218. copy = arr.slice().reverse()
  219. ob.once('mutate', function (key, array, mutation) {
  220. assert.strictEqual(key, 'test')
  221. assert.strictEqual(array, arr)
  222. assert.strictEqual(mutation.method, 'reverse')
  223. assert.strictEqual(mutation.args.length, 0)
  224. assert.strictEqual(mutation.result, arr)
  225. for (var i = 0; i < copy.length; i++) {
  226. assert.strictEqual(array[i], copy[i])
  227. }
  228. emitted = true
  229. })
  230. var r = arr.reverse()
  231. assert.ok(emitted)
  232. assert.strictEqual(r, arr)
  233. })
  234. })
  235. describe('Augmentations', function () {
  236. it('remove', function () {
  237. var emitted = false,
  238. expected = arr[0] = { a: 1 }
  239. ob.once('mutate', function (key, array, mutation) {
  240. emitted = true
  241. assert.strictEqual(mutation.method, 'splice')
  242. assert.strictEqual(mutation.args.length, 2)
  243. })
  244. var r = arr.remove(expected)
  245. assert.ok(emitted)
  246. assert.strictEqual(r, expected)
  247. })
  248. it('replace', function () {
  249. var emitted = false,
  250. expected = arr[0] = { a: 1 },
  251. arg = 45678
  252. ob.once('mutate', function (key, array, mutation) {
  253. emitted = true
  254. assert.strictEqual(mutation.method, 'splice')
  255. assert.strictEqual(mutation.args.length, 3)
  256. })
  257. var r = arr.replace(expected, arg)
  258. assert.ok(emitted)
  259. assert.strictEqual(r, expected)
  260. assert.strictEqual(arr[0], arg)
  261. })
  262. it('mutateFilter', function () {
  263. var filter = function (e) {
  264. return e > 1000
  265. },
  266. copy = arr.slice().filter(filter)
  267. arr.mutateFilter(filter)
  268. for (var i = 0; i < copy.length; i++) {
  269. assert.strictEqual(arr[i], copy[i])
  270. }
  271. })
  272. })
  273. })
  274. function setTestFactory (opts) {
  275. return function () {
  276. var ob = new Emitter(),
  277. i = 0,
  278. obj = opts.obj,
  279. expects = opts.expects
  280. ob.proxies = {}
  281. Observer.observe(obj, opts.path, ob)
  282. ob.on('set', function (key, val) {
  283. var expect = expects[i]
  284. assert.strictEqual(key, expect.key)
  285. assert.strictEqual(val, expect.val)
  286. i++
  287. })
  288. expects.forEach(function (expect) {
  289. if (expect.skip) return
  290. var path = expect.key.split('.'),
  291. j = 1,
  292. scope = obj
  293. while (j < path.length - 1) {
  294. scope = scope[path[j]]
  295. j++
  296. }
  297. scope[path[j]] = expect.val
  298. })
  299. assert.strictEqual(i, expects.length)
  300. }
  301. }
  302. function getTestFactory (opts) {
  303. return function () {
  304. var ob = new Emitter(),
  305. i = 0,
  306. obj = opts.obj,
  307. expects = opts.expects
  308. ob.proxies = {}
  309. Observer.observe(obj, opts.path, ob)
  310. ob.on('get', function (key) {
  311. var expected = expects[i]
  312. assert.strictEqual(key, expected)
  313. i++
  314. })
  315. expects.forEach(function (key) {
  316. var path = key.split('.'),
  317. j = 1,
  318. scope = obj
  319. while (j < path.length) {
  320. scope = scope[path[j]]
  321. j++
  322. }
  323. })
  324. assert.strictEqual(i, expects.length)
  325. }
  326. }
  327. })