 
       Rally.environment.getMessageBus().publish(Rally.Message.objectUpdate, Rally.test.mock.ModelObjectMother.getRecord('Release'))
 
-      expect(addContentSpy.callCount).toBe 0
-
-  it "only gets tzOffset and scheduleStates once", ->
+      expect(addContentSpy).not.toHaveBeenCalled()
+
+  it "only calculates timebox info once", ->
     httpGetSpy = @spy(Rally.env.IoProvider.prototype, 'httpGet')
     @_createApp({}).then (app) =>
-
-      addContentSpy = @spy(app, 'addContent')
-      componentReadyListenter = @stub()
-
-      expect(httpGetSpy.callCount).toBe 1
-
-      modelsSpy = @spy(Rally.data.ModelFactory, 'getModels')
-      modelSpy = @spy(Rally.data.ModelFactory, 'getModel')
-
-      messageBus = Rally.environment.getMessageBus()
-      messageBus.subscribe(Rally.BrowserTest.getComponentReadyMessageName(app), componentReadyListenter)
-      messageBus.publish(Rally.Message.objectUpdate, Rally.test.mock.ModelObjectMother.getRecord('HierarchicalRequirement'))
-      @waitForCallback(componentReadyListenter).then =>
-
-        expect(httpGetSpy.callCount).toBe 1
-        expect(addContentSpy.callCount).toBe 1
-
-        # 8 because there are four artifact types getting loaded, and each
-        # one calls getModel twice, if more than 8, then the getModel call
-        # to get schedule states happened again, meaning the test failed
-        expect(modelsSpy).toHaveBeenCalledOnce()
-        expect(modelSpy).not.toHaveBeenCalled()
+      expect(httpGetSpy).toHaveBeenCalledOnce()
+
+      app.calculateTimeboxInfo().then ->
+        expect(httpGetSpy).toHaveBeenCalledOnce()
+
+  it "only gets scheduleStates once", ->
+    scheduleStates = ['Defined', 'In-Progress', 'Completed']
+    ajaxRequest = @ajax.whenQueryingAllowedValues('userstory', 'ScheduleState').respondWith scheduleStates
+    @_createApp({}).then (app) =>
+      expect(scheduleStates).toEqual scheduleStates
+      expect(ajaxRequest).toHaveBeenCalledOnce()
+
+      ajaxRequest = @ajax.whenQueryingAllowedValues('userstory', 'ScheduleState').respondWith ['Defined', 'In-Progress', 'Accepted']
+      app.getScheduleStates().then (scheduleStates2) ->
+        expect(scheduleStates).toEqual scheduleStates
+        expect(ajaxRequest).not.toHaveBeenCalled()
 
   it "rounds estimates to two decimal places", ->
     @ajax.whenQuerying('defectsuite').respondWith()

        }, initialValues)
      })

      app = Ext.create('Rally.apps.iterationsummary.IterationSummaryApp', {
        context:context
      })

      @container.add(app)
      @waitForComponentReady(app)

    _stubApp: (config) ->
      @stub(Rally.apps.iterationsummary.IterationSummaryApp.prototype, 'getScheduleStates')
        .returns(config.scheduleStates || ["Defined", "In-Progress", "Completed", "Accepted"])
      @stub(Rally.apps.iterationsummary.IterationSummaryApp.prototype, 'getStartDate').returns(config.startDate || new Date())
      @stub(Rally.apps.iterationsummary.IterationSummaryApp.prototype, 'getEndDate').returns(config.endDate || new Date())
      @stub(Rally.apps.iterationsummary.IterationSummaryApp.prototype, 'getTzOffset').returns(config.tzOffset || 0)
      @stub(Rally.util.Timebox, 'getToday').returns(config.today || new Date())

    _prepareNoneAcceptedData: ->
      @ajax.whenQuerying('userstory').respondWith([{


      @_createApp({}).then (app) =>

        acceptanceSpy.firstCall.returnValue.then (configAcceptance) ->
          expect(!!configAcceptance.title).toBeFalsy()
          expect(!!configAcceptance.status).toBeFalsy()
          expect(!!configAcceptance.message).toBeFalsy()

          configDefects = defectSpy.firstCall.returnValue
          expect(!!configDefects.title).toBeFalsy()
          expect(!!configDefects.status).toBeFalsy()
          expect(!!configDefects.message).toBeFalsy()

          configTests = testSpy.firstCall.returnValue
          expect(!!configTests.title).toBeFalsy()
          expect(!!configTests.status).toBeFalsy()
          expect(!!configTests.message).toBeFalsy()

    it "displays no alarming acceptance stats when timebox has just started", ->

      @_prepareNoneAcceptedData()

      @_stubApp(
        startDate:new Date(2011, 4, 13)
        endDate:new Date(2011, 4, 20, 23, 59, 59)
        today:new Date(2011, 4, 14)
      )

      acceptanceSpy = @spy(Rally.apps.iterationsummary.IterationSummaryApp.prototype, '_getAcceptanceConfigObject')

      @_createApp({}).then (app) =>

        acceptanceSpy.firstCall.returnValue.always (configAcceptance) ->
          expect(configAcceptance.title).toBe "0% Accepted"
          expect(configAcceptance.subtitle).toBe "(0 of 27 Points)"
          expect(configAcceptance.status).toBe "pending"
          expect(configAcceptance.message).toBe app.self.CURRENT_WITH_NO_ACCEPTED_WORK

    it "does not display defect stats when no active defects for current timebox", ->

      @_prepareNoActiveDefectsData()

      @_stubApp(
        startDate:new Date(2011, 4, 13)
        endDate:new Date(2011, 4, 20, 23, 59, 59)
        today:new Date(2011, 4, 14)
      )

      defectSpy = @spy(Rally.apps.iterationsummary.IterationSummaryApp.prototype, '_getDefectsConfigObject')

      @_createApp({}).then (app) =>

        configDefects = defectSpy.firstCall.returnValue
        expect(!!configDefects.title).toBeFalsy()
        expect(!!configDefects.status).toBeFalsy()
        expect(!!configDefects.message).toBeFalsy()

    it "displays defect stats for current timebox", ->

      @_prepareFiveDefectsData()

      @_stubApp(
        startDate:new Date(2011, 4, 13)
