rest_api_builder 0.0.1 → 0.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1ffe941de96bc46453108079ed3dce2d654947b2930f2127c2e18737c9b00199
4
- data.tar.gz: 59665b1e50fe3a2ab479d73dd549a2369718f6f2ba7adc02b66399b1a6c32a24
3
+ metadata.gz: 7e04eb4a2a88c29a02d4fc831018d118ce8cd570f7523625cc83bd155041734a
4
+ data.tar.gz: 1092c81256426cb4d0e590452c0831291b20697108a07358fe5efdc5761d74b0
5
5
  SHA512:
6
- metadata.gz: cf33cca8a23fdfe9302e0fd6e9fabfddb4b67bc73c762f91689f1bf0130d6827c5545f5eb9ee3e4dda639f053fdc07a9ab92c175463b370ee2884e52c6ea3dbe
7
- data.tar.gz: 8a70a3bbf1b7cd2c83b5ad65c45b98191a32daf864ac826fa40920f30a4f423169e9bfbadd6896eee2f6796b886f4caeabe65fa90fad834ff8d1b9b7ca574e1b
6
+ metadata.gz: b494a395a84ce64096cbe07231457e742de4ddd812bdf092e00e717db0c078496c907d81d19e671f32ce484f8b6464e310aba16184c6ed4724d0c0c19f7a5749
7
+ data.tar.gz: 2626417df9c9241d33ac3e76b2a9a5f64638b6a0397785c470f921303fb47188ab606914fc4890b47aaf4fd4fdc6f96fe8c6569ac9a29f114b9854ef66d48c29
data/LICENSE CHANGED
File without changes
data/README.md CHANGED
@@ -84,7 +84,7 @@ response[:status] #=> 200
84
84
  response[:body] #=> ''
85
85
  response[:headers] #=> {}
86
86
 
87
- # Specifying response details
87
+ # Specifying expectation details with WebMock::Request methods
88
88
  Expectations
89
89
  .expect_execute(base_url: "test.com", method: :get)
90
90
  .to_return(status: 404, body: "not found")
@@ -93,6 +93,29 @@ response = Request.execute(base_url: "test.com", method: :get)
93
93
  response[:success] #=> false
94
94
  response[:status] #=> 404
95
95
  response[:body] #=> "not found"
96
+
97
+ # Specifying expectation details with :request and :response options
98
+ Expectations.expect_execute(
99
+ base_url: "test.com",
100
+ method: :post,
101
+ response: { body: 'hello' },
102
+ request: { body: WebMock::API.hash_including({foo: "bar"}) }
103
+ )
104
+ response = Request.json_execute(base_url: "test.com", method: :post, body: {foo: "bar"})
105
+ response[:success] #=> true
106
+ response[:body] #=> 'hello'
107
+
108
+ Request.json_execute(base_url: "test.com", method: :post, body: {bar: "baz"}) # => Raises WebMock::NetConnectNotAllowedError
109
+
110
+ # Using #expect_json_execute
111
+ Expectations.expect_json_execute(
112
+ base_url: "test.com",
113
+ method: :get,
114
+ response: { body: {hi: 'hello'} }
115
+ )
116
+ response = Request.execute(base_url: "test.com", method: :get)
117
+ response[:success] #=> true
118
+ response[:body] #=> "{\"hi\":\"hello\"}"
96
119
  ```
97
120
 
98
121
  ## Request API
@@ -110,6 +133,7 @@ Does not throw on non-200 responses like RestClient does, but will throw on any
110
133
  * **query**: Query hash to be appended to the resulting url. Optional.
111
134
  * **logger**: A `Logger` instance to be passed to RestClient in `log` option. Will also log response details as RestClient does not do this by default. Optional
112
135
  * **parse_json**: Boolean. If `true`, will attempt to parse the response body as JSON. Will return the response body unchanged if it does not contain valid JSON. `false` by default.
136
+ * **raw_response**: Boolean. If `true`, the response returned by RestClient will not be parsed into {:status, :body, :headers}, but instead returned as {:raw_response}. `false` by default.
113
137
  * **rest_client_options**: Any additional options to be passed to `RestClient::Request.execute` unchanged. **Any option set here will completely overwrite all custom options**. For example, if you call `RestAPIBuilder::Request.execute(method: :post, rest_client_options: {method: :get})`, the resulting request will be sent as GET. Optional.
114
138
 
115
139
  ### RestAPIBuilder::Request.json_execute(options)
@@ -127,6 +151,11 @@ Defines a request expectation using WebMock's `stub_request`. Returns an instanc
127
151
  * **base_url**: Base URL of the request. Required.
128
152
  * **method**: HTTP method of the request(e.g :get, :post, :patch). Required.
129
153
  * **path**: Path to be appended to the :base_url. Optional.
154
+ * **request**: request details which will be passed to `WebMock::RequestStub#with` if provided. Optional
155
+ * **response**: response details which will be passed to `WebMock::RequestStub#to_return` if provided. Optional
156
+
157
+ ### RestAPIBuilder::WebMockRequestExpectations.expect_json_execute(options)
158
+ A convenience shortcut for `#json_execute` which will convert `request[:body]` to JSON if it's provided
130
159
 
