frenetic 0.0.6 → 0.0.7
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.
- data/README.md +41 -25
- data/frenetic.gemspec +5 -6
- data/lib/frenetic.rb +13 -9
- data/lib/frenetic/configuration.rb +73 -71
- data/lib/frenetic/version.rb +1 -1
- data/spec/lib/frenetic/configuration_spec.rb +159 -92
- data/spec/lib/frenetic/hal_json_spec.rb +5 -5
- data/spec/lib/frenetic/resource_spec.rb +1 -1
- data/spec/lib/frenetic_spec.rb +26 -10
- data/spec/spec_helper.rb +12 -24
- metadata +23 -40
- data/Guardfile +0 -15
data/README.md
CHANGED
@@ -95,31 +95,6 @@ will not trigger another API request.
|
|
95
95
|
|
96
96
|
|
97
97
|
|
98
|
-
### API Resources
|
99
|
-
|
100
|
-
While HAL+JSON is awesome, not all implementations are perfect. Frenetic
|
101
|
-
assumes a HAL+JSON response as built by [Roar], which may not be in 100%
|
102
|
-
compliance.
|
103
|
-
|
104
|
-
Example:
|
105
|
-
|
106
|
-
```js
|
107
|
-
{
|
108
|
-
"id":1,
|
109
|
-
"first_name":"Foo",
|
110
|
-
"last_name":"Bar",
|
111
|
-
"_links":{
|
112
|
-
"self":{"href":"/order/1"},
|
113
|
-
"next":{"href":"/order/2"}
|
114
|
-
}
|
115
|
-
}
|
116
|
-
```
|
117
|
-
|
118
|
-
The problem here is that the entire response really should be wrapped in
|
119
|
-
`"_embedded"` and `"order"` keys.
|
120
|
-
|
121
|
-
So until that is fixed, Frenetic will continue to be pig headed and continue
|
122
|
-
to do the "wrong" thing.
|
123
98
|
|
124
99
|
## Installation
|
125
100
|
|
@@ -157,6 +132,33 @@ MyAPI = Frenetic.new(
|
|
157
132
|
)
|
158
133
|
```
|
159
134
|
|
135
|
+
Symbol- or string-based keys work equally well.
|
136
|
+
|
137
|
+
#### Sending API Keys
|
138
|
+
|
139
|
+
If the API you are consuming requires an API Key, you can provide that in the
|
140
|
+
config hash:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
Frenetic.new( url:'https://example.org', api_key:'abcde12345' )
|
144
|
+
```
|
145
|
+
|
146
|
+
The value will be sent as the `:username` portion of the HTTP
|
147
|
+
Basic Authentication header.
|
148
|
+
|
149
|
+
#### Sending API Keys with an App ID
|
150
|
+
|
151
|
+
If the API requires both an App ID or access token in addition to an API Key,
|
152
|
+
you can provide that in the config hash as well:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
Frenetic.new( url:'https://example.org', app_id:'abcde12345', api_key:'mysecret' )
|
156
|
+
```
|
157
|
+
|
158
|
+
The App ID will be sent as the `:username` and the API Key will be sent as the
|
159
|
+
password portion of the HTTP Basic Authentication header.
|
160
|
+
|
161
|
+
|
160
162
|
|
161
163
|
### Response Caching
|
162
164
|
|
@@ -180,6 +182,20 @@ supports can be added to the Hash.
|
|
180
182
|
|
181
183
|
|
182
184
|
|
185
|
+
# Middlware
|
186
|
+
|
187
|
+
Frenetic supports anything that Faraday does. You may specify additional
|
188
|
+
middleware with the `use` method:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
Frenetic.new( url:'http://example.org' ) do |config|
|
192
|
+
config.use :instrumentation
|
193
|
+
config.use MyMiddleware, { foo:123 }
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
|
198
|
+
|
183
199
|
### Making Requests
|
184
200
|
|
185
201
|
Once you have created a client instance, you are free to use it however you'd
|
data/frenetic.gemspec
CHANGED
@@ -17,13 +17,12 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_dependency 'faraday', '~> 0.8.1'
|
19
19
|
gem.add_dependency 'faraday_middleware', '~> 0.9.0'
|
20
|
+
gem.add_dependency 'activesupport', '>= 2'
|
20
21
|
gem.add_dependency 'rack-cache', '~> 1.1'
|
21
|
-
gem.add_dependency 'addressable', '~> 2.
|
22
|
+
gem.add_dependency 'addressable', '~> 2.2'
|
22
23
|
gem.add_dependency 'patron', '~> 0.4.18'
|
23
24
|
|
24
|
-
gem.add_development_dependency '
|
25
|
-
gem.add_development_dependency '
|
26
|
-
gem.add_development_dependency '
|
27
|
-
gem.add_development_dependency 'webmock', '~> 1.8.10'
|
28
|
-
gem.add_development_dependency 'vcr', '~> 2.2.5'
|
25
|
+
gem.add_development_dependency 'rspec', '~> 2.12.0'
|
26
|
+
gem.add_development_dependency 'webmock', '~> 1.9.0'
|
27
|
+
gem.add_development_dependency 'vcr', '~> 2.4.0'
|
29
28
|
end
|
data/lib/frenetic.rb
CHANGED
@@ -10,9 +10,10 @@ require "frenetic/resource"
|
|
10
10
|
require "frenetic/version"
|
11
11
|
|
12
12
|
class Frenetic
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Error = Class.new(StandardError)
|
14
|
+
ConfigurationError = Class.new(Error)
|
15
|
+
MissingAPIReference = Class.new(Error)
|
16
|
+
InvalidAPIDescription = Class.new(Error)
|
16
17
|
|
17
18
|
extend Forwardable
|
18
19
|
def_delegators :@connection, :get, :put, :post, :delete
|
@@ -25,17 +26,20 @@ class Frenetic
|
|
25
26
|
|
26
27
|
yield config if block_given?
|
27
28
|
|
28
|
-
api_url = Addressable::URI.parse( config
|
29
|
+
api_url = Addressable::URI.parse( config.url )
|
29
30
|
@root_url = api_url.path
|
30
31
|
|
31
|
-
@connection = Faraday.new( config ) do |builder|
|
32
|
+
@connection = Faraday.new( config.to_hash ) do |builder|
|
32
33
|
builder.use HalJson
|
33
|
-
builder.request :basic_auth, config[:username], config[:password]
|
34
34
|
|
35
|
-
|
35
|
+
config.middleware.each { |mw| builder.use(*mw) }
|
36
|
+
|
37
|
+
builder.request :basic_auth, config.username, config.password
|
38
|
+
|
39
|
+
builder.response :logger if config.response[:use_logger]
|
36
40
|
|
37
|
-
if config
|
38
|
-
builder.use FaradayMiddleware::RackCompatible, Rack::Cache::Context, config
|
41
|
+
if config.cache.present?
|
42
|
+
builder.use FaradayMiddleware::RackCompatible, Rack::Cache::Context, config.cache
|
39
43
|
end
|
40
44
|
|
41
45
|
builder.adapter :patron
|
@@ -1,98 +1,100 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'active_support/core_ext/hash/keys'
|
4
|
+
require 'active_support/core_ext/hash/deep_merge'
|
2
5
|
|
3
6
|
class Frenetic
|
4
|
-
class Configuration
|
7
|
+
class Configuration
|
8
|
+
|
9
|
+
@@defaults = {
|
10
|
+
cache: nil,
|
11
|
+
url: nil,
|
12
|
+
username: nil,
|
13
|
+
password: nil,
|
14
|
+
headers: {
|
15
|
+
accept: 'application/hal+json'
|
16
|
+
},
|
17
|
+
request: {},
|
18
|
+
response: {}
|
19
|
+
}
|
20
|
+
|
21
|
+
attr_accessor :cache, :url, :username, :password
|
22
|
+
attr_accessor :headers, :request, :response, :middleware
|
23
|
+
|
24
|
+
def initialize( config = {} )
|
25
|
+
config = @@defaults.deep_merge( config.symbolize_keys )
|
26
|
+
|
27
|
+
map_api_key_to_username config
|
28
|
+
append_user_agent config
|
29
|
+
filter_cache_headers config
|
30
|
+
|
31
|
+
config.each do |k, v|
|
32
|
+
v.symbolize_keys! if v.is_a? Hash
|
33
|
+
|
34
|
+
instance_variable_set "@#{k}", v
|
35
|
+
end
|
36
|
+
end
|
5
37
|
|
6
|
-
|
38
|
+
def attributes
|
39
|
+
validate!
|
7
40
|
|
8
|
-
|
9
|
-
|
10
|
-
def initialize( custom_config = {} )
|
11
|
-
config = config_file.merge custom_config
|
12
|
-
config = symbolize_keys config
|
41
|
+
(instance_variables - [:@middleware]).each_with_object({}) do |k, attrs|
|
42
|
+
key = k.to_s.gsub( '@', '' )
|
13
43
|
|
14
|
-
|
15
|
-
config[:headers] ||= {}
|
16
|
-
config[:request] ||= {}
|
17
|
-
config[:response] ||= {}
|
44
|
+
value = instance_variable_get( k )
|
18
45
|
|
19
|
-
|
46
|
+
attrs[key.to_sym] = value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
alias_method :to_hash, :attributes
|
20
50
|
|
21
|
-
|
22
|
-
|
51
|
+
def validate!
|
52
|
+
raise(Frenetic::ConfigurationError, 'No API URL defined!') unless @url.present?
|
23
53
|
|
24
|
-
|
54
|
+
if @cache
|
55
|
+
raise( ConfigurationError, 'No cache :metastore defined!' ) unless @cache[:metastore].present?
|
56
|
+
raise( ConfigurationError, "No cache :entitystore defined!" ) unless @cache[:entitystore].present?
|
57
|
+
end
|
58
|
+
end
|
25
59
|
|
26
|
-
|
27
|
-
|
60
|
+
def middleware
|
61
|
+
@middleware ||= []
|
62
|
+
end
|
28
63
|
|
29
|
-
|
64
|
+
def use( *args )
|
65
|
+
middleware << args
|
30
66
|
end
|
31
67
|
|
32
68
|
private
|
33
69
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
if self[:headers][:user_agent]
|
38
|
-
self[:headers][:user_agent] << " (#{frenetic_ua})"
|
39
|
-
else
|
40
|
-
self[:headers][:user_agent] = frenetic_ua
|
41
|
-
end
|
70
|
+
def user_agent
|
71
|
+
"Frenetic v#{Frenetic::VERSION}; #{Socket.gethostname}"
|
42
72
|
end
|
43
73
|
|
44
|
-
def
|
45
|
-
if
|
46
|
-
|
47
|
-
|
48
|
-
|
74
|
+
def map_api_key_to_username( config )
|
75
|
+
if config[:api_key]
|
76
|
+
if config[:app_id]
|
77
|
+
config[:username] = config.delete :app_id
|
78
|
+
config[:password] = config.delete :api_key
|
79
|
+
else
|
80
|
+
config[:username] = config.delete :api_key
|
81
|
+
end
|
49
82
|
end
|
50
83
|
end
|
51
84
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
raise( ConfigurationError, "No cache :metastore defined!" ) if self[:cache][:metastore].to_s == ""
|
58
|
-
raise( ConfigurationError, "No cache :entitystore defined!" ) if self[:cache][:entitystore].to_s == ""
|
59
|
-
raise( ConfigurationError, "Required cache header filters are missing!" ) if missing_required_headers?
|
85
|
+
def append_user_agent( config )
|
86
|
+
if config[:headers][:user_agent]
|
87
|
+
config[:headers][:user_agent] << " (#{user_agent})"
|
88
|
+
else
|
89
|
+
config[:headers][:user_agent] = user_agent
|
60
90
|
end
|
61
91
|
end
|
62
92
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
header_set = self[:cache][:ignore_headers]
|
67
|
-
custom_headers = header_set - %w[Set-Cookie X-Content-Digest]
|
68
|
-
|
69
|
-
header_set == custom_headers
|
70
|
-
end
|
71
|
-
|
72
|
-
# TODO: Is this even being used?
|
73
|
-
def config_file
|
74
|
-
path = File.join 'config/frenetic.yml'
|
75
|
-
config = YAML.load_file( path )
|
76
|
-
env = ENV['RAILS_ENV'] || ENV['RACK_ENV']
|
93
|
+
def filter_cache_headers( config )
|
94
|
+
if config[:cache]
|
95
|
+
ignore_headers = config[:cache][:ignore_headers] || []
|
77
96
|
|
78
|
-
|
79
|
-
rescue Errno::ENOENT, NoMethodError
|
80
|
-
{}
|
81
|
-
end
|
82
|
-
|
83
|
-
def symbolize_keys( arg )
|
84
|
-
case arg
|
85
|
-
when Array
|
86
|
-
arg.map { |elem| symbolize_keys elem }
|
87
|
-
when Hash
|
88
|
-
Hash[
|
89
|
-
arg.map { |key, value|
|
90
|
-
k = key.is_a?(String) ? key.to_sym : key
|
91
|
-
v = symbolize_keys value
|
92
|
-
[k,v]
|
93
|
-
}]
|
94
|
-
else
|
95
|
-
arg
|
97
|
+
config[:cache][:ignore_headers] = (ignore_headers + %w[Set-Cookie X-Content-Digest]).uniq
|
96
98
|
end
|
97
99
|
end
|
98
100
|
|
data/lib/frenetic/version.rb
CHANGED
@@ -1,120 +1,187 @@
|
|
1
1
|
describe Frenetic::Configuration do
|
2
|
-
let(:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
'accept' => content_type,
|
9
|
-
},
|
10
|
-
'response' => {
|
11
|
-
'use_logger' => true
|
12
|
-
},
|
13
|
-
'request' => {
|
14
|
-
'timeout' => 10000
|
15
|
-
}
|
16
|
-
}
|
2
|
+
let(:config) { { url:'http://example.org' } }
|
3
|
+
|
4
|
+
let(:cache_cfg) do
|
5
|
+
{
|
6
|
+
metastore: 'foo',
|
7
|
+
entitystore: 'bar'
|
17
8
|
}
|
18
|
-
|
19
|
-
let(:config) { Frenetic::Configuration.new( unknown: :option ) }
|
9
|
+
end
|
20
10
|
|
21
|
-
|
11
|
+
let(:instance) { described_class.new( config ) }
|
22
12
|
|
23
|
-
|
24
|
-
include FakeFS::SpecHelpers
|
13
|
+
subject { instance }
|
25
14
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
15
|
+
it { should respond_to(:cache) }
|
16
|
+
it { should respond_to(:url) }
|
17
|
+
it { should respond_to(:username) }
|
18
|
+
it { should respond_to(:password) }
|
19
|
+
it { should respond_to(:headers) }
|
20
|
+
it { should respond_to(:request) }
|
21
|
+
it { should respond_to(:response) }
|
22
|
+
it { should respond_to(:middleware) }
|
23
|
+
|
24
|
+
describe '#attributes' do
|
25
|
+
before { instance.use 'MyMiddleware' }
|
26
|
+
|
27
|
+
subject { instance.attributes }
|
28
|
+
|
29
|
+
it { should include(:cache) }
|
30
|
+
it { should include(:url) }
|
31
|
+
it { should include(:username) }
|
32
|
+
it { should include(:password) }
|
33
|
+
it { should include(:headers) }
|
34
|
+
it { should include(:request) }
|
35
|
+
it { should include(:response) }
|
36
|
+
it { should_not include(:middleware) }
|
37
|
+
|
38
|
+
it 'should validate the configuration' do
|
39
|
+
instance.should_receive :validate!
|
33
40
|
|
34
|
-
|
35
|
-
|
41
|
+
subject
|
42
|
+
end
|
36
43
|
|
37
|
-
|
44
|
+
context 'with string keys' do
|
45
|
+
let(:config) { {'url' => 'https://example.org'} }
|
38
46
|
|
39
|
-
it
|
40
|
-
subject[:
|
47
|
+
it 'should symbolize the keys' do
|
48
|
+
subject[:url].should == 'https://example.org'
|
41
49
|
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#headers' do
|
54
|
+
let(:attrs) { instance.headers }
|
42
55
|
|
43
|
-
|
44
|
-
|
56
|
+
context 'Accepts' do
|
57
|
+
subject { attrs[:accept] }
|
58
|
+
|
59
|
+
it { should == 'application/hal+json' }
|
60
|
+
|
61
|
+
context 'with other specific headers' do
|
62
|
+
before { config.merge!(headers:{foo:123} )}
|
63
|
+
|
64
|
+
it { should == 'application/hal+json' }
|
45
65
|
end
|
46
66
|
|
47
|
-
|
48
|
-
|
67
|
+
context 'with a custom Accepts header' do
|
68
|
+
before { config.merge!(headers:{'accept' => 'application/vnd.yoursite-v1.hal+json'} )}
|
69
|
+
|
70
|
+
it { should == 'application/vnd.yoursite-v1.hal+json' }
|
49
71
|
end
|
72
|
+
end
|
50
73
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
74
|
+
context 'User-Agent' do
|
75
|
+
subject { attrs[:user_agent] }
|
76
|
+
|
77
|
+
it { should match %r{Frenetic v\d+\.\d+\.\d+; .+\Z} }
|
78
|
+
|
79
|
+
context 'with a custom value' do
|
80
|
+
before { config.merge!( headers:{user_agent:'MyApp'}) }
|
81
|
+
|
82
|
+
it { should match %r{\AMyApp \(Frenetic v\d+\.\d+\.\d+; .+\)\Z} }
|
55
83
|
end
|
56
|
-
|
57
|
-
|
84
|
+
end
|
85
|
+
end
|
58
86
|
|
59
|
-
|
60
|
-
|
61
|
-
|
87
|
+
describe '#cache' do
|
88
|
+
before { config.merge!(cache:cache_cfg) }
|
89
|
+
|
90
|
+
subject { instance.cache }
|
91
|
+
|
92
|
+
it { should include(metastore:'foo') }
|
93
|
+
it { should include(entitystore:'bar') }
|
94
|
+
it { should include(ignore_headers:%w[Set-Cookie X-Content-Digest]) }
|
95
|
+
|
96
|
+
context 'with custom ignore headers' do
|
97
|
+
before { cache_cfg.merge!(ignore_headers:%w{Set-Cookie X-My-Header}) }
|
98
|
+
|
99
|
+
it { should include(ignore_headers:%w[Set-Cookie X-My-Header X-Content-Digest]) }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#username' do
|
104
|
+
subject { instance.username }
|
105
|
+
|
106
|
+
before { config.merge!(api_key:'api_key') }
|
107
|
+
|
108
|
+
it { should == 'api_key' }
|
109
|
+
|
110
|
+
context 'and an App ID' do
|
111
|
+
before { config.merge!(app_id:'app_id') }
|
112
|
+
|
113
|
+
it { should == 'app_id' }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#password' do
|
118
|
+
subject { instance.password }
|
119
|
+
|
120
|
+
before { config.merge!(api_key:'api_key') }
|
121
|
+
|
122
|
+
it { should be_nil }
|
123
|
+
|
124
|
+
context 'and an App ID' do
|
125
|
+
before { config.merge!(app_id:'app_id') }
|
126
|
+
|
127
|
+
it { should == 'api_key' }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#initialize' do
|
132
|
+
subject { instance.attributes }
|
133
|
+
|
134
|
+
it { should be_a Hash }
|
135
|
+
it { should_not be_empty }
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '#validate!' do
|
139
|
+
subject { instance.validate! }
|
140
|
+
|
141
|
+
shared_examples_for 'a misconfigured instance' do
|
142
|
+
it 'by raising an error when empty' do
|
143
|
+
expect{ subject }.to raise_error Frenetic::ConfigurationError
|
62
144
|
end
|
63
145
|
end
|
64
146
|
|
65
|
-
context
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
147
|
+
context ':url' do
|
148
|
+
before { config.delete :url }
|
149
|
+
|
150
|
+
it_should_behave_like 'a misconfigured instance'
|
151
|
+
end
|
152
|
+
|
153
|
+
context ':cache' do
|
154
|
+
context 'with a missing :metastore' do
|
155
|
+
before { config.merge!(cache:{}) }
|
156
|
+
|
157
|
+
it_should_behave_like 'a misconfigured instance'
|
70
158
|
end
|
71
|
-
context "and passed options" do
|
72
|
-
let(:config) { Frenetic::Configuration.new( 'url' => 'http://example.org' ) }
|
73
159
|
|
74
|
-
|
75
|
-
|
76
|
-
it "should set an Accepts request header" do
|
77
|
-
subject[:headers].should include(:accept => 'application/hal+json')
|
78
|
-
end
|
79
|
-
it "should set a User Agent request header" do
|
80
|
-
subject[:headers][:user_agent].should =~ %r{Frenetic v.+; \S+$}
|
81
|
-
end
|
160
|
+
context 'with a missing :entitystore' do
|
161
|
+
before { config.merge!(cache:{metastore:'store'}) }
|
82
162
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
)
|
92
|
-
end
|
93
|
-
|
94
|
-
it "should raise a configuration error for a missing :entitystore" do
|
95
|
-
expect {
|
96
|
-
Frenetic::Configuration.new('url' => 'http://example.org', 'cache' => { 'metastore' => 'foo' } )
|
97
|
-
}.to raise_error(
|
98
|
-
Frenetic::Configuration::ConfigurationError, "No cache :entitystore defined!"
|
99
|
-
)
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should raise a configuration error for missing required header filters" do
|
103
|
-
cache_cfg = {
|
104
|
-
'metastore' => 'foo',
|
105
|
-
'entitystore' => 'bar',
|
106
|
-
'ignore_headers' => ['baz'] # `configure_cache` method is skipped to create a bad state
|
107
|
-
}
|
108
|
-
|
109
|
-
expect {
|
110
|
-
Frenetic::Configuration.new('url' => 'http://example.org', 'cache' => cache_cfg )
|
111
|
-
}.to raise_error(
|
112
|
-
Frenetic::Configuration::ConfigurationError, "Required cache header filters are missing!"
|
113
|
-
)
|
114
|
-
end
|
163
|
+
it_should_behave_like 'a misconfigured instance'
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'with no missing properties' do
|
167
|
+
before { config.merge!(cache:{metastore:'mstore',entitystore:'estore'}) }
|
168
|
+
|
169
|
+
it 'should not raise an error' do
|
170
|
+
expect{ subject }.to_not raise_error
|
115
171
|
end
|
116
172
|
end
|
117
173
|
end
|
118
174
|
end
|
119
175
|
|
176
|
+
describe '#use' do
|
177
|
+
before do
|
178
|
+
stub_const 'MyMiddleware', Class.new
|
179
|
+
|
180
|
+
instance.use MyMiddleware, foo:123
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should use the middleware' do
|
184
|
+
subject.middleware.should include [ MyMiddleware, {foo:123} ]
|
185
|
+
end
|
186
|
+
end
|
120
187
|
end
|
@@ -31,8 +31,8 @@ describe Frenetic::HalJson do
|
|
31
31
|
context "with a successful response" do
|
32
32
|
let(:env) do
|
33
33
|
{
|
34
|
-
:
|
35
|
-
:
|
34
|
+
status:200,
|
35
|
+
body: JSON.generate({
|
36
36
|
'_links' => {}
|
37
37
|
})
|
38
38
|
}
|
@@ -50,17 +50,17 @@ describe Frenetic::HalJson do
|
|
50
50
|
subject { hal_json.success?( env ) }
|
51
51
|
|
52
52
|
context "with a 200 OK response" do
|
53
|
-
let(:env) { {:
|
53
|
+
let(:env) { { status:200 } }
|
54
54
|
|
55
55
|
it { should be_true }
|
56
56
|
end
|
57
57
|
context "with a 201 Created response" do
|
58
|
-
let(:env) { {:
|
58
|
+
let(:env) { { status:201 } }
|
59
59
|
|
60
60
|
it { should be_true }
|
61
61
|
end
|
62
62
|
context "with a 204 No Content" do
|
63
|
-
let(:env) { {:
|
63
|
+
let(:env) { { status:204 } }
|
64
64
|
|
65
65
|
it { should be_false }
|
66
66
|
end
|
data/spec/lib/frenetic_spec.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
describe Frenetic do
|
2
|
-
let(:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
let(:config) do
|
3
|
+
{
|
4
|
+
url: 'http://example.org:5447/api',
|
5
|
+
api_key: '1234567890',
|
6
|
+
version: 'v1',
|
7
|
+
response: {}
|
8
|
+
}
|
9
|
+
end
|
10
10
|
|
11
|
-
|
11
|
+
let(:client) { described_class.new(config) }
|
12
12
|
|
13
13
|
subject { client }
|
14
14
|
|
@@ -24,7 +24,7 @@ describe Frenetic do
|
|
24
24
|
|
25
25
|
it 'should accept a configuration block' do
|
26
26
|
described_class.new( config ) do |cfg|
|
27
|
-
cfg.should
|
27
|
+
cfg.should be_a described_class::Configuration
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -50,6 +50,22 @@ describe Frenetic do
|
|
50
50
|
|
51
51
|
it { should include 'Faraday::Response::Logger' }
|
52
52
|
end
|
53
|
+
|
54
|
+
describe 'middleware initialization' do
|
55
|
+
before { stub_const 'MyMiddleware', Class.new }
|
56
|
+
|
57
|
+
let(:client) do
|
58
|
+
described_class.new(config) do |cfg|
|
59
|
+
cfg.use MyMiddleware, foo:123
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
subject { connection.builder.handlers }
|
64
|
+
|
65
|
+
it 'should add the middleware to the connection' do
|
66
|
+
subject.should include MyMiddleware
|
67
|
+
end
|
68
|
+
end
|
53
69
|
end
|
54
70
|
|
55
71
|
describe "#description" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,29 +1,17 @@
|
|
1
|
-
require 'spork'
|
2
1
|
ENV['RAILS_ENV'] ||= 'test'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
require 'rspec'
|
4
|
+
require 'awesome_print'
|
5
|
+
require 'vcr'
|
6
|
+
require 'frenetic'
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
RSpec.configure do |config|
|
15
|
-
config.filter_run focus:true
|
16
|
-
config.run_all_when_everything_filtered = true
|
17
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
18
|
-
end
|
19
|
-
|
20
|
-
VCR.configure do |c|
|
21
|
-
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
22
|
-
c.hook_into :webmock
|
23
|
-
end
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.filter_run focus:true
|
10
|
+
config.run_all_when_everything_filtered = true
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
24
12
|
end
|
25
13
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
14
|
+
VCR.configure do |c|
|
15
|
+
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
16
|
+
c.hook_into :webmock
|
17
|
+
end
|
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.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
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:
|
12
|
+
date: 2013-01-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
@@ -44,29 +44,29 @@ dependencies:
|
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 0.9.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: activesupport
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - ! '>='
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '2'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
63
|
+
name: rack-cache
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
69
|
+
version: '1.1'
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,15 +74,15 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
77
|
+
version: '1.1'
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
79
|
+
name: addressable
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
81
81
|
none: false
|
82
82
|
requirements:
|
83
83
|
- - ~>
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version:
|
85
|
+
version: '2.2'
|
86
86
|
type: :runtime
|
87
87
|
prerelease: false
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -90,39 +90,23 @@ dependencies:
|
|
90
90
|
requirements:
|
91
91
|
- - ~>
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
93
|
+
version: '2.2'
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
|
-
requirements:
|
99
|
-
- - ~>
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: 1.2.0
|
102
|
-
type: :development
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ~>
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: 1.2.0
|
110
|
-
- !ruby/object:Gem::Dependency
|
111
|
-
name: guard-rspec
|
95
|
+
name: patron
|
112
96
|
requirement: !ruby/object:Gem::Requirement
|
113
97
|
none: false
|
114
98
|
requirements:
|
115
99
|
- - ~>
|
116
100
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
118
|
-
type: :
|
101
|
+
version: 0.4.18
|
102
|
+
type: :runtime
|
119
103
|
prerelease: false
|
120
104
|
version_requirements: !ruby/object:Gem::Requirement
|
121
105
|
none: false
|
122
106
|
requirements:
|
123
107
|
- - ~>
|
124
108
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
109
|
+
version: 0.4.18
|
126
110
|
- !ruby/object:Gem::Dependency
|
127
111
|
name: rspec
|
128
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,7 +114,7 @@ dependencies:
|
|
130
114
|
requirements:
|
131
115
|
- - ~>
|
132
116
|
- !ruby/object:Gem::Version
|
133
|
-
version: 2.
|
117
|
+
version: 2.12.0
|
134
118
|
type: :development
|
135
119
|
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -138,7 +122,7 @@ dependencies:
|
|
138
122
|
requirements:
|
139
123
|
- - ~>
|
140
124
|
- !ruby/object:Gem::Version
|
141
|
-
version: 2.
|
125
|
+
version: 2.12.0
|
142
126
|
- !ruby/object:Gem::Dependency
|
143
127
|
name: webmock
|
144
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,7 +130,7 @@ dependencies:
|
|
146
130
|
requirements:
|
147
131
|
- - ~>
|
148
132
|
- !ruby/object:Gem::Version
|
149
|
-
version: 1.
|
133
|
+
version: 1.9.0
|
150
134
|
type: :development
|
151
135
|
prerelease: false
|
152
136
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -154,7 +138,7 @@ dependencies:
|
|
154
138
|
requirements:
|
155
139
|
- - ~>
|
156
140
|
- !ruby/object:Gem::Version
|
157
|
-
version: 1.
|
141
|
+
version: 1.9.0
|
158
142
|
- !ruby/object:Gem::Dependency
|
159
143
|
name: vcr
|
160
144
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,7 +146,7 @@ dependencies:
|
|
162
146
|
requirements:
|
163
147
|
- - ~>
|
164
148
|
- !ruby/object:Gem::Version
|
165
|
-
version: 2.
|
149
|
+
version: 2.4.0
|
166
150
|
type: :development
|
167
151
|
prerelease: false
|
168
152
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -170,7 +154,7 @@ dependencies:
|
|
170
154
|
requirements:
|
171
155
|
- - ~>
|
172
156
|
- !ruby/object:Gem::Version
|
173
|
-
version: 2.
|
157
|
+
version: 2.4.0
|
174
158
|
description: An opinionated Ruby-based Hypermedia API client.
|
175
159
|
email:
|
176
160
|
- dlindahl@customink.com
|
@@ -182,7 +166,6 @@ files:
|
|
182
166
|
- .rvmrc
|
183
167
|
- .travis.yml
|
184
168
|
- Gemfile
|
185
|
-
- Guardfile
|
186
169
|
- LICENSE
|
187
170
|
- README.md
|
188
171
|
- Rakefile
|
data/Guardfile
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# More info at https://github.com/guard/guard#readme
|
2
|
-
|
3
|
-
guard 'rspec', :notification => false do
|
4
|
-
watch(%r{^spec/.+_spec\.rb$})
|
5
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
6
|
-
watch('spec/spec_helper.rb') { "spec" }
|
7
|
-
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
8
|
-
end
|
9
|
-
|
10
|
-
guard 'spork', :rspec_env => { 'RAILS_ENV' => 'test' } do
|
11
|
-
watch('config/environment.rb')
|
12
|
-
watch('Gemfile')
|
13
|
-
watch('Gemfile.lock')
|
14
|
-
watch('spec/spec_helper.rb') { :rspec }
|
15
|
-
end
|