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

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 (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