cosm-rb 0.2.00 → 0.2.01

Sign up to get free protection for your applications and to get access to all the features.
@@ -59,7 +59,7 @@ module Cosm
59
59
  return pass
60
60
  end
61
61
 
62
- def initialize(input = {}, format = nil)
62
+ def initialize(input = {}, csv_version = nil, format = nil)
63
63
  raise InvalidFormatError, "Unknown format specified, currently we can only parse JSON, XML or CSV." unless [nil,:json,:xml,:csv].include?(format)
64
64
  if input.is_a? Hash
65
65
  self.attributes = input
@@ -68,7 +68,7 @@ module Cosm
68
68
  elsif format == :xml || (format.nil? && input.strip[0...1].to_s == "<")
69
69
  self.attributes = from_xml(input)
70
70
  else
71
- self.attributes = from_csv(input)
71
+ self.attributes = from_csv(input, csv_version)
72
72
  end
73
73
  end
74
74
 
@@ -10,15 +10,39 @@ module Cosm
10
10
  # we are running under 1.8.x or 1.9.x
11
11
  raise InvalidCSVError, e.message
12
12
  end
13
- raise InvalidCSVError, "CSV is invalid. Can only construct a Cosm::Datastream object from a single row of data" if rows.size > 1
14
- row = rows.first
15
- raise InvalidCSVError, "CSV is invalid. Too many fields; must only be a single value, or a timestamp and a value" if row.size > 2
16
- if row.size == 2
17
- return { "updated" => row[0].to_s.strip, "current_value" => row[1].to_s.strip }
18
- else
13
+
14
+ version = FeedDefaults.detect_version(rows, csv_version)
15
+
16
+ raise InvalidCSVError, "CSV is invalid. Submitted data appears to be empty" if rows.nil?
17
+
18
+ if version == :v1
19
+ raise InvalidCSVError, "CSV is invalid. Can only construct a Cosm::Datastream object from a single row of data" if rows.size > 1
20
+ row = rows.first
21
+ raise InvalidCSVError, "CSV is invalid. Too many fields; must only be a single value" if row.size > 1
19
22
  return { "current_value" => row[0].to_s.strip }
23
+ else
24
+ row_sizes = rows.collect { |row| row.size }.uniq
25
+ raise InvalidCSVError, "CSV is invalid. Too many fields; must only be a single value, or a timestamp and a value" if row_sizes.max > 2
26
+
27
+ if rows.size == 1
28
+ # capture single lines (normal case)
29
+ row = rows.first
30
+
31
+ if row.size == 2
32
+ return { "updated" => row[0].to_s.strip, "current_value" => row[1].to_s.strip }
33
+ else
34
+ return { "current_value" => row[0].to_s.strip }
35
+ end
36
+ else
37
+ # capture multiple lines
38
+ raise InvalidCSVError, "CSV is invalid. If multiple values are included, then a timestamp and value must be submitted for every row" if row_sizes.min < 2
39
+
40
+ return { "datapoints" => rows.collect { |row| { "at" => row[0].to_s.strip, "value" => row[1].to_s.strip } } }
41
+ end
20
42
  end
43
+
21
44
  end
45
+
22
46
  end
23
47
  end
24
48
  end
@@ -5,6 +5,16 @@ module Cosm
5
5
  class InvalidCSVError < Cosm::ParserError ; end
6
6
 
7
7
  module FeedDefaults
8
+
9
+ class << self
10
+ def detect_version(rows, version = nil)
11
+ return version if version
12
+ return :v2 if rows.size >= 2
13
+ return :v1 if rows.size == 1 && rows.first.size != 2
14
+ raise UnknownVersionError, "CSV Version could not be detected"
15
+ end
16
+ end
17
+
8
18
  def from_csv(csv, csv_version = nil)
9
19
  begin
10
20
  rows = Cosm::CSV.parse(csv.strip)
@@ -13,17 +23,13 @@ module Cosm
13
23
  # we are running under 1.8.x or 1.9.x
14
24
  raise InvalidCSVError, e.message
15
25
  end
16
- version = detect_version(rows, csv_version)
26
+
27
+ version = FeedDefaults.detect_version(rows, csv_version)
28
+
17
29
  hash = Hash.new
30
+
18
31
  if version == :v2
19
- raise InvalidCSVError, "CSV is invalid. Incorrect number of fields" if rows.sort { |a,b| a.length <=> b.length }.reverse.first.length > 3
20
- hash["datastreams"] = rows.collect {|row|
21
- timestamp = {}
22
- if row.size == 3
23
- timestamp["updated"] = row[1].strip
24
- end
25
- { "id" => row.first.to_s.strip, "current_value" => row.last.to_s.strip }.merge(timestamp)
26
- }
32
+ hash["datastreams"] = extract_datastreams(rows)
27
33
  elsif version == :v1
