my_api_client 0.14.0.pre → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +179 -38
  3. data/.dependabot/config.yml +19 -1
  4. data/.envrc.skeleton +1 -0
  5. data/.rubocop.yml +9 -1
  6. data/.rubocop_challenge.yml +5 -0
  7. data/.rubocop_todo.yml +29 -1
  8. data/CHANGELOG.md +177 -1
  9. data/Gemfile.lock +47 -45
  10. data/README.jp.md +156 -21
  11. data/bin/console +4 -0
  12. data/example/api_clients/application_api_client.rb +13 -0
  13. data/example/api_clients/my_error_api_client.rb +34 -0
  14. data/example/api_clients/my_errors.rb +27 -0
  15. data/example/api_clients/my_pagination_api_client.rb +18 -0
  16. data/example/api_clients/my_rest_api_client.rb +48 -0
  17. data/example/api_clients/my_status_api_client.rb +22 -0
  18. data/lib/generators/rails/templates/application_api_client.rb.erb +0 -11
  19. data/lib/generators/rspec/templates/api_client_spec.rb.erb +22 -15
  20. data/lib/my_api_client.rb +7 -0
  21. data/lib/my_api_client/base.rb +4 -2
  22. data/lib/my_api_client/default_error_handlers.rb +64 -0
  23. data/lib/my_api_client/error_handling.rb +6 -6
  24. data/lib/my_api_client/error_handling/generator.rb +23 -7
  25. data/lib/my_api_client/errors.rb +1 -53
  26. data/lib/my_api_client/errors/api_limit_error.rb +6 -0
  27. data/lib/my_api_client/errors/client_error.rb +93 -0
  28. data/lib/my_api_client/errors/network_error.rb +43 -0
  29. data/lib/my_api_client/errors/server_error.rb +42 -0
  30. data/lib/my_api_client/request.rb +29 -34
  31. data/lib/my_api_client/request/basic.rb +32 -0
  32. data/lib/my_api_client/request/executor.rb +1 -1
  33. data/lib/my_api_client/request/pagination.rb +39 -0
  34. data/lib/my_api_client/rspec/matchers/request_to.rb +3 -4
  35. data/lib/my_api_client/version.rb +1 -1
  36. data/my_api/.envrc.skeleton +3 -0
  37. data/my_api/.gitignore +14 -0
  38. data/my_api/.jetskeep +1 -0
  39. data/my_api/.rspec +3 -0
  40. data/my_api/.ruby-version +1 -0
  41. data/my_api/Gemfile +23 -0
  42. data/my_api/Gemfile.lock +243 -0
  43. data/my_api/Procfile +7 -0
  44. data/my_api/README.md +54 -0
  45. data/my_api/Rakefile +4 -0
  46. data/my_api/app/controllers/application_controller.rb +5 -0
  47. data/my_api/app/controllers/error_controller.rb +21 -0
  48. data/my_api/app/controllers/pagination_controller.rb +58 -0
  49. data/my_api/app/controllers/rest_controller.rb +60 -0
  50. data/my_api/app/controllers/status_controller.rb +11 -0
  51. data/my_api/app/helpers/application_helper.rb +5 -0
  52. data/my_api/app/jobs/application_job.rb +7 -0
  53. data/my_api/app/models/application_item.rb +5 -0
  54. data/my_api/config.ru +7 -0
  55. data/my_api/config/application.rb +73 -0
  56. data/my_api/config/dynamodb.yml +22 -0
  57. data/my_api/config/environments/development.rb +9 -0
  58. data/my_api/config/environments/production.rb +11 -0
  59. data/my_api/config/environments/test.rb +9 -0
  60. data/my_api/config/routes.rb +17 -0
  61. data/my_api/db/.gitkeep +0 -0
  62. data/my_api/public/404.html +67 -0
  63. data/my_api/public/422.html +67 -0
  64. data/my_api/public/500.html +66 -0
  65. data/my_api/public/favicon.ico +0 -0
  66. data/my_api/public/index.html +91 -0
  67. data/my_api/spec/controllers/error_controller_spec.rb +43 -0
  68. data/my_api/spec/controllers/pagination_controller_spec.rb +73 -0
  69. data/my_api/spec/controllers/rest_controller_spec.rb +99 -0
  70. data/my_api/spec/controllers/status_controller_spec.rb +47 -0
  71. data/my_api/spec/fixtures/payloads/posts-index.json +51 -0
  72. data/my_api/spec/fixtures/payloads/posts-show.json +53 -0
  73. data/my_api/spec/spec_helper.rb +31 -0
  74. data/rails_app/rails_5.2/.rspec +3 -0
  75. data/rails_app/rails_5.2/Gemfile +18 -0
  76. data/rails_app/rails_5.2/Gemfile.lock +171 -0
  77. data/rails_app/rails_5.2/README.md +24 -0
  78. data/rails_app/rails_5.2/Rakefile +8 -0
  79. data/rails_app/rails_5.2/app/controllers/application_controller.rb +4 -0
  80. data/rails_app/rails_5.2/app/jobs/application_job.rb +4 -0
  81. data/rails_app/rails_5.2/bin/bundle +5 -0
  82. data/rails_app/rails_5.2/bin/rails +6 -0
  83. data/rails_app/rails_5.2/bin/rake +6 -0
  84. data/rails_app/rails_5.2/bin/setup +27 -0
  85. data/rails_app/rails_5.2/bin/update +27 -0
  86. data/rails_app/rails_5.2/config.ru +7 -0
  87. data/rails_app/rails_5.2/config/application.rb +37 -0
  88. data/rails_app/rails_5.2/config/boot.rb +6 -0
  89. data/rails_app/rails_5.2/config/credentials.yml.enc +1 -0
  90. data/rails_app/rails_5.2/config/environment.rb +7 -0
  91. data/rails_app/rails_5.2/config/environments/development.rb +41 -0
  92. data/rails_app/rails_5.2/config/environments/production.rb +70 -0
  93. data/rails_app/rails_5.2/config/environments/test.rb +38 -0
  94. data/rails_app/rails_5.2/config/initializers/application_controller_renderer.rb +9 -0
  95. data/rails_app/rails_5.2/config/initializers/backtrace_silencers.rb +8 -0
  96. data/rails_app/rails_5.2/config/initializers/cors.rb +17 -0
  97. data/rails_app/rails_5.2/config/initializers/filter_parameter_logging.rb +6 -0
  98. data/rails_app/rails_5.2/config/initializers/inflections.rb +17 -0
  99. data/rails_app/rails_5.2/config/initializers/mime_types.rb +5 -0
  100. data/rails_app/rails_5.2/config/initializers/wrap_parameters.rb +11 -0
  101. data/rails_app/rails_5.2/config/locales/en.yml +33 -0
  102. data/rails_app/rails_5.2/config/routes.rb +5 -0
  103. data/rails_app/rails_5.2/config/spring.rb +8 -0
  104. data/rails_app/rails_5.2/public/robots.txt +1 -0
  105. data/rails_app/rails_5.2/spec/rails_helper.rb +14 -0
  106. data/rails_app/rails_5.2/spec/spec_helper.rb +13 -0
  107. data/rails_app/rails_6.0/.rspec +3 -0
  108. data/rails_app/rails_6.0/Gemfile +17 -0
  109. data/rails_app/rails_6.0/Gemfile.lock +186 -0
  110. data/rails_app/rails_6.0/README.md +24 -0
  111. data/rails_app/rails_6.0/Rakefile +8 -0
  112. data/rails_app/rails_6.0/app/controllers/application_controller.rb +4 -0
  113. data/rails_app/rails_6.0/app/jobs/application_job.rb +9 -0
  114. data/rails_app/rails_6.0/bin/rails +6 -0
  115. data/rails_app/rails_6.0/bin/rake +6 -0
  116. data/rails_app/rails_6.0/bin/setup +27 -0
  117. data/rails_app/rails_6.0/config.ru +7 -0
  118. data/rails_app/rails_6.0/config/application.rb +39 -0
  119. data/rails_app/rails_6.0/config/boot.rb +6 -0
  120. data/rails_app/rails_6.0/config/credentials.yml.enc +1 -0
  121. data/rails_app/rails_6.0/config/environment.rb +7 -0
  122. data/rails_app/rails_6.0/config/environments/development.rb +39 -0
  123. data/rails_app/rails_6.0/config/environments/production.rb +90 -0
  124. data/rails_app/rails_6.0/config/environments/test.rb +41 -0
  125. data/rails_app/rails_6.0/config/initializers/application_controller_renderer.rb +9 -0
  126. data/rails_app/rails_6.0/config/initializers/backtrace_silencers.rb +8 -0
  127. data/rails_app/rails_6.0/config/initializers/cors.rb +17 -0
  128. data/rails_app/rails_6.0/config/initializers/filter_parameter_logging.rb +6 -0
  129. data/rails_app/rails_6.0/config/initializers/inflections.rb +17 -0
  130. data/rails_app/rails_6.0/config/initializers/mime_types.rb +5 -0
  131. data/rails_app/rails_6.0/config/initializers/wrap_parameters.rb +11 -0
  132. data/rails_app/rails_6.0/config/locales/en.yml +33 -0
  133. data/rails_app/rails_6.0/config/routes.rb +5 -0
  134. data/rails_app/rails_6.0/config/spring.rb +8 -0
  135. data/rails_app/rails_6.0/public/robots.txt +1 -0
  136. data/rails_app/rails_6.0/spec/rails_helper.rb +14 -0
  137. data/rails_app/rails_6.0/spec/spec_helper.rb +13 -0
  138. metadata +120 -5
  139. data/renovate.json +0 -21
