contextio 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.document +4 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +1 -0
  4. data/.yardopts +1 -0
  5. data/ChangeLog.md +5 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE.md +20 -0
  8. data/README.md +62 -22
  9. data/Rakefile +46 -36
  10. data/contextio.gemspec +30 -0
  11. data/lib/contextio.rb +69 -583
  12. data/lib/contextio/account.rb +132 -0
  13. data/lib/contextio/account_collection.rb +57 -0
  14. data/lib/contextio/account_sync_data.rb +22 -0
  15. data/lib/contextio/api.rb +162 -0
  16. data/lib/contextio/api/association_helpers.rb +17 -0
  17. data/lib/contextio/api/resource.rb +230 -0
  18. data/lib/contextio/api/resource_collection.rb +174 -0
  19. data/lib/contextio/api/url_builder.rb +153 -0
  20. data/lib/contextio/body_part.rb +45 -0
  21. data/lib/contextio/body_part_collection.rb +13 -0
  22. data/lib/contextio/connect_token.rb +57 -0
  23. data/lib/contextio/connect_token_collection.rb +44 -0
  24. data/lib/contextio/contact.rb +43 -0
  25. data/lib/contextio/contact_collection.rb +21 -0
  26. data/lib/contextio/email_address.rb +53 -0
  27. data/lib/contextio/email_address_collection.rb +21 -0
  28. data/lib/contextio/email_settings.rb +146 -0
  29. data/lib/contextio/file.rb +92 -0
  30. data/lib/contextio/file_collection.rb +13 -0
  31. data/lib/contextio/folder.rb +56 -0
  32. data/lib/contextio/folder_collection.rb +18 -0
  33. data/lib/contextio/folder_sync_data.rb +32 -0
  34. data/lib/contextio/message.rb +96 -0
  35. data/lib/contextio/message_collection.rb +35 -0
  36. data/lib/contextio/oauth_provider.rb +29 -0
  37. data/lib/contextio/oauth_provider_collection.rb +46 -0
  38. data/lib/contextio/source.rb +55 -0
  39. data/lib/contextio/source_collection.rb +41 -0
  40. data/lib/contextio/source_sync_data.rb +23 -0
  41. data/lib/contextio/thread.rb +15 -0
  42. data/lib/contextio/thread_collection.rb +25 -0
  43. data/lib/contextio/version.rb +11 -0
  44. data/lib/contextio/webhook.rb +39 -0
  45. data/lib/contextio/webhook_collection.rb +26 -0
  46. data/spec/config.yml.example +3 -0
  47. data/spec/contextio/account_collection_spec.rb +78 -0
  48. data/spec/contextio/account_spec.rb +52 -0
  49. data/spec/contextio/api/association_helpers_spec.rb +28 -0
  50. data/spec/contextio/api/resource_collection_spec.rb +286 -0
  51. data/spec/contextio/api/resource_spec.rb +467 -0
  52. data/spec/contextio/api/url_builder_spec.rb +78 -0
  53. data/spec/contextio/api_spec.rb +123 -0
  54. data/spec/contextio/connect_token_collection_spec.rb +74 -0
  55. data/spec/contextio/connect_token_spec.rb +58 -0
  56. data/spec/contextio/email_settings_spec.rb +112 -0
  57. data/spec/contextio/oauth_provider_collection_spec.rb +36 -0
  58. data/spec/contextio/oauth_provider_spec.rb +120 -0
  59. data/spec/contextio/source_collection_spec.rb +57 -0
  60. data/spec/contextio/source_spec.rb +52 -0
  61. data/spec/contextio/version_spec.rb +10 -0
  62. data/spec/contextio_spec.rb +64 -0
  63. data/spec/spec_helper.rb +17 -0
  64. metadata +234 -12
  65. data/README.textile +0 -29
