postcodeinfo-client-ruby 0.1.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 +7 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/.ruby-gemset +2 -0
- data/.ruby-version +1 -0
- data/.simplecov +6 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +97 -0
- data/LICENSE.MD +19 -0
- data/README.md +150 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/lib/postcodeinfo-client-ruby.rb +3 -0
- data/lib/postcodeinfo/client.rb +129 -0
- data/lib/postcodeinfo/exceptions.rb +16 -0
- data/lib/postcodeinfo/postcode.rb +65 -0
- data/postcodeinfo-client-ruby.gemspec +80 -0
- data/spec/client_spec.rb +289 -0
- data/spec/postcode_spec.rb +225 -0
- data/spec/spec_helper.rb +22 -0
- metadata +181 -0
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            module PostcodeInfo
         | 
| 2 | 
            +
              class APIExceptionWrapper < Exception
         | 
| 3 | 
            +
                attr_accessor :original_exception, :response
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(original_exception, response)
         | 
| 6 | 
            +
                  self.original_exception = original_exception
         | 
| 7 | 
            +
                  self.response = response
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              class ServiceUnavailable < APIExceptionWrapper; end
         | 
| 12 | 
            +
              class ServerError < APIExceptionWrapper; end
         | 
| 13 | 
            +
              class UnparseableResponse < APIExceptionWrapper; end
         | 
| 14 | 
            +
              class InvalidAuthToken < APIExceptionWrapper; end
         | 
| 15 | 
            +
              class UnrecognisedPostcode < APIExceptionWrapper; end
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,65 @@ | |
| 1 | 
            +
            module PostcodeInfo
         | 
| 2 | 
            +
              class Postcode
         | 
| 3 | 
            +
                # these attributes are set on construction
         | 
| 4 | 
            +
                attr_reader :as_given, :normalised
         | 
| 5 | 
            +
                attr_accessor :client
         | 
| 6 | 
            +
                # these attributes require lookups
         | 
| 7 | 
            +
                # attr_reader :latitude, :longitude, :addresses, :local_authority
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def initialize(given_postcode, client)
         | 
| 10 | 
            +
                  @as_given = given_postcode
         | 
| 11 | 
            +
                  @normalised = self.class.normalise(@as_given)
         | 
| 12 | 
            +
                  @client = client
         | 
| 13 | 
            +
                  @info = nil
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def self.normalise(postcode)
         | 
| 17 | 
            +
                  postcode.downcase.gsub(/[^a-z0-9]/, '')
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def latitude
         | 
| 21 | 
            +
                  lookup_info! if @info.nil?
         | 
| 22 | 
            +
                  @latitude
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def longitude
         | 
| 26 | 
            +
                  lookup_info! if @info.nil?
         | 
| 27 | 
            +
                  @longitude
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def local_authority
         | 
| 31 | 
            +
                  lookup_info! if @info.nil?
         | 
| 32 | 
            +
                  @local_authority
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
                def addresses
         | 
| 36 | 
            +
                  @addresses ||= @client.addresses(@normalised)
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
                alias_method :lookup_addresses!, :addresses
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def valid?
         | 
| 41 | 
            +
                  @valid ||= @client.valid?(@normalised)
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
                
         | 
| 44 | 
            +
                def lookup_info!
         | 
| 45 | 
            +
                  @info = @client.info(@normalised)
         | 
| 46 | 
            +
                  parse_info!
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
             | 
| 50 | 
            +
                protected
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def set_coordinates!(info)
         | 
| 53 | 
            +
                    if info[:centre]
         | 
| 54 | 
            +
                      @latitude = info[:centre][:latitude]
         | 
| 55 | 
            +
                      @longitude = info[:centre][:longitude]
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  def parse_info!
         | 
| 60 | 
            +
                    set_coordinates!(@info)
         | 
| 61 | 
            +
                    @local_authority = @info[:local_authority]
         | 
| 62 | 
            +
                    @valid = true
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
            end
         | 
| @@ -0,0 +1,80 @@ | |
| 1 | 
            +
            # Generated by jeweler
         | 
| 2 | 
            +
            # DO NOT EDIT THIS FILE DIRECTLY
         | 
