xively-rb 0.2.09

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.
Files changed (124) hide show
  1. data/.gitignore +13 -0
  2. data/.rbenv-version +1 -0
  3. data/.rspec +2 -0
  4. data/.rvmrc +1 -0
  5. data/.travis.yml +7 -0
  6. data/CHANGELOG.md +91 -0
  7. data/CONTRIBUTING.md +95 -0
  8. data/Gemfile +15 -0
  9. data/LICENSE.md +13 -0
  10. data/README.md +10 -0
  11. data/Rakefile +25 -0
  12. data/ci/build_hudson.sh +24 -0
  13. data/init.rb +2 -0
  14. data/lib/xively-rb.rb +44 -0
  15. data/lib/xively-rb/array_extensions.rb +6 -0
  16. data/lib/xively-rb/base.rb +52 -0
  17. data/lib/xively-rb/base/instance_methods.rb +28 -0
  18. data/lib/xively-rb/client.rb +43 -0
  19. data/lib/xively-rb/datapoint.rb +72 -0
  20. data/lib/xively-rb/datastream.rb +127 -0
  21. data/lib/xively-rb/exceptions.rb +5 -0
  22. data/lib/xively-rb/feed.rb +109 -0
  23. data/lib/xively-rb/hash_extensions.rb +16 -0
  24. data/lib/xively-rb/helpers.rb +41 -0
  25. data/lib/xively-rb/key.rb +99 -0
  26. data/lib/xively-rb/nil_content.rb +15 -0
  27. data/lib/xively-rb/object_extensions.rb +6 -0
  28. data/lib/xively-rb/parsers/csv/datastream_defaults.rb +50 -0
  29. data/lib/xively-rb/parsers/csv/feed_defaults.rb +97 -0
  30. data/lib/xively-rb/parsers/defaults.rb +15 -0
  31. data/lib/xively-rb/parsers/json/datapoint_defaults.rb +16 -0
  32. data/lib/xively-rb/parsers/json/datastream_defaults.rb +58 -0
  33. data/lib/xively-rb/parsers/json/feed_defaults.rb +114 -0
  34. data/lib/xively-rb/parsers/json/key_defaults.rb +20 -0
  35. data/lib/xively-rb/parsers/json/search_result_defaults.rb +24 -0
  36. data/lib/xively-rb/parsers/json/trigger_defaults.rb +16 -0
  37. data/lib/xively-rb/parsers/xml/datapoint_defaults.rb +27 -0
  38. data/lib/xively-rb/parsers/xml/datastream_defaults.rb +53 -0
  39. data/lib/xively-rb/parsers/xml/errors.rb +7 -0
  40. data/lib/xively-rb/parsers/xml/feed_defaults.rb +83 -0
  41. data/lib/xively-rb/parsers/xml/helpers.rb +116 -0
  42. data/lib/xively-rb/parsers/xml/key_defaults.rb +46 -0
  43. data/lib/xively-rb/parsers/xml/trigger_defaults.rb +28 -0
  44. data/lib/xively-rb/permission.rb +67 -0
  45. data/lib/xively-rb/resource.rb +43 -0
  46. data/lib/xively-rb/search_result.rb +68 -0
  47. data/lib/xively-rb/string_extensions.rb +6 -0
  48. data/lib/xively-rb/templates/csv/datapoint_defaults.rb +22 -0
  49. data/lib/xively-rb/templates/csv/datastream_defaults.rb +43 -0
  50. data/lib/xively-rb/templates/csv/feed_defaults.rb +47 -0
  51. data/lib/xively-rb/templates/defaults.rb +14 -0
  52. data/lib/xively-rb/templates/json/datapoint_defaults.rb +15 -0
  53. data/lib/xively-rb/templates/json/datastream_defaults.rb +61 -0
  54. data/lib/xively-rb/templates/json/feed_defaults.rb +90 -0
  55. data/lib/xively-rb/templates/json/key_defaults.rb +39 -0
  56. data/lib/xively-rb/templates/json/search_result_defaults.rb +42 -0
  57. data/lib/xively-rb/templates/json/trigger_defaults.rb +21 -0
  58. data/lib/xively-rb/templates/xml/datapoint_defaults.rb +25 -0
  59. data/lib/xively-rb/templates/xml/datastream_defaults.rb +66 -0
  60. data/lib/xively-rb/templates/xml/feed_defaults.rb +112 -0
  61. data/lib/xively-rb/templates/xml/search_result_defaults.rb +118 -0
  62. data/lib/xively-rb/templates/xml_headers.rb +17 -0
  63. data/lib/xively-rb/trigger.rb +66 -0
  64. data/lib/xively-rb/validations.rb +9 -0
  65. data/lib/xively-rb/version.rb +3 -0
  66. data/spec/fixtures/models.rb +81 -0
  67. data/spec/spec_helper.rb +29 -0
  68. data/spec/support/contain_datapoint_eeml_matcher.rb +16 -0
  69. data/spec/support/contain_datastream_eeml_matcher.rb +60 -0
  70. data/spec/support/contain_feed_eeml_matcher.rb +98 -0
  71. data/spec/support/datapoint_helper.rb +53 -0
  72. data/spec/support/datastream_helper.rb +324 -0
  73. data/spec/support/describe_eeml_matcher.rb +23 -0
  74. data/spec/support/feed_helper.rb +783 -0
  75. data/spec/support/fully_represent_datapoint_matcher.rb +30 -0
  76. data/spec/support/fully_represent_datastream_matcher.rb +96 -0
  77. data/spec/support/fully_represent_feed_matcher.rb +234 -0
  78. data/spec/support/fully_represent_key_matcher.rb +74 -0
  79. data/spec/support/fully_represent_search_result_matcher.rb +67 -0
  80. data/spec/support/fully_represent_trigger_matcher.rb +29 -0
  81. data/spec/support/key_helper.rb +74 -0
  82. data/spec/support/search_result_helper.rb +252 -0
  83. data/spec/support/trigger_helper.rb +51 -0
  84. data/spec/xively-rb/array_extensions_spec.rb +9 -0
  85. data/spec/xively-rb/base/instance_methods_spec.rb +109 -0
  86. data/spec/xively-rb/base_spec.rb +56 -0
  87. data/spec/xively-rb/client_spec.rb +51 -0
  88. data/spec/xively-rb/datapoint_spec.rb +187 -0
  89. data/spec/xively-rb/datastream_spec.rb +344 -0
  90. data/spec/xively-rb/feed_spec.rb +341 -0
  91. data/spec/xively-rb/hash_extensions_spec.rb +20 -0
  92. data/spec/xively-rb/helpers_spec.rb +56 -0
  93. data/spec/xively-rb/key_spec.rb +198 -0
  94. data/spec/xively-rb/parsers/csv/datastream_defaults_spec.rb +110 -0
  95. data/spec/xively-rb/parsers/csv/feed_defaults_spec.rb +234 -0
  96. data/spec/xively-rb/parsers/json/datapoint_defaults_spec.rb +21 -0
  97. data/spec/xively-rb/parsers/json/datastream_defaults_spec.rb +105 -0
  98. data/spec/xively-rb/parsers/json/feed_defaults_spec.rb +45 -0
  99. data/spec/xively-rb/parsers/json/key_defaults_spec.rb +14 -0
  100. data/spec/xively-rb/parsers/json/search_result_defaults_spec.rb +18 -0
  101. data/spec/xively-rb/parsers/json/trigger_defaults_spec.rb +22 -0
  102. data/spec/xively-rb/parsers/xml/datapoint_defaults_spec.rb +19 -0
  103. data/spec/xively-rb/parsers/xml/datastream_defaults_spec.rb +148 -0
  104. data/spec/xively-rb/parsers/xml/feed_defaults_spec.rb +254 -0
  105. data/spec/xively-rb/parsers/xml/key_defaults_spec.rb +22 -0
  106. data/spec/xively-rb/parsers/xml/trigger_defaults_spec.rb +22 -0
  107. data/spec/xively-rb/search_result_spec.rb +257 -0
  108. data/spec/xively-rb/string_extensions_spec.rb +12 -0
  109. data/spec/xively-rb/templates/csv/datapoint_defaults_spec.rb +41 -0
  110. data/spec/xively-rb/templates/csv/datastream_defaults_spec.rb +131 -0
  111. data/spec/xively-rb/templates/csv/feed_defaults_spec.rb +78 -0
  112. data/spec/xively-rb/templates/json/datapoint_defaults_spec.rb +14 -0
  113. data/spec/xively-rb/templates/json/datastream_defaults_spec.rb +170 -0
  114. data/spec/xively-rb/templates/json/feed_defaults_spec.rb +399 -0
  115. data/spec/xively-rb/templates/json/key_defaults_spec.rb +29 -0
  116. data/spec/xively-rb/templates/json/search_result_defaults_spec.rb +37 -0
  117. data/spec/xively-rb/templates/json/trigger_defaults_spec.rb +19 -0
  118. data/spec/xively-rb/templates/xml/datapoint_defaults_spec.rb +14 -0
  119. data/spec/xively-rb/templates/xml/datastream_defaults_spec.rb +113 -0
  120. data/spec/xively-rb/templates/xml/feed_defaults_spec.rb +131 -0
  121. data/spec/xively-rb/templates/xml/search_result_defaults_spec.rb +44 -0
  122. data/spec/xively-rb/trigger_spec.rb +157 -0
  123. data/xively-rb.gemspec +41 -0
  124. metadata +333 -0
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xively::Base do
4
+ describe "#is_xively" do
5
+ it "should take a class name and a hash of options" do
6
+ lambda { Feed.is_xively }.should raise_error(ArgumentError, "wrong number of arguments (0 for 1)")
7
+ lambda { Feed.is_xively(:feed, {}, "bogus third arg") }.should raise_error(ArgumentError, "wrong number of arguments (3 for 2)")
8
+ end
9
+
10
+ it "should assign mapping class" do
11
+ class TestClass
12
+ extend Xively::Base
13
+ is_xively :datastream
14
+ end
15
+ TestClass.xively_class.should == Xively::Datastream
16
+ end
17
+
18
+ it "should assign mapping class for datapoints" do
19
+ class TestClass
20
+ extend Xively::Base
21
+ is_xively :datapoint
22
+ end
23
+ TestClass.xively_class.should == Xively::Datapoint
24
+ end
25
+
26
+ it "should not assign mapping class if unrecognized" do
27
+ class TestClass
28
+ extend Xively::Base
29
+ is_xively :hero_stream
30
+ end
31
+ TestClass.xively_class.should be_nil
32
+ end
33
+
34
+ it "should assign optional mappings" do
35
+ class TestClass
36
+ extend Xively::Base
37
+ is_xively :feed, {:title => :custom_method, :website => :custom_method}
38
+ def custom_method
39
+ "Custom title"
40
+ end
41
+ end
42
+ TestClass.xively_mappings.should == {:title => :custom_method, :website => :custom_method}
43
+ end
44
+
45
+ it "should include our instance methods into a class when we call it" do
46
+ class TestClass
47
+ extend Xively::Base
48
+ end
49
+ TestClass.should_receive(:include).with(Xively::Base::InstanceMethods)
50
+ class TestClass
51
+ is_xively :feed
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Xively::Client" do
4
+ before do
5
+ @client = Xively::Client.new("abcdefg")
6
+ end
7
+
8
+ it "should have the base uri defined" do
9
+ Xively::Client.base_uri.should == 'https://api.xively.com'
10
+ end
11
+
12
+ it "should be initializable with an api key" do
13
+ @client.api_key.should eql("abcdefg")
14
+ end
15
+
16
+ describe "#get" do
17
+ it "should make the appropriate request" do
18
+ request_stub = stub_request(:get, "#{Xively::Client.base_uri}/v2/feeds/504.json").
19
+ with(:headers => {'User-Agent' => Xively::Client.user_agent, 'X-ApiKey' => 'abcdefg'})
20
+ @client.get('/v2/feeds/504.json')
21
+ request_stub.should have_been_made
22
+ end
23
+ end
24
+
25
+ describe "#put" do
26
+ it "should make the appropriate request" do
27
+ request_stub = stub_request(:put, "#{Xively::Client.base_uri}/v2/feeds/504.json").
28
+ with(:headers => {'User-Agent' => Xively::Client.user_agent, 'X-ApiKey' => 'abcdefg'}, :body => "dataz")
29
+ @client.put('/v2/feeds/504.json', :body => "dataz")
30
+ request_stub.should have_been_made
31
+ end
32
+ end
33
+
34
+ describe "#post" do
35
+ it "should make the appropriate request" do
36
+ request_stub = stub_request(:post, "#{Xively::Client.base_uri}/v2/feeds/504.json").
37
+ with(:headers => {'User-Agent' => Xively::Client.user_agent, 'X-ApiKey' => 'abcdefg'}, :body => "dataz")
38
+ @client.post('/v2/feeds/504.json', :body => "dataz")
39
+ request_stub.should have_been_made
40
+ end
41
+ end
42
+
43
+ describe "#delete" do
44
+ it "should make the appropriate request" do
45
+ request_stub = stub_request(:delete, "#{Xively::Client.base_uri}/v2/feeds/504/datastreams/test.json").
46
+ with(:headers => {'User-Agent' => Xively::Client.user_agent, 'X-ApiKey' => 'abcdefg'})
47
+ @client.delete('/v2/feeds/504/datastreams/test.json')
48
+ request_stub.should have_been_made
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,187 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xively::Datapoint do
4
+
5
+ it "should have a constant that defines the allowed keys" do
6
+ Xively::Datapoint::ALLOWED_KEYS.should == %w(feed_id datastream_id at value)
7
+ end
8
+
9
+ describe "validation" do
10
+ before(:each) do
11
+ @datapoint = Xively::Datapoint.new
12
+ end
13
+
14
+ %w(datastream_id value feed_id).each do |field|
15
+ it "should require a '#{field}'" do
16
+ @datapoint.send("#{field}=".to_sym, nil)
17
+ @datapoint.should_not be_valid
18
+ @datapoint.errors[field.to_sym].should include("can't be blank")
19
+ end
20
+ end
21
+ end
22
+
23
+ describe "#initialize" do
24
+ it "should create a blank slate when passed no arguments" do
25
+ datapoint = Xively::Datapoint.new
26
+ Xively::Datapoint::ALLOWED_KEYS.each do |attr|
27
+ datapoint.attributes[attr.to_sym].should be_nil
28
+ end
29
+ end
30
+
31
+ it "should accept xml" do
32
+ datapoint = Xively::Datapoint.new(datapoint_as_(:xml))
33
+ datapoint.value.should == "2000"
34
+ end
35
+
36
+ it "should accept json" do
37
+ datapoint = Xively::Datapoint.new(datapoint_as_(:json))
38
+ datapoint.value.should == "2000"
39
+ end
40
+
41
+ it "should accept a hash of attributes" do
42
+ datapoint = Xively::Datapoint.new(datapoint_as_(:hash))
43
+ datapoint.value.should == "2000"
44
+ end
45
+
46
+ it "should raise known exception if passed json but told xml" do
47
+ expect {
48
+ Xively::Datapoint.new(datapoint_as_(:json), :xml)
49
+ }.to raise_error(Xively::Parsers::XML::InvalidXMLError)
50
+ end
51
+
52
+ it "should raise known exception if passed xml but told json" do
53
+ expect {
54
+ Xively::Datapoint.new(datapoint_as_(:xml), :json)
55
+ }.to raise_error(Xively::Parsers::JSON::InvalidJSONError)
56
+ end
57
+
58
+ it "should raise known exception if given unknown format" do
59
+ expect {
60
+ Xively::Datapoint.new(datapoint_as_(:json), :msgpack)
61
+ }.to raise_error(Xively::InvalidFormatError)
62
+ end
63
+ end
64
+
65
+ describe "#attributes" do
66
+ it "should return a hash of datapoint properties" do
67
+ attrs = {}
68
+ Xively::Datapoint::ALLOWED_KEYS.each do |key|
69
+ attrs[key] = "key #{rand(1000)}"
70
+ end
71
+ datapoint = Xively::Datapoint.new(attrs)
72
+
73
+ datapoint.attributes.should == attrs
74
+ end
75
+
76
+ it "should not return nil values" do
77
+ attrs = {}
78
+ Xively::Datapoint::ALLOWED_KEYS.each do |key|
79
+ attrs[key] = "key #{rand(1000)}"
80
+ end
81
+ attrs["created_at"] = nil
82
+ datapoint = Xively::Datapoint.new(attrs)
83
+
84
+ datapoint.attributes.should_not include("created_at")
85
+ end
86
+ end
87
+
88
+ describe "#attributes=" do
89
+ it "should accept and save a hash of datapoint properties" do
90
+ datapoint = Xively::Datapoint.new({})
91
+
92
+ attrs = {}
93
+ Xively::Datapoint::ALLOWED_KEYS.each do |key|
94
+ value = "key #{rand(1000)}"
95
+ attrs[key] = value
96
+ datapoint.should_receive("#{key}=").with(value)
97
+ end
98
+ datapoint.attributes=(attrs)
99
+ end
100
+ end
101
+
102
+ # Provided by Xively::Templates::DatapointDefaults
103
+ describe "#generate_json" do
104
+ it "should take a version and generate the appropriate template" do
105
+ now = Time.now
106
+ datapoint = Xively::Datapoint.new({:at => now, :value => 123})
107
+ datapoint.generate_json.should == {:at => now.iso8601(6), :value => 123}
108
+ end
109
+ end
110
+
111
+ describe "#to_csv" do
112
+ it "should call the csv generator with default version (nil as there only is one version)" do
113
+ datapoint = Xively::Datapoint.new({})
114
+ datapoint.should_receive(:generate_csv).with(nil, {}).and_return("3")
115
+ datapoint.to_csv.should == "3"
116
+ end
117
+
118
+ it "should accept optional csv version" do
119
+ datapoint = Xively::Datapoint.new({})
120
+ datapoint.should_receive(:generate_csv).with("1", {}).and_return("34")
121
+ datapoint.to_csv(:version => "1").should == "34"
122
+ end
123
+
124
+ it "should accept additional options" do
125
+ datapoint = Xively::Datapoint.new({})
126
+ datapoint.should_receive(:generate_csv).with("1", {:full => true}).and_return("34")
127
+ datapoint.to_csv(:version => "1", :full => true).should == "34"
128
+ end
129
+ end
130
+
131
+ describe "#to_xml" do
132
+
133
+ it "should call the xml generator with default version (nil as there only is one version)" do
134
+ datapoint = Xively::Datapoint.new({})
135
+ datapoint.should_receive(:generate_xml).with(nil).and_return("<xml></xml>")
136
+ datapoint.to_xml.should == "<xml></xml>"
137
+ end
138
+
139
+ it "should accept optional xml version" do
140
+ datapoint = Xively::Datapoint.new({})
141
+ datapoint.should_receive(:generate_xml).with("5").and_return("<xml></xml>")
142
+ datapoint.to_xml(:version => "5").should == "<xml></xml>"
143
+ end
144
+
145
+ end
146
+
147
+ describe "#as_json" do
148
+
149
+ it "should call the json generator with default version (nil as there only is one version)" do
150
+ datapoint = Xively::Datapoint.new({})
151
+ datapoint.should_receive(:generate_json).with(nil).and_return({"title" => "Environment"})
152
+ datapoint.as_json.should == {"title" => "Environment"}
153
+ end
154
+
155
+ it "should accept optional json version" do
156
+ datapoint = Xively::Datapoint.new({})
157
+ datapoint.should_receive(:generate_json).with("0.6-alpha").and_return({"title" => "Environment"})
158
+ datapoint.as_json(:version => "0.6-alpha").should == {"title" => "Environment"}
159
+ end
160
+
161
+ end
162
+
163
+ describe "#to_json" do
164
+ it "should call #as_json" do
165
+ datapoint_hash = {"id" => "env001", "value" => "2344"}
166
+ datapoint = Xively::Datapoint.new(datapoint_hash)
167
+ datapoint.should_receive(:as_json).with({})
168
+ datapoint.to_json
169
+ end
170
+
171
+ it "should pass options through to #as_json" do
172
+ datapoint_hash = {"id" => "env001", "value" => "2344"}
173
+ datapoint = Xively::Datapoint.new(datapoint_hash)
174
+ datapoint.should_receive(:as_json).with({:crazy => "options"})
175
+ datapoint.to_json({:crazy => "options"})
176
+ end
177
+
178
+ it "should pass the output of #as_json to yajl" do
179
+ datapoint_hash = {"id" => "env001", "value" => "2344"}
180
+ datapoint = Xively::Datapoint.new(datapoint_hash)
181
+ datapoint.should_receive(:as_json).and_return({:awesome => "hash"})
182
+ MultiJson.should_receive(:dump).with({:awesome => "hash"})
183
+ datapoint.to_json
184
+ end
185
+ end
186
+ end
187
+
@@ -0,0 +1,344 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Xively::Datastream do
5
+
6
+ it "should have a constant that defines the allowed keys" do
7
+ Xively::Datastream::ALLOWED_KEYS.should == %w(feed_id id feed_creator current_value datapoints max_value min_value tags unit_label unit_symbol unit_type updated datapoints_function)
8
+ end
9
+
10
+ describe "validation" do
11
+ before(:each) do
12
+ @datastream = Xively::Datastream.new
13
+ end
14
+
15
+ %w(id).each do |field|
16
+ it "should require a '#{field}'" do
17
+ @datastream.send("#{field}=".to_sym, nil)
18
+ @datastream.should_not be_valid
19
+ @datastream.errors[field.to_sym].should include("can't be blank")
20
+ end
21
+ end
22
+
23
+ ["red hat", "foo*", "KYB:FOO"].each do |invalid_id|
24
+ it "should not allow '#{invalid_id}' as an id" do
25
+ @datastream.id = invalid_id
26
+ @datastream.should_not be_valid
27
+ @datastream.errors[:id].should include("is invalid")
28
+ end
29
+ end
30
+
31
+ ["üöäÜÖÄ", "ÜÖÄ", "üöä", "current_to_direction-degrees_true-1", "current_to_direction.degrees_true.1"].each do |valid_id|
32
+ it "should allow '#{valid_id}' as an id" do
33
+ @datastream.feed_id = 1234
34
+ @datastream.id = valid_id
35
+ @datastream.should be_valid
36
+ @datastream.errors[:id].should be_empty
37
+ end
38
+ end
39
+
40
+ ["red hat", "foo*", 12.05].each do |invalid_feed_id|
41
+ it "should not allow '#{invalid_feed_id}' as a feed_id" do
42
+ @datastream.id = "1"
43
+ @datastream.feed_id = invalid_feed_id
44
+ @datastream.should_not be_valid
45
+ @datastream.errors[:feed_id].should include("is invalid")
46
+ end
47
+ end
48
+
49
+ [0, 1234, 102931203, "123"].each do |valid_feed_id|
50
+ it "should allow '#{valid_feed_id}' as a feed_id" do
51
+ @datastream.id = "1"
52
+ @datastream.feed_id = valid_feed_id
53
+ @datastream.should be_valid
54
+ @datastream.errors[:feed_id].should be_empty
55
+ end
56
+ end
57
+
58
+ %w(current_value tags).each do |field|
59
+ it "should restrict '#{field}' field length to 255" do
60
+ @datastream.send("#{field}=".to_sym, "a"*256)
61
+ @datastream.should_not be_valid
62
+ @datastream.errors[field.to_sym].should == ["is too long (maximum is 255 characters)"]
63
+ end
64
+ end
65
+
66
+ it "should not allow arrays of 255 entries for tags" do
67
+ @datastream.tags = []
68
+ 254.times {@datastream.tags << 'a'}
69
+ @datastream.should_not be_valid
70
+ @datastream.errors[:tags].should == ["is too long (maximum is 255 characters)"]
71
+ end
72
+
73
+ %w(unit_type current_value).each do |field|
74
+ it "should allow blank '#{field}'" do
75
+ @datastream.send("#{field}=".to_sym, nil)
76
+ @datastream.valid?
77
+ @datastream.errors[field.to_sym].should be_blank
78
+ end
79
+ end
80
+
81
+ %w(basicSI derivedSI conversionBasedUnits derivedUnits contextDependentUnits).each do |valid_unit_type|
82
+ it "should allow unit_type of '#{valid_unit_type}'" do
83
+ @datastream.unit_type = valid_unit_type
84
+ @datastream.valid?
85
+ @datastream.errors[:unit_type].should be_blank
86
+ end
87
+ end
88
+
89
+ %w(baicSI deriedSI conversinBasedUnits deriedUnits cotextDependentUnits).each do |invalid_unit_type|
90
+ it "should not allow unit_type of '#{invalid_unit_type}'" do
91
+ @datastream.unit_type = invalid_unit_type
92
+ @datastream.valid?
93
+ @datastream.errors[:unit_type].should == ["is not a valid unit_type (pick one from #{Xively::Datastream::VALID_UNIT_TYPES.join(', ')} or leave blank)"]
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ describe "#initialize" do
100
+ it "should create a blank slate when passed no arguments" do
101
+ datastream = Xively::Datastream.new
102
+ Xively::Datastream::ALLOWED_KEYS.each do |attr|
103
+ datastream.attributes[attr.to_sym].should be_nil
104
+ end
105
+ end
106
+
107
+ %w(xml json hash csv).each do |format|
108
+ it "should accept #{format}" do
109
+ datastream = Xively::Datastream.new(datastream_as_(format.to_sym))
110
+ datastream.current_value.should == "14"
111
+ end
112
+
113
+ %w(to_csv as_json to_xml to_json attributes).each do |output_format|
114
+ it "should be able to output from #{format} using #{output_format}" do
115
+ datastream = Xively::Datastream.new(datastream_as_(format.to_sym))
116
+ lambda {datastream.send(output_format.to_sym)}.should_not raise_error
117
+ end
118
+ end
119
+ end
120
+
121
+ it "should raise known exception if passed json but told xml" do
122
+ expect {
123
+ Xively::Datastream.new(datastream_as_(:json), :v2, :xml)
124
+ }.to raise_error(Xively::Parsers::XML::InvalidXMLError)
125
+ end
126
+
127
+ it "should raise known exception if passed csv but told xml" do
128
+ expect {
129
+ Xively::Datastream.new(datastream_as_(:csv), :v2, :xml)
130
+ }.to raise_error(Xively::Parsers::XML::InvalidXMLError)
131
+ end
132
+
133
+ it "should raise known exception if passed xml but told json" do
134
+ expect {
135
+ Xively::Datastream.new(datastream_as_(:xml), :v2, :json)
136
+ }.to raise_error(Xively::Parsers::JSON::InvalidJSONError)
137
+ end
138
+
139
+ it "should raise known exception if passed csv but told json" do
140
+ expect {
141
+ Xively::Datastream.new(datastream_as_(:csv), :v2, :json)
142
+ }.to raise_error(Xively::Parsers::JSON::InvalidJSONError)
143
+ end
144
+
145
+ it "should raise known exception if passed json but told csv" do
146
+ expect {
147
+ Xively::Datastream.new(datastream_as_(:json), :v2, :csv)
148
+ }.to raise_error(Xively::Parsers::CSV::InvalidCSVError)
149
+ end
150
+
151
+ it "should raise known exception if passed xml but told csv" do
152
+ expect {
153
+ Xively::Datastream.new(datastream_as_(:xml), :v2, :csv)
154
+ }.to raise_error(Xively::Parsers::CSV::InvalidCSVError)
155
+ end
156
+
157
+ it "should raise known exception if told some format we don't accept" do
158
+ expect {
159
+ Xively::Datastream.new(datastream_as_(:xml), :v2, :html)
160
+ }.to raise_error(Xively::InvalidFormatError)
161
+ end
162
+
163
+ end
164
+
165
+ describe "#attributes" do
166
+ it "should return a hash of datastream properties" do
167
+ attrs = {}
168
+ Xively::Datastream::ALLOWED_KEYS.each do |key|
169
+ attrs[key] = "key #{rand(1000)}"
170
+ end
171
+ attrs["datapoints"] = [Xively::Datapoint.new({"value" => "ein"})]
172
+ datastream = Xively::Datastream.new(attrs)
173
+
174
+ datastream.attributes.should == attrs
175
+ end
176
+
177
+ it "should not return nil values" do
178
+ attrs = {}
179
+ Xively::Datastream::ALLOWED_KEYS.each do |key|
180
+ attrs[key] = "key #{rand(1000)}"
181
+ end
182
+ attrs["created_at"] = nil
183
+ datastream = Xively::Datastream.new(attrs)
184
+
185
+ datastream.attributes.should_not include("created_at")
186
+ end
187
+ end
188
+
189
+ describe "#attributes=" do
190
+ it "should accept and save a hash of datastream properties" do
191
+ datastream = Xively::Datastream.new({})
192
+
193
+ attrs = {}
194
+ Xively::Datastream::ALLOWED_KEYS.each do |key|
195
+ value = "key #{rand(1000)}"
196
+ attrs[key] = value
197
+ datastream.should_receive("#{key}=").with(value)
198
+ end
199
+ datastream.attributes=(attrs)
200
+ end
201
+ end
202
+
203
+ context "associated datapoints" do
204
+
205
+ describe "#datapoints" do
206
+ it "should return an array of datapoints" do
207
+ datapoints = [Xively::Datapoint.new(datapoint_as_(:hash))]
208
+ attrs = {"datapoints" => datapoints}
209
+ datastream = Xively::Datastream.new(attrs)
210
+ datastream.datapoints.each do |ds|
211
+ ds.should be_kind_of(Xively::Datapoint)
212
+ end
213
+ end
214
+
215
+ it "should never be nil" do
216
+ Xively::Datastream.new({}).datapoints.should == []
217
+ end
218
+ end
219
+
220
+ describe "#datapoints=" do
221
+ before(:each) do
222
+ @datastream = Xively::Datastream.new({})
223
+ end
224
+
225
+ it "should be empty if not assigned an array" do
226
+ @datastream.datapoints = "kittens"
227
+ @datastream.datapoints.should be_empty
228
+ end
229
+
230
+ it "should accept an array of datapoints and hashes and store an array of datapoints" do
231
+ new_datapoint1 = Xively::Datapoint.new(datapoint_as_(:hash))
232
+ new_datapoint2 = Xively::Datapoint.new(datapoint_as_(:hash))
233
+ Xively::Datapoint.should_receive(:new).with(datapoint_as_(:hash)).and_return(new_datapoint2)
234
+
235
+ datapoints = [new_datapoint1, datapoint_as_(:hash)]
236
+ @datastream.datapoints = datapoints
237
+ @datastream.datapoints.length.should == 2
238
+ @datastream.datapoints.should include(new_datapoint1)
239
+ @datastream.datapoints.should include(new_datapoint2)
240
+ end
241
+
242
+ it "should accept an array of datapoints and store an array of datapoints" do
243
+ datapoints = [Xively::Datapoint.new(datapoint_as_(:hash))]
244
+ @datastream.datapoints = datapoints
245
+ @datastream.datapoints.should == datapoints
246
+ end
247
+
248
+ it "should accept an array of hashes and store an array of datapoints" do
249
+ new_datapoint = Xively::Datapoint.new(datapoint_as_(:hash))
250
+ Xively::Datapoint.should_receive(:new).with(datapoint_as_(:hash)).and_return(new_datapoint)
251
+
252
+ datapoints_hash = [datapoint_as_(:hash)]
253
+ @datastream.datapoints = datapoints_hash
254
+ @datastream.datapoints.should == [new_datapoint]
255
+ end
256
+ end
257
+ end
258
+
259
+ # Provided by Xively::Templates::DatastreamDefaults
260
+ describe "#generate_json" do
261
+ it "should take a version and generate the appropriate template" do
262
+ datastream = Xively::Datastream.new({})
263
+ datastream.generate_json("1.0.0").should == {:version => "1.0.0"}
264
+ end
265
+ end
266
+
267
+ describe "#to_csv" do
268
+
269
+ it "should call the csv generator with default version" do
270
+ datastream = Xively::Datastream.new({})
271
+ datastream.should_receive(:generate_csv).with("2", {}).and_return("2")
272
+ datastream.to_csv.should == "2"
273
+ end
274
+
275
+ it "should accept optional xml version" do
276
+ datastream = Xively::Datastream.new({})
277
+ datastream.should_receive(:generate_csv).with("1", {}).and_return("1234,32")
278
+ datastream.to_csv(:version => "1").should == "1234,32"
279
+ end
280
+
281
+ it "should accept additional options" do
282
+ datastream = Xively::Datastream.new({})
283
+ datastream.should_receive(:generate_csv).with("1", {:full => true}).and_return("34")
284
+ datastream.to_csv(:version => "1", :full => true).should == "34"
285
+ end
286
+ end
287
+
288
+ describe "#to_xml" do
289
+
290
+ it "should call the xml generator with default version" do
291
+ datastream = Xively::Datastream.new({})
292
+ datastream.should_receive(:generate_xml).with("0.5.1", {}).and_return("<xml></xml>")
293
+ datastream.to_xml.should == "<xml></xml>"
294
+ end
295
+
296
+ it "should accept optional xml version" do
297
+ datastream = Xively::Datastream.new({})
298
+ datastream.should_receive(:generate_xml).with("5", {}).and_return("<xml></xml>")
299
+ datastream.to_xml(:version => "5").should == "<xml></xml>"
300
+ end
301
+
302
+ end
303
+
304
+ describe "#as_json" do
305
+
306
+ it "should call the json generator with default version" do
307
+ datastream = Xively::Datastream.new({})
308
+ datastream.should_receive(:generate_json).with("1.0.0", {}).and_return({"title" => "Environment"})
309
+ datastream.as_json.should == {"title" => "Environment"}
310
+ end
311
+
312
+ it "should accept optional json version" do
313
+ datastream = Xively::Datastream.new({})
314
+ datastream.should_receive(:generate_json).with("0.6-alpha", {}).and_return({"title" => "Environment"})
315
+ datastream.as_json(:version => "0.6-alpha").should == {"title" => "Environment"}
316
+ end
317
+
318
+ end
319
+
320
+ describe "#to_json" do
321
+ it "should call #as_json" do
322
+ datastream_hash = {"id" => "env001", "value" => "2344"}
323
+ datastream = Xively::Datastream.new(datastream_hash)
324
+ datastream.should_receive(:as_json).with({})
325
+ datastream.to_json
326
+ end
327
+
328
+ it "should pass options through to #as_json" do
329
+ datastream_hash = {"id" => "env001", "value" => "2344"}
330
+ datastream = Xively::Datastream.new(datastream_hash)
331
+ datastream.should_receive(:as_json).with({:crazy => "options"})
332
+ datastream.to_json({:crazy => "options"})
333
+ end
334
+
335
+ it "should pass the output of #as_json to yajl" do
336
+ datastream_hash = {"id" => "env001", "value" => "2344"}
337
+ datastream = Xively::Datastream.new(datastream_hash)
338
+ datastream.should_receive(:as_json).and_return({:awesome => "hash"})
339
+ MultiJson.should_receive(:dump).with({:awesome => "hash"})
340
+ datastream.to_json
341
+ end
342
+ end
343
+ end
344
+