fulfil-io 0.4.8 → 0.5.0

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: 2ee812b819341ca5960284540853594c9ec4ec07735f75672913cbdce1e7bf72
4
- data.tar.gz: 01f68a856b317a9ccc00946bac7ce06e638e9d016bf075a7e4130d17420f7c8a
3
+ metadata.gz: 1100e113c9323c0fa742ece65d8a41923c060c382b1b97ad6c50ad20c550b5a9
4
+ data.tar.gz: 80535f7bea24218d958812bbd8e4ab789ce966c346e5dfa891369160fc04e536
5
5
  SHA512:
6
- metadata.gz: cb6a91114dea84e8c578f96ab2599ad03c036fc3222bf4b494f8cd32f79944b744660a2c0e4c7c45602e05e28f651eb6a6786a51e591950e04e36b291b3755a3
7
- data.tar.gz: 7d107fba6190bafa996da7cb9f081089d64d7d8bc1f1cbf2506e30b310e789b2567669b84208dc807456372e1330ebce5ac701b762f4d0c95b38551de18daf83
6
+ metadata.gz: b1ea6e403ab80bb108a90dff5f7ad58c39c228ed610ce497c631b5ae45a3ef5d2912100acd95ee33d7f2aa7c5609b71300c7a2322e1b2efcec688646573bf8da
7
+ data.tar.gz: d63d23350f0775bac73f28fdbabd0645798ed28a0466e7851ade38328a9f17e7a75982bc6bada6c1d951e4eb3ed0a4ffd872c79a6dc3c848f4308ddcfd11db16
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.4.9
2
+
3
+ * Add client tests and stub with Webmock.
4
+
1
5
  ## 0.4.8
2
6
 
3
7
  * Feature: Allow more params with InteractiveReport.
data/README.md CHANGED
@@ -129,10 +129,48 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
129
129
  `rake test` to run the tests. You can also run `bin/console` for an interactive
130
130
  prompt that will allow you to experiment.
131
131
 
132
- To install this gem onto your local machine, run `bundle exec rake install`. To
133
- release a new version, update the version number in `version.rb`, and then run
134
- `bundle exec rake release`, which will create a git tag for the version, push
135
- git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
132
+ To install this gem onto your local machine, run `bundle exec rake install`.
133
+
134
+ ### Release a new version
135
+
136
+ We're following semver for the release process of this gem. Make sure to apply the correct semver version for a new release.
137
+
138
+ To release a new version, run the `bin/release x.x.x`. That's it.
139
+
140
+ > **NOTE:** You don't have to add a v to the version you want to release. The release script will handle that for you.
141
+
142
+ ### Testing
143
+
144
+ For non-client tests, create the test class or case.
145
+
146
+ For client tests, you'll need to add a couple steps. If running against a real
147
+ backend, you'll need to provide a couple of environment variables:
148
+ `FULFIL_SUBDOMAIN` and `FULFIL_TOKEN`. Additionally, pass `debug: true` to the
149
+ client instance in the test. This will output the response body. Webmock will
150
+ probably complain that real requests aren't allowed at this point, offering you
151
+ the stub. We don't need most of that.
152
+
153
+ We will need to capture the response body as JSON and store it in the
154
+ `test/fixtures` directory. Formatted for readability, please. You'll also need
155
+ to make note of the path and body of the request. Once you have that, you can
156
+ generate your stub.
157
+
158
+ To stub a request, use (or create) the helper method based on the verb. For
159
+ example, to stub a `GET` request, use `stub_fulfil_get`. Here's an example:
160
+
161
+ ```ruby
162
+ def test_find_one
163
+ stub_fulfil_get('sale.sale/213112', 'sale_sale')
164
+
165
+ client = Fulfil::Client.new
166
+ response = client.find_one(model: 'sale.sale', id: 213_112)
167
+
168
+ assert_equal 213_112, response['id']
169
+ end
170
+ ```
171
+
172
+ `stub_fulfil_get` takes two arguments: the URL path (after `/api/v2/model/`)
173
+ and the fixture file name to be returned.
136
174
 
137
175
  ## Contributing
138
176
 
data/lib/fulfil/client.rb CHANGED
@@ -10,6 +10,12 @@ module Fulfil
10
10
  OAUTH_TOKEN = ENV['FULFIL_TOKEN']
11
11
 
12
12
  class Client
13
+ class InvalidClientError < StandardError
14
+ def message
15
+ 'Client is not configured correctly.'
16
+ end
17
+ end
18
+
13
19
  class NotAuthorizedError < StandardError; end
14
20
 
15
21
  class UnknownHTTPError < StandardError; end
@@ -24,6 +30,16 @@ module Fulfil
24
30
  @debug = debug
25
31
  @headers = headers
26
32
  @headers.delete('X-API-KEY') if @token
33
+
34
+ raise InvalidClientError if invalid?
35
+ end
36
+
37
+ def invalid?
38
+ @subdomain.nil? || @subdomain.empty?
39
+ end
40
+
41
+ def valid?
42
+ !invalid?
27
43
  end
28
44
 
29
45
  def find(model:, ids: [], id: nil, fields: %w[id rec_name])
@@ -125,19 +141,12 @@ module Fulfil
125
141
  end
126
142
 
127
143
  def request(endpoint:, verb: :get, **args)
144
+ raise InvalidClientError if invalid?
145
+
128
146
  response = client.request(verb, endpoint, args)
147
+ Fulfil::ResponseHandler.new(response).verify!
129
148
 
130
- if response.status.ok? || response.status.created?
131
- response.parse
132
- elsif response.code == 204
133
- []
134
- elsif response.code == 401
135
- error = response.parse
136
- raise NotAuthorizedError, "Not authorized: #{error['error']}: #{error['error_description']}"
137
- else
138
- puts response.body.to_s
139
- raise Error, 'Error encountered while processing response:'
140
- end
149
+ response.parse
141
150
  rescue HTTP::Error => e
