bootic_client 0.0.7 → 0.0.8
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 +4 -4
- data/README.md +31 -0
- data/lib/bootic_client/client.rb +12 -13
- data/lib/bootic_client/entity.rb +2 -1
- data/lib/bootic_client/errors.rb +4 -5
- data/lib/bootic_client/relation.rb +5 -1
- data/lib/bootic_client/strategies/authorized.rb +4 -4
- data/lib/bootic_client/strategies/basic_auth.rb +27 -0
- data/lib/bootic_client/strategies/client_credentials.rb +4 -3
- data/lib/bootic_client/strategies/oauth2_strategy.rb +61 -0
- data/lib/bootic_client/strategies/strategy.rb +36 -29
- data/lib/bootic_client/version.rb +1 -1
- data/spec/authorized_strategy_spec.rb +2 -2
- data/spec/basic_auth_strategy_spec.rb +71 -0
- data/spec/client_credentials_strategy_spec.rb +2 -2
- data/spec/client_spec.rb +9 -17
- data/spec/entity_spec.rb +9 -2
- data/spec/relation_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ca933989403d66243755d735272c645458c5575
|
4
|
+
data.tar.gz: bdbdb38d2b417c05634953ffb48395d3f2971301
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c76703781e56dc5ee87eb065355fb8de38daf775f5fc38989e626985abe0a12e3800d94334482405081281ffbdbae295c8e9a66915e6e1f6b2c3f1f0b977b0f4
|
7
|
+
data.tar.gz: b5eac3f968ba339d877a798929c123c25beea50eae2f83e04078935ccbce24b97e57833ad398593d97d1dfbe057619bcc4286a0f5199cf2918968a0fd80c24f8
|
data/README.md
CHANGED
@@ -115,6 +115,20 @@ client = BooticClient.client(:client_credentials, scope: 'admin', access_token:
|
|
115
115
|
end
|
116
116
|
```
|
117
117
|
|
118
|
+
### 3. Basic Auth
|
119
|
+
|
120
|
+
This strategy uses a `username` and `password` against APIs supporting HTTP's Basic Authentication scheme.
|
121
|
+
|
122
|
+
The official Bootic API only supports OAuth2 tokens, but this allows the client to be used against internal APIs or stub APIs on development.
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
client = BooticClient.client(:basic_auth, username: 'foo', password: 'bar')
|
126
|
+
|
127
|
+
root = client.root # etc
|
128
|
+
```
|
129
|
+
|
130
|
+
NOTE: `username` and `password` have nothing to do with your Bootic administrative credentials, and will be up to API maintainers to define.
|
131
|
+
|
118
132
|
## Non GET links
|
119
133
|
|
120
134
|
Most resource links lead to `GET` resources, but some will expect `POST`, `PUT`, `DELETE` or others.
|
@@ -186,6 +200,23 @@ BooticClient.configure do |c|
|
|
186
200
|
end
|
187
201
|
```
|
188
202
|
|
203
|
+
## Pre-loaded or custom root resources
|
204
|
+
|
205
|
+
This client is designed to always navigate APIs starting from the root endpoint (the Hypermedia approach), but it's also possible to skip the root and start from a locally defined resource definition.
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
messaging_api = client.from_hash(
|
209
|
+
"_links" => {
|
210
|
+
"send_message" => {"href" => 'https://some.api.com/messages', "method" => 'post'},
|
211
|
+
"delete_message" => {"href" => 'https://some.api.com/messages/:id', "method" => 'delete', "templated" => true}
|
212
|
+
}
|
213
|
+
)
|
214
|
+
|
215
|
+
new_message = messaging_api.send_message(title: 'This is a new message')
|
216
|
+
|
217
|
+
messaging_api.delete_message(id: new_message.id)
|
218
|
+
```
|
219
|
+
|
189
220
|
## Contributing
|
190
221
|
|
191
222
|
1. Fork it
|
data/lib/bootic_client/client.rb
CHANGED
@@ -15,7 +15,6 @@ module BooticClient
|
|
15
15
|
|
16
16
|
def initialize(options = {}, &block)
|
17
17
|
@options = {
|
18
|
-
access_token: nil,
|
19
18
|
logging: false
|
20
19
|
}.merge(options.dup)
|
21
20
|
|
@@ -24,32 +23,38 @@ module BooticClient
|
|
24
23
|
conn &block if block_given?
|
25
24
|
end
|
26
25
|
|
27
|
-
def get(href, query = {})
|
26
|
+
def get(href, query = {}, headers = {})
|
28
27
|
validated_request!(:get, href) do |req|
|
28
|
+
req.headers.update headers
|
29
29
|
req.params.update(query)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def post(href, payload = {})
|
33
|
+
def post(href, payload = {}, headers = {})
|
34
34
|
validated_request!(:post, href) do |req|
|
35
|
+
req.headers.update headers
|
35
36
|
req.body = JSON.dump(payload)
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
39
|
-
def put(href, payload = {})
|
40
|
+
def put(href, payload = {}, headers = {})
|
40
41
|
validated_request!(:put, href) do |req|
|
42
|
+
req.headers.update headers
|
41
43
|
req.body = JSON.dump(payload)
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
45
|
-
def patch(href, payload = {})
|
47
|
+
def patch(href, payload = {}, headers = {})
|
46
48
|
validated_request!(:patch, href) do |req|
|
49
|
+
req.headers.update headers
|
47
50
|
req.body = JSON.dump(payload)
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
51
|
-
def delete(href,
|
52
|
-
validated_request!(:delete, href)
|
54
|
+
def delete(href, headers = {})
|
55
|
+
validated_request!(:delete, href) do |req|
|
56
|
+
req.headers.update headers
|
57
|
+
end
|
53
58
|
end
|
54
59
|
|
55
60
|
protected
|
@@ -69,7 +74,6 @@ module BooticClient
|
|
69
74
|
|
70
75
|
def request_headers
|
71
76
|
{
|
72
|
-
'Authorization' => "Bearer #{options[:access_token]}",
|
73
77
|
'User-Agent' => USER_AGENT,
|
74
78
|
'Accept' => JSON_MIME,
|
75
79
|
'Content-Type' => JSON_MIME
|
@@ -77,7 +81,6 @@ module BooticClient
|
|
77
81
|
end
|
78
82
|
|
79
83
|
def validated_request!(verb, href, &block)
|
80
|
-
validate_request!
|
81
84
|
resp = conn.send(verb) do |req|
|
82
85
|
req.url href
|
83
86
|
req.headers.update request_headers
|
@@ -88,10 +91,6 @@ module BooticClient
|
|
88
91
|
resp
|
89
92
|
end
|
90
93
|
|
91
|
-
def validate_request!
|
92
|
-
raise NoAccessTokenError, "Missing access token" unless options[:access_token]
|
93
|
-
end
|
94
|
-
|
95
94
|
def raise_if_invalid!(resp)
|
96
95
|
raise ServerError, "Server Error" if resp.status > 499
|
97
96
|
raise NotFoundError, "Not Found" if resp.status == 404
|
data/lib/bootic_client/entity.rb
CHANGED
data/lib/bootic_client/errors.rb
CHANGED
@@ -2,8 +2,7 @@ module BooticClient
|
|
2
2
|
class TransportError < StandardError; end
|
3
3
|
class ServerError < TransportError; end
|
4
4
|
class NotFoundError < ServerError; end
|
5
|
-
class
|
6
|
-
class UnauthorizedError <
|
7
|
-
class AccessForbiddenError <
|
8
|
-
|
9
|
-
end
|
5
|
+
class AuthorizationError < ServerError; end
|
6
|
+
class UnauthorizedError < AuthorizationError; end
|
7
|
+
class AccessForbiddenError < AuthorizationError; end
|
8
|
+
end
|
@@ -45,7 +45,11 @@ module BooticClient
|
|
45
45
|
|
46
46
|
def run(opts = {})
|
47
47
|
if templated?
|
48
|
-
|
48
|
+
uri_vars = uri.variables
|
49
|
+
payload = opts.each_with_object({}) do |(k,v),memo|
|
50
|
+
memo[k] = v unless uri_vars.include?(k.to_s)
|
51
|
+
end
|
52
|
+
client.request_and_wrap transport_method.to_sym, uri.expand(opts), wrapper_class, payload
|
49
53
|
else
|
50
54
|
client.request_and_wrap transport_method.to_sym, href, wrapper_class, opts
|
51
55
|
end
|
@@ -1,13 +1,13 @@
|
|
1
|
-
require 'bootic_client/strategies/
|
1
|
+
require 'bootic_client/strategies/oauth2_strategy'
|
2
2
|
|
3
3
|
module BooticClient
|
4
4
|
module Strategies
|
5
5
|
|
6
|
-
class Authorized <
|
6
|
+
class Authorized < Oauth2Strategy
|
7
7
|
protected
|
8
8
|
|
9
|
-
def validate!
|
10
|
-
raise "options MUST include access_token" unless options[:access_token]
|
9
|
+
def validate!
|
10
|
+
raise ArgumentError, "options MUST include access_token" unless options[:access_token]
|
11
11
|
end
|
12
12
|
|
13
13
|
def get_token
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'bootic_client/strategies/strategy'
|
2
|
+
|
3
|
+
module BooticClient
|
4
|
+
module Strategies
|
5
|
+
class BasicAuth < Strategy
|
6
|
+
|
7
|
+
def inspect
|
8
|
+
%(#<#{self.class.name} root: #{config.api_root} username: #{options[:username]}>)
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def validate!
|
14
|
+
raise ArgumentError, "options MUST include username" unless options[:username]
|
15
|
+
raise ArgumentError, "options MUST include password" unless options[:password]
|
16
|
+
end
|
17
|
+
|
18
|
+
def client
|
19
|
+
@client ||= Client.new(options) do |c|
|
20
|
+
c.request :basic_auth, options[:username], options[:password]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
strategies[:basic_auth] = Strategies::BasicAuth
|
27
|
+
end
|
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'bootic_client/strategies/
|
1
|
+
require 'bootic_client/strategies/oauth2_strategy'
|
2
2
|
|
3
3
|
module BooticClient
|
4
4
|
module Strategies
|
5
5
|
|
6
|
-
class ClientCredentials <
|
6
|
+
class ClientCredentials < Oauth2Strategy
|
7
7
|
protected
|
8
|
+
|
8
9
|
def get_token
|
9
10
|
opts = {}
|
10
11
|
opts['scope'] = options.delete(:scope) if options[:scope]
|
@@ -16,4 +17,4 @@ module BooticClient
|
|
16
17
|
end
|
17
18
|
|
18
19
|
strategies[:client_credentials] = Strategies::ClientCredentials
|
19
|
-
end
|
20
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
require 'bootic_client/strategies/strategy'
|
3
|
+
|
4
|
+
module BooticClient
|
5
|
+
module Strategies
|
6
|
+
|
7
|
+
class Oauth2Strategy < Strategy
|
8
|
+
|
9
|
+
def inspect
|
10
|
+
%(#<#{self.class.name} cid: #{config.client_id} root: #{config.api_root} auth: #{config.auth_host}>)
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def validate!
|
16
|
+
raise ArgumentError, "MUST include client_id" unless config.client_id
|
17
|
+
raise ArgumentError, "MUST include client_secret" unless config.client_secret
|
18
|
+
raise ArgumentError, "MUST include api_root" unless config.api_root
|
19
|
+
end
|
20
|
+
|
21
|
+
def pre_flight
|
22
|
+
update_token! unless options[:access_token]
|
23
|
+
end
|
24
|
+
|
25
|
+
def request_headers
|
26
|
+
{
|
27
|
+
'Authorization' => "Bearer #{options[:access_token]}"
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def retryable(&block)
|
32
|
+
begin
|
33
|
+
yield
|
34
|
+
rescue AuthorizationError => e
|
35
|
+
update_token!
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_token!
|
41
|
+
new_token = get_token
|
42
|
+
options[:access_token] = new_token
|
43
|
+
on_new_token.call new_token
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_token
|
47
|
+
raise "Implement this in subclasses"
|
48
|
+
end
|
49
|
+
|
50
|
+
def auth
|
51
|
+
@auth ||= OAuth2::Client.new(
|
52
|
+
config.client_id,
|
53
|
+
config.client_secret,
|
54
|
+
site: config.auth_host
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'oauth2'
|
2
|
-
|
3
1
|
module BooticClient
|
4
2
|
module Strategies
|
5
3
|
class Strategy
|
@@ -8,11 +6,7 @@ module BooticClient
|
|
8
6
|
|
9
7
|
def initialize(config, client_opts = {}, &on_new_token)
|
10
8
|
@config, @options, @on_new_token = config, client_opts, (on_new_token || Proc.new{})
|
11
|
-
|
12
|
-
raise "MUST include client_secret" unless config.client_secret
|
13
|
-
raise "MUST include api_root" unless config.api_root
|
14
|
-
validate! @options
|
15
|
-
reset!
|
9
|
+
validate!
|
16
10
|
end
|
17
11
|
|
18
12
|
def root
|
@@ -24,43 +18,56 @@ module BooticClient
|
|
24
18
|
end
|
25
19
|
|
26
20
|
def request_and_wrap(request_method, href, wrapper_class, payload = {})
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
new_token = get_token
|
31
|
-
options[:access_token] = new_token
|
32
|
-
reset!
|
33
|
-
on_new_token.call new_token
|
34
|
-
wrapper_class.new client.send(request_method, href, payload).body, self
|
21
|
+
pre_flight
|
22
|
+
retryable do
|
23
|
+
wrapper_class.new client.send(request_method, href, payload, request_headers).body, self
|
35
24
|
end
|
36
25
|
end
|
37
26
|
|
38
27
|
def inspect
|
39
|
-
%(#<#{self.class.name}
|
28
|
+
%(#<#{self.class.name} root: #{config.api_root}>)
|
40
29
|
end
|
41
30
|
|
42
31
|
protected
|
43
32
|
|
44
|
-
attr_reader :config, :on_new_token
|
33
|
+
attr_reader :config, :on_new_token
|
34
|
+
|
35
|
+
def validate!
|
36
|
+
# Overwrite in sub classes
|
37
|
+
# to raise ArgumentErrors on
|
38
|
+
# missing config attributes of options values.
|
39
|
+
end
|
45
40
|
|
46
|
-
def
|
47
|
-
|
41
|
+
def pre_flight
|
42
|
+
# Runs before every request
|
43
|
+
# Overwrite in sub classes to run checks
|
44
|
+
# (ie authorisation status, missing options, expired token refresh)
|
48
45
|
end
|
49
46
|
|
50
|
-
|
51
|
-
|
47
|
+
# Noop.
|
48
|
+
# Overwrite in sub classes to implement retryable requests.
|
49
|
+
# Example:
|
50
|
+
#
|
51
|
+
# def retryable(&block)
|
52
|
+
# begin
|
53
|
+
# yield # issue request
|
54
|
+
# rescue SomeException => e
|
55
|
+
# fix_cause_of_exception
|
56
|
+
# yield # try again
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
def retryable(&block)
|
61
|
+
yield
|
52
62
|
end
|
53
63
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
config.client_secret,
|
58
|
-
site: config.auth_host
|
59
|
-
)
|
64
|
+
# Noop. Merge these headers into every request.
|
65
|
+
def request_headers
|
66
|
+
{}
|
60
67
|
end
|
61
68
|
|
62
|
-
def
|
63
|
-
@client
|
69
|
+
def client
|
70
|
+
@client ||= Client.new(options)
|
64
71
|
end
|
65
72
|
end
|
66
73
|
end
|
@@ -55,7 +55,7 @@ describe 'BooticClient::Strategies::Authorized' do
|
|
55
55
|
it 'raises error' do
|
56
56
|
expect{
|
57
57
|
BooticClient.client(:authorized)
|
58
|
-
}.to raise_error
|
58
|
+
}.to raise_error(ArgumentError)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -63,7 +63,7 @@ describe 'BooticClient::Strategies::Authorized' do
|
|
63
63
|
it 'raises error' do
|
64
64
|
expect{
|
65
65
|
BooticClient.client(:authorized)
|
66
|
-
}.to raise_error
|
66
|
+
}.to raise_error(ArgumentError)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'BooticClient::Strategies::BasicAuth' do
|
4
|
+
require 'webmock/rspec'
|
5
|
+
|
6
|
+
let(:root_data) {
|
7
|
+
{
|
8
|
+
'_links' => {
|
9
|
+
'a_product' => {'href' => 'https://api.bootic.net/v1/products/1'}
|
10
|
+
},
|
11
|
+
'message' => "Hello!"
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
let(:product_data) {
|
16
|
+
{'title' => 'iPhone 6 Plus'}
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:client) { BooticClient.client(:basic_auth, username: 'foo', password: 'bar') }
|
20
|
+
|
21
|
+
describe '#inspect' do
|
22
|
+
it 'is informative' do
|
23
|
+
expect(client.inspect).to eql %(#<BooticClient::Strategies::BasicAuth root: https://api.bootic.net/v1 username: foo>)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with missing credentials' do
|
28
|
+
it 'raises error' do
|
29
|
+
expect{
|
30
|
+
BooticClient.client(:basic_auth)
|
31
|
+
}.to raise_error(ArgumentError)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with invalid BasicAuth credentials' do
|
36
|
+
let!(:root_request) do
|
37
|
+
stub_request(:get, 'https://foo:bar@api.bootic.net/v1')
|
38
|
+
.to_return(status: 401, body: JSON.dump(root_data))
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'raises an Unauthorized error' do
|
42
|
+
expect{ client.root }.to raise_error(BooticClient::UnauthorizedError)
|
43
|
+
expect(root_request).to have_been_requested
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with valid BasicAuth credentials' do
|
48
|
+
let!(:root_request) do
|
49
|
+
stub_request(:get, 'https://foo:bar@api.bootic.net/v1')
|
50
|
+
.to_return(status: 200, body: JSON.dump(root_data))
|
51
|
+
end
|
52
|
+
|
53
|
+
let!(:product_request) do
|
54
|
+
stub_request(:get, 'https://foo:bar@api.bootic.net/v1/products/1')
|
55
|
+
.to_return(status: 200, body: JSON.dump(product_data))
|
56
|
+
end
|
57
|
+
|
58
|
+
let!(:root) { client.root }
|
59
|
+
|
60
|
+
it 'includes Basic Auth credentials in request' do
|
61
|
+
expect(root_request).to have_been_requested
|
62
|
+
expect(root.message).to eql('Hello!')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'follows links as normal, including Basic Auth in every request' do
|
66
|
+
product = root.a_product
|
67
|
+
expect(product_request).to have_been_requested
|
68
|
+
expect(product.title).to eql 'iPhone 6 Plus'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -18,7 +18,7 @@ describe 'BooticClient::Strategies::ClientCredentials' do
|
|
18
18
|
BooticClient.client_id = nil
|
19
19
|
expect{
|
20
20
|
BooticClient.client(:client_credentials, scope: 'admin')
|
21
|
-
}.to raise_error
|
21
|
+
}.to raise_error(ArgumentError)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -33,7 +33,7 @@ describe 'BooticClient::Strategies::ClientCredentials' do
|
|
33
33
|
def stub_api_root(access_token, status, body)
|
34
34
|
stub_request(:get, "https://api.bootic.net/v1").
|
35
35
|
with(headers: {'Accept'=>'application/json', 'Authorization'=>"Bearer #{access_token}"}).
|
36
|
-
to_return(status: status, :
|
36
|
+
to_return(status: status, body: JSON.dump(body))
|
37
37
|
end
|
38
38
|
|
39
39
|
before do
|
data/spec/client_spec.rb
CHANGED
@@ -6,9 +6,9 @@ describe BooticClient::Client do
|
|
6
6
|
|
7
7
|
describe 'valid response' do
|
8
8
|
let(:root_url) { 'https://api.bootic.net/v1' }
|
9
|
-
let(:client) { BooticClient::Client.new
|
9
|
+
let(:client) { BooticClient::Client.new }
|
10
10
|
let(:request_headers) {
|
11
|
-
{'
|
11
|
+
{'Authorization' => "Bearer xxx"}
|
12
12
|
}
|
13
13
|
let(:response_headers) {
|
14
14
|
{
|
@@ -35,7 +35,7 @@ describe BooticClient::Client do
|
|
35
35
|
.to_return(status: 200, body: JSON.dump(root_data), headers: response_headers)
|
36
36
|
end
|
37
37
|
|
38
|
-
let!(:response) { client.get(root_url) }
|
38
|
+
let!(:response) { client.get(root_url, {}, request_headers) }
|
39
39
|
|
40
40
|
it 'returns parsed Faraday response' do
|
41
41
|
expect(response).to be_kind_of(Faraday::Response)
|
@@ -53,7 +53,7 @@ describe BooticClient::Client do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'returns cached response' do
|
56
|
-
r = client.get(root_url)
|
56
|
+
r = client.get(root_url, {}, request_headers)
|
57
57
|
expect(@cached_request).to have_been_requested
|
58
58
|
|
59
59
|
expect(r.status).to eql(200)
|
@@ -71,7 +71,7 @@ describe BooticClient::Client do
|
|
71
71
|
end
|
72
72
|
|
73
73
|
it 'returns cached response' do
|
74
|
-
r = client.get(root_url)
|
74
|
+
r = client.get(root_url, {}, request_headers)
|
75
75
|
expect(@cached_request).to have_been_requested
|
76
76
|
|
77
77
|
expect(r.status).to eql(200)
|
@@ -83,14 +83,6 @@ describe BooticClient::Client do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
context 'errors' do
|
86
|
-
describe 'no access token' do
|
87
|
-
it 'raises error' do
|
88
|
-
expect{
|
89
|
-
BooticClient::Client.new.get(root_url)
|
90
|
-
}.to raise_error(BooticClient::NoAccessTokenError)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
86
|
describe '500 Server error' do
|
95
87
|
before do
|
96
88
|
stub_request(:get, root_url)
|
@@ -156,7 +148,7 @@ describe BooticClient::Client do
|
|
156
148
|
end
|
157
149
|
|
158
150
|
it 'GETs response' do
|
159
|
-
expect(client.get(root_url, foo: 'bar').body['message']).to eql('Hello!')
|
151
|
+
expect(client.get(root_url, {foo: 'bar'}, request_headers).body['message']).to eql('Hello!')
|
160
152
|
end
|
161
153
|
end
|
162
154
|
|
@@ -168,7 +160,7 @@ describe BooticClient::Client do
|
|
168
160
|
end
|
169
161
|
|
170
162
|
it 'POSTs request and parses response' do
|
171
|
-
expect(client.post(root_url, foo: 'bar').body['message']).to eql('Hello!')
|
163
|
+
expect(client.post(root_url, {foo: 'bar'}, request_headers).body['message']).to eql('Hello!')
|
172
164
|
end
|
173
165
|
end
|
174
166
|
|
@@ -181,7 +173,7 @@ describe BooticClient::Client do
|
|
181
173
|
end
|
182
174
|
|
183
175
|
it "#{verb.to_s.upcase}s request and parses response" do
|
184
|
-
expect(client.send(verb, root_url, foo: 'bar').body['message']).to eql('Hello!')
|
176
|
+
expect(client.send(verb, root_url, {foo: 'bar'}, request_headers).body['message']).to eql('Hello!')
|
185
177
|
end
|
186
178
|
end
|
187
179
|
end
|
@@ -194,7 +186,7 @@ describe BooticClient::Client do
|
|
194
186
|
end
|
195
187
|
|
196
188
|
it 'DELETEs request and parses response' do
|
197
|
-
expect(client.send(:delete, root_url).status).to eql(200)
|
189
|
+
expect(client.send(:delete, root_url, request_headers).status).to eql(200)
|
198
190
|
expect(@delete_requst).to have_been_requested
|
199
191
|
end
|
200
192
|
end
|
data/spec/entity_spec.rb
CHANGED
@@ -29,6 +29,7 @@ describe BooticClient::Entity do
|
|
29
29
|
{
|
30
30
|
'title' => 'iPhone 4',
|
31
31
|
'price' => 12345,
|
32
|
+
'published' => false,
|
32
33
|
'_links' => {
|
33
34
|
'self' => {href: '/products/iphone4'},
|
34
35
|
'btc:delete_product' => {'href' => '/products/12345'}
|
@@ -43,6 +44,7 @@ describe BooticClient::Entity do
|
|
43
44
|
{
|
44
45
|
'title' => 'iPhone 5',
|
45
46
|
'price' => 12342,
|
47
|
+
'published' => true,
|
46
48
|
'_links' => {
|
47
49
|
'self' => {href: '/products/iphone5'}
|
48
50
|
},
|
@@ -52,7 +54,7 @@ describe BooticClient::Entity do
|
|
52
54
|
}
|
53
55
|
}
|
54
56
|
}
|
55
|
-
|
57
|
+
|
56
58
|
] # / items
|
57
59
|
}
|
58
60
|
}
|
@@ -118,6 +120,11 @@ describe BooticClient::Entity do
|
|
118
120
|
expect(shop.name).to eql('Acme')
|
119
121
|
end
|
120
122
|
end
|
123
|
+
|
124
|
+
it 'includes FALSE values' do
|
125
|
+
expect(entity.items.first.published).to be false
|
126
|
+
expect(entity.items.last.published).to be true
|
127
|
+
end
|
121
128
|
end #/ embedded entities
|
122
129
|
|
123
130
|
describe 'link relations' do
|
@@ -161,7 +168,7 @@ describe BooticClient::Entity do
|
|
161
168
|
end
|
162
169
|
|
163
170
|
it 'takes optional URI parameters' do
|
164
|
-
expect(client).to receive(:request_and_wrap).with(:get, '/search?q=foo', BooticClient::Entity, {
|
171
|
+
expect(client).to receive(:request_and_wrap).with(:get, '/search?q=foo', BooticClient::Entity, {}).and_return next_page
|
165
172
|
entity.search(q: 'foo').tap do |next_entity|
|
166
173
|
expect(next_entity).to be_kind_of(BooticClient::Entity)
|
167
174
|
expect(next_entity.page).to eql(2)
|
data/spec/relation_spec.rb
CHANGED
@@ -48,8 +48,8 @@ describe BooticClient::Relation do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it 'interpolates tokens' do
|
51
|
-
expect(client).to receive(:request_and_wrap).with(:get, '/foos/2?q=test&page=2', BooticClient::Entity, {
|
52
|
-
expect(relation.run(id: 2, q: 'test', page: 2)).to eql(entity)
|
51
|
+
expect(client).to receive(:request_and_wrap).with(:get, '/foos/2?q=test&page=2', BooticClient::Entity, {other: 'other'}).and_return entity
|
52
|
+
expect(relation.run(id: 2, q: 'test', page: 2, other: 'other')).to eql(entity)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -62,9 +62,9 @@ describe BooticClient::Relation do
|
|
62
62
|
client.stub(:request_and_wrap).with(:post, '/foo/bars', BooticClient::Entity, {}).and_return entity
|
63
63
|
expect(relation.run).to eql(entity)
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
it 'interpolates templated URLs' do
|
67
|
-
client.stub(:request_and_wrap).with(:post, '/foo/123', BooticClient::Entity, {foo: 'bar'
|
67
|
+
client.stub(:request_and_wrap).with(:post, '/foo/123', BooticClient::Entity, {foo: 'bar'}).and_return entity
|
68
68
|
expect(relation_templated.run(bars: 123, foo: 'bar')).to eql(entity)
|
69
69
|
end
|
70
70
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bootic_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ismael Celis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -186,10 +186,13 @@ files:
|
|
186
186
|
- lib/bootic_client/relation.rb
|
187
187
|
- lib/bootic_client/stores/memcache.rb
|
188
188
|
- lib/bootic_client/strategies/authorized.rb
|
189
|
+
- lib/bootic_client/strategies/basic_auth.rb
|
189
190
|
- lib/bootic_client/strategies/client_credentials.rb
|
191
|
+
- lib/bootic_client/strategies/oauth2_strategy.rb
|
190
192
|
- lib/bootic_client/strategies/strategy.rb
|
191
193
|
- lib/bootic_client/version.rb
|
192
194
|
- spec/authorized_strategy_spec.rb
|
195
|
+
- spec/basic_auth_strategy_spec.rb
|
193
196
|
- spec/bootic_client_spec.rb
|
194
197
|
- spec/client_credentials_strategy_spec.rb
|
195
198
|
- spec/client_spec.rb
|
@@ -223,6 +226,7 @@ specification_version: 4
|
|
223
226
|
summary: Official Ruby client for the Bootic API
|
224
227
|
test_files:
|
225
228
|
- spec/authorized_strategy_spec.rb
|
229
|
+
- spec/basic_auth_strategy_spec.rb
|
226
230
|
- spec/bootic_client_spec.rb
|
227
231
|
- spec/client_credentials_strategy_spec.rb
|
228
232
|
- spec/client_spec.rb
|