| 3 | 
            +
            # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
         | 
| 4 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 5 | 
            +
            # stub: postcodeinfo-client-ruby 0.1.0 ruby lib
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Gem::Specification.new do |s|
         | 
| 8 | 
            +
              s.name = "postcodeinfo-client-ruby"
         | 
| 9 | 
            +
              s.version = "0.1.0"
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 12 | 
            +
              s.require_paths = ["lib"]
         | 
| 13 | 
            +
              s.authors = ["Al Davidson"]
         | 
| 14 | 
            +
              s.date = "2015-05-29"
         | 
| 15 | 
            +
              s.description = "Provides a convenient interface for looking up postcodes in an instance of the MoJ postcodeinfo API (https://://github.com/ministryofjustice/postcodeinfo).\n    Lets you check if a postcode is valid, and ookup:\n    * all addresses with that postcode\n    * the latitude/longitude of its centre point\n    * the name & GSS code of the local authority under which it resides."
         | 
| 16 | 
            +
              s.email = "alistair.davidson@digital.justice.gov.uk"
         | 
| 17 | 
            +
              s.extra_rdoc_files = [
         | 
| 18 | 
            +
                "LICENSE.MD",
         | 
| 19 | 
            +
                "README.md"
         | 
| 20 | 
            +
              ]
         | 
| 21 | 
            +
              s.files = [
         | 
| 22 | 
            +
                ".document",
         | 
| 23 | 
            +
                ".rspec",
         | 
| 24 | 
            +
                ".ruby-gemset",
         | 
| 25 | 
            +
                ".ruby-version",
         | 
| 26 | 
            +
                ".simplecov",
         | 
| 27 | 
            +
                "Gemfile",
         | 
| 28 | 
            +
                "Gemfile.lock",
         | 
| 29 | 
            +
                "LICENSE.MD",
         | 
| 30 | 
            +
                "README.md",
         | 
| 31 | 
            +
                "Rakefile",
         | 
| 32 | 
            +
                "VERSION",
         | 
| 33 | 
            +
                "lib/postcodeinfo-client-ruby.rb",
         | 
| 34 | 
            +
                "lib/postcodeinfo/client.rb",
         | 
| 35 | 
            +
                "lib/postcodeinfo/exceptions.rb",
         | 
| 36 | 
            +
                "lib/postcodeinfo/postcode.rb",
         | 
| 37 | 
            +
                "postcodeinfo-client-ruby.gemspec",
         | 
| 38 | 
            +
                "spec/client_spec.rb",
         | 
| 39 | 
            +
                "spec/postcode_spec.rb",
         | 
| 40 | 
            +
                "spec/spec_helper.rb"
         | 
| 41 | 
            +
              ]
         | 
| 42 | 
            +
              s.homepage = "https://github.com/ministryofjustice/postcodeinfo-client-ruby"
         | 
| 43 | 
            +
              s.licenses = ["Open Government License"]
         | 
| 44 | 
            +
              s.rubygems_version = "2.4.3"
         | 
| 45 | 
            +
              s.summary = "Client for postcodeinfo API (https://://github.com/ministryofjustice/postcodeinfo)"
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              if s.respond_to? :specification_version then
         | 
| 48 | 
            +
                s.specification_version = 4
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
         | 
| 51 | 
            +
                  s.add_runtime_dependency(%q<json>, [">= 0"])
         | 
| 52 | 
            +
                  s.add_runtime_dependency(%q<rest-client>, [">= 0"])
         | 
| 53 | 
            +
                  s.add_development_dependency(%q<byebug>, [">= 0"])
         | 
| 54 | 
            +
                  s.add_development_dependency(%q<rspec>, [">= 3.2.0"])
         | 
| 55 | 
            +
                  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
         | 
| 56 | 
            +
                  s.add_development_dependency(%q<bundler>, ["~> 1.0"])
         | 
| 57 | 
            +
                  s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
         | 
| 58 | 
            +
                  s.add_development_dependency(%q<simplecov>, [">= 0"])
         | 
| 59 | 
            +
                else
         | 
