frenetic 0.0.20.alpha.6 → 1.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -1
  3. data/Appraisals +9 -0
  4. data/Gemfile +1 -1
  5. data/README.md +2 -2
  6. data/frenetic.gemspec +8 -5
  7. data/gemfiles/faraday_08.gemfile +10 -0
  8. data/gemfiles/faraday_08.gemfile.lock +77 -0
  9. data/gemfiles/faraday_09.gemfile +10 -0
  10. data/gemfiles/faraday_09.gemfile.lock +77 -0
  11. data/lib/frenetic.rb +57 -30
  12. data/lib/frenetic/briefly_memoizable.rb +34 -0
  13. data/lib/frenetic/concerns/collection_rest_methods.rb +1 -1
  14. data/lib/frenetic/concerns/hal_linked.rb +5 -35
  15. data/lib/frenetic/concerns/member_rest_methods.rb +0 -2
  16. data/lib/frenetic/concerns/structured.rb +0 -5
  17. data/lib/frenetic/connection.rb +110 -0
  18. data/lib/frenetic/errors.rb +112 -0
  19. data/lib/frenetic/hypermedia_link.rb +74 -0
  20. data/lib/frenetic/hypermedia_link_set.rb +43 -0
  21. data/lib/frenetic/middleware/hal_json.rb +9 -12
  22. data/lib/frenetic/resource.rb +22 -6
  23. data/lib/frenetic/resource_collection.rb +0 -1
  24. data/lib/frenetic/resource_mockery.rb +55 -1
  25. data/lib/frenetic/version.rb +1 -1
  26. data/spec/{concerns/breifly_memoizable_spec.rb → briefly_memoizable_spec.rb} +10 -18
  27. data/spec/concerns/hal_linked_spec.rb +49 -62
  28. data/spec/concerns/member_rest_methods_spec.rb +8 -10
  29. data/spec/concerns/structured_spec.rb +70 -75
  30. data/spec/connection_spec.rb +137 -0
  31. data/spec/fixtures/test_api_requests.rb +8 -2
  32. data/spec/frenetic_spec.rb +221 -133
  33. data/spec/hypermedia_link_set_spec.rb +155 -0
  34. data/spec/hypermedia_link_spec.rb +153 -0
  35. data/spec/middleware/hal_json_spec.rb +13 -15
  36. data/spec/resource_collection_spec.rb +17 -16
  37. data/spec/resource_mockery_spec.rb +69 -0
  38. data/spec/resource_spec.rb +110 -63
  39. data/spec/support/rspec.rb +0 -1
  40. metadata +88 -75
  41. data/lib/frenetic/concerns/briefly_memoizable.rb +0 -34
  42. data/lib/frenetic/concerns/configurable.rb +0 -59
  43. data/lib/frenetic/concerns/resource_mockery.rb +0 -48
  44. data/lib/frenetic/configuration.rb +0 -88
  45. data/spec/concerns/configurable_spec.rb +0 -50
  46. data/spec/concerns/resource_mockery_spec.rb +0 -56
  47. data/spec/configuration_spec.rb +0 -134
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ describe Frenetic::Connection do
4
+ let(:url) { 'http://example.com' }
5
+ let(:cfg) do
6
+ {
7
+ adapter: :net_http,
8
+ url: url
9
+ }
10
+ end
11
+
12
+ subject(:instance) { described_class.new(cfg) }
13
+
14
+ describe '#initialize?' do
15
+ subject { super().valid? }
16
+
17
+ context 'with an invalid configuration' do
18
+ let(:url) { nil }
19
+
20
+ it 'raises an error' do
21
+ expect{subject}.to raise_error Frenetic::ConfigError, %r{Url must be present}
22
+ end
23
+ end
24
+
25
+ context 'with a valid configuration' do
26
+ let(:url) { 'http://example.com' }
27
+
28
+ it 'does not raise an error' do
29
+ expect{subject}.to_not raise_error
30
+ end
31
+ end
32
+ end
33
+
34
+ describe '#process_config' do
35
+ subject { super().process_config(url:url) }
36
+
37
+ it 'returns a Faraday builder-compatible config' do
38
+ expect(subject[0]).to be_a Hash
39
+ end
40
+
41
+ it 'returns a Faraday::Connection-compatible config' do
42
+ expect(subject[1]).to include :url
43
+ end
44
+
45
+ it 'converts URLs to URIs' do
46
+ expect(subject[1]).to include url:kind_of(Addressable::URI)
47
+ end
48
+ end
49
+
50
+ describe '#configure_authentication' do
51
+ let(:builder) { double('FaradayBuilder', request:true) }
52
+
53
+ subject { super().configure_authentication(builder) }
54
+
55
+ context 'with no authentication credentials' do
56
+ it 'does not use any authentication middleware' do
57
+ subject
58
+ expect(builder).to_not have_received(:request)
59
+ end
60
+ end
61
+
62
+ context 'with Basic Auth credentials' do
63
+ let(:cfg) { super().merge(username:'un', password:'pw') }
64
+
65
+ it 'uses the Basic Auth middleware' do
66
+ subject
67
+ expect(builder).to have_received(:request).with(:basic_auth, 'un', 'pw')
68
+ end
69
+ end
70
+
71
+ context 'with Basic Auth credentials' do
72
+ let(:cfg) { super().merge(api_token:'abc123') }
73
+
74
+ it 'uses the Basic Auth middleware' do
75
+ subject
76
+ expect(builder).to have_received(:request).with(:token_auth, 'abc123')
77
+ end
78
+ end
79
+ end
80
+
81
+ describe '#configure_cache' do
82
+ let(:builder) { double('FaradayBuilder', use:true) }
83
+
84
+ subject { super().configure_cache(builder) }
85
+
86
+ context 'with no cache settings' do
87
+ it 'does not use any caching middleware' do
88
+ subject
89
+ expect(builder).to_not have_received(:use)
90
+ end
91
+ end
92
+
93
+ context 'with :rack' do
94
+ let(:cfg) { super().merge(cache: :rack) }
95
+
96
+ it 'uses the Rack::Compatible caching middleware' do
97
+ subject
98
+ expect(builder).to have_received(:use).with(
99
+ FaradayMiddleware::RackCompatible,
100
+ Rack::Cache::Context,
101
+ hash_including(
102
+ :metastore,
103
+ :entitystore,
104
+ :ignore_headers
105
+ )
106
+ )
107
+ end
108
+ end
109
+
110
+ context 'with :rails' do
111
+ let(:cfg) { super().merge(cache: :rails) }
112
+ let(:rails) { double('Rails').as_null_object }
113
+
114
+ before { stub_const 'Rails', rails }
115
+
116
+ it 'uses the HttpCache caching middleware' do
117
+ subject
118
+ expect(builder).to have_received(:use).with(
119
+ Faraday::HttpCache,
120
+ hash_including(:store)
121
+ )
122
+ end
123
+ end
124
+ end
125
+
126
+ describe '#configure_adapter' do
127
+ let(:builder) { double('FaradayBuilder', adapter:true) }
128
+ let(:cfg) { super().merge(adapter: :patron) }
129
+
130
+ subject { super().configure_adapter(builder) }
131
+
132
+ it 'uses the specified adapter' do
133
+ subject
134
+ expect(builder).to have_received(:adapter).with(:patron)
135
+ end
136
+ end
137
+ end
@@ -1,7 +1,6 @@
1
1
  require 'json'
