_ = require 'underscore' EventEmitter = require('events').EventEmitter ModelView = require '../src/flux/stores/model-view' # ModelView is an abstract base class. Basic implementation for tests class TestModelView extends ModelView constructor: -> super @_pageSize = 100 count: -> 1000 stubFillPage: (page) -> letter = ['A','B','C','D','E','F','G','H','I','J'][page] items = [] items.push({id: "#{letter}#{ii}"}) for ii in [0..99] @_pages[page] = loading: false items: items retrievePage: (page) -> @_pages[page] = items: [] loading: true setTimeout -> @stubFillPage(page) , 1 describe "ModelView", -> beforeEach -> @view = new TestModelView() describe "setRetainedRange", -> it "should perform basic bounds checks to avoid fetching non-existent pages", -> @view.setRetainedRange({start: -100, end: 15000}) expect(@view._retainedRange).toEqual({start:0, end: @view.count()}) it "should call the padding method to optionally expand the retained range", -> spyOn(@view, 'padRetainedRange').andCallFake ({start, end}) -> {start: start - 50, end: end + 50} @view.setRetainedRange({start: 0, end: 100}) expect(@view._retainedRange).toEqual({start:0, end: 150}) it "should retrieve pages in the range that are not cached", -> spyOn(@view, 'retrievePage').andCallThrough() @view.setRetainedRange({start: 0, end: 250}) expect(@view.retrievePage.callCount).toBe(3) expect(@view.retrievePage.calls[0].args).toEqual([0]) expect(@view.retrievePage.calls[1].args).toEqual([1]) expect(@view.retrievePage.calls[2].args).toEqual([2]) it "should not retrieve pages that are already cached", -> @view.stubFillPage(0) @view.stubFillPage(1) spyOn(@view, 'retrievePage').andCallThrough() @view.setRetainedRange({start: 0, end: 250}) expect(@view.retrievePage.callCount).toBe(1) expect(@view.retrievePage.calls[0].args).toEqual([2]) it "should call cullPages(), allowing subclasses to remove unneeded pages from the cache", -> spyOn(@view, 'cullPages') @view.setRetainedRange({start: 0, end: 250}) expect(@view.cullPages).toHaveBeenCalled() describe "accessors", -> beforeEach -> @view.stubFillPage(0) @view.stubFillPage(1) describe "loaded", -> it "should return true if all of the retained pages are loaded", -> @view.setRetainedRange({start: 0, end: 100}) expect(@view.loaded()).toBe(true) it "should return false if any retained pages are still loading", -> @view.setRetainedRange({start: 0, end: 300}) expect(@view.loaded()).toBe(false) describe "get", -> it "should return the item at the index provided", -> expect(@view.get(12).id).toBe('A12') expect(@view.get(112).id).toBe('B12') it "should return null if the item cannot be found", -> expect(@view.get(12154)).toBe(null) it "should throw an exception if the user passes something other than an integer index", -> expect(( => @view.get('oops an id'))).toThrow() describe "getById", -> it "should return the item with the requested id", -> expect(@view.getById('A88')).toEqual({id: 'A88'}) expect(@view.getById('B12')).toEqual({id: 'B12'}) it "should return null if the item cannot be found", -> expect(@view.getById('E12')).toEqual(null) it "should return null if no id is provided", -> expect(@view.getById(undefined)).toEqual(null) describe "indexOfId", -> it "should return the index of the item with the id", -> expect(@view.indexOfId('A88')).toEqual(88) expect(@view.indexOfId('B12')).toEqual(100 * 1 + 12) it "should return -1 if the item cannot be found", -> expect(@view.indexOfId('E12')).toEqual(-1) it "should return -1 if no id is provided", -> expect(@view.indexOfId(undefined)).toEqual(-1) describe "pagesRetained", -> it "should return an array of page indexes currently being maintained", -> @view._retainedRange = {start: 0, end: 99} expect(@view.pagesRetained()).toEqual([0]) @view._retainedRange = {start: 0, end: 340} expect(@view.pagesRetained()).toEqual([0..3]) @view._retainedRange = {start: 900, end: 999} expect(@view.pagesRetained()).toEqual([9]) describe "invalidateRetainedRange", -> it "should initiate requests for all the pages in the retained range", -> spyOn(@view, 'retrievePage') @view._retainedRange = {start: 0, end: 340} @view.invalidateRetainedRange() expect(@view.retrievePage.callCount).toBe(4) for i in [0..3] expect(@view.retrievePage.calls[i].args).toEqual([i])