| 60 | 
            +
                  s.add_dependency(%q<json>, [">= 0"])
         | 
| 61 | 
            +
                  s.add_dependency(%q<rest-client>, [">= 0"])
         | 
| 62 | 
            +
                  s.add_dependency(%q<byebug>, [">= 0"])
         | 
| 63 | 
            +
                  s.add_dependency(%q<rspec>, [">= 3.2.0"])
         | 
| 64 | 
            +
                  s.add_dependency(%q<rdoc>, ["~> 3.12"])
         | 
| 65 | 
            +
                  s.add_dependency(%q<bundler>, ["~> 1.0"])
         | 
| 66 | 
            +
                  s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
         | 
| 67 | 
            +
                  s.add_dependency(%q<simplecov>, [">= 0"])
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              else
         | 
| 70 | 
            +
                s.add_dependency(%q<json>, [">= 0"])
         | 
| 71 | 
            +
                s.add_dependency(%q<rest-client>, [">= 0"])
         | 
| 72 | 
            +
                s.add_dependency(%q<byebug>, [">= 0"])
         | 
| 73 | 
            +
                s.add_dependency(%q<rspec>, [">= 3.2.0"])
         | 
| 74 | 
            +
                s.add_dependency(%q<rdoc>, ["~> 3.12"])
         | 
| 75 | 
            +
                s.add_dependency(%q<bundler>, ["~> 1.0"])
         | 
| 76 | 
            +
                s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
         | 
| 77 | 
            +
                s.add_dependency(%q<simplecov>, [">= 0"])
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
            end
         | 
| 80 | 
            +
             | 
    
        data/spec/client_spec.rb
    ADDED
    
    | @@ -0,0 +1,289 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe PostcodeInfo::Client do
         | 
| 4 | 
            +
              let(:args){ {auth_token: '12345'} }
         | 
| 5 | 
            +
              let(:client){ PostcodeInfo::Client.new(args) }
         | 
| 6 | 
            +
              let(:postcode){ 'SN15NB' }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
             | 
| 9 | 
            +
              describe 'constructing a new client' do
         | 
| 10 | 
            +
                context 'with no :auth_token' do
         | 
| 11 | 
            +
                  let(:args){ {} }
         | 
| 12 | 
            +
                  it 'does not raise an ArgumentError' do
         | 
| 13 | 
            +
                    expect{ described_class.new }.to_not raise_error
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
                context 'with an :auth_token' do
         | 
| 17 | 
            +
                  let(:args){ {auth_token: '12345'} }
         | 
| 18 | 
            +
                  let(:client){ PostcodeInfo::Client.new(args) }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  it 'stores the auth_token in an instance variable' do
         | 
| 21 | 
            +
                    expect( client.auth_token ).to eq('12345')
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  context 'and an :api_url' do
         | 
| 25 | 
            +
                    before{ args[:api_url] = 'http://my/ur.l' }
         | 
| 26 | 
            +
                    
         | 
| 27 | 
            +
                    it 'parses the :api_url' do
         | 
| 28 | 
            +
                      expect( URI ).to receive(:parse).with('http://my/ur.l')
         | 
| 29 | 
            +
                      client
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  context 'and no :api_url' do
         | 
| 34 | 
            +
                    let(:mock_urls){
         | 
| 35 | 
            +
                      {
         | 
| 36 | 
            +
                        my_env: 'http://my/env/url',
         | 
| 37 | 
            +
                        foo: 'https://foo/'
         | 
| 38 | 
            +
                      }
         | 
| 39 | 
            +
                    }
         | 
| 40 | 
            +
                    before do
         | 
| 41 | 
            +
                      allow(described_class).to receive(:api_urls).and_return( mock_urls )
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    context 'but an :env' do
         | 
| 45 | 
            +
                      before{ args[:env] = 'my_env' }
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                      it 'parses the looked-up :api_url' do
         | 
| 48 | 
            +
                        expect( URI ).to receive(:parse).with('http://my/env/url')
         | 
| 49 | 
            +
                        client
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    context 'and no :env' do
         | 
| 54 | 
            +
                      context 'when ENV["RAILS_ENV"] is present' do
         | 
