compendium 0.0.1 → 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.
- checksums.yaml +15 -0
- data/README.md +70 -4
- data/Rakefile +4 -0
- data/app/assets/stylesheets/compendium/_metrics.css.scss +92 -0
- data/app/assets/stylesheets/compendium/options.css.scss +41 -0
- data/app/assets/stylesheets/compendium/report.css.scss +22 -0
- data/app/classes/compendium/presenters/base.rb +30 -0
- data/app/classes/compendium/presenters/chart.rb +31 -0
- data/app/classes/compendium/presenters/metric.rb +19 -0
- data/app/classes/compendium/presenters/option.rb +97 -0
- data/app/classes/compendium/presenters/query.rb +23 -0
- data/app/classes/compendium/presenters/settings/query.rb +22 -0
- data/app/classes/compendium/presenters/settings/table.rb +23 -0
- data/app/classes/compendium/presenters/table.rb +81 -0
- data/app/controllers/compendium/reports_controller.rb +52 -0
- data/app/helpers/compendium/reports_helper.rb +21 -0
- data/app/views/compendium/reports/run.haml +1 -0
- data/app/views/compendium/reports/setup.haml +14 -0
- data/compendium.gemspec +7 -1
- data/config/initializers/rails/active_record/connection_adapters/quoting.rb +14 -0
- data/config/initializers/ruby/numeric.rb +26 -0
- data/config/locales/en.yml +5 -0
- data/lib/compendium/abstract_chart_provider.rb +30 -0
- data/lib/compendium/chart_provider/amcharts.rb +20 -0
- data/lib/compendium/context_wrapper.rb +27 -0
- data/lib/compendium/dsl.rb +79 -0
- data/lib/compendium/engine/mount.rb +13 -0
- data/lib/compendium/engine.rb +8 -0
- data/lib/compendium/metric.rb +29 -0
- data/lib/compendium/open_hash.rb +68 -0
- data/lib/compendium/option.rb +37 -0
- data/lib/compendium/param_types.rb +91 -0
- data/lib/compendium/params.rb +40 -0
- data/lib/compendium/query.rb +94 -0
- data/lib/compendium/report.rb +56 -0
- data/lib/compendium/result_set.rb +24 -0
- data/lib/compendium/version.rb +1 -1
- data/lib/compendium.rb +46 -1
- data/spec/context_wrapper_spec.rb +71 -0
- data/spec/dsl_spec.rb +90 -0
- data/spec/metric_spec.rb +84 -0
- data/spec/option_spec.rb +12 -0
- data/spec/param_types_spec.rb +147 -0
- data/spec/params_spec.rb +28 -0
- data/spec/presenters/base_spec.rb +20 -0
- data/spec/presenters/option_spec.rb +49 -0
- data/spec/query_spec.rb +33 -0
- data/spec/report_spec.rb +93 -0
- data/spec/spec_helper.rb +1 -0
- metadata +135 -14
data/lib/compendium/version.rb
CHANGED
data/lib/compendium.rb
CHANGED
@@ -1,5 +1,50 @@
|
|
1
|
-
require
|
1
|
+
require 'compendium/engine'
|
2
|
+
require 'compendium/version'
|
3
|
+
require 'active_support/configurable'
|
2
4
|
|
3
5
|
module Compendium
|
6
|
+
autoload :AbstractChartProvider, 'compendium/abstract_chart_provider'
|
7
|
+
autoload :ChartProvider, 'compendium/abstract_chart_provider'
|
8
|
+
autoload :ContextWrapper, 'compendium/context_wrapper'
|
9
|
+
autoload :DSL, 'compendium/dsl'
|
10
|
+
autoload :Metric, 'compendium/metric'
|
11
|
+
autoload :Option, 'compendium/option'
|
12
|
+
autoload :Params, 'compendium/params'
|
13
|
+
autoload :Query, 'compendium/query'
|
14
|
+
autoload :ResultSet, 'compendium/result_set'
|
15
|
+
autoload :Report, 'compendium/report'
|
4
16
|
|
17
|
+
autoload :Param, 'compendium/param_types'
|
18
|
+
autoload :BooleanParam, 'compendium/param_types'
|
19
|
+
autoload :DateParam, 'compendium/param_types'
|
20
|
+
autoload :DropdownParam, 'compendium/param_types'
|
21
|
+
autoload :ParamWithChoices, 'compendium/param_types'
|
22
|
+
autoload :RadioParam, 'compendium/param_types'
|
23
|
+
|
24
|
+
def self.reports
|
25
|
+
@reports ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
# Configures global settings for Compendium
|
29
|
+
# Compendium.configure do |config|
|
30
|
+
# config.chart_provider = :AmCharts
|
31
|
+
# end
|
32
|
+
def self.configure(&block)
|
33
|
+
yield @config ||= Compendium::Configuration.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.config
|
37
|
+
@config
|
38
|
+
end
|
39
|
+
|
40
|
+
# need a Class for 3.0
|
41
|
+
class Configuration #:nodoc:
|
42
|
+
include ActiveSupport::Configurable
|
43
|
+
|
44
|
+
config_accessor :chart_provider
|
45
|
+
end
|
46
|
+
|
47
|
+
configure do |config|
|
48
|
+
config.chart_provider = Compendium::AbstractChartProvider.find_chart_provider
|
49
|
+
end
|
5
50
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'compendium/context_wrapper'
|
2
|
+
|
3
|
+
class Wrapper1
|
4
|
+
def test_val
|
5
|
+
123
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Wrapper2
|
10
|
+
def wrapped
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Wrapper3
|
16
|
+
def wrapper_num
|
17
|
+
3
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Wrapper4
|
22
|
+
def wrapper_num
|
23
|
+
4
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Compendium::ContextWrapper do
|
28
|
+
describe ".wrap" do
|
29
|
+
let(:w1) { Wrapper1.new }
|
30
|
+
let(:w2) { Wrapper2.new }
|
31
|
+
let(:w3) { Wrapper3.new }
|
32
|
+
let(:w4) { Wrapper4.new }
|
33
|
+
|
34
|
+
subject { described_class.wrap(w2, w1) }
|
35
|
+
|
36
|
+
it { should respond_to :test_val }
|
37
|
+
it { should respond_to :wrapped }
|
38
|
+
|
39
|
+
its(:test_val) { should == 123 }
|
40
|
+
its(:wrapped) { should == true }
|
41
|
+
|
42
|
+
it "should not affect the original objects" do
|
43
|
+
subject
|
44
|
+
w1.should_not respond_to :wrapped
|
45
|
+
w2.should_not respond_to :test_val
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should yield a block if given" do
|
49
|
+
described_class.wrap(w2, w1) { test_val }.should == 123
|
50
|
+
end
|
51
|
+
|
52
|
+
context "overriding methods" do
|
53
|
+
subject { described_class.wrap(w4, w3) }
|
54
|
+
its(:wrapper_num) { should == 4 }
|
55
|
+
end
|
56
|
+
|
57
|
+
context "nested wrapping" do
|
58
|
+
let(:inner) { described_class.wrap(w2, w1) }
|
59
|
+
subject { described_class.wrap(inner, w3) }
|
60
|
+
|
61
|
+
it { should respond_to :test_val }
|
62
|
+
it { should respond_to :wrapped }
|
63
|
+
it { should respond_to :wrapper_num }
|
64
|
+
|
65
|
+
it "should not extend the inner wrap" do
|
66
|
+
subject
|
67
|
+
inner.should_not respond_to :wrapper_num
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/dsl_spec.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'compendium'
|
2
|
+
require 'compendium/dsl'
|
3
|
+
|
4
|
+
describe Compendium::DSL do
|
5
|
+
subject do
|
6
|
+
Class.new do
|
7
|
+
extend Compendium::DSL
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#option" do
|
12
|
+
before { subject.option :starting_on, :date }
|
13
|
+
|
14
|
+
its(:options) { should include :starting_on }
|
15
|
+
specify { subject.options[:starting_on].should be_date }
|
16
|
+
|
17
|
+
it "should allow previously defined options to be redefined" do
|
18
|
+
subject.option :starting_on, :boolean
|
19
|
+
subject.options[:starting_on].should be_boolean
|
20
|
+
subject.options[:starting_on].should_not be_date
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#query" do
|
25
|
+
subject do
|
26
|
+
Class.new(Compendium::Report) do
|
27
|
+
query :test
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
its(:queries) { should include :test }
|
32
|
+
|
33
|
+
it "should relate the new query back to the report instance" do
|
34
|
+
r = subject.new
|
35
|
+
r.test.report.should == r
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not relate a query to the report class" do
|
39
|
+
subject.test.report.should be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#chart" do
|
44
|
+
before { subject.chart(:chart) }
|
45
|
+
|
46
|
+
its(:queries) { should include :chart }
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#data" do
|
50
|
+
before { subject.data(:data) }
|
51
|
+
|
52
|
+
its(:queries) { should include :data }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#metric" do
|
56
|
+
let(:metric_proc) { ->{ :metric } }
|
57
|
+
|
58
|
+
before do
|
59
|
+
subject.query :test
|
60
|
+
subject.metric :test_metric, metric_proc, through: :test
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should add a metric to the given query" do
|
64
|
+
subject.queries[:test].metrics.first.name.should == :test_metric
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should set the metric command" do
|
68
|
+
subject.queries[:test].metrics.first.command.should == metric_proc
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should raise an error if through is not specified" do
|
72
|
+
expect{ subject.metric :test_metric, metric_proc }.to raise_error ArgumentError, 'through option must be specified for metric'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should raise an error if specified for an invalid query" do
|
76
|
+
expect{ subject.metric :test_metric, metric_proc, through: :fake }.to raise_error ArgumentError, 'query fake is not defined'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should allow previously defined queries to be redefined by name" do
|
81
|
+
subject.query :test_query
|
82
|
+
subject.test_query foo: :bar
|
83
|
+
subject.queries[:test_query].options.should == { foo: :bar }
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should allow previously defined queries to be accessed by name" do
|
87
|
+
subject.query :test_query
|
88
|
+
subject.test_query.should == subject.queries[:test_query]
|
89
|
+
end
|
90
|
+
end
|
data/spec/metric_spec.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'compendium/metric'
|
2
|
+
|
3
|
+
class MetricContext
|
4
|
+
def calculate(data)
|
5
|
+
data.first.first
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Compendium::Metric do
|
10
|
+
let(:ctx) { MetricContext.new }
|
11
|
+
let(:data) { [[1, 2, 3], [4, 5, 6]] }
|
12
|
+
|
13
|
+
subject { described_class.new(:test_metric, :query, nil) }
|
14
|
+
|
15
|
+
describe "#run" do
|
16
|
+
it "should delegate the command to the context when the command is a symbol" do
|
17
|
+
subject.command = :calculate
|
18
|
+
subject.run(ctx, data).should == 1
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should call the command when it is a proc" do
|
22
|
+
subject.command = -> d { d.flatten.inject(:+) }
|
23
|
+
subject.run(ctx, data).should == 21
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should allow procs that refer back to the context" do
|
27
|
+
subject.command = -> d { calculate(d) * 2 }
|
28
|
+
subject.run(ctx, data).should == 2
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when an if proc is given" do
|
32
|
+
before { subject.command = -> * { 100 } }
|
33
|
+
|
34
|
+
it "should calculate the metric if the proc evaluates to true" do
|
35
|
+
subject.options[:if] = ->{ true }
|
36
|
+
subject.run(ctx, data).should == 100
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not calculate the metric if the proc evaluates to false" do
|
40
|
+
subject.options[:if] = ->{ false }
|
41
|
+
subject.run(ctx, data).should be_nil
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should clear the result if the proc evaluates to false" do
|
45
|
+
subject.options[:if] = ->{ false }
|
46
|
+
subject.result = 123
|
47
|
+
subject.run(ctx, data)
|
48
|
+
subject.result.should be_nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when an unless proc is given" do
|
53
|
+
before { subject.command = -> * { 100 } }
|
54
|
+
|
55
|
+
it "should calculate the metric if the proc evaluates to false" do
|
56
|
+
subject.options[:unless] = ->{ false }
|
57
|
+
subject.run(ctx, data).should == 100
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not calculate the metric if the proc evaluates to true" do
|
61
|
+
subject.options[:unless] = ->{ true }
|
62
|
+
subject.run(ctx, data).should be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should clear the result if the proc evaluates to false" do
|
66
|
+
subject.options[:unless] = ->{ true }
|
67
|
+
subject.result = 123
|
68
|
+
subject.run(ctx, data)
|
69
|
+
subject.result.should be_nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#ran?" do
|
75
|
+
it "should return true if there are any results" do
|
76
|
+
subject.stub(result: 123)
|
77
|
+
subject.should have_ran
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return false if there are no results" do
|
81
|
+
subject.should_not have_ran
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/spec/option_spec.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'compendium/option'
|
2
|
+
|
3
|
+
describe Compendium::Option do
|
4
|
+
it "should raise an ArgumentError if no name is given" do
|
5
|
+
expect { described_class.new }.to raise_error ArgumentError, "name must be provided"
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should set up type predicates from the type option" do
|
9
|
+
o = described_class.new(name: :option, type: :date)
|
10
|
+
o.should be_date
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'compendium/param_types'
|
2
|
+
|
3
|
+
describe Compendium::Param do
|
4
|
+
subject{ described_class.new(:test) }
|
5
|
+
|
6
|
+
it { should_not be_boolean }
|
7
|
+
it { should_not be_date }
|
8
|
+
it { should_not be_dropdown }
|
9
|
+
it { should_not be_radio }
|
10
|
+
|
11
|
+
describe "#==" do
|
12
|
+
it "should compare to the param's value" do
|
13
|
+
subject.stub(value: :test_value)
|
14
|
+
subject.should == :test_value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe Compendium::ParamWithChoices do
|
20
|
+
subject{ described_class.new(0, %w(a b c)) }
|
21
|
+
|
22
|
+
it { should_not be_boolean }
|
23
|
+
it { should_not be_date }
|
24
|
+
it { should_not be_dropdown }
|
25
|
+
it { should_not be_radio }
|
26
|
+
|
27
|
+
it "should return the index when given an index" do
|
28
|
+
p = described_class.new(1, [:foo, :bar, :baz])
|
29
|
+
p.should == 1
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return the index when given a value" do
|
33
|
+
p = described_class.new(:foo, [:foo, :bar, :baz])
|
34
|
+
p.should == 0
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return the index when given a string value" do
|
38
|
+
p = described_class.new("2", [:foo, :bar, :baz])
|
39
|
+
p.should == 2
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should raise an error if given an invalid index" do
|
43
|
+
expect { described_class.new(3, [:foo, :bar, :baz]) }.to raise_error IndexError
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should raise an error if given a value that is not included in the choices" do
|
47
|
+
expect { described_class.new(:quux, [:foo, :bar, :baz]) }.to raise_error IndexError
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#value" do
|
51
|
+
it "should return the value of the given choice" do
|
52
|
+
p = described_class.new(2, [:foo, :bar, :baz])
|
53
|
+
p.value.should == :baz
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe Compendium::BooleanParam do
|
59
|
+
subject{ described_class.new(true) }
|
60
|
+
|
61
|
+
it { should be_boolean }
|
62
|
+
it { should_not be_date }
|
63
|
+
it { should_not be_dropdown }
|
64
|
+
it { should_not be_radio }
|
65
|
+
|
66
|
+
it "should pass along 0 and 1" do
|
67
|
+
described_class.new(0).should == 0
|
68
|
+
described_class.new(1).should == 1
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should convert a numeric string to a number" do
|
72
|
+
described_class.new('0').should == 0
|
73
|
+
described_class.new('1').should == 1
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return 0 for a truthy value" do
|
77
|
+
described_class.new(true).should == 0
|
78
|
+
described_class.new(:abc).should == 0
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return 1 for a falsey value" do
|
82
|
+
described_class.new(false).should == 1
|
83
|
+
described_class.new(nil).should == 1
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#value" do
|
87
|
+
it "should return true for a truthy value" do
|
88
|
+
described_class.new(true).value.should == true
|
89
|
+
described_class.new(:abc).value.should == true
|
90
|
+
described_class.new(0).value.should == true
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return false for a falsey value" do
|
94
|
+
described_class.new(false).value.should == false
|
95
|
+
described_class.new(nil).value.should == false
|
96
|
+
described_class.new(1).value.should == false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#!" do
|
101
|
+
it "should return false if the boolean is true" do
|
102
|
+
!described_class.new(true).should == false
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should return true if the boolean is false" do
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe Compendium::DateParam do
|
112
|
+
subject{ described_class.new(Date.today) }
|
113
|
+
|
114
|
+
it { should_not be_boolean }
|
115
|
+
it { should be_date }
|
116
|
+
it { should_not be_dropdown }
|
117
|
+
it { should_not be_radio }
|
118
|
+
|
119
|
+
it "should convert date strings to date objects" do
|
120
|
+
p = described_class.new("2010-05-20")
|
121
|
+
p.should == Date.new(2010, 5, 20)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should convert other date/time formats to date objects" do
|
125
|
+
described_class.new(DateTime.new(2010, 5, 20, 10, 30, 59)) == Date.new(2010, 5, 20)
|
126
|
+
described_class.new(Time.new(2010, 5, 20, 10, 30, 59)) == Date.new(2010, 5, 20)
|
127
|
+
described_class.new(Date.new(2010, 5, 20)) == Date.new(2010, 5, 20)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe Compendium::DropdownParam do
|
132
|
+
subject{ described_class.new(0, %w(a b c)) }
|
133
|
+
|
134
|
+
it { should_not be_boolean }
|
135
|
+
it { should_not be_date }
|
136
|
+
it { should be_dropdown }
|
137
|
+
it { should_not be_radio }
|
138
|
+
end
|
139
|
+
|
140
|
+
describe Compendium::RadioParam do
|
141
|
+
subject{ described_class.new(0, %w(a b c)) }
|
142
|
+
|
143
|
+
it { should_not be_boolean }
|
144
|
+
it { should_not be_date }
|
145
|
+
it { should_not be_dropdown }
|
146
|
+
it { should be_radio }
|
147
|
+
end
|
data/spec/params_spec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'compendium/params'
|
2
|
+
|
3
|
+
describe Compendium::Params do
|
4
|
+
let(:options) { {
|
5
|
+
starting_on: Compendium::Option.new(name: :starting_on, type: :date, default: ->{ Date.today }),
|
6
|
+
ending_on: Compendium::Option.new(name: :ending_on, type: :date),
|
7
|
+
report_type: Compendium::Option.new(name: :report_type, type: :radio, choices: [:big, :small]),
|
8
|
+
boolean: Compendium::Option.new(name: :boolean, type: :boolean),
|
9
|
+
another_boolean: Compendium::Option.new(name: :another_boolean, type: :boolean)
|
10
|
+
} }
|
11
|
+
|
12
|
+
subject{ described_class.new(@params, options) }
|
13
|
+
|
14
|
+
it "should only allow keys that are given as options" do
|
15
|
+
@params = { starting_on: '2013-10-15', foo: :bar }
|
16
|
+
subject.keys.should_not include :foo
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should set missing options to their default value" do
|
20
|
+
@params = {}
|
21
|
+
subject.starting_on.should == Date.today
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set missing options to nil if there is no default value" do
|
25
|
+
@params = {}
|
26
|
+
subject.ending_on.should be_nil
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'compendium/presenters/base'
|
3
|
+
|
4
|
+
TestPresenter = Class.new(Compendium::Presenters::Base) do
|
5
|
+
presents :test_obj
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Compendium::Presenters::Base do
|
9
|
+
let(:template) { double("Template", delegated?: true) }
|
10
|
+
subject { TestPresenter.new(template, :test) }
|
11
|
+
|
12
|
+
it "should allow the object name to be overridden" do
|
13
|
+
subject.test_obj.should == :test
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should delegate missing methods to the template object" do
|
17
|
+
template.should_receive(:delegated?)
|
18
|
+
subject.should be_delegated
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'compendium/presenters/option'
|
3
|
+
require 'compendium/option'
|
4
|
+
|
5
|
+
describe Compendium::Presenters::Option do
|
6
|
+
let(:template) do
|
7
|
+
t = double('Template')
|
8
|
+
t.stub(:t) { |key| key } # Stub I18n.t to just return the given value
|
9
|
+
t
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:option) { Compendium::Option.new(name: :test_option) }
|
13
|
+
|
14
|
+
subject { described_class.new(template, option) }
|
15
|
+
|
16
|
+
describe "#name" do
|
17
|
+
it "should pass the name through I18n" do
|
18
|
+
template.should_receive(:t).with(:test_option)
|
19
|
+
subject.name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#note" do
|
24
|
+
before { template.stub(:content_tag) }
|
25
|
+
|
26
|
+
it "should return nil if no note is specified" do
|
27
|
+
subject.note.should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should pass to I18n if the note option is set to true" do
|
31
|
+
option.merge!(note: true)
|
32
|
+
template.should_receive(:t).with(:test_option_note)
|
33
|
+
subject.note
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should pass to I18n if the note option is set" do
|
37
|
+
option.merge!(note: :the_note)
|
38
|
+
template.should_receive(:t).with(:the_note)
|
39
|
+
subject.note
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should create the note within a div with class option-note" do
|
43
|
+
option.merge!(note: true)
|
44
|
+
template.should_receive(:content_tag).with(:div, anything, class: 'option-note')
|
45
|
+
subject.note
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
data/spec/query_spec.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'compendium/query'
|
2
|
+
|
3
|
+
describe Compendium::Query do
|
4
|
+
describe "#run" do
|
5
|
+
let(:query) { described_class.new(:test, {}, -> * { [1, 2, 3] }) }
|
6
|
+
before { query.stub(:fetch_results) { |c| c } }
|
7
|
+
|
8
|
+
it "should return the result of the query" do
|
9
|
+
query.run(nil).should == [1, 2, 3]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should mark the query as having ran" do
|
13
|
+
query.run(nil)
|
14
|
+
query.should have_run
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should not affect any cloned queries" do
|
18
|
+
q2 = query.clone
|
19
|
+
query.run(nil)
|
20
|
+
q2.should_not have_run
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#nil?" do
|
25
|
+
it "should return true if the query's proc is nil" do
|
26
|
+
Compendium::Query.new(:test, {}, nil).should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return false if the query's proc is not nil" do
|
30
|
+
Compendium::Query.new(:test, {}, ->{}).should_not be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/spec/report_spec.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'compendium/report'
|
2
|
+
|
3
|
+
describe Compendium::Report do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
its(:queries) { should be_empty }
|
7
|
+
its(:options) { should be_empty }
|
8
|
+
|
9
|
+
it "should not do anything when run" do
|
10
|
+
report = subject.new
|
11
|
+
report.run
|
12
|
+
report.results.should be_empty
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with multiple instances" do
|
16
|
+
let(:report_class) do
|
17
|
+
Class.new(Compendium::Report) do
|
18
|
+
query :test
|
19
|
+
metric :test_metric, ->{}, through: :test
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
subject { report_class.new }
|
24
|
+
let(:report2) { report_class.new }
|
25
|
+
|
26
|
+
its(:queries) { should_not equal report2.queries }
|
27
|
+
its(:queries) { should_not equal report_class.queries }
|
28
|
+
its(:metrics) { should_not equal report2.metrics }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#run" do
|
32
|
+
let(:report_class) do
|
33
|
+
Class.new(Compendium::Report) do
|
34
|
+
option :first, :date
|
35
|
+
option :second, :date
|
36
|
+
|
37
|
+
query :test do |params|
|
38
|
+
[params[:first].__getobj__, params[:second].__getobj__]
|
39
|
+
end
|
40
|
+
|
41
|
+
metric :test_metric, -> results { results.to_a.max }, through: :test
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
subject { report_class.new(first: '2010-10-10', second: '2011-11-11') }
|
46
|
+
let!(:report2) { report_class.new }
|
47
|
+
|
48
|
+
before do
|
49
|
+
Compendium::Query.any_instance.stub(:fetch_results) { |c| c }
|
50
|
+
subject.run
|
51
|
+
end
|
52
|
+
|
53
|
+
its('test_results.records') { should == [Date.new(2010, 10, 10), Date.new(2011, 11, 11)] }
|
54
|
+
|
55
|
+
it "should run its metrics" do
|
56
|
+
subject.test.metrics[:test_metric].result.should == Date.new(2011, 11, 11)
|
57
|
+
subject.metrics[:test_metric].result.should == Date.new(2011, 11, 11)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not affect other instances of the report class" do
|
61
|
+
report2.test.results.should be_nil
|
62
|
+
report2.metrics[:test_metric].result.should be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should not affect the class collections" do
|
66
|
+
report_class.test.results.should be_nil
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with through queries" do
|
70
|
+
let(:report_class) do
|
71
|
+
Class.new(Compendium::Report) do
|
72
|
+
option :first, :boolean, default: false
|
73
|
+
query(:test) { |params| !!params[:first] ? [100, 200, 400, 800] : [1600, 3200, 6400]}
|
74
|
+
query(:through, through: :test) { |results| [results.first] }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
subject { report_class.new(first: true) }
|
79
|
+
|
80
|
+
its('through.results') { should == [100] }
|
81
|
+
|
82
|
+
it "should not mark other instances' queries as ran" do
|
83
|
+
report2.test.should_not have_run
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not affect other instances" do
|
87
|
+
report2.queries.each { |q| q.stub(:fetch_results) { |c| c } }
|
88
|
+
report2.run
|
89
|
+
report2.through.results.should == [1600]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
$:.unshift File.expand_path("../../app/classes", __FILE__)
|