           new Thread(accountId: 'a', clientId: '1', lastMessageReceivedTimestamp: 1),
         ]
         mustUpdate: true
-        mustRefetchAllIds: false
       },{
         name: 'Item not in set deleted'
         change:

          new Thread(accountId: 'a', clientId: '3', lastMessageReceivedTimestamp: 3),
          new Thread(accountId: 'a', clientId: '2', lastMessageReceivedTimestamp: 2),
        ]
        mustUpdate: false
        mustTrigger: true
        mustRefetchAllIds: true
      },{
        name: 'Item saved - does not match query clauses, offset > 0'
        change:

            subscription._updateInFlight = false
            subscription.applyChangeRecord(test.change)

            if test.mustUpdate
              expect(subscription.update).toHaveBeenCalledWith({mustRefetchEntireRange: true})
            else
              if test.nextModels is 'unchanged'
                expect(subscription._set.models()).toEqual(scenario.lastModels)
              else
                expect(subscription._set.models()).toEqual(test.nextModels)

            if test.mustTriger
              expect(subscription._createResultAndTrigger).toHaveBeenCalled()

  describe "update", ->
    beforeEach ->
      spyOn(QuerySubscription.prototype, '_fetchRange').andCallFake ->
        @_set ?= new MutableQueryResultSet()
        Promise.resolve()

    describe "when the query has an infinite range", ->
      it "should call _fetchRange for the entire range", ->
        subscription = new QuerySubscription(DatabaseStore.findAll(Thread))
        subscription.update()
        advanceClock()
        expect(subscription._fetchRange).toHaveBeenCalledWith(QueryRange.infinite(), {fetchEntireModels: true, version: 1})

      it "should fetch full full models only when the previous set is empty", ->
        subscription = new QuerySubscription(DatabaseStore.findAll(Thread))