131
160
  ## License
132
161
  MIT
@@ -1 +1,21 @@
1
+ require 'forwardable'
1
2
  require 'rest_api_builder/request'
3
+ require 'rest_api_builder/request_options'
4
+ require 'rest_api_builder/response_handler'
5
+
6
+ module RestAPIBuilder
7
+ extend Forwardable
8
+
9
+ def_delegator :request_options, :compose, :compose_request_options
10
+ def_delegator :request_options, :compose_json, :compose_json_request_options
11
+
12
+ def_delegators :response_handler, :handle_response, :handle_json_response, :handle_response_error
13
+
14
+ def request_options
15
+ RequestOptions.new
16
+ end
17
+
18
+ def response_handler
19
+ ResponseHandler.new
20
+ end
21
+ end
@@ -1,11 +1,7 @@
1
1
  require 'rest-client'
2
- require 'rest_api_builder/url_helper'
3
- require 'rest_api_builder/rest_client_response_parser'
4
2
 
5
3
  module RestAPIBuilder
6
4
  class RequestSingleton
7
- include RestAPIBuilder::UrlHelper
8
-
9
5
  def json_execute(headers: {}, body: nil, **options)
10
6
  headers = headers.merge(content_type: :json)
11
7
  body &&= JSON.generate(body)
@@ -21,29 +17,27 @@ module RestAPIBuilder
21
17
  path: nil,
22
18
  logger: nil,
23
19
  parse_json: false,
20
+ raw_response: false,
24
21
  rest_client_options: {}
25
22
  )
26
- if method == :get && body
27
- raise ArgumentError, 'GET requests do not support body'
28
- end
29
-
30
- response_parser = RestAPIBuilder::RestClientResponseParser.new(logger: logger, parse_json: parse_json)
31
- headers = headers.merge(params: query) if query
23
+ options = RequestOptions.new.compose(
24
+ base_url: base_url,
25
+ method: method,
26
+ body: body,
27
+ headers: headers,
28
+ query: query,
29
+ path: path
30
+ )
32
31
 
33
- begin
34
- response = RestClient::Request.execute(
35
- method: method,
36
- url: full_url(base_url, path),
37
- payload: body,
38
- headers: headers,
39
- log: logger,
40
- **rest_client_options
41
- )
42
- response_parser.parse_response(response, success: true)
43
- rescue RestClient::RequestFailed => e
44
- raise e unless e.response
32
+ response_handler = ResponseHandler.new
33
+ execute_request = proc { RestClient::Request.execute(**options, log: logger, **rest_client_options) }
45
34
 
46
- response_parser.parse_response(e.response, success: false)
35
+ if raw_response
36
+ response_handler.handle_response_error(&execute_request)
37
+ elsif parse_json
38
+ response_handler.handle_json_response(logger: logger, &execute_request)
39
+ else
40
+ response_handler.handle_response(logger: logger, &execute_request)
47
41
  end
48
42
  end
49
43
  end
