pulse_meter-dygraphs_visualizer 0.4.15
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 +9 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/Procfile +3 -0
- data/README.md +40 -0
- data/Rakefile +54 -0
- data/examples/basic.ru +125 -0
- data/examples/basic_sensor_data.rb +97 -0
- data/lib/pulse_meter/dygraphs_visualize/app.rb +78 -0
- data/lib/pulse_meter/dygraphs_visualize/base.rb +15 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/application.coffee +37 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/collections/page_info_list.coffee +17 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/collections/sensor_info_list.coffee +4 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/collections/widget_list.coffee +14 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/extensions.coffee +26 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/models/dinamic_widget.coffee +34 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/models/page_info.coffee +2 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/models/sensor_info.coffee +2 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/models/widget.coffee +63 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/presenters/line.coffee +1 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/presenters/series.coffee +26 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/presenters/stack.coffee +1 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/presenters/timeline.coffee +13 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/presenters/widget.coffee +48 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/router.coffee +21 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/views/dynamic_chart.coffee +92 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/views/dynamic_widget.coffee +58 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/views/page_title.coffee +17 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/views/page_titles.coffee +15 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/views/sensor_info_list.coffee +19 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/views/widget.coffee +91 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/views/widget_chart.coffee +15 -0
- data/lib/pulse_meter/dygraphs_visualize/coffee/views/widget_list.coffee +15 -0
- data/lib/pulse_meter/dygraphs_visualize/dsl/base.rb +131 -0
- data/lib/pulse_meter/dygraphs_visualize/dsl/errors.rb +40 -0
- data/lib/pulse_meter/dygraphs_visualize/dsl/layout.rb +27 -0
- data/lib/pulse_meter/dygraphs_visualize/dsl/page.rb +26 -0
- data/lib/pulse_meter/dygraphs_visualize/dsl/sensor.rb +20 -0
- data/lib/pulse_meter/dygraphs_visualize/dsl/widget.rb +37 -0
- data/lib/pulse_meter/dygraphs_visualize/dsl/widgets/line.rb +22 -0
- data/lib/pulse_meter/dygraphs_visualize/dsl/widgets/stack.rb +29 -0
- data/lib/pulse_meter/dygraphs_visualize/layout.rb +79 -0
- data/lib/pulse_meter/dygraphs_visualize/page.rb +25 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/application.css +61 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/bootstrap.css +4883 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/bootstrap.min.css +729 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-bg_glass_75_ffffff_1x400.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-bg_inset-soft_95_fef1ec_1x100.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-icons_222222_256x240.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-icons_2e83ff_256x240.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-icons_454545_256x240.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-icons_888888_256x240.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/images/ui-icons_f6cf3b_256x240.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/css/jquery-ui-1.8.16.bootstrap.css +1320 -0
- data/lib/pulse_meter/dygraphs_visualize/public/favicon.ico +208 -0
- data/lib/pulse_meter/dygraphs_visualize/public/img/glyphicons-halflings-white.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/img/glyphicons-halflings.png +0 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/application.js +833 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/backbone-min.js +38 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/bootstrap.js +1835 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/dygraph-combined.js +2 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/jquery-1.7.2.min.js +4 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/jquery-ui-1.8.16.bootstrap.min.js +791 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/jquery-ui-1.8.23.custom.min.js +21 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/jquery-ui-timepicker-addon.js +1687 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/json2.js +487 -0
- data/lib/pulse_meter/dygraphs_visualize/public/js/underscore-min.js +32 -0
- data/lib/pulse_meter/dygraphs_visualize/sensor.rb +63 -0
- data/lib/pulse_meter/dygraphs_visualize/series_color.rb +39 -0
- data/lib/pulse_meter/dygraphs_visualize/series_extractor.rb +107 -0
- data/lib/pulse_meter/dygraphs_visualize/views/main.haml +30 -0
- data/lib/pulse_meter/dygraphs_visualize/views/sensors.haml +75 -0
- data/lib/pulse_meter/dygraphs_visualize/views/widgets/extend_options.haml +11 -0
- data/lib/pulse_meter/dygraphs_visualize/views/widgets/line.haml +43 -0
- data/lib/pulse_meter/dygraphs_visualize/views/widgets/stack.haml +43 -0
- data/lib/pulse_meter/dygraphs_visualize/widget.rb +38 -0
- data/lib/pulse_meter/dygraphs_visualize/widgets/timeline.rb +107 -0
- data/lib/pulse_meter/dygraphs_visualizer.rb +34 -0
- data/lib/pulse_meter_dygraphs_visualizer.rb +2 -0
- data/pulse_meter-dygraphs_visualizer.gemspec +41 -0
- data/spec/pulse_meter/dygraphs_visualize/app_spec.rb +27 -0
- data/spec/pulse_meter/dygraphs_visualize/dsl/layout_spec.rb +64 -0
- data/spec/pulse_meter/dygraphs_visualize/dsl/page_spec.rb +62 -0
- data/spec/pulse_meter/dygraphs_visualize/dsl/sensor_spec.rb +30 -0
- data/spec/pulse_meter/dygraphs_visualize/dsl/widget_spec.rb +6 -0
- data/spec/pulse_meter/dygraphs_visualize/dsl/widgets/line_spec.rb +44 -0
- data/spec/pulse_meter/dygraphs_visualize/dsl/widgets/stack_spec.rb +55 -0
- data/spec/pulse_meter/dygraphs_visualize/layout_spec.rb +54 -0
- data/spec/pulse_meter/dygraphs_visualize/page_spec.rb +145 -0
- data/spec/pulse_meter/dygraphs_visualize/sensor_spec.rb +120 -0
- data/spec/pulse_meter/dygraphs_visualize/series_extractor_spec.rb +80 -0
- data/spec/pulse_meter/dygraphs_visualize/widgets/line_spec.rb +6 -0
- data/spec/pulse_meter/dygraphs_visualize/widgets/stack_spec.rb +6 -0
- data/spec/pulse_meter/dygraphs_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 +497 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PulseMeter::DygraphsVisualize::DSL::Widgets::Stack do
|
4
|
+
it_should_behave_like "dsl widget"
|
5
|
+
|
6
|
+
let(:interval){ 100 }
|
7
|
+
let(:name) { "some_sensor" }
|
8
|
+
let!(:sensor){ PulseMeter::Sensor::Timelined::Max.new(name, :ttl => 1000, :interval => interval) }
|
9
|
+
|
10
|
+
let(:widget_name){ "some_widget" }
|
11
|
+
let(:w){ described_class.new(widget_name) }
|
12
|
+
|
13
|
+
describe "#to_data" do
|
14
|
+
let(:data){ w.to_data }
|
15
|
+
|
16
|
+
it "should produce PulseMeter::DygraphsVisualize::Widgets::Stack class" do
|
17
|
+
data.should be_kind_of(PulseMeter::DygraphsVisualize::Widgets::Stack)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "dygraphs_options" do
|
21
|
+
let(:dygraphs_options){ data.dygraphs_options }
|
22
|
+
|
23
|
+
it "should set stack Dygraphs options" do
|
24
|
+
dygraphs_options[:stacked_graph].should be_true
|
25
|
+
dygraphs_options[:stacked_graph_na_n_fill].should == 'inside'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#values_label" do
|
31
|
+
it "should set values_label" do
|
32
|
+
w.values_label "some y-axis legend"
|
33
|
+
w.to_data.values_label.should == "some y-axis legend"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#show_last_point" do
|
38
|
+
it "should set show_last_point" do
|
39
|
+
w.show_last_point true
|
40
|
+
w.to_data.show_last_point.should be_true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#timespan" do
|
45
|
+
it "should set timespan" do
|
46
|
+
w.timespan 5
|
47
|
+
w.to_data.timespan.should == 5
|
48
|
+
end
|
49
|
+
it "should raise exception if timespan is negative" do
|
50
|
+
expect{ w.timespan(-1) }.to raise_exception(PulseMeter::DygraphsVisualize::DSL::BadWidgetTimeSpan)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PulseMeter::DygraphsVisualize::Layout do
|
4
|
+
let(:layout) do
|
5
|
+
l = PulseMeter::DygraphsVisualize::DSL::Layout.new
|
6
|
+
l.page "page1" do |p|
|
7
|
+
p.line "w1"
|
8
|
+
p.line "w2"
|
9
|
+
p.dygraphs_options({a: 1})
|
10
|
+
end
|
11
|
+
l.page "page2" do |p|
|
12
|
+
p.line "w3"
|
13
|
+
p.line "w4"
|
14
|
+
end
|
15
|
+
l.to_data
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#page_infos" do
|
19
|
+
it "should return list of page infos with ids" do
|
20
|
+
layout.page_infos.should == [
|
21
|
+
{title: "page1", id: 1, dygraphs_options: {a: 1}},
|
22
|
+
{title: "page2", id: 2, dygraphs_options: {}}
|
23
|
+
]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#options" do
|
28
|
+
it "should return layout options" do
|
29
|
+
ldsl = PulseMeter::DygraphsVisualize::DSL::Layout.new
|
30
|
+
ldsl.use_utc true
|
31
|
+
ldsl.dygraphs_options({a: 1})
|
32
|
+
l = ldsl.to_data
|
33
|
+
l.options.should == {use_utc: true, dygraphs_options: {a: 1}}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#widget" do
|
38
|
+
it "should return data for correct widget" do
|
39
|
+
w = layout.widget(1, 0)
|
40
|
+
w.should include(id: 1, title: "w3")
|
41
|
+
w = layout.widget(0, 1, timespan: 123)
|
42
|
+
w.should include(id: 2, title: "w2")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#widgets" do
|
47
|
+
it "should return data for correct widgets of a page" do
|
48
|
+
datas = layout.widgets(1)
|
49
|
+
datas[0].should include(id: 1, title: "w3")
|
50
|
+
datas[1].should include(id: 2, title: "w4")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PulseMeter::DygraphsVisualize::Page 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(:type) { :some_type }
|
9
|
+
let(:widget_name){ "some_widget" }
|
10
|
+
|
11
|
+
let(:redraw_interval){5}
|
12
|
+
let(:values_label){'xxxx'}
|
13
|
+
let(:width){6}
|
14
|
+
let(:show_last_point){false}
|
15
|
+
let(:timespan){interval * 2}
|
16
|
+
let(:a_color){'#FF0000'}
|
17
|
+
let(:b_color){'#FFFF00'}
|
18
|
+
|
19
|
+
let(:interval_start){ Time.at((Time.now.to_i / interval) * interval) }
|
20
|
+
let(:page_title){"Dashboard"}
|
21
|
+
|
22
|
+
|
23
|
+
let(:page) do
|
24
|
+
p = PulseMeter::DygraphsVisualize::DSL::Page.new(page_title)
|
25
|
+
p.line(widget_name) do |w|
|
26
|
+
w.redraw_interval redraw_interval
|
27
|
+
w.values_label values_label
|
28
|
+
w.width width
|
29
|
+
w.show_last_point show_last_point
|
30
|
+
w.timespan timespan
|
31
|
+
|
32
|
+
w.sensor :a_sensor, color: a_color
|
33
|
+
w.sensor :b_sensor, color: b_color
|
34
|
+
end
|
35
|
+
p.line(widget_name) do |w|
|
36
|
+
w.redraw_interval redraw_interval
|
37
|
+
w.values_label values_label
|
38
|
+
w.width width
|
39
|
+
w.show_last_point show_last_point
|
40
|
+
w.timespan timespan
|
41
|
+
|
42
|
+
w.sensor :a_sensor, color: a_color
|
43
|
+
w.sensor :b_sensor, color: b_color
|
44
|
+
end
|
45
|
+
p.to_data
|
46
|
+
end
|
47
|
+
|
48
|
+
before(:each) do
|
49
|
+
Timecop.freeze(interval_start + 1) do
|
50
|
+
a_sensor.event(12)
|
51
|
+
b_sensor.event(33)
|
52
|
+
end
|
53
|
+
Timecop.freeze(interval_start + interval + 1) do
|
54
|
+
a_sensor.event(111)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#widget_data" do
|
59
|
+
|
60
|
+
it "should generate correct data of single widget" do
|
61
|
+
Timecop.freeze(interval_start + 2 * interval - 1) do
|
62
|
+
page.widget_data(0)[:id].should == 1
|
63
|
+
page.widget_data(1)[:id].should == 2
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should generate correct data of single widget" do
|
68
|
+
Timecop.freeze(interval_start + 2 * interval - 1) do
|
69
|
+
page.widget_data(0)[:series].should ==
|
70
|
+
{
|
71
|
+
titles: [a_sensor.annotation, b_sensor.annotation],
|
72
|
+
rows: [[interval_start.to_i * 1000, 12, 33]],
|
73
|
+
options: [
|
74
|
+
{color: a_color},
|
75
|
+
{color: b_color}
|
76
|
+
]
|
77
|
+
}
|
78
|
+
page.widget_data(1)[:series].should ==
|
79
|
+
{
|
80
|
+
titles: [a_sensor.annotation, b_sensor.annotation],
|
81
|
+
rows: [[interval_start.to_i * 1000, 12, 33]],
|
82
|
+
options: [
|
83
|
+
{color: a_color},
|
84
|
+
{color: b_color}
|
85
|
+
]
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
Timecop.freeze(interval_start + 2 * interval - 1) do
|
90
|
+
page.widget_data(0, timespan: 0)[:series].should ==
|
91
|
+
{
|
92
|
+
titles: [a_sensor.annotation, b_sensor.annotation],
|
93
|
+
rows: [],
|
94
|
+
options: [
|
95
|
+
{color: a_color},
|
96
|
+
{color: b_color}
|
97
|
+
]
|
98
|
+
}
|
99
|
+
page.widget_data(1, timespan: 1)[:series].should ==
|
100
|
+
{
|
101
|
+
titles: [a_sensor.annotation, b_sensor.annotation],
|
102
|
+
rows: [],
|
103
|
+
options: [
|
104
|
+
{color: a_color},
|
105
|
+
{color: b_color}
|
106
|
+
]
|
107
|
+
}
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "#widget_datas" do
|
114
|
+
it "should generate correct ids for all widgets" do
|
115
|
+
Timecop.freeze(interval_start + 2 * interval - 1) do
|
116
|
+
page.widget_datas.map{|h| h[:id]}.should == [1,2]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should generate correct series data of all widgets" do
|
121
|
+
Timecop.freeze(interval_start + 2 * interval - 1) do
|
122
|
+
|
123
|
+
page.widget_datas.map{|h| h[:series]}.should == [
|
124
|
+
{
|
125
|
+
titles: [a_sensor.annotation, b_sensor.annotation],
|
126
|
+
rows: [[interval_start.to_i * 1000, 12, 33]],
|
127
|
+
options: [
|
128
|
+
{color: a_color},
|
129
|
+
{color: b_color}
|
130
|
+
]
|
131
|
+
},
|
132
|
+
{
|
133
|
+
titles: [a_sensor.annotation, b_sensor.annotation],
|
134
|
+
rows: [[interval_start.to_i * 1000, 12, 33]],
|
135
|
+
options: [
|
136
|
+
{color: a_color},
|
137
|
+
{color: b_color}
|
138
|
+
]
|
139
|
+
}
|
140
|
+
]
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PulseMeter::DygraphsVisualize::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::DygraphsVisualize::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::DygraphsVisualize::Sensor.new(name: :simple_sensor)}
|
17
|
+
let!(:hashed_sensor){PulseMeter::DygraphsVisualize::Sensor.new(name: :hashed_sensor)}
|
18
|
+
|
19
|
+
describe "simple extractor" do
|
20
|
+
|
21
|
+
let(:extractor) {PulseMeter::DygraphsVisualize.extractor(simple_sensor)}
|
22
|
+
|
23
|
+
it "should be created for simple sensors" do
|
24
|
+
extractor.should be_kind_of(PulseMeter::DygraphsVisualize::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::DygraphsVisualize.extractor(hashed_sensor)}
|
46
|
+
|
47
|
+
it "should be created for hash sensors" do
|
48
|
+
extractor.should be_kind_of(PulseMeter::DygraphsVisualize::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
|