28
34
  raise InvalidCSVError, "CSV is invalid. Currently we can only accept CSV for your most recent set of values. You have submitted #{rows.size} rows of data." if rows.size > 1
29
35
  hash["datastreams"] = []
@@ -37,11 +43,49 @@ module Cosm
37
43
 
38
44
  private
39
45
 
40
- def detect_version(rows, version = nil)
41
- return version if version
42
- return :v2 if rows.size >= 2
43
- return :v1 if rows.size == 1 && rows.first.size != 2
44
- raise UnknownVersionError, "CSV Version could not be detected"
46
+ def extract_datastreams(rows)
47
+ row_sizes = rows.collect { |row| row.size }.uniq
48
+ row_ids = rows.collect { |row| row.first.to_s.strip }.uniq
49
+
50
+ raise InvalidCSVError, "CSV is invalid. Incorrect number of fields" if row_sizes.max > 3
51
+
52
+ datastream_buckets = {}
53
+
54
+ # iterate through each row bucketing by datastream id
55
+ rows.each do |row|
56
+ # this splits each row into the id first element, and an array containing the rest of the row
57
+ id, *rest = *row
58
+
59
+ # make empty array if it doesn't exist
60
+ datastream_buckets[id.to_s.strip] ||= []
61
+ # add this row to the correct bucketed array
62
+ datastream_buckets[id.to_s.strip] << rest
63
+ end
64
+
65
+ datastreams = []
66
+
67
+ row_ids.each do |datastream_id|
68
+ datastream_data = datastream_buckets[datastream_id]
69
+
70
+ if datastream_data.size == 1
71
+ # single value for this datastream - current normal
72
+ data = datastream_data[0]
73
+ if data.size == 2
74
+ datastreams << { "id" => datastream_id, "updated" => data[0].to_s.strip, "current_value" => data[1].to_s.strip }
75
+ else
76
+ datastreams << { "id" => datastream_id, "current_value" => data[0].to_s.strip }
77
+ end
78
+ else
79
+ # multiple values for this datastream
80
+ raise InvalidCSVError, "CSV is invalid. If multiple values given they must include a timestamp for all values" if datastream_data.collect { |d| d.size }.min < 2
81
+
82
+ datapoints = datastream_data.collect { |datapoint_data| { "at" => datapoint_data[0].to_s.strip, "value" => datapoint_data[1].to_s.strip } }
83
+
84
+ datastreams << { "id" => datastream_id, "datapoints" => datapoints }
85
+ end
86
+ end
87
+
88
+ return datastreams
45
89
  end
46
90
  end
47
91
  end
@@ -11,8 +11,10 @@ module Cosm
11
11
  raise InvalidXMLError, "Missing 'environment' node from base node" if parsed['eeml'].nil? || !parsed['eeml'].key?('environment')
12
12
  return {} if parsed['eeml']['environment'].nil?
13
13
  datastream = parsed['eeml']['environment']['data']
14
+ raise InvalidXMLError, "Multiple 'data' nodes are not permitted for Datapoint level XML" if datastream.is_a?(Array)
14
15
  datapoint = datastream['datapoints']
15
- _extract_datapoint(datapoint)
16
+ raise InvalidXMLError, "Multiple 'value' nodes are not permitted for Datapoint level XML" if datapoint.is_a?(Array)
17
+ _extract_datapoints(datapoint).first
16
18
  rescue MultiXml::ParseError => e
17
19
  raise InvalidXMLError, e.message
18
20
  end
@@ -23,6 +23,7 @@ module Cosm
23
23
 
24
24
  # As produced by http://cosm.com/api/v2/FEED_ID/datastreams/DATASTREAM_ID.xml
25
25
  def transform_v2(xml)
26
+ validate_xml(xml)
26
27
  datastream = convert_to_hash(xml['data'])