@@ -0,0 +1,33 @@
1
+ require 'rest_api_builder/url_helper'
2
+
3
+ module RestAPIBuilder
4
+ class RequestOptions
5
+ include RestAPIBuilder::UrlHelper
6
+
7
+ def compose(base_url:, method:, path: nil, body: nil, headers: {}, query: nil)
8
+ if method == :get && body
9
+ raise ArgumentError, 'GET requests do not support body'
10
+ end
11
+
12
+ headers = headers.merge(params: query) if query
13
+
14
+ {
15
+ method: method,
16
+ url: full_url(base_url, path),
17
+ payload: body,
18
+ headers: headers
19
+ }
20
+ end
21
+
22
+ def compose_json(**options)
23
+ result = compose(**options)
24
+ headers = result[:headers]
25
+ payload = result[:payload]
26
+
27
+ result.merge(
28
+ headers: headers.merge(content_type: :json),
29
+ payload: payload && JSON.generate(payload)
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,44 @@
1
+ module RestAPIBuilder
2
+ class ResponseHandler
3
+ def handle_json_response(**options, &block)
4
+ result = handle_response(**options, &block)
5
+ result.merge(body: parse_json(result[:body]))
6
+ end
7
+
8
+ def handle_response(logger: nil, &block)
9
+ result = parse_response(**handle_response_error(&block))
10
+ maybe_log_result(result, logger: logger)
11
+ result
12
+ end
13
+
14
+ def handle_response_error
15
+ response = yield
16
+ { raw_response: response, success: true }
17
+ rescue RestClient::RequestFailed => e
18
+ raise e unless e.response
19
+
20
+ { raw_response: e.response, success: false }
21
+ end
22
+
23
+ private
24
+
25
+ def parse_response(raw_response:, success:)
26
+ {
27
+ success: success,
28
+ status: raw_response.code,
29
+ body: raw_response.body,
30
+ headers: raw_response.headers
31
+ }
32
+ end
33
+
34
+ def maybe_log_result(result, logger:)
35
+ logger && logger << "# => Response: #{result}\n"
36
+ end
37
+
38
+ def parse_json(json)
39
+ JSON.parse(json)
40
+ rescue JSON::ParserError
41
+ json
42
+ end
43
+ end
44
+ end
File without changes
@@ -6,8 +6,21 @@ module RestAPIBuilder
6
6
  include WebMock::API
7
7
  include RestAPIBuilder::UrlHelper
8
8
 
9
- def expect_execute(base_url:, method:, path: nil)
10
- stub_request(method, full_url(base_url, path))
9
+ def expect_json_execute(response: nil, **options)
10
+ if response && response[:body]
11
+ response = response.merge(body: JSON.generate(response[:body]))
12
+ end
13
+
14
+ expect_execute(**options, response: response)
15
+ end
16
+
17
+ def expect_execute(base_url:, method:, path: nil, request: nil, response: nil)
18
+ expectation = stub_request(method, full_url(base_url, path))
19
+
20
+ expectation.with(request) if request
21
+ expectation.to_return(response) if response
22
+
23
+ expectation
11
24
  end
12
25
  end
13
26
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rest_api_builder'
3
- s.version = '0.0.1'
3
+ s.version = '0.0.6'
4
4
  s.summary = "A simple wrapper for rest-client"
5
5
  s.description = "A simple wrapper for rest-client aiming to make creation and testing of API clients easier."
6
6
  s.authors = ["Alexey D"]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest_api_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey D
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-16 00:00:00.000000000 Z
11
+ date: 2020-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -63,7 +63,8 @@ files:
63
63
  - README.md
64
64
  - lib/rest_api_builder.rb
65
65
  - lib/rest_api_builder/request.rb
66
- - lib/rest_api_builder/rest_client_response_parser.rb
66
+ - lib/rest_api_builder/request_options.rb
67
+ - lib/rest_api_builder/response_handler.rb
67
68
  - lib/rest_api_builder/url_helper.rb
68
69
  - lib/rest_api_builder/webmock_request_expectations.rb
69
70
  - rest_api_builder.gemspec
@@ -86,7 +87,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
87
  - !ruby/object:Gem::Version
87
88
  version: '0'
88
89
  requirements: []
89
- rubygems_version: 3.1.2
90
+ rubyforge_project:
91
+ rubygems_version: 2.7.8
90
92
  signing_key:
91
93
  specification_version: 4
92
94
  summary: A simple wrapper for rest-client
@@ -1,35 +0,0 @@
1
- require 'json'
2
-
3
- module RestAPIBuilder
4
- class RestClientResponseParser
5
- def initialize(logger:, parse_json:)
6
- @logger = logger
7
- @parse_json = parse_json
8
- end
9
-
10
- def parse_response(response, success:)
11
- body = @parse_json ? parse_json(response.body) : response.body
12
- result = {
13
- success: success,
14
- status: response.code,
15
- body: body,
16
- headers: response.headers
17
- }
18
- maybe_log_result(result)
19
-
20
- result
21
- end
22
-
23
- private
24
-
25
- def parse_json(json)
26
- JSON.parse(json)
27
- rescue JSON::ParserError
28
- json
29
- end
30
-
31
- def maybe_log_result(result)
32
- @logger && @logger << "# => Response: #{result}"
33
- end
34
- end
35
- end