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