redtastic 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,776 @@
1
+ require 'spec_helper'
2
+
3
+ describe Redtastic::Model do
4
+
5
+ it 'validates type' do
6
+ expect do
7
+ class InvalidType < Redtastic::Model
8
+ type :foo
9
+ end
10
+ end.to raise_error(RuntimeError, 'foo is not a valid type')
11
+ end
12
+
13
+ it 'validates resolution' do
14
+ expect do
15
+ class InvalidResolution < Redtastic::Model
16
+ type :counter
17
+ resolution :foo
18
+ end
19
+ end.to raise_error(RuntimeError, 'foo is not a valid resolution')
20
+ end
21
+
22
+ context 'counter' do
23
+ before do
24
+ class Visits < Redtastic::Model
25
+ type :counter
26
+ resolution :days
27
+ end
28
+
29
+ class NoResolutions < Redtastic::Model
30
+ type :counter
31
+ end
32
+
33
+ @no_resolution_key = 'app1:no_resolutions:1'
34
+ @day_key = 'app1:visits:2014-01-05:1'
35
+ @week_key = 'app1:visits:2014-W1:1'
36
+ @month_key = 'app1:visits:2014-01:1'
37
+ @year_key = 'app1:visits:2014:1'
38
+ @id = 1001
39
+ @index = 1
40
+ @timestamp = '2014-01-05'
41
+ end
42
+
43
+ describe '#increment' do
44
+ context 'a model with a daily resolution' do
45
+ before do
46
+ Visits.increment(timestamp: @timestamp, id: @id)
47
+ end
48
+
49
+ it 'increments the daily key' do
50
+ expect(Redtastic::Connection.redis.hget(@day_key, @index)).to eq('1')
51
+ end
52
+
53
+ it 'increments the weekly key' do
54
+ expect(Redtastic::Connection.redis.hget(@week_key, @index)).to eq('1')
55
+ end
56
+
57
+ it 'increments the monthly key' do
58
+ expect(Redtastic::Connection.redis.hget(@month_key, @index)).to eq('1')
59
+ end
60
+
61
+ it 'increments the yearly key' do
62
+ expect(Redtastic::Connection.redis.hget(@year_key, @index)).to eq('1')
63
+ end
64
+ end
65
+
66
+ context 'a model with no resolution' do
67
+ it 'increments the key' do
68
+ NoResolutions.increment(id: @id)
69
+ expect(Redtastic::Connection.redis.hget(@no_resolution_key, @index)).to eq('1')
70
+ end
71
+ end
72
+
73
+ context 'multiple ids' do
74
+ before do
75
+ ids = [1001, 1002, 2003]
76
+ Visits.increment(timestamp: @timestamp, id: ids)
77
+ end
78
+
79
+ it 'increments the keys for each id' do
80
+ expect(Redtastic::Connection.redis.hget(@day_key, '1')).to eq('1')
81
+ expect(Redtastic::Connection.redis.hget(@day_key, '2')).to eq('1')
82
+ expect(Redtastic::Connection.redis.hget('app1:visits:2014-01-05:2', '3')).to eq('1')
83
+ end
84
+ end
85
+ end
86
+
87
+ describe '#decrement' do
88
+ before do
89
+ Redtastic::Connection.redis.hset(@day_key, @index, '1')
90
+ Visits.decrement(timestamp: @timestamp, id: @id)
91
+ end
92
+
93
+ context 'a model with a resolution' do
94
+ it 'decrements the key' do
95
+ expect(Redtastic::Connection.redis.hget(@day_key, @index)).to eq('0')
96
+ end
97
+ end
98
+
99
+ context 'a model with no resolution' do
100
+ before do
101
+ Redtastic::Connection.redis.hset(@no_resolution_key, @index, '1')
102
+ NoResolutions.decrement(id: @id)
103
+ end
104
+
105
+ it 'decrements the key' do
106
+ expect(Redtastic::Connection.redis.hget(@no_resolution_key, @index)).to eq('0')
107
+ end
108
+ end
109
+
110
+ context 'multiple ids' do
111
+ before do
112
+ ids = [1001, 1002, 2003]
113
+ Visits.decrement(timestamp: @timestamp, id: ids)
114
+ end
115
+
116
+ it 'decrements the keys for each id' do
117
+ expect(Redtastic::Connection.redis.hget(@day_key, '1')).to eq('-1')
118
+ expect(Redtastic::Connection.redis.hget(@day_key, '2')).to eq('-1')
119
+ expect(Redtastic::Connection.redis.hget('app1:visits:2014-01-05:2', '3')).to eq('-1')
120
+ end
121
+ end
122
+ end
123
+
124
+ describe '#find' do
125
+ context 'a model with a resolution' do
126
+ before do
127
+ Visits.increment(timestamp: @timestamp, id: @id)
128
+ Visits.increment(timestamp: '2014-01-02', id: @id)
129
+ end
130
+
131
+ it 'finds the value for a single day' do
132
+ expect(Visits.find(year: 2014, month: 1, day: 5, id: @id)).to eq(1)
133
+ end
134
+
135
+ it 'finds the value for a single week' do
136
+ expect(Visits.find(year: 2014, week: 1, id: @id)).to eq(2)
137
+ end
138
+
139
+ it 'finds the value for a single month' do
140
+ expect(Visits.find(year: 2014, month: 1, id: @id)).to eq(2)
141
+ end
142
+
143
+ it 'finds the value for a single year' do
144
+ expect(Visits.find(year: 2014, id: @id)).to eq(2)
145
+ end
146
+ end
147
+
148
+ context 'a model with no resolution' do
149
+ before do
150
+ 3.times { NoResolutions.increment(id: @id) }
151
+ end
152
+
153
+ it 'finds the value for the counter' do
154
+ expect(NoResolutions.find(id: @id)).to eq(3)
155
+ end
156
+ end
157
+
158
+ context 'mutiple ids' do
159
+ before do
160
+ 2.times { Visits.increment(timestamp: @timestamp, id: 1001) }
161
+ Visits.increment(timestamp: @timestamp, id: 2003)
162
+ end
163
+
164
+ it 'returns an array of the values for each id' do
165
+ expected_result = [2, 1]
166
+ expect(Visits.find(year: 2014, month: 1, day: 5, id: [1001, 2003])).to eq(expected_result)
167
+ end
168
+ end
169
+ end
170
+
171
+ describe '#aggregate' do
172
+ context 'when no interval specified' do
173
+ it 'returns the total over the date range' do
174
+ 9.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:1", '1', 1) }
175
+ res = Visits.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
176
+ expect(res).to eq(9)
177
+ end
178
+
179
+ it 'returns the correct total over the date range when resolution is weeks' do
180
+ class Foo < Redtastic::Model
181
+ type :counter
182
+ resolution :weeks
183
+ end
184
+ 3.times { |num| Redtastic::Connection.redis.hincrby("app1:foo:2014-W#{num}:1", '1', 1) }
185
+ res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
186
+ expect(res).to eq(2)
187
+ end
188
+
189
+ it 'returns the correct total over the date range when the resolution is months' do
190
+ class Foo < Redtastic::Model
191
+ type :counter
192
+ resolution :months
193
+ end
194
+ 3.times { Redtastic::Connection.redis.hincrby('app1:foo:2014-01:1', '1', 1) }
195
+ res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
196
+ expect(res).to eq(3)
197
+ end
198
+
199
+ it 'returns the correct total over the date range when resolution is yearly' do
200
+ class Foo < Redtastic::Model
201
+ type :counter
202
+ resolution :years
203
+ end
204
+ 3.times { Redtastic::Connection.redis.hincrby('app1:foo:2014:1', '1', 1) }
205
+ res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
206
+ expect(res).to eq(3)
207
+ end
208
+ end
209
+
210
+ context 'when interval is specified' do
211
+ before do
212
+ @params = { start_date: '2014-01-01', end_date: '2014-01-08', id: @id }
213
+ 8.times { |day| Visits.increment(timestamp: "2014-01-0#{day + 1}", id: @id) }
214
+ end
215
+
216
+ context 'and is days' do
217
+ before do
218
+ @params[:interval] = :days
219
+ @result = Visits.aggregate(@params)
220
+ end
221
+
222
+ it 'returns the total over the date range' do
223
+ expect(@result[:visits]).to eq(8)
224
+ end
225
+
226
+ it 'returns the proper amount of data points' do
227
+ expect(@result[:days].size).to eq(8)
228
+ end
229
+
230
+ it 'returns the correct data for each point in the interval' do
231
+ @result[:days].each do |day|
232
+ expect(day[:visits]).to eq(1)
233
+ end
234
+ end
235
+
236
+ it 'returns the correct dates for each point in the interval' do
237
+ current_date = Date.parse(@params[:start_date])
238
+ @result[:days].each do |day|
239
+ expect(day[:date]).to eq(current_date.strftime('%Y-%m-%d'))
240
+ current_date = current_date.advance(days: +1)
241
+ end
242
+ end
243
+ end
244
+
245
+ context 'and is weeks' do
246
+ before do
247
+ @params[:interval] = :weeks
248
+ @result = Visits.aggregate(@params)
249
+ end
250
+
251
+ it 'returns the total over the date range' do
252
+ expect(@result[:visits]).to eq(8)
253
+ end
254
+
255
+ it 'returns the proper amount of data points' do
256
+ expect(@result[:weeks].size).to eq(2)
257
+ end
258
+
259
+ it 'returns the correct data for each point in the interval' do
260
+ expect(@result[:weeks][0][:visits]).to eq(5)
261
+ expect(@result[:weeks][1][:visits]).to eq(3)
262
+ end
263
+
264
+ it 'returns the correct dates for each point in the interval' do
265
+ expect(@result[:weeks][0][:date]).to eq('2014-W1')
266
+ expect(@result[:weeks][1][:date]).to eq('2014-W2')
267
+ end
268
+ end
269
+
270
+ context 'and is months' do
271
+ before do
272
+ @params[:interval] = :months
273
+ @result = Visits.aggregate(@params)
274
+ end
275
+
276
+ it 'returns the total over the date range' do
277
+ expect(@result[:visits]).to eq(8)
278
+ end
279
+
280
+ it 'returns the proper amount of data points' do
281
+ expect(@result[:months].size).to eq(1)
282
+ end
283
+
284
+ it 'returns the correct data for each point in the interval' do
285
+ expect(@result[:months][0][:visits]).to eq(8)
286
+ end
287
+
288
+ it 'returns the correct dates for each point in the interval' do
289
+ expect(@result[:months][0][:date]).to eq('2014-01')
290
+ end
291
+ end
292
+
293
+ context 'and is years' do
294
+ before do
295
+ @params[:interval] = :years
296
+ @result = Visits.aggregate(@params)
297
+ end
298
+
299
+ it 'returns the total over the date range' do
300
+ expect(@result[:visits]).to eq(8)
301
+ end
302
+
303
+ it 'returns the proper amount of data points' do
304
+ expect(@result[:years].size).to eq(1)
305
+ end
306
+
307
+ it 'returns the correct data for each point in the interval' do
308
+ expect(@result[:years][0][:visits]).to eq(8)
309
+ end
310
+
311
+ it 'returns the correct dates for each point in the interval' do
312
+ expect(@result[:years][0][:date]).to eq('2014')
313
+ end
314
+ end
315
+ end
316
+
317
+ context 'mutiple ids' do
318
+ before do
319
+ 9.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:1", '1', 1) }
320
+ 3.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:2", '3', 1) }
321
+ @params = { start_date: '2014-01-01', end_date: '2014-01-09', id: [1001, 2003] }
322
+ end
323
+
324
+ context 'when no interval is specified' do
325
+ it 'returns the aggregate total for both ids combined' do
326
+ result = Visits.aggregate(@params)
327
+ expect(result).to eq(12)
328
+ end
329
+ end
330
+
331
+ context 'when an interval is specified' do
332
+ before do
333
+ @result = Visits.aggregate(@params.merge!(interval: :days))
334
+ end
335
+
336
+ it 'returns the total over the date range' do
337
+ expect(@result[:visits]).to eq(12)
338
+ end
339
+
340
+ it 'returns the proper amount of data points' do
341
+ expect(@result[:days].size).to eq(9)
342
+ end
343
+
344
+ it 'returns the correct data for each point in the interval' do
345
+ 3.times do |num|
346
+ expect(@result[:days][num][:visits]).to eq(2)
347
+ end
348
+ (3..8).each do |num|
349
+ expect(@result[:days][num][:visits]).to eq(1)
350
+ end
351
+ end
352
+ end
353
+ end
354
+ end
355
+ end
356
+
357
+ context 'unique counter' do
358
+ before do
359
+ class Customers < Redtastic::Model
360
+ type :unique
361
+ resolution :days
362
+ end
363
+ @id = 1001
364
+ @timestamp = '2014-01-05'
365
+ @user1 = 4321
366
+ @user2 = 8765
367
+ @day_key = 'app1:customers:2014-01-05:1001'
368
+ @week_key = 'app1:customers:2014-W1:1001'
369
+ @month_key = 'app1:customers:2014-01:1001'
370
+ @year_key = 'app1:customers:2014:1001'
371
+ end
372
+
373
+ describe '#increment' do
374
+ context 'single ids' do
375
+ before do
376
+ Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user1)
377
+ Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user2)
378
+ end
379
+
380
+ it 'adds user 1 to the set' do
381
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
382
+ end
383
+
384
+ it 'adds user 2 to the set' do
385
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user2)).to be true
386
+ end
387
+
388
+ it 'adds user 1 to the weekly set' do
389
+ expect(Redtastic::Connection.redis.sismember(@week_key, @user1)).to be true
390
+ end
391
+
392
+ it 'adds user 1 to the monthly set' do
393
+ expect(Redtastic::Connection.redis.sismember(@month_key, @user1)).to be true
394
+ end
395
+
396
+ it 'adds user 1 to the yearly set' do
397
+ expect(Redtastic::Connection.redis.sismember(@year_key, @user1)).to be true
398
+ end
399
+ end
400
+
401
+ context 'multiple ids' do
402
+ before do
403
+ ids = [1001, 1002]
404
+ Customers.increment(id: ids, timestamp: @timestamp, unique_id: @user1)
405
+ end
406
+
407
+ it 'increments bits on both keys' do
408
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
409
+ expect(Redtastic::Connection.redis.sismember('app1:customers:2014-01-05:1002', @user1)).to be true
410
+ end
411
+ end
412
+ end
413
+
414
+ describe '#decrement' do
415
+ before do
416
+ # First add user 1
417
+ Redtastic::Connection.redis.sadd(@day_key, @user1)
418
+ end
419
+
420
+ it 'decrements user1 removing it from the set' do
421
+ # Make sure it was properly added first
422
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
423
+ Customers.decrement(id: @id, timestamp: @timestamp, unique_id: @user1)
424
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be false
425
+ end
426
+ end
427
+
428
+ describe '#find' do
429
+ context 'single ids' do
430
+ before do
431
+ Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user1)
432
+ end
433
+
434
+ it 'finds the value for a unique id on a single day' do
435
+ expect(Customers.find(id: @id, year: 2014, month: 1, day: 5, unique_id: @user1)).to eq(1)
436
+ expect(Customers.find(id: @id, year: 2014, month: 1, day: 5, unique_id: 1)).to eq(0)
437
+ end
438
+
439
+ it 'finds the value for a unique id in a single week' do
440
+ expect(Customers.find(id: @id, year: 2014, week: 1, unique_id: @user1)).to eq(1)
441
+ expect(Customers.find(id: @id, year: 2014, week: 1, unique_id: 1)).to eq(0)
442
+ end
443
+
444
+ it 'finds the value for a unique id in a single month' do
445
+ expect(Customers.find(id: @id, year: 2014, month: 1, unique_id: @user1)).to eq(1)
446
+ expect(Customers.find(id: @id, year: 2014, month: 1, unique_id: 1)).to eq(0)
447
+ end
448
+
449
+ it 'finds the value for a unique id in a single year' do
450
+ expect(Customers.find(id: @id, year: 2014, unique_id: @user1)).to eq(1)
451
+ expect(Customers.find(id: @id, year: 2014, unique_id: 1)).to eq(0)
452
+ end
453
+ end
454
+
455
+ context 'mutiple ids' do
456
+ before do
457
+ 2.times { Customers.increment(id: 1001, timestamp: @timestamp, unique_id: @user1) }
458
+ Customers.increment(id: 1002, timestamp: @timestamp, unique_id: @user1)
459
+ end
460
+
461
+ it 'returns an array of the values for each id' do
462
+ expected_result = [1, 1, 0]
463
+ params = { id: [1001, 1002, 1003], year: 2014, month: 1, day: 5, unique_id: @user1 }
464
+ expect(Customers.find(params)).to eq(expected_result)
465
+ end
466
+ end
467
+ end
468
+
469
+ describe '#aggregate' do
470
+ context 'when no interval is specified' do
471
+ it 'returns the total over the date range' do
472
+ 9.times { |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{@id}", @user1) }
473
+ 3.times { |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{@id}", @user2) }
474
+ result = Customers.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
475
+ expect(result).to eq(2)
476
+ end
477
+
478
+ it 'returns the correct total over the date range when the resolution is weeks' do
479
+ class Foo < Redtastic::Model
480
+ type :unique
481
+ resolution :weeks
482
+ end
483
+ 3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-W#{num}:#{@id}", @user1) }
484
+ 2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-W#{num}:#{@id}", @user2) }
485
+ result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
486
+ expect(result).to eq(2)
487
+ end
488
+
489
+ it 'returns the correct total over the date range when the resolution is months' do
490
+ class Foo < Redtastic::Model
491
+ type :unique
492
+ resolution :months
493
+ end
494
+ 3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-01:#{@id}", @user1) }
495
+ 2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-01:#{@id}", @user2) }
496
+ result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
497
+ expect(result).to eq(2)
498
+ end
499
+
500
+ it 'returns the correct total over the date range when the resolution is years' do
501
+ class Foo < Redtastic::Model
502
+ type :unique
503
+ resolution :years
504
+ end
505
+ 3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014:#{@id}", @user1) }
506
+ 2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014:#{@id}", @user2) }
507
+ result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
508
+ expect(result).to eq(2)
509
+ end
510
+ end
511
+
512
+ context 'when interval is specified' do
513
+ before do
514
+ @params = { start_date: '2014-01-01', end_date: '2014-01-09', id: @id }
515
+ 9.times { |day| Customers.increment(id: @id, timestamp: "2014-01-0#{day + 1}", unique_id: @user1) }
516
+ 3.times { |day| Customers.increment(id: @id, timestamp: "2014-01-0#{day + 1}", unique_id: @user2) }
517
+ end
518
+
519
+ context 'and is days' do
520
+ before do
521
+ @params[:interval] = :days
522
+ @result = Customers.aggregate(@params)
523
+ end
524
+
525
+ it 'returns the total over the date range' do
526
+ expect(@result[:customers]).to eq(2)
527
+ end
528
+
529
+ it 'returns the proper amount of data points' do
530
+ expect(@result[:days].size).to eq(9)
531
+ end
532
+
533
+ it 'returns the correct data for each point in the interval' do
534
+ 3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
535
+ 6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(1) }
536
+ end
537
+
538
+ it 'returns the correct dates for each point in the interval' do
539
+ current_date = Date.parse(@params[:start_date])
540
+ @result[:days].each do |day|
541
+ expect(day[:date]).to eq(current_date.strftime('%Y-%m-%d'))
542
+ current_date = current_date.advance(days: +1)
543
+ end
544
+ end
545
+ end
546
+
547
+ context 'and is weeks' do
548
+ before do
549
+ @params[:interval] = :weeks
550
+ @result = Customers.aggregate(@params)
551
+ end
552
+
553
+ it 'returns the total over the date range' do
554
+ expect(@result[:customers]).to eq(2)
555
+ end
556
+
557
+ it 'returns the proper amount of data points' do
558
+ expect(@result[:weeks].size).to eq(2)
559
+ end
560
+
561
+ it 'returns the correct data for each point in the interval' do
562
+ expect(@result[:weeks][0][:customers]).to eq(2)
563
+ expect(@result[:weeks][1][:customers]).to eq(1)
564
+ end
565
+
566
+ it 'returns the correct dates for each point in the interval' do
567
+ expect(@result[:weeks][0][:date]).to eq('2014-W1')
568
+ expect(@result[:weeks][1][:date]).to eq('2014-W2')
569
+ end
570
+ end
571
+
572
+ context 'and is years' do
573
+ before do
574
+ @params[:interval] = :years
575
+ @result = Customers.aggregate(@params)
576
+ end
577
+
578
+ it 'returns the total over the date range' do
579
+ expect(@result[:customers]).to eq(2)
580
+ end
581
+
582
+ it 'returns the proper amount of data points' do
583
+ expect(@result[:years].size).to eq(1)
584
+ end
585
+
586
+ it 'returns the correct data for each point in the interval' do
587
+ expect(@result[:years][0][:customers]).to eq(2)
588
+ end
589
+
590
+ it 'returns the correct dates for each point in the interval' do
591
+ expect(@result[:years][0][:date]).to eq('2014')
592
+ end
593
+ end
594
+ end
595
+
596
+ context 'multiple ids' do
597
+ before do
598
+ 9.times do |day|
599
+ Customers.increment(id: 1001, timestamp: "2014-01-0#{day + 1}", unique_id: @user1)
600
+ Customers.increment(id: 1002, timestamp: "2014-01-0#{day + 1}", unique_id: @user1)
601
+ end
602
+ 3.times { |day| Customers.increment(id: 1001, timestamp: "2014-01-0#{day + 1}", unique_id: @user2) }
603
+ @params = { start_date: '2014-01-01', end_date: '2014-01-09', id: [1001, 2003] }
604
+ end
605
+
606
+ context 'when no interval is specified' do
607
+ it 'returns the aggregate total for both ids combined' do
608
+ result = Customers.aggregate(@params)
609
+ expect(result).to eq(2)
610
+ end
611
+ end
612
+
613
+ context 'when an interval is specified' do
614
+ before do
615
+ @result = Customers.aggregate(@params.merge!(interval: :days))
616
+ end
617
+
618
+ it 'returns the total over the date range' do
619
+ expect(@result[:customers]).to eq(2)
620
+ end
621
+
622
+ it 'returns the proper amount of data points' do
623
+ expect(@result[:days].size).to eq(9)
624
+ end
625
+
626
+ it 'returns the correct data for each point in the interval' do
627
+ 3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
628
+ (3..8).each { |num| expect(@result[:days][num][:customers]).to eq(1) }
629
+ end
630
+ end
631
+ end
632
+ end
633
+ end
634
+
635
+ context 'attributes' do
636
+ before do
637
+ class Customers < Redtastic::Model
638
+ type :unique
639
+ resolution :days
640
+ end
641
+ class Males < Redtastic::Model
642
+ type :unique
643
+ end
644
+ class Mobile < Redtastic::Model
645
+ type :unique
646
+ end
647
+ @user1 = 1111
648
+ @user2 = 2222
649
+ @user3 = 3333
650
+ @attribute_key = 'app1:males'
651
+ end
652
+
653
+ describe '#increment' do
654
+ before do
655
+ Males.increment(unique_id: @user1)
656
+ Males.increment(unique_id: @user2)
657
+ end
658
+
659
+ it 'adds user1 to the set' do
660
+ result = Redtastic::Connection.redis.sismember(@attribute_key, @user1)
661
+ expect(result).to be true
662
+ end
663
+
664
+ it 'adds user2 to the set' do
665
+ result = Redtastic::Connection.redis.sismember(@attribute_key, @user2)
666
+ expect(result).to be true
667
+ end
668
+ end
669
+
670
+ describe '#decrement' do
671
+ before do
672
+ Males.increment(unique_id: @user1)
673
+ end
674
+
675
+ it 'adds user1 to the set' do
676
+ Males.decrement(unique_id: @user1)
677
+ result = Redtastic::Connection.redis.sismember(@attribute_key, @user1)
678
+ expect(result).to be false
679
+ end
680
+ end
681
+
682
+ describe '#find' do
683
+ before do
684
+ Males.increment(unique_id: @user1)
685
+ end
686
+
687
+ it 'returns 1 for a unique_id that is in the attribute set' do
688
+ expect(Males.find(unique_id: @user1)).to eq(1)
689
+ end
690
+
691
+ it 'returns 0 for a unique_id that is not in the attribute set' do
692
+ expect(Males.find(unique_id: @user2)).to eq(0)
693
+ end
694
+ end
695
+
696
+ describe '#aggregate' do
697
+ before do
698
+ Males.increment(unique_id: @user1)
699
+ Males.increment(unique_id: @user2)
700
+ Mobile.increment(unique_id: @user2)
701
+ 9.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{2222}", @user1) }
702
+ 3.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{1111}", @user2) }
703
+ 3.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{1111}", @user3) }
704
+ @params = { id: [1111, 2222], start_date: '2014-01-01', end_date: '2014-01-09' }
705
+ @attributes = []
706
+ end
707
+
708
+ context 'when no interval is specified' do
709
+ context 'and single attribute is specified' do
710
+ it 'returns the total over the date range' do
711
+ @attributes << :males
712
+ result = Customers.aggregate(@params.merge!(attributes: @attributes))
713
+ expect(result).to eq(2)
714
+ end
715
+
716
+ it 'does not require use of an array if specifying only one attribute' do
717
+ result = Customers.aggregate(@params.merge!(attributes: :males))
718
+ expect(result).to eq(2)
719
+ end
720
+ end
721
+
722
+ context 'and multiple attributes are specified' do
723
+ it 'returns the total over the date range' do
724
+ @attributes << :males
725
+ @attributes << :mobile
726
+ result = Customers.aggregate(@params.merge!(attributes: @attributes))
727
+ expect(result).to eq(1)
728
+ end
729
+ end
730
+ end
731
+
732
+ context 'when interval is specified' do
733
+ context 'and single attribute is specified' do
734
+ before do
735
+ @attributes << :males
736
+ @result = Customers.aggregate(@params.merge!(attributes: @attributes, interval: :days))
737
+ end
738
+
739
+ it 'returns the total over the date range' do
740
+ expect(@result[:customers]).to eq(2)
741
+ end
742
+
743
+ it 'returns the proper amount of data points' do
744
+ expect(@result[:days].size).to eq(9)
745
+ end
746
+
747
+ it 'returns the correct data for each point in the interval' do
748
+ 3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
749
+ 6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(1) }
750
+ end
751
+ end
752
+
753
+ context 'and multiple attributes are specified' do
754
+ before do
755
+ @attributes << :males
756
+ @attributes << :mobile
757
+ @result = Customers.aggregate(@params.merge!(attributes: @attributes, interval: :days))
758
+ end
759
+
760
+ it 'returns the total over the date range' do
761
+ expect(@result[:customers]).to eq(1)
762
+ end
763
+
764
+ it 'returns the proper amount of data points' do
765
+ expect(@result[:days].size).to eq(9)
766
+ end
767
+
768
+ it 'returns the correct data for each point in the interval' do
769
+ 3.times { |num| expect(@result[:days][num][:customers]).to eq(1) }
770
+ 6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(0) }
771
+ end
772
+ end
773
+ end
774
+ end
775
+ end
776
+ end