27
28
  _extract_datastream(datastream).merge({
28
29
  :feed_id => strip(xml,'id'),
@@ -32,6 +33,7 @@ module Cosm
32
33
 
33
34
  # As produced by http://cosm.com/api/v1/FEED_ID/datastreams/DATASTREAM_ID.xml
34
35
  def transform_v1(xml)
36
+ validate_xml(xml)
35
37
  datastream = convert_to_hash(xml['data'])
36
38
  _extract_datastream_v1(datastream).merge({
37
39
  :feed_id => strip(xml,'id'),
@@ -40,6 +42,10 @@ module Cosm
40
42
  })
41
43
  end
42
44
 
45
+ def validate_xml(xml)
46
+ raise InvalidXMLError, "Multiple 'data' nodes are not permitted for Datastream level XML" if xml['data'].is_a?(Array)
47
+ raise InvalidXMLError, "Missing 'data' node from source document" if xml['data'].nil?
48
+ end
43
49
  end
44
50
  end
45
51
  end
@@ -86,10 +86,9 @@ module Cosm
86
86
  end
87
87
 
88
88
  def _extract_datapoint(xml)
89
- value = convert_to_hash(xml['value'])
90
89
  {
91
- :at => strip(value,'at'),
92
- :value => strip(value,'__content__')
90
+ :at => strip(xml,'at'),
91
+ :value => strip(xml,'__content__')
93
92
  }
94
93
  end
95
94
 
@@ -1,3 +1,3 @@
1
1
  module Cosm #:nodoc:
2
- VERSION = '0.2.00'
2
+ VERSION = '0.2.01'
3
3
  end
@@ -120,43 +120,43 @@ describe Cosm::Datastream do
120
120
 
121
121
  it "should raise known exception if passed json but told xml" do
122
122
  expect {
123
- Cosm::Datastream.new(datastream_as_(:json), :xml)
123
+ Cosm::Datastream.new(datastream_as_(:json), :v2, :xml)
124
124
  }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
125
125
  end
126
126
 
127
127
  it "should raise known exception if passed csv but told xml" do
128
128
  expect {
129
- Cosm::Datastream.new(datastream_as_(:csv), :xml)
129
+ Cosm::Datastream.new(datastream_as_(:csv), :v2, :xml)
130
130
  }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
131
131
  end
132
132
 
133
133
  it "should raise known exception if passed xml but told json" do
134
134
  expect {
135
- Cosm::Datastream.new(datastream_as_(:xml), :json)
135
+ Cosm::Datastream.new(datastream_as_(:xml), :v2, :json)
136
136
  }.to raise_error(Cosm::Parsers::JSON::InvalidJSONError)
137
137
  end
138
138
 
139
139
  it "should raise known exception if passed csv but told json" do
140
140
  expect {
141
- Cosm::Datastream.new(datastream_as_(:csv), :json)
141
+ Cosm::Datastream.new(datastream_as_(:csv), :v2, :json)
142
142
  }.to raise_error(Cosm::Parsers::JSON::InvalidJSONError)
143
143
  end
144
144
 
145
145
  it "should raise known exception if passed json but told csv" do
146
146
  expect {
147
- Cosm::Datastream.new(datastream_as_(:json), :csv)
147
+ Cosm::Datastream.new(datastream_as_(:json), :v2, :csv)
148
148
  }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
149
149
  end
150
150
 
151
151
  it "should raise known exception if passed xml but told csv" do
152
152
  expect {
153
- Cosm::Datastream.new(datastream_as_(:xml), :csv)
153
+ Cosm::Datastream.new(datastream_as_(:xml), :v2, :csv)
154
154
  }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
155
155
  end
156
156
 
157
157
  it "should raise known exception if told some format we don't accept" do
158
158
  expect {
159
- Cosm::Datastream.new(datastream_as_(:xml), :html)
159
+ Cosm::Datastream.new(datastream_as_(:xml), :v2, :html)
160
160
  }.to raise_error(Cosm::InvalidFormatError)
161
161
  end
162
162
 
@@ -4,13 +4,13 @@ describe "default datastream csv parser" do
4
4
  describe "csv" do
5
5
  it "should convert Pachube CSV into attributes hash" do
6
6
  csv = datastream_as_(:csv)
7
- datastream = Cosm::Datastream.new(csv)
7
+ datastream = Cosm::Datastream.new(csv, :v2)
8
8
  datastream.should fully_represent_datastream(:csv, csv)
9
9
  end
10
10
 
11
11
  it "should capture timestamp if present" do
12
12
  csv = datastream_as_(:csv, :version => "timestamped")
13
- datastream = Cosm::Datastream.new(csv)
13
+ datastream = Cosm::Datastream.new(csv, :v2, :csv)
14
14
  datastream.updated.should == "2011-02-16T16:21:01.834174Z"
15
15
  datastream.current_value.should == "14"
16
16
  end
@@ -29,11 +29,82 @@ describe "default datastream csv parser" do
29
29
  }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
30
30
  end
31
31
 
32
+ it "should raise error if passed more than a single value as v1" do
33
+ csv = "192,2"
34
+ expect {
35
+ Cosm::Datastream.new(csv, :v1)
36
+ }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
37
+ end
38
+
32
39
  it "should raise exception if passed garbage csv" do
33
40
  expect {
34
41
  Cosm::Datastream.new("badly, \"quoted", :csv)
35
42
  }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
36
43
  end
44
+
45
+ it "should not raise exception if passed data with nil value" do
46
+ expect {
47
+ datastream = Cosm::Datastream.new("2012-08-12T00:00:00Z,", :v2)
48
+ datastream.current_value.should be_empty
49
+ }.to_not raise_error
50
+ end
51
+
52
+ it "should parse multiline csv" do
53
+ csv = <<-CSV
54
+ 2012-02-08T00:00:00Z,123
55
+ 2012-02-08T00:00:10Z,124
56
+ 2012-02-08T00:00:20Z,125
57
+ 2012-02-08T00:00:30Z,126
58
+ CSV
59
+ datastream = Cosm::Datastream.new(csv, :v2)
60
+ datastream.updated.should be_nil
61
+ datastream.current_value.should be_nil
62
+ datastream.datapoints.size.should == 4
63
+ datastream.datapoints.collect { |d| [d.at, d.value].join(",") }.join("\n").should == csv.strip
64
+ end
65
+
66
+ it "should not parse multiline csv passed to the v1 api" do
67
+ csv = <<-CSV
68
+ 2012-02-08T00:00:00Z,123
69
+ 2012-02-08T00:00:10Z,124
70
+ 2012-02-08T00:00:20Z,125
71
+ 2012-02-08T00:00:30Z,126
72
+ CSV
73
+ expect {
74
+ datastream = Cosm::Datastream.new(csv, :v1)
75
+ }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
76
+ end
77
+
78
+ it "should not accept multiline csv with just single values" do
79
+ csv = <<-CSV
80
+ 123
81
+ 124
82
+ 125
83
+ 126
84
+ CSV
85
+
86
+ expect {
87
+ datastream = Cosm::Datastream.new(csv, :v2)
88
+ }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
89
+ end
90
+
91
+ it "should strip whitespace from multiline values" do
92
+ csv = <<-CSV
93
+ 2012-02-08T00:00:00Z , 123
94
+ 2012-02-08T00:00:10Z , 124
95
+ 2012-02-08T00:00:20Z , 125
96
+ 2012-02-08T00:00:30Z , 126
97
+ CSV
98
+
99
+ datastream = Cosm::Datastream.new(csv, :v2)
100
+ datastream.updated.should be_nil
101
+ datastream.current_value.should be_nil
102
+ datastream.datapoints.size.should == 4
103
+ datastream.datapoints.sort { |a, b| a.at <=> b.at }.collect { |d| [d.at, d.value] }.should == [["2012-02-08T00:00:00Z","123"],
104
+ ["2012-02-08T00:00:10Z","124"],
105
+ ["2012-02-08T00:00:20Z","125"],
106
+ ["2012-02-08T00:00:30Z","126"]]
107
+ end
37
108
  end
38
109
  end
39
110
 
@@ -61,6 +61,26 @@ CSV
61
61
  }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError, /3 rows/)
