Model.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. describe('Model', function() {
  2. var Model = $.fullCalendar.Model
  3. describe('set/get', function() {
  4. it('retrieves a previously set value', function() {
  5. var funcs = {
  6. change: function(val) {
  7. expect(val).toBe(5)
  8. }
  9. }
  10. var spy = spyOn(funcs, 'change').and.callThrough()
  11. var m = new Model()
  12. m.on('change:myvar', funcs.change)
  13. m.set('myvar', 5)
  14. expect(m.get('myvar')).toBe(5)
  15. expect(spy).toHaveBeenCalled()
  16. })
  17. it('retrieves values previously set in bulk', function() {
  18. var m = new Model()
  19. m.set({
  20. myvar: 5,
  21. myothervar: 6
  22. })
  23. expect(m.get('myvar')).toBe(5)
  24. expect(m.get('myothervar')).toBe(6)
  25. })
  26. it('retrieves undefined when not previously set', function() {
  27. var m = new Model()
  28. expect(m.get('myvar')).toBeUndefined()
  29. })
  30. it('can retreive whole internal object', function() {
  31. var m = new Model()
  32. m.set({
  33. myvar: 5,
  34. myothervar: 6
  35. })
  36. expect(m.get()).toEqual({
  37. myvar: 5,
  38. myothervar: 6
  39. })
  40. })
  41. it('fires all before:change events beforehand when setting in bulk', function() {
  42. var ops = []
  43. var m = new Model()
  44. m.set({
  45. myvar: 5,
  46. myothervar: 6
  47. })
  48. m.on('before:change:myvar', function(val) {
  49. ops.push('before:change:myvar')
  50. })
  51. m.on('before:change:myothervar', function(val) {
  52. ops.push('before:change:myothervar')
  53. })
  54. m.on('change:myvar', function(val) {
  55. ops.push('change:myvar')
  56. })
  57. m.on('change:myothervar', function(val) {
  58. ops.push('change:myothervar')
  59. })
  60. m.set({
  61. myvar: 7,
  62. myothervar: 8
  63. })
  64. expect(ops).toEqual([
  65. 'before:change:myvar',
  66. 'before:change:myothervar',
  67. 'change:myvar',
  68. 'change:myothervar'
  69. ])
  70. })
  71. })
  72. describe('unset', function() {
  73. it('can unset a single prop', function() {
  74. var m = new Model()
  75. m.set({
  76. myvar: 5,
  77. myothervar: 6
  78. })
  79. m.unset('myvar')
  80. expect(m.get()).toEqual({
  81. myothervar: 6
  82. })
  83. })
  84. it('can unset multiple props', function() {
  85. var m = new Model()
  86. m.set({
  87. myvar: 5,
  88. myothervar: 6,
  89. myothervarr: 7
  90. })
  91. m.unset([ 'myvar', 'myothervar' ])
  92. expect(m.get()).toEqual({
  93. myothervarr: 7
  94. })
  95. })
  96. })
  97. describe('reset', function() {
  98. it('will change all props', function() {
  99. var m = new Model()
  100. m.set({
  101. foo1: 5,
  102. foo2: 6
  103. })
  104. m.reset({
  105. bar1: 7,
  106. bar2: 8
  107. })
  108. expect(m.get()).toEqual({
  109. bar1: 7,
  110. bar2: 8
  111. })
  112. })
  113. })
  114. describe('has', function() {
  115. it('reports false when not previously set', function() {
  116. var m = new Model()
  117. expect(m.has('myvar')).toBe(false)
  118. })
  119. it('reports true when previously set', function() {
  120. var m = new Model()
  121. m.set('myvar', 5)
  122. expect(m.has('myvar')).toBe(true)
  123. })
  124. })
  125. describe('watch', function() {
  126. describe('when called as a task', function() {
  127. describe('when no deps', function() {
  128. it('resolves immediately', function() {
  129. var funcs = {
  130. start: function() { }
  131. }
  132. var spy = spyOn(funcs, 'start')
  133. var m = new Model()
  134. m.watch('myid', [], funcs.start)
  135. expect(spy).toHaveBeenCalled()
  136. expect(m.has('myid')).toBe(true)
  137. })
  138. })
  139. describe('when all deps already satisfied', function() {
  140. it('resolves immediately', function() {
  141. var funcs = {
  142. start: function() { }
  143. }
  144. var spy = spyOn(funcs, 'start')
  145. var m = new Model()
  146. m.set({
  147. myvar: 5,
  148. myothervar: 6
  149. })
  150. m.watch('myid', [ 'myvar', 'myothervar' ], funcs.start)
  151. expect(spy).toHaveBeenCalled()
  152. expect(m.has('myid')).toBe(true)
  153. })
  154. })
  155. describe('when not all deps satisfied', function() {
  156. it('resolves only after all deps are set', function() {
  157. var funcs = {
  158. start: function() { }
  159. }
  160. var spy = spyOn(funcs, 'start')
  161. var m = new Model()
  162. m.set('myvar', 5)
  163. m.watch('myid', [ 'myvar', 'myothervar' ], funcs.start)
  164. expect(spy).not.toHaveBeenCalled()
  165. expect(m.has('myid')).toBe(false)
  166. m.set('myothervar', 6)
  167. expect(spy).toHaveBeenCalled()
  168. expect(m.has('myid')).toBe(true)
  169. })
  170. })
  171. describe('when previously resolved dep is unset', function() {
  172. it('calls the stop function', function() {
  173. var funcs = {
  174. start: function() { },
  175. stop: function() { }
  176. }
  177. var startSpy = spyOn(funcs, 'start')
  178. var stopSpy = spyOn(funcs, 'stop')
  179. var m = new Model()
  180. m.set('myvar', 5)
  181. m.watch('myid', [ 'myvar', 'myothervar' ], funcs.start, funcs.stop)
  182. m.set('myothervar', 6)
  183. expect(startSpy).toHaveBeenCalled()
  184. expect(stopSpy).not.toHaveBeenCalled()
  185. expect(m.has('myid')).toBe(true)
  186. m.unset('myothervar')
  187. expect(stopSpy).toHaveBeenCalled()
  188. expect(m.has('myid')).toBe(false)
  189. })
  190. })
  191. describe('when resetting a dependency', function() {
  192. it('calls all shutdown funcs before all startup funcs', function() {
  193. var m = new Model()
  194. var ops = []
  195. m.set('var1', 5)
  196. m.watch('doingSomething1', [ 'var1' ], function() {
  197. ops.push('start1')
  198. }, function() {
  199. ops.push('stop1')
  200. })
  201. m.watch('doingSomething2', [ 'var1' ], function() {
  202. ops.push('start2')
  203. }, function() {
  204. ops.push('stop2')
  205. })
  206. expect(ops).toEqual([
  207. 'start1', 'start2'
  208. ])
  209. m.set('var1', 6)
  210. expect(ops).toEqual([
  211. 'start1', 'start2',
  212. 'stop1', 'stop2',
  213. 'start1', 'start2'
  214. ])
  215. })
  216. })
  217. describe('with an optional value', function() {
  218. it('resolves immediately', function() {
  219. var funcs = {
  220. start: function() { },
  221. stop: function() { }
  222. }
  223. var startSpy = spyOn(funcs, 'start')
  224. var stopSpy = spyOn(funcs, 'stop')
  225. var m = new Model()
  226. m.watch('myid', [ '?optvar' ], funcs.start, funcs.stop)
  227. expect(startSpy).toHaveBeenCalled()
  228. expect(stopSpy).not.toHaveBeenCalled()
  229. })
  230. it('calls stop/start when value changed', function() {
  231. var funcs = {
  232. start: function() { },
  233. stop: function() { }
  234. }
  235. var startSpy = spyOn(funcs, 'start')
  236. var stopSpy = spyOn(funcs, 'stop')
  237. var m = new Model()
  238. m.set('optvar', 5)
  239. m.watch('myid', [ '?optvar' ], funcs.start, funcs.stop)
  240. expect(stopSpy).not.toHaveBeenCalled()
  241. expect(startSpy).toHaveBeenCalledTimes(1)
  242. m.set('optvar', 6)
  243. expect(stopSpy).toHaveBeenCalledTimes(1)
  244. expect(startSpy).toHaveBeenCalledTimes(2)
  245. })
  246. it('calls stop/start when value unset', function() {
  247. var funcs = {
  248. start: function() { },
  249. stop: function() { }
  250. }
  251. var startSpy = spyOn(funcs, 'start')
  252. var stopSpy = spyOn(funcs, 'stop')
  253. var m = new Model()
  254. m.set('optvar', 5)
  255. m.watch('myid', [ '?optvar' ], funcs.start, funcs.stop)
  256. expect(stopSpy).not.toHaveBeenCalled()
  257. expect(startSpy).toHaveBeenCalledTimes(1)
  258. m.unset('optvar')
  259. expect(stopSpy).toHaveBeenCalledTimes(1)
  260. expect(startSpy).toHaveBeenCalledTimes(2)
  261. })
  262. })
  263. describe('when multiple deps changed atomically', function() {
  264. it('fires stop/start only once per change', function() {
  265. var funcs = {
  266. start: function() { },
  267. stop: function() { }
  268. }
  269. var startSpy = spyOn(funcs, 'start')
  270. var stopSpy = spyOn(funcs, 'stop')
  271. var m = new Model()
  272. m.set({
  273. myvar1: 5,
  274. myvar2: 6
  275. })
  276. m.watch('taskid', [ 'myvar1', 'myvar2' ], funcs.start, funcs.stop)
  277. m.set({
  278. myvar1: 7,
  279. myvar2: 8
  280. })
  281. expect(stopSpy).toHaveBeenCalledTimes(1)
  282. expect(startSpy).toHaveBeenCalledTimes(2)
  283. })
  284. })
  285. })
  286. describe('when called as a computed value', function() {
  287. describe('when it has no deps', function() {
  288. it('resolves immediately', function() {
  289. var funcs = {
  290. generator: function() {
  291. return 9
  292. },
  293. change: function(val) {
  294. expect(val).toBe(9)
  295. }
  296. }
  297. var generatorSpy = spyOn(funcs, 'generator').and.callThrough()
  298. var changeSpy = spyOn(funcs, 'change').and.callThrough()
  299. var m = new Model()
  300. m.on('change:myid', funcs.change)
  301. m.watch('myid', [], funcs.generator)
  302. expect(generatorSpy).toHaveBeenCalled()
  303. expect(changeSpy).toHaveBeenCalled()
  304. expect(m.has('myid')).toBe(true)
  305. expect(m.get('myid')).toBe(9)
  306. })
  307. })
  308. describe('when all deps already satisfied', function() {
  309. it('resolves immediately', function() {
  310. var funcs = {
  311. generator: function(deps) {
  312. return deps.myvar + deps.myothervar
  313. }
  314. }
  315. var spy = spyOn(funcs, 'generator').and.callThrough()
  316. var m = new Model()
  317. m.set({
  318. myvar: 5,
  319. myothervar: 6
  320. })
  321. m.watch('myid', [ 'myvar', 'myothervar' ], funcs.generator)
  322. expect(spy).toHaveBeenCalled()
  323. expect(m.has('myid')).toBe(true)
  324. expect(m.get('myid')).toBe(11)
  325. })
  326. })
  327. describe('when not all deps satisfied', function() {
  328. it('resolves only after all deps are set', function() {
  329. var funcs = {
  330. generator: function(deps) {
  331. return deps.myvar + deps.myothervar
  332. }
  333. }
  334. var spy = spyOn(funcs, 'generator').and.callThrough()
  335. var m = new Model()
  336. m.set('myvar', 5)
  337. m.watch('myid', [ 'myvar', 'myothervar' ], funcs.generator)
  338. expect(spy).not.toHaveBeenCalled()
  339. expect(m.has('myid')).toBe(false)
  340. m.set('myothervar', 6)
  341. expect(spy).toHaveBeenCalled()
  342. expect(m.has('myid')).toBe(true)
  343. expect(m.get('myid')).toBe(11)
  344. })
  345. describe('when watching an instance', function() {
  346. it('resolves only after final async dep resolves', function(done) {
  347. var funcs = {
  348. generator: function(deps) {
  349. return deps.myvar + deps.myothervar
  350. }
  351. }
  352. var spy = spyOn(funcs, 'generator').and.callThrough()
  353. var m = new Model()
  354. m.set('myvar', 5)
  355. m.watch('myothervar', [ 'myvar' ], function(deps) {
  356. var deferred = $.Deferred()
  357. setTimeout(function() {
  358. deferred.resolve(deps.myvar * 2)
  359. }, 100)
  360. return deferred.promise()
  361. })
  362. m.watch('myid', [ 'myvar', 'myothervar' ], funcs.generator)
  363. expect(spy).not.toHaveBeenCalled()
  364. expect(m.has('myid')).toBe(false)
  365. setTimeout(function() {
  366. expect(spy).toHaveBeenCalled()
  367. expect(m.has('myid')).toBe(true)
  368. expect(m.get('myid')).toBe(15)
  369. done()
  370. }, 200)
  371. })
  372. })
  373. describe('when using class-methods', function() {
  374. it('resolves only after final async dep resolves', function(done) {
  375. var funcs = {
  376. generator: function(deps) {
  377. return deps.myvar + deps.myothervar
  378. }
  379. }
  380. var spy = spyOn(funcs, 'generator').and.callThrough()
  381. var MyClass = Model.extend()
  382. MyClass.watch('myothervar', [ 'myvar' ], function(deps) {
  383. var deferred = $.Deferred()
  384. setTimeout(function() {
  385. deferred.resolve(deps.myvar * 2)
  386. }, 100)
  387. return deferred.promise()
  388. })
  389. MyClass.watch('myid', [ 'myvar', 'myothervar' ], funcs.generator)
  390. var m = new MyClass()
  391. m.set({
  392. myvar: 5
  393. })
  394. expect(spy).not.toHaveBeenCalled()
  395. expect(m.has('myid')).toBe(false)
  396. setTimeout(function() {
  397. expect(spy).toHaveBeenCalled()
  398. expect(m.has('myid')).toBe(true)
  399. expect(m.get('myid')).toBe(15)
  400. done()
  401. }, 200)
  402. })
  403. })
  404. })
  405. })
  406. })
  407. describe('unwatch', function() {
  408. it('calls the stop function and won\'t call the start function again', function() {
  409. var funcs = {
  410. start: function() { },
  411. stop: function() { }
  412. }
  413. var startSpy = spyOn(funcs, 'start')
  414. var stopSpy = spyOn(funcs, 'stop')
  415. var m = new Model()
  416. m.set('myvar', 5)
  417. m.watch('myid', [ 'myvar', 'myothervar' ], funcs.start, funcs.stop)
  418. expect(startSpy).not.toHaveBeenCalled()
  419. m.set('myothervar', 6)
  420. expect(startSpy).toHaveBeenCalledTimes(1)
  421. m.unwatch('myid')
  422. expect(stopSpy).toHaveBeenCalledTimes(1)
  423. // doesn't call it again
  424. m.set('myvar', 5)
  425. expect(startSpy).toHaveBeenCalledTimes(1)
  426. })
  427. })
  428. describe('flash', function() {
  429. describe('if already satisfied', function() {
  430. it('calls stop+start', function() {
  431. var funcs = {
  432. start: function(deps) {
  433. expect(deps.dep1).toBe(6)
  434. },
  435. stop: function() { }
  436. }
  437. var startSpy = spyOn(funcs, 'start').and.callThrough()
  438. var stopSpy = spyOn(funcs, 'stop')
  439. var m = new Model()
  440. m.set({ dep1: 6 })
  441. m.watch('task1', [ 'dep1' ], startSpy, stopSpy)
  442. expect(stopSpy).toHaveBeenCalledTimes(0)
  443. expect(startSpy).toHaveBeenCalledTimes(1)
  444. m.flash('task1')
  445. expect(stopSpy).toHaveBeenCalledTimes(1)
  446. expect(startSpy).toHaveBeenCalledTimes(2)
  447. })
  448. })
  449. describe('if not satisfied', function() {
  450. it('does not call stop+start', function() {
  451. var funcs = {
  452. start: function() { },
  453. stop: function() { }
  454. }
  455. var startSpy = spyOn(funcs, 'start')
  456. var stopSpy = spyOn(funcs, 'stop')
  457. var m = new Model()
  458. m.watch('task1', [ 'dep1' ], startSpy, stopSpy)
  459. expect(stopSpy).toHaveBeenCalledTimes(0)
  460. expect(startSpy).toHaveBeenCalledTimes(0)
  461. m.flash('task1')
  462. expect(stopSpy).toHaveBeenCalledTimes(0)
  463. expect(startSpy).toHaveBeenCalledTimes(0)
  464. })
  465. })
  466. })
  467. })