my_target_api 1.2.4 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 332efd986b48d1eb9282a1d9f279af9a73c0d68c
4
- data.tar.gz: d5c0aaed3310f3916c89efe27429eeeceee0a613
3
+ metadata.gz: 4254318b97e9d1f594438694a31a6511ea9461fc
4
+ data.tar.gz: 69e005cf224551553abdc2c047d84b278a3f3e70
5
5
  SHA512:
6
- metadata.gz: e76f8ff06d6cf4babe4d373a4b16f8205741f2d5f271f8cd435018775036b37444384519d36dcdcaac36abcfcb5f8f41d6e0969362e7dc769a6d5b4b49906e23
7
- data.tar.gz: 711ddc0150a890da7c0e31ca94dfa4227e3139cc009e6eec8ca5cce194e0d15ec61d0207035b497355b0a8d4aaf3bf67d6c6e8f292ef17061d260dceb9c60ec4
6
+ metadata.gz: '08db4857b6fb49cacdc2050356b43aa94b3998fb2a8f0d31fc133e12554b07d190e0a370363b9b8bc5dfa88a53717c91b449b0ba5de5d1254dab65bfd3e93c38'
7
+ data.tar.gz: '08966200b98a7df2bfc4fee600650072ee52343e5ff3f83b987a450cd915901ee88b2273aea35e67b6a40f66e50020a75ee68ac35e66b713f14207d5aa12fe3b'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- my_target_api (1.2.4)
4
+ my_target_api (2.0.1)
5
5
  json (~> 2.0, >= 2.0.0)
6
6
  rest-client (~> 2.0, >= 2.0.0)
7
7
 
@@ -10,7 +10,7 @@ GEM
10
10
  specs:
11
11
  addressable (2.6.0)
12
12
  public_suffix (>= 2.0.2, < 4.0)
13
- ast (2.4.0)
13
+ ast (2.4.1)
14
14
  crack (0.4.3)
15
15
  safe_yaml (~> 1.0.0)
16
16
  diff-lcs (1.3)
@@ -24,17 +24,18 @@ GEM
24
24
  mime-types-data (~> 3.2015)
25
25
  mime-types-data (3.2018.0812)
26
26
  netrc (0.11.0)
27
- parallel (1.13.0)
28
- parser (2.6.0.0)
29
- ast (~> 2.4.0)
30
- powerpack (0.1.2)
27
+ parallel (1.19.2)
28
+ parser (2.7.1.4)
29
+ ast (~> 2.4.1)
31
30
  public_suffix (3.0.3)
32
31
  rainbow (3.0.0)
33
32
  rake (12.3.2)
33
+ regexp_parser (1.7.1)
34
34
  rest-client (2.0.2)
35
35
  http-cookie (>= 1.0.2, < 2.0)
36
36
  mime-types (>= 1.16, < 4.0)
37
37
  netrc (~> 0.8)
38
+ rexml (3.2.4)
38
39
  rspec (3.7.0)
39
40
  rspec-core (~> 3.7.0)
40
41
  rspec-expectations (~> 3.7.0)
@@ -48,19 +49,23 @@ GEM
48
49
  diff-lcs (>= 1.2.0, < 2.0)
49
50
  rspec-support (~> 3.7.0)
50
51
  rspec-support (3.7.1)
51
- rubocop (0.54.0)
52
+ rubocop (0.89.1)
52
53
  parallel (~> 1.10)
53
- parser (>= 2.5)
54
- powerpack (~> 0.1)
54
+ parser (>= 2.7.1.1)
55
55
  rainbow (>= 2.2.2, < 4.0)
56
+ regexp_parser (>= 1.7)
57
+ rexml
58
+ rubocop-ast (>= 0.3.0, < 1.0)
56
59
  ruby-progressbar (~> 1.7)
57
- unicode-display_width (~> 1.0, >= 1.0.1)
58
- ruby-progressbar (1.10.0)
60
+ unicode-display_width (>= 1.4.0, < 2.0)
61
+ rubocop-ast (0.3.0)
62
+ parser (>= 2.7.1.4)
63
+ ruby-progressbar (1.10.1)
59
64
  safe_yaml (1.0.4)
60
65
  unf (0.1.4)
61
66
  unf_ext
62
67
  unf_ext (0.0.7.5)
63
- unicode-display_width (1.4.1)
68
+ unicode-display_width (1.7.0)
64
69
  webmock (2.3.2)
65
70
  addressable (>= 2.3.6)
66
71
  crack (>= 0.3.2)
@@ -70,12 +75,12 @@ PLATFORMS
70
75
  ruby