@@ -0,0 +1,467 @@
1
+ require 'spec_helper'
2
+ require 'contextio/api/resource'
3
+
4
+ class ResourceCollection
5
+ def initialize(*args); end
6
+
7
+ ContextIO::API::AssociationHelpers.register_resource(self, :resources)
8
+ end
9
+
10
+ class Resource
11
+ def initialize(*args); end
12
+
13
+ ContextIO::API::AssociationHelpers.register_resource(self, :resource)
14
+ end
15
+
16
+ describe ContextIO::API::Resource do
17
+ let(:api) { double('api') }
18
+
19
+ describe ".new" do
20
+ let(:helper_class) do
21
+ Class.new do
22
+ include ContextIO::API::Resource
23
+
24
+ self.primary_key = :foo
25
+
26
+ def foo
27
+ 'defined in class'
28
+ end
29
+ end
30
+ end
31
+
32
+ subject { helper_class.new(api, foo: 'defined in method call', bar: 'baz') }
33
+
34
+ it "defines accessors for options passed in" do
35
+ expect(subject.bar).to eq('baz')
36
+ end
37
+
38
+ it "doesn't over-write accessors that already exist" do
39
+ expect(subject.foo).to eq('defined in class')
40
+ end
41
+ end
42
+
43
+ describe "#validate_options" do
44
+ context "with a string primary key" do
45
+ subject do
46
+ Class.new do
47
+ include ContextIO::API::Resource
48
+
49
+ self.primary_key = 'string'
50
+ end
51
+ end
52
+
53
+ it "matches a symbol" do
54
+ expect { subject.new(api, string: 'foo') }.to_not raise_error
55
+ end
56
+
57
+ it "matches a string" do
58
+ expect { subject.new(api, 'string' => 'foo') }.to_not raise_error
59
+ end
60
+
61
+ it "raises with missing keys" do
62
+ expect { subject.new(api, foo: 'bar') }.to raise_error
63
+ end
64
+
65
+ it "doesn't raise if resource_url is set" do
66
+ expect { subject.new(api, resource_url: 'some url') }.to_not raise_error
67
+ end
68
+ end
69
+
70
+ context "with a symbol primary key"
71
+ subject do
72
+ Class.new do
73
+ include ContextIO::API::Resource
74
+
75
+ self.primary_key = :symbol
76
+ end
77
+ end
78
+
79
+ it "matches a string" do
80
+ expect { subject.new(api, 'symbol' => 'foo') }.to_not raise_error
81
+ end
82
+
83
+ it "matches a symbol" do
84
+ expect { subject.new(api, symbol: 'bar') }.to_not raise_error
85
+ end
86
+
87
+ it "raises with missing keys" do
88
+ expect { subject.new(api, foo: 'bar') }.to raise_error
89
+ end
90
+
91
+ it "doesn't raise if resource_url is set" do
92
+ expect { subject.new(api, resource_url: 'some url') }.to_not raise_error
93
+ end
94
+ end
95
+
96
+ describe ".lazy_attributes" do
97
+ let(:helper_class) do
98
+ Class.new do
99
+ include ContextIO::API::Resource
100
+
101
+ lazy_attributes :foo, :longer_name
102
+ end
103
+ end
104
+
105
+ let(:api) do
106
+ double('api', request: {'foo' => 'set from API', 'longer-name' => 'bar'})
107
+ end
108
+
109
+ subject { helper_class.new(api, resource_url: 'resource_url') }
110
+
111
+ it "defines a method for the attribute" do
112
+ expect(subject).to respond_to(:foo)
113
+ end
114
+
115
+ context "when the attribute is set at creation" do
116
+ subject do
117
+ helper_class.new(api, resource_url: 'resource_url', foo: 'foo', 'longer-name' => 'bar')
118
+ end
119
+
120
+ it "returns the value set" do
121
+ expect(subject.foo).to eq('foo')
122
+ end
123
+
124
+ it "doesn't try to fetch from the API" do
125
+ subject.should_not_receive(:fetch_attributes)
126
+
127
+ subject.foo
128
+ end
129
+
130
+ it "subs '-' for '_' in attribute names" do
131
+ expect(subject.longer_name).to eq('bar')
132
+ end
133
+ end
134
+
135
+ context "when the attributes is not set at creation" do
136
+ it "tries to fetch from the API" do
137
+ api.should_receive(:request).with(:get, 'resource_url').
138
+ and_return({'foo' => 'set from API', 'longer-name' => 'bar'})
139
+
140
+ subject.foo
141
+ end
142
+
143
+ it "returns the value from the API" do
144
+ expect(subject.foo).to eq('set from API')
145
+ end
146
+
147
+ it "subs '-' for '_' in attribute names" do
148
+ expect(subject.longer_name).to eq('bar')
149
+ end
150
+ end
151
+ end
152
+
153
+ describe ".belongs_to" do
154
+ let(:helper_class) do
155
+ Class.new do
156
+ include ContextIO::API::Resource
157
+
158
+ belongs_to :resource
159
+ end
160
+ end
161
+
162
+ context "when one isn't passed in at creation" do
163
+ context "and one is returned from the API" do
164
+ subject { helper_class.new(api, resource_url: 'resource_url') }
165
+
166
+ before do
167
+ api.stub(:request).and_return(
168
+ {
169
+ 'resource' => {
170
+ 'resource_url' => 'relation_url'
171
+ }
172
+ }
173
+ )
174
+ end
175
+
176
+ it "makes a related object available" do
177
+ expect(subject.resource).to be_a(Resource)
178
+ end
179
+
180
+ it "passes keys from the api response to the new object" do
181
+ Resource.should_receive(:new).with(api, 'resource_url' => 'relation_url')
182
+
183
+ subject.resource
184
+ end
185
+
186
+ it "returns the same object each time" do
187
+ expect(subject.resource).to be(subject.resource)
188
+ end
189
+ end
190
+
191
+ context "and one isn't returned from the API" do
192
+ subject { helper_class.new(api, resource_url: 'resource_url') }
193
+
194
+ before do
195
+ api.stub(:request).and_return({ })
196
+ end
197
+
198
+ it "makes the resource nil" do
199
+ expect(subject.resource).to be_nil
200
+ end
201
+ end
202
+
203
+ context "and the API returns an empty hash" do
204
+ subject { helper_class.new(api, resource_url: 'resource_url') }
205
+
206
+ before do
207
+ api.stub(:request).and_return(
208
+ {
209
+ 'resource' => { }
210
+ }
211
+ )
212
+ end
213
+
214
+ it "makes the resource nil" do
215
+ expect(subject.resource).to be_nil
216
+ end
217
+ end
218
+
219
+ context "and the API returns an empty array" do
220
+ subject { helper_class.new(api, resource_url: 'resource_url') }
221
+
222
+ before do
223
+ api.stub(:request).and_return(
224
+ {
225
+ 'resource' => [ ]
226
+ }
227
+ )
228
+ end
229
+
230
+ it "makes the resource nil" do
231
+ expect(subject.resource).to be_nil
232
+ end
233
+ end
234
+ end
235
+
236
+ context "when one is passed in at creation" do
237
+ let(:relation_object) { Resource.new(api, resource_url: 'relation_url') }
238
+
239
+ subject { helper_class.new(api, resource_url: 'resource_url', resource: relation_object)}
240
+
241
+ it "makes the passed-in related object available" do
242
+ expect(subject.resource).to be(relation_object)
243
+ end
244
+
245
+ it "doesn't make any API calls" do
246
+ api.should_not_receive(:request)
247
+
248
+ subject.resource
249
+ end
250
+ end
251
+ end
252
+
253
+ describe ".has_many" do
254
+ let(:helper_class) do
255
+ Class.new do
256
+ include ContextIO::API::Resource
257
+
258
+ has_many :resources
259
+ self.association_name = :helper_class
260
+ end
261
+ end
262
+
263
+ context "when a collection isn't passed in at creation" do
264
+ context "and a collection is returned from the API" do
265
+ subject { helper_class.new(api, resource_url: 'resource_url') }
266
+
267
+ before do
268
+ api.stub(:request).and_return(
269
+ {
270
+ 'resources' => [{
271
+ 'resource_url' => 'relation_url'
272
+ }]
273
+ }
274
+ )
275
+ end
276
+
277
+ it "makes a related collection object available" do
278
+ expect(subject.resources).to be_a(ResourceCollection)
279
+ end
280
+
281
+ it "passes keys from the api response to the new object" do
282
+ ResourceCollection.should_receive(:new).with(api, hash_including(attribute_hashes: [{'resource_url' => 'relation_url'}]))
283
+
284
+ subject.resources
285
+ end
286
+
287
+ it "returns the same object each time" do
288
+ expect(subject.resources).to be(subject.resources)
289
+ end
290
+
291
+ it "passes its self to the new collection" do
292
+ ResourceCollection.should_receive(:new).with(anything, hash_including(:helper_class => subject))
293
+
294
+ subject.resources
295
+ end
296
+ end
297
+
298
+ context "and a collection isn't returned from the API" do
299
+ subject { helper_class.new(api, resource_url: 'resource_url') }
300
+
301
+ before do
302
+ api.stub(:request).and_return({ 'foo' => 'bar' })
303
+ end
304
+
305
+ it "tries the API only once" do
306
+ api.should_receive(:request).exactly(:once).and_return({ 'foo' => 'bar' })
307
+
308
+ subject.resources
309
+ subject.resources
310
+ end
311
+
312
+ it "still builds a relation object" do
313
+ expect(subject.resources).to be_a(ResourceCollection)
314
+ end
315
+
316
+ it "passes its self to the new collection" do
317
+ ResourceCollection.should_receive(:new).with(anything, hash_including(:helper_class => subject))
318
+
319
+ subject.resources
320
+ end
321
+ end
322
+ end
323
+
324
+ context "when an Array of Hashes is passed in at creation" do
325
+ subject do
326
+ helper_class.new(api, resource_url: 'resource_url', resources: [{'resource_url' => 'xxx'}])
327
+ end
328
+
329
+ it "makes a collection object available" do
330
+ expect(subject.resources).to be_a(ResourceCollection)
331
+ end
332
+
333
+ it "doesn't make any API calls" do
334
+ api.should_not_receive(:request)
335
+
336
+ subject.resources
337
+ end
338
+ end
339
+ end
340
+
341
+ describe "#fetch_attributes" do
342
+ let(:helper_class) do
343
+ Class.new do
344
+ include ContextIO::API::Resource
345
+ end
346
+ end
347
+
348
+ subject do
349
+ helper_class.new(api, resource_url: 'resource_url')
350
+ end
351
+
352
+ it "makes a request to the API" do
353
+ subject.api.should_receive(:request).with(:get, 'resource_url').and_return({})
354
+
355
+ subject.send(:fetch_attributes)
356
+ end
357
+
358
+ it "defines getter methods for new attributes returned" do
359
+ subject.api.stub(:request).and_return(foo: 'bar')
360
+
361
+ subject.send(:fetch_attributes)
362
+
363
+ expect(subject.foo).to eq('bar')
364
+ end
365
+
366
+ it "doesn't override existing getter methods" do
367
+ def subject.foo
368
+ 'hard coded value'
369
+ end
370
+
371
+ subject.api.stub(:request).and_return(foo: 'bar')
372
+
373
+ subject.send(:fetch_attributes)
374
+
375
+ expect(subject.foo).to eq('hard coded value')
376
+ end
377
+
378
+ it "stores the response hash" do
379
+ subject.api.stub(:request).and_return('foo' => 'bar')
380
+
381
+ subject.send(:fetch_attributes)
382
+
383
+ expect(subject.api_attributes).to eq('foo' => 'bar')
384
+ end
385
+ end
386
+
387
+ describe "#api_attributes" do
388
+ let(:helper_class) do
389
+ Class.new do
390
+ include ContextIO::API::Resource
391
+ end
392
+ end
393
+
394
+ let(:api) do
395
+ double('api', request: { 'foo' => 'bar', 'boolean' => false })
396
+ end
397
+
398
+ subject do
399
+ helper_class.new(api, resource_url: 'resource_url')
400
+ end
401
+
402
+ it "hits the API only on first call" do
403
+ api.should_receive(:request).exactly(:once)
404
+
405
+ subject.api_attributes
406
+ subject.api_attributes
407
+ end
408
+
409
+ it "caches the api response hash" do
410
+ expect(subject.api_attributes).to eq('foo' => 'bar', 'boolean' => false)
411
+ end
412
+ end
413
+
414
+ describe "#resource_url" do
415
+ let(:helper_class) do
416
+ Class.new do
417
+ include ContextIO::API::Resource
418
+
419
+ self.primary_key = :id
420
+ end
421
+ end
422
+
423
+ context "when one is set at creation" do
424
+ subject do
425
+ helper_class.new(api, resource_url: 'resource_url')
426
+ end
427
+
428
+ it "returns the one passed in" do
429
+ expect(subject.resource_url).to eq('resource_url')
430
+ end
431
+ end
432
+
433
+ context "when one is not set at creation" do
434
+ subject do
435
+ helper_class.new(api, id: '33f1')
436
+ end
437
+
438
+ it "delegates URL construction to the api" do
439
+ api.should_receive(:url_for).with(subject).and_return('helpers/33f1')
440
+
441
+ expect(subject.resource_url).to eq('helpers/33f1')
442
+ end
443
+ end
444
+ end
445
+
446
+ describe "#delete" do
447
+ let(:helper_class) do
448
+ Class.new do
449
+ include ContextIO::API::Resource
450
+ end
451
+ end
452
+
453
+ subject do
454
+ helper_class.new(double('api', :request => {'success' => true}), resource_url: 'resource_url')
455
+ end
456
+
457
+ it "makes a request to the API" do
458
+ subject.api.should_receive(:request).with(:delete, 'resource_url')
459
+
460
+ subject.delete
461
+ end
462
+
463
+ it "returns the contents of the 'success' key" do
464
+ expect(subject.delete).to eq(true)
465
+ end
466
+ end
467
+ end