62
62
  end
63
63
 
64
+ context "nil attribute csv" do
65
+ before(:each) do
66
+ @csv = "0,,"
67
+ end
68
+
69
+ it "should not raise exception if csv has nil values as v1" do
70
+ expect {
71
+ feed = Cosm::Feed.new(@csv, :v1)
72
+ feed.datastreams.size.should == 3
73
+ }.to_not raise_error
74
+ end
75
+
76
+ it "should not raise exception if csv has nil attributes as v2" do
77
+ expect {
78
+ feed = Cosm::Feed.new(@csv, :v2)
79
+ feed.datastreams.size.should == 1
80
+ }.to_not raise_error
81
+ end
82
+ end
83
+
64
84
  context "unwanted whitespace" do
65
85
  it "should strip whitespace from v2" do
66
86
  dodgy_csv = <<-CSV
@@ -84,6 +104,107 @@ CSV
84
104
  feed.should fully_represent_feed(:csv_v1, good_csv)
85
105
  end
86
106
  end
107
+
108
+ context "multivalue csv" do
109
+ def check_multiline_csv(csv)
110
+ feed = Cosm::Feed.new(csv)
111
+
112
+ feed.datastreams.size.should == 2
113
+ feed.datastreams.each do |datastream|
114
+ datastream.updated.should be_nil
115
+ datastream.current_value.should be_nil
116
+ datastream.datapoints.size.should == 3
117
+ datastream.datapoints.sort { |a,b| a.at <=> b.at }.collect { |d| [d.at, d.value] }.should == [["2012-08-12T00:00:00Z", "1"],
118
+ ["2012-08-12T00:00:05Z", "2"],
119
+ ["2012-08-12T00:00:10Z", "3"]]
120
+ end
121
+ end
122
+
123
+ it "should capture multivalue csv with timestamps" do
124
+ csv = <<-CSV
125
+ stream0,2012-08-12T00:00:00Z,1
126
+ stream1,2012-08-12T00:00:00Z,1
127
+ stream0,2012-08-12T00:00:05Z,2
128
+ stream1,2012-08-12T00:00:05Z,2
129
+ stream0,2012-08-12T00:00:10Z,3
130
+ stream1,2012-08-12T00:00:10Z,3
131
+ CSV
132
+
133
+ check_multiline_csv(csv)
134
+ end
135
+
136
+ it "should capture multivalue csv with timestamps no matter the grouping" do
137
+ csv = <<-CSV
138
+ stream0,2012-08-12T00:00:00Z,1
139
+ stream0,2012-08-12T00:00:05Z,2
140
+ stream0,2012-08-12T00:00:10Z,3
141
+ stream1,2012-08-12T00:00:00Z,1
142
+ stream1,2012-08-12T00:00:05Z,2
143
+ stream1,2012-08-12T00:00:10Z,3
144
+ CSV
145
+
146
+ check_multiline_csv(csv)
147
+ end
148
+
149
+ it "should strip whitespace from multiline csv" do
150
+ csv = <<-CSV
151
+ stream0, 2012-08-12T00:00:00Z, 1
152
+ stream0, 2012-08-12T00:00:05Z, 2
153
+ stream0, 2012-08-12T00:00:10Z, 3
154
+ stream1, 2012-08-12T00:00:00Z, 1
155
+ stream1, 2012-08-12T00:00:05Z, 2
156
+ stream1, 2012-08-12T00:00:10Z, 3
157
+ CSV
158
+
159
+ check_multiline_csv(csv)
160
+ end
161
+
162
+ it "should reject multivalue csv without timestamps" do
163
+ csv = <<-CSV
164
+ stream0,1
165
+ stream1,1
166
+ stream0,2
167
+ stream1,2
168
+ stream0,3
169
+ stream1,3
170
+ CSV
171
+ expect {
172
+ Cosm::Feed.new(csv)
173
+ }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
174
+ end
175
+
176
+ it "should reject multivalue csv if we tell it its v1" do
177
+ csv = <<-CSV
178
+ stream0,2012-08-12T00:00:00Z,1
179
+ stream1,2012-08-12T00:00:00Z,1
180
+ CSV
181
+
182
+ expect {
183
+ Cosm::Feed.new(csv, :v1)
184
+ }.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
185
+ end
186
+
187
+ it "should permit an individual value within a larger update to not have a timestamp" do
188
+ csv = <<-CSV
189
+ stream0,2012-08-12T00:00:00Z,1
190
+ stream1,2012-08-12T00:00:00Z,1
191
+ stream0,2012-08-12T00:00:05Z,2
192
+ stream1,2012-08-12T00:00:05Z,2
193
+ stream0,2012-08-12T00:00:10Z,3
194
+ stream1,2012-08-12T00:00:10Z,3
195
+ stream2,4
196
+ CSV
197
+ feed = Cosm::Feed.new(csv)
198
+ feed.datastreams.size.should == 3
199
+ sorted_datastreams = feed.datastreams.sort { |a, b| a.id <=> b.id }
200
+ [0,1].each do |i|
201
+ sorted_datastreams[i].current_value.should be_nil
202
+ sorted_datastreams[i].updated.should be_nil
203
+ sorted_datastreams[i].datapoints.size.should == 3
204
+ end
205
+ sorted_datastreams[2].current_value.should == "4"
206
+ end
207
+ end
87
208
  end
