PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/test/test.coffee

http://github.com/beastridge/viewjs
CoffeeScript | 441 lines | 377 code | 50 blank | 14 comment | 2 complexity | 3029b2f582f0033aab08c18c50f9f4c0 MD5 | raw file
  1. assert = require 'assert'
  2. {jsdom} = require 'jsdom'
  3. document = jsdom '<html><head></head><body></body></html>'
  4. global.window = document.createWindow()
  5. {View,Builder,Router,RouteResolver} = require __dirname + '/../lib/view.js'
  6. jQuery = require 'jquery'
  7. Backbone = require 'backbone'
  8. global.Backbone = Backbone
  9. array_from = (object) ->
  10. return [] if not object
  11. length = object.length or 0
  12. results = new Array length
  13. while length--
  14. results[length] = object[length]
  15. results
  16. View.extend
  17. document: document
  18. module.exports.parses = ->
  19. assert.ok(true)
  20. module.exports.stack = (before_exit) ->
  21. i = 0
  22. sequence = []
  23. {StackView} = View.create
  24. StackView:
  25. stack:initialize:add: (next) ->
  26. sequence.push 'a'
  27. @a = 'a'
  28. ++i
  29. next()
  30. StackView.extend stack:initialize:add: (next) ->
  31. sequence.push 'b'
  32. @b = 'b'
  33. ++i
  34. next()
  35. StackView.initialize ->
  36. before_exit ->
  37. assert.equal StackView._stack.initialize.stack.length, 3
  38. assert.equal 2, i
  39. assert.equal StackView.a, 'a'
  40. assert.equal StackView.b, 'b'
  41. assert.equal sequence[0], 'a'
  42. assert.equal sequence[1], 'b'
  43. module.exports.canDeferViewManagerCallback = ->
  44. call_count = 0
  45. View QuantumView: ->
  46. ++call_count
  47. View.create QuantumView: {}
  48. assert.equal call_count, 1
  49. module.exports.canTriggerEvents = ->
  50. {TestView} = View.create TestView: {}
  51. i = 0
  52. TestView.bind 'test', -> ++i
  53. TestView.trigger 'test'
  54. assert.equal i, 1
  55. module.exports.canDetectModel = (before_exit) ->
  56. _model = false
  57. model = new Backbone.Model
  58. model.set key: 'value'
  59. {ModelView} = View.create ModelView:
  60. model: model
  61. initialize: (next) ->
  62. _model = @model
  63. next()
  64. ModelView.initialize -> before_exit ->
  65. assert.equal ModelView.model, model
  66. assert.equal _model, model
  67. module.exports.canDetectCollection = (before_exit) ->
  68. _collection = false
  69. collection = new Backbone.Collection
  70. {CollectionView} = View.create CollectionView:
  71. collection: collection
  72. initialize: (next) ->
  73. _collection = @collection
  74. next()
  75. CollectionView.initialize ->
  76. before_exit ->
  77. assert.equal CollectionView.collection, collection
  78. assert.equal CollectionView.collection, _collection
  79. module.exports.canRender = ->
  80. {BuilderView} = View.create BuilderView: [Builder,
  81. render: ->
  82. @p 'test'
  83. on:ready: ->
  84. assert.equal @[0].firstChild.innerHTML, 'test'
  85. ]
  86. View BuilderView: -> @initialize()
  87. module.exports.canRenderCollection = ->
  88. Item = Backbone.Model.extend()
  89. List = new (Backbone.Collection.extend(model: Item))
  90. render_count = 0
  91. contents = [
  92. {content: 'One'}
  93. {content: 'Two'}
  94. {content: 'Three'}
  95. ]
  96. List.add array_from contents
  97. {ListView} = View.create ListView:
  98. collection: List
  99. element: -> @tag 'ul'
  100. render: (item) ->
  101. ++render_count
  102. @tag 'li', item.get 'content'
  103. ListView.initialize ->
  104. assert.equal @[0].tagName.toLowerCase(), 'ul'
  105. assert.equal render_count, 3
  106. assert.equal ListView[0].childNodes.length, 3
  107. assert.equal ListView[0].firstChild.innerHTML, 'One'
  108. List.remove List.at(0)
  109. assert.equal render_count, 3
  110. assert.equal ListView[0].childNodes.length, 2
  111. assert.equal ListView[0].firstChild.innerHTML, 'Two'
  112. List.add content: 'Four'
  113. assert.equal render_count, 4
  114. assert.equal ListView[0].childNodes.length, 3
  115. assert.equal ListView[0].firstChild.innerHTML, 'Two'
  116. assert.equal ListView[0].childNodes[2].innerHTML, 'Four'
  117. List.refresh contents
  118. assert.equal render_count, 7
  119. assert.equal ListView[0].childNodes.length, 3
  120. assert.equal ListView[0].firstChild.innerHTML, 'One'
  121. assert.equal ListView[0].childNodes[2].innerHTML, 'Three'
  122. module.exports.viewManager = ->
  123. View.create TestView2: key: 'value'
  124. View.create TestView3: key: 'value2'
  125. [TestView2,TestView3] = View ['TestView2', 'TestView3']
  126. assert.equal TestView2.key, 'value'
  127. assert.equal TestView3.key, 'value2'
  128. module.exports.canUseCreateAsCallback = ->
  129. instance = View.create ->
  130. @key = 'value'
  131. assert.equal instance.key, 'value'
  132. module.exports.canDepend = ->
  133. sequence = []
  134. View.create
  135. ParentView:
  136. views: ['ChildView1','ChildView2','ChildView3']
  137. initialize: (next) ->
  138. assert.equal @ChildView1.name, 'ChildView1'
  139. assert.equal @ChildView2.name, 'ChildView2'
  140. assert.equal @ChildView3.name, 'ChildView3'
  141. next()
  142. ChildView1:
  143. name: 'ChildView1'
  144. render: ->
  145. sequence.push 'a'
  146. @document.createElement 'div'
  147. ChildView2:
  148. name: 'ChildView2'
  149. render: ->
  150. sequence.push 'b'
  151. @document.createElement 'div'
  152. ChildView3:
  153. name: 'ChildView3'
  154. render: ->
  155. sequence.push 'c'
  156. @document.createElement 'div'
  157. View ParentView: ->
  158. @initialize()
  159. @on ready: ->
  160. assert.equal sequence[0], 'a'
  161. assert.equal sequence[1], 'b'
  162. assert.equal sequence[2], 'c'
  163. module.exports.canDependAsync = (before_exit) ->
  164. View.create
  165. AsyncParentView: [Builder,
  166. views: ['AsyncChildView1','AsyncChildView2']
  167. initialize: (next) ->
  168. setTimeout next, 50
  169. render: ->
  170. @ul @AsyncChildView1, @AsyncChildView2
  171. ]
  172. AsyncChildView1: [Builder,
  173. initialize: (next) ->
  174. setTimeout next, 1
  175. render: ->
  176. @li 'A'
  177. ]
  178. AsyncChildView2: [Builder,
  179. initialize: (next) ->
  180. setTimeout next, 100
  181. render: ->
  182. @li 'B'
  183. ]
  184. View AsyncParentView: ->
  185. @initialize()
  186. @on ready: ->
  187. before_exit =>
  188. assert.equal jQuery('li:first',@[0]).html(), 'A'
  189. module.exports.canPassViewsToBuilder = ->
  190. {OuterView} = View.create OuterView: [Builder,
  191. initialize: (next) ->
  192. InnerView.on ready: next
  193. InnerView.initialize()
  194. render: ->
  195. @div InnerView, class: 'test'
  196. on:ready: ->
  197. assert.equal @[0].firstChild.firstChild.firstChild.innerHTML, 'test'
  198. ]
  199. {InnerView} = View.create InnerView: [Builder,
  200. render: ->
  201. @p 'test'
  202. ]
  203. OuterView.initialize()
  204. module.exports.canDiscardMixin = ->
  205. View.extend extend:discard: (value,discard) ->
  206. @discard = value
  207. discard()
  208. {DiscardView} = View.create
  209. DiscardView: {}
  210. DiscardView.extend
  211. discard: 'discard'
  212. {DiscardChildView} = DiscardView.create DiscardChildView: {}
  213. assert.equal DiscardView.discard, 'discard'
  214. assert.equal typeof DiscardChildView.discard, 'undefined'
  215. module.exports.canObserveKeyChanges = ->
  216. _a = ''
  217. _b = ''
  218. _c = ''
  219. {KeyChangeView} = View.create KeyChangeView:
  220. on:
  221. change:
  222. a: (a) -> _a = a
  223. b: (b) -> _b = b
  224. KeyChangeView.bind 'change:c', (c) -> _c = c
  225. KeyChangeView.set a: 'a', b: 'b', c: 'c'
  226. assert.equal _a, 'a'
  227. assert.equal _b, 'b'
  228. assert.equal _c, 'c'
  229. module.exports.canHaveDefaults = ->
  230. {DefaultsView} = View.create DefaultsView:
  231. defaults:
  232. key: 'value'
  233. assert.equal DefaultsView.get('key'), 'value'
  234. assert.equal DefaultsView.create().get('key'), 'value'
  235. module.exports.canUseArrayInBuilder = (before_exit) ->
  236. {ArrayBuilderViewA,ArrayBuilderViewB,ArrayBuilderViewC} = View.create
  237. ArrayBuilderViewA:
  238. views: ['ArrayBuilderViewB','ArrayBuilderViewC']
  239. render: ->
  240. @tag 'ul', [@ArrayBuilderViewB,@ArrayBuilderViewC]
  241. ArrayBuilderViewB:
  242. render: ->
  243. @tag 'li', 'b'
  244. ArrayBuilderViewC:
  245. render: ->
  246. @tag 'li', 'c'
  247. ArrayBuilderViewA.initialize ->
  248. before_exit =>
  249. assert.ok @[0].firstChild.firstChild?
  250. assert.equal @[0].firstChild.firstChild.firstChild.innerHTML, 'b'
  251. module.exports.router = (before_exit) ->
  252. #initial call sets
  253. View.extend routes: {
  254. '/': 'IndexView'
  255. '/post/:id?': 'PostView'
  256. '/:a/:b/:c?': 'AlphabetView'
  257. }
  258. #views should be auto assigned routes after they are created
  259. #if they didn't exist at the time the router was called
  260. post_view_render_count = 0
  261. index_view_render_count = 0
  262. {PostView,IndexView,ContainerView} = View.create
  263. SidebarView:
  264. render: ->
  265. @tag 'div', class: 'sidebar'
  266. PostView:
  267. on:
  268. change:id: ->
  269. @render()
  270. render: ->
  271. ++post_view_render_count
  272. @tag 'div', 'post'
  273. IndexView:
  274. render: ->
  275. ++index_view_render_count
  276. @tag 'div', 'index'
  277. ContainerView: [Router,
  278. views: ['SidebarView']
  279. render: ->
  280. element = @tag('div'
  281. @SidebarView
  282. @tag('div',
  283. @Router
  284. )
  285. )
  286. element
  287. ]
  288. AlphabetView: {}
  289. #can turn a url into parsed view and params
  290. #can turn an object with params into a url
  291. assert.deepEqual '/post/5', RouteResolver PostView: id: 5
  292. assert.deepEqual {PostView: id: "5"}, RouteResolver '/post/5'
  293. assert.deepEqual '/', RouteResolver IndexView: {}
  294. assert.deepEqual {IndexView: {}}, RouteResolver '/'
  295. assert.deepEqual {AlphabetView: {a:'a',b:'b',c:'c'}}, RouteResolver '/a/b/c'
  296. assert.deepEqual {AlphabetView: {a:'a',b:'b',c:'c'}}, RouteResolver '/a/b/c'
  297. assert.deepEqual '/a/b/', RouteResolver {AlphabetView: {a:'a',b:'b'}}
  298. #router can resolve ordered params
  299. assert.equal '/a/b/c', RouteResolver(AlphabetView: ['a','b','c'])
  300. #view can generate a url for itself
  301. assert.equal '/post/5', PostView.url id: 5
  302. assert.equal '/', IndexView.url()
  303. assert.equal '/post/5', IndexView.url PostView: id: 5
  304. assert.equal '/', RouteResolver 'IndexView'
  305. #should have route auto set
  306. callback_count = 0
  307. ContainerView.initialize ->
  308. #use as dispatcher
  309. RouteResolver '/post/5', (view,params) ->
  310. #callback should only be called after
  311. assert.equal view.get('id'), '5'
  312. assert.ok PostView.element().style.display isnt 'none'
  313. assert.ok IndexView.element().style.display is 'none'
  314. ++callback_count
  315. #dispatcher can take object argument
  316. RouteResolver {IndexView: {}}, (view,params) ->
  317. assert.ok IndexView.element().style.display isnt 'none'
  318. assert.ok PostView.element().style.display is 'none'
  319. ++callback_count
  320. #dispatcher can take ordered param argument
  321. RouteResolver {PostView:['4']}, (view,params) ->
  322. assert.equal view.get('id'), '4'
  323. assert.ok PostView.element().style.display isnt 'none'
  324. assert.ok IndexView.element().style.display is 'none'
  325. ++callback_count
  326. #IndexView should not re-render
  327. RouteResolver {IndexView: {}}, (view,params) ->
  328. assert.ok IndexView.element().style.display isnt 'none'
  329. assert.ok PostView.element().style.display is 'none'
  330. ++callback_count
  331. #default logic of hiding siblings can be disabled
  332. PostView.unbind 'route'
  333. RouteResolver {PostView: id: 4}, (view,params) ->
  334. assert.ok IndexView.element().style.display is 'none'
  335. assert.ok PostView.element().style.display isnt 'none'
  336. ++callback_count
  337. before_exit ->
  338. assert.equal 5, callback_count
  339. assert.equal 4, post_view_render_count
  340. assert.equal 1, index_view_render_count
  341. module.exports.canPassDataInitialize = (before_exit) ->
  342. model = new Backbone.Model
  343. collection = new Backbone.Collection
  344. attributes = {key:'value'}
  345. model_view = View.create()
  346. model_view.initialize model, ->
  347. assert.equal model_view.model, model
  348. collection_view = View.create()
  349. collection_view.initialize collection, ->
  350. assert.equal collection_view.collection, collection
  351. attributes_view = View.create()
  352. attributes_view.initialize attributes, ->
  353. before_exit ->
  354. assert.equal attributes.key, attributes_view.get 'key'
  355. module.exports.canUse$InBuilder = (before_exit) ->
  356. click_count = 0
  357. {$BuilderView} = View.create $BuilderView: [Builder,
  358. $: jQuery
  359. delegate:
  360. 'click div': ->
  361. ++click_count
  362. click:
  363. div: ->
  364. ++click_count
  365. render: ->
  366. @key = 'test'
  367. @table(
  368. @tr(
  369. @td(),
  370. @td(
  371. @div().click =>
  372. ++click_count
  373. assert.equal @key, 'test'
  374. )
  375. )
  376. )
  377. ]
  378. $BuilderView.initialize -> before_exit ->
  379. $BuilderView.$('div').trigger('click')
  380. assert.equal click_count, 3
  381. assert.equal $BuilderView.$('td').length, 2
  382. module.exports.canReverseLookup = ->
  383. {ReverseLookupView} = View.create ReverseLookupView:
  384. $: jQuery
  385. ReverseLookupView.initialize ->
  386. assert.equal jQuery(@).view().name, 'ReverseLookupView'
  387. assert.equal @$.view().name, 'ReverseLookupView'
  388. module.exports.anonViewHasElement = ->
  389. anon = View.create()
  390. assert.ok anon[0]
  391. assert.equal anon[0].tagName, 'DIV'