1 | mongojs = require 'mongojs'
|
2 | async = require 'async'
|
3 | Datastore = require '../src/datastore'
|
4 | Cache = require 'meshblu-core-cache'
|
5 | redis = require 'fakeredis'
|
6 | RedisNS = require '@octoblu/redis-ns'
|
7 | UUID = require 'uuid'
|
8 |
|
9 | describe 'Datastore', ->
|
10 | beforeEach (done) ->
|
11 | redisKey = UUID.v4()
|
12 | client = new RedisNS 'datastore:test:things', redis.createClient redisKey
|
13 | cache = new Cache {client}
|
14 | @redis = new RedisNS 'datastore:test:things', redis.createClient redisKey
|
15 |
|
16 | @sut = new Datastore
|
17 | database: mongojs('datastore-test')
|
18 | collection: 'things'
|
19 | cache: cache
|
20 | cacheAttributes: ['uuid']
|
21 | useQueryCache: true
|
22 |
|
23 | @db = mongojs 'datastore-test', ['things']
|
24 | @db.things.remove done
|
25 |
|
26 | describe '->find', ->
|
27 | describe 'when there exists a thing', ->
|
28 | beforeEach (done) ->
|
29 | record =
|
30 | uuid: 'wood'
|
31 | type: 'campfire'
|
32 | token: 'I bet you can\'t jump over it'
|
33 | @sut.insert record, done
|
34 |
|
35 | beforeEach (done) ->
|
36 | record =
|
37 | uuid: 'marshmellow'
|
38 | type: 'campfire'
|
39 | token: 'How long can you hold your hand in the fire?'
|
40 | @sut.insert record, done
|
41 |
|
42 | describe 'when find is called', ->
|
43 | beforeEach (done) ->
|
44 | @sut.find type: 'campfire', (error, @result) => done error
|
45 |
|
46 | it 'should yield the record without mongo stuff', ->
|
47 | expect(@result).to.deep.equal [
|
48 | {uuid: 'wood', type: 'campfire', token: 'I bet you can\'t jump over it'}
|
49 | {uuid: 'marshmellow', type: 'campfire', token: 'How long can you hold your hand in the fire?'}
|
50 | ]
|
51 |
|
52 | it 'should add to the search cache', (done) ->
|
53 | @redis.hget 'query:things', 'b098a0f435aa7818a057fc4aa21aa0775e74a09e', (error, data) =>
|
54 | return done error if error?
|
55 | expect(JSON.parse data).to.deep.equal {
|
56 | '3205fe0fa790bfe1039f95ba0bba03eec1faa05c': '874dbf9e6e84121a057e6ad2b9c047ebc95150f3'
|
57 | '9c77a994790ddf88bc197b11091643662c999a30': '2e9fb62f7fe1d2231b4a09f4d172cd808372327c'
|
58 | }
|
59 | done()
|
60 |
|
61 | it 'should add to the cache', (done) ->
|
62 | @redis.hget '3205fe0fa790bfe1039f95ba0bba03eec1faa05c', '874dbf9e6e84121a057e6ad2b9c047ebc95150f3', (error, data) =>
|
63 | return done error if error?
|
64 | expect(JSON.parse data).to.deep.equal uuid: 'wood', type: 'campfire', token: 'I bet you can\'t jump over it'
|
65 | done()
|
66 |
|
67 | it 'should add the other to the cache', (done) ->
|
68 | @redis.hget '9c77a994790ddf88bc197b11091643662c999a30', '2e9fb62f7fe1d2231b4a09f4d172cd808372327c', (error, data) =>
|
69 | return done error if error?
|
70 | expect(JSON.parse data).to.deep.equal uuid: 'marshmellow', type: 'campfire', token: 'How long can you hold your hand in the fire?'
|
71 | done()
|
72 |
|
73 | describe 'when a record is already cached', ->
|
74 | beforeEach (done) ->
|
75 | data =
|
76 | '3205fe0fa790bfe1039f95ba0bba03eec1faa05c': '9635cce604dbe5de11fe870a88e250115a3bda4d'
|
77 | '9c77a994790ddf88bc197b11091643662c999a30': '77e560dbcffbfd744248a6ff9e6d29de2763e35f'
|
78 |
|
79 | @redis.hset 'query:things', 'b098a0f435aa7818a057fc4aa21aa0775e74a09e', JSON.stringify(data), done
|
80 |
|
81 | beforeEach (done) ->
|
82 | data = uuid: 'wood', type: 'campfire', token: 'I bet you can\'t jump over it'
|
83 | @redis.hset '3205fe0fa790bfe1039f95ba0bba03eec1faa05c', '9635cce604dbe5de11fe870a88e250115a3bda4d', JSON.stringify(data), done
|
84 |
|
85 | beforeEach (done) ->
|
86 | data = uuid: 'marshmellow', type: 'campfire', token: 'How long can you hold your hand in the fire?'
|
87 | @redis.hset '9c77a994790ddf88bc197b11091643662c999a30', '77e560dbcffbfd744248a6ff9e6d29de2763e35f', JSON.stringify(data), done
|
88 |
|
89 | context 'when all the records exist', ->
|
90 | beforeEach (done) ->
|
91 | @sut.find type: 'campfire', (error, @result) => done error
|
92 |
|
93 | it 'should yield the record without mongo stuff', ->
|
94 | expect(@result).to.deep.equal [
|
95 | {uuid: 'wood', type: 'campfire', token: 'I bet you can\'t jump over it'}
|
96 | {uuid: 'marshmellow', type: 'campfire', token: 'How long can you hold your hand in the fire?'}
|
97 | ]
|
98 |
|
99 | describe 'when a record is missing', ->
|
100 | beforeEach (done) ->
|
101 | data =
|
102 | '3205fe0fa790bfe1039f95ba0bba03eec1faa05c': '9635cce604dbe5de11fe870a88e250115a3bda4d'
|
103 | '9c77a994790ddf88bc197b11091643662c999a30': '77e560dbcffbfd744248a6ff9e6d29de2763e35f'
|
104 |
|
105 | @redis.hset 'query:things', 'b098a0f435aa7818a057fc4aa21aa0775e74a09e', JSON.stringify(data), done
|
106 |
|
107 | beforeEach (done) ->
|
108 | data = uuid: 'wood', type: 'campfire', token: 'I bet you can\'t jump over it'
|
109 | @redis.hset '3205fe0fa790bfe1039f95ba0bba03eec1faa05c', '9635cce604dbe5de11fe870a88e250115a3bda4d', JSON.stringify(data), done
|
110 |
|
111 | context 'when all the records exist', ->
|
112 | beforeEach (done) ->
|
113 | @sut.find type: 'campfire', (error, @result) => done error
|
114 |
|
115 | it 'should yield the record without mongo stuff', ->
|
116 | expect(@result).to.deep.equal []
|
117 |
|
118 | describe 'with a projection', ->
|
119 | beforeEach (done) ->
|
120 | record =
|
121 | uuid: 'wood'
|
122 | type: 'campfire'
|
123 | token: 'I bet you can\'t jump over it'
|
124 | @sut.insert record, done
|
125 |
|
126 | beforeEach (done) ->
|
127 | record =
|
128 | uuid: 'marshmellow'
|
129 | type: 'campfire'
|
130 | token: 'How long can you hold your hand in the fire?'
|
131 | @sut.insert record, done
|
132 |
|
133 | describe 'when find is called', ->
|
134 | beforeEach (done) ->
|
135 | @sut.find {type: 'campfire'}, {type: true, uuid: true}, (error, @result) => done error
|
136 |
|
137 | it 'should yield the record without mongo stuff', ->
|
138 | expect(@result).to.deep.equal [
|
139 | {uuid: 'wood', type: 'campfire'}
|
140 | {uuid: 'marshmellow', type: 'campfire'}
|
141 | ]
|
142 |
|
143 | it 'should add to the search cache', (done) ->
|
144 | @redis.hget 'query:things', '592e16c142809fcd4f5930e933f79a3980939f49', (error, data) =>
|
145 | return done error if error?
|
146 | expect(JSON.parse data).to.deep.equal {
|
147 | '3205fe0fa790bfe1039f95ba0bba03eec1faa05c': '9635cce604dbe5de11fe870a88e250115a3bda4d'
|
148 | '9c77a994790ddf88bc197b11091643662c999a30': '77e560dbcffbfd744248a6ff9e6d29de2763e35f'
|
149 | }
|
150 | done()
|
151 |
|
152 | it 'should add to the cache', (done) ->
|
153 | @redis.hget '3205fe0fa790bfe1039f95ba0bba03eec1faa05c', '9635cce604dbe5de11fe870a88e250115a3bda4d', (error, data) =>
|
154 | return done error if error?
|
155 | expect(JSON.parse data).to.deep.equal uuid: 'wood', type: 'campfire'
|
156 | done()
|
157 |
|
158 | it 'should add the other to the cache', (done) ->
|
159 | @redis.hget '9c77a994790ddf88bc197b11091643662c999a30', '77e560dbcffbfd744248a6ff9e6d29de2763e35f', (error, data) =>
|
160 | return done error if error?
|
161 | expect(JSON.parse data).to.deep.equal uuid: 'marshmellow', type: 'campfire'
|
162 | done()
|
163 |
|
164 | describe 'when there exists no thing', ->
|
165 | beforeEach (done) ->
|
166 | @sut.find type: 'nobody cares', (error, @result) => done error
|
167 |
|
168 | it 'should yield a empty array', ->
|
169 | expect(@result).to.be.empty
|
170 | expect(@result).to.be.array
|
171 |
|
172 | it 'should add to the search cache', (done) ->
|
173 | @redis.hget 'query:things', '6f6903006fed8fdff009079cf659b624c8a46403', (error, data) =>
|
174 | return done error if error?
|
175 | expect(JSON.parse data).to.deep.equal {}
|
176 | done()
|
177 |
|
178 | describe '->findOne', ->
|
179 | describe 'on a record that exists', ->
|
180 | beforeEach (done) ->
|
181 | record =
|
182 | uuid: 'sandbag'
|
183 | token: 'This’ll hold that pesky tsunami!'
|
184 | @sut.insert record, done
|
185 |
|
186 | beforeEach (done) ->
|
187 | @sut.findOne uuid: 'sandbag', (error, @result) => done error
|
188 |
|
189 | it 'should yield the record without mongo stuff', ->
|
190 | expect(@result).to.deep.equal
|
191 | uuid: 'sandbag'
|
192 | token: 'This’ll hold that pesky tsunami!'
|
193 |
|
194 | it 'should add to the cache', (done) ->
|
195 | @redis.hget '779f48bb3d0177cb8c61d78e3c0899a5157cdcbd', 'cfc702c2d593c0667981e3220a271912e456fe61', (error, data) =>
|
196 | return done error if error?
|
197 | expect(JSON.parse data).to.deep.equal uuid: 'sandbag', token: 'This’ll hold that pesky tsunami!'
|
198 | done()
|
199 |
|
200 | describe 'record is already cached', ->
|
201 | beforeEach (done) ->
|
202 | @redis.hset '779f48bb3d0177cb8c61d78e3c0899a5157cdcbd', 'cfc702c2d593c0667981e3220a271912e456fe61', JSON.stringify('hi': 'there'), done
|
203 |
|
204 | beforeEach (done) ->
|
205 | @sut.findOne uuid: 'sandbag', (error, @result) => done error
|
206 |
|
207 | it 'should yield the record without mongo stuff', ->
|
208 | expect(@result).to.deep.equal
|
209 | hi: 'there'
|
210 |
|
211 | describe 'on a record that does not exist', ->
|
212 | beforeEach (done) ->
|
213 | @sut.findOne uuid: 'blank', (error, @result) => done error
|
214 |
|
215 | it 'should yield a non extant record', ->
|
216 | expect(@result).not.to.exist
|
217 |
|
218 | describe 'on with projection', ->
|
219 | beforeEach (done) ->
|
220 | record =
|
221 | uuid: 'sandbag'
|
222 | token: 'This’ll hold that pesky tsunami!'
|
223 | @sut.insert record, done
|
224 |
|
225 | beforeEach (done) ->
|
226 | @sut.findOne {uuid: 'sandbag'}, {token: false}, (error, @result) => done error
|
227 |
|
228 | it 'should yield the record without mongo stuff', ->
|
229 | expect(@result).to.deep.equal
|
230 | uuid: 'sandbag'
|
231 |
|
232 | it 'should cache the projection', (done) ->
|
233 | @redis.hget '779f48bb3d0177cb8c61d78e3c0899a5157cdcbd', '18ba252583142b0a3a85fc47f56852630f8dfb5c', (error, data) =>
|
234 | return done error if error?
|
235 | expect(JSON.parse data).to.deep.equal uuid: 'sandbag'
|
236 | done()
|
237 |
|
238 | describe 'with a different projection', ->
|
239 | beforeEach (done) ->
|
240 | record =
|
241 | uuid: 'sandbag'
|
242 | token: 'This’ll hold that pesky tsunami!'
|
243 | spork: 'bork'
|
244 | @sut.insert record, done
|
245 |
|
246 | beforeEach (done) ->
|
247 | @sut.findOne {uuid: 'sandbag'}, {uuid: true, spork: true}, (error, @result) => done error
|
248 |
|
249 | it 'should yield the record without mongo stuff', ->
|
250 | expect(@result).to.deep.equal
|
251 | uuid: 'sandbag'
|
252 | spork: 'bork'
|
253 |
|
254 | it 'should cache the projection', (done) ->
|
255 | @redis.hget '779f48bb3d0177cb8c61d78e3c0899a5157cdcbd', '3b71f93def87ecb1fc0f44eda7e588a3cd4eef95', (error, data) =>
|
256 | return done error if error?
|
257 | expect(JSON.parse data).to.deep.equal uuid: 'sandbag', spork: 'bork'
|
258 | done()
|
259 |
|
260 | describe '->insert', ->
|
261 | describe 'when called with an object', ->
|
262 | beforeEach (done) ->
|
263 | @redis.hset 'query:things', 'blah', 'blah', done
|
264 |
|
265 | beforeEach (done) ->
|
266 | record =
|
267 | uuid: 'goose'
|
268 | token: 'Duck, duck, DEAD'
|
269 | @sut.insert record, (error, @result) => done error
|
270 |
|
271 | it 'should yield nothing', ->
|
272 | expect(@result).not.to.exist
|
273 |
|
274 | it 'should store the thing', (done) ->
|
275 | @sut.findOne uuid: 'goose', (error, record) =>
|
276 | return done error if error?
|
277 | expect(record).to.containSubset
|
278 | uuid: 'goose'
|
279 | token: 'Duck, duck, DEAD'
|
280 | done()
|
281 |
|
282 | it 'should remove the query cache', (done) ->
|
283 | @redis.exists 'query:things', (error, exists) =>
|
284 | return done error if error?
|
285 | expect(exists).to.equal 0
|
286 | done()
|
287 |
|
288 | describe '->upsert', ->
|
289 | describe 'when called with an object', ->
|
290 | beforeEach (done) ->
|
291 | @redis.hset 'query:things', 'blah', 'blah', done
|
292 |
|
293 | beforeEach (done) ->
|
294 | record =
|
295 | uuid: 'goose'
|
296 | token: 'Duck, duck, DEAD'
|
297 | @sut.upsert {uuid: 'goose'}, record, (error) => done error
|
298 |
|
299 | it 'should store the thing', (done) ->
|
300 | @sut.findOne uuid: 'goose', (error, record) =>
|
301 | return done error if error?
|
302 | expect(record).to.containSubset
|
303 | uuid: 'goose'
|
304 | token: 'Duck, duck, DEAD'
|
305 | done()
|
306 |
|
307 | it 'should remove the query cache', (done) ->
|
308 | @redis.exists 'query:things', (error, exists) =>
|
309 | return done error if error?
|
310 | expect(exists).to.equal 0
|
311 | done()
|
312 |
|
313 | describe '->remove', ->
|
314 | beforeEach (done) ->
|
315 | @redis.hset 'sandbag', 'foo', 'bar', done
|
316 |
|
317 | describe 'when there exists a thing', ->
|
318 | beforeEach (done) ->
|
319 | record =
|
320 | uuid: 'sandbag'
|
321 | token: 'This’ll hold that pesky tsunami!'
|
322 | @sut.insert record, done
|
323 |
|
324 | describe 'when called with a query', ->
|
325 | beforeEach (done) ->
|
326 | @sut.remove uuid: 'sandbag', done
|
327 |
|
328 | it 'should remove the record', (done) ->
|
329 | @sut.findOne uuid: 'sandbag', (error, device) =>
|
330 | return done error if error?
|
331 | expect(device).not.to.exist
|
332 | done()
|
333 |
|
334 | it 'should clear the cache', (done) ->
|
335 | @redis.exists '779f48bb3d0177cb8c61d78e3c0899a5157cdcbd', (error, exists) =>
|
336 | return done error if error?
|
337 | expect(exists).to.equal 0
|
338 | done()
|
339 |
|
340 | describe '->recycle', ->
|
341 | beforeEach (done) ->
|
342 | @redis.hset 'sandbag', 'foo', 'bar', done
|
343 |
|
344 | describe 'when there exists a thing', ->
|
345 | beforeEach (done) ->
|
346 | record =
|
347 | uuid: 'sandbag'
|
348 | token: 'This’ll hold that pesky tsunami!'
|
349 | @sut.insert record, done
|
350 |
|
351 | describe 'when called with a query', ->
|
352 | beforeEach (done) ->
|
353 | @sut.recycle uuid: 'sandbag', done
|
354 |
|
355 | it 'should insert the record into the deleted collection', (done) ->
|
356 | @sut.findOneRecycled uuid: 'sandbag', (error, device) =>
|
357 | return done error if error?
|
358 | expect(device).to.exist
|
359 | done()
|
360 |
|
361 | it 'should remove the record', (done) ->
|
362 | @sut.findOne uuid: 'sandbag', (error, device) =>
|
363 | return done error if error?
|
364 | expect(device).not.to.exist
|
365 | done()
|
366 |
|
367 | it 'should clear the cache', (done) ->
|
368 | @redis.exists '779f48bb3d0177cb8c61d78e3c0899a5157cdcbd', (error, exists) =>
|
369 | return done error if error?
|
370 | expect(exists).to.equal 0
|
371 | done()
|
372 |
|
373 | describe '->update', ->
|
374 | describe 'when an object exists', ->
|
375 | beforeEach (done) ->
|
376 | @redis.hset '9f0f2e3f4d49c05e64727e8993f152f775e1f317', 'foo', 'bar', done
|
377 |
|
378 | beforeEach (done) ->
|
379 | @sut.insert uuid: 'hardware', byline: 'Does it grate?', done
|
380 |
|
381 | describe 'when called with an object', ->
|
382 | beforeEach (done) ->
|
383 | query = uuid: 'hardware'
|
384 | update = $set: {byline: 'Lee Press-Ons?'}
|
385 | @sut.update query, update, (error) => done error
|
386 |
|
387 | it 'should update the thing', (done) ->
|
388 | @sut.findOne uuid: 'hardware', (error, record) =>
|
389 | return done error if error?
|
390 | expect(record).to.containSubset
|
391 | uuid: 'hardware'
|
392 | byline: 'Lee Press-Ons?'
|
393 | done()
|
394 |
|
395 | it 'should clear the cache', (done) ->
|
396 | @redis.exists '9f0f2e3f4d49c05e64727e8993f152f775e1f317', (error, exists) =>
|
397 | return done error if error?
|
398 | expect(exists).to.equal 0
|
399 | done()
|