88
209
  end
89
210
 
@@ -32,7 +32,7 @@ describe "default datastream json parser" do
32
32
 
33
33
  it "should raise known exception if passed garbage as JSON" do
34
34
  expect {
35
- Cosm::Datastream.new("This is not json", :json)
35
+ Cosm::Datastream.new("This is not json", :v2, :json)
36
36
  }.to raise_error(Cosm::Parsers::JSON::InvalidJSONError)
37
37
  end
38
38
 
@@ -3,8 +3,8 @@ require 'spec_helper'
3
3
  describe "default datastream xml parser" do
4
4
  context "0.5.1 (used by API v2)" do
5
5
  it "should convert into attributes hash" do
6
- @xml = datastream_as_(:xml)
7
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
6
+ xml = datastream_as_(:xml)
7
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
8
8
  end
9
9
 
10
10
  it "should convert into attributes hash when no version string but correct xmlns" do
@@ -13,30 +13,57 @@ describe "default datastream xml parser" do
13
13
  end
14
14
 
15
15
  it "should handle blank tags" do
16
- @xml = datastream_as_(:xml, :except_node => :tag)
17
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
16
+ xml = datastream_as_(:xml, :except_node => :tag)
17
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
18
18
  end
19
19
 
20
20
  it "should handle blank units" do
21
- @xml = datastream_as_(:xml, :except_node => :unit)
22
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
21
+ xml = datastream_as_(:xml, :except_node => :unit)
22
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
23
23
  end
24
24
 
25
25
  it "should handle missing unit attributes" do
26
- @xml = datastream_as_(:xml, :except_node => :unit_attributes)
27
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
26
+ xml = datastream_as_(:xml, :except_node => :unit_attributes)
27
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
28
28
  end