71
76
 
72
77
  DEPENDENCIES
73
- bundler (~> 1.6)
78
+ bundler (~> 2.1.4)
74
79
  my_target_api!
75
80
  rake (~> 12.3.0, >= 12.3.0)
76
81
  rspec (~> 3.7.0, >= 3.7.0)
77
- rubocop (~> 0.54.0)
82
+ rubocop (~> 0.89.1)
78
83
  webmock (~> 2.3.2, >= 2.3.2)
79
84
 
80
85
  BUNDLED WITH
81
- 1.16.1
86
+ 2.1.4
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  Add this line to your application's Gemfile:
8
8
 
9
9
  ```
10
- gem 'my_target_api', '~> 1.2.4'
10
+ gem 'my_target_api', '~> 2.0.1'
11
11
  ```
12
12
 
13
13
  Or install from command line:
@@ -43,6 +43,7 @@ Name | Default value | Description
43
43
  ---|---|---
44
44
  `:v` | 1 | API version
45
45
  `:logger` | | An object to log requests and exceptions. The object must respond to `<<` method
46
+ `:headers` | | Headers hash to pass with request
46
47
 
47
48
  ### Create, Read, Update, Delete
48
49
 
@@ -60,7 +61,7 @@ remarketing_counters_resource.delete(id: 343434) # => [{ 'success' => true }]
60
61
 
61
62
  #### Options
62
63
 
63
- Name | Default value | Description
64
+ Name | Default value | Description
64
65
  ---|---|---
65
66
  `:id` | | Resource ID. Optional for Read, required for Update and Delete
66
67
  `:id_param_key` | `:id` | Option key for resource ID
@@ -96,19 +97,18 @@ def read_active_campaigns
96
97
 
97
98
  campaigns_resource.read(status: 'active')
98
99
 
99
- rescue MyTargetApi::RequestError, MyTargetApi::ConnectionError => e
100
+ rescue MyTargetApi::RequestError => e
100
101
 
101
- puts e.message, e.backtrace
102
+ puts e.message, e.params, e.response, e.backtrace
102
103
  # You can access the original exception
103
- puts e.original_exception.message, e.original_exception.backtrace
104
+ puts e.original_exception&.message, e.original_exception&.backtrace
104
105
 
105
106
  end