| 55 | 
            +
                        before do
         | 
| 56 | 
            +
                          allow(ENV).to receive(:[]).with('RAILS_ENV').and_return( 'foo' )
         | 
| 57 | 
            +
                        end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                        it 'parses the looked-up :api_url' do
         | 
| 60 | 
            +
                          expect( URI ).to receive(:parse).with('https://foo/')
         | 
| 61 | 
            +
                          client
         | 
| 62 | 
            +
                        end
         | 
| 63 | 
            +
                      end
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              describe 'setting the api_url' do
         | 
| 70 | 
            +
                let(:new_url){ 'https://my.dom.ain/' }
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                it 'stores the parsed URI as @api_uri' do
         | 
| 73 | 
            +
                  expect{ client.api_url=new_url }.to change(client, :api_uri).to( URI.parse(new_url) )
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              describe 'getting the api_url' do
         | 
| 78 | 
            +
                it 'returns a string' do
         | 
| 79 | 
            +
                  expect(client.api_url).to be_a(String)
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              describe 'lookup_postcode' do
         | 
| 84 | 
            +
                let(:mock_constructed_postcode){ double(PostcodeInfo::Postcode).as_null_object }
         | 
| 85 | 
            +
                before do
         | 
| 86 | 
            +
                  allow(PostcodeInfo::Postcode).to receive(:new).and_return(mock_constructed_postcode)
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                context 'given a valid postcode' do
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  it 'returns a PostcodeInfo::Postcode' do
         | 
| 92 | 
            +
                    expect(client.lookup_postcode(postcode)).to eq(mock_constructed_postcode)
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  it 'looks-up the addresses' do
         | 
| 96 | 
            +
                    expect(mock_constructed_postcode).to receive(:lookup_addresses!)
         | 
| 97 | 
            +
                    allow(mock_constructed_postcode).to receive(:lookup_info!)
         | 
| 98 | 
            +
                    client.lookup_postcode(postcode)
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  it 'looks-up the info' do
         | 
| 102 | 
            +
                    allow(mock_constructed_postcode).to receive(:lookup_addresses!)
         | 
| 103 | 
            +
                    expect(mock_constructed_postcode).to receive(:lookup_info!)
         | 
| 104 | 
            +
                    client.lookup_postcode(postcode)
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                context 'when the response raises a RestClient::ResourceNotFound exception' do
         | 
| 109 | 
            +
                  before do
         | 
| 110 | 
            +
                    allow(mock_constructed_postcode).to receive(:lookup_info!).and_raise(RestClient::ResourceNotFound)
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  it 'raises PostcodeInfo::UnrecognizedPostcode' do
         | 
| 114 | 
            +
                    expect{client.lookup_postcode(postcode)}.to raise_error( PostcodeInfo::UnrecognisedPostcode )
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
              end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
              describe 'valid?' do
         | 
| 120 | 
            +
                let(:mock_response){ double('response').as_null_object }
         | 
| 121 | 
            +
                before do
         | 
| 122 | 
            +
                  allow(client).to receive(:make_request).with('/postcodes/SN15NB').and_return(mock_response)
         | 
| 123 | 
            +
                end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                it 'makes a request to /postcodes/(given_postcode)' do
         | 
| 126 | 
            +
                  expect(client).to receive(:make_request).with('/postcodes/SN15NB').and_return(mock_response)
         | 
| 127 | 
            +
                  client.valid?(postcode)
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                context 'when the response has code 200' do
         | 
| 131 | 
            +
                  let(:mock_response){ double('response', code: 200) }
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                  it 'returns true' do
         | 
| 134 | 
            +
                    expect(client.valid?(postcode)).to eq(true)
         | 
| 135 | 
            +
                  end
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
                
         | 
| 138 | 
            +
                context 'when the response has code 404' do
         | 
| 139 | 
            +
                  let(:mock_response){ double('response', code: 404) }
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                  it 'returns false' do
         | 
| 142 | 
            +
                    expect(client.valid?(postcode)).to eq(false)
         | 
| 143 | 
            +
                  end
         | 
| 144 | 
            +
                end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
             | 
