clarify 1.1.1 → 2.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|