trackoid_mongoid4 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,490 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ class TestModel
4
+ include Mongoid::Document
5
+ include Mongoid::Tracking
6
+
7
+ field :name # Dummy field
8
+
9
+ # Note that references to "track" and "aggregate" in this test are mixed
10
+ # for testing purposes. Trackoid does not make any difference in the
11
+ # declaration order of tracking fields and aggregate tokens.
12
+ track :visits
13
+ aggregate :browsers do |b| b.split.first.downcase if b; end
14
+
15
+ track :uniques
16
+ aggregate :referers do |r| r.split.last.downcase if r; end
17
+ end
18
+
19
+ class SecondTestModel
20
+ include Mongoid::Document
21
+ include Mongoid::Tracking
22
+
23
+ field :name # Dummy field
24
+ track :something
25
+
26
+ aggregate :aggregate_one do 1 end
27
+ aggregate :aggregate_two do "p" end
28
+ aggregate :aggregate_three do BSON::ObjectId.new end
29
+ aggregate :aggregate_four do Time.now end
30
+ end
31
+
32
+ # Namespaced models to test avoid name collisions
33
+ # Collitions may happen when declaring internal aggregate classes for a model
34
+ # which has the same name as other models in another namespace
35
+ module MyCompany
36
+ class TestPerson
37
+ include Mongoid::Document
38
+ include Mongoid::Tracking
39
+
40
+ field :my_name
41
+
42
+ track :logins
43
+ aggregate :initials do |n| n.to_s[0]; end
44
+ end
45
+ end
46
+
47
+ module YourCompany
48
+ class TestPerson
49
+ include Mongoid::Document
50
+ include Mongoid::Tracking
51
+
52
+ field :your_name
53
+
54
+ track :logins
55
+ aggregate :initials do |n| n.to_s[0]; end
56
+ end
57
+ end
58
+
59
+
60
+ describe Mongoid::Tracking::Aggregates do
61
+
62
+ before(:all) do
63
+ @mock = TestModel.new(:name => "TestInstance")
64
+ end
65
+
66
+ it "should define a class model named after the original model" do
67
+ expect(defined?(TestModelAggregates)).not_to eq(nil)
68
+ end
69
+
70
+ it "should define a class model named after the original second model" do
71
+ expect(defined?(SecondTestModelAggregates)).not_to eq(nil)
72
+ end
73
+
74
+ it "should create a has_many relationship in the original model" do
75
+ # Note that due to ActiveSupport "class_inheritable_accessor" this method
76
+ # is available both as class method and instance method.
77
+ expect(@mock.class.method_defined?(:browsers_accessor)).to eq true
78
+ end
79
+
80
+ it "should have the aggregates klass in a class/instance var" do
81
+ # Note that due to ActiveSupport "class_inheritable_accessor" this method
82
+ # is available both as class method and instance method.
83
+ @mock.class.aggregate_klass == TestModelAggregates
84
+ end
85
+
86
+ it "should create a hash in the class with all aggregate fields" do
87
+ # Note that due to ActiveSupport "class_inheritable_accessor" this method
88
+ # is available both as class method and instance method.
89
+ expect(@mock.class.aggregate_fields.keys.to_set).to eq [ :browsers, :referers ].to_set
90
+ end
91
+
92
+ it "should create an array in the class with all aggregate fields even when monkey patching" do
93
+ class TestModel
94
+ aggregate :quarters do |q|
95
+ "Q1";
96
+ end
97
+ end
98
+ expect(@mock.class.aggregate_fields.keys.to_set).to eq [ :browsers, :referers, :quarters ].to_set
99
+ end
100
+
101
+ it "the aggregated class should have the same tracking fields as the parent class" do
102
+ expect(TestModelAggregates.tracked_fields).to eq TestModel.tracked_fields
103
+ end
104
+
105
+ it "should raise error if we try to add an aggregation token twice" do
106
+ expect {
107
+ class TestModel
108
+ aggregate :referers do
109
+ "(none)"
110
+ end
111
+ end
112
+ }.to raise_error Mongoid::Tracking::Errors::AggregationAlreadyDefined
113
+ end
114
+
115
+ it "should raise error if we try to use 'hours' as aggregate" do
116
+ expect {
117
+ class TestModel
118
+ aggregate :hours do
119
+ "(none)"
120
+ end
121
+ end
122
+ }.to raise_error Mongoid::Tracking::Errors::AggregationNameDeprecated
123
+ end
124
+
125
+ it "should have Mongoid accessors defined" do
126
+ tm = TestModel.create(:name => "Dummy")
127
+ expect(tm.send(tm.class.send(:internal_accessor_name, "browsers")).class).to eq Mongoid::Relations::Targets::Enumerable
128
+ expect(tm.send(tm.class.send(:internal_accessor_name, "referers")).class).to eq Mongoid::Relations::Targets::Enumerable
129
+ expect(tm.send(tm.class.send(:internal_accessor_name, "quarters")).class).to eq Mongoid::Relations::Targets::Enumerable
130
+ end
131
+
132
+ it "should indicate this is an aggregated traking object with aggregated?" do
133
+ expect(@mock.aggregated?).to eq true
134
+ end
135
+
136
+ it "should indicate this is an aggregated class with aggregated?" do
137
+ expect(@mock.class.aggregated?).to eq true
138
+ end
139
+
140
+ it "should raise error if already defined class with the same aggregated klass name" do
141
+ expect {
142
+ class MockTestAggregates
143
+ def dummy; true; end
144
+ end
145
+ class MockTest
146
+ include Mongoid::Document
147
+ include Mongoid::Tracking
148
+ track :something
149
+ aggregate :other_something do
150
+ "other"
151
+ end
152
+ end
153
+ }.to raise_error Mongoid::Tracking::Errors::ClassAlreadyDefined
154
+ end
155
+
156
+ it "should NOT raise error if the already defined class is our aggregated model" do
157
+ expect {
158
+ class MockTest2
159
+ include Mongoid::Document
160
+ include Mongoid::Tracking
161
+ track :something
162
+ end
163
+ class MockTest2
164
+ include Mongoid::Document
165
+ include Mongoid::Tracking
166
+ track :something_else
167
+ aggregate :other_something do
168
+ "other"
169
+ end
170
+ end
171
+ }.not_to raise_error #Mongoid::Tracking::Errors::ClassAlreadyDefined
172
+ end
173
+
174
+ it "should raise error although the already defined class includes tracking" do
175
+ expect {
176
+ class MockTest3Aggregates
177
+ include Mongoid::Document
178
+ include Mongoid::Tracking
179
+ track :something
180
+ end
181
+ class MockTest3
182
+ include Mongoid::Document
183
+ include Mongoid::Tracking
184
+ track :something_else
185
+ aggregate :other_something do
186
+ "other"
187
+ end
188
+ end
189
+ }.to raise_error Mongoid::Tracking::Errors::ClassAlreadyDefined
190
+ end
191
+
192
+ describe "testing different object class for aggregation key" do
193
+ let(:second_test_model) do
194
+ SecondTestModel.create(name: "test")
195
+ end
196
+
197
+ it "should correctly save all aggregation keys as strings (inc)" do
198
+ second_test_model.something("test").inc
199
+ expect(second_test_model.something.aggregate_one.first.key.is_a?(String)).to eq true
200
+ expect(second_test_model.something.aggregate_two.first.key.is_a?(String)).to eq true
201
+ expect(second_test_model.something.aggregate_three.first.key.is_a?(String)).to eq true
202
+ expect(second_test_model.something.aggregate_four.first.key.is_a?(String)).to eq true
203
+ end
204
+
205
+ it "should correctly save all aggregation keys as strings (set)" do
206
+ second_test_model.something("test").set(5)
207
+ expect(second_test_model.something.aggregate_one.first.key.is_a?(String)).to eq true
208
+ expect(second_test_model.something.aggregate_two.first.key.is_a?(String)).to eq true
209
+ expect(second_test_model.something.aggregate_three.first.key.is_a?(String)).to eq true
210
+ expect(second_test_model.something.aggregate_four.first.key.is_a?(String)).to eq true
211
+ end
212
+ end
213
+
214
+ describe "when tracking a model with aggregation data" do
215
+ let(:test_model) do
216
+ TestModel.create(:name => "test")
217
+ end
218
+
219
+ it "calling an aggregation scope should return the appropiate class" do
220
+ expect(test_model.browsers.class).to eq Mongoid::Tracking::TrackerAggregates
221
+ end
222
+
223
+ it "should increment visits for all aggregated instances" do
224
+ test_model.visits("Mozilla Firefox").inc
225
+ expect(test_model.browsers.count).to eq 1
226
+ expect(test_model.referers.count).to eq 1
227
+ expect(test_model.quarters.count).to eq 1
228
+ end
229
+
230
+ it "should increment visits for specific aggregation keys" do
231
+ test_model.visits("Mozilla Firefox").inc
232
+ expect(test_model.browsers("mozilla").size).to eq 1
233
+ expect(test_model.referers("firefox").size).to eq 1
234
+ expect(test_model.quarters("Q1").size).to eq 1
235
+ end
236
+
237
+ it "should NOT increment visits for different aggregation keys" do
238
+ expect(test_model.browsers("internet explorer").size).to eq 0
239
+ expect(test_model.referers("yahoo slurp").size).to eq 0
240
+ expect(test_model.quarters("Q2").size).to eq 0
241
+ end
242
+
243
+ it "should have 1 visits today" do
244
+ test_model.visits("Mozilla Firefox").inc
245
+ expect(test_model.visits.browsers.today).to eq [["mozilla", 1]]
246
+ expect(test_model.visits.referers.today).to eq [["firefox", 1]]
247
+ end
248
+
249
+ it "should have 0 visits yesterday" do
250
+ test_model.visits("Mozilla Firefox").inc
251
+ expect(test_model.visits.browsers.yesterday).to eq [["mozilla", 0]]
252
+ expect(test_model.visits.referers.yesterday).to eq [["firefox", 0]]
253
+ end
254
+
255
+ it "should have 1 visits last 7 days" do
256
+ test_model.visits("Mozilla Firefox").inc
257
+ expect(test_model.visits.browsers.last_days(7)).to eq [["mozilla", [0, 0, 0, 0, 0, 0, 1]]]
258
+ expect(test_model.visits.referers.last_days(7)).to eq [["firefox", [0, 0, 0, 0, 0, 0, 1]]]
259
+ end
260
+
261
+ it "should work also for arbitrary days" do
262
+ test_model.visits("Mozilla Firefox").inc
263
+ expect(test_model.visits.browsers.last_days(15)).to eq [["mozilla", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]]]
264
+ expect(test_model.visits.referers.last_days(15)).to eq [["firefox", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]]]
265
+ end
266
+
267
+ it "should work adding 1 visit with different aggregation data" do
268
+ test_model.visits("Mozilla Firefox").inc
269
+ test_model.visits("Google Chrome").inc
270
+ expect(test_model.visits.browsers.today).to match [["mozilla", 1], ["google", 1]]
271
+ expect(test_model.visits.referers.today).to match [["firefox", 1], ["chrome", 1]]
272
+
273
+ # Just for testing array manipulations
274
+ expect(test_model.visits.browsers.today.inject(0) {|total, c| c.last + total }).to eq 2
275
+ end
276
+
277
+ it "should return only values when specifying the aggregation key" do
278
+ test_model.visits("Mozilla Firefox").inc
279
+ expect(test_model.visits.browsers("mozilla").today).to eq 1
280
+ end
281
+
282
+ it "should work also with set" do
283
+ test_model.visits("Mozilla Firefox").inc
284
+ test_model.visits("Google Chrome").set(5)
285
+ expect(test_model.visits.browsers.today).to match [["mozilla", 1], ["google", 5]]
286
+ expect(test_model.visits.referers.today).to match [["firefox", 1], ["chrome", 5]]
287
+ expect(test_model.visits.today).to eq 5
288
+ end
289
+
290
+ it "should work without aggregation information" do
291
+ test_model.visits("Mozilla Firefox").set(1)
292
+ test_model.visits("Google Chrome").set(6)
293
+ test_model.visits.inc
294
+
295
+
296
+ expect(test_model.visits.browsers.today).to match [["mozilla", 1], ["google", 6]]
297
+ expect(test_model.visits.referers.today).to match [["firefox", 1], ["chrome", 6]]
298
+
299
+ # A more throughout test would check totals...
300
+ visits_today = test_model.visits.today
301
+ visits_today_with_browser = test_model.visits.browsers.today.inject(0) {|total, c| c.last + total }
302
+ expect(visits_today).to eq visits_today_with_browser
303
+ end
304
+ end
305
+
306
+ describe "When using reset method for aggregates" do
307
+ let(:test_model) do
308
+ TestModel.create(:name => "test")
309
+ end
310
+
311
+ before(:each) do
312
+ test_model.visits("Mozilla Firefox").set(1, "2010-07-11")
313
+ test_model.visits("Google Chrome").set(2, "2010-07-11")
314
+ test_model.visits("Internet Explorer").set(3, "2010-07-11")
315
+
316
+ test_model.visits("Mozilla Firefox").set(4, "2010-07-14")
317
+ test_model.visits("Google Chrome").set(5, "2010-07-14")
318
+ test_model.visits("Internet Explorer").set(6, "2010-07-14")
319
+
320
+ test_model.uniques("Mozilla Firefox").set(1, "2010-07-11")
321
+ test_model.uniques("Google Chrome").set(2, "2010-07-11")
322
+ test_model.uniques("Internet Explorer").set(3, "2010-07-11")
323
+
324
+ test_model.uniques("Mozilla Firefox").set(4, "2010-07-14")
325
+ test_model.uniques("Google Chrome").set(5, "2010-07-14")
326
+ test_model.uniques("Internet Explorer").set(6, "2010-07-14")
327
+ end
328
+
329
+ it "should have the correct values when using a value" do
330
+ test_model.visits.reset(99, "2010-07-14")
331
+
332
+ expect(test_model.visits.on("2010-07-14")).to eq 99
333
+ expect(test_model.visits.browsers.all_values).to match [
334
+ ["mozilla", [1, 0, 0, 99]],
335
+ ["google", [2, 0, 0, 99]],
336
+ ["internet", [3, 0, 0, 99]]
337
+ ]
338
+ expect(test_model.visits.referers.all_values).to match [
339
+ ["firefox", [1, 0, 0, 99]],
340
+ ["chrome", [2, 0, 0, 99]],
341
+ ["explorer", [3, 0, 0, 99]]
342
+ ]
343
+ end
344
+
345
+ it "should delete the values when using nil" do
346
+ test_model.visits.reset(nil, "2010-07-14")
347
+ expect(test_model.visits.on("2010-07-14")).to eq 0
348
+ expect(test_model.visits.browsers.all_values).to match [
349
+ ["mozilla", [1]],
350
+ ["google", [2]],
351
+ ["internet", [3]]
352
+ ]
353
+ expect(test_model.visits.referers.all_values).to match [
354
+ ["firefox", [1]],
355
+ ["chrome", [2]],
356
+ ["explorer", [3]]
357
+ ]
358
+ end
359
+
360
+ it "erase method sould also work" do
361
+ test_model.visits.erase("2010-07-14")
362
+
363
+ expect(test_model.visits.on("2010-07-14")).to eq 0
364
+ expect(test_model.visits.browsers.all_values).to match [
365
+ ["mozilla", [1]],
366
+ ["google", [2]],
367
+ ["internet", [3]]
368
+ ]
369
+ end
370
+
371
+ it "should reset the correct tracking fields" do
372
+ test_model.visits.reset(99, "2010-07-14")
373
+
374
+ expect(test_model.uniques.on("2010-07-14")).to eq 6
375
+ expect(test_model.uniques.browsers.all_values).to match [
376
+ ["mozilla", [1, 0, 0, 4]],
377
+ ["google", [2, 0, 0, 5]],
378
+ ["internet", [3, 0, 0, 6]]
379
+ ]
380
+ expect(test_model.uniques.referers.all_values).to match [
381
+ ["firefox", [1, 0, 0, 4]],
382
+ ["chrome", [2, 0, 0, 5]],
383
+ ["explorer", [3, 0, 0, 6]]
384
+ ]
385
+ end
386
+
387
+ it "should erase the correct tracking fields" do
388
+ test_model.visits.erase("2010-07-14")
389
+
390
+ expect(test_model.uniques.on("2010-07-14")).to eq 6
391
+ expect(test_model.uniques.browsers.all_values).to match [
392
+ ["mozilla", [1, 0, 0, 4]],
393
+ ["google", [2, 0, 0, 5]],
394
+ ["internet", [3, 0, 0, 6]]
395
+ ]
396
+ expect(test_model.uniques.referers.all_values).to match [
397
+ ["firefox", [1, 0, 0, 4]],
398
+ ["chrome", [2, 0, 0, 5]],
399
+ ["explorer", [3, 0, 0, 6]]
400
+ ]
401
+ end
402
+ end
403
+
404
+ describe "Testing all accessors" do
405
+ let(:test_model) { TestModel.create(name: "test") }
406
+
407
+ before do
408
+ # For 'first' values
409
+ test_model.visits("Mozilla Firefox").set(1, "2010-07-11")
410
+ test_model.visits("Google Chrome").set(2, "2010-07-12")
411
+ test_model.visits("Internet Explorer").set(3, "2010-07-13")
412
+
413
+ # For 'last' values
414
+ test_model.visits("Mozilla Firefox").set(4, "2010-07-14")
415
+ test_model.visits("Google Chrome").set(5, "2010-07-15")
416
+ test_model.visits("Internet Explorer").set(6, "2010-07-16")
417
+ end
418
+
419
+ it "should return the correct values for .all_values" do
420
+ expect(test_model.visits.all_values).to eq [1, 2, 3, 4, 5, 6]
421
+ end
422
+
423
+ it "should return the all values for every aggregate" do
424
+ expect(test_model.visits.browsers.all_values).to match [
425
+ ["mozilla", [1, 0, 0, 4]],
426
+ ["google", [2, 0, 0, 5]],
427
+ ["internet", [3, 0, 0, 6]]
428
+ ]
429
+ end
430
+
431
+ it "should return the correct first_date for every aggregate" do
432
+ expect(test_model.visits.browsers.first_date).to match [
433
+ ["mozilla", Time.parse("2010-07-11")],
434
+ ["google", Time.parse("2010-07-12")],
435
+ ["internet", Time.parse("2010-07-13")]
436
+ ]
437
+ end
438
+
439
+ it "should return the correct last_date for every aggregate" do
440
+ expect(test_model.visits.browsers.last_date).to match [
441
+ ["mozilla", Time.parse("2010-07-14")],
442
+ ["google", Time.parse("2010-07-15")],
443
+ ["internet", Time.parse("2010-07-16")]
444
+ ]
445
+ end
446
+
447
+ it "should return the first value for aggregates" do
448
+ expect(test_model.visits.browsers.first_value).to match [
449
+ ["mozilla", 1],
450
+ ["google", 2],
451
+ ["internet", 3]
452
+ ]
453
+ end
454
+
455
+ it "should return the last value for aggregates" do
456
+ expect(test_model.visits.browsers.last_value).to match [
457
+ ["mozilla", 4],
458
+ ["google", 5],
459
+ ["internet", 6]
460
+ ]
461
+ end
462
+ end
463
+
464
+ describe "When using models with same name on different namespaces" do
465
+ let(:test_person1) do
466
+ MyCompany::TestPerson.create(my_name: "twoixter")
467
+ end
468
+
469
+ let(:test_person2) do
470
+ YourCompany::TestPerson.create(your_name: "test")
471
+ end
472
+
473
+ before do
474
+ test_person1.logins("ASCII").set(1, "2012-07-07")
475
+ test_person1.logins("EBCDIC").set(1, "2012-07-07")
476
+
477
+ test_person2.logins("UTF8").set(1, "2012-07-07")
478
+ test_person2.logins("LATIN1").set(1, "2012-07-07")
479
+ end
480
+
481
+ it "should be different objects" do
482
+ expect(test_person1.my_name).not_to eq test_person2.your_name
483
+ end
484
+
485
+ it "should yield different aggregates" do
486
+ expect(test_person1.logins.initials.on("2012-07-07")).to match [["A", 1], ["E", 1]]
487
+ expect(test_person2.logins.initials.on("2012-07-07")).to match [["U", 1], ["L", 1]]
488
+ end
489
+ end
490
+ end
@@ -0,0 +1,96 @@
1
+ #
2
+ # This is a simple spec to check if tracking works within embedded documents
3
+ # If this passes, the rest of the funcionality it's assumed to work (TZ, etc)
4
+ #
5
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
6
+
7
+ class TestEmbedOne
8
+ include Mongoid::Document
9
+ field :name # Dummy field
10
+ embeds_one :embedded_test
11
+ end
12
+
13
+ class TestEmbedMany
14
+ include Mongoid::Document
15
+ field :name # Dummy field
16
+ embeds_many :embedded_test
17
+ end
18
+
19
+ class EmbeddedTest
20
+ include Mongoid::Document
21
+ include Mongoid::Tracking
22
+ field :name # Dummy field
23
+ track :visits
24
+ embedded_in :test_embed_one
25
+ embedded_in :test_embed_many
26
+ end
27
+
28
+ # And Now For Something Completely Different...
29
+
30
+ class TestEmbedOuter
31
+ include Mongoid::Document
32
+ field :name # Dummy field
33
+ embeds_one :test_embed_middle
34
+ end
35
+
36
+ class TestEmbedMiddle
37
+ include Mongoid::Document
38
+ field :name # Dummy field
39
+ embedded_in :test_embed_outer
40
+ embeds_one :test_embed_final
41
+ end
42
+
43
+ class TestEmbedFinal
44
+ include Mongoid::Document
45
+ include Mongoid::Tracking
46
+ field :name # Dummy field
47
+ track :visits
48
+ embedded_in :test_embed_middle
49
+ end
50
+
51
+
52
+ describe Mongoid::Tracking do
53
+
54
+ # Useful to see all MongoDB operations in place while RSpec is working
55
+ before(:all) do
56
+ # Moped.logger.level = Logger::DEBUG
57
+ end
58
+
59
+ context "within a document which embeds one or more models with tracking" do
60
+ let(:today) { Time.now }
61
+ let(:mock_one) { TestEmbedOne.create(:name => "Parent", :embedded_test => {:name => "Child"}) }
62
+ let(:mock_many) { TestEmbedMany.create(:name => "Parent", :embedded_test => [{:name => "Child1"}, {:name => "Child2"} ]) }
63
+
64
+ it "should have the tracking field working and not bleed to the parent" do
65
+ expect(mock_one.respond_to?(:visits)).to eq(false)
66
+ expect(mock_one.embedded_test.respond_to?(:visits)).to eq(true)
67
+ expect(mock_many.respond_to?(:visits)).to eq(false)
68
+ expect(mock_many.embedded_test.first.respond_to?(:visits)).to eq(true)
69
+ expect(mock_many.embedded_test.last.respond_to?(:visits)).to eq(true)
70
+ end
71
+
72
+ it "the tracking data should work fine" do
73
+ mock_one.embedded_test.visits.inc(today)
74
+ expect(mock_one.embedded_test.visits.on(today)).to eq 1
75
+
76
+ mock_many.embedded_test.first.visits.inc(today)
77
+ expect(mock_many.embedded_test.first.visits.on(today)).to eq 1
78
+ expect(mock_many.embedded_test.last.visits.on(today)).to eq 0
79
+ end
80
+ end
81
+
82
+ context "within a three level embedded model" do
83
+ let(:today) { Time.now }
84
+ let(:outer) { TestEmbedOuter.create(:name => "Outer", :test_embed_middle => {:name => "Middle", :test_embed_final => { :name => "Final" }}) }
85
+
86
+ it "should just work..." do
87
+ expect(outer.respond_to?(:visits)).to eq(false)
88
+ expect(outer.test_embed_middle.respond_to?(:visits)).to eq(false)
89
+ expect(outer.test_embed_middle.test_embed_final.respond_to?(:visits)).to eq(true)
90
+
91
+ outer.test_embed_middle.test_embed_final.visits.inc(today)
92
+ expect(outer.test_embed_middle.test_embed_final.visits.on(today)).to eq 1
93
+ expect(outer.test_embed_middle.test_embed_final.visits.on(today - 1.day)).to eq 0
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,114 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Range do
4
+ describe "using the diff method" do
5
+ before do
6
+ ENV['TZ'] = 'America/Los_Angeles'
7
+ end
8
+
9
+ it "should work for normal ranges" do
10
+ expect((0..2).diff).to eq 3
11
+ expect((0...2).diff).to eq 2
12
+ end
13
+
14
+ it "should work for Time ranges (DAYS)" do
15
+ now = Time.now
16
+ inc_range = now..(now + 1*Range::DAYS)
17
+ exc_range = now...(now + 1*Range::DAYS)
18
+
19
+ expect(inc_range.diff).to eq 2
20
+ expect(exc_range.diff).to eq 1
21
+ end
22
+
23
+ it "should work for Time ranges (HOURS)" do
24
+ now = Time.now
25
+ inc_range = now..(now + 10*Range::HOURS)
26
+ exc_range = now...(now + 10*Range::HOURS)
27
+
28
+ expect(inc_range.diff(Range::HOURS)).to eq 11
29
+ expect(exc_range.diff(Range::HOURS)).to eq 10
30
+ end
31
+
32
+ it "should also work when using helper methods" do
33
+ now = Time.now
34
+ inc_range = now..(now + 10*Range::HOURS)
35
+ exc_range = now...(now + 10*Range::HOURS)
36
+
37
+ expect(inc_range.hour_diff).to eq 11
38
+ expect(exc_range.hour_diff).to eq 10
39
+ end
40
+
41
+ it "should behave like normal ranges for 1 element" do
42
+ now = Time.now
43
+ inc_range = now..now
44
+ exc_range = now...now
45
+
46
+ expect(inc_range.diff).to eq 1
47
+ expect(exc_range.diff).to eq 0
48
+ end
49
+
50
+ it "should keep Time UTC and DST properties" do
51
+ date1 = Time.local(2011, 4, 1, 0, 0)
52
+ date2 = Time.utc(2011, 4, 1, 0, 0)
53
+
54
+ range1 = date1..date1
55
+ range2 = date2..date2
56
+
57
+ range1.first.should_not be_utc
58
+ range1.first.should be_dst
59
+ range2.first.should be_utc
60
+ range2.first.should_not be_dst
61
+ end
62
+ end
63
+
64
+ describe "using the map method" do
65
+ it "should work for normal ranges (using enumerator)" do
66
+ inc_result = (0..2).map.to_a
67
+ inc_result.should == [0, 1, 2]
68
+
69
+ exc_result = (0...2).map.to_a
70
+ exc_result.should == [0, 1]
71
+ end
72
+
73
+ it "should work for normal ranges (using block)" do
74
+ inc_result = (0..2).map {|e| e}
75
+ inc_result.should == [0, 1, 2]
76
+
77
+ exc_result = (0...2).map {|e| e}
78
+ exc_result.should == [0, 1]
79
+ end
80
+
81
+ it "should work for Time ranges" do
82
+ date = Time.utc(2011, 4, 1, 0, 0)
83
+ inc_range = date..(date + 5*Range::DAYS)
84
+ inc_result = inc_range.map {|d| d.to_i_timestamp}
85
+ inc_result.should == [15065, 15066, 15067, 15068, 15069, 15070]
86
+
87
+ exc_range = date...(date + 5*Range::DAYS)
88
+ exc_result = exc_range.map {|d| d.to_i_timestamp}
89
+ exc_result.should == [15065, 15066, 15067, 15068, 15069]
90
+ end
91
+
92
+ it "should work for empty excluding Time ranges" do
93
+ date = Time.utc(2011, 4, 1, 0, 0)
94
+ exc_range = date...date
95
+ exc_result = exc_range.map {|d| d.to_i_timestamp}
96
+ exc_result.should == []
97
+ end
98
+
99
+ it "should return an array if no block given" do
100
+ date = Time.utc(2011, 4, 1, 0, 0)
101
+ result = (date..(date + 5*Range::DAYS)).map
102
+ result.count.should == 6
103
+
104
+ # Result is now an array
105
+ result.map(&:to_i_timestamp).should == [15065, 15066, 15067, 15068, 15069, 15070]
106
+ end
107
+
108
+ it "should also work using helper methods" do
109
+ date = Time.utc(2011, 4, 1, 0, 0)
110
+ result = (date..(date + 5*Range::HOURS)).hour_map
111
+ result.count.should == 6
112
+ end
113
+ end
114
+ end