Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Surface original Vertex errors via new bang methods #75

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

This file tracks all the changes (https://keepachangelog.com/en/1.0.0/) made to the client. This allows parsers such as Dependabot to provide a clean overview in pull requests.

## [v0.12.0] - 2024-08-07

#### Added

- Added `quotation!`, `invoice!`, `distribute_tax!`, `tax_area!` class methods to `VertexClient` that raise `Savon::SOAPFault` errors when errors are returned from the Vertex SOAP API
- Existing non-bang methods receive `nil` internally and return `fallback_response` defined in each resource

## [v0.11.0] - 2024-04-03

#### Changed
Expand Down
16 changes: 16 additions & 0 deletions lib/vertex_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,34 @@ def quotation(payload)
Resource::Quotation.new(payload).result
end

def quotation!(payload)
Resource::Quotation.new(payload).result!
end

def invoice(payload)
Resource::Invoice.new(payload).result
end

def invoice!(payload)
Resource::Invoice.new(payload).result!
end

def distribute_tax(payload)
Resource::DistributeTax.new(payload).result
end

def distribute_tax!(payload)
Resource::DistributeTax.new(payload).result!
end

def tax_area(payload)
Resource::TaxArea.new(payload).result
end

def tax_area!(payload)
Resource::TaxArea.new(payload).result!
end

def circuit
return unless circuit_configured?

Expand Down
30 changes: 23 additions & 7 deletions lib/vertex_client/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ def initialize(endpoint, resource_key=nil)

def request(payload)
call_with_circuit_if_available do
client.call(
:vertex_envelope,
message: shell_with_auth.merge(payload)
)
raw_request(payload)
end
end

def request!(payload)
call_with_circuit_if_available(raise_exceptions: true) do
raw_request(payload)
end
end

Expand All @@ -32,6 +35,13 @@ def client

private

def raw_request(payload)
client.call(
:vertex_envelope,
message: shell_with_auth.merge(payload)
)
end

def config
@config ||= VertexClient.configuration
end
Expand All @@ -40,14 +50,20 @@ def resource_config
config.resource_config[@resource_key] || {}
end

def call_with_circuit_if_available
def call_with_circuit_if_available(raise_exceptions: false)
if VertexClient.circuit
VertexClient.circuit.run(exception: false) { yield }
begin
VertexClient.circuit.run(exception: raise_exceptions) { yield }
rescue Circuitbox::ServiceFailureError => e
nil
raise e.original if raise_exceptions
end
else
begin
yield
rescue => _e
rescue => e
nil
raise e if raise_exceptions
end
end
end
Expand Down
21 changes: 17 additions & 4 deletions lib/vertex_client/resources/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,44 @@
module VertexClient
module Resource
class Base
class NotImplementedError < StandardError; end

def initialize(params)
@payload = payload_type.new(params)
end

def result
@result ||= (response ? formatted_response : fallback_response)
@result ||= (formatted_response(response) || fallback_response)
end

def result!
formatted_response(response!)
end

def config_key
demodulized_class_name.underscore.to_sym
end

def fallback_response
raise NotImplementedError
end

private

def response
@response ||= connection.request(@payload.transform)
connection.request(@payload.transform)
end

def response!
connection.request!(@payload.transform)
end

def connection
@connection ||= Connection.new(self.class::ENDPOINT, config_key)
end

def formatted_response
response_type.new(response)
def formatted_response(raw_response)
response_type.new(raw_response) if raw_response
end

def payload_type
Expand Down
2 changes: 1 addition & 1 deletion lib/vertex_client/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module VertexClient
VERSION = '0.11.0'
VERSION = '0.12.0'
end
30 changes: 28 additions & 2 deletions test/resources/base_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
describe VertexClient::Resource::Base do
class VertexClient::Resource::MyTest < VertexClient::Resource::Base
ENDPOINT = 'MyEndPoint'.freeze

def fallback_response
{ fall: :back }
end
end
class VertexClient::Payload::MyTest < VertexClient::Payload::Base
def validate!
Expand Down Expand Up @@ -51,11 +55,33 @@ class VertexClient::Response::MyTest < VertexClient::Response::Base; end;
end
end

describe 'result!' do
describe 'without exceptions' do
before do
resource.stubs(:response!).returns({ test: :ok })
end

it 'returns a formatted response' do
resource.expects(:formatted_response)
resource.result!
end
end

describe 'with exceptions' do
before do
resource.stubs(:response!).raises(StandardError)
end

it 'raises the exception' do
assert_raises(StandardError) { resource.result! }
end
end
end

describe 'formatted_response' do
it 'returns a new response of the proper type' do
resource.expects(:response).returns({test: :ok})
VertexClient::Response::MyTest.expects(:new).with({test: :ok})
resource.send(:formatted_response)
resource.send(:formatted_response, {test: :ok})
end
end
end
28 changes: 28 additions & 0 deletions test/vertex_client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,55 @@
assert VertexClient.quotation(working_quote_params)
end

it 'does a quotation!' do
VertexClient::Resource::Quotation.expects(:new)
.with(working_quote_params)
.returns(stub(result!: true))
assert VertexClient.quotation!(working_quote_params)
end

it 'does invoice' do
VertexClient::Resource::Invoice.expects(:new)
.with(working_quote_params)
.returns(stub(result: true))
assert VertexClient.invoice(working_quote_params)
end

it 'does invoice!' do
VertexClient::Resource::Invoice.expects(:new)
.with(working_quote_params)
.returns(stub(result!: true))
assert VertexClient.invoice!(working_quote_params)
end

it 'does distribute_tax' do
VertexClient::Resource::DistributeTax.expects(:new)
.with(working_quote_params)
.returns(stub(result: true))
assert VertexClient.distribute_tax(working_quote_params)
end

it 'does distribute_tax!' do
VertexClient::Resource::DistributeTax.expects(:new)
.with(working_quote_params)
.returns(stub(result!: true))
assert VertexClient.distribute_tax!(working_quote_params)
end

it 'does tax_area' do
VertexClient::Resource::TaxArea.expects(:new)
.with(working_quote_params)
.returns(stub(result: true))
assert VertexClient.tax_area(working_quote_params)
end

it 'does tax_area!' do
VertexClient::Resource::TaxArea.expects(:new)
.with(working_quote_params)
.returns(stub(result!: true))
assert VertexClient.tax_area!(working_quote_params)
end

describe 'circuit' do
it 'only exists if circuit_config is provided to configuration' do
VertexClient.configuration.circuit_config = nil
Expand Down
Loading