reportable 1.0.0
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.
- data/HISTORY.md +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +29 -0
- data/generators/reportable_migration/reportable_migration_generator.rb +9 -0
- data/generators/reportable_migration/templates/migration.erb +40 -0
- data/lib/saulabs/reportable.rb +63 -0
- data/lib/saulabs/reportable/cumulated_report.rb +42 -0
- data/lib/saulabs/reportable/grouping.rb +140 -0
- data/lib/saulabs/reportable/report.rb +165 -0
- data/lib/saulabs/reportable/report_cache.rb +163 -0
- data/lib/saulabs/reportable/reporting_period.rb +181 -0
- data/lib/saulabs/reportable/sparkline_tag_helper.rb +62 -0
- data/rails/init.rb +9 -0
- data/spec/boot.rb +25 -0
- data/spec/classes/cumulated_report_spec.rb +169 -0
- data/spec/classes/grouping_spec.rb +155 -0
- data/spec/classes/report_cache_spec.rb +296 -0
- data/spec/classes/report_spec.rb +574 -0
- data/spec/classes/reporting_period_spec.rb +335 -0
- data/spec/db/database.yml +15 -0
- data/spec/db/schema.rb +38 -0
- data/spec/other/report_method_spec.rb +44 -0
- data/spec/other/sparkline_tag_helper_spec.rb +64 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +23 -0
- metadata +100 -0
@@ -0,0 +1,155 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Saulabs::Reportable::Grouping do
|
4
|
+
|
5
|
+
describe '#new' do
|
6
|
+
|
7
|
+
it 'should raise an error if an unsupported grouping is specified' do
|
8
|
+
lambda { Saulabs::Reportable::Grouping.new(:unsupported) }.should raise_error(ArgumentError)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#to_sql' do
|
14
|
+
|
15
|
+
describe 'for MySQL' do
|
16
|
+
|
17
|
+
before do
|
18
|
+
ActiveRecord::Base.connection.stub!(:adapter_name).and_return('MySQL')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should use DATE_FORMAT with format string "%Y/%m/%d/%H" for grouping :hour' do
|
22
|
+
Saulabs::Reportable::Grouping.new(:hour).send(:to_sql, 'created_at').should == "DATE_FORMAT(created_at, '%Y/%m/%d/%H')"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should use DATE_FORMAT with format string "%Y/%m/%d" for grouping :day' do
|
26
|
+
Saulabs::Reportable::Grouping.new(:day).send(:to_sql, 'created_at').should == "DATE_FORMAT(created_at, '%Y/%m/%d')"
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should use YEARWEEK with mode 3 for grouping :week' do
|
30
|
+
Saulabs::Reportable::Grouping.new(:week).send(:to_sql, 'created_at').should == "YEARWEEK(created_at, 3)"
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should use DATE_FORMAT with format string "%Y/%m" for grouping :month' do
|
34
|
+
Saulabs::Reportable::Grouping.new(:month).send(:to_sql, 'created_at').should == "DATE_FORMAT(created_at, '%Y/%m')"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'for PostgreSQL' do
|
40
|
+
|
41
|
+
before do
|
42
|
+
ActiveRecord::Base.connection.stub!(:adapter_name).and_return('PostgreSQL')
|
43
|
+
end
|
44
|
+
|
45
|
+
for grouping in [:hour, :day, :week, :month] do
|
46
|
+
|
47
|
+
it "should use date_trunc with truncation identifier \"#{grouping.to_s}\" for grouping :#{grouping.to_s}" do
|
48
|
+
Saulabs::Reportable::Grouping.new(grouping).send(:to_sql, 'created_at').should == "date_trunc('#{grouping.to_s}', created_at)"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'for SQLite3' do
|
56
|
+
|
57
|
+
before do
|
58
|
+
ActiveRecord::Base.connection.stub!(:adapter_name).and_return('SQLite')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should use strftime with format string "%Y/%m/%d/%H" for grouping :hour' do
|
62
|
+
Saulabs::Reportable::Grouping.new(:hour).send(:to_sql, 'created_at').should == "strftime('%Y/%m/%d/%H', created_at)"
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should use strftime with format string "%Y/%m/%d" for grouping :day' do
|
66
|
+
Saulabs::Reportable::Grouping.new(:day).send(:to_sql, 'created_at').should == "strftime('%Y/%m/%d', created_at)"
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should use date with mode "weekday 0" for grouping :week' do
|
70
|
+
Saulabs::Reportable::Grouping.new(:week).send(:to_sql, 'created_at').should == "date(created_at, 'weekday 0')"
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should use strftime with format string "%Y/%m" for grouping :month' do
|
74
|
+
Saulabs::Reportable::Grouping.new(:month).send(:to_sql, 'created_at').should == "strftime('%Y/%m', created_at)"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#date_parts_from_db_string' do
|
82
|
+
|
83
|
+
describe 'for SQLite3' do
|
84
|
+
|
85
|
+
before do
|
86
|
+
ActiveRecord::Base.connection.stub!(:adapter_name).and_return('SQLite')
|
87
|
+
end
|
88
|
+
|
89
|
+
for grouping in [[:hour, '2008/12/31/12'], [:day, '2008/12/31'], [:month, '2008/12']] do
|
90
|
+
|
91
|
+
it "should split the string with '/' for grouping :#{grouping[0].to_s}" do
|
92
|
+
Saulabs::Reportable::Grouping.new(grouping[0]).date_parts_from_db_string(grouping[1]).should == grouping[1].split('/').map(&:to_i)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should split the string with "-" and return teh calendar year and week for grouping :week' do
|
98
|
+
db_string = '2008-2-1'
|
99
|
+
expected = [2008, 5]
|
100
|
+
|
101
|
+
Saulabs::Reportable::Grouping.new(:week).date_parts_from_db_string(db_string).should == expected
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
describe 'for PostgreSQL' do
|
107
|
+
|
108
|
+
before do
|
109
|
+
ActiveRecord::Base.connection.stub!(:adapter_name).and_return('PostgreSQL')
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should split the date part of the string with "-" and read out the hour for grouping :hour' do
|
113
|
+
Saulabs::Reportable::Grouping.new(:hour).date_parts_from_db_string('2008-12-03 06:00:00').should == [2008, 12, 03, 6]
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should split the date part of the string with "-" for grouping :day' do
|
117
|
+
Saulabs::Reportable::Grouping.new(:day).date_parts_from_db_string('2008-12-03 00:00:00').should == [2008, 12, 03]
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should split the date part of the string with "-" and calculate the calendar week for grouping :week' do
|
121
|
+
Saulabs::Reportable::Grouping.new(:week).date_parts_from_db_string('2008-12-01 00:00:00').should == [2008, 49]
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should split the date part of the string with "-" and return year and month for grouping :month' do
|
125
|
+
Saulabs::Reportable::Grouping.new(:month).date_parts_from_db_string('2008-12-01 00:00:00').should == [2008, 12]
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'for MySQL' do
|
131
|
+
|
132
|
+
before do
|
133
|
+
ActiveRecord::Base.connection.stub!(:adapter_name).and_return('MySQL')
|
134
|
+
end
|
135
|
+
|
136
|
+
for grouping in [[:hour, '2008/12/31/12'], [:day, '2008/12/31'], [:month, '2008/12']] do
|
137
|
+
|
138
|
+
it "should split the string with '/' for grouping :#{grouping[0].to_s}" do
|
139
|
+
Saulabs::Reportable::Grouping.new(grouping[0]).date_parts_from_db_string(grouping[1]).should == grouping[1].split('/').map(&:to_i)
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should use the first 4 numbers for the year and the last 2 numbers for the week for grouping :week' do
|
145
|
+
db_string = '200852'
|
146
|
+
expected = [2008, 52]
|
147
|
+
|
148
|
+
Saulabs::Reportable::Grouping.new(:week).date_parts_from_db_string(db_string).should == expected
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
@@ -0,0 +1,296 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Saulabs::Reportable::ReportCache do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@report = Saulabs::Reportable::Report.new(User, :registrations, :limit => 10)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '.clear_for' do
|
10
|
+
|
11
|
+
it 'should delete all entries in the cache for the klass and report name' do
|
12
|
+
Saulabs::Reportable::ReportCache.should_receive(:delete_all).once.with(:conditions => {
|
13
|
+
:model_name => User.name,
|
14
|
+
:report_name => 'registrations'
|
15
|
+
})
|
16
|
+
|
17
|
+
Saulabs::Reportable::ReportCache.clear_for(User, :registrations)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.process' do
|
23
|
+
|
24
|
+
before do
|
25
|
+
Saulabs::Reportable::ReportCache.stub!(:find).and_return([])
|
26
|
+
Saulabs::Reportable::ReportCache.stub!(:prepare_result).and_return([])
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should raise an ArgumentError if no block is given' do
|
30
|
+
lambda do
|
31
|
+
Saulabs::Reportable::ReportCache.process(@report, @report.options)
|
32
|
+
end.should raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'sould start a transaction' do
|
36
|
+
Saulabs::Reportable::ReportCache.should_receive(:transaction)
|
37
|
+
|
38
|
+
Saulabs::Reportable::ReportCache.process(@report, @report.options) {}
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'with :live_data = true' do
|
42
|
+
|
43
|
+
before do
|
44
|
+
@options = @report.options.merge(:live_data => true)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should yield to the given block' do
|
48
|
+
lambda {
|
49
|
+
Saulabs::Reportable::ReportCache.process(@report, @options) { raise YieldMatchException.new }
|
50
|
+
}.should raise_error(YieldMatchException)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should yield the first reporting period if not all required data could be retrieved from the cache' do
|
54
|
+
reporting_period = Saulabs::Reportable::ReportingPeriod.new(
|
55
|
+
@report.options[:grouping],
|
56
|
+
Time.now - 3.send(@report.options[:grouping].identifier)
|
57
|
+
)
|
58
|
+
Saulabs::Reportable::ReportCache.stub!(:all).and_return([Saulabs::Reportable::ReportCache.new])
|
59
|
+
|
60
|
+
Saulabs::Reportable::ReportCache.process(@report, @options) do |begin_at, end_at|
|
61
|
+
begin_at.should == Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping], @report.options[:limit]).date_time
|
62
|
+
end_at.should == nil
|
63
|
+
[]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should yield the reporting period after the last one in the cache if all required data could be retrieved from the cache' do
|
68
|
+
reporting_period = Saulabs::Reportable::ReportingPeriod.new(
|
69
|
+
@report.options[:grouping],
|
70
|
+
Time.now - @report.options[:limit].send(@report.options[:grouping].identifier)
|
71
|
+
)
|
72
|
+
cached = Saulabs::Reportable::ReportCache.new
|
73
|
+
cached.stub!(:reporting_period).and_return(reporting_period.date_time)
|
74
|
+
Saulabs::Reportable::ReportCache.stub!(:all).and_return(Array.new(@report.options[:limit] - 1, Saulabs::Reportable::ReportCache.new), cached)
|
75
|
+
|
76
|
+
Saulabs::Reportable::ReportCache.process(@report, @options) do |begin_at, end_at|
|
77
|
+
begin_at.should == reporting_period.date_time
|
78
|
+
end_at.should == nil
|
79
|
+
[]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe 'with :live_data = false' do
|
86
|
+
|
87
|
+
it 'should not yield if all required data could be retrieved from the cache' do
|
88
|
+
Saulabs::Reportable::ReportCache.stub!(:all).and_return(Array.new(@report.options[:limit], Saulabs::Reportable::ReportCache.new))
|
89
|
+
|
90
|
+
lambda {
|
91
|
+
Saulabs::Reportable::ReportCache.process(@report, @report.options) { raise YieldMatchException.new }
|
92
|
+
}.should_not raise_error(YieldMatchException)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should yield to the block if no data could be retrieved from the cache' do
|
96
|
+
Saulabs::Reportable::ReportCache.stub!(:all).and_return([])
|
97
|
+
|
98
|
+
lambda {
|
99
|
+
Saulabs::Reportable::ReportCache.process(@report, @report.options) { raise YieldMatchException.new }
|
100
|
+
}.should raise_error(YieldMatchException)
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'with :end_date = <some date>' do
|
104
|
+
|
105
|
+
before do
|
106
|
+
@options = @report.options.merge(:end_date => Time.now)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should yield the last date and time of the reporting period for the specified end date' do
|
110
|
+
reporting_period = Saulabs::Reportable::ReportingPeriod.new(@report.options[:grouping], @options[:end_date])
|
111
|
+
|
112
|
+
Saulabs::Reportable::ReportCache.process(@report, @options) do |begin_at, end_at|
|
113
|
+
end_at.should == reporting_period.last_date_time
|
114
|
+
[]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should read existing data from the cache' do
|
123
|
+
Saulabs::Reportable::ReportCache.should_receive(:all).once.with(
|
124
|
+
:conditions => [
|
125
|
+
'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND `condition` = ? AND reporting_period >= ?',
|
126
|
+
@report.klass.to_s,
|
127
|
+
@report.name.to_s,
|
128
|
+
@report.options[:grouping].identifier.to_s,
|
129
|
+
@report.aggregation.to_s,
|
130
|
+
@report.options[:conditions].to_s,
|
131
|
+
Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping], 10).date_time
|
132
|
+
],
|
133
|
+
:limit => 10,
|
134
|
+
:order => 'reporting_period ASC'
|
135
|
+
).and_return([])
|
136
|
+
|
137
|
+
Saulabs::Reportable::ReportCache.process(@report, @report.options) { [] }
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should utilize the end_date in the conditions' do
|
141
|
+
end_date = Time.now
|
142
|
+
Saulabs::Reportable::ReportCache.should_receive(:all).once.with(
|
143
|
+
:conditions => [
|
144
|
+
'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND `condition` = ? AND reporting_period BETWEEN ? AND ?',
|
145
|
+
@report.klass.to_s,
|
146
|
+
@report.name.to_s,
|
147
|
+
@report.options[:grouping].identifier.to_s,
|
148
|
+
@report.aggregation.to_s,
|
149
|
+
@report.options[:conditions].to_s,
|
150
|
+
Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping], 9).date_time,
|
151
|
+
Saulabs::Reportable::ReportingPeriod.new(@report.options[:grouping], end_date).date_time
|
152
|
+
],
|
153
|
+
:limit => 10,
|
154
|
+
:order => 'reporting_period ASC'
|
155
|
+
).and_return([])
|
156
|
+
|
157
|
+
Saulabs::Reportable::ReportCache.process(@report, @report.options.merge(:end_date => end_date)) { [] }
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should read existing data from the cache for the correct grouping if one other than the report's default grouping is specified" do
|
161
|
+
grouping = Saulabs::Reportable::Grouping.new(:month)
|
162
|
+
Saulabs::Reportable::ReportCache.should_receive(:find).once.with(
|
163
|
+
:all,
|
164
|
+
:conditions => [
|
165
|
+
'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND `condition` = ? AND reporting_period >= ?',
|
166
|
+
@report.klass.to_s,
|
167
|
+
@report.name.to_s,
|
168
|
+
grouping.identifier.to_s,
|
169
|
+
@report.aggregation.to_s,
|
170
|
+
@report.options[:conditions].to_s,
|
171
|
+
Saulabs::Reportable::ReportingPeriod.first(grouping, 10).date_time
|
172
|
+
],
|
173
|
+
:limit => 10,
|
174
|
+
:order => 'reporting_period ASC'
|
175
|
+
).and_return([])
|
176
|
+
|
177
|
+
Saulabs::Reportable::ReportCache.process(@report, { :limit => 10, :grouping => grouping }) { [] }
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should yield the first reporting period if the cache is empty' do
|
181
|
+
Saulabs::Reportable::ReportCache.process(@report, @report.options) do |begin_at, end_at|
|
182
|
+
begin_at.should == Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping], 10).date_time
|
183
|
+
end_at.should == nil
|
184
|
+
[]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe '.prepare_result' do
|
190
|
+
|
191
|
+
before do
|
192
|
+
@current_reporting_period = Saulabs::Reportable::ReportingPeriod.new(@report.options[:grouping])
|
193
|
+
@new_data = [[@current_reporting_period.previous.date_time, 1.0]]
|
194
|
+
Saulabs::Reportable::ReportingPeriod.stub!(:from_db_string).and_return(@current_reporting_period.previous)
|
195
|
+
@cached = Saulabs::Reportable::ReportCache.new
|
196
|
+
@cached.stub!(:save!)
|
197
|
+
Saulabs::Reportable::ReportCache.stub!(:build_cached_data).and_return(@cached)
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'should create :limit instances of Saulabs::Reportable::ReportCache with value 0.0 if no new data has been read and nothing was cached' do
|
201
|
+
Saulabs::Reportable::ReportCache.should_receive(:build_cached_data).exactly(10).times.with(
|
202
|
+
@report,
|
203
|
+
@report.options[:grouping],
|
204
|
+
@report.options[:conditions],
|
205
|
+
anything(),
|
206
|
+
0.0
|
207
|
+
).and_return(@cached)
|
208
|
+
|
209
|
+
Saulabs::Reportable::ReportCache.send(:prepare_result, [], [], @report, @report.options)
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should create a new Saulabs::Reportable::ReportCache with the correct value if new data has been read' do
|
213
|
+
Saulabs::Reportable::ReportCache.should_receive(:build_cached_data).exactly(9).times.with(
|
214
|
+
@report,
|
215
|
+
@report.options[:grouping],
|
216
|
+
@report.options[:conditions],
|
217
|
+
anything(),
|
218
|
+
0.0
|
219
|
+
).and_return(@cached)
|
220
|
+
Saulabs::Reportable::ReportCache.should_receive(:build_cached_data).once.with(
|
221
|
+
@report,
|
222
|
+
@report.options[:grouping],
|
223
|
+
@report.options[:conditions],
|
224
|
+
@current_reporting_period.previous,
|
225
|
+
1.0
|
226
|
+
).and_return(@cached)
|
227
|
+
|
228
|
+
Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'should save the created Saulabs::Reportable::ReportCache' do
|
232
|
+
@cached.should_receive(:save!).once
|
233
|
+
|
234
|
+
Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'should return an array of arrays of Dates and Floats' do
|
238
|
+
result = Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
|
239
|
+
|
240
|
+
result.should be_kind_of(Array)
|
241
|
+
result[0].should be_kind_of(Array)
|
242
|
+
result[0][0].should be_kind_of(Date)
|
243
|
+
result[0][1].should be_kind_of(Float)
|
244
|
+
end
|
245
|
+
|
246
|
+
describe 'with :live_data = false' do
|
247
|
+
|
248
|
+
before do
|
249
|
+
@result = Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'should return an array of length :limit' do
|
253
|
+
@result.length.should == 10
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'should not include an entry for the current reporting period' do
|
257
|
+
@result.find { |row| row[0] == @current_reporting_period.date_time }.should be_nil
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
describe 'with :live_data = true' do
|
263
|
+
|
264
|
+
before do
|
265
|
+
options = @report.options.merge(:live_data => true)
|
266
|
+
@result = Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, options)
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'should return an array of length (:limit + 1)' do
|
270
|
+
@result.length.should == 11
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'should include an entry for the current reporting period' do
|
274
|
+
@result.find { |row| row[0] == @current_reporting_period.date_time }.should_not be_nil
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
describe '.find_value' do
|
281
|
+
|
282
|
+
before do
|
283
|
+
@data = [[Saulabs::Reportable::ReportingPeriod.new(Saulabs::Reportable::Grouping.new(:day)), 3.0]]
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'should return the correct value when new data has been read for the reporting period' do
|
287
|
+
Saulabs::Reportable::ReportCache.send(:find_value, @data, @data[0][0]).should == 3.0
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'should return 0.0 when no data has been read for the reporting period' do
|
291
|
+
Saulabs::Reportable::ReportCache.send(:find_value, @data, @data[0][0].next).should == 0.0
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|