29
29
 
30
30
  it "should handle missing timestamps" do
31
- @xml = datastream_as_(:xml, :except_node => :timestamps)
32
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
31
+ xml = datastream_as_(:xml, :except_node => :timestamps)
32
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
33
+ end
34
+
35
+ it "should capture all datapoints" do
36
+ xml = datastream_as_(:xml)
37
+ datastream = Cosm::Datastream.new(xml)
38
+ datastream.datapoints.size.should == 3
39
+ end
40
+
41
+ it "should raise exception if passed xml containing more than one datastream" do
42
+ xml = feed_as_(:xml)
43
+ expect {
44
+ Cosm::Datastream.new(xml)
45
+ }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
46
+ end
47
+
48
+ it "should raise exception if passed xml without any datastreams" do
49
+ xml = <<-XML
50
+ <?xml version="1.0" encoding="UTF-8"?>
51
+ <eeml xmlns="http://www.eeml.org/xsd/0.5.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.5.1" xsi:schemaLocation="http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd">
52
+ <environment id="504" creator="http://appdev.loc:3000/users/occaecati">
53
+ </environment>
54
+ </eeml>
55
+ XML
56
+
57
+ expect {
58
+ Cosm::Datastream.new(xml)
59
+ }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
33
60
  end
34
61
  end
35
62
 
36
63
  context "5 (used by API v1)" do
37
64
  it "should convert into attributes hash" do
38
- @xml = datastream_as_(:xml, :version => "5")
39
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
65
+ xml = datastream_as_(:xml, :version => "5")
66
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
40
67
  end
41
68
 
42
69
  it "should convert into attributes hash even when no version attribute if correct xmlns" do
@@ -45,34 +72,55 @@ describe "default datastream xml parser" do
45
72
  end
46
73
 
47
74
  it "should handle blank tags" do
48
- @xml = datastream_as_(:xml, :version => "5", :except_node => :tag)
49
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
75
+ xml = datastream_as_(:xml, :version => "5", :except_node => :tag)
76
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
50
77
  end
51
78
 
52
79
  it "should handle blank units" do
53
- @xml = datastream_as_(:xml, :version => "5", :except_node => :unit)
54
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
80
+ xml = datastream_as_(:xml, :version => "5", :except_node => :unit)
81
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
55
82
  end
56
83
 
57
84
  it "should handle missing unit attributes" do
58
- @xml = datastream_as_(:xml, :version => "5", :except_node => :unit_attributes)
59
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
85
+ xml = datastream_as_(:xml, :version => "5", :except_node => :unit_attributes)
86
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
60
87
  end
61
88
 
62
89
  it "should handle missing value attributes" do
63
- @xml = datastream_as_(:xml, :version => "5", :except_node => :value_attributes)
64
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
90
+ xml = datastream_as_(:xml, :version => "5", :except_node => :value_attributes)
91
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
65
92
  end
66
93
 
67
94
  it "should handle missing timestamps" do
68
- @xml = datastream_as_(:xml, :version => "5", :except_node => :timestamps)
69
- Cosm::Datastream.new(@xml).should fully_represent_datastream(:xml, @xml)
95
+ xml = datastream_as_(:xml, :version => "5", :except_node => :timestamps)
96
+ Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
97
+ end
98
+
99
+ it "should raise exception if passed xml containing more than one datastream" do
100
+ xml = feed_as_(:xml, :version => "5")
101
+ expect {
102
+ Cosm::Datastream.new(xml)
103
+ }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
104
+ end
105
+
106
+ it "should raise exception if passed xml without any datastreams" do
107
+ xml = <<-XML
108
+ <?xml version="1.0" encoding="UTF-8"?>
109
+ <eeml xmlns="http://www.eeml.org/xsd/005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="5" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd">
110
+ <environment updated="2011-02-16T16:21:01.834174Z" id="504" creator="http://appdev.loc:3000/users/occaecati">
111
+ </environment>
112
+ </eeml>
113
+ XML
114
+
115
+ expect {
116
+ Cosm::Datastream.new(xml)
117
+ }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
70
118
  end
71
119
  end
72
120
 
73
121
  it "should raise exception if passed garbage as XML" do
74
122
  expect {
75
- Cosm::Datastream.new("This is not xml", :xml)
123
+ Cosm::Datastream.new("This is not xml", :v2, :xml)
76
124
  }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
77
125
  end
78
126
  end
@@ -216,5 +216,39 @@ EOXML
216
216
  }.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
217
217
  end
218
218
  end
