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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -1
- data/Appraisals +9 -0
- data/Gemfile +1 -1
- data/README.md +2 -2
- data/frenetic.gemspec +8 -5
- data/gemfiles/faraday_08.gemfile +10 -0
- data/gemfiles/faraday_08.gemfile.lock +77 -0
- data/gemfiles/faraday_09.gemfile +10 -0
- data/gemfiles/faraday_09.gemfile.lock +77 -0
- data/lib/frenetic.rb +57 -30
- data/lib/frenetic/briefly_memoizable.rb +34 -0
- data/lib/frenetic/concerns/collection_rest_methods.rb +1 -1
- data/lib/frenetic/concerns/hal_linked.rb +5 -35
- data/lib/frenetic/concerns/member_rest_methods.rb +0 -2
- data/lib/frenetic/concerns/structured.rb +0 -5
- data/lib/frenetic/connection.rb +110 -0
- data/lib/frenetic/errors.rb +112 -0
- data/lib/frenetic/hypermedia_link.rb +74 -0
- data/lib/frenetic/hypermedia_link_set.rb +43 -0
- data/lib/frenetic/middleware/hal_json.rb +9 -12
- data/lib/frenetic/resource.rb +22 -6
- data/lib/frenetic/resource_collection.rb +0 -1
- data/lib/frenetic/resource_mockery.rb +55 -1
- data/lib/frenetic/version.rb +1 -1
- data/spec/{concerns/breifly_memoizable_spec.rb → briefly_memoizable_spec.rb} +10 -18
- data/spec/concerns/hal_linked_spec.rb +49 -62
- data/spec/concerns/member_rest_methods_spec.rb +8 -10
- data/spec/concerns/structured_spec.rb +70 -75
- data/spec/connection_spec.rb +137 -0
- data/spec/fixtures/test_api_requests.rb +8 -2
- data/spec/frenetic_spec.rb +221 -133
- data/spec/hypermedia_link_set_spec.rb +155 -0
- data/spec/hypermedia_link_spec.rb +153 -0
- data/spec/middleware/hal_json_spec.rb +13 -15
- data/spec/resource_collection_spec.rb +17 -16
- data/spec/resource_mockery_spec.rb +69 -0
- data/spec/resource_spec.rb +110 -63
- data/spec/support/rspec.rb +0 -1
- metadata +88 -75
- data/lib/frenetic/concerns/briefly_memoizable.rb +0 -34
- data/lib/frenetic/concerns/configurable.rb +0 -59
- data/lib/frenetic/concerns/resource_mockery.rb +0 -48
- data/lib/frenetic/configuration.rb +0 -88
- data/spec/concerns/configurable_spec.rb +0 -50
- data/spec/concerns/resource_mockery_spec.rb +0 -56
- 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|
|
data/spec/frenetic_spec.rb
CHANGED
@@ -1,155 +1,243 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Frenetic do
|
4
|
-
let(:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
subject
|
21
|
-
|
22
|
-
|
23
|
-
|
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 '#
|
55
|
-
subject {
|
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
|
-
|
73
|
-
|
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
|
-
|
117
|
-
|
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 '#
|
127
|
-
subject { instance.
|
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 '#
|
137
|
-
subject {
|
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
|
-
|
52
|
+
it 'returns a Connection' do
|
53
|
+
expect(subject).to be_a Frenetic::Connection
|
143
54
|
end
|
144
55
|
end
|
145
56
|
|
146
|
-
describe '#
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
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
|