142
151
  puts e
143
152
  raise UnknownHTTPError, 'Unhandled HTTP error encountered'
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fulfil
4
+ class Error < StandardError; end
5
+
6
+ # The `Fulfil::HttpError` is raised whenever an API request returns a 400+ HTTP status code.
7
+ # See `Fulfil::ResponseHandler` for more information.
8
+ class HttpError < Error
9
+ attr_reader :metadata
10
+
11
+ def initialize(message, metadata = {})
12
+ @metadata = metadata
13
+ super(message)
14
+ end
15
+
16
+ class BadRequest < HttpError; end
17
+ class AuthorizationRequired < HttpError; end
18
+ class PaymentRequired < HttpError; end
19
+ class Forbidden < HttpError; end
20
+ class NotFound < HttpError; end
21
+ class MethodNotAllowed < HttpError; end
22
+ class NotAccepted < HttpError; end
23
+ class UnprocessableEntity < HttpError; end
24
+ class TooManyRequests < HttpError; end
25
+ class InternalServerError < HttpError; end
26
+ end
27
+ end
@@ -37,4 +37,4 @@ module Fulfil
37
37
  }
38
38
  end
39
39
  end
40
- end
40
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fulfil
4
+ # The `Fulfil::ResponseHandler` is parses the HTTP response from Fulfil. If it
5
+ # encounters an HTTP status code that indicates an error, it will raise an internal
6
+ # exception that the consumer can catch.
7
+ #
8
+ # @example
9
+ # Fulfil::ResponseHandler.new(@response).verify!
10
+ # => true
11
+ #
12
+ # Fulfil::ResponseHandler.new(@response).verify!
13
+ # => Fulfil::Error::BadRequest
14
+ class ResponseHandler
15
+ HTTP_ERROR_CODES = {
16
+ 400 => Fulfil::HttpError::BadRequest,
17
+ 401 => Fulfil::HttpError::AuthorizationRequired,
18
+ 402 => Fulfil::HttpError::PaymentRequired,
19
+ 403 => Fulfil::HttpError::Forbidden,
20
+ 404 => Fulfil::HttpError::NotFound,
21
+ 405 => Fulfil::HttpError::MethodNotAllowed,
22
+ 406 => Fulfil::HttpError::NotAccepted,
23
+ 422 => Fulfil::HttpError::UnprocessableEntity,
24
+ 429 => Fulfil::HttpError::TooManyRequests,
25
+ 500 => Fulfil::HttpError::InternalServerError
26
+ }.freeze
27
+
28
+ def initialize(response)
29
+ @response = response
30
+ @status_code = response.code
31
+ end
32
+
33
+ def verify!
34
+ return true unless @status_code >= 400
35
+
36
+ raise HTTP_ERROR_CODES.fetch(@status_code, Fulfil::HttpError).new(
37
+ response_body['error_description'],
38
+ {
39
+ body: @response.body,
40
+ headers: @response.headers,
41
+ status: @response.status
42
+ }
43
+ )
44
+ end
45
+
46
+ private
47
+
48
+ def response_body
49
+ @response_body ||= @response.parse
50
+ end
51
+ end
52
+ end
@@ -41,7 +41,7 @@ module Fulfil
41
41
  def self.group(key_value_tuples)
42
42
  key_value_tuples
43
43
  .group_by { |kv_tuple| kv_tuple[0][0] }
44
- .map { |group_key, kv_tuples|
44
+ .map do |group_key, kv_tuples|
45
45
  if kv_tuples.length == 1
46
46
  [group_key, mapped_value_field(value: kv_tuples[0][1])]
47
47
  else
@@ -49,7 +49,7 @@ module Fulfil
49
49
  attrs = kv_tuples[1..-1].map { |tuple| [tuple[0][1..-1], tuple[1]] }
50
50
  [group_key, [['id', id[1]]].concat(group(attrs)).to_h]
51
51
  end
52
- }
52
+ end
53
53
  end
54
54
 
55
55
  def self.parse(item:)
@@ -57,5 +57,4 @@ module Fulfil
57
57
  group(key_value_tuples).to_h
58
58
  end
59
59
  end
60
-
61
60
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fulfil
4
- VERSION = '0.4.8'
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/fulfil.rb CHANGED
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fulfil/version'
4
+ require 'fulfil/error'
2
5
  require 'fulfil/client'
3
6
  require 'fulfil/model'
4
7
  require 'fulfil/interactive_report'
8
+ require 'fulfil/response_handler'
5
9
  require 'fulfil/response_parser'
6
10
 
7
11
  module Fulfil
8
- class Error < StandardError; end
9
12
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fulfil-io
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.8
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Moore
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-11-30 00:00:00.000000000 Z
12
+ date: 2021-12-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: http
@@ -95,6 +95,20 @@ dependencies:
95
95
  - - ">="
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: webmock
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
98
112
  description:
99
113
  email:
100
114
  - chris@knowndecimal.com
@@ -111,9 +125,11 @@ files:
111
125
  - Rakefile
112
126
  - lib/fulfil.rb
113
127
  - lib/fulfil/client.rb
128
+ - lib/fulfil/error.rb
114
129
  - lib/fulfil/interactive_report.rb
115
130
  - lib/fulfil/model.rb
116
131
  - lib/fulfil/query.rb
132
+ - lib/fulfil/response_handler.rb
117
133
  - lib/fulfil/response_parser.rb
118
134
  - lib/fulfil/version.rb
119
135
  homepage: https://github.com/knowndecimal/fulfil