219
+
220
+ context "feeds with datapoints" do
221
+ it "should grab all datapoints present in valid xml" do
222
+ xml = <<-XML
223
+ <eeml xmlns="http://www.eeml.org/xsd/0.5.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.5.1" xsi:schemaLocation="http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd">
224
+ <environment>
225
+ <data id="0">
226
+ <datapoints>
227
+ <value at="2010-05-20T11:01:43Z">294</value>
228
+ <value at="2010-05-20T11:01:44Z">295</value>
229
+ <value at="2010-05-20T11:01:45Z">296</value>
230
+ <value at="2010-05-20T11:01:46Z">297</value>
231
+ </datapoints>
232
+ </data>
233
+ <data id="1">
234
+ <current_value at="2010-05-20T11:01:47Z">23</current_value>
235
+ <datapoints>
236
+ <value at="2010-05-20T11:01:43Z">24</value>
237
+ <value at="2010-05-20T11:01:44Z">25</value>
238
+ </datapoints>
239
+ </data>
240
+ </environment>
241
+ </eeml>
242
+ XML
243
+ feed = Cosm::Feed.new(xml)
244
+ feed.datastreams.size.should == 2
245
+ feed.datastreams[0].current_value.should == nil
246
+ feed.datastreams[0].datapoints.size.should == 4
247
+ feed.datastreams[0].datapoints.collect { |d| d.value }.should == ["294", "295", "296", "297"]
248
+ feed.datastreams[1].current_value.should == "23"
249
+ feed.datastreams[1].datapoints.size.should == 2
250
+ feed.datastreams[1].datapoints.collect { |d| d.value }.should == ["24", "25"]
251
+ end
252
+ end
219
253
  end
220
254
 
@@ -14,6 +14,7 @@ if !defined?(JRUBY_VERSION)
14
14
  SimpleCov.start do
15
15
  add_filter "/spec/"
16
16
  add_filter "/lib/cosm-rb.rb"
17
+ add_filter "/vendor/"
17
18
  end
18
19
  end
19
20
  end
@@ -77,10 +77,14 @@ RSpec::Matchers.define :fully_represent_datastream do |format, formatted_datastr
77
77
  def match_json_datastream(datastream, formatted_datastream)
78
78
  json = MultiJson.load(formatted_datastream)
79
79
  case json['version']
80
- when '1.0.0'
80
+ when '0.6-alpha'
81
81
  raise "Not implemented"
82
82
  else
83
- false
83
+ datastream.current_value.should == json["current_value"]
84
+ datastream.id.should == json["id"]
85
+ datastream.updated.should == json["at"]
86
+ datastream.min_value.should == json["min_value"]
87
+ datastream.max_value.should == json["max_value"]
84
88
  end
85
89
  end
86
90
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cosm-rb
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 0
10
- version: 0.2.00
9
+ - 1
10
+ version: 0.2.01
11
11
  platform: ruby
12
12
  authors:
13
13
  - Paul Bellamy
@@ -21,9 +21,7 @@ date: 2012-09-11 00:00:00 +00:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
24
- name: multi_json
25
- prerelease: false
26
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
27
25
  none: false
28
26
  requirements:
29
27
  - - ">="
@@ -34,12 +32,12 @@ dependencies:
34
32
  - 3
35
33
  - 6
36
34
  version: 1.3.6
35
+ requirement: *id001
37
36
  type: :runtime
38
- version_requirements: *id001
39
- - !ruby/object:Gem::Dependency
40
- name: multi_xml
37
+ name: multi_json
41
38
  prerelease: false
42
- requirement: &id002 !ruby/object:Gem::Requirement
39
+ - !ruby/object:Gem::Dependency
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
43
41
  none: false
44
42
  requirements:
45
43
  - - ">="
@@ -50,12 +48,12 @@ dependencies:
50
48
  - 5
51
49
  - 1
52
50
  version: 0.5.1
51
+ requirement: *id002
53
52
  type: :runtime
54
- version_requirements: *id002
55
- - !ruby/object:Gem::Dependency
56
- name: yajl-ruby
53
+ name: multi_xml
57
54
  prerelease: false
58
- requirement: &id003 !ruby/object:Gem::Requirement
55
+ - !ruby/object:Gem::Dependency
56
+ version_requirements: &id003 !ruby/object:Gem::Requirement
59
57
  none: false
60
58
  requirements:
61
59
  - - ">="
@@ -66,12 +64,12 @@ dependencies:
66
64
  - 1
67
65
  - 0
68
66
  version: 1.1.0
67
+ requirement: *id003
69
68
  type: :runtime
70
- version_requirements: *id003
71
- - !ruby/object:Gem::Dependency
72
- name: nokogiri
69
+ name: yajl-ruby
73
70
  prerelease: false
74
- requirement: &id004 !ruby/object:Gem::Requirement
71
+ - !ruby/object:Gem::Dependency
72
+ version_requirements: &id004 !ruby/object:Gem::Requirement
75
73
  none: false
76
74
  requirements:
77
75
  - - ">="
@@ -82,12 +80,12 @@ dependencies:
82
80
  - 4
