frenetic 0.0.20.alpha.2 → 0.0.20.alpha.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -340,9 +340,54 @@ the schema has changed. If so, it will redefine the the getter methods available
340
340
  on your Class. This is what Hypermedia APIs are all about, a loose coupling
341
341
  between client and server.
342
342
 
343
+ #### Mocking Resources
343
344
 
345
+ Sometimes, when you are writing tests for your API client, it is helpful to have
346
+ a mock instance of your API resource to play with.
344
347
 
348
+ Frenetic provides a mixin that removes some of the HTTP interactions required
349
+ when interacting with a Hypermedia API. It essentially turns your resource
350
+ into a fancy OpenStruct, allowing you to assign whatever attributes you want.
345
351
 
352
+ You can enable this by directly mixing in the behavior into your resource:
353
+
354
+ ```ruby
355
+ require 'frenetic/resource_mockery'
356
+
357
+ MyResource.send :include, Frenetic::ResourceMockery
358
+ ```
359
+
360
+ Or by creating a special Class specifically for testing (which is recommended)
361
+
362
+ ```ruby
363
+ # models/my_mock_resource.rb
364
+ require 'frenetic/resource_mockery'
365
+
366
+ class MyMockResource < MyResource
367
+ include Frenetic::ResourceMockery
368
+
369
+ def default_attributes
370
+ {
371
+ name: 'Mock Name',
372
+ city: 'Mock City'
373
+ }
374
+ end
375
+ end
376
+
377
+ # spec/integrations/my_integration_spec.rb
378
+ describe 'My contrived integration test' do
379
+ it 'returns a Resource' do
380
+ MyResource.stub(:find).and_return MyMockResource.new city:'Washington, DC'
381
+
382
+ do_my_thing
383
+
384
+ payee.city.should == 'Washington, DC'
385
+ end
386
+ end
387
+ ```
388
+
389
+ As you can see, this allows you to supply some default values for the attributes
390
+ of your resource to ease object creation in testing.
346
391
 
347
392
  ## Contributing
348
393
 
@@ -0,0 +1,34 @@
1
+ require 'ostruct'
2
+
3
+ class Frenetic
4
+ module ResourceMockery
5
+
6
+ def attributes
7
+ @params
8
+ end
9
+
10
+ def properties
11
+ @params.each_with_object({}) do |(k,v), props|
12
+ props[k] = v.class.to_s.underscore
13
+ end
14
+ end
15
+
16
+ # Provides a place for a Resources that are mocked to declare reasonable
17
+ # default values for Mock Resources
18
+ def default_attributes
19
+ {}
20
+ end
21
+
22
+ private
23
+
24
+ def build_params( p )
25
+ defaults = default_attributes.with_indifferent_access
26
+ @params = defaults.merge( (p || {}).with_indifferent_access )
27
+ end
28
+
29
+ def build_structure
30
+ @structure = OpenStruct.new( @attrs )
31
+ end
32
+
33
+ end
34
+ end
@@ -53,7 +53,13 @@ class Frenetic
53
53
  end
54
54
 
55
55
  def headers
56
- @@defaults[:headers].merge( @_cfg[:headers] || {} )
56
+ @@defaults[:headers].merge( @_cfg[:headers] || {} ).tap do |h|
57
+ if @_cfg[:headers] && @_cfg[:headers][:user_agent]
58
+ if h[:user_agent] != @@defaults[:headers][:user_agent]
59
+ h[:user_agent] = "#{h[:user_agent]} (#{@@defaults[:headers][:user_agent]})"
60
+ end
61
+ end
62
+ end
57
63
  end
58
64
 
59
65
  def password
@@ -47,14 +47,14 @@ class Frenetic
47
47
  end
48
48
 
49
49
  def initialize( p = {} )
50
- @params = (p || {}).with_indifferent_access
50
+ build_params p
51
51
  @attrs = {}
52
52
 
53
53
  properties.keys.each do |k|
54
54
  @attrs[k] = @params[k]
55
55
  end
56
56
 
57
- @structure = structure.new( *@attrs.values )
57
+ build_structure
58
58
  end
59
59
 
60
60
  def attributes
@@ -74,7 +74,7 @@ class Frenetic
74
74
  end
75
75
 
76
76
  def inspect
77
- attrs = @structure.each_pair.collect do |k,v|
77
+ attrs = attributes.collect do |k,v|
78
78
  val = v.is_a?(String) ? "\"#{v}\"" : v || 'nil'
79
79
  "#{k}=#{val}"
80
80
  end.join(' ')
@@ -94,6 +94,14 @@ class Frenetic
94
94
 
95
95
  private
96
96
 
