SuperModel = require 'models/SuperModel' User = require 'models/User' ComponentsCollection = require 'collections/ComponentsCollection' factories = require 'test/app/factories' describe 'SuperModel', -> describe '.trackRequest(jqxhr, value)', -> it 'takes a jqxhr and tracks its progress', (done) -> s = new SuperModel() jqxhrA = $.get('/db/a') reqA = jasmine.Ajax.requests.mostRecent() jqxhrB = $.get('/db/b') reqB = jasmine.Ajax.requests.mostRecent() s.trackRequest(jqxhrA, 1) s.trackRequest(jqxhrB, 3) expect(s.progress).toBe(0) reqA.respondWith({status: 200, responseText: '[]'}) _.defer -> expect(s.progress).toBe(0.25) reqB.respondWith({status: 200, responseText: '[]'}) _.defer -> expect(s.progress).toBe(1) done() describe 'progress (property)', -> it 'is finished by default', -> s = new SuperModel() expect(s.finished()).toBeTruthy() it 'is based on resource completion and value', (done) -> s = new SuperModel() r1 = s.addSomethingResource('???', 2) r2 = s.addSomethingResource('???', 3) expect(s.progress).toBe(0) r1.markLoaded() # progress updates are deferred so defer more _.defer -> expect(s.progress).toBe(0.4) r2.markLoaded() _.defer -> expect(s.progress).toBe(1) done() describe 'loadModel (function)', -> it 'starts loading the model if it isn\'t already loading', -> s = new SuperModel() m = new User({_id: '12345'}) s.loadModel(m) request = jasmine.Ajax.requests.mostRecent() expect(request).toBeDefined() it 'also loads collections', -> s = new SuperModel() c = new ComponentsCollection() s.loadModel(c) request = jasmine.Ajax.requests.mostRecent() expect(request).toBeDefined() describe 'timeout handling', -> beforeEach -> jasmine.clock().install() afterEach -> jasmine.clock().uninstall() it 'automatically retries stalled requests', -> s = new SuperModel() m = new User({_id: '12345'}) s.loadModel(m) timeUntilRetry = 5000 # Retry request 5 times for timesTried in [1..5] expect(s.failed).toBeFalsy() expect(s.resources[1].loadsAttempted).toBe(timesTried) expect(jasmine.Ajax.requests.all().length).toBe(timesTried) jasmine.clock().tick(timeUntilRetry) timeUntilRetry *= 1.5 # And then stop retrying expect(s.resources[1].loadsAttempted).toBe(5) expect(jasmine.Ajax.requests.all().length).toBe(5) expect(s.failed).toBe(true) it 'stops retrying once the model loads', (done) -> s = new SuperModel() m = new User({_id: '12345'}) s.loadModel(m) timeUntilRetry = 5000 # Retry request 2 times for timesTried in [1..2] expect(s.failed).toBeFalsy() expect(s.resources[1].loadsAttempted).toBe(timesTried) expect(jasmine.Ajax.requests.all().length).toBe(timesTried) jasmine.clock().tick(timeUntilRetry) timeUntilRetry *= 1.5 # Respond to the third reqest expect(s.finished()).toBeFalsy() expect(s.failed).toBeFalsy() request = jasmine.Ajax.requests.mostRecent() request.respondWith({status: 200, responseText: JSON.stringify(factories.makeUser({ _id: '12345' }).attributes)}) _.defer -> expect(s.finished()).toBe(true) expect(s.failed).toBeFalsy() # It shouldn't send any more requests after loading expect(s.resources[1].loadsAttempted).toBe(3) expect(jasmine.Ajax.requests.all().length).toBe(3) jasmine.clock().tick(60000) expect(s.resources[1].loadsAttempted).toBe(3) expect(jasmine.Ajax.requests.all().length).toBe(3) done() describe 'events', -> it 'triggers "loaded-all" when finished', (done) -> s = new SuperModel() m = new User({_id: '12345'}) triggered = false s.once 'loaded-all', -> triggered = true s.loadModel(m) request = jasmine.Ajax.requests.mostRecent() request.respondWith({status: 200, responseText: '{}'}) _.defer -> expect(triggered).toBe(true) done() describe 'collection loading', -> it 'combines models which are fetched from multiple sources', -> s = new SuperModel() c1 = new ComponentsCollection() c1.url = '/db/level.component?v=1' s.loadCollection(c1, 'components') c2 = new ComponentsCollection() c2.url = '/db/level.component?v=2' s.loadCollection(c2, 'components') request = jasmine.Ajax.requests.sendResponses({ '/db/level.component?v=1': [{"_id":"id","name":"Something"}] '/db/level.component?v=2': [{"_id":"id","description":"This is something"}] }) expect(s.models['/db/level.component/id'].get('name')).toBe('Something') expect(s.models['/db/level.component/id'].get('description')).toBe('This is something')