83
81
  - 4
84
82
  version: 1.4.4
83
+ requirement: *id004
85
84
  type: :runtime
86
- version_requirements: *id004
87
- - !ruby/object:Gem::Dependency
88
- name: httparty
85
+ name: nokogiri
89
86
  prerelease: false
90
- requirement: &id005 !ruby/object:Gem::Requirement
87
+ - !ruby/object:Gem::Dependency
88
+ version_requirements: &id005 !ruby/object:Gem::Requirement
91
89
  none: false
92
90
  requirements:
93
91
  - - ">="
@@ -98,12 +96,12 @@ dependencies:
98
96
  - 8
99
97
  - 3
100
98
  version: 0.8.3
99
+ requirement: *id005
101
100
  type: :runtime
102
- version_requirements: *id005
103
- - !ruby/object:Gem::Dependency
104
- name: fastercsv
101
+ name: httparty
105
102
  prerelease: false
106
- requirement: &id006 !ruby/object:Gem::Requirement
103
+ - !ruby/object:Gem::Dependency
104
+ version_requirements: &id006 !ruby/object:Gem::Requirement
107
105
  none: false
108
106
  requirements:
109
107
  - - ">="
@@ -114,12 +112,12 @@ dependencies:
114
112
  - 5
115
113
  - x
116
114
  version: 1.5.x
115
+ requirement: *id006
117
116
  type: :runtime
118
- version_requirements: *id006
119
- - !ruby/object:Gem::Dependency
120
- name: ox
117
+ name: fastercsv
121
118
  prerelease: false
122
- requirement: &id007 !ruby/object:Gem::Requirement
119
+ - !ruby/object:Gem::Dependency
120
+ version_requirements: &id007 !ruby/object:Gem::Requirement
123
121
  none: false
124
122
  requirements:
125
123
  - - ">="
@@ -130,12 +128,12 @@ dependencies:
130
128
  - 5
131
129
  - 9
132
130
  version: 1.5.9
131
+ requirement: *id007
133
132
  type: :runtime
134
- version_requirements: *id007
135
- - !ruby/object:Gem::Dependency
136
- name: ruby-debug
133
+ name: ox
137
134
  prerelease: false
138
- requirement: &id008 !ruby/object:Gem::Requirement
135
+ - !ruby/object:Gem::Dependency
136
+ version_requirements: &id008 !ruby/object:Gem::Requirement
139
137
  none: false
140
138
  requirements:
141
139
  - - ">="
@@ -144,12 +142,12 @@ dependencies:
144
142
  segments:
145
143
  - 0
146
144
  version: "0"
145
+ requirement: *id008
147
146
  type: :development
148
- version_requirements: *id008
149
- - !ruby/object:Gem::Dependency
150
- name: rcov
147
+ name: ruby-debug
151
148
  prerelease: false
152
- requirement: &id009 !ruby/object:Gem::Requirement
149
+ - !ruby/object:Gem::Dependency
150
+ version_requirements: &id009 !ruby/object:Gem::Requirement
153
151
  none: false
154
152
  requirements:
155
153
  - - ">="
@@ -160,12 +158,12 @@ dependencies:
160
158
  - 9
161
159
  - 9
162
160
  version: 0.9.9
161
+ requirement: *id009
163
162
  type: :development
164
- version_requirements: *id009
165
- - !ruby/object:Gem::Dependency
166
- name: rake
163
+ name: rcov
167
164
  prerelease: false
168
- requirement: &id010 !ruby/object:Gem::Requirement
165
+ - !ruby/object:Gem::Dependency
166
+ version_requirements: &id010 !ruby/object:Gem::Requirement
169
167
  none: false
170
168
  requirements:
171
169
  - - "="
@@ -176,12 +174,12 @@ dependencies:
176
174
  - 8
177
175
  - 7
178
176
  version: 0.8.7
177
+ requirement: *id010
179
178
  type: :development
180
- version_requirements: *id010
181
- - !ruby/object:Gem::Dependency
182
- name: rspec
179
+ name: rake
183
180
  prerelease: false
184
- requirement: &id011 !ruby/object:Gem::Requirement
181
+ - !ruby/object:Gem::Dependency
182
+ version_requirements: &id011 !ruby/object:Gem::Requirement
185
183
  none: false
186
184
  requirements:
187
185
  - - "="
@@ -192,8 +190,10 @@ dependencies:
192
190
  - 6
193
191
  - 0
194
192
  version: 2.6.0
193
+ requirement: *id011
195
194
  type: :development
196
- version_requirements: *id011
195
+ name: rspec
196
+ prerelease: false
197
197
  description: A library for communicating with the Cosm REST API, parsing and rendering Cosm feed formats
198
198
  email:
199
199
  - paul.a.bellamy@gmail.com