2
2
 
3
3
  class HttpStubs
4
-
5
4
  def initialize( rspec )
6
5
  @rspec = rspec
7
6
  end
@@ -81,8 +80,16 @@ class HttpStubs
81
80
  my_temp_resource: {
82
81
  description: 'Humanized resource description',
83
82
  properties: {
83
+ id: 'number',
84
84
  name: 'string'
85
85
  }
86
+ },
87
+ abstract_resource: {
88
+ description: 'A random thing',
89
+ properties: {
90
+ id: 'number',
91
+ genus: 'string'
92
+ }
86
93
  }
87
94
  }
88
95
  },
@@ -103,7 +110,6 @@ class HttpStubs
103
110
  }
104
111
  }
105
112
  end
106
-
107
113
  end
108
114
 
109
115
  RSpec.configure do |c|
@@ -1,155 +1,243 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Frenetic do
4
- let(:test_cfg) do
5
- {
6
- url:'http://example.com/api'
7
- }
8
- end
9
-
10
- subject(:instance) { described_class.new( test_cfg ) }
11
-
12
- describe '#connection' do
13
- subject { instance.connection }
14
-
15
- it { should be_a Faraday::Connection }
16
-
17
- context 'configured with a :username' do
18
- let(:test_cfg) { super().merge username:'foo' }
19
-
20
- subject { super().builder.handlers }
21
-
22
- it { should include Faraday::Request::BasicAuthentication }
23
- end
24
-
25
- context 'configured with a :api_token' do
26
- let(:test_cfg) { super().merge api_token:'API_TOKEN' }
27
-
28
- subject { super().builder.handlers }
29
-
30
- it { should include Faraday::Request::TokenAuthentication }
31
- end
32
-
33
- context 'configured to use Rack::Cache' do
34
- let(:test_cfg) { super().merge cache: :rack }
35
-
36
- subject { super().builder.handlers }
37
-
38
- it { should include FaradayMiddleware::RackCompatible }
39
- end
40
-
41
- context 'when Frenetic is initialized with a block' do
42
- it 'should yield the Faraday builder to the block argument' do
43
- builder = nil
44
-
45
- described_class.new(test_cfg) do |b|
46
- builder = b
47
- end.connection
48
-
49
- builder.should be_a Faraday::Connection
50
- end
4
+ let(:url) { 'http://example.com/api' }
5
+ let(:test_cfg) { { url:url } }
6
+
7
+ subject(:instance) { described_class.new(test_cfg) }
8
+
9
+ describe '.config' do
10
+ subject { described_class.config }
11
+
12
+ it 'includes expected options' do
13
+ expect(subject).to include adapter: Faraday.default_adapter
14
+ expect(subject).to include :api_token
15
+ expect(subject).to include cache:false
16
+ expect(subject).to include :default_root_cache_age
17
+ expect(subject).to include headers:kind_of(Hash)
18
+ expect(subject).to include middleware:[]
19
+ expect(subject).to include :password
20
+ expect(subject).to include ssl:{verify:true}
21
+ expect(subject).to include test_mode:false
22
+ expect(subject).to include :url
23
+ expect(subject).to include :username
51
24
  end
