oomph
Version:
Object Oriented javascript models for the client and the server
957 lines (869 loc) • 82.2 kB
text/coffeescript
Redis = require 'redis'
Promise = require 'promise'
redisObjectClassDataStore = require '../../src/privateModules/redisObjectClassDataStore'
_ = require 'lodash'
_utilities = require '../../src/publicModules/utilities'
ValidationError = require '../../src/models/ValidationError'
describe 'redisObjectClassDataStore', ->
beforeAll (done) ->
@redis = Redis.createClient(1111, 'localhost')
@redis.on "error", ->
throw new Error "Redis server not connected on port 1111 - try running 'redis-server --port 1111 &'"
@redis.on "ready", =>
@redis.flushdb()
done()
@redisObjectClassDataStore = _.clone redisObjectClassDataStore
@redisObjectClassDataStore.name = 'RedisObjectClassDataStore'
@redisObjectClassDataStore.prototype = null
@redisObjectClassDataStore.redis = @redis
@referenceModel = _.clone redisObjectClassDataStore
@referenceModel.name = 'Reference'
@referenceModel.prototype = null
@referenceModel.redis = @redis
beforeEach ->
@referenceModel.attributes =
secondId:
dataType: 'string'
@redisObjectClassDataStore.attributes =
url:
dataType: 'string'
identifiable: true
sortable: true
one:
dataType: 'integer'
sortable: true
two:
dataType: 'integer'
sortable: true
three:
dataType: 'integer'
sortable: true
integer:
dataType: 'integer'
sortable: true
identifier:
dataType: 'string'
identifiable: true
reference:
dataType: 'reference'
referenceModelName: 'Reference'
manyReferences:
dataType: 'reference'
many: true
referenceModelName: 'Reference'
sortableString:
dataType: 'string'
sortable: true
sortableInteger:
dataType: 'integer'
sortable: true
searchableText:
dataType: 'text'
searchable: true
searchableString:
dataType: 'string'
searchable: true
boolean:
dataType: 'boolean'
afterEach ->
@redis.flushdb()
afterAll ->
@redis.flushdb()
@redis.end()
it 'should be a valid module', ->
expect(@redisObjectClassDataStore).toEqual jasmine.any(Object)
expect(@redisObjectClassDataStore.name).toEqual "RedisObjectClassDataStore"
describe '#create', ->
it 'should return a promise', ->
createPromise = @redisObjectClassDataStore.create(integer: 1)
expect(createPromise).toEqual jasmine.any(Promise)
describe 'stored data types', ->
describe 'for string attributes', ->
describe 'where identifiable is true', ->
it 'adds to a key-value pair', (done) ->
multi = @redisObjectClassDataStore.redis.multi()
spyOn(@redisObjectClassDataStore.redis, 'multi').and.returnValue(multi)
spyOn(multi, 'set')
@redisObjectClassDataStore.create(identifier: 'identifierValue').then (createdObject) ->
expect(multi.set).toHaveBeenCalledWith('RedisObjectClassDataStore#identifier:identifierValue', createdObject.id)
done()
describe 'where sortable is true', ->
it 'adds to an ordered list', (done) ->
testPromise1 = @redisObjectClassDataStore.create( sortableString: 'd' )
testPromise2 = @redisObjectClassDataStore.create( sortableString: 'a' )
testPromise3 = @redisObjectClassDataStore.create( sortableString: 'c' )
testPromise4 = @redisObjectClassDataStore.create( sortableString: 'b' )
Promise.all([testPromise1,testPromise2,testPromise3,testPromise4]).done (testObjectArray) =>
test1Id = testObjectArray[0].id
test2Id = testObjectArray[1].id
test3Id = testObjectArray[2].id
test4Id = testObjectArray[3].id
@redis.zrange "RedisObjectClassDataStore>sortableString", 0, -1, (error, list) ->
expect(list).toEqual [test1Id, test3Id, test4Id, test2Id]
done()
describe 'where searchable is true', ->
it 'adds to partial words sets when the modules class has attributes with the field type of "string" and is searchable', (done) ->
spyOn(@redisObjectClassDataStore.redis, 'zadd').and.callThrough()
@redisObjectClassDataStore.create(searchableText: 'Search This').then (createdObject) =>
calledArgs = @redisObjectClassDataStore.redis.zadd.calls.allArgs()
keysCalled = []
for call in calledArgs
keysCalled.push call[0]
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/s')
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/se')
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/sea')
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/sear')
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/search')
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/t')
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/th')
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/thi')
expect(keysCalled).toContain('RedisObjectClassDataStore#searchableText/this')
done()
describe 'for integer attributes', ->
# Integers are always sortable
it 'adds to a sorted set', (done) ->
testPromise1 = @redisObjectClassDataStore.create( integer: 11 )
testPromise2 = @redisObjectClassDataStore.create( integer: 8 )
testPromise3 = @redisObjectClassDataStore.create( integer: 10 )
testPromise4 = @redisObjectClassDataStore.create( integer: 9 )
Promise.all([testPromise1,testPromise2,testPromise3,testPromise4]).done (testObjectArray) =>
test1Id = testObjectArray[0].id
test2Id = testObjectArray[1].id
test3Id = testObjectArray[2].id
test4Id = testObjectArray[3].id
@redis.zrange "RedisObjectClassDataStore>integer", 0, -1, (error, list) ->
expect(list).toEqual [test2Id, test4Id, test3Id, test1Id]
done()
it 'adds to a sorted set with values', (done) ->
multi = @redisObjectClassDataStore.redis.multi()
spyOn(@redisObjectClassDataStore.redis, 'multi').and.returnValue(multi)
spyOn(multi, 'zadd')
@redisObjectClassDataStore.create(integer: 1).then (createdObject) ->
expect(multi.zadd).toHaveBeenCalledWith('RedisObjectClassDataStore>integer', 1, createdObject.id)
done()
describe 'for boolean attributes', ->
it 'adds to a zset', (done) ->
multi = @redisObjectClassDataStore.redis.multi()
spyOn(@redisObjectClassDataStore.redis, 'multi').and.returnValue(multi)
spyOn(multi, 'zadd')
@redisObjectClassDataStore.create(boolean: true).then (createdObject) ->
expect(multi.zadd).toHaveBeenCalledWith('RedisObjectClassDataStore#boolean:true', 1, createdObject.id)
done()
describe 'for reference attributes', ->
describe 'when many is true', ->
it "sets the reference to true", (done) ->
@referenceModel.create(secondId: 'id1').then (ref1) =>
@redisObjectClassDataStore.create(manyReferences: [ref1.id]).then (createdObject) =>
@redis.hgetall 'RedisObjectClassDataStore:' + createdObject.id, (err, obj) ->
expect(obj.manyReferences).toEqual 'true'
done()
it "sets the reference to even when empty", (done) ->
@referenceModel.create(secondId: 'id1').then (ref1) =>
@redisObjectClassDataStore.create(url: 'one').then (createdObject) =>
@redis.hgetall 'RedisObjectClassDataStore:' + createdObject.id, (err, obj) ->
expect(obj.manyReferences).toEqual 'true'
done()
it 'adds to a set', (done) ->
@redisObjectClassDataStore.attributes =
linkedModel:
dataType: 'reference'
many: true
referenceModelName: 'LinkedModel'
multi = @redisObjectClassDataStore.redis.multi()
spyOn(@redisObjectClassDataStore.redis, 'multi').and.returnValue(multi)
spyOn(multi, 'sadd')
@redisObjectClassDataStore.create(linkedModel: ['linkedModelId1', 'linkedModelId2']).then (createdObject) ->
expect(multi.sadd).toHaveBeenCalledWith('RedisObjectClassDataStore:' + createdObject.id + '#linkedModel:LinkedModelRefs', 'linkedModelId1', 'linkedModelId2')
expect(multi.sadd).toHaveBeenCalledWith('LinkedModel:linkedModelId1#linkedModel:RedisObjectClassDataStoreRefs', createdObject.id)
expect(multi.sadd).toHaveBeenCalledWith('LinkedModel:linkedModelId2#linkedModel:RedisObjectClassDataStoreRefs', createdObject.id)
done()
it 'adds to a set with a reverseReferenceAttribute', (done) ->
@redisObjectClassDataStore.attributes =
linkedModel:
dataType: 'reference'
many: true
referenceModelName: 'LinkedModel'
reverseReferenceAttribute: 'namespaced'
multi = @redisObjectClassDataStore.redis.multi()
spyOn(@redisObjectClassDataStore.redis, 'multi').and.returnValue(multi)
spyOn(multi, 'sadd')
@redisObjectClassDataStore.create(linkedModel: ['linkedModelId1', 'linkedModelId2']).then (createdObject) ->
expect(multi.sadd).toHaveBeenCalledWith('RedisObjectClassDataStore:' + createdObject.id + '#linkedModel:LinkedModelRefs', 'linkedModelId1', 'linkedModelId2')
expect(multi.sadd).toHaveBeenCalledWith('LinkedModel:linkedModelId1#namespaced:RedisObjectClassDataStoreRefs', createdObject.id)
expect(multi.sadd).toHaveBeenCalledWith('LinkedModel:linkedModelId2#namespaced:RedisObjectClassDataStoreRefs', createdObject.id)
done()
describe 'when many is not true', ->
it 'stores the reference id', (done) ->
@referenceModel.create(secondId: 'id1').done (ref1) =>
@redisObjectClassDataStore.create(reference: ref1.id).then (createdObject) =>
@redis.hgetall 'RedisObjectClassDataStore:' + createdObject.id, (err, obj) ->
expect(obj.reference).toEqual ref1.id
done()
describe '#find', ->
it 'should return a promise', ->
testObject = @redisObjectClassDataStore.find('test1')
expect(testObject).toEqual jasmine.any(Promise)
it 'should resolve to a valid instance of the modules class when given an id', (done) ->
pending()
#redisObjectClassDataStoreClass = @redisObjectClassDataStoreClass
#testProps = { one: 1, two: 2, three: 3 }
#test1Object = new redisObjectClassDataStoreClass(testProps)
#@redisObjectClassDataStore.create(testProps).then (returnObject) =>
# id = returnObject.id
# findPromise = @redisObjectClassDataStore.find(id)
# findPromise.done (returnValue) ->
# # remove generated props for the test
# delete returnValue.id
# delete returnValue.createdAt
# expect(returnValue).toEqual test1Object
# done()
it 'should reject if no object is found', (done) ->
findPromise = @redisObjectClassDataStore.find('testNotFound')
findPromise.catch (error) ->
expect(error).toEqual new Error "Not Found"
done()
it 'should create an object of the same class as the module owner', (done) ->
pending()
it 'should return an integer correctly', (done) ->
testProps = { integer: '1'}
@redisObjectClassDataStore.create(testProps).then (createdObject) =>
findPromise = @redisObjectClassDataStore.find(createdObject.id)
findPromise.done (returnValue) ->
expect(returnValue.integer).toEqual jasmine.any(Number)
done()
it 'should return the reference id when many is false', (done) ->
@redisObjectClassDataStore.attributes =
singleReference:
dataType: 'reference'
referenceModelName: 'Reference'
many: false
createReferencePromise = @referenceModel.create(secondId: 'id1')
createReferencePromise.then (ref1) =>
@redisObjectClassDataStore.create(singleReference: ref1.id).then (createdObject) =>
findPromise = @redisObjectClassDataStore.find(createdObject.id)
findPromise.done (foundObj) ->
expect(foundObj.singleReference).toEqual ref1
done()
it 'should return an array of reference ids when many is true', (done) ->
ref1 = @referenceModel.create(secondId: 'id1')
ref2 = @referenceModel.create(secondId: 'id2')
ref3 = @referenceModel.create(secondId: 'id3')
createReferencesPromise = Promise.all([ref1, ref2, ref3])
createReferencesPromise.done (referencesObjects) =>
referenceIds = _.map referencesObjects, 'id'
testProps = manyReferences: referenceIds, url: 'new'
@redisObjectClassDataStore.create(testProps).then (createdObject) =>
findPromise = @redisObjectClassDataStore.find(createdObject.id)
findPromise.done (foundObj) ->
expect(foundObj.manyReferences).toContain referencesObjects[0]
expect(foundObj.manyReferences).toContain referencesObjects[1]
expect(foundObj.manyReferences).toContain referencesObjects[2]
expect(foundObj.manyReferences.length).toEqual 3
done()
describe '#findBy', ->
it 'should return a promise', ->
testObject = @redisObjectClassDataStore.findBy(id: 'test1')
expect(testObject).toEqual jasmine.any(Promise)
it "should resolve to a valid instance of the module's class when given an id", (done) ->
testProps = { url: 'uniqueValue', one: 1, two: 2, three: 3 }
@redisObjectClassDataStore.create(testProps).then (createdObject) =>
findByPromise = @redisObjectClassDataStore.findBy(id: createdObject.id)
findByPromise.done (returnValue) ->
expect(returnValue).toEqual createdObject
done()
it "should resolve to a valid instance of the module's class when given a url", (done) ->
testProps = { url: 'uniqueValue', one: 1, two: 2, three: 3 }
@redisObjectClassDataStore.create(testProps).then (createdObject) =>
findByPromise = @redisObjectClassDataStore.findBy(url: 'uniqueValue')
findByPromise.done (returnValue) ->
expect(returnValue).toEqual createdObject
done()
it 'should reject if no object is found', (done) ->
findByPromise = @redisObjectClassDataStore.findBy(url: 'urlNotFound')
findByPromise.catch (returnValue) ->
expect(returnValue).toEqual new Error "Not Found"
done()
describe '#where', ->
it 'should remove temporary sorted sets', (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', integer: 1 )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', integer: 1 )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', integer: 2 )
Promise.all([testPromise1,testPromise2,testPromise3]).done =>
wherePromise = @redisObjectClassDataStore.where(integer: 1)
wherePromise.done (returnValue) =>
setTimeout =>
@redisObjectClassDataStore.redis.keys 'temporary*', (err, keys) ->
expect(keys).toEqual []
done()
,1100
it 'should return a promise', ->
testObject = @redisObjectClassDataStore.where(one: '1')
expect(testObject).toEqual jasmine.any(Promise)
it 'should be able to return multiple test objects', (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', boolean: true )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', boolean: true )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', boolean: false )
Promise.all([testPromise1,testPromise2,testPromise3]).done =>
wherePromise = @redisObjectClassDataStore.where(boolean: true)
wherePromise.done (returnValue) =>
expect(returnValue.total).toEqual 2
expect(returnValue.items.length).toEqual 2
done()
it 'should be able to return a single test objects', (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', one: 2 )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', one: 1 )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', one: 1 )
Promise.all([testPromise1,testPromise2,testPromise3]).done =>
wherePromise = @redisObjectClassDataStore.where(one: equalTo: 2)
wherePromise.done (returnValue) =>
expect(returnValue.total).toEqual 1
expect(returnValue.items.length).toEqual 1
expect(returnValue.items[0]).toEqual jasmine.objectContaining url: 'uniqueValue1'
done()
it 'should return correct test objects when multiple properties conditions are met', (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', one: 1, two: 1 )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', one: 1, two: 2 )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', one: 1, two: 2 )
Promise.all([testPromise1,testPromise2,testPromise3]).then =>
whereConditions =
one:
equalTo: 1
two:
equalTo: 1
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.total).toEqual 1
expect(returnValue.items[0]).toEqual jasmine.objectContaining url: 'uniqueValue1'
done()
it 'should return an empty array when nothing matches the conditions', (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', one: 1, two: 2, three: 3 )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', one: 1, two: 2, three: 3 )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', one: 1, two: 2, three: 3 )
Promise.all([testPromise1,testPromise2,testPromise3]).then =>
whereConditions =
one:
equalTo: 1
two:
equalTo: 2
three:
equalTo: 4
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.total).toEqual 0
expect(returnValue.items).toEqual []
done()
it "should resolve to an array of valid instances of the module's class", (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', one: 1 )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', one: 1 )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', one: null )
Promise.all([testPromise1,testPromise2,testPromise3]).then (createdObjectArray) =>
wherePromise = @redisObjectClassDataStore.where(one: 1)
wherePromise.done (returnValue) =>
expect(returnValue.items).toContain createdObjectArray[0]
expect(returnValue.items).toContain createdObjectArray[1]
expect(returnValue.items.length).toEqual 2
expect(returnValue.total).toEqual 2
done()
it 'should return an array of objects sorted consistently (by id)', (done) ->
integerArray = [1, 1, 1, 2, 2, 3, 4, 5, 5]
promiseArray = _.map integerArray, (integer) =>
@redisObjectClassDataStore.create( integer: integer )
Promise.all(promiseArray).then (createdObjectArray) =>
@redisObjectClassDataStore.where(integer: equalTo: 1).done (firstResultArray) =>
@redisObjectClassDataStore.where(integer: equalTo: 1).done (secondResultArray) =>
expect(secondResultArray).toEqual firstResultArray
expect(secondResultArray.items.length).toEqual 3
expect(secondResultArray.total).toEqual 3
done()
it "should default to sorting by created at time (alphabetically by id)", (done) ->
createDelayedObj = (integer) ->
new Promise (resolve) =>
setTimeout =>
resolve @redisObjectClassDataStore.create(integer: integer)
, 10
delayedCreatePromises = []
for i in [0..9]
delayedCreatePromises.push createDelayedObj.apply(this, [i%2])
Promise.all(delayedCreatePromises).then (createdObjectArray) =>
@redisObjectClassDataStore.where(integer: equalTo: 1).done (returnArray) ->
returnedIds = if returnArray then _.map(returnArray.items.ids, (x) -> x.id ) else []
sortedReturnedIds = returnedIds.sort (a,b) -> a > b
expect(returnArray.items.length).toEqual 5
expect(returnedIds).toEqual sortedReturnedIds
done()
describe 'arguements', ->
describe 'integers', ->
beforeEach (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', integer: 5 )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', integer: 10 )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', integer: 15 )
Promise.all([testPromise1,testPromise2,testPromise3]).then (testObjects) =>
@testObject1 = testObjects[0]
@testObject2 = testObjects[1]
@testObject3 = testObjects[2]
done()
it 'should return an array of objects that have an integer greater than', (done) ->
whereConditions =
integer:
greaterThan: 10
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.total).toEqual 1
expect(returnValue.items[0]).toEqual @testObject3
done()
it 'should return an array of objects that have an integer greater than or equal to', (done) ->
whereConditions =
integer:
greaterThanOrEqualTo: 10
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.total).toEqual 2
expect(returnValue.items.length).toEqual 2
expect(returnValue.items).toContain @testObject3
expect(returnValue.items).toContain @testObject2
done()
it 'should return an array of objects that have an integer less than', (done) ->
whereConditions =
integer:
lessThan: 10
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.total).toEqual 1
expect(returnValue.items[0]).toEqual @testObject1
done()
it 'should return an array of objects that have an integer less than or equal to', (done) ->
whereConditions =
integer:
lessThanOrEqualTo: 10
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.total).toEqual 2
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject2
done()
it 'should return an array of objects that have an integer equal to', (done) ->
whereConditions =
integer:
equalTo: 10
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.total).toEqual 1
expect(returnValue.items[0]).toEqual @testObject2
done()
describe 'keywords', ->
beforeEach (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', searchableText: 'bananas apples throat', searchableString: 'tongue' )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', searchableText: 'two one four', searchableString: 'neck apples' )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', searchableText: 'One two Three throat', searchableString: 'throat two' )
Promise.all([testPromise1,testPromise2,testPromise3]).then (testObjects) =>
@testObject1 = testObjects[0]
@testObject2 = testObjects[1]
@testObject3 = testObjects[2]
done()
it 'should return an array of objects that includes case insensitive keywords', (done) ->
whereConditions =
includes:
keywords: 'one'
in: 'searchableText'
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.total).toEqual 2
expect(returnValue.items).toContain @testObject2
expect(returnValue.items).toContain @testObject3
done()
it 'should ignore empty spaces and punctuation characters', ->
pending()
it 'should return an array of objects that includes partial keywords', (done) ->
whereConditions =
includes:
keywords: 'thr'
in: 'searchableText'
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.total).toEqual 2
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject3
done()
it 'should return an array of objects that includes multiple keywords in any order', (done) ->
whereConditions =
includes:
keywords: 'two one'
in: 'searchableText'
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.total).toEqual 2
expect(returnValue.items).toContain @testObject2
expect(returnValue.items).toContain @testObject3
done()
describe 'inAllOf', ->
it 'should return an array of objects that includes keywords in all different attributes', (done) ->
whereConditions =
includes:
keywords: 'throat'
inAllOf: ['searchableText', 'searchableString']
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.total).toEqual 1
expect(returnValue.items).toContain @testObject3
done()
it 'should return an array of objects that includes multiple keywords in all different attributes', (done) ->
whereConditions =
includes:
keywords: 'throat two'
inAllOf: ['searchableText', 'searchableString']
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.total).toEqual 1
expect(returnValue.items).toContain @testObject3
done()
it 'should return an array of objects that includes multiple keywords in all different attributes', (done) ->
whereConditions =
includes:
keywords: 'throat One'
inAllOf: ['searchableText', 'searchableString']
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 0
done()
describe 'inAnyOf', ->
it 'should return an array of objects that includes keywords in any different attributes', (done) ->
whereConditions =
includes:
keywords: 'throat'
inAnyOf: ['searchableText', 'searchableString']
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.total).toEqual 2
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject3
done()
it 'should return an array of objects that includes keywords in any different attributes ordered by relevance by default', (done) ->
whereConditions =
includes:
keywords: 'apples'
inAnyOf: ['searchableText', 'searchableString']
modifiedWeights: [
attributes: 'searchableText'
weight: 0.5
]
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.total).toEqual 2
expect(returnValue.items[0]).toEqual @testObject2
expect(returnValue.items[1]).toEqual @testObject1
done()
it 'should return an array of objects that includes keywords in any different attributes ordered by relevance by default', (done) ->
whereConditions =
includes:
keywords: 'apples'
inAnyOf: ['searchableText', 'searchableString']
modifiedWeights: [
attributes: 'searchableString'
weight: 0.5
]
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.items[0]).toEqual @testObject1
expect(returnValue.items[1]).toEqual @testObject2
done()
it 'should return an array of objects that includes multiple keywords in any different attributes ordered by relevance by default', (done) ->
testPromise1 = @redisObjectClassDataStore.create( searchableText: 'bear', searchableString: 'cow cow' )
testPromise2 = @redisObjectClassDataStore.create( searchableText: 'cow cow', searchableString: 'bear' )
testPromise3 = @redisObjectClassDataStore.create( searchableText: 'cow', searchableString: 'dog' )
whereConditions =
includes:
keywords: 'bear cow'
inAnyOf: ['searchableText', 'searchableString']
modifiedWeights: [
attributes: 'searchableString'
weight: 0.5
]
Promise.all([testPromise1,testPromise2,testPromise3]).done (testobjects) =>
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.items).toContain testobjects[1]
expect(returnValue.items).toContain testobjects[0]
done()
describe 'reference', ->
beforeEach (done) ->
@redisObjectClassDataStore.attributes.oneRef =
dataType: 'reference'
referenceModelName: 'Reference'
@redisObjectClassDataStore.manyReferences =
dataType: 'reference'
many: true
referenceModelName: 'Reference'
ref1 = @referenceModel.create(secondId: 'id1')
ref2 = @referenceModel.create(secondId: 'id2')
ref3 = @referenceModel.create(secondId: 'id3')
ref4 = @referenceModel.create(secondId: 'id4')
ref5 = @referenceModel.create(secondId: 'id5')
createReferencesPromise = Promise.all([ref1, ref2, ref3, ref4, ref5])
createTestObjectsPromise = createReferencesPromise.then (references) =>
@ref1Id = references[0].id
@ref2Id = references[1].id
@ref3Id = references[2].id
@ref4Id = references[3].id
@ref5Id = references[4].id
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', manyReferences: [@ref1Id, @ref2Id], oneRef: @ref4Id )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', manyReferences: [@ref2Id], oneRef: @ref4Id )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', manyReferences: [@ref1Id, @ref2Id, @ref3Id], oneRef: @ref5Id )
Promise.all([testPromise1,testPromise2,testPromise3])
createTestObjectsPromise.then (testObjects) =>
@testObject1 = testObjects[0]
@testObject2 = testObjects[1]
@testObject3 = testObjects[2]
done()
describe 'includesAllOf', ->
it 'returns all objects when all match', (done) ->
wherePromise = @redisObjectClassDataStore.where manyReferences: { includesAllOf: [@ref1Id, @ref2Id, @ref3Id] }
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.items).toContain @testObject3
done()
it 'returns some objects when some match', (done) ->
wherePromise = @redisObjectClassDataStore.where manyReferences: { includesAllOf: [@ref1Id, @ref2Id] }
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject3
done()
it 'returns one object when one matches', (done) ->
wherePromise = @redisObjectClassDataStore.where manyReferences: { includesAllOf: [@ref2Id] }
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 3
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject2
expect(returnValue.items).toContain @testObject3
done()
describe 'includesAnyOf', ->
it 'returns all objects when all match', (done) ->
wherePromise = @redisObjectClassDataStore.where manyReferences: { includesAnyOf: [@ref3Id] }
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.items).toContain @testObject3
done()
it 'returns some objects when some match', (done) ->
wherePromise = @redisObjectClassDataStore.where manyReferences: { includesAnyOf: [@ref1Id, @ref3Id] }
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject3
done()
it 'returns one object when one matches', (done) ->
wherePromise = @redisObjectClassDataStore.where manyReferences: { includesAnyOf: [@ref2Id] }
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 3
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject2
expect(returnValue.items).toContain @testObject3
done()
describe 'non-many', ->
it 'returns all objects when all match', (done) ->
wherePromise = @redisObjectClassDataStore.where oneRef: { anyOf: [@ref4Id, @ref5Id] }
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 3
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject2
expect(returnValue.items).toContain @testObject3
done()
it 'returns some objects when some match', (done) ->
wherePromise = @redisObjectClassDataStore.where oneRef: @ref4Id
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.items).toContain @testObject1
expect(returnValue.items).toContain @testObject2
done()
it 'returns one object when one matches', (done) ->
wherePromise = @redisObjectClassDataStore.where oneRef: @ref5Id
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 1
expect(returnValue.items).toContain @testObject3
done()
describe 'sortBy', ->
it 'should return an array of objects ordered by a sortable field', (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', sortableString: 'alpha', boolean: true )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', sortableString: 'beta', boolean: false )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', sortableString: 'charlie', boolean: true )
whereConditions =
boolean: true
sortBy: 'sortableString'
Promise.all([testPromise1,testPromise2,testPromise3]).done =>
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 2
expect(returnValue.items[0]).toEqual jasmine.objectContaining url: 'uniqueValue1'
expect(returnValue.items[1]).toEqual jasmine.objectContaining url: 'uniqueValue3'
done()
it 'should return an array of objects that includes keywords in different attributes, ordered by a sortable field (not weight)', (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', searchableText: 'bananas apples throat', searchableString: 'tongue', sortableString: 'charlie' )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', searchableText: 'two one four', searchableString: 'neck', sortableString: 'beta' )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', searchableText: 'One two Three', searchableString: 'throat', sortableString: 'alpha' )
whereConditions =
includes:
keywords: 'throat'
inAnyOf: ['searchableText', 'searchableString']
modifiedWeights: [
attributes: 'searchableText'
weight: 2
]
sortBy: 'sortableString'
Promise.all([testPromise1,testPromise2,testPromise3]).done =>
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) ->
expect(returnValue.items.length).toEqual 2
expect(returnValue.items[0]).toEqual jasmine.objectContaining url: 'uniqueValue3'
expect(returnValue.items[1]).toEqual jasmine.objectContaining url: 'uniqueValue1'
done()
it 'should return an array of objects randomly ordered', (done) ->
#FIXME: shouldn't have randomly failing tests
console.log 'Occassional fail expected - testing random order'
urlArray = ['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot', 'golf', 'hotel','india', 'juliet' ]
i = 0
promiseArray = _.map urlArray, (url) =>
i++
@redisObjectClassDataStore.create( url: url, boolean: (i <= 5) )
whereConditions =
sortBy: 'random'
boolean: true
Promise.all(promiseArray).done =>
wherePromise = @redisObjectClassDataStore.where(whereConditions)
wherePromise.done (returnValue) =>
expect(returnValue.items.length).toEqual 5
expect(returnValue[4]).not.toEqual jasmine.objectContaining url: 'echo'
done()
describe '#all', ->
it 'should return a promise', ->
testObject = @redisObjectClassDataStore.all()
expect(testObject).toEqual jasmine.any(Promise)
it "should resolve to an array of all the instances of the module's class", (done) ->
testPromise1 = @redisObjectClassDataStore.create( url: 'uniqueValue1', one: 1, two: 2, three: 3 )
testPromise2 = @redisObjectClassDataStore.create( url: 'uniqueValue2', one: 1, two: 2, three: 3 )
testPromise3 = @redisObjectClassDataStore.create( url: 'uniqueValue3', one: 1, two: 2, three: 3 )
Promise.all([testPromise1,testPromise2,testPromise3]).then (createdObjectArray) =>
allPromise = @redisObjectClassDataStore.all()
allPromise.done (returnValue) ->
expect(returnValue.items).toContain createdObjectArray[0]
expect(returnValue.items).toContain createdObjectArray[1]
expect(returnValue.items).toContain createdObjectArray[2]
expect(returnValue.items.length).toEqual 3
expect(returnValue.total).toEqual 3
done()
it "should not resolve any instances of a different module's class", (done) ->
pending()
#differentModel = _.clone @redisObjectClassDataStore
#differentModel.name = "DifferentModel"
#redisObjectClassDataStoreCreatePromise = @redisObjectClassDataStore.create( url: 'redisObjectClassDataStoreModelInstance')
#differentModelCreatePromise = differentModel.create( url: 'differentModelInstance')
#Promise.all([redisObjectClassDataStoreCreatePromise, differentModelCreatePromise]).then (createdObjectArray) =>
# redisObjectClassDataStoreAllPromise = @redisObjectClassDataStore.all()
# differentModelAllPromise = differentModel.all()
# Promise.all([redisObjectClassDataStoreAllPromise, differentModelAllPromise]).done (returnArray) =>
# expect(returnArray.items[0]).toEqual [createdObjectArray[0]]
# expect(returnArray.items[1]).toEqual [createdObjectArray[1]]
# done()
it "should return an array of objects sorted consistently (by id)", (done) ->
urlArray = ['india', 'juliet', 'golf', 'hotel', 'alpha', 'bravo', 'delta', 'echo', 'foxtrot', 'charlie']
promiseArray = _.map urlArray, (url) =>
@redisObjectClassDataStore.create( url: url )
Promise.all(promiseArray).then (createdObjectArray) =>
@redisObjectClassDataStore.all().done (firstResultArray) =>
@redisObjectClassDataStore.all().done (secondResultArray) ->
expect(secondResultArray).toEqual firstResultArray
done()
it "should default to sorting by create at time (alphabetically by id)", (done) ->
createDelayedObj = (integer) ->
new Promise (resolve) =>
nextTick(resolve @redisObjectClassDataStore.create(integer: integer))
delayedCreatePromises = []
for i in [0..9]
delayedCreatePromises.push createDelayedObj.bind(this, i)
_utilities.promiseEachFn(delayedCreatePromises).then (createdObjectArray) =>
@redisObjectClassDataStore.all().done (returnArray) ->
expect(returnArray.items.length).toEqual 10
expect(returnArray.items).toEqual createdObjectArray
done()
it "should return an array of objects sorted by sortableString when passed sortBy args", (done) ->
stringArray = ['india', 'juliet', 'golf', 'hotel', 'alpha', 'bravo', 'delta', 'echo', 'foxtrot', 'charlie']
objectsPromise = _.map stringArray, (string) =>
@redisObjectClassDataStore.create( sortableString: string )
Promise.all(objectsPromise).then (createdObjectArray) =>
@redisObjectClassDataStore.all(sortBy: 'sortableString').done (returnArray) ->
expect(returnArray.items.length).toEqual 10
expect(returnArray.total).toEqual 10
expect(returnArray.items[0]).toEqual jasmine.objectContaining sortableString: 'alpha'
expect(returnArray.items[1]).toEqual jasmine.objectContaining sortableString: 'bravo'
expect(returnArray.items[2]).toEqual jasmine.objectContaining sortableString: 'charlie'
expect(returnArray.items[3]).toEqual jasmine.objectContaining sortableString: 'delta'
expect(returnArray.items[4]).toEqual jasmine.objectContaining sortableString: 'echo'
expect(returnArray.items[5]).toEqual jasmine.objectContaining sortableString: 'foxtrot'
expect(returnArray.items[6]).toEqual jasmine.objectContaining sortableString: 'golf'
expect(returnArray.items[7]).toEqual jasmine.objectContaining sortableString: 'hotel'
expect(returnArray.items[8]).toEqual jasmine.objectContaining sortableString: 'india'
expect(returnArray.items[9]).toEqual jasmine.objectContaining sortableString: 'juliet'
done()
it "should return an array of objects sorted in ascending order when passed sortBy and sortDirection args", (done) ->
stringArray = ['india', 'juliet', 'golf', 'hotel', 'alpha', 'bravo', 'delta', 'echo', 'foxtrot', 'charlie']
objectsPromise = _.map stringArray, (string) =>
@redisObjectClassDataStore.create( sortableString: string )
Promise.all(objectsPromise).then (createdObjectArray) =>
@redisObjectClassDataStore.all(sortBy: 'sortableString', sortDirection: 'asc').done (returnArray) ->
expect(returnArray.items.length).toEqual 10
expect(returnArray.total).toEqual 10
expect(returnArray.items[0]).toEqual jasmine.objectContaining sortableString: 'alpha'
expect(returnArray.items[1]).toEqual jasmine.objectContaining sortableString: 'bravo'
expect(returnArray.items[2]).toEqual jasmine.objectContaining sortableString: 'charlie'
expect(returnArray.items[3]).toEqual jasmine.objectContaining sortableString: 'delta'
expect(returnArray.items[4]).toEqual jasmine.objectContaining sortableString: 'echo'
expect(returnArray.items[5]).toEqual jasmine.objectContaining sortableString: 'foxtrot'
expect(returnArray.items[6]).toEqual jasmine.objectContaining sortableString: 'golf'
expect(returnArray.items[7]).toEqual jasmine.objectContaining sortableString: 'hotel'
expect(returnArray.items[8]).toEqual jasmine.objectContaining sortableString: 'india'
expect(returnArray.items[9]).toEqual jasmine.objectContaining sortableString: 'juliet'
done()
it "should return an array of objects sorted in decending order when passed sortBy and sortDirection args", (done) ->
stringArray = ['india', 'juliet', 'golf', 'hotel', 'alpha', 'bravo', 'delta', 'echo', 'foxtrot', 'charlie']
objectsPromise = _.map stringArray, (string) =>
@redisObjectClassDataStore.create( sortableString: string )
Promise.all(objectsPromise).then (createdObjectArray) =>
@redisObjectClassDataStore.all(sortBy: 'sortableString', sortDirection: 'desc').done (returnArray) ->
expect(returnArray.total).toEqual 10
expect(returnArray.items.length).toEqual 10
expect(returnArray.items[0]).toEqual jasmine.objectContaining sortableString: 'juliet'
expect(returnArray.items[1]).toEqual jasmine.objectContaining sortableString: 'india'
expect(returnArray.items[2]).toEqual jasmine.objectContaining sortableString: 'hotel'
expect(returnArray.items[3]).toEqual jasmine.objectContaining sortableString: 'golf'
expect(returnArray.items[4]).toEqual jasmine.objectContaining sortableString: 'foxtrot'
expect(returnArray.items[5]).toEqual jasmine.objectContaining sortableString: 'echo'
expect(returnArray.items[6]).toEqual jasmine.objectContaining sortableString: 'delta'
expect(returnArray.items[7]).toEqual jasmine.objectContaining sortableString: 'charlie'
expect(returnArray.items[8]).toEqual jasmine.objectContaining sortableString: 'bravo'
expect(returnArray.items[9]).toEqual jasmine.objectContaining sortableString: 'alpha'
done()
it "should return an array of 5 items when passed a limit of 5", (done) ->
stringArray = ['india', 'juliet', 'golf', 'hotel', 'alpha', 'bravo', 'delta', 'echo', 'foxtrot', 'charlie']
objectsPromise = _.map stringArray, (string) =>
@redisObjectClassDataStore.create( sortableString: string )
Promise.all(objectsPromise).then (createdObjectArray) =>
@redisObjectClassDataStore.all(limit: 5).done (returnArray) ->
expect(returnArray.items.length).toEqual 5
expect(returnArray.total).toEqual 10
done()
it "should return an array of all available items when passed a limit of 0", (done) ->
stringArray = ['india', 'juliet', 'golf', 'hotel', 'alpha', 'bravo', 'delta', 'echo', 'foxtrot', 'charlie']
objectsPromise = _.map stringArray, (string) =>
@redisO