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,341 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xively::Feed do
4
+
5
+ it "should have a constant that defines the allowed keys" do
6
+ Xively::Feed::ALLOWED_KEYS.should == %w(id creator owner_login datastreams description email feed icon location_disposition location_domain location_ele location_exposure location_lat location_lon location_name location_waypoints private status tags title updated created website auto_feed_url product_id device_serial csv_version)
7
+ end
8
+
9
+ context "attr accessors" do
10
+ before(:each) do
11
+ @feed = Xively::Feed.new(feed_as_(:json))
12
+ end
13
+
14
+ describe "setting whitelisted fields" do
15
+ Xively::Feed::ALLOWED_KEYS.each do |key|
16
+ it "##{key}=" do
17
+ lambda {
18
+ @feed.send("#{key}=", key)
19
+ }.should_not raise_error
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "getting whitelisted fields" do
25
+ Xively::Feed::ALLOWED_KEYS.each do |key|
26
+ it "##{key}" do
27
+ lambda {
28
+ @feed.send(key)
29
+ }.should_not raise_error
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "setting non-whitelisted keys" do
35
+ it "should not be possible to set non-whitelisted fields" do
36
+ lambda {
37
+ @feed.something_bogus = 'whatevs'
38
+ }.should raise_error
39
+ end
40
+
41
+ it "should not be possible to get non-whitelisted fields" do
42
+ lambda {
43
+ @feed.something_bogus
44
+ }.should raise_error
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "validation" do
50
+ %w(title).each do |field|
51
+ it "should require a '#{field}'" do
52
+ feed = Xively::Feed.new
53
+ feed.send("#{field}=".to_sym, nil)
54
+ feed.should_not be_valid
55
+ feed.errors[field.to_sym].should == ["can't be blank"]
56
+ end
57
+ end
58
+
59
+ it "should not allow duplicate datastreams" do
60
+ feed = Xively::Feed.new
61
+ feed.datastreams = [Xively::Datastream.new('id' => '1'), Xively::Datastream.new('id' => '1')]
62
+ feed.should_not be_valid
63
+ feed.errors[:datastreams].should == ["can't have duplicate IDs: 1"]
64
+ end
65
+
66
+ it "should validate all datastreams" do
67
+ feed = Xively::Feed.new
68
+ feed.datastreams = [Xively::Datastream.new('id' => '')]
69
+ feed.should_not be_valid
70
+ feed.errors[:datastreams_id].should == ["can't be blank"]
71
+ end
72
+ end
73
+
74
+ describe "#initialize" do
75
+ it "should create a blank slate when passed no arguments" do
76
+ feed = Xively::Feed.new
77
+ Xively::Feed::ALLOWED_KEYS.each do |attr|
78
+ feed.attributes[attr.to_sym].should be_nil
79
+ end
80
+ end
81
+
82
+ %w(xml json hash).each do |format|
83
+ it "should accept #{format}" do
84
+ feed = Xively::Feed.new(feed_as_(format.to_sym))
85
+ feed.title.downcase.should == "xively office environment"
86
+ end
87
+
88
+ %w(to_csv as_json to_xml to_json attributes).each do |output_format|
89
+ it "should be able to output from #{format} using #{output_format}" do
90
+ feed = Xively::Feed.new(feed_as_(format.to_sym))
91
+ lambda {feed.send(output_format.to_sym)}.should_not raise_error
92
+ end
93
+ end
94
+ end
95
+
96
+ context "specifying format" do
97
+ it "should raise known exception if told xml but given csv" do
98
+ expect {
99
+ Xively::Feed.new(feed_as_(:csv), :v2, :xml)
100
+ }.to raise_error(Xively::Parsers::XML::InvalidXMLError)
101
+ end
102
+
103
+ it "should raise known exception if told xml but given json" do
104
+ expect {
105
+ Xively::Feed.new(feed_as_(:json), nil, :xml)
106
+ }.to raise_error(Xively::Parsers::XML::InvalidXMLError)
107
+ end
108
+
109
+ it "should raise known exception if told json but given xml" do
110
+ expect {
111
+ Xively::Feed.new(feed_as_(:xml), nil, :json)
112
+ }.to raise_error(Xively::Parsers::JSON::InvalidJSONError)
113
+ end
114
+
115
+ it "should raise known exception if told json but given csv" do
116
+ expect {
117
+ Xively::Feed.new(feed_as_(:csv), nil, :json)
118
+ }.to raise_error(Xively::Parsers::JSON::InvalidJSONError)
119
+ end
120
+
121
+ it "should raise known exception if told csv but given xml" do
122
+ expect {
123
+ Xively::Feed.new(feed_as_(:xml), :v2, :csv)
124
+ }.to raise_error(Xively::Parsers::CSV::InvalidCSVError)
125
+ end
126
+
127
+ it "should raise known exception if told csv but given json" do
128
+ expect {
129
+ Xively::Feed.new(feed_as_(:json), :v2, :csv)
130
+ }.to raise_error(Xively::Parsers::CSV::InvalidCSVError)
131
+ end
132
+
133
+ it "should raise known exception if told format is something unknown" do
134
+ expect {
135
+ Xively::Feed.new(feed_as_(:json), :v2, :msgpack)
136
+ }.to raise_error(Xively::InvalidFormatError)
137
+ end
138
+ end
139
+ end
140
+
141
+ describe "#attributes" do
142
+ it "should return a hash of feed properties" do
143
+ attrs = {}
144
+ Xively::Feed::ALLOWED_KEYS.each do |key|
145
+ attrs[key] = "key #{rand(1000)}"
146
+ end
147
+ attrs["datastreams"] = [Xively::Datastream.new({"id" => "ein"})]
148
+ feed = Xively::Feed.new(attrs)
149
+
150
+ feed.attributes.should == attrs
151
+ end
152
+
153
+ it "should contain csv_version in the allowed keys" do
154
+ Xively::Feed::ALLOWED_KEYS.should include("csv_version")
155
+ end
156
+
157
+ it "should not return nil values" do
158
+ attrs = {}
159
+ Xively::Feed::ALLOWED_KEYS.each do |key|
160
+ attrs[key] = "key #{rand(1000)}"
161
+ end
162
+ attrs["created_at"] = nil
163
+ feed = Xively::Feed.new(attrs)
164
+
165
+ feed.attributes.should_not include("created_at")
166
+ end
167
+ end
168
+
169
+ describe "#attributes=" do
170
+ it "should accept and save a hash of feed properties" do
171
+ feed = Xively::Feed.new({})
172
+
173
+ attrs = {}
174
+ Xively::Feed::ALLOWED_KEYS.each do |key|
175
+ value = "key #{rand(1000)}"
176
+ attrs[key] = value
177
+ feed.should_receive("#{key}=").with(value)
178
+ end
179
+ feed.attributes=(attrs)
180
+ end
181
+ end
182
+
183
+ context "associated datastreams" do
184
+
185
+ describe "#datastreams" do
186
+ it "should return an array of datastreams" do
187
+ datastreams = [Xively::Datastream.new(datastream_as_(:hash))]
188
+ attrs = {"datastreams" => datastreams}
189
+ feed = Xively::Feed.new(attrs)
190
+ feed.datastreams.each do |ds|
191
+ ds.should be_kind_of(Xively::Datastream)
192
+ end
193
+ end
194
+
195
+ it "should default to an empty array" do
196
+ feed = Xively::Feed.new({})
197
+ feed.datastreams.should == []
198
+ end
199
+ end
200
+
201
+ describe "#datastreams=" do
202
+ before(:each) do
203
+ @feed = Xively::Feed.new({})
204
+ end
205
+
206
+ it "should return an empty array if not an array" do
207
+ @feed.datastreams = "kittens"
208
+ @feed.datastreams.should be_empty
209
+ end
210
+
211
+ it "should accept an array of datastreams and hashes and store an array of datastreams" do
212
+ new_datastream1 = Xively::Datastream.new(datastream_as_(:hash))
213
+ new_datastream2 = Xively::Datastream.new(datastream_as_(:hash))
214
+ Xively::Datastream.should_receive(:new).with(datastream_as_(:hash)).and_return(new_datastream2)
215
+
216
+ datastreams = [new_datastream1, datastream_as_(:hash)]
217
+ @feed.datastreams = datastreams
218
+ @feed.datastreams.length.should == 2
219
+ @feed.datastreams.should include(new_datastream1)
220
+ @feed.datastreams.should include(new_datastream2)
221
+ end
222
+
223
+ it "should accept an array of datastreams and store an array of datastreams" do
224
+ datastreams = [Xively::Datastream.new(datastream_as_(:hash))]
225
+ @feed.datastreams = datastreams
226
+ @feed.datastreams.should == datastreams
227
+ end
228
+
229
+ it "should accept an array of hashes and store an array of datastreams" do
230
+ new_datastream = Xively::Datastream.new(datastream_as_(:hash))
231
+ Xively::Datastream.should_receive(:new).with(datastream_as_(:hash)).and_return(new_datastream)
232
+
233
+ datastreams_hash = [datastream_as_(:hash)]
234
+ @feed.datastreams = datastreams_hash
235
+ @feed.datastreams.should == [new_datastream]
236
+ end
237
+
238
+ it "should accept an array of subclass of datastream and store an array of datastreams" do
239
+ class OurSpecialDatastreamClass < Xively::Datastream
240
+ attr_accessor :something_new
241
+ end
242
+
243
+ datastreams = [OurSpecialDatastreamClass.new(datastream_as_(:hash))]
244
+ @feed.datastreams = datastreams
245
+ @feed.datastreams.should == datastreams
246
+ end
247
+ end
248
+
249
+ end
250
+
251
+ # Provided by Xively::Templates::FeedDefaults
252
+ describe "#generate_json" do
253
+ it "should take a version and generate the appropriate template" do
254
+ feed = Xively::Feed.new({})
255
+ feed.generate_json("1.0.0").should == {:version => "1.0.0"}
256
+ end
257
+ end
258
+
259
+ describe "#to_csv" do
260
+ it "should call the csv generator with default version" do
261
+ feed = Xively::Feed.new({})
262
+ feed.should_receive(:generate_csv).with("2", {}).and_return("1,2,3,4")
263
+ feed.to_csv.should == "1,2,3,4"
264
+ end
265
+
266
+ it "should accept optional csv version" do
267
+ version = "1"
268
+ feed = Xively::Feed.new({})
269
+ feed.should_receive(:generate_csv).with(version, {}).and_return("1,2,3,4")
270
+ feed.to_csv(:version => version).should == "1,2,3,4"
271
+ end
272
+
273
+ it "should accept additional options" do
274
+ version = "1"
275
+ feed = Xively::Feed.new({})
276
+ feed.should_receive(:generate_csv).with(version, :full => true).and_return("1,2,3,4")
277
+ feed.to_csv(:version => version, :full => true).should == "1,2,3,4"
278
+ end
279
+ end
280
+
281
+ describe "#to_xml" do
282
+ it "should call the xml generator with default version" do
283
+ feed = Xively::Feed.new({})
284
+ feed.should_receive(:generate_xml).with("0.5.1", {}).and_return("<xml></xml>")
285
+ feed.to_xml.should == "<xml></xml>"
286
+ end
287
+
288
+ it "should accept optional xml version" do
289
+ version = "5"
290
+ feed = Xively::Feed.new({})
291
+ feed.should_receive(:generate_xml).with(version, {}).and_return("<xml></xml>")
292
+ feed.to_xml(:version => version).should == "<xml></xml>"
293
+ end
294
+ end
295
+
296
+ describe "#as_json" do
297
+ it "should call the json generator with default version" do
298
+ feed = Xively::Feed.new({})
299
+ feed.should_receive(:generate_json).with("1.0.0", {}).and_return({"title" => "Environment"})
300
+ feed.as_json.should == {"title" => "Environment"}
301
+ end
302
+
303
+ it "should accept optional json version" do
304
+ version = "0.6-alpha"
305
+ feed = Xively::Feed.new({})
306
+ feed.should_receive(:generate_json).with(version, {}).and_return({"title" => "Environment"})
307
+ feed.as_json(:version => version).should == {"title" => "Environment"}
308
+ end
309
+ end
310
+
311
+ describe "#to_json" do
312
+ it "should call #as_json" do
313
+ feed_hash = {"title" => "Environment"}
314
+ feed = Xively::Feed.new(feed_hash)
315
+ feed.should_receive(:as_json).with({})
316
+ feed.to_json
317
+ end
318
+
319
+ it "should pass options through to #as_json" do
320
+ feed_hash = {"title" => "Environment"}
321
+ feed = Xively::Feed.new(feed_hash)
322
+ feed.should_receive(:as_json).with({:crazy => "options"})
323
+ feed.to_json({:crazy => "options"})
324
+ end
325
+
326
+ it "should generate datastreams" do
327
+ feed = Xively::Feed.new(feed_as_('hash'))
328
+ feed.datastreams = datastream_as_(:hash)
329
+ MultiJson.load(feed.to_json)["datastreams"].should_not be_nil
330
+ end
331
+
332
+ it "should pass the output of #as_json to yajl" do
333
+ feed_hash = {"title" => "Environment"}
334
+ feed = Xively::Feed.new(feed_hash)
335
+ feed.should_receive(:as_json).and_return({:awesome => "hash"})
336
+ MultiJson.should_receive(:dump).with({:awesome => "hash"})
337
+ feed.to_json
338
+ end
339
+ end
340
+ end
341
+
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Hash extensions" do
4
+ it "should add a delete_if_nil_value method to hashes" do
5
+ hash = { "foo" => "awesome", "bar" => nil, :symbol => "" }
6
+ hash.delete_if_nil_value.should == { "foo" => "awesome" }
7
+ end
8
+
9
+ # HACK probably
10
+ it "should add a deep_stringify_keys method to hash instances" do
11
+ hash = { :sym => "val", :nested => { "str" => 12, :symtoo => 58 } }
12
+ hash.deep_stringify_keys.should == { "sym" => "val", "nested" => { "str" => 12, "symtoo" => 58 } }
13
+ end
14
+
15
+ it "should have a destructive in place version of the deep_stringify_keys method" do
16
+ hash = { :sym => "val", :nested => { "str" => 12, :symtoo => 58 } }
17
+ hash.deep_stringify_keys!
18
+ hash.should == { "sym" => "val", "nested" => { "str" => 12, "symtoo" => 58 } }
19
+ end
20
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Template helpers" do
4
+ include Xively::Helpers
5
+
6
+ describe "#join_tags" do
7
+
8
+ it "should just return the string if it already is one" do
9
+ join_tags('help, me').should == 'help, me'
10
+ end
11
+
12
+ it "should convert an array into a string" do
13
+ join_tags(['bag', 'jag', 'lag', 'tag']).should == 'bag,jag,lag,tag'
14
+ end
15
+
16
+ it "should sort the array" do
17
+ join_tags(['zag', 'xag', 'Bag', 'aag']).should == 'aag,Bag,xag,zag'
18
+ end
19
+ end
20
+
21
+ describe "#parse_tag_string" do
22
+ it "should handle single tags" do
23
+ parse_tag_string('tag').should == ['tag']
24
+ end
25
+
26
+ it "should handle multiple tags" do
27
+ parse_tag_string('tag, bag ,lag,jag').should == ['bag', 'jag', 'lag', 'tag']
28
+ end
29
+
30
+ it "should handle complex tags" do
31
+ string = 'apple, orange, "red room", " I like space ", "tennis, later"'
32
+ parse_tag_string(string).should ==
33
+ [
34
+ " I like space ",
35
+ "apple",
36
+ "orange",
37
+ "red room",
38
+ "tennis, later"
39
+ ]
40
+ end
41
+
42
+ it "should handle tags with escaped double quote" do
43
+ string = 'apple, orange, "horse:height=2\"", " I like space ", "tennis, later", "\"quote\""'
44
+ parse_tag_string(string).should ==
45
+ [
46
+ " I like space ",
47
+ "\"quote\"",
48
+ "apple",
49
+ "horse:height=2\"",
50
+ "orange",
51
+ "tennis, later"
52
+ ]
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,198 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xively::Key do
4
+ it "should have a constant that defines the allowed keys" do
5
+ Xively::Key::ALLOWED_KEYS.sort.should == %w(expires_at id key label user permissions private_access).sort
6
+ end
7
+
8
+ describe "validation" do
9
+ before(:each) do
10
+ @key = Xively::Key.new
11
+ end
12
+
13
+ %w(label permissions user).each do |field|
14
+ it "should require a '#{field}'" do
15
+ @key.send("#{field}=".to_sym, nil)
16
+ @key.should_not be_valid
17
+ @key.errors[field.to_sym].should include("can't be blank")
18
+ end
19
+ end
20
+
21
+ it "should not be valid if resource present with no feed_id" do
22
+ @key.attributes = { :user => "bob", :permissions => [ { :access_methods => ["get"], :resources => [{}] } ] }
23
+ @key.should_not be_valid
24
+ end
25
+
26
+ it "should not be valid if we have a datastream_id with no feed_id in a resource" do
27
+ @key.attributes = { :user => "bob", :permissions => [ { :access_methods => ["get"], :resources => [{:datastream_id => "0"}] } ] }
28
+ @key.should_not be_valid
29
+ end
30
+
31
+ it "should always return a boolean from the permission private_access? attribute, even if nil" do
32
+ @key.private_access.should be_nil
33
+ @key.private_access?.should be_false
34
+ @key.private_access = true
35
+ @key.private_access?.should be_true
36
+ end
37
+
38
+ it "should not be valid if a permission object with no methods is added" do
39
+ @key.attributes = { :user => "bob", :permissions => [ { :label => "label" } ] }
40
+ @key.should_not be_valid
41
+ @key.errors[:permissions_access_methods].should include("can't be blank")
42
+ end
43
+
44
+ it "should return the key as the id if no id attribute is specified" do
45
+ hash = key_as_(:hash)
46
+ hash.delete("id")
47
+ @key.attributes = hash
48
+ @key.id.should == "abcdefghasdfaoisdj109usasdf0a9sf"
49
+ end
50
+ end
51
+
52
+ describe "#initialize" do
53
+ it "should create a blank slate when passed no arguments" do
54
+ key = Xively::Key.new
55
+ Xively::Key::ALLOWED_KEYS.each do |attr|
56
+ key.attributes[attr.to_sym].should be_nil
57
+ end
58
+ end
59
+
60
+ it "should accept xml" do
61
+ key = Xively::Key.new(key_as_(:xml))
62
+ key.permissions.first.access_methods.should == ["get", "put", "post", "delete"]
63
+ end
64
+
65
+ it "should accept json" do
66
+ key = Xively::Key.new(key_as_(:json))
67
+ key.permissions.first.access_methods.should == ["get", "put", "post", "delete"]
68
+ end
69
+
70
+ it "should accept a hash of attributes" do
71
+ key = Xively::Key.new(key_as_(:hash))
72
+ key.permissions.first.access_methods.should == ["get", "put", "post", "delete"]
73
+ end
74
+
75
+ context "specifying format" do
76
+ it "should raise known exception if told xml but given json" do
77
+ expect {
78
+ Xively::Key.new(key_as_(:json), :xml)
79
+ }.to raise_error(Xively::Parsers::XML::InvalidXMLError)
80
+ end
81
+
82
+ it "should raise known exception if told json but given xml" do
83
+ expect {
84
+ Xively::Key.new(key_as_(:xml), :json)
85
+ }.to raise_error(Xively::Parsers::JSON::InvalidJSONError)
86
+ end
87
+
88
+ it "should raise known exception if given unknown format" do
89
+ expect {
90
+ Xively::Key.new(key_as_(:xml), :gif)
91
+ }.to raise_error(Xively::InvalidFormatError)
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "#attributes" do
97
+ it "should return a hash of key properties" do
98
+ attrs = {}
99
+ Xively::Key::ALLOWED_KEYS.each do |key|
100
+ attrs[key] = "key #{rand(1000)}"
101
+ end
102
+ attrs["permissions"] = [Xively::Permission.new(:permissions => [:get])]
103
+ key = Xively::Key.new(attrs)
104
+
105
+ key.attributes.should == attrs
106
+ end
107
+
108
+ it "should not return nil values" do
109
+ attrs = {}
110
+ Xively::Key::ALLOWED_KEYS.each do |key|
111
+ attrs[key] = "key #{rand(1000)}"
112
+ end
113
+ attrs["notified_at"] = nil
114
+ key = Xively::Key.new(attrs)
115
+
116
+ key.attributes.should_not include("notified_at")
117
+ end
118
+ end
119
+
120
+ describe "#attributes=" do
121
+ it "should accept and save a hash of properties" do
122
+ key = Xively::Key.new({})
123
+
124
+ attrs = {}
125
+ Xively::Key::ALLOWED_KEYS.each do |attr|
126
+ value = "key #{rand(1000)}"
127
+ attrs[attr] = value
128
+ key.should_receive("#{attr}=").with(value)
129
+ end
130
+ key.attributes=(attrs)
131
+ end
132
+
133
+ it "should accept deep nested attributes for permissions array" do
134
+ key = Xively::Key.new({})
135
+ key.attributes = { :permissions_attributes => [{:label => "label", :access_methods => [:get, :put], :resources_attributes => [{:feed_id => 123, :datastream_id => "0"}]}] }
136
+ key.permissions.size.should == 1
137
+ key.permissions.first.label.should == "label"
138
+ key.permissions.first.resources.size.should == 1
139
+ key.permissions.first.resources.first.feed_id.should == 123
140
+ end
141
+
142
+ it "should set deep nested attributes using class instances as well (not just hashes of attributes)" do
143
+ resource = Xively::Resource.new(:feed_id => 123)
144
+ permission = Xively::Permission.new(:label => "label", :access_methods => [:get], :resources => [resource])
145
+ key = Xively::Key.new(:permissions => [permission])
146
+ key.permissions.size.should == 1
147
+ key.permissions.first.resources.size.should == 1
148
+ end
149
+ end
150
+
151
+ describe "#as_json" do
152
+ it "should call the json generator" do
153
+ options = {:include_blanks => true}
154
+ key = Xively::Key.new
155
+ key.should_receive(:generate_json).with(options).and_return({"permissions" => [:get, :put]})
156
+ key.as_json(options).should == {"permissions" => [:get, :put]}
157
+ end
158
+
159
+ it "should accept *very* nil options" do
160
+ key = Xively::Key.new
161
+ key.should_receive(:generate_json).with({}).and_return({"permissions" => [:get, :put]})
162
+ key.as_json(nil).should == {"permissions" => [:get, :put]}
163
+ end
164
+
165
+ it "should return iso8601 formatted expires_at string if present" do
166
+ time = Time.now
167
+ key = Xively::Key.new(:expires_at => time)
168
+ key.as_json[:key][:expires_at].should == time.iso8601(6)
169
+ end
170
+ end
171
+
172
+ describe "#to_json" do
173
+ before(:each) do
174
+ @time = Time.now
175
+ @key_hash = { "label" => "label", :expires_at => @time, "permissions" => [{"permissions" => [:get, :put, :post], :resources => [{:feed_id => 504, :datastream_id => "0"}]}] }
176
+ end
177
+
178
+ it "should call #as_json" do
179
+ key = Xively::Key.new(@key_hash)
180
+ key.should_receive(:as_json).with(nil)
181
+ key.to_json
182
+ end
183
+
184
+ it "should pass options through to #as_json" do
185
+ key = Xively::Key.new(@key_hash)
186
+ key.should_receive(:as_json).with({:crazy => "options"})
187
+ key.to_json({:crazy => "options"})
188
+ end
189
+
190
+ it "should pass the output of #as_json to yajl" do
191
+ key = Xively::Key.new(@key_hash)
192
+ key.should_receive(:as_json).and_return({:awesome => "hash"})
193
+ MultiJson.should_receive(:dump).with({:awesome => "hash"})
194
+ key.to_json
195
+ end
196
+ end
197
+
198
+ end