52
25
  end
53
26
 
54
- describe '#description' do
55
- subject { instance.description }
56
-
57
- context 'with a URL that returns a' do
58
- context 'valid response' do
59
- before { @stubs.api_description }
60
-
61
- it { should include '_embedded', '_links' }
62
- end
63
-
64
- context 'server error' do
65
- before { @stubs.api_server_error }
66
-
67
- it 'should raise an error' do
68
- expect{ subject }.to raise_error Frenetic::ServerError
69
- end
70
- end
27
+ describe '#config' do
28
+ subject { super().config }
71
29
 
72
- context 'client error' do
73
- before { @stubs.api_client_error :json }
74
-
75
- it 'should raise an error' do
76
- expect{ subject }.to raise_error Frenetic::ClientError
77
- end
78
- end
79
-
80
- context 'JSON parsing error' do
81
- context 'for an otherwise successful response' do
82
- before { @stubs.api_html_response }
83
-
84
- it 'should raise an error' do
85
- expect{ subject }.to raise_error Frenetic::ParsingError
86
- end
87
- end
88
-
89
- context 'for a server error' do
90
- before { @stubs.api_server_error :text }
91
-
92
- it 'should raise an error' do
93
- expect{ subject }.to raise_error Frenetic::ServerError, '500 Error encountered'
94
- end
95
- end
96
-
97
- context 'for a client error' do
98
- before { @stubs.api_client_error :text }
99
-
100
- it 'should raise an error' do
101
- expect{ subject }.to raise_error Frenetic::ClientError, '404 Error encountered'
102
- end
103
- end
104
- end
30
+ it 'includes non-default instance values' do
31
+ expect(subject.url).to eq url
105
32
  end
