~tim/mailchimp3

421e9f6f05a2037353c4ae72894d6c0e4f7274fd — Tim Morgan 5 years ago d96c10e
Raise ServerError if parsing response JSON fails
M lib/mailchimp3/endpoint.rb => lib/mailchimp3/endpoint.rb +20 -15
@@ 1,5 1,5 @@
require 'faraday'
require 'faraday_middleware'
require 'json'

module MailChimp3
  class Endpoint


@@ 65,33 65,39 @@ module MailChimp3
    private

    def _build_response(result)
      case result.status
      body = _parse_body(result)
      case (status = result.status)
      when 200..299
        result.body
        body
      when 400
        fail Errors::BadRequest, result
        fail Errors::BadRequest, status: status, body: body
      when 401
        fail Errors::Unauthorized, result
        fail Errors::Unauthorized, status: status, body: body
      when 403
        fail Errors::Forbidden, result
        fail Errors::Forbidden, status: status, body: body
      when 404
        fail Errors::NotFound, result
        fail Errors::NotFound, status: status, body: body
      when 405
        fail Errors::MethodNotAllowed, result
        fail Errors::MethodNotAllowed, status: status, body: body
      when 422
        fail Errors::UnprocessableEntity, result
        fail Errors::UnprocessableEntity, status: status, body: body
      when 400..499
        fail Errors::ClientError, result
        fail Errors::ClientError, status: status, body: body
      when 500
        fail Errors::InternalServerError, result
        fail Errors::InternalServerError, status: status, body: body
      when 500..599
        fail Errors::ServerError, result
        fail Errors::ServerError, status: status, body: body
      else
        binding.pry
        fail "unknown status #{result.status}"
        fail "unknown status #{status}"
      end
    end

    def _parse_body(result)
      JSON.parse(result.body)
    rescue JSON::ParserError
      raise Errors::ServerError, status: result.status, body: result.body
    end

    def _build_endpoint(path)
      @cache[path] ||= begin
        self.class.new(


@@ 114,7 120,6 @@ module MailChimp3
    def _connection
      @connection ||= Faraday.new(url: url) do |faraday|
        faraday.adapter :excon
        faraday.response :json, content_type: /\bjson$/
        if @basic_auth_key
          faraday.basic_auth '', @basic_auth_key
        elsif @oauth_access_token

M lib/mailchimp3/errors.rb => lib/mailchimp3/errors.rb +8 -8
@@ 6,16 6,16 @@ module MailChimp3
    class BaseError < StandardError
      attr_reader :status, :details

      def initialize(response)
        @status = response.status
        @message = if response.body.is_a?(Hash) && response.body['error']
                     "#{response.body['name']}: #{response.body['error']}"
                   elsif response.body.is_a?(Hash)
                     "#{response.body['title']}: #{response.body['detail']}"
      def initialize(body:, status:)
        @status = status
        @message = if body.is_a?(Hash) && body['error']
                     "#{body['name']}: #{body['error']}"
                   elsif body.is_a?(Hash)
                     "#{body['title']}: #{body['detail']}"
                   else
                     response.body.to_s
                     body.to_s
                   end
        @details = response.body if response.body.is_a?(Hash)
        @details = body if body.is_a?(Hash)
      end

      def to_s

M mailchimp3.gemspec => mailchimp3.gemspec +0 -1
@@ 18,7 18,6 @@ Gem::Specification.new do |s|
  s.test_files = Dir["spec/**/*"]

  s.add_dependency "faraday", "~> 0.9.1"
  s.add_dependency "faraday_middleware", "~> 0.9.1"
  s.add_dependency "excon", "~> 0.45.3"
  s.add_dependency "oauth2", "~> 1.0.0"
  s.add_development_dependency "rspec", "~> 3.2"

M spec/mailchimp3/endpoint_spec.rb => spec/mailchimp3/endpoint_spec.rb +44 -25
@@ 68,13 68,16 @@ describe MailChimp3::Endpoint do
      end

      it 'raises a NotFound error' do
        error = begin
                  subject.get
                rescue MailChimp3::Errors::NotFound => e
                  e
                end
        expect(error.status).to eq(404)
        expect(error.message).to eq('Resource Not Found: The requested resource could not be found.')
        expect { subject.get }.to raise_error do |error|
          expect(error).to be_a(MailChimp3::Errors::NotFound)
          expect(error.status).to eq(404)
          expect(error.message).to eq('Resource Not Found: The requested resource could not be found.')
          expect(error.details).to eq(
            'status' => 404,
            'title' => 'Resource Not Found',
            'detail' => 'The requested resource could not be found.'
          )
        end
      end
    end



@@ 94,9 97,7 @@ describe MailChimp3::Endpoint do
      end

      it 'raises a ClientError error' do
        expect {
          subject.get
        }.to raise_error(MailChimp3::Errors::ClientError)
        expect { subject.get }.to raise_error(MailChimp3::Errors::ClientError)
      end
    end



@@ 116,9 117,7 @@ describe MailChimp3::Endpoint do
      end

      it 'raises a ServerError error' do
        expect {
          subject.get
        }.to raise_error(MailChimp3::Errors::ServerError)
        expect { subject.get }.to raise_error(MailChimp3::Errors::ServerError)
      end
    end
  end


@@ 132,21 131,41 @@ describe MailChimp3::Endpoint do
      }
    end

    let(:result) do
      {
        'id'   => 'd3ed40bd7c',
        'name' => 'Foo'
      }
    end
    context do
      let(:result) do
        {
          'id'   => 'd3ed40bd7c',
          'name' => 'Foo'
        }
      end

    before do
      stub_request(:post, 'https://us2.api.mailchimp.com/3.0/lists')
        .to_return(status: 201, body: result.to_json, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
      @result = subject.post(resource)
      before do
        stub_request(:post, 'https://us2.api.mailchimp.com/3.0/lists')
          .to_return(status: 201, body: result.to_json, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
        @result = subject.post(resource)
      end

      it 'returns the result of making a POST request to the endpoint' do
        expect(@result).to eq(result)
      end
    end

    it 'returns the result of making a POST request to the endpoint' do
      expect(@result).to eq(result)
    context 'when the response is not valid JSON' do
      let(:result) { 'bad' }

      before do
        stub_request(:post, 'https://us2.api.mailchimp.com/3.0/lists')
          .to_return(status: 200, body: result, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
      end

      it 'raises an error' do
        expect { subject.post(resource) }.to raise_error do |error|
          expect(error).to be_a(MailChimp3::Errors::ServerError)
          expect(error.status).to eq(200)
          expect(error.message).to eq('bad')
          expect(error.details).to be_nil
        end
      end
    end
  end