New QueryRange specs, fixes

This commit is contained in:
Ben Gotow 2016-01-14 12:03:06 -08:00
parent 9814d80d5a
commit 88b901d8a5
5 changed files with 103 additions and 10 deletions

View file

@ -70,7 +70,7 @@ describe "MutableQueryResultSet", ->
'C': {id: 'C', clientId: 'C-local'},
})
describe "addIdsInRange", ->
fdescribe "addIdsInRange", ->
describe "when the set is currently empty", ->
it "should set the result set to the provided one", ->
@set = new MutableQueryResultSet()
@ -101,10 +101,13 @@ describe "MutableQueryResultSet", ->
@set.addIdsInRange(['0', '1', '2'], new QueryRange(offset: 2, limit: 3))
.not.toThrow()
it "should throw an exception if the range provided and the ids provided are different lengths", ->
expect =>
@set.addIdsInRange(['F', 'G', 'H'], new QueryRange(offset: 10, limit: 5))
.toThrow()
it "should work if the IDs array is shorter than the result range they represent (addition)", ->
@set.addIdsInRange(['F', 'G', 'H'], new QueryRange(offset: 10, limit: 5))
expect(@set.ids()).toEqual(['A','B','C','D','E', 'F', 'G', 'H'])
it "should work if the IDs array is shorter than the result range they represent (replacement)", ->
@set.addIdsInRange(['A', 'B', 'C'], new QueryRange(offset: 5, limit: 5))
expect(@set.ids()).toEqual(['A','B','C'])
it "should correctly add ids (trailing) and update the offset", ->
@set.addIdsInRange(['F', 'G', 'H'], new QueryRange(offset: 10, limit: 3))

View file

@ -0,0 +1,88 @@
QueryRange = require '../../src/flux/models/query-range'
describe "QueryRange", ->
describe "@infinite", ->
it "should return a query range with a null limit and offset", ->
infinite = QueryRange.infinite()
expect(infinite.limit).toBe(null)
expect(infinite.offset).toBe(null)
describe "@rangesBySubtracting", ->
it "should throw an exception if either range is infinite", ->
infinite = QueryRange.infinite()
expect ->
QueryRange.rangesBySubtracting(infinite, new QueryRange({offset: 0, limit: 10}))
.toThrow()
expect ->
QueryRange.rangesBySubtracting(new QueryRange({offset: 0, limit: 10}), infinite)
.toThrow()
it "should return one or more ranges created by punching the provided range", ->
test = ({a, b, result}) ->
expect(QueryRange.rangesBySubtracting(a, b)).toEqual(result)
test
a: new QueryRange(offset: 0, limit: 10),
b: new QueryRange(offset: 3, limit: 3),
result: [new QueryRange(offset: 0, limit: 3), new QueryRange(offset: 6, limit: 4)]
test
a: new QueryRange(offset: 0, limit: 10),
b: new QueryRange(offset: 3, limit: 10),
result: [new QueryRange(offset: 0, limit: 3)]
test
a: new QueryRange(offset: 0, limit: 10),
b: new QueryRange(offset: 0, limit: 10),
result: []
test
a: new QueryRange(offset: 5, limit: 10),
b: new QueryRange(offset: 0, limit: 4),
result: [new QueryRange(offset: 5, limit: 10)]
test
a: new QueryRange(offset: 5, limit: 10),
b: new QueryRange(offset: 0, limit: 8),
result: [new QueryRange(offset: 8, limit: 7)]
describe "isInfinite", ->
it "should return true for an infinite range, false otherwise", ->
infinite = QueryRange.infinite()
expect(infinite.isInfinite()).toBe(true)
expect(new QueryRange(offset:0, limit:4).isInfinite()).toBe(false)
describe "start", ->
it "should be an alias for offset", ->
expect((new QueryRange(offset:3, limit:4)).start).toBe(3)
describe "end", ->
it "should be offset + limit", ->
expect((new QueryRange(offset:3, limit:4)).end).toBe(7)
describe "isContiguousWith", ->
it "should return true if either range is infinite", ->
a = new QueryRange(offset:3, limit:4)
expect(a.isContiguousWith(QueryRange.infinite())).toBe(true)
expect(QueryRange.infinite().isContiguousWith(a)).toBe(true)
it "should return true if the ranges intersect or touch, false otherwise", ->
a = new QueryRange(offset:3, limit:4)
b = new QueryRange(offset:0, limit:2)
c = new QueryRange(offset:0, limit:3)
d = new QueryRange(offset:7, limit:10)
e = new QueryRange(offset:8, limit:10)
# True
expect(a.isContiguousWith(d)).toBe(true)
expect(d.isContiguousWith(a)).toBe(true)
expect(a.isContiguousWith(c)).toBe(true)
expect(c.isContiguousWith(a)).toBe(true)
# False
expect(a.isContiguousWith(b)).toBe(false)
expect(b.isContiguousWith(a)).toBe(false)
expect(a.isContiguousWith(e)).toBe(false)
expect(e.isContiguousWith(a)).toBe(false)
expect(b.isContiguousWith(e)).toBe(false)
expect(e.isContiguousWith(b)).toBe(false)

View file

@ -53,7 +53,7 @@ class MutableQueryResultSet extends QueryResultSet
existingBefore = @_ids.slice(0, range.offset - @_offset)
existingAfter = []
if currentEnd > rangeIdsEnd
if rangeIds.length is range.limit and currentEnd > rangeIdsEnd
existingAfter = @_ids.slice(rangeIdsEnd - @_offset)
@_ids = [].concat(existingBefore, rangeIds, existingAfter)

View file

@ -4,8 +4,8 @@ class QueryRange
@rangeWithUnion: (a, b) ->
return QueryRange.infinite() if a.isInfinite() or b.isInfinite()
if not a.intersects(b)
throw new Error('You cannot union ranges which do not overlap.')
if not a.isContiguousWith(b)
throw new Error('You cannot union ranges which do not touch or intersect.')
new QueryRange
start: Math.min(a.start, b.start)
@ -48,7 +48,9 @@ class QueryRange
isEqual: (b) ->
return @start is b.start and @end is b.end
intersects: (b) ->
# Returns true if joining the two ranges would not result in empty space.
# ie: they intersect or touch
isContiguousWith: (b) ->
return true if @isInfinite() or b.isInfinite()
return @start <= b.start <= @end or @start <= b.end <= @end

View file

@ -141,7 +141,7 @@ class QuerySubscription
rangeQuery ?= @_query
DatabaseStore.run(rangeQuery, {format: false}).then (results) =>
@_set = null unless @_set?.range().intersects(range)
@_set = null unless @_set?.range().isContiguousWith(range)
@_set ?= new MutableQueryResultSet()
if entireModels