106
- end
107
-
108
- describe '.schema' do
109
- subject { instance.schema }
110
-
111
- before { @stubs.api_description }
112
-
113
- it { should include 'my_temp_resource' }
114
- end
115
33
 
116
- describe '#get' do
117
- subject { instance.get '/foo' }
118
-
119
- it 'should delegate to Faraday' do
120
- instance.connection.should_receive :get
121
-
122
- subject
34
+ it 'does not override the default class values' do
35
+ expect(subject.url).to_not eq described_class.config.url
123
36
  end
124
37
  end
125
38
 
126
- describe '#put' do
127
- subject { instance.put '/foo' }
128
-
129
- it 'should delegate to Faraday' do
130
- instance.connection.should_receive :put
39
+ describe '#configure' do
40
+ subject { instance.configure {|c| } }
131
41
 
42
+ it 'resets the Connection' do
43
+ prev_connection = instance.connection
132
44
  subject
45
+ expect(instance.connection).to_not eq prev_connection
133
46
  end
134
47
  end
135
48
 
136
- describe '#post' do
137
- subject { instance.post '/foo' }
138
-
139
- it 'should delegate to Faraday' do
140
- instance.connection.should_receive :post
49
+ describe '#connection' do
50
+ subject { super().connection }
141
51
 
142
- subject
52
+ it 'returns a Connection' do
53
+ expect(subject).to be_a Frenetic::Connection
143
54
  end
144
55
  end
145
56
 
