diff --git a/README.markdown b/README.markdown index bc6ae22..8df1f52 100644 --- a/README.markdown +++ b/README.markdown @@ -32,13 +32,14 @@ Using in a simple ruby file: To access the apis you can use: ```ruby - mws_api._api_name_._action_to_calll(params={}) + mws_api._api_name_._action_to_call!(params={}) ``` +The method above will return an error if any `ErrorResponse` is returned from MWS Let's say we want to retrieve a list of orders using MWS orders api: ```ruby - mws_api.orders.list_orders( + mws_api.orders.list_orders!( "MarketplaceId.Id.1" => "marketplace id", created_after: Time.new(2013, 1, 1) ) diff --git a/lib/mws.rb b/lib/mws.rb index 135b2ce..42613f1 100644 --- a/lib/mws.rb +++ b/lib/mws.rb @@ -9,6 +9,7 @@ require_relative 'mws/query' require_relative 'mws/connection' +require_relative 'mws/api' require_relative 'mws/api/base' require_relative 'mws/api/orders' require_relative 'mws/api/reports' diff --git a/lib/mws/api.rb b/lib/mws/api.rb new file mode 100644 index 0000000..7a06855 --- /dev/null +++ b/lib/mws/api.rb @@ -0,0 +1,8 @@ +module MWS + # API module + module API + ResponseError = Class.new(StandardError) + + RESPONSE_ERROR_KEY = 'ErrorResponse'.freeze + end +end diff --git a/lib/mws/api/base.rb b/lib/mws/api/base.rb index a5dccf2..9a896f4 100644 --- a/lib/mws/api/base.rb +++ b/lib/mws/api/base.rb @@ -7,6 +7,7 @@ class Base # TODO: Temporary solution, move to configuration DEFAULT_TIMEOUT = 2000 USER_AGENT = 'User-Agent'.freeze + STRICT_MEHTHOD_ENDING = '!'.freeze def initialize(connection) @verb ||= :get @@ -43,12 +44,27 @@ def build_query_from_params(action, params) def method_missing(name, *args) if self.class::ACTIONS.include?(name) + warn "[DEPRECATION] `#{name}` will be removed in next major version. " \ + "Please use `#{name}!` instead." + call(name, *args) + elsif self.class::ACTIONS.include?(method_without_bang(name)) + response = call(method_without_bang(name), *args) + + return response unless response.key?(MWS::API::RESPONSE_ERROR_KEY) + + raise MWS::API::ResponseError, response.to_json else super end end + def respond_to_missing?(name, include_private = false) + self.class::ACTIONS.include?(name) || + self.class::ACTIONS.include?(method_without_bang(name)) || + super + end + def http_request_options @http_request_options ||= begin options = { timeout: DEFAULT_TIMEOUT } @@ -56,6 +72,12 @@ def http_request_options options end end + + private + + def method_without_bang(name) + name.to_s.chomp(STRICT_MEHTHOD_ENDING).to_sym + end end end end diff --git a/spec/mws-rb/api/base_spec.rb b/spec/mws-rb/api/base_spec.rb index f1846ca..15d361e 100644 --- a/spec/mws-rb/api/base_spec.rb +++ b/spec/mws-rb/api/base_spec.rb @@ -40,14 +40,89 @@ def initialize(connection) end describe 'method_missing to call actions' do - before(:each) { allow(HTTParty).to receive(:get).and_return({}) } + before(:each) { allow(HTTParty).to receive(:get).and_return(result) } - it 'should raise exception if Actions do not contain the action name' do - expect { test_api.action_not_found }.to raise_error(NoMethodError) + context 'regular method call' do + let(:result) { {} } + let(:expected_deprication_warning) do + '[DEPRECATION] `test_action` will be removed in next major version. ' \ + "Please use `test_action!` instead.\n" + end + + it 'should raise exception if Actions do not contain the action name', :stub_stdout do + expect { test_api.action_not_found }.to raise_error(NoMethodError) + end + + it 'makes api call and return result if Actions contain the action name', :stub_stdout do + expect(test_api.test_action).to eq result + end + + it 'prints a deprication warning' do + expect { test_api.test_action } + .to output(expected_deprication_warning) + .to_stderr + end + end + + context 'bang method' do + context 'API response does not contain errors' do + let(:result) { {} } + + it 'raises exception if Actions do not contain the action name' do + expect { test_api.action_not_found! }.to raise_error(NoMethodError) + end + + it 'makes api call and return result if Actions contain the action name' do + expect(test_api.test_action!).to eq result + end + end + + context 'API response contains errors' do + let(:result) { { 'ErrorResponse' => {} } } + + it 'makes api call and returns error' do + expect { test_api.test_action! } + .to raise_error MWS::API::ResponseError, '{"ErrorResponse":{}}' + end + end + end + end + + describe '#respond_to_missing?' do + subject { test_api.respond_to?(method_name) } + + context 'Actions contain method' do + let(:method_name) { 'test_action' } + + it { is_expected.to be true } + end + + context 'Actions do not contain method' do + let(:method_name) { 'missed_test_action' } + + it { is_expected.to be false } + end + + context 'Actions contain bang method' do + let(:method_name) { 'test_action!' } + + it { is_expected.to be true } + end + + context 'Actions do not contain bang method' do + let(:method_name) { 'missed_test_action!' } + + it { is_expected.to be false } + end + + context 'regular Ruby method' do + let(:method_name) { 'nil?' } + + it { is_expected.to be true } end end - context 'user agent' do + context 'user agent', :stub_stdout do subject { test_api.test_action(params) } before do |example| diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d676e2a..4391c65 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -14,4 +14,10 @@ config.filter_sensitive_data('DUMMY_AWS_SELLER_ID') { ENV['AWS_SELLER_ID'] } end +RSpec.configure do |config| + config.before(:each, :stub_stdout) do + allow_any_instance_of(Kernel).to receive(:warn) + end +end + RSpec.configure(&:raise_errors_for_deprecations!)