pulse_meter_visualizer 0.4.11
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.rbenv-version +1 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/Procfile +3 -0
- data/README.md +40 -0
- data/Rakefile +72 -0
- data/examples/basic.ru +145 -0
- data/examples/basic_sensor_data.rb +96 -0
- data/lib/pulse_meter/visualize/app.rb +78 -0
- data/lib/pulse_meter/visualize/base.rb +15 -0
- data/lib/pulse_meter/visualize/coffee/application.coffee +40 -0
- data/lib/pulse_meter/visualize/coffee/collections/page_info_list.coffee +17 -0
- data/lib/pulse_meter/visualize/coffee/collections/sensor_info_list.coffee +4 -0
- data/lib/pulse_meter/visualize/coffee/collections/widget_list.coffee +14 -0
- data/lib/pulse_meter/visualize/coffee/extensions.coffee +26 -0
- data/lib/pulse_meter/visualize/coffee/models/dinamic_widget.coffee +34 -0
- data/lib/pulse_meter/visualize/coffee/models/page_info.coffee +2 -0
- data/lib/pulse_meter/visualize/coffee/models/sensor_info.coffee +2 -0
- data/lib/pulse_meter/visualize/coffee/models/widget.coffee +54 -0
- data/lib/pulse_meter/visualize/coffee/presenters/area.coffee +2 -0
- data/lib/pulse_meter/visualize/coffee/presenters/gauge.coffee +11 -0
- data/lib/pulse_meter/visualize/coffee/presenters/line.coffee +2 -0
- data/lib/pulse_meter/visualize/coffee/presenters/pie.coffee +20 -0
- data/lib/pulse_meter/visualize/coffee/presenters/series.coffee +44 -0
- data/lib/pulse_meter/visualize/coffee/presenters/table.coffee +10 -0
- data/lib/pulse_meter/visualize/coffee/presenters/timeline.coffee +13 -0
- data/lib/pulse_meter/visualize/coffee/presenters/widget.coffee +65 -0
- data/lib/pulse_meter/visualize/coffee/router.coffee +21 -0
- data/lib/pulse_meter/visualize/coffee/views/dynamic_chart.coffee +91 -0
- data/lib/pulse_meter/visualize/coffee/views/dynamic_widget.coffee +58 -0
- data/lib/pulse_meter/visualize/coffee/views/page_title.coffee +17 -0
- data/lib/pulse_meter/visualize/coffee/views/page_titles.coffee +15 -0
- data/lib/pulse_meter/visualize/coffee/views/sensor_info_list.coffee +19 -0
- data/lib/pulse_meter/visualize/coffee/views/widget.coffee +99 -0
- data/lib/pulse_meter/visualize/coffee/views/widget_chart.coffee +13 -0
- data/lib/pulse_meter/visualize/coffee/views/widget_list.coffee +15 -0
- data/lib/pulse_meter/visualize/dsl/base.rb +131 -0
- data/lib/pulse_meter/visualize/dsl/errors.rb +40 -0
- data/lib/pulse_meter/visualize/dsl/layout.rb +27 -0
- data/lib/pulse_meter/visualize/dsl/page.rb +33 -0
- data/lib/pulse_meter/visualize/dsl/sensor.rb +20 -0
- data/lib/pulse_meter/visualize/dsl/widget.rb +37 -0
- data/lib/pulse_meter/visualize/dsl/widgets/area.rb +20 -0
- data/lib/pulse_meter/visualize/dsl/widgets/gauge.rb +12 -0
- data/lib/pulse_meter/visualize/dsl/widgets/line.rb +21 -0
- data/lib/pulse_meter/visualize/dsl/widgets/pie.rb +16 -0
- data/lib/pulse_meter/visualize/dsl/widgets/table.rb +19 -0
- data/lib/pulse_meter/visualize/layout.rb +79 -0
- data/lib/pulse_meter/visualize/page.rb +25 -0
- data/lib/pulse_meter/visualize/public/css/application.css +56 -0
- data/lib/pulse_meter/visualize/public/css/bootstrap.css +4883 -0
- data/lib/pulse_meter/visualize/public/css/bootstrap.min.css +729 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-bg_glass_75_ffffff_1x400.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-bg_inset-soft_95_fef1ec_1x100.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-icons_222222_256x240.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-icons_2e83ff_256x240.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-icons_454545_256x240.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-icons_888888_256x240.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/lib/pulse_meter/visualize/public/css/images/ui-icons_f6cf3b_256x240.png +0 -0
- data/lib/pulse_meter/visualize/public/css/jquery-ui-1.8.16.bootstrap.css +1320 -0
- data/lib/pulse_meter/visualize/public/favicon.ico +208 -0
- data/lib/pulse_meter/visualize/public/img/glyphicons-halflings-white.png +0 -0
- data/lib/pulse_meter/visualize/public/img/glyphicons-halflings.png +0 -0
- data/lib/pulse_meter/visualize/public/js/application.js +973 -0
- data/lib/pulse_meter/visualize/public/js/backbone-min.js +38 -0
- data/lib/pulse_meter/visualize/public/js/bootstrap.js +1835 -0
- data/lib/pulse_meter/visualize/public/js/jquery-1.7.2.min.js +4 -0
- data/lib/pulse_meter/visualize/public/js/jquery-ui-1.8.16.bootstrap.min.js +791 -0
- data/lib/pulse_meter/visualize/public/js/jquery-ui-1.8.23.custom.min.js +21 -0
- data/lib/pulse_meter/visualize/public/js/jquery-ui-timepicker-addon.js +1687 -0
- data/lib/pulse_meter/visualize/public/js/json2.js +487 -0
- data/lib/pulse_meter/visualize/public/js/underscore-min.js +32 -0
- data/lib/pulse_meter/visualize/sensor.rb +63 -0
- data/lib/pulse_meter/visualize/series_extractor.rb +107 -0
- data/lib/pulse_meter/visualize/views/main.haml +30 -0
- data/lib/pulse_meter/visualize/views/sensors.haml +76 -0
- data/lib/pulse_meter/visualize/views/widgets/area.haml +53 -0
- data/lib/pulse_meter/visualize/views/widgets/extend_options.haml +11 -0
- data/lib/pulse_meter/visualize/views/widgets/gauge.haml +13 -0
- data/lib/pulse_meter/visualize/views/widgets/line.haml +54 -0
- data/lib/pulse_meter/visualize/views/widgets/pie.haml +13 -0
- data/lib/pulse_meter/visualize/views/widgets/table.haml +45 -0
- data/lib/pulse_meter/visualize/widget.rb +38 -0
- data/lib/pulse_meter/visualize/widgets/gauge.rb +47 -0
- data/lib/pulse_meter/visualize/widgets/pie.rb +36 -0
- data/lib/pulse_meter/visualize/widgets/timeline.rb +114 -0
- data/lib/pulse_meter/visualizer.rb +38 -0
- data/lib/pulse_meter_visualizer.rb +2 -0
- data/pulse_meter_visualizer.gemspec +41 -0
- data/spec/pulse_meter/visualize/app_spec.rb +27 -0
- data/spec/pulse_meter/visualize/dsl/layout_spec.rb +64 -0
- data/spec/pulse_meter/visualize/dsl/page_spec.rb +62 -0
- data/spec/pulse_meter/visualize/dsl/sensor_spec.rb +30 -0
- data/spec/pulse_meter/visualize/dsl/widget_spec.rb +6 -0
- data/spec/pulse_meter/visualize/dsl/widgets/area_spec.rb +44 -0
- data/spec/pulse_meter/visualize/dsl/widgets/gauge_spec.rb +22 -0
- data/spec/pulse_meter/visualize/dsl/widgets/line_spec.rb +44 -0
- data/spec/pulse_meter/visualize/dsl/widgets/pie_spec.rb +35 -0
- data/spec/pulse_meter/visualize/dsl/widgets/table_spec.rb +36 -0
- data/spec/pulse_meter/visualize/layout_spec.rb +54 -0
- data/spec/pulse_meter/visualize/page_spec.rb +153 -0
- data/spec/pulse_meter/visualize/sensor_spec.rb +120 -0
- data/spec/pulse_meter/visualize/series_extractor_spec.rb +80 -0
- data/spec/pulse_meter/visualize/widgets/area_spec.rb +6 -0
- data/spec/pulse_meter/visualize/widgets/gauge_spec.rb +63 -0
- data/spec/pulse_meter/visualize/widgets/line_spec.rb +6 -0
- data/spec/pulse_meter/visualize/widgets/pie_spec.rb +73 -0
- data/spec/pulse_meter/visualize/widgets/table_spec.rb +6 -0
- data/spec/pulse_meter/visualizer_spec.rb +42 -0
- data/spec/shared_examples/dsl_widget.rb +106 -0
- data/spec/shared_examples/widget.rb +97 -0
- data/spec/spec_helper.rb +36 -0
- metadata +518 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PulseMeter::Visualize::Sensor do
|
4
|
+
let(:interval){ 100 }
|
5
|
+
let(:name) { "some_sensor" }
|
6
|
+
let(:annotation) { 'sensor descr' }
|
7
|
+
let!(:real_sensor){ PulseMeter::Sensor::Timelined::Counter.new(name, ttl: 1000, interval: interval, annotation: annotation) }
|
8
|
+
let(:sensor) { described_class.new(name: name) }
|
9
|
+
|
10
|
+
let(:color){ '#ABCDEF' }
|
11
|
+
let(:sensor_with_color) { described_class.new(name: name, color: color) }
|
12
|
+
|
13
|
+
let(:bad_sensor) { described_class.new(name: "bad_sensor_name") }
|
14
|
+
let(:interval_start){ Time.at((Time.now.to_i / interval) * interval) }
|
15
|
+
|
16
|
+
describe '#last_value' do
|
17
|
+
context "when sensor does not exist" do
|
18
|
+
it "should raise RestoreError" do
|
19
|
+
expect{ bad_sensor.last_value(Time.now) }.to raise_exception(PulseMeter::RestoreError)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
context "when sensor has no data" do
|
25
|
+
it "should return nil" do
|
26
|
+
sensor.last_value(Time.now).should be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when sensor has data" do
|
31
|
+
context "when need_incomplete arg is true" do
|
32
|
+
it "should return last value" do
|
33
|
+
Timecop.freeze(interval_start) do
|
34
|
+
real_sensor.event(101)
|
35
|
+
end
|
36
|
+
Timecop.freeze(interval_start+1) do
|
37
|
+
sensor.last_value(Time.now, true).should == 101
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when need_incomplete arg is false" do
|
43
|
+
it "should return last complete value" do
|
44
|
+
Timecop.freeze(interval_start) do
|
45
|
+
real_sensor.event(101)
|
46
|
+
end
|
47
|
+
Timecop.freeze(interval_start + 1) do
|
48
|
+
sensor.last_value(Time.now).should be_nil
|
49
|
+
end
|
50
|
+
Timecop.freeze(interval_start + interval + 1) do
|
51
|
+
sensor.last_value(Time.now).should == 101
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#last_point_data" do
|
60
|
+
|
61
|
+
context "when sensor does not exist" do
|
62
|
+
it "should raise RestoreError" do
|
63
|
+
expect{ bad_sensor.last_point_data(Time.now) }.to raise_exception(PulseMeter::RestoreError)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return last value with annotation (and color)" do
|
68
|
+
Timecop.freeze(interval_start) do
|
69
|
+
real_sensor.event(101)
|
70
|
+
end
|
71
|
+
Timecop.freeze(interval_start + 1) do
|
72
|
+
sensor.last_point_data(Time.now, true).should == [{name: annotation, y: 101}]
|
73
|
+
sensor.last_point_data(Time.now).should == [{name: annotation, y: nil}]
|
74
|
+
sensor_with_color.last_point_data(Time.now, true).should == [{name: annotation, y: 101, color: color}]
|
75
|
+
sensor_with_color.last_point_data(Time.now).should == [{name: annotation, y: nil, color: color}]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#timeline_data" do
|
81
|
+
before(:each) do
|
82
|
+
Timecop.freeze(interval_start) do
|
83
|
+
real_sensor.event(101)
|
84
|
+
end
|
85
|
+
Timecop.freeze(interval_start + interval) do
|
86
|
+
real_sensor.event(55)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when sensor does not exist" do
|
91
|
+
it "should raise RestoreError" do
|
92
|
+
expect{ bad_sensor.timeline_data(Time.now - interval, Time.now) }.to raise_exception(PulseMeter::RestoreError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
describe "returned value" do
|
98
|
+
it "should contain sensor annotation" do
|
99
|
+
Timecop.freeze(interval_start + interval + 1) do
|
100
|
+
sensor.timeline_data(Time.now - interval, Time.now).first[:name].should == annotation
|
101
|
+
end
|
102
|
+
end
|
103
|
+
it "should contain sensor color" do
|
104
|
+
Timecop.freeze(interval_start + interval + 1) do
|
105
|
+
sensor_with_color.timeline_data(Time.now - interval, Time.now).first[:color].should == color
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should contain [interval_start, value] pairs for each interval" do
|
110
|
+
Timecop.freeze(interval_start + interval + 1) do
|
111
|
+
data = sensor.timeline_data(Time.now - interval * 2, Time.now)
|
112
|
+
data.first[:data].should == [{x: interval_start.to_i * 1000, y: 101}]
|
113
|
+
data = sensor.timeline_data(Time.now - interval * 2, Time.now, true)
|
114
|
+
data.first[:data].should == [{x: interval_start.to_i * 1000, y: 101}, {x: (interval_start + interval).to_i * 1000, y: 55}]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PulseMeter::Visualize::SeriesExtractor do
|
4
|
+
let(:interval){ 100 }
|
5
|
+
let!(:real_simple_sensor){ PulseMeter::Sensor::Timelined::Counter.new(:simple_sensor,
|
6
|
+
ttl: 1000,
|
7
|
+
interval: interval,
|
8
|
+
annotation: 'simple sensor'
|
9
|
+
) }
|
10
|
+
let!(:real_hashed_sensor){ PulseMeter::Sensor::Timelined::HashedCounter.new(:hashed_sensor,
|
11
|
+
ttl: 1000,
|
12
|
+
interval: interval,
|
13
|
+
annotation: 'hashed sensor'
|
14
|
+
) }
|
15
|
+
|
16
|
+
let!(:simple_sensor){PulseMeter::Visualize::Sensor.new(name: :simple_sensor)}
|
17
|
+
let!(:hashed_sensor){PulseMeter::Visualize::Sensor.new(name: :hashed_sensor)}
|
18
|
+
|
19
|
+
describe "simple extractor" do
|
20
|
+
|
21
|
+
let(:extractor) {PulseMeter::Visualize.extractor(simple_sensor)}
|
22
|
+
|
23
|
+
it "should be created for simple sensors" do
|
24
|
+
extractor.should be_kind_of(PulseMeter::Visualize::SeriesExtractor::Simple)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should create point data correctly" do
|
28
|
+
extractor.point_data(123).should == [{y: 123, name: 'simple sensor'}]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should create timeline data correctly" do
|
32
|
+
tl_data = [
|
33
|
+
PulseMeter::SensorData.new(Time.at(1), 11),
|
34
|
+
PulseMeter::SensorData.new(Time.at(2), "22")
|
35
|
+
]
|
36
|
+
extractor.series_data(tl_data).should == [{
|
37
|
+
name: 'simple sensor',
|
38
|
+
data: [{x: 1000, y: 11}, {x: 2000, y: 22}]
|
39
|
+
}]
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "hash extractor" do
|
45
|
+
let(:extractor) {PulseMeter::Visualize.extractor(hashed_sensor)}
|
46
|
+
|
47
|
+
it "should be created for hash sensors" do
|
48
|
+
extractor.should be_kind_of(PulseMeter::Visualize::SeriesExtractor::Hashed)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should create point data correctly" do
|
52
|
+
extractor.point_data('{"x": 123, "y": 321}').should == [
|
53
|
+
{y: 123, name: 'hashed sensor: x'},
|
54
|
+
{y: 321, name: 'hashed sensor: y'}
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should create timeline data correctly" do
|
59
|
+
tl_data = [
|
60
|
+
PulseMeter::SensorData.new(Time.at(1), {"a" => 5, "b" => 6}),
|
61
|
+
PulseMeter::SensorData.new(Time.at(2), '{"c": 7, "b": 6}')
|
62
|
+
]
|
63
|
+
extractor.series_data(tl_data).should == [
|
64
|
+
{
|
65
|
+
name: 'hashed sensor: a',
|
66
|
+
data: [{x: 1000, y: 5}, {x: 2000, y: nil}]
|
67
|
+
},
|
68
|
+
{
|
69
|
+
name: 'hashed sensor: b',
|
70
|
+
data: [{x: 1000, y: 6}, {x: 2000, y: 6}]
|
71
|
+
},
|
72
|
+
{
|
73
|
+
name: 'hashed sensor: c',
|
74
|
+
data: [{x: 1000, y: nil}, {x: 2000, y: 7}]
|
75
|
+
}
|
76
|
+
]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PulseMeter::Visualize::Widgets::Gauge do
|
4
|
+
let(:interval){ 100 }
|
5
|
+
let!(:a_sensor){PulseMeter::Sensor::Indicator.new(:a_sensor, annotation: 'A')}
|
6
|
+
let!(:b_sensor){PulseMeter::Sensor::Indicator.new(:b_sensor, annotation: 'B')}
|
7
|
+
let!(:c_sensor){PulseMeter::Sensor::HashedIndicator.new(:c_sensor, annotation: 'C')}
|
8
|
+
|
9
|
+
|
10
|
+
let(:widget_name){ "some_widget" }
|
11
|
+
|
12
|
+
let(:redraw_interval){5}
|
13
|
+
let(:width){6}
|
14
|
+
|
15
|
+
let(:interval_start){ Time.at((Time.now.to_i / interval) * interval) }
|
16
|
+
|
17
|
+
let(:widget) do
|
18
|
+
w = PulseMeter::Visualize::DSL::Widgets::Gauge.new(widget_name)
|
19
|
+
w.redraw_interval redraw_interval
|
20
|
+
w.width width
|
21
|
+
w.sensor :a_sensor
|
22
|
+
w.sensor :b_sensor
|
23
|
+
w.sensor :c_sensor
|
24
|
+
w.gchart_options a: 1
|
25
|
+
w.to_data
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#data" do
|
29
|
+
it "should contain type, title, redraw_interval, width, gchart_options attriutes" do
|
30
|
+
wdata = widget.data
|
31
|
+
wdata[:type].should == 'gauge'
|
32
|
+
wdata[:title].should == widget_name
|
33
|
+
wdata[:redraw_interval].should == redraw_interval
|
34
|
+
wdata[:width].should == width
|
35
|
+
wdata[:gchart_options].should == {a: 1}
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "series attribute" do
|
39
|
+
before(:each) do
|
40
|
+
a_sensor.event(12)
|
41
|
+
b_sensor.event(33)
|
42
|
+
c_sensor.event(:a => 44)
|
43
|
+
c_sensor.event(:b => 55)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should contain valid gauge slices" do
|
47
|
+
|
48
|
+
widget.data[:series].sort.should == [
|
49
|
+
['A', 12],
|
50
|
+
['B', 33],
|
51
|
+
["C: a", 44],
|
52
|
+
["C: b", 55]
|
53
|
+
].sort
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PulseMeter::Visualize::Widgets::Pie do
|
4
|
+
let(:interval){ 100 }
|
5
|
+
let!(:a_sensor){ PulseMeter::Sensor::Timelined::Counter.new(:a_sensor, :ttl => 1000, :interval => interval, annotation: 'A') }
|
6
|
+
let!(:b_sensor){ PulseMeter::Sensor::Timelined::Counter.new(:b_sensor, :ttl => 1000, :interval => interval, annotation: 'B') }
|
7
|
+
|
8
|
+
let(:widget_name){ "some_widget" }
|
9
|
+
|
10
|
+
let(:redraw_interval){5}
|
11
|
+
let(:values_label){'xxxx'}
|
12
|
+
let(:width){6}
|
13
|
+
let(:a_color){'#FF0000'}
|
14
|
+
let(:b_color){'#FFFF00'}
|
15
|
+
|
16
|
+
let(:interval_start){ Time.at((Time.now.to_i / interval) * interval) }
|
17
|
+
|
18
|
+
let(:widget) do
|
19
|
+
w = PulseMeter::Visualize::DSL::Widgets::Pie.new(widget_name)
|
20
|
+
w.redraw_interval redraw_interval
|
21
|
+
w.width width
|
22
|
+
w.sensor :a_sensor, color: a_color
|
23
|
+
w.sensor :b_sensor, color: b_color
|
24
|
+
w.gchart_options a: 1
|
25
|
+
w.to_data
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#data" do
|
29
|
+
it "should contain type, title, redraw_interval, width, gchart_options attriutes" do
|
30
|
+
wdata = widget.data
|
31
|
+
wdata[:type].should == 'pie'
|
32
|
+
wdata[:title].should == widget_name
|
33
|
+
wdata[:redraw_interval].should == redraw_interval
|
34
|
+
wdata[:width].should == width
|
35
|
+
wdata[:gchart_options].should == {a: 1}
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "series attribute" do
|
39
|
+
before(:each) do
|
40
|
+
Timecop.freeze(interval_start + 1) do
|
41
|
+
a_sensor.event(12)
|
42
|
+
b_sensor.event(33)
|
43
|
+
end
|
44
|
+
Timecop.freeze(interval_start + interval + 1) do
|
45
|
+
a_sensor.event(111)
|
46
|
+
end
|
47
|
+
@current_time = interval_start + 2 * interval - 1
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should contain valid pie slices" do
|
51
|
+
|
52
|
+
Timecop.freeze(@current_time) do
|
53
|
+
widget.data[:series].should ==
|
54
|
+
{
|
55
|
+
data: [
|
56
|
+
[a_sensor.annotation, 12],
|
57
|
+
[b_sensor.annotation, 33]
|
58
|
+
],
|
59
|
+
options: [
|
60
|
+
{color: a_color},
|
61
|
+
{color: b_color}
|
62
|
+
]
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PulseMeter::Visualizer do
|
4
|
+
describe "::draw" do
|
5
|
+
it "should generate correct layout with passed block" do
|
6
|
+
layout = described_class.draw do |l|
|
7
|
+
|
8
|
+
l.title "My Gauges"
|
9
|
+
|
10
|
+
l.page "Dashboard" do |p|
|
11
|
+
p.line :convertion do |c|
|
12
|
+
c.sensor :adv_clicks, color: :green
|
13
|
+
c.sensor :adv_shows, color: :red
|
14
|
+
end
|
15
|
+
|
16
|
+
p.pie :agents, title: 'User Agents' do |c|
|
17
|
+
c.sensor :agent_ie
|
18
|
+
c.sensor :agent_chrome
|
19
|
+
c.sensor :agent_ff
|
20
|
+
c.sensor :agent_other
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
l.page "Request stats" do |p|
|
26
|
+
p.line :rph_total, sensor: :rph_total
|
27
|
+
p.line :rph_main_page, sensor: :rph_main_page
|
28
|
+
p.line :request_time_p95_hour
|
29
|
+
|
30
|
+
p.pie :success_vs_fail_total_hourly do |w|
|
31
|
+
w.sensor :success_total_hourly
|
32
|
+
w.sensor :fail_total_hourly
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
layout.should be_kind_of(PulseMeter::Visualize::Layout)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,106 @@
|
|
1
|
+
shared_examples_for "dsl widget" do
|
2
|
+
|
3
|
+
let(:interval){ 100 }
|
4
|
+
let(:name) { "some_sensor" }
|
5
|
+
let!(:sensor){ PulseMeter::Sensor::Timelined::Max.new(name, :ttl => 1000, :interval => interval) }
|
6
|
+
|
7
|
+
let(:widget_name){ "some_widget" }
|
8
|
+
let(:w){ described_class.new(widget_name) }
|
9
|
+
|
10
|
+
describe '.new' do
|
11
|
+
it "should set default value for width papram" do
|
12
|
+
wid = w.to_data
|
13
|
+
wid.width.should == PulseMeter::Visualize::DSL::Widget::MAX_WIDTH
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should set title param from .new argument" do
|
17
|
+
wid = w.to_data
|
18
|
+
wid.title.should == widget_name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#process_args" do
|
23
|
+
it "should set sensor by :sensor param" do
|
24
|
+
w.process_args :sensor => :sss
|
25
|
+
sensors = w.to_data.sensors
|
26
|
+
sensors.size.should == 1
|
27
|
+
sensors.first.name.to_s.should == 'sss'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should set title by :title param" do
|
31
|
+
w.process_args :title => 'Title XXX'
|
32
|
+
w.to_data.title.should == 'Title XXX'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should set width by :width param" do
|
36
|
+
w.process_args :width => 5
|
37
|
+
w.to_data.width.should == 5
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#sensor" do
|
43
|
+
it "should add sensor" do
|
44
|
+
w.sensor :s1
|
45
|
+
w.sensor :s2
|
46
|
+
sensors = w.to_data.sensors
|
47
|
+
sensors.size.should == 2
|
48
|
+
sensors.first.name.to_s.should == 's1'
|
49
|
+
sensors.last.name.to_s.should == 's2'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#title" do
|
54
|
+
it "should set title" do
|
55
|
+
w.title 'Title XXX'
|
56
|
+
w.to_data.title.should == 'Title XXX'
|
57
|
+
w.title 'Title YYY'
|
58
|
+
w.to_data.title.should == 'Title YYY'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#width" do
|
63
|
+
it "should set width" do
|
64
|
+
w.width 6
|
65
|
+
w.to_data.width.should == 6
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should raise exception if width is invalid" do
|
69
|
+
expect { w.width -1 }.to raise_exception(PulseMeter::Visualize::DSL::BadWidgetWidth)
|
70
|
+
expect { w.width 11 }.to raise_exception(PulseMeter::Visualize::DSL::BadWidgetWidth)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#redraw_interval" do
|
75
|
+
it "should set redraw_interval" do
|
76
|
+
w.redraw_interval 5
|
77
|
+
w.to_data.redraw_interval.should == 5
|
78
|
+
end
|
79
|
+
it "should raise exception if redraw_interval is negative" do
|
80
|
+
expect{ w.redraw_interval(-1) }.to raise_exception(PulseMeter::Visualize::DSL::BadWidgetRedrawInterval)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#to_data" do
|
86
|
+
it "should convert dsl data to widget" do
|
87
|
+
w.to_data.should be_kind_of(PulseMeter::Visualize::Widget)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#gchart_options" do
|
92
|
+
it "should add options to gchart_options hash" do
|
93
|
+
w.gchart_options a: 1
|
94
|
+
w.gchart_options b: 2
|
95
|
+
w.to_data.gchart_options.should == {a: 1, b: 2}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "any anknown method" do
|
100
|
+
it "should add options to gchart_options hash" do
|
101
|
+
w.foobar 123
|
102
|
+
w.to_data.gchart_options.should == {foobar: 123}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|