| 147 | 
            +
                context 'when the response raises a RestClient::ResourceNotFound exception' do
         | 
| 148 | 
            +
                  before do
         | 
| 149 | 
            +
                    allow(client).to receive(:make_request).and_raise(RestClient::ResourceNotFound)
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                  it 'returns false' do
         | 
| 153 | 
            +
                    expect(client.valid?(postcode)).to eq(false)
         | 
| 154 | 
            +
                  end
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                context 'when the response has code 4XX' do
         | 
| 158 | 
            +
                  let(:mock_response){ double('response', code: 418) }
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                  it 'returns nil' do
         | 
| 161 | 
            +
                    expect(client.valid?(postcode)).to be_nil
         | 
| 162 | 
            +
                  end
         | 
| 163 | 
            +
                end
         | 
| 164 | 
            +
                
         | 
| 165 | 
            +
                context 'when the response has code 5XX' do
         | 
| 166 | 
            +
                  let(:mock_response){ double('response', code: 500) }
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                  it 'returns nil' do
         | 
| 169 | 
            +
                    expect(client.valid?(postcode)).to be_nil
         | 
| 170 | 
            +
                  end
         | 
| 171 | 
            +
                end
         | 
| 172 | 
            +
              end
         | 
| 173 | 
            +
             | 
| 174 | 
            +
              describe 'addresses' do
         | 
| 175 | 
            +
                let(:mock_response){ double('response').as_null_object }
         | 
| 176 | 
            +
                
         | 
| 177 | 
            +
                before do
         | 
| 178 | 
            +
                  allow(client).to receive(:handle_response).and_return('handled response')
         | 
| 179 | 
            +
                  allow(client).to receive(:make_request).with('/addresses/?postcode=SN15NB').and_return(mock_response)
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                it 'makes a request to /addresses/?postcode=(given_postcode)' do
         | 
| 183 | 
            +
                  expect(client).to receive(:make_request).with('/addresses/?postcode=SN15NB').and_return(mock_response)
         | 
| 184 | 
            +
                  client.addresses(postcode)
         | 
| 185 | 
            +
                end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                it 'handles the response' do
         | 
| 188 | 
            +
                  expect(client).to receive(:handle_response).with(mock_response)
         | 
| 189 | 
            +
                  client.addresses(postcode)
         | 
| 190 | 
            +
                end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                it 'returns the handled response' do
         | 
| 193 | 
            +
                  expect(client.addresses(postcode)).to eq('handled response')
         | 
| 194 | 
            +
                end
         | 
| 195 | 
            +
              end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
              describe 'info' do
         | 
| 198 | 
            +
                let(:mock_response){ double('response').as_null_object }
         | 
| 199 | 
            +
                
         | 
| 200 | 
            +
                before do
         | 
| 201 | 
            +
                  allow(client).to receive(:handle_response).and_return('handled response')
         | 
| 202 | 
            +
                  allow(client).to receive(:make_request).with('/postcodes/SN15NB').and_return(mock_response)
         | 
| 203 | 
            +
                end
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                it 'makes a request to /postcodes/(given_postcode)' do
         | 
| 206 | 
            +
                  expect(client).to receive(:make_request).with('/postcodes/SN15NB').and_return(mock_response)
         | 
| 207 | 
            +
                  client.info(postcode)
         | 
| 208 | 
            +
                end
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                it 'handles the response' do
         | 
| 211 | 
            +
                  expect(client).to receive(:handle_response).with(mock_response)
         | 
| 212 | 
            +
                  client.info(postcode)
         | 
| 213 | 
            +
                end
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                it 'returns the handled response' do
         | 
| 216 | 
            +
                  expect(client.info(postcode)).to eq('handled response')
         | 
| 217 | 
            +
                end
         | 
| 218 | 
            +
              end
         | 
| 219 | 
            +
             | 
| 220 | 
            +
              describe 'make_request' do
         | 
| 221 | 
            +
                before do
         | 
| 222 | 
            +
                  client.api_uri = URI.parse("http://my.api/")
         | 
| 223 | 
            +
                  allow(RestClient::Request).to receive(:execute).and_return( 'response' )
         | 