146
- describe '#delete' do
147
- subject { instance.delete '/foo' }
148
-
149
- it 'should delegate to Faraday' do
150
- instance.connection.should_receive :delete
151
-
152
- subject
153
- end
154
- end
57
+ # describe '#connection' do
58
+ # subject { super().connection }
59
+
60
+ # it 'returns a Faraday Connection' do
61
+ # expect(subject).to be_a Faraday::Connection
62
+ # end
63
+
64
+ # context 'when Frenetic is initialized with a block' do
65
+ # subject do
66
+ # builder = nil
67
+ # described_class.new(test_cfg) do |b|
68
+ # builder = b
69
+ # end.connection
70
+ # builder
71
+ # end
72
+
73
+ # it 'yields the Faraday builder to the block argument' do
74
+ # expect(subject).to be_a Faraday::Connection
75
+ # end
76
+ # end
77
+
78
+ # describe 'middleware' do
79
+ # subject { super().builder.handlers }
80
+
81
+ # context 'configured with a :username' do
82
+ # let(:test_cfg) { super().merge username:'foo' }
83
+
84
+ # it 'includes Basic Auth middleware' do
85
+ # expect(subject).to include Faraday::Request::BasicAuthentication
86
+ # end
87
+ # end
88
+
89
+ # context 'configured with a :api_token' do
90
+ # let(:test_cfg) { super().merge api_token:'API_TOKEN' }
91
+
92
+ # it 'includes Token Authentication middleware' do
93
+ # expect(subject).to include Faraday::Request::TokenAuthentication
94
+ # end
95
+ # end
96
+
97
+ # context 'configured to use Rack::Cache' do
98
+ # let(:test_cfg) { super().merge cache: :rack }
99
+
100
+ # it 'includes Rack middleware' do
101
+ # expect(subject).to include FaradayMiddleware::RackCompatible
102
+ # end
103
+ # end
104
+ # end
105
+ # end
106
+
107
+ # describe '#description' do
108
+ # subject { super().description }
109
+
110
+ # context 'with a URL that returns a' do
111
+ # context 'valid response' do
112
+ # before { @stubs.api_description }
113
+
114
+ # it 'includes meta Hypermedia properties' do
115
+ # expect(subject).to include '_embedded'
116
+ # expect(subject).to include '_links'
117
+ # end
118
+ # end
119
+
120
+ # context 'server error' do
121
+ # before { @stubs.api_server_error }
122
+
123
+ # it 'raises an error' do
124
+ # expect{subject}.to raise_error Frenetic::ServerParsingError
125
+ # end
126
+ # end
127
+
128
+ # context 'client error' do
129
+ # before { @stubs.api_client_error :json }
130
+
131
+ # it 'raises an error' do
132
+ # expect{subject}.to raise_error Frenetic::ClientError
133
+ # end
134
+ # end
135
+
136
+ # context 'JSON parsing error' do
137
+ # context 'for an otherwise successful response' do
138
+ # before { @stubs.api_html_response }
139
+
140
+ # it 'raises an error' do
141
+ # expect{subject}.to raise_error Frenetic::UnknownParsingError
142
+ # end
143
+ # end
144
+
145
+ # context 'for a server error' do
146
+ # before { @stubs.api_server_error :text }
147
+
148
+ # it 'raises an error' do
149
+ # expect{subject}.to raise_error Frenetic::ServerParsingError
150
+ # end
151
+ # end
152
+
153
+ # context 'for a client error' do
154
+ # before { @stubs.api_client_error :text }
155
+
156
+ # it 'raises an error' do
157
+ # expect{subject}.to raise_error Frenetic::ClientParsingError
158
+ # end
159
+ # end
160
+ # end
161
+ # end
162
+ # end
163
+
164
+ # describe '.schema' do
165
+ # before { @stubs.api_description }
166
+
167
+ # subject { super().schema }
168
+
169
+ # it 'includes a list of defined resources' do
170
+ # expect(subject).to include 'my_temp_resource'
171
+ # end
172
+ # end
173
+
174
+ # describe '#get' do
175
+ # subject { super().get '/foo' }
176
+
177
+ # it 'delegates to Faraday' do
178
+ # allow(instance.connection).to receive(:get)
179
+ # subject
180
+ # expect(instance.connection).to have_received(:get)
181
+ # end
182
+ # end
183
+
184
+ # describe '#put' do
185
+ # subject { super().put '/foo' }
186
+
187
+ # it 'delegates to Faraday' do
188
+ # allow(instance.connection).to receive(:put)
189
+ # subject
190
+ # expect(instance.connection).to have_received(:put)
191
+ # end
192
+ # end
193
+
194
+ # describe '#patch' do
195
+ # subject { super().patch '/foo' }
196
+
197
+ # it 'delegates to Faraday' do
198
+ # allow(instance.connection).to receive(:patch)
199
+ # subject
200
+ # expect(instance.connection).to have_received(:patch)
201
+ # end
202
+ # end
203
+
204
+ # describe '#head' do
205
+ # subject { instance.head '/foo' }
206
+
207
+ # it 'delegates to Faraday' do
208
+ # allow(instance.connection).to receive(:head)
209
+ # subject
210
+ # expect(instance.connection).to have_received(:head)
211
+ # end
212
+ # end
213
+
214
+ # describe '#options' do
215
+ # subject { instance.options '/foo' }
216
+
217
+ # it 'delegates to Faraday' do
218
+ # allow(instance.connection).to receive(:options)
219
+ # subject
220
+ # expect(instance.connection).to have_received(:options)
221
+ # end
222
+ # end
223
+
224
+ # describe '#post' do
225
+ # subject { super().post '/foo' }
226
+
227
+ # it 'delegates to Faraday' do
228
+ # allow(instance.connection).to receive(:post)
229
+ # subject
230
+ # expect(instance.connection).to have_received(:post)
231
+ # end
232
+ # end
233
+
234
+ # describe '#delete' do
235
+ # subject { super().delete '/foo' }
236
+
237
+ # it 'delegates to Faraday' do
238
+ # allow(instance.connection).to receive(:delete)
239
+ # subject
240
+ # expect(instance.connection).to have_received(:delete)
241
+ # end
242
+ # end
155
243
  end