cosm-rb 0.2.00 → 0.2.01

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.
@@ -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