Skip to content

Instantly share code, notes, and snippets.

@searls
Created February 10, 2012 15:35
Show Gist options
  • Select an option

  • Save searls/1790322 to your computer and use it in GitHub Desktop.

Select an option

Save searls/1790322 to your computer and use it in GitHub Desktop.
class App.CollectionView extends App.SerializableView
constructor: (options) ->
@bind('rendered', => @__renderItems() unless @__itemsHaveBeenInitiallyRendered)
super(options)
@collection.bind('add',@__renderAddedItem)
ensureAtLeastOneItem: =>
if @collection.size() == 0
@collection.add({})
#private
__renderItems: =>
@collection.each (item) =>
@__renderItem(item) unless @skipItemsThat?(item)
@__itemsHaveBeenInitiallyRendered = true
@
__renderItem: (item) =>
itemView = new @itemViewType(model: item)
$item = $(itemView.render().el)
if @wrapItemsIn?
$item = $(@wrapItemsIn).clone().append($item)
if @itemContainerSelector
@$(@itemContainerSelector).append($item)
else
@$el.append($item)
itemView
__renderAddedItem: (item) =>
if @__itemsHaveBeenInitiallyRendered
itemView = @__renderItem(item)
@trigger('rendered')
@trigger('rendered:item',itemView)
__serialize: ->
if _(@serialize).isFunction()
@serialize()
else if @serialize
@serialize
JST.mouth = ->
class ToothView extends Backbone.View
render: ->
@$el.html('<div class="tooth"></div>')
@
class MouthView extends App.CollectionView
#Required
template: "mouth"
itemContainerSelector: ".teeth"
itemViewType: ToothView
#Optional
serialize: -> "SERIALIZED"
wrapItemsIn: $('<li class="gums"></li>')
describe "App.CollectionView", ->
Given -> @tooth = new Backbone.Model
Given -> @collection = new Backbone.Collection(@tooth)
Given -> @subject = new MouthView(collection: @collection)
describe "#render", ->
Given -> @renderedWasFired = false
And -> @subject.bind('rendered', => @renderedWasFired = true)
And -> spyOn(_,'defer').andCallFake (f) -> f() #this defer is necessary b/c of layoutmanager
lastToothView = null
Given -> ToothView.prototype.initialize = -> lastToothView = this
context "in a layoutmanager view", ->
Given -> @subject.$el.affix('.teeth')
Given -> @layout = jasmine.createSpy().when(@subject).thenReturn
render: jasmine.createSpy().when("SERIALIZED").thenReturn $.Deferred().resolve()
When -> @subject.render(@layout)
Then -> lastToothView.model == @tooth
Then -> expect(@subject.$el).toContain(".tooth")
Then -> @renderedWasFired == true
context "in a standalone view", ->
context "typical case", ->
Given -> spyOn(JST, "mouth").when("SERIALIZED").thenReturn('<div class="teeth"></div>')
When -> @result = @subject.render()
Then -> @result == @subject
Then -> lastToothView.model == @tooth
Then -> expect(@subject.$el).toContain("li.gums .tooth")
Then -> @renderedWasFired == true
context "~adding one new item", ->
Given -> @subject.bind("rendered:item",@renderedItemWasFired = jasmine.createSpy())
Given -> @renderedItemCaptor = jasmine.captor()
Given -> spyOn(@subject, "render")
Given -> @renderedWasFired = false
When -> @newTooth = @collection.add({}).last()
Then -> expect(@subject.render).not.toHaveBeenCalled()
Then -> expect(@subject.$('.tooth').length).toBe(2)
Then -> @renderedWasFired == true
Then( -> expect(@renderedItemWasFired).toHaveBeenCalledWith(@renderedItemCaptor.capture()))
.Then( -> expect(@renderedItemCaptor.value).toBeInstanceOf(ToothView))
.Then( -> expect(@renderedItemCaptor.value.model).toBe(@newTooth))
context "no serialize method", ->
Given -> @subject.serialize = null
Given -> spyOn(JST, "mouth").andReturn('<div class="teeth"></div>')
When -> @subject.render()
Then -> expect(@subject.$el).toContain(".tooth")
context "no itemContainerSelector", ->
Given -> @subject.itemContainerSelector = null
Given -> spyOn(JST, "mouth").andReturn('')
When -> @subject.render()
Then -> expect(@subject.$el).toContain(".tooth")
context "not wrapping items", ->
Given -> delete @subject['wrapItemsIn']
Given -> spyOn(JST, "mouth").andReturn('<div class="teeth"></div>')
When -> @subject.render()
Then -> expect(@subject.$el).toContain(".tooth")
context "#skipItemsThat", ->
Given -> @subject.skipItemsThat = (item) -> item.get('molar') == true
Given -> @collection.add({molar: true})
Given -> spyOn(JST, "mouth").andReturn('<div class="teeth"></div>')
When -> @subject.render()
Then -> expect(@subject.$('.tooth').length).toBe(1)
describe "#ensureAtLeastOneItem", ->
Given -> @collection.remove(@tooth)
When -> @subject.ensureAtLeastOneItem()
Then -> @collection.size() == 1
Then -> @collection.first() != @tooth
describe "~removing when bound", ->
Given -> @collection.bind('remove', @subject.ensureAtLeastOneItem)
When -> @collection.remove(@tooth)
Then -> @collection.size() == 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment