clarify 1.1.1 → 2.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 +4 -4
- data/.gitignore +2 -16
- data/.rspec +2 -0
- data/.simplecov +3 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +4 -0
- data/Dockerfile +11 -0
- data/Gemfile +2 -2
- data/LICENSE +1 -1
- data/README.md +202 -47
- data/Rakefile +62 -4
- data/clarify.gemspec +10 -7
- data/cucumber.yml +1 -0
- data/features/create-bundles.feature +10 -0
- data/features/delete-bundle.feature +7 -0
- data/features/identity-steps.feature +6 -0
- data/features/list-bundles.feature +13 -0
- data/features/search-bundles.feature +10 -0
- data/features/step_definitions/curied_url_steps.rb +6 -0
- data/features/step_definitions/error_steps.rb +4 -0
- data/features/step_definitions/http_verification_step.rb +4 -0
- data/features/step_definitions/identity_steps.rb +12 -0
- data/features/step_definitions/list_steps.rb +76 -0
- data/features/support/env.rb +36 -0
- data/features/support/lib/curies.rb +19 -0
- data/features/support/lib/customer.rb +41 -0
- data/features/support/lib/exceptions.rb +27 -0
- data/features/support/lib/names.rb +16 -0
- data/lib/clarify.rb +16 -14
- data/lib/clarify/bundle_repository.rb +26 -0
- data/lib/clarify/client.rb +51 -0
- data/lib/clarify/collection_iterator.rb +27 -0
- data/lib/clarify/configuration.rb +29 -7
- data/lib/clarify/errors.rb +22 -0
- data/lib/clarify/response.rb +29 -0
- data/lib/clarify/response_factory.rb +34 -0
- data/lib/clarify/responses/bundle.rb +11 -0
- data/lib/clarify/responses/collection.rb +31 -0
- data/lib/clarify/responses/no_body.rb +13 -0
- data/lib/clarify/responses/search_collection.rb +18 -0
- data/lib/clarify/responses/tracks.rb +15 -0
- data/lib/clarify/rest_client.rb +129 -0
- data/lib/clarify/version.rb +3 -1
- data/spec/clarify/bundle_repository_spec.rb +37 -0
- data/spec/clarify/client_spec.rb +93 -0
- data/spec/clarify/collection_iterator_spec.rb +86 -0
- data/spec/clarify/configuration_spec.rb +77 -0
- data/spec/clarify/errors_spec.rb +15 -0
- data/spec/clarify/response_factory_spec.rb +51 -0
- data/spec/clarify/response_spec.rb +69 -0
- data/spec/clarify/responses/bundle_spec.rb +8 -0
- data/spec/clarify/responses/collection_spec.rb +58 -0
- data/spec/clarify/responses/search_collection_spec.rb +40 -0
- data/spec/clarify/responses/tracks_spec.rb +18 -0
- data/spec/clarify/rest_client_spec.rb +222 -0
- data/spec/spec_helper.rb +4 -9
- data/src_readme/README_no_output.md +186 -0
- data/src_readme/examples/bundle_create.rb +11 -0
- data/src_readme/examples/bundle_fetch.rb +9 -0
- data/src_readme/examples/bundles_list_fetch.rb +11 -0
- data/src_readme/examples/bundles_paged_over.rb +8 -0
- data/src_readme/examples/bundles_search.rb +20 -0
- data/src_readme/examples/list_bundles.rb +6 -0
- data/src_readme/examples/searches_paged_over.rb +10 -0
- data/src_readme/examples/setup.rb +5 -0
- data/src_readme/make.rb +56 -0
- data/src_readme/readme.md.erb +55 -0
- metadata +127 -62
- data/LICENSE.txt +0 -24
- data/examples/create.rb +0 -14
- data/examples/delete.rb +0 -12
- data/examples/list.rb +0 -14
- data/examples/search.rb +0 -26
- data/examples/test.rb +0 -15
- data/lib/clarify/bundle.rb +0 -40
- data/lib/clarify/metadata.rb +0 -26
- data/lib/clarify/request.rb +0 -37
- data/lib/clarify/search.rb +0 -10
- data/lib/clarify/track.rb +0 -40
- data/spec/lib/clarify/bundle_spec.rb +0 -43
- data/spec/lib/clarify/configuration_spec.rb +0 -19
- data/spec/lib/clarify/metadata_spec.rb +0 -36
- data/spec/lib/clarify/search_spec.rb +0 -22
- data/spec/lib/clarify/track_spec.rb +0 -81
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
module Clarify
|
3
|
+
# Iterate over a paginated collection
|
4
|
+
class CollectionIterator
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize(restclient, collection)
|
8
|
+
@restclient = restclient
|
9
|
+
@collection = collection
|
10
|
+
end
|
11
|
+
|
12
|
+
def each
|
13
|
+
collections.each { |collection| collection.each { |*i| yield(*i) } }
|
14
|
+
end
|
15
|
+
|
16
|
+
def collections
|
17
|
+
Enumerator.new do |y|
|
18
|
+
current = @collection
|
19
|
+
loop do
|
20
|
+
y << current
|
21
|
+
break unless current.more?
|
22
|
+
current = @restclient.get(current.next)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,16 +1,38 @@
|
|
1
|
+
|
1
2
|
module Clarify
|
3
|
+
# A Configuration class represents the server to communicate with, and the
|
4
|
+
# credentials to consume. You can use multiple Configuration objects with
|
5
|
+
# multiple RestClient objects to support multiple accounts in the same
|
6
|
+
# application.
|
2
7
|
class Configuration
|
3
|
-
|
4
|
-
|
8
|
+
attr_reader :api_key
|
9
|
+
attr_reader :server
|
10
|
+
|
11
|
+
def initialize(conf = {})
|
12
|
+
@api_key = conf.fetch(:api_key)
|
13
|
+
@server = conf.fetch(:server, 'https://api.clarify.io')
|
14
|
+
end
|
15
|
+
|
16
|
+
def api_key?
|
17
|
+
return false unless api_key
|
18
|
+
return false if api_key.empty?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def ssl?
|
23
|
+
uri.scheme == 'https'
|
24
|
+
end
|
5
25
|
|
6
|
-
def
|
7
|
-
|
8
|
-
@version = '1' # latest version is default
|
26
|
+
def host
|
27
|
+
uri.host
|
9
28
|
end
|
10
29
|
|
11
|
-
def
|
12
|
-
|
30
|
+
def port
|
31
|
+
uri.port
|
13
32
|
end
|
14
33
|
|
34
|
+
def uri
|
35
|
+
URI(server)
|
36
|
+
end
|
15
37
|
end
|
16
38
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
module Clarify
|
3
|
+
class StandardError < Exception
|
4
|
+
end
|
5
|
+
|
6
|
+
# This Response error is to be raised when a particular Response has a status
|
7
|
+
# code of 401
|
8
|
+
class UnauthenticatedError < Clarify::StandardError
|
9
|
+
def initialize(response)
|
10
|
+
@response = response
|
11
|
+
|
12
|
+
super 'Response had code 401'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Handles errors where we are unable to understand the response from the API.
|
17
|
+
class UnrecognizedResponseError < Clarify::StandardError
|
18
|
+
def initialize(type)
|
19
|
+
super "Unrecognized response class #{type}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Clarify
|
2
|
+
# A general purpose response which handles status code access and accessing
|
3
|
+
# link relations.
|
4
|
+
class Response
|
5
|
+
attr_reader :body
|
6
|
+
attr_reader :response
|
7
|
+
|
8
|
+
def initialize(body, response)
|
9
|
+
@body = body
|
10
|
+
@response = response
|
11
|
+
end
|
12
|
+
|
13
|
+
def http_status_code
|
14
|
+
response.code.to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def relation!(link)
|
18
|
+
url = relation(link)
|
19
|
+
|
20
|
+
fail ArgumentError, "Link '#{link}' not present" if url.nil?
|
21
|
+
|
22
|
+
url
|
23
|
+
end
|
24
|
+
|
25
|
+
def relation(link)
|
26
|
+
body.fetch('_links', {}).fetch(link, {}).fetch('href', nil)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module Clarify
|
3
|
+
# Handles the HTTP response and returns responses. Also raises exceptions
|
4
|
+
# around API failures.
|
5
|
+
class ResponseFactory
|
6
|
+
def make_result(response)
|
7
|
+
raise_on_code!(response)
|
8
|
+
|
9
|
+
return Clarify::Responses::NoBody.new(response) if response.body.nil?
|
10
|
+
|
11
|
+
data = JSON.parse(response.body || '')
|
12
|
+
klass_for_class(data['_class']).new(data, response)
|
13
|
+
rescue KeyError
|
14
|
+
raise Clarify::UnrecognizedResponseError, data['_class']
|
15
|
+
end
|
16
|
+
|
17
|
+
def raise_on_code!(response)
|
18
|
+
return unless response.code.to_i == 401
|
19
|
+
fail Clarify::UnauthenticatedError, response
|
20
|
+
end
|
21
|
+
|
22
|
+
def klass_for_class(name)
|
23
|
+
klasses = {
|
24
|
+
'Collection' => Clarify::Responses::Collection,
|
25
|
+
'SearchCollection' => Clarify::Responses::SearchCollection,
|
26
|
+
'Bundle' => Clarify::Responses::Bundle,
|
27
|
+
'Tracks' => Clarify::Responses::Tracks,
|
28
|
+
'Ref' => Clarify::Response
|
29
|
+
}
|
30
|
+
|
31
|
+
klasses.fetch name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Clarify
|
5
|
+
module Responses
|
6
|
+
# A Collection represents a list of results from the API, primarily used in
|
7
|
+
# the Bundle list and the Search results (a SearchCollection.)
|
8
|
+
#
|
9
|
+
# A collection can be paged through using next / prev / first / last link
|
10
|
+
# relations.
|
11
|
+
class Collection < Clarify::Response
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
def each
|
15
|
+
items.each { |i| yield i['href'] }
|
16
|
+
end
|
17
|
+
|
18
|
+
def items
|
19
|
+
body['_links']['items']
|
20
|
+
end
|
21
|
+
|
22
|
+
def more?
|
23
|
+
!self.next.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def next
|
27
|
+
relation('next')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
module Clarify
|
3
|
+
module Responses
|
4
|
+
# The Tracks class represents a collection of tracks within a bundle. A
|
5
|
+
# bundle may have zero or more tracks. Iterating over a Tracks object will
|
6
|
+
# yield each track in the tracks resource.
|
7
|
+
class NoBody < Clarify::Response
|
8
|
+
def initialize(response)
|
9
|
+
super response, nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
module Clarify
|
3
|
+
module Responses
|
4
|
+
# A SearchCollection represents a list of search results from the API.
|
5
|
+
#
|
6
|
+
# A collection can be paged through using next / prev / first / last link
|
7
|
+
# relations.
|
8
|
+
class SearchCollection < Clarify::Responses::Collection
|
9
|
+
def each
|
10
|
+
items.each { |result, ref| yield result, ref['href'] }
|
11
|
+
end
|
12
|
+
|
13
|
+
def items
|
14
|
+
body['item_results'].zip(body['_links']['items'])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
module Clarify
|
3
|
+
module Responses
|
4
|
+
# The Tracks class represents a collection of tracks within a bundle. A
|
5
|
+
# bundle may have zero or more tracks. Iterating over a Tracks object will
|
6
|
+
# yield each track in the tracks resource.
|
7
|
+
class Tracks < Clarify::Response
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def each
|
11
|
+
body['tracks'].each { |i| yield i }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Clarify
|
7
|
+
# Implement the HTTP layer. All the communication in this restclient goes over
|
8
|
+
# the one HTTP connection for performance. The connection is created by the
|
9
|
+
# input of the Configuration object which is passed in by default.
|
10
|
+
#
|
11
|
+
# This is a bit over complex, but deals with:
|
12
|
+
#
|
13
|
+
# 1. Authenticating and identifying (via UserAgent) requests ("blessing")
|
14
|
+
# 2. Actually calling the API over HTTP
|
15
|
+
# 3. Converting the resulting responses into Response objects
|
16
|
+
#
|
17
|
+
# In other words, this does too many things, but it is a start.
|
18
|
+
class RestClient
|
19
|
+
attr_reader :config
|
20
|
+
|
21
|
+
def initialize(config)
|
22
|
+
@config = config
|
23
|
+
@cached = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(url, params = {})
|
27
|
+
request(get_request(url, params))
|
28
|
+
end
|
29
|
+
|
30
|
+
def post(url, params = {})
|
31
|
+
request(post_request(url, params))
|
32
|
+
end
|
33
|
+
|
34
|
+
def put(url, params = {})
|
35
|
+
request(put_request(url, params))
|
36
|
+
end
|
37
|
+
|
38
|
+
def delete(url, params = {})
|
39
|
+
request(delete_request(url, params))
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_request(url, params = {})
|
43
|
+
url = make_get_url(url, params)
|
44
|
+
Net::HTTP::Get.new(url)
|
45
|
+
end
|
46
|
+
|
47
|
+
def post_request(url, body = {})
|
48
|
+
request = Net::HTTP::Post.new(url)
|
49
|
+
request.set_form_data(body)
|
50
|
+
request
|
51
|
+
end
|
52
|
+
|
53
|
+
def put_request(url, body = {})
|
54
|
+
request = Net::HTTP::Put.new(url)
|
55
|
+
request.set_form_data(body)
|
56
|
+
request
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_request(url, body = {})
|
60
|
+
request = Net::HTTP::Delete.new(url)
|
61
|
+
request.set_form_data(body)
|
62
|
+
request
|
63
|
+
end
|
64
|
+
|
65
|
+
def make_get_url(url, parameters)
|
66
|
+
# Convert the URL to a URI object we can manipulate
|
67
|
+
uri = URI.parse(url)
|
68
|
+
|
69
|
+
# Code a=b to [['a', 'b']] -- this array of arrays format is used
|
70
|
+
# so you can represent (valid) URLs which look like:
|
71
|
+
# a=b&a=c via [['a', 'b'], ['a', 'c']]
|
72
|
+
original_params = URI.decode_www_form(uri.query.to_s)
|
73
|
+
|
74
|
+
# Now we convert the incoming URL parameters which could either look like:
|
75
|
+
# 1. { b: 'c' }
|
76
|
+
# 2. { b: ['c', 'd'] }
|
77
|
+
# 3. { b: :c }
|
78
|
+
# 4. [['b', 'c']]
|
79
|
+
# to consistently be in the fourth format by encoding (flexible on input)
|
80
|
+
# and decoding again (which always produces the fourth format.)
|
81
|
+
new_params = URI.decode_www_form(URI.encode_www_form(parameters))
|
82
|
+
|
83
|
+
# Merge the two arrays [['b', 'c']] and [['a', 'b']] into
|
84
|
+
# [['a', 'b'], ['b', 'c']] and put it into the uri object for returning
|
85
|
+
uri.query = URI.encode_www_form(original_params + new_params)
|
86
|
+
|
87
|
+
# Set the query to nil if the query is empty, otherwise the generated URL
|
88
|
+
# will have a trailing ?.
|
89
|
+
uri.query = nil if uri.query.empty?
|
90
|
+
|
91
|
+
uri.to_s
|
92
|
+
end
|
93
|
+
|
94
|
+
def request(request)
|
95
|
+
request = bless_request(request)
|
96
|
+
response = connection.request(request)
|
97
|
+
make_result(response)
|
98
|
+
end
|
99
|
+
|
100
|
+
def bless_request(request)
|
101
|
+
request['Authorization'] = "Bearer #{config.api_key}" if config.api_key?
|
102
|
+
request['User-Agent'] = user_agent
|
103
|
+
|
104
|
+
request
|
105
|
+
end
|
106
|
+
|
107
|
+
def user_agent
|
108
|
+
ruby_version = "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
|
109
|
+
"clarify-ruby/#{Clarify::VERSION}/#{ruby_version}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def make_result(response)
|
113
|
+
response_factory.make_result(response)
|
114
|
+
end
|
115
|
+
|
116
|
+
def response_factory
|
117
|
+
@response_factory ||= Clarify::ResponseFactory.new
|
118
|
+
end
|
119
|
+
|
120
|
+
def connection
|
121
|
+
unless @connection
|
122
|
+
@connection ||= Net::HTTP.new(config.host, config.port)
|
123
|
+
@connection.use_ssl = config.ssl?
|
124
|
+
end
|
125
|
+
|
126
|
+
@connection
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/lib/clarify/version.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
describe Clarify::BundleRepository do
|
3
|
+
let(:restclient) { double(:restclient) }
|
4
|
+
let(:repo) { Clarify::BundleRepository.new(restclient) }
|
5
|
+
|
6
|
+
describe '#fetch' do
|
7
|
+
it 'performs a get on the restclient' do
|
8
|
+
expect(restclient).to receive(:get).with('/v1/bundles')
|
9
|
+
repo.fetch
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#search' do
|
14
|
+
it 'performs a get on the restclient' do
|
15
|
+
expect(restclient).to receive(:get).with('/v1/search', query: 'abc')
|
16
|
+
repo.search 'abc'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#create!' do
|
21
|
+
it 'performs a post on the restclient' do
|
22
|
+
body = { hey: :there }
|
23
|
+
expect(restclient).to receive(:post).with('/v1/bundles', body)
|
24
|
+
repo.create! body
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#delete!' do
|
29
|
+
it 'performs a delete on the restclient' do
|
30
|
+
bundle = double(:bundle)
|
31
|
+
expect(bundle).to receive(:relation!)
|
32
|
+
.with('self').and_return('/v1/bundle/thisone')
|
33
|
+
expect(restclient).to receive(:delete).with('/v1/bundle/thisone')
|
34
|
+
repo.delete! bundle
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
|
2
|
+
describe Clarify::Client do
|
3
|
+
let(:opts) { {} }
|
4
|
+
let(:config) { { api_key: 'abc123' } }
|
5
|
+
let(:client) { Clarify::Client.new(config, opts) }
|
6
|
+
|
7
|
+
context 'with a fake restclient' do
|
8
|
+
let(:url) { double(:url) }
|
9
|
+
let(:params) { double(:params) }
|
10
|
+
let(:restclient) { double(:restclient) }
|
11
|
+
before(:each) do
|
12
|
+
allow(client).to receive(:restclient).and_return(restclient)
|
13
|
+
end
|
14
|
+
describe '#get' do
|
15
|
+
it 'calls get on the restclient' do
|
16
|
+
expect(restclient).to receive(:get).with(url, params)
|
17
|
+
client.get(url, params)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#put' do
|
22
|
+
it 'calls put on the restclient' do
|
23
|
+
expect(restclient).to receive(:put).with(url, params)
|
24
|
+
client.put(url, params)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#post' do
|
29
|
+
it 'calls post on the restclient' do
|
30
|
+
expect(restclient).to receive(:post).with(url, params)
|
31
|
+
client.post(url, params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#delete' do
|
36
|
+
it 'calls delete on the restclient' do
|
37
|
+
expect(restclient).to receive(:delete).with(url, params)
|
38
|
+
client.delete(url, params)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#pager' do
|
44
|
+
let(:collection) { double(:collection) }
|
45
|
+
let(:restclient) { double(:restclient) }
|
46
|
+
let(:iterator_klass) { double(:iterator_klass) }
|
47
|
+
let(:opts) { { iterator: iterator_klass } }
|
48
|
+
it 'creates an iterator with the restclient' do
|
49
|
+
expect(client).to receive(:restclient).and_return(restclient)
|
50
|
+
expect(iterator_klass).to receive(:new).with(restclient, collection)
|
51
|
+
client.pager(collection)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#bundles' do
|
56
|
+
let(:repo) { double(:repo) }
|
57
|
+
it 'calls the bundle_repository method' do
|
58
|
+
expect(client).to receive(:bundle_repository).and_return(repo)
|
59
|
+
expect(client.bundles).to eq(repo)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#bundle_repository' do
|
64
|
+
let(:restclient) { double(:restclient) }
|
65
|
+
let(:bundle_klass) { double(:bundle_klass) }
|
66
|
+
let(:opts) { { bundle_repository: bundle_klass } }
|
67
|
+
it 'creates a bundle repository with the restclient' do
|
68
|
+
expect(client).to receive(:restclient).and_return(restclient)
|
69
|
+
expect(bundle_klass).to receive(:new).with(restclient)
|
70
|
+
client.bundle_repository
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#restclient' do
|
75
|
+
let(:configuration) { double(:configuration) }
|
76
|
+
let(:restclient_klass) { double(:restclient_klass) }
|
77
|
+
let(:opts) { { rest_client: restclient_klass } }
|
78
|
+
it 'creates a new restclient with the configuration' do
|
79
|
+
expect(client).to receive(:configuration).and_return(configuration)
|
80
|
+
expect(restclient_klass).to receive(:new).with(configuration)
|
81
|
+
client.restclient
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#configuration' do
|
86
|
+
let(:config_klass) { double(:config_klass) }
|
87
|
+
let(:opts) { { configuration: config_klass } }
|
88
|
+
it 'should create a new Configuration from the opts' do
|
89
|
+
expect(config_klass).to receive(:new).with(config)
|
90
|
+
client.configuration
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|