97
+ def build_params( p )
98
+ @params = (p || {}).with_indifferent_access
99
+ end
100
+
101
+ def build_structure
102
+ @structure = structure.new( *@attrs.values )
103
+ end
104
+
97
105
  def namespace
98
106
  self.class.namespace
99
107
  end
@@ -0,0 +1 @@
1
+ require 'frenetic/concerns/resource_mockery'
@@ -1,3 +1,3 @@
1
1
  class Frenetic
2
- VERSION = '0.0.20.alpha.2'
2
+ VERSION = '0.0.20.alpha.3'
3
3
  end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ require 'frenetic/resource_mockery'
4
+
5
+ describe Frenetic::ResourceMockery do
6
+ let(:my_mocked_resource) do
7
+ Class.new(Frenetic::Resource) do
8
+ def default_attributes
9
+ { qux:'qux' }
10
+ end
11
+ end
12
+ end
13
+
14
+ before do
15
+ stub_const 'MyNamespace::MyMockedResource', my_mocked_resource
16
+
17
+ MyNamespace::MyMockedResource.send :include, described_class
18
+ end
19
+
20
+ let(:params) { { foo:1, bar:'baz' } }
21
+
22
+ subject { MyNamespace::MyMockedResource.new params }
23
+
24
+ describe '#properties' do
25
+ subject { super().properties }
26
+
27
+ it 'should return a hash of available properties' do
28
+ subject.should include 'foo' => 'fixnum'
29
+ subject.should include 'bar' => 'string'
30
+ end
31
+ end
32
+
33
+ describe '#attributes' do
34
+ subject { super().attributes }
35
+
36
+ it 'should return a hash of the resources attributes' do
37
+ subject.should include 'foo' => 1
38
+ subject.should include 'bar' => 'baz'
39
+ subject.should include 'qux' => 'qux'
40
+ end
41
+ end
42
+
43
+ describe '#default_attributes' do
44
+ it 'should allow implementors to specify sane defaults' do
45
+ subject.qux.should == 'qux'
46
+ end
47
+ end
48
+ end
@@ -70,6 +70,16 @@ describe Frenetic::Configuration do
70
70
  subject.should include accept:'MIME'
71
71
  subject.should include x_foo:'BAR'
72
72
  end
73
+
74
+ context 'with a custom User-Agent' do
75
+ let(:cfg) do
76
+ { headers:{ user_agent:'Foo v1.1' } }
77
+ end
78
+
79
+ it 'should append the Frenentic User-Agent' do
80
+ subject[:user_agent].should match %r{\AFoo v1.1 \(Frenetic v.[^;]*; [^)]*\)\Z}
81
+ end
82
+ end
73
83
  end
74
84
 
75
85
  describe '#password' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frenetic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20.alpha.2
4
+ version: 0.0.20.alpha.3
5
5
  prerelease: 7
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-12 00:00:00.000000000 Z
12
+ date: 2013-05-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -177,16 +177,19 @@ files:
177
177
  - lib/frenetic/concerns/configurable.rb
178
178
  - lib/frenetic/concerns/hal_linked.rb
179
179
  - lib/frenetic/concerns/member_rest_methods.rb
180
+ - lib/frenetic/concerns/resource_mockery.rb
180
181
  - lib/frenetic/concerns/structured.rb
181
182
  - lib/frenetic/configuration.rb
182
183
  - lib/frenetic/middleware/hal_json.rb
183
184
  - lib/frenetic/resource.rb
184
185
  - lib/frenetic/resource_collection.rb
186
+ - lib/frenetic/resource_mockery.rb
185
187
  - lib/frenetic/version.rb
186
188
  - spec/concerns/breifly_memoizable_spec.rb
187
189
  - spec/concerns/configurable_spec.rb
188
190
  - spec/concerns/hal_linked_spec.rb
189
191
  - spec/concerns/member_rest_methods_spec.rb
192
+ - spec/concerns/resource_mockery_spec.rb
190
193
  - spec/concerns/structured_spec.rb
191
194
  - spec/configuration_spec.rb
192
195
  - spec/fixtures/test_api_requests.rb
@@ -212,7 +215,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
212
215
  version: '0'
213
216
  segments:
214
217
  - 0
215
- hash: -863323542650757064
218
+ hash: -3162981887620573122
216
219
  required_rubygems_version: !ruby/object:Gem::Requirement
217
220
  none: false
218
221
  requirements:
@@ -231,6 +234,7 @@ test_files:
231
234
  - spec/concerns/configurable_spec.rb
232
235
  - spec/concerns/hal_linked_spec.rb
233
236
  - spec/concerns/member_rest_methods_spec.rb
237
+ - spec/concerns/resource_mockery_spec.rb
234
238
  - spec/concerns/structured_spec.rb
235
239
  - spec/configuration_spec.rb
236
240
  - spec/fixtures/test_api_requests.rb