pulse_meter_visualizer 0.4.11
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/.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
|
+
|