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.
- data/.gitignore +13 -0
- data/.rbenv-version +1 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +91 -0
- data/CONTRIBUTING.md +95 -0
- data/Gemfile +15 -0
- data/LICENSE.md +13 -0
- data/README.md +10 -0
- data/Rakefile +25 -0
- data/ci/build_hudson.sh +24 -0
- data/init.rb +2 -0
- data/lib/xively-rb.rb +44 -0
- data/lib/xively-rb/array_extensions.rb +6 -0
- data/lib/xively-rb/base.rb +52 -0
- data/lib/xively-rb/base/instance_methods.rb +28 -0
- data/lib/xively-rb/client.rb +43 -0
- data/lib/xively-rb/datapoint.rb +72 -0
- data/lib/xively-rb/datastream.rb +127 -0
- data/lib/xively-rb/exceptions.rb +5 -0
- data/lib/xively-rb/feed.rb +109 -0
- data/lib/xively-rb/hash_extensions.rb +16 -0
- data/lib/xively-rb/helpers.rb +41 -0
- data/lib/xively-rb/key.rb +99 -0
- data/lib/xively-rb/nil_content.rb +15 -0
- data/lib/xively-rb/object_extensions.rb +6 -0
- data/lib/xively-rb/parsers/csv/datastream_defaults.rb +50 -0
- data/lib/xively-rb/parsers/csv/feed_defaults.rb +97 -0
- data/lib/xively-rb/parsers/defaults.rb +15 -0
- data/lib/xively-rb/parsers/json/datapoint_defaults.rb +16 -0
- data/lib/xively-rb/parsers/json/datastream_defaults.rb +58 -0
- data/lib/xively-rb/parsers/json/feed_defaults.rb +114 -0
- data/lib/xively-rb/parsers/json/key_defaults.rb +20 -0
- data/lib/xively-rb/parsers/json/search_result_defaults.rb +24 -0
- data/lib/xively-rb/parsers/json/trigger_defaults.rb +16 -0
- data/lib/xively-rb/parsers/xml/datapoint_defaults.rb +27 -0
- data/lib/xively-rb/parsers/xml/datastream_defaults.rb +53 -0
- data/lib/xively-rb/parsers/xml/errors.rb +7 -0
- data/lib/xively-rb/parsers/xml/feed_defaults.rb +83 -0
- data/lib/xively-rb/parsers/xml/helpers.rb +116 -0
- data/lib/xively-rb/parsers/xml/key_defaults.rb +46 -0
- data/lib/xively-rb/parsers/xml/trigger_defaults.rb +28 -0
- data/lib/xively-rb/permission.rb +67 -0
- data/lib/xively-rb/resource.rb +43 -0
- data/lib/xively-rb/search_result.rb +68 -0
- data/lib/xively-rb/string_extensions.rb +6 -0
- data/lib/xively-rb/templates/csv/datapoint_defaults.rb +22 -0
- data/lib/xively-rb/templates/csv/datastream_defaults.rb +43 -0
- data/lib/xively-rb/templates/csv/feed_defaults.rb +47 -0
- data/lib/xively-rb/templates/defaults.rb +14 -0
- data/lib/xively-rb/templates/json/datapoint_defaults.rb +15 -0
- data/lib/xively-rb/templates/json/datastream_defaults.rb +61 -0
- data/lib/xively-rb/templates/json/feed_defaults.rb +90 -0
- data/lib/xively-rb/templates/json/key_defaults.rb +39 -0
- data/lib/xively-rb/templates/json/search_result_defaults.rb +42 -0
- data/lib/xively-rb/templates/json/trigger_defaults.rb +21 -0
- data/lib/xively-rb/templates/xml/datapoint_defaults.rb +25 -0
- data/lib/xively-rb/templates/xml/datastream_defaults.rb +66 -0
- data/lib/xively-rb/templates/xml/feed_defaults.rb +112 -0
- data/lib/xively-rb/templates/xml/search_result_defaults.rb +118 -0
- data/lib/xively-rb/templates/xml_headers.rb +17 -0
- data/lib/xively-rb/trigger.rb +66 -0
- data/lib/xively-rb/validations.rb +9 -0
- data/lib/xively-rb/version.rb +3 -0
- data/spec/fixtures/models.rb +81 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/contain_datapoint_eeml_matcher.rb +16 -0
- data/spec/support/contain_datastream_eeml_matcher.rb +60 -0
- data/spec/support/contain_feed_eeml_matcher.rb +98 -0
- data/spec/support/datapoint_helper.rb +53 -0
- data/spec/support/datastream_helper.rb +324 -0
- data/spec/support/describe_eeml_matcher.rb +23 -0
- data/spec/support/feed_helper.rb +783 -0
- data/spec/support/fully_represent_datapoint_matcher.rb +30 -0
- data/spec/support/fully_represent_datastream_matcher.rb +96 -0
- data/spec/support/fully_represent_feed_matcher.rb +234 -0
- data/spec/support/fully_represent_key_matcher.rb +74 -0
- data/spec/support/fully_represent_search_result_matcher.rb +67 -0
- data/spec/support/fully_represent_trigger_matcher.rb +29 -0
- data/spec/support/key_helper.rb +74 -0
- data/spec/support/search_result_helper.rb +252 -0
- data/spec/support/trigger_helper.rb +51 -0
- data/spec/xively-rb/array_extensions_spec.rb +9 -0
- data/spec/xively-rb/base/instance_methods_spec.rb +109 -0
- data/spec/xively-rb/base_spec.rb +56 -0
- data/spec/xively-rb/client_spec.rb +51 -0
- data/spec/xively-rb/datapoint_spec.rb +187 -0
- data/spec/xively-rb/datastream_spec.rb +344 -0
- data/spec/xively-rb/feed_spec.rb +341 -0
- data/spec/xively-rb/hash_extensions_spec.rb +20 -0
- data/spec/xively-rb/helpers_spec.rb +56 -0
- data/spec/xively-rb/key_spec.rb +198 -0
- data/spec/xively-rb/parsers/csv/datastream_defaults_spec.rb +110 -0
- data/spec/xively-rb/parsers/csv/feed_defaults_spec.rb +234 -0
- data/spec/xively-rb/parsers/json/datapoint_defaults_spec.rb +21 -0
- data/spec/xively-rb/parsers/json/datastream_defaults_spec.rb +105 -0
- data/spec/xively-rb/parsers/json/feed_defaults_spec.rb +45 -0
- data/spec/xively-rb/parsers/json/key_defaults_spec.rb +14 -0
- data/spec/xively-rb/parsers/json/search_result_defaults_spec.rb +18 -0
- data/spec/xively-rb/parsers/json/trigger_defaults_spec.rb +22 -0
- data/spec/xively-rb/parsers/xml/datapoint_defaults_spec.rb +19 -0
- data/spec/xively-rb/parsers/xml/datastream_defaults_spec.rb +148 -0
- data/spec/xively-rb/parsers/xml/feed_defaults_spec.rb +254 -0
- data/spec/xively-rb/parsers/xml/key_defaults_spec.rb +22 -0
- data/spec/xively-rb/parsers/xml/trigger_defaults_spec.rb +22 -0
- data/spec/xively-rb/search_result_spec.rb +257 -0
- data/spec/xively-rb/string_extensions_spec.rb +12 -0
- data/spec/xively-rb/templates/csv/datapoint_defaults_spec.rb +41 -0
- data/spec/xively-rb/templates/csv/datastream_defaults_spec.rb +131 -0
- data/spec/xively-rb/templates/csv/feed_defaults_spec.rb +78 -0
- data/spec/xively-rb/templates/json/datapoint_defaults_spec.rb +14 -0
- data/spec/xively-rb/templates/json/datastream_defaults_spec.rb +170 -0
- data/spec/xively-rb/templates/json/feed_defaults_spec.rb +399 -0
- data/spec/xively-rb/templates/json/key_defaults_spec.rb +29 -0
- data/spec/xively-rb/templates/json/search_result_defaults_spec.rb +37 -0
- data/spec/xively-rb/templates/json/trigger_defaults_spec.rb +19 -0
- data/spec/xively-rb/templates/xml/datapoint_defaults_spec.rb +14 -0
- data/spec/xively-rb/templates/xml/datastream_defaults_spec.rb +113 -0
- data/spec/xively-rb/templates/xml/feed_defaults_spec.rb +131 -0
- data/spec/xively-rb/templates/xml/search_result_defaults_spec.rb +44 -0
- data/spec/xively-rb/trigger_spec.rb +157 -0
- data/xively-rb.gemspec +41 -0
- 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
|
+
|