| 224 | 
            +
                end
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                it 'makes a get request to the given endpoint' do
         | 
| 227 | 
            +
                  expect(RestClient::Request).to receive(:execute).with(hash_including(method: :get, url: 'http://my.api/my/endpoint')).and_return('response')
         | 
| 228 | 
            +
                  client.make_request('/my/endpoint')
         | 
| 229 | 
            +
                end
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                it 'sends the auth_token as an authorization header' do
         | 
| 232 | 
            +
                  expect(RestClient::Request).to receive(:execute).with(hash_including(headers: { 'Authorization' => 'Token 12345' }))
         | 
| 233 | 
            +
                  client.make_request('/my/endpoint')
         | 
| 234 | 
            +
                end
         | 
| 235 | 
            +
             | 
| 236 | 
            +
                it 'returns the response' do
         | 
| 237 | 
            +
                  expect( client.make_request('endpoint') ).to eq('response')
         | 
| 238 | 
            +
                end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                context 'when the get raises a RestClient::Unauthorized exception' do
         | 
| 241 | 
            +
                  before do
         | 
| 242 | 
            +
                    allow(RestClient::Request).to receive(:execute).and_raise( RestClient::Unauthorized.new('some error msg') )
         | 
| 243 | 
            +
                  end
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                  it 're-raises a PostcodeInfo::InvalidAuthToken' do
         | 
| 246 | 
            +
                    expect{ client.make_request('endpoint') }.to raise_error( PostcodeInfo::InvalidAuthToken )
         | 
| 247 | 
            +
                  end
         | 
| 248 | 
            +
                end
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                context 'when the get raises a RestClient::InternalServerError exception' do
         | 
| 251 | 
            +
                  before do
         | 
| 252 | 
            +
                    allow(RestClient::Request).to receive(:execute).and_raise( RestClient::InternalServerError.new('some error msg') )
         | 
| 253 | 
            +
                  end
         | 
| 254 | 
            +
             | 
| 255 | 
            +
                  it 're-raises a PostcodeInfo::ServerError' do
         | 
| 256 | 
            +
                    expect{ client.make_request('endpoint') }.to raise_error( PostcodeInfo::ServerError )
         | 
| 257 | 
            +
                  end
         | 
| 258 | 
            +
                end
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                context 'when the get raises a SocketError exception' do
         | 
| 261 | 
            +
                  before do
         | 
| 262 | 
            +
                    allow(RestClient::Request).to receive(:execute).and_raise( SocketError.new('some error msg') )
         | 
| 263 | 
            +
                  end
         | 
| 264 | 
            +
             | 
| 265 | 
            +
                  it 're-raises a PostcodeInfo::ServiceUnavailable' do
         | 
| 266 | 
            +
                    expect{ client.make_request('endpoint') }.to raise_error( PostcodeInfo::ServiceUnavailable )
         | 
| 267 | 
            +
                  end
         | 
| 268 | 
            +
                end
         | 
| 269 | 
            +
             | 
| 270 | 
            +
                context 'when the get raises any other exception' do
         | 
| 271 | 
            +
                  before do
         | 
| 272 | 
            +
                    allow(RestClient::Request).to receive(:execute).and_raise( ArgumentError.new('some error msg') )
         | 
| 273 | 
            +
                  end
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                  it 're-raises the original exception' do
         | 
| 276 | 
            +
                    expect{ client.make_request('endpoint') }.to raise_error( ArgumentError )
         | 
| 277 | 
            +
                  end
         | 
| 278 | 
            +
                end
         | 
| 279 | 
            +
              end
         | 
| 280 | 
            +
             | 
| 281 | 
            +
              describe 'handle_response' do
         | 
| 282 | 
            +
                let(:mock_response){ double('response', body: 'body') }
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                it 'parses the body as JSON, and symbolizes the keys' do
         | 
| 285 | 
            +
                  expect(JSON).to receive(:parse).with('body', symbolize_names: true).and_return('parsed')
         | 
| 286 | 
            +
                  client.send(:handle_response, mock_response)
         | 
| 287 | 
            +
                end
         | 
| 288 | 
            +
              end
         | 
| 289 | 
            +
            end
         |