106
107
  ```
107
108
 
108
- Name | Description
109
+ Name | Description
109
110
  ---|---
110
111
  `MyTargetApi::RequestError` | Request didn't succeed
111
- `MyTargetApi::ConnectionError` | Connection didn't succeed
112
112
 
113
113
  ## Testing
114
114
 
@@ -7,9 +7,9 @@ class MyTargetApi
7
7
 
8
8
  autoload :Resource, 'my_target_api/resource'
9
9
  autoload :Request, 'my_target_api/request'
10
-
11
- autoload :ConnectionError, 'my_target_api/connection_error'
12
10
  autoload :RequestError, 'my_target_api/request_error'
11
+ autoload :NetClient, 'my_target_api/net_client'
12
+ autoload :LogRequestParametersDecorator, 'my_target_api/log_request_parameters_decorator'
13
13
 
14
14
  def initialize(access_token, options = {})
15
15
  @access_token = access_token
@@ -44,7 +44,14 @@ class MyTargetApi
44
44
  attr_reader :access_token, :options
45
45
 
46
46
  def request_object
47
- Request.new(logger: options[:logger], access_token: access_token)
47
+ @_request_object ||= begin
48
+ options = {
49
+ logger: self.options[:logger],
50
+ access_token: access_token,
51
+ headers: self.options[:headers]
52
+ }
53
+ LogRequestParametersDecorator.new(Request.new(options), options)
54
+ end
48
55
  end
49
56
 
50
57
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require_relative './response_formatter'
5
+ require_relative './net_client'
6
+
7
+ class MyTargetApi
8
+ # Requests
9
+ class LogRequestParametersDecorator
10
+
11
+ def initialize(origin, options = {})
12
+ @origin = origin
13
+ @options = options
14
+ end
15
+
16
+ def get(url, params = {})
17
+ log_hash(method: 'Request#get', url: url, params: params)
18
+
19
+ origin.get(url, params)
20
+ end
21
+
22
+ def post(url, params = {})
23
+ log_hash(method: 'Request#post', url: url, params: params)
24
+
25
+ origin.post(url, params)
26
+ end
27
+
28
+ def delete(url, params = {})
29
+ log_hash(method: 'Request#delete', url: url, params: params)
30
+
31
+ origin.delete(url, params)
32
+ end
33
+
34
+ def upload(url, content, params = {})
35
+ log_hash(method: 'Request#upload', url: url, params: params, content: 'no logging')
36
+
37
+ origin.upload(url, content, params)
38
+ end
39
+
40
+ private
41
+
42
+ attr_reader :origin, :options
43
+
44
+ def log_hash(hash)
45
+ log(hash.map do |key, value|
46
+ "#{key}: #{value.is_a?(String) ? value : value.inspect}"
47
+ end.join("\n"))
48
+ end
49
+
50
+ def log(message)
51
+ options[:logger] << message if options[:logger]
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'rest-client'
5
+
6
+ class MyTargetApi
7
+ # Requests
8
+ class NetClient
9
+
10
+ # NetClient response
11
+ class Response
12
+
13
+ def initialize(body, code, headers)
14
+ @body = body
15
+ @code = code
16
+ @headers = headers
17
+ end
18
+
19
+ attr_reader :body, :code, :headers
20
+
21
+ end
22
+
23
+ # NetClient exception
24
+ class Exception < StandardError
25
+
26
+ def initialize(exception, message)
27
+ @original_exception = exception
28
+
29
+ super(message)
30
+ end
31
+
32
+ attr_reader :original_exception
33
+
34
+ end
35
+
36
+ class << self
37
+
38
+ def get(*args)
39
+ RestClient.get(*args) { |response, &block| process_response(response, &block) }
40
+ rescue StandardError => e
41
+ raise(Exception.new(e, e.message).tap { e.set_backtrace(caller) })
42
+ end
43
+
44
+ def post(*args)
45
+ RestClient.post(*args) { |response, &block| process_response(response, &block) }
46
+ rescue StandardError => e
47
+ raise(Exception.new(e, e.message).tap { e.set_backtrace(caller) })
48
+ end
49
+
50
+ def delete(*args)
51
+ RestClient.delete(*args) { |response, &block| process_response(response, &block) }
52
+ rescue StandardError => e
53
+ raise(Exception.new(e, e.message).tap { e.set_backtrace(caller) })
54
+ end
55
+
56
+ private
57
+
58
+ def process_response(response, &block)
59
+ result =
60
+ case response.code
61
+ when 200..207, 400..599
62
+ response
63
+ else
64
+ response.return!(&block)
65
+ end
66
+ Response.new(result.body, result.code, format_headers(result.headers))
67
+ rescue StandardError => e
68
+ raise(Exception.new(e, e.message).tap { e.set_backtrace(caller) })
69
+ end
70
+
71
+ def format_headers(headers)
72
+ headers.map do |key, value|
73
+ [key.to_s.split('_').map(&:capitalize).join('-'), value]
74
+ end.to_h
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+ end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
- require 'rest-client'
4
+ require_relative './response_formatter'
5
+ require_relative './net_client'
5
6
 
6
7
  class MyTargetApi
7
8
  # Requests
@@ -12,41 +13,35 @@ class MyTargetApi
12
13
  end
13
14
 
14
15
  def get(url, params = {})
15
- log_hash(method: 'Request#get', url: url, params: params)
16
-
17
- response = with_exception_handling do
18
- RestClient.get(url, headers.merge(query(params)))
16
+ response = with_exception_handling(params) do
17
+ NetClient.get(url, headers.merge(query(params)))
19
18
  end
20
19
 
21
20
  process_response(response)
22
21
  end
23
22
 
24
23
  def post(url, params = {})
25
- log_hash(method: 'Request#post', url: url, params: params)
26
-
27
- response = with_exception_handling do
28
- RestClient.post(url, body_parameters(params), headers)
24
+ response = with_exception_handling(params) do
25
+ NetClient.post(url, body_parameters(params), headers)
29
26
  end
30
27
 
31
28
  process_response(response)
32
29
  end
33
30
 
34
31
  def delete(url, params = {})
35
- log_hash(method: 'Request#delete', url: url, params: params)
36
-
37
- response = with_exception_handling do
38
- RestClient.delete(url, headers.merge(query(params)))
32
+ response = with_exception_handling(params) do
33
+ NetClient.delete(url, headers.merge(query(params)))
39
34
  end
40
35
 
41
36
  process_response(response)
42
37
  end
43
38
 
44
39
  def upload(url, content, params = {})
45
- log_hash(method: 'Request#upload', url: url, params: params, content: 'no logging')
46
-
47
- response = with_exception_handling do
48
- RestClient.post(
49
- url, content, headers.merge(query(params)).merge(content_type: 'application/octet-stream')
40
+ response = with_exception_handling(params) do
41
+ NetClient.post(
42
+ url,
43
+ content,
44
+ headers.merge(query(params)).merge('Content-Type' => 'application/octet-stream')
50
45
  )
51
46
  end
52
47
 
@@ -68,9 +63,9 @@ class MyTargetApi
68
63
  end
69
64
 
70
65
  def individual_body_parameters(params)
71
- params.map do |name, value|
72
- [name, value.is_a?(Array) || value.is_a?(Hash) ? value.to_json : value]
73
- end.to_h
66
+ params.transform_values do |value|
67
+ value.is_a?(Array) || value.is_a?(Hash) ? value.to_json : value
68
+ end
74
69
  end
75
70
 
76
71
  def query(params)
@@ -78,7 +73,11 @@ class MyTargetApi
78
73
  end
79
74
 
80
75
  def headers
81
- { Authorization: "Bearer #{access_token}" }
76
+ if access_token
77
+ optional_headers.merge('Authorization' => "Bearer #{access_token}")
78
+ else
79
+ optional_headers
80
+ end
82
81
  end
83
82
 
84
83
  def process_response(response)
@@ -87,38 +86,33 @@ class MyTargetApi
87
86
  response.body
88
87
  end
89
88
 
90
- def with_exception_handling
89
+ def with_exception_handling(params)
91
90
  response = yield
92
- log(response)
91
+ log_response(response)
92
+ raise_with_params(params: params, response: response) if response.code >= 400
93
93
  response
94
- rescue RestClient::ExceptionWithResponse => e
95
- log_rest_client_exception(e)
96
- raise MyTargetApi::RequestError, e
97
- rescue RestClient::Exception => e
98
- log("#{e.class.name} #{e.message}")
99
- raise MyTargetApi::RequestError, e
100
- rescue SocketError => e
101
- raise MyTargetApi::ConnectionError, e
94
+ rescue NetClient::Exception => e
95
+ original_exception = e.original_exception
96
+ log("#{original_exception.class.name} #{original_exception.message}")
97
+ raise_with_params(params: params, original_exception: original_exception)
102
98
  end
103
99
 
104
- def log_rest_client_exception(exception)
105
- log_message =
106
- <<-LOG
107
- RestClient exception
108
- Class: #{exception.class}
109
- Message: #{exception.message}
110
- HTTP Code: #{exception.http_code}
111
- HTTP Body: #{exception.http_body}
112
- HTTP headers: #{exception.http_headers}
113
- LOG
100
+ def log_response(response)
101
+ log(ResponseFormatter.new(response).format)
102
+ end
114
103
 
115
- log(log_message)
104
+ def headers_to_string(headers)
105
+ headers.map do |name, value|
106
+ "#{name}: #{value}"
107
+ end.join("\n")
116
108
  end
117
109
 
118
- def log_hash(hash)
119
- log(hash.map do |key, value|
120
- "#{key}: #{value.is_a?(String) ? value : value.inspect}"
121
- end.join("\n"))
110
+ def raise_with_params(params:, response: nil, original_exception: nil)
111
+ result = MyTargetApi::RequestError.new(params: params,
112
+ response: response,
113
+ original_exception: original_exception)
114
+ result.set_backtrace(caller)
115
+ raise result
122
116
  end
123
117
 
124
118
  def log(message)
@@ -129,5 +123,9 @@ class MyTargetApi
129
123
  options[:access_token]
130
124
  end
131
125
 
126
+ def optional_headers
127
+ options[:headers] || {}
128
+ end
129
+
132
130
  end
133
131
  end
@@ -4,24 +4,18 @@ class MyTargetApi
4
4
  # Error for request
5
5
  class RequestError < StandardError
6
6
 
7
- attr_reader :original_exception
7
+ attr_reader :params, :original_exception, :response
8
8
 
9
- def initialize(exception)
10
- @original_exception = exception
11
- super build_message exception
12
- end
9
+ def initialize(params:, original_exception: nil, response: nil)
10
+ @params = params
11
+ @response = response
12
+ @original_exception = original_exception
13
13
 
14
- private
14
+ message =
15
+ "#{(response ? "#{response.code}: #{response.body}. " : '')}"\
16
+ 'Inspect #params, #response and #original_exception for more details'
15
17
 
16
- def build_message(exception)
17
- body = JSON.parse exception.response
18
- if body['error']
19
- "#{body['error']} : #{body['error_description']}"
20
- else
21
- body.map { |field, error| "#{field}: #{error}" }.join(', ')
22
- end
23
- rescue StandardError
24
- exception.response
18
+ super(message)
25
19
  end
26
20
 
27
21
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ class MyTargetApi
6
+ # Format response
7
+ class ResponseFormatter
8
+
9
+ def initialize(response)
10
+ @response = response
11
+ end
12
+
13
+ def format
14
+ headers = response.headers.empty? ? ' No headers' : "\n#{headers_in_lines}"
15
+ body = response.body.to_s == '' ? ' No body' : "\n#{response.body}"
16
+ <<~RESPONSE
17
+ HTTP Code: #{response.code}
18
+ HTTP Body:#{body}
19
+ HTTP Headers:#{headers}
20
+ RESPONSE
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :response
26
+
27
+ def headers_in_lines
28
+ headers.map do |name, value|
29
+ "#{name}: #{value}"
30
+ end.join("\n")
31
+ end
32
+
33
+ def headers
34
+ @_headers ||= response.headers
35
+ end
36
+
37
+ end
38
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  class MyTargetApi
4
4
 
5
- VERSION = '1.2.4'
5
+ VERSION = '2.0.2'
6
6
 
7
7
  end
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
17
17
  DESC
18
18
  spec.homepage = 'https://github.com/resivalex/my_target_api'
19
19
  spec.license = 'MIT'
20
+ spec.required_ruby_version = '>= 2.4.0'
20
21
 
21
22
  spec.files = Dir['**/*']
22
23
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -26,9 +27,9 @@ Gem::Specification.new do |spec|
26
27
  spec.add_runtime_dependency 'json', '~> 2.0', '>= 2.0.0'
27
28
  spec.add_runtime_dependency 'rest-client', '~> 2.0', '>= 2.0.0'
28
29
 
29
- spec.add_development_dependency 'bundler', '~> 1.6'
30
+ spec.add_development_dependency 'bundler', '~> 2.1.4'
30
31
  spec.add_development_dependency 'rake', '~> 12.3.0', '>= 12.3.0'
31
32
  spec.add_development_dependency 'rspec', '~> 3.7.0', '>= 3.7.0'
32
- spec.add_development_dependency 'rubocop', '~> 0.54.0'
33
+ spec.add_development_dependency 'rubocop', '~> 0.89.1'
33
34
  spec.add_development_dependency 'webmock', '~> 2.3.2', '>= 2.3.2'
34
35
  end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'my_target_api'
4
+
5
+ describe MyTargetApi::NetClient do
6
+ describe '#post' do
7
+ it 'OK' do
8
+ stub_request(:post, 'https://api.com')
9
+ .with(body: 'param1=1&param2[two]=2')
10
+ .to_return(body: 'body')
11
+
12
+ expect(
13
+ MyTargetApi::NetClient.post('https://api.com', param1: 1, param2: { two: 2 }).body
14
+ ).to eq('body')
15
+ end
16
+
17
+ it 'Content-Type' do
18
+ stub_request(:post, 'https://api.com')
19
+ .with(body: 'payload',
20
+ headers: { 'Content-Type' => 'application/octet-stream' })
21
+ .to_return(body: '{}')
22
+
23
+ expect(
24
+ MyTargetApi::NetClient.post('https://api.com',
25
+ 'payload',
26
+ 'Content-Type' => 'application/octet-stream').body
27
+ ).to eq('{}')
28
+ end
29
+ end
30
+
31
+ describe '#get' do
32
+ it 'OK' do
33
+ stub_request(:get, 'https://api.com?p=3').to_return(body: 'body')
34
+
35
+ expect(MyTargetApi::NetClient.get('https://api.com', params: { p: 3 }).body).to eq('body')
36
+ end
37
+
38
+ it 'Content-Type' do
39
+ stub_request(:get, 'https://api.com/?param1=1&param2%5Btwo%5D=2')
40
+ .with(headers: { 'Content-Type' => 'application/octet-stream' })
41
+ .to_return(body: '{}')
42
+
43
+ expect(MyTargetApi::NetClient.get(
44
+ 'https://api.com',
45
+ params: { param1: 1, param2: { two: 2 } },
46
+ 'Content-Type' => 'application/octet-stream'
47
+ ).body).to eq('{}')
48
+ end
49
+
50
+ it ':content_type' do
51
+ stub_request(:get, 'https://api.com')
52
+ .with(headers: { 'Content-Type' => 'application/octet-stream' })
53
+ .to_return(body: 'abc')
54
+
55
+ expect(
56
+ MyTargetApi::NetClient.get('https://api.com', content_type: 'application/octet-stream').body
57
+ ).to eq('abc')
58
+ end
59
+
60
+ it 'Headers' do
61
+ stub_request(:get, 'https://api.com?p=3')
62
+ .to_return(body: 'body', headers: { 'app-version' => '344354325' })
63
+
64
+ result = MyTargetApi::NetClient.get('https://api.com', params: { p: 3 })
65
+
66
+ expect(result.body).to eq('body')
67
+ expect(result.code).to eq(200)
68
+ expect(result.headers).to eq('App-Version' => '344354325')
69
+ end
70
+
71
+ it '404' do
72
+ stub_request(:get, 'https://api.com').to_return(body: 'not found', status: 404)
73
+
74
+ result = MyTargetApi::NetClient.get('https://api.com', {})
75
+
76
+ expect(result.body).to eq('not found')
77
+ expect(result.code).to eq(404)
78
+ end
79
+
80
+ it '301' do
81
+ stub_request(:get, 'https://api.com')
82
+ .to_return(body: 'not found', status: 301, headers: { 'Location' => 'https://api2.com' })
83
+ stub_request(:get, 'https://api2.com/').to_return(body: 'OK', status: 200)
84
+
85
+ result = MyTargetApi::NetClient.get('https://api.com', {})
86
+
87
+ expect(result.body).to eq('OK')
88
+ expect(result.code).to eq(200)
89
+ end
90
+ end
91
+
92
+ describe '#delete' do
93
+ it 'OK' do
94
+ stub_request(:delete, 'https://api.com').to_return(body: 'body')
95
+
96
+ expect(MyTargetApi::NetClient.delete('https://api.com', {}).body).to eq('body')
97
+ end
98
+
99
+ it 'Content-Type' do
100
+ stub_request(:delete, 'https://api.com/?param1=1&param2%5Btwo%5D=2')
101
+ .with(headers: { 'Content-Type' => 'application/octet-stream' })
102
+ .to_return(body: '{}')
103
+
104
+ expect(MyTargetApi::NetClient.delete(
105
+ 'https://api.com',
106
+ params: { param1: 1, param2: { two: 2 } },
107
+ 'Content-Type' => 'application/octet-stream'
108
+ ).body).to eq('{}')
109
+ end
110
+
111
+ it '404' do
112
+ stub_request(:delete, 'https://api.com').to_return(body: 'not found', status: 404)
113
+
114
+ result = MyTargetApi::NetClient.delete('https://api.com', {})
115
+
116
+ expect(result.body).to eq('not found')
117
+ expect(result.code).to eq(404)
118
+ end
119
+ end
120
+ end
@@ -3,8 +3,6 @@
3
3
  require 'my_target_api'
4
4
 
5
5
  describe MyTargetApi::Request do
6
- let(:access_token) { 'myTarget token' }
7
-
8
6
  let(:request) { MyTargetApi::Request.new }
9
7
 
10
8
  describe 'myTarget request types' do
@@ -16,41 +14,69 @@ describe MyTargetApi::Request do
16
14
 
17
15
  describe 'request something' do
18
16
  it 'return parsed json' do
19
- stub_request(:post, 'https://target.my.com/api/v1/campaigns.json')
20
- .to_return(body: '{"name": "Campaign 1"}')
17
+ allow(MyTargetApi::NetClient).to(
18
+ receive(:post).and_return(double(code: 200, body: '{"name": "Campaign 1"}', headers: {}))
19
+ )
20
+
21
+ result = subject.post('https://target.my.com/api/v1/campaigns.json')
21
22
 
22
- expect(subject.post('https://target.my.com/api/v1/campaigns.json'))
23
- .to eq('name' => 'Campaign 1')
23
+ expect(MyTargetApi::NetClient).to(
24
+ have_received(:post).with('https://target.my.com/api/v1/campaigns.json', '{}', {})
25
+ )
26
+
27
+ expect(result).to eq('name' => 'Campaign 1')
24
28
  end
25
29
 
26
30
  it 'pass parameters by url in get' do
27
- stub_request(:get, 'https://target.my.com/api/v1/vk_groups.json?q=unfound')
28
- .to_return(body: '[]')
31
+ allow(MyTargetApi::NetClient)
32
+ .to receive(:get).and_return(double(code: 200, body: '[]', headers: {}))
33
+
34
+ result = subject.get('https://target.my.com/api/v1/vk_groups.json', q: 'unfound')
29
35
 
30
- expect(subject.get('https://target.my.com/api/v1/vk_groups.json', q: 'unfound'))
31
- .to eq([])
36
+ expect(MyTargetApi::NetClient).to(
37
+ have_received(:get).with('https://target.my.com/api/v1/vk_groups.json',
38
+ params: { q: 'unfound' })
39
+ )
40
+ expect(result).to eq([])
32
41
  end
33
42
 
34
43
  it 'deletes object' do
35
- stub_request(:delete, 'https://target.my.com/api/v1/remarketing_context_phrases/53.json')
36
- .to_return(body: '[{ "success": true }]')
44
+ allow(MyTargetApi::NetClient).to(
45
+ receive(:delete).and_return(double(code: 200, body: '[{ "success": true }]', headers: {}))
46
+ )
37
47
 
38
- expect(
39
- subject.delete('https://target.my.com/api/v1/remarketing_context_phrases/53.json')
40
- ).to eq([{ 'success' => true }])
48
+ result = subject.delete('https://target.my.com/api/v1/remarketing_context_phrases/53.json')
49
+
50
+ expect(MyTargetApi::NetClient).to(
51
+ have_received(:delete).with(
52
+ 'https://target.my.com/api/v1/remarketing_context_phrases/53.json',
53
+ params: {}
54
+ )
55
+ )
56
+ expect(result).to eq([{ 'success' => true }])
41
57
  end
42
58
 
43
59
  it 'uploads raw content' do
44
- stub_request(:post, 'https://target.my.com/api/v2/search_phrases.json?name=list')
45
- .to_return(body: '{"id": 123, "name": "list"}')
46
-
47
- expect(
48
- subject.upload(
60
+ allow(MyTargetApi::NetClient).to(
61
+ receive(:post)
62
+ .and_return(double(code: 200, body: '{"id": 123, "name": "list"}', headers: {}))
63
+ )
64
+
65
+ result = subject.upload(
66
+ 'https://target.my.com/api/v2/search_phrases.json',
67
+ "phrase\nfirst\nsecond",
68
+ name: 'list'
69
+ )
70
+
71
+ expect(MyTargetApi::NetClient).to(
72
+ have_received(:post).with(
49
73
  'https://target.my.com/api/v2/search_phrases.json',
50
74
  "phrase\nfirst\nsecond",
51
- name: 'list'
75
+ 'Content-Type' => 'application/octet-stream',
76
+ params: { name: 'list' }
52
77
  )
53
- ).to eq('id' => 123, 'name' => 'list')
78
+ )
79
+ expect(result).to eq('id' => 123, 'name' => 'list')
54
80
  end
55
81
 
56
82
  it 'raises exception on bad statuses' do
@@ -58,7 +84,28 @@ describe MyTargetApi::Request do
58
84
  .to_return(body: 'Unknown resource', status: 404)
59
85
 
60
86
  expect { subject.get('https://target.my.com/api/v1/wrong_path.json') }
61
- .to raise_error(MyTargetApi::RequestError, 'Unknown resource')
87
+ .to raise_error(MyTargetApi::RequestError,
88
+ '404: Unknown resource. Inspect #params, #response and #original_exception'\
89
+ ' for more details')
90
+ end
91
+
92
+ it 'sets authorization header' do
93
+ allow(MyTargetApi::NetClient).to(
94
+ receive(:get).and_return(double(code: 200,
95
+ body: 'response body',
96
+ headers: {}))
97
+ )
98
+
99
+ request = MyTargetApi::Request.new(access_token: 'my_target_token')
100
+ request.get('https://target.my.com/api/v1/some_path.json')
101
+
102
+ expect(MyTargetApi::NetClient).to(
103
+ have_received(:get).with(
104
+ 'https://target.my.com/api/v1/some_path.json',
105
+ 'Authorization' => 'Bearer my_target_token',
106
+ params: {}
107
+ )
108
+ )
62
109
  end
63
110
  end
64
111
 
@@ -67,11 +114,61 @@ describe MyTargetApi::Request do
67
114
  let(:request) { MyTargetApi::Request.new(logger: logger) }
68
115
 
69
116
  it 'pass parameters by url in get' do
70
- stub_request(:get, 'https://target.my.com/api/v1/request.json')
71
- .to_return(body: '[]')
117
+ logger = double('Logger double', '<<': nil)
118
+ options = { logger: logger }
119
+ request = MyTargetApi::LogRequestParametersDecorator.new(
120
+ MyTargetApi::Request.new(options), options
121
+ )
122
+ allow(MyTargetApi::NetClient).to(
123
+ receive(:get).and_return(double(code: 200,
124
+ body: 'response body',
125
+ headers: {}))
126
+ )
72
127
 
73
- expect(logger).to(receive(:<<))
74
128
  request.get('https://target.my.com/api/v1/request.json')
129
+
130
+ expect(logger).to(have_received(:<<).with("method: Request#get\n"\
131
+ "url: https://target.my.com/api/v1/request.json\n"\
132
+ 'params: {}'))
133
+ expect(logger).to(have_received(:<<).with(<<~LOG))
134
+ HTTP Code: 200
135
+ HTTP Body:
136
+ response body
137
+ HTTP Headers: No headers
138
+ LOG
139
+ end
140
+
141
+ it '404' do
142
+ logger = double('Logger double', '<<': nil)
143
+ options = { logger: logger }
144
+ request = MyTargetApi::LogRequestParametersDecorator.new(
145
+ MyTargetApi::Request.new(options), options
146
+ )
147
+ allow(MyTargetApi::NetClient).to(
148
+ receive(:get).and_return(
149
+ double(
150
+ body: 'Unknown resource',
151
+ code: 404,
152
+ headers: { 'Header': 'Value' }
153
+ )
154
+ )
155
+ )
156
+
157
+ expect { request.get('https://target.my.com/api/v1/request.json') }
158
+ .to raise_error(MyTargetApi::RequestError,
159
+ '404: Unknown resource. Inspect #params, #response and #original_exception'\
160
+ ' for more details')
161
+
162
+ expect(logger).to(have_received(:<<).with("method: Request#get\n"\
163
+ "url: https://target.my.com/api/v1/request.json\n"\
164
+ 'params: {}'))
165
+ expect(logger).to(have_received(:<<).with(<<~LOG))
166
+ HTTP Code: 404
167
+ HTTP Body:
168
+ Unknown resource
169
+ HTTP Headers:
170
+ Header: Value
171
+ LOG
75
172
  end
76
173
  end
77
174
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: my_target_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - OneRetarget.com
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-27 00:00:00.000000000 Z
11
+ date: 2020-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -56,14 +56,14 @@ dependencies:
56
56
  requirements:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
- version: '1.6'
59
+ version: 2.1.4
60
60
  type: :development
61
61
  prerelease: false
62
62
  version_requirements: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
- version: '1.6'
66
+ version: 2.1.4
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: rake
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -110,14 +110,14 @@ dependencies:
110
110
  requirements:
111
111
  - - "~>"
112
112
  - !ruby/object:Gem::Version
113
- version: 0.54.0
113
+ version: 0.89.1
114
114
  type: :development
115
115
  prerelease: false
116
116
  version_requirements: !ruby/object:Gem::Requirement
117
117
  requirements:
118
118
  - - "~>"
119
119
  - !ruby/object:Gem::Version
120
- version: 0.54.0
120
+ version: 0.89.1
121
121
  - !ruby/object:Gem::Dependency
122
122
  name: webmock
123
123
  requirement: !ruby/object:Gem::Requirement
@@ -153,12 +153,15 @@ files:
153
153
  - LICENSE.txt
154
154
  - README.md
155
155
  - lib/my_target_api.rb
156
- - lib/my_target_api/connection_error.rb
156
+ - lib/my_target_api/log_request_parameters_decorator.rb
157
+ - lib/my_target_api/net_client.rb
157
158
  - lib/my_target_api/request.rb
158
159
  - lib/my_target_api/request_error.rb
159
160
  - lib/my_target_api/resource.rb
161
+ - lib/my_target_api/response_formatter.rb
160
162
  - lib/my_target_api/version.rb
161
163
  - my_target_api.gemspec
164
+ - spec/net_client_spec.rb
162
165
  - spec/request_spec.rb
163
166
  - spec/resource_spec.rb
164
167
  - spec/root_spec.rb
@@ -175,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
178
  requirements:
176
179
  - - ">="
177
180
  - !ruby/object:Gem::Version
178
- version: '0'
181
+ version: 2.4.0
179
182
  required_rubygems_version: !ruby/object:Gem::Requirement
180
183
  requirements:
181
184
  - - ">="
@@ -188,6 +191,7 @@ signing_key:
188
191
  specification_version: 4
189
192
  summary: Ruby client for myTarget API
190
193
  test_files:
194
+ - spec/net_client_spec.rb
191
195
  - spec/request_spec.rb
192
196
  - spec/resource_spec.rb
193
197
  - spec/root_spec.rb
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class MyTargetApi
4
- # Error class
5
- class ConnectionError < StandardError
6
-
7
- attr_reader :original_exception
8
-
9
- def initialize(exception)
10
- @original_exception = exception
11
- @exception = exception
12
- end
13
-
14
- def message
15
- @exception.message
16
- end
17
-
18
- end
19
- end