@@ -4,6 +4,7 @@ module MyApiClient
4
4
  # The ancestor class for all API request error
5
5
  class Error < StandardError
6
6
  attr_reader :params
7
+
7
8
  delegate :metadata, to: :params
8
9
  alias to_bugsnag metadata
9
10
 
@@ -25,57 +26,4 @@ module MyApiClient
25
26
  { error: super, params: params }.inspect
26
27
  end
27
28
  end
28
-
29
- NETWORK_ERRORS = [
30
- Faraday::TimeoutError,
31
- Faraday::ConnectionFailed,
32
- Faraday::SSLError,
33
- OpenSSL::SSL::SSLError,
34
- Net::OpenTimeout,
35
- Net::ReadTimeout,
36
- SocketError,
37
- ].freeze
38
-
39
- # Raises it when occurred to some network error
40
- class NetworkError < Error
41
- attr_reader :original_error
42
-
43
- # Initialize the error class
44
- #
45
- # @param params [MyApiClient::Params::Params]
46
- # The request and response parameters
47
- # @param original_error [StandardError]
48
- # Some network error
49
- def initialize(params, original_error)
50
- @original_error = original_error
51
- super params, original_error.message
52
- end
53
-
54
- # Returns contents as string for to be readable for human
55
- #
56
- # @return [String] Contents as string
57
- def inspect
58
- { error: original_error, params: params }.inspect
59
- end
60
-
61
- # Generate metadata for bugsnag.
62
- #
63
- # @return [Hash] Metadata for bugsnag
64
- def metadata
65
- super.merge(original_error: original_error.inspect)
66
- end
67
- end
68
-
69
- # NOTE: The built-in error classes are following. Although they are prepared
70
- # to save the trouble of defining, but you can create any error classes
71
- # which inherit the ancestor error class.
72
-
73
- # For 4xx client error
74
- class ClientError < Error; end
75
-
76
- # For 5xx server error
77
- class ServerError < Error; end
78
-
79
- # For API request limit error
80
- class ApiLimitError < Error; end
81
29
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MyApiClient
4
+ # For API request limit error
5
+ class ApiLimitError < Error; end
6
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MyApiClient
4
+ # For 4xx client error
5
+ class ClientError < Error
6
+ # 400 Bad Request
7
+ class BadRequest < ClientError; end
8
+
9
+ # 401 Unauthorized
10
+ class Unauthorized < ClientError; end
11
+
12
+ # 402 Payment Required
13
+ class PaymentRequired < ClientError; end
14
+
15
+ # 403 Forbidden
16
+ class Forbidden < ClientError; end
17
+
18
+ # 404 Not Found
19
+ class NotFound < ClientError; end
20
+
21
+ # 405 Method Not Allowed
22
+ class MethodNotAllowed < ClientError; end
23
+
24
+ # 406 Not Acceptable
25
+ class NotAcceptable < ClientError; end
26
+
27
+ # 407 Proxy Authentication Required
28
+ class ProxyAuthenticationRequired < ClientError; end
29
+
30
+ # 408 Request Timeout
31
+ class RequestTimeout < ClientError; end
32
+
33
+ # 409 Conflict
34
+ class Conflict < ClientError; end
35
+
36
+ # 410 Gone
37
+ class Gone < ClientError; end
38
+
39
+ # 411 Length Required
40
+ class LengthRequired < ClientError; end
41
+
42
+ # 412 Precondition Failed
43
+ class PreconditionFailed < ClientError; end
44
+
45
+ # 413 Payload Too Large
46
+ class RequestEntityTooLarge < ClientError; end
47
+
48
+ # 414 URI Too Long
49
+ class RequestUriTooLong < ClientError; end
50
+
51
+ # 415 Unsupported Media Type
52
+ class UnsupportedMediaType < ClientError; end
53
+
54
+ # 416 Range Not Satisfiable
55
+ class RequestedRangeNotSatisfiable < ClientError; end
56
+
57
+ # 417 Expectation Failed
58
+ class ExpectationFailed < ClientError; end
59
+
60
+ # 418 I'm a teapot
61
+ class IamTeapot < ClientError; end
62
+
63
+ # 421 Misdirected Request
64
+ class MisdirectedRequest < ClientError; end
65
+
66
+ # 422 Unprocessable Entity
67
+ class UnprocessableEntity < ClientError; end
68
+
69
+ # 423 Locked
70
+ class Locked < ClientError; end
71
+
72
+ # 424 Failed Dependency
73
+ class FailedDependency < ClientError; end
74
+
75
+ # 425 Too Early
76
+ class TooEarly < ClientError; end
77
+
78
+ # 426 Upgrade Required
79
+ class UpgradeRequired < ClientError; end
80
+
81
+ # 428 Precondition Required
82
+ class PreconditionRequired < ClientError; end
83
+
84
+ # 429 Too Many Requests
85
+ class TooManyRequests < ClientError; end
86
+
87
+ # 431 Request Header Fields Too Large
88
+ class RequestHeaderFieldsTooLarge < ClientError; end
89
+
90
+ # 451 Unavailable for Legal Reasons
91
+ class UnavailableForLegalReasons < ClientError; end
92
+ end
93
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MyApiClient
4
+ NETWORK_ERRORS = [
5
+ Faraday::TimeoutError,
6
+ Faraday::ConnectionFailed,
7
+ Faraday::SSLError,
8
+ OpenSSL::SSL::SSLError,
9
+ Net::OpenTimeout,
10
+ Net::ReadTimeout,
11
+ SocketError,
12
+ ].freeze
13
+
14
+ # Raises it when occurred to some network error
15
+ class NetworkError < Error
16
+ attr_reader :original_error
17
+
18
+ # Initialize the error class
19
+ #
20
+ # @param params [MyApiClient::Params::Params]
21
+ # The request and response parameters
22
+ # @param original_error [StandardError]
23
+ # Some network error
24
+ def initialize(params, original_error)
25
+ @original_error = original_error
26
+ super params, original_error.message
27
+ end
28
+
29
+ # Returns contents as string for to be readable for human
30
+ #
31
+ # @return [String] Contents as string
32
+ def inspect
33
+ { error: original_error, params: params }.inspect
34
+ end
35
+
36
+ # Generate metadata for bugsnag.
37
+ #
38
+ # @return [Hash] Metadata for bugsnag
39
+ def metadata
40
+ super.merge(original_error: original_error.inspect)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MyApiClient
4
+ # For 5xx server error
5
+ class ServerError < Error
6
+ # 500 Internal Server Error
7
+ class InternalServerError < ServerError; end
8
+
9
+ # 501 Not Implemented
10
+ class NotImplemented < ServerError; end
11
+
12
+ # 502 Bad Gateway
13
+ class BadGateway < ServerError; end
14
+
15
+ # 503 Service Unavailable
16
+ class ServiceUnavailable < ServerError; end
17
+
18
+ # 504 Gateway Timeout
19
+ class GatewayTimeout < ServerError; end
20
+
21
+ # 505 HTTP Version Not Supported
22
+ class HttpVersionNotSupported < ServerError; end
23
+
24
+ # 506 Variant Also Negotiates
25
+ class VariantAlsoNegotiates < ServerError; end
26
+
27
+ # 507 Insufficient Storage
28
+ class InsufficientStorage < ServerError; end
29
+
30
+ # 508 Loop Detected
31
+ class LoopDetected < ServerError; end
32
+
33
+ # 509 Bandwidth Limit Exceeded
34
+ class BandwidthLimitExceeded < ServerError; end
35
+
36
+ # 510 Not Extended
37
+ class NotExtended < ServerError; end
38
+
39
+ # 511 Network Authentication Required
40
+ class NetworkAuthenticationRequired < ServerError; end
41
+ end
42
+ end
@@ -1,41 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MyApiClient
4
- # Description of Request
4
+ # Provides HTTP request method.
5
5
  module Request
6
- HTTP_METHODS = %i[get post patch delete].freeze
7
-
8
- HTTP_METHODS.each do |http_method|
9
- class_eval <<~METHOD, __FILE__, __LINE__ + 1
10
- # Executes HTTP request with #{http_method.upcase} method
11
- #
12
- # @param pathname [String]
13
- # Pathname of the request target URL.
14
- # It's joined with the defined `endpoint`.
15
- # @param headers [Hash, nil]
16
- # Request headers.
17
- # @param query [Hash, nil]
18
- # Query string.
19
- # @param body [Hash, nil]
20
- # Request body. You should not specify it when use GET method.
21
- # @return [Sawyer::Resouce]
22
- # Response body instance.
23
- def #{http_method}(pathname, headers: nil, query: nil, body: nil)
24
- query_strings = query.present? ? '?' + query&.to_query : ''
25
- uri = URI.join(File.join(endpoint, pathname), query_strings)
26
- response = call(:_request, :#{http_method}, uri, headers, body)
27
- response.data
28
- end
29
- METHOD
30
- end
31
- alias put patch
6
+ include Basic
7
+ include Pagination
32
8
 
33
9
  private
34
10
 
35
- # Executes HTTP request.
11
+ # Executes HTTP request with relative URI.
12
+ #
13
+ # @param http_method [Symbol]
14
+ # HTTP method. e.g. `:get`, `:post`, `:put`, `:patch` and `:delete`.
15
+ # @param pathname [String]
16
+ # Pathname of the request target URL.
17
+ # It's joined with the defined by `endpoint`.
18
+ # @param headers [Hash, nil]
19
+ # Request headers.
20
+ # @param query [Hash, nil]
21
+ # Query string.
22
+ # @param body [Hash, nil]
23
+ # Request body.
24
+ # @return [Sawyer::Response]
25
+ # Response instance.
26
+ def _request_with_relative_uri(http_method, pathname, headers, query, body)
27
+ query_strings = query.present? ? '?' + query&.to_query : ''
28
+ uri = URI.join(File.join(endpoint, pathname), query_strings)
29
+ _request_with_absolute_uri(http_method, uri, headers, body)
30
+ end
31
+
32
+ # Executes HTTP request with absolute URI.
36
33
  #
37
34
  # @param http_method [Symbol]
38
- # HTTP method. e.g. `:get`, `:post`, `:patch` and `:delete`.
35
+ # HTTP method. e.g. `:get`, `:post`, `:put`, `:patch` and `:delete`.
39
36
  # @param uri [URI]
40
37
  # Request target URI including query strings.
41
38
  # @param headers [Hash, nil]
@@ -44,13 +41,11 @@ module MyApiClient
44
41
  # Request body.
45
42
  # @return [Sawyer::Response]
46
43
  # Response instance.
47
- def _request(http_method, uri, headers, body)
48
- request_params = Params::Request.new(http_method, uri, headers, body)
49
- request_logger = Logger.new(logger, http_method, uri)
44
+ def _request_with_absolute_uri(http_method, uri, headers, body)
50
45
  Executor.call(
51
46
  instance: self,
52
- request_params: request_params,
53
- request_logger: request_logger,
47
+ request_params: Params::Request.new(http_method, uri, headers, body),
48
+ request_logger: Logger.new(logger, http_method, uri),
54
49
  faraday_options: faraday_options
55
50
  )
56
51
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MyApiClient
4
+ module Request
5
+ # Provides basic HTTP request method.
6
+ module Basic
7
+ HTTP_METHODS = %i[get post put patch delete].freeze
8
+
9
+ HTTP_METHODS.each do |http_method|
10
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
11
+ # Executes HTTP request with #{http_method.upcase} method
12
+ #
13
+ # @param pathname [String]
14
+ # Pathname of the request target URL.
15
+ # It's joined with the defined by `endpoint`.
16
+ # @param headers [Hash, nil]
17
+ # Request headers.
18
+ # @param query [Hash, nil]
19
+ # Query string.
20
+ # @param body [Hash, nil]
21
+ # Request body. You should not specify it when use GET method.
22
+ # @return [Sawyer::Resource]
23
+ # Response body instance.
24
+ def #{http_method}(pathname, headers: nil, query: nil, body: nil)
25
+ response = call(:_request_with_relative_uri, :#{http_method}, pathname, headers, query, body)
26
+ response.data
27
+ end
28
+ METHOD
29
+ end
30
+ end
31
+ end
32
+ end
@@ -32,7 +32,7 @@ module MyApiClient
32
32
  def call
33
33
  request_logger.info('Start')
34
34
  response = api_request
35
- request_logger.info("Duration #{response.timing} sec")
35
+ request_logger.info("Duration #{response.timing.in_milliseconds} msec")
36
36
  verify(response)
37
37
  rescue MyApiClient::Error => e
38
38
  request_logger.warn("Failure (#{e.message})")
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MyApiClient
4
+ module Request
5
+ # Provides enumerable HTTP request method.
6
+ module Pagination
7
+ # Executes HTTP request with GET method, for pagination API. Expects the
8
+ # pagination API to provide pagination links as part of the content of the response.
9
+ #
10
+ # @param pathname [String]
11
+ # Pathname of the request target URL. It's joined with the defined by `endpoint`.
12
+ # @param paging [String]
13
+ # Specify the pagination link path included in the response body as JsonPath expression
14
+ # @param headers [Hash, nil]
15
+ # Request headers.
16
+ # @param query [Hash, nil]
17
+ # Query string.
18
+ # @param body [Hash, nil]
19
+ # Request body. You should not specify it when use GET method.
20
+ # @return [Enumerator::Lazy]
21
+ # Yields the pagination API response.
22
+ def pageable_get(pathname, paging:, headers: nil, query: nil)
23
+ Enumerator.new do |y|
24
+ response = call(:_request_with_relative_uri, :get, pathname, headers, query, nil)
25
+ loop do
26
+ y << response.data
27
+
28
+ next_uri = JsonPath.new(paging).first(response.body)
29
+ break if next_uri.blank?
30
+
31
+ response = call(:_request_with_absolute_uri, :get, next_uri, headers, nil)
32
+ end
33
+ end.lazy
34
+ end
35
+
36
+ alias pget pageable_get
37
+ end
38
+ end
39
+ end
@@ -8,10 +8,9 @@ RSpec::Matchers.define :request_to do |expected_method, expected_url|
8
8
  match do |api_request|
9
9
  disable_logging
10
10
  @expected = {
11
- request_line: request_line(expected_method, expected_url),
11
+ request_line: request_line(expected_method, expected_url, expected_options[:query]),
12
12
  body: expected_options[:body],
13
13
  headers: expected_options[:headers],
14
- query: expected_options[:query],
15
14
  }.compact
16
15
  @actual = {}
17
16
  sawyer = instance_double(Sawyer::Agent)
@@ -24,7 +23,6 @@ RSpec::Matchers.define :request_to do |expected_method, expected_url|
24
23
  request_line: request_line(method, @actual_schema_and_hostname + pathname),
25
24
  body: body,
26
25
  headers: options[:headers],
27
- query: options[:query],
28
26
  }.compact
29
27
  end.and_return(dummy_response)
30
28
  safe_execution(api_request)
@@ -51,7 +49,8 @@ RSpec::Matchers.define :request_to do |expected_method, expected_url|
51
49
  nil
52
50
  end
53
51
 
54
- def request_line(method, url)
52
+ def request_line(method, url, query = nil)
53
+ url += '?' + query.to_query if query.present?
55
54
  "#{method.upcase} #{url}"
56
55
  end
57
56