ideal_postcodes 0.1.1 → 2.0.1

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.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +22 -0
  3. data/CHANGELOG.md +20 -0
  4. data/LICENSE +21 -0
  5. data/README.md +289 -43
  6. data/Rakefile +13 -6
  7. data/ideal-postcodes-ruby.gemspec +11 -11
  8. data/lib/ideal_postcodes.rb +1 -1
  9. data/lib/idealpostcodes/address.rb +31 -0
  10. data/lib/idealpostcodes/errors.rb +31 -26
  11. data/lib/idealpostcodes/key.rb +14 -0
  12. data/lib/idealpostcodes/postcode.rb +20 -32
  13. data/lib/idealpostcodes/util.rb +38 -25
  14. data/lib/idealpostcodes/version.rb +2 -2
  15. data/lib/idealpostcodes.rb +114 -81
  16. data/spec/addresses_spec.rb +68 -0
  17. data/spec/idealpostcodes_spec.rb +56 -0
  18. data/spec/keys_spec.rb +25 -0
  19. data/spec/postcodes_spec.rb +77 -0
  20. data/spec/spec_helper.rb +89 -0
  21. data/spec/vcr_cassettes/IdealPostcodes_Address_lookup_raises_an_exception_if_invalid_key.yml +42 -0
  22. data/spec/vcr_cassettes/IdealPostcodes_Address_lookup_raises_an_exception_if_limit_breached.yml +42 -0
  23. data/spec/vcr_cassettes/IdealPostcodes_Address_lookup_raises_an_exception_if_no_lookups_remaining.yml +42 -0
  24. data/spec/vcr_cassettes/IdealPostcodes_Address_lookup_returns_an_address_for_a_valid_UDPRN.yml +74 -0
  25. data/spec/vcr_cassettes/IdealPostcodes_Address_lookup_returns_nil_for_an_invalid_UDPRN.yml +42 -0
  26. data/spec/vcr_cassettes/IdealPostcodes_Address_search_is_sensitive_to_limit.yml +81 -0
  27. data/spec/vcr_cassettes/IdealPostcodes_Address_search_is_sensitive_to_page.yml +369 -0
  28. data/spec/vcr_cassettes/IdealPostcodes_Address_search_raises_an_exception_if_invalid_key.yml +42 -0
  29. data/spec/vcr_cassettes/IdealPostcodes_Address_search_raises_an_exception_if_limit_breached.yml +42 -0
  30. data/spec/vcr_cassettes/IdealPostcodes_Address_search_raises_an_exception_if_no_lookups_remaining.yml +42 -0
  31. data/spec/vcr_cassettes/IdealPostcodes_Address_search_returns_results_in_a_SearchResult_object.yml +273 -0
  32. data/spec/vcr_cassettes/IdealPostcodes_Key_lookup_details_returns_key_details.yml +62 -0
  33. data/spec/vcr_cassettes/IdealPostcodes_Key_lookup_returns_the_availability_status_of_a_key_false_key_.yml +45 -0
  34. data/spec/vcr_cassettes/IdealPostcodes_Key_lookup_returns_the_availability_status_of_a_key_true_key_.yml +45 -0
  35. data/spec/vcr_cassettes/IdealPostcodes_Postcode_find_by_location_is_sensitive_to_limit_parameter.yml +52 -0
  36. data/spec/vcr_cassettes/IdealPostcodes_Postcode_find_by_location_is_sensitive_to_radius_parament.yml +133 -0
  37. data/spec/vcr_cassettes/IdealPostcodes_Postcode_find_by_location_returns_an_array_of_postcodes_and_locations.yml +84 -0
  38. data/spec/vcr_cassettes/IdealPostcodes_Postcode_find_by_location_returns_an_empty_array_if_no_results_are_found.yml +43 -0
  39. data/spec/vcr_cassettes/IdealPostcodes_Postcode_lookup_raises_an_exception_if_invalid_key.yml +42 -0
  40. data/spec/vcr_cassettes/IdealPostcodes_Postcode_lookup_raises_an_exception_if_key_has_run_out_of_balance.yml +42 -0
  41. data/spec/vcr_cassettes/IdealPostcodes_Postcode_lookup_raises_an_exception_if_limit_has_been_reached.yml +42 -0
  42. data/spec/vcr_cassettes/IdealPostcodes_Postcode_lookup_returns_a_list_of_addresses_for_a_postcode.yml +268 -0
  43. data/spec/vcr_cassettes/IdealPostcodes_Postcode_lookup_returns_an_empty_array_if_postcode_does_not_exist.yml +42 -0
  44. data/spec/vcr_cassettes/IdealPostcodes_key_available_returns_false_if_key_is_unavailable.yml +45 -0
  45. data/spec/vcr_cassettes/IdealPostcodes_key_available_returns_true_if_key_is_available.yml +45 -0
  46. data/spec/vcr_cassettes/IdealPostcodes_key_details_raises_an_exception_if_no_secret_is_provided.yml +45 -0
  47. data/spec/vcr_cassettes/IdealPostcodes_key_details_returns_key_information.yml +62 -0
  48. data/spec/vcr_cassettes/IdealPostcodes_request_generates_a_HTTP_request.yml +268 -0
  49. data/spec/vcr_cassettes/IdealPostcodes_request_raises_authentication_error_if_invalid_key_is_provided.yml +42 -0
  50. data/spec/vcr_cassettes/IdealPostcodes_request_raises_limit_reached_error_if_a_limit_has_been_breached.yml +42 -0
  51. data/spec/vcr_cassettes/IdealPostcodes_request_raises_token_exhausted_error_if_key_balance_is_depleted.yml +42 -0
  52. metadata +117 -52
  53. data/test/test_helper.rb +0 -77
  54. data/test/test_ideal_postcodes.rb +0 -78
@@ -1,35 +1,23 @@
1
1
  module IdealPostcodes
2
- class Postcode
2
+ module Postcode
3
+ def self.lookup(postcode)
4
+ begin
5
+ response = IdealPostcodes.request :get, "postcodes/#{postcode}"
6
+ addresses = response[:result]
7
+ rescue IdealPostcodes::ResourceNotFoundError => e
8
+ raise e unless e.response_code == 4040
3
9
 
4
- attr_reader :postcode_data, :postcode, :addresses
10
+ addresses = []
11
+ end
12
+ addresses
13
+ end
5
14
 
6
- def initialize(postcode = nil, postcode_data = nil)
7
- @raw = postcode_data
8
- @addresses = (postcode_data.nil? || postcode_data[:result].nil?) ? [] : postcode_data[:result]
9
- @postcode = postcode
10
- end
11
-
12
- def self.lookup(postcode)
13
- begin
14
- response = IdealPostcodes.request :get, "postcodes/#{postcode}"
15
- rescue IdealPostcodes::ResourceNotFoundError => error
16
- raise error unless error.response_code == 4040
17
- response = nil
18
- end
19
- new postcode, response
20
- end
21
-
22
- def empty?
23
- @raw.nil?
24
- end
25
-
26
- def addresses
27
- @addresses
28
- end
29
-
30
- def to_s
31
- addresses.to_s
32
- end
33
-
34
- end
35
- end
15
+ def self.find_by_location(geolocation)
16
+ query = { lonlat: "#{geolocation[:longitude]},#{geolocation[:latitude]}" }
17
+ query[:limit] = geolocation[:limit] unless geolocation[:limit].nil?
18
+ query[:radius] = geolocation[:radius] unless geolocation[:radius].nil?
19
+ response = IdealPostcodes.request :get, 'postcodes', query
20
+ response[:result]
21
+ end
22
+ end
23
+ end
@@ -1,29 +1,42 @@
1
+ require 'uri'
2
+
1
3
  module IdealPostcodes
2
- class Util
4
+ DEFAULT_PARSER = URI::Parser.new
3
5
 
4
- def self.merge_params(hash)
5
- result = []
6
- hash.each do |key, value|
7
- result << "#{CGI.escape(key.to_s)}=#{CGI.escape(value)}"
8
- end
9
- result.join("&")
10
- end
6
+ class Util
7
+ def self.escape(str)
8
+ IdealPostcodes::DEFAULT_PARSER.escape(str)
9
+ end
11
10
 
12
- def self.keys_to_sym(object)
13
- case object
14
- when Hash
15
- temp = {}
16
- object.each do |key, value|
17
- key = (key.to_sym rescue key) || key
18
- temp[key] = keys_to_sym(value)
19
- end
20
- temp
21
- when Array
22
- object.map { |elem| keys_to_sym(elem) }
23
- else
24
- object
25
- end
26
- end
11
+ def self.merge_params(hash)
12
+ result = []
13
+ hash.each do |key, value|
14
+ result << "#{escape(key.to_s)}=#{escape(value.to_s)}"
15
+ end
16
+ result.join('&')
17
+ end
27
18
 
28
- end
29
- end
19
+ def self.keys_to_sym(object)
20
+ case object
21
+ when Hash
22
+ temp = {}
23
+ object.each do |key, value|
24
+ key =
25
+ (
26
+ begin
27
+ key.to_sym
28
+ rescue StandardError
29
+ key
30
+ end
31
+ ) || key
32
+ temp[key] = keys_to_sym(value)
33
+ end
34
+ temp
35
+ when Array
36
+ object.map { |elem| keys_to_sym(elem) }
37
+ else
38
+ object
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,3 +1,3 @@
1
1
  module IdealPostcodes
2
- VERSION = '0.1.1'
3
- end
2
+ VERSION = '2.0.1'
3
+ end
@@ -1,91 +1,124 @@
1
- require 'rest-client'
2
- require 'uri'
3
- require 'multi_json'
4
1
  require 'cgi'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'rest-client'
5
5
  require 'idealpostcodes/version'
6
- require 'idealpostcodes/postcode'
6
+
7
+ # Require utility libraries
7
8
  require 'idealpostcodes/util'
8
9
  require 'idealpostcodes/errors'
9
10
 
11
+ # Require Resources
12
+ require 'idealpostcodes/key'
13
+ require 'idealpostcodes/address'
14
+ require 'idealpostcodes/postcode'
15
+
10
16
  module IdealPostcodes
11
- @base_url = 'https://api.ideal-postcodes.co.uk'
12
- @version = '1'
13
-
14
- class << self
15
- attr_accessor :api_key, :base_url, :version
16
- end
17
-
18
- def self.request(method, path, params = {})
19
- unless @api_key
20
- raise IdealPostcodes::AuthenticationError.new('No API Key provided. ' +
21
- 'Set your key with IdealPostcodes.api_key = #your_key')
22
- end
23
-
24
- url = URI.parse(resource_url(path))
25
- params.merge! api_key: @api_key
26
- url.query = Util.merge_params(params)
27
- request_options = {
28
- method: method.downcase.to_sym,
29
- url: url.to_s
30
- }
31
-
32
- begin
33
- response = generate_request(request_options)
34
- rescue RestClient::ExceptionWithResponse => error
35
- if rcode = error.http_code && rbody = error.http_body
36
- handle_error(rcode, rbody)
37
- else
38
- handle_client_error(error)
39
- end
40
- rescue RestClient::Exception, Errno::ECONNREFUSED => error
41
- handle_client_error(e)
42
- end
43
- parse response.body
44
- end
45
-
46
- private
47
-
48
- def self.resource_url(path='')
49
- URI.escape "#{@base_url}/v#{@version}/#{path}"
50
- end
51
-
52
- def self.generate_request(options)
53
- RestClient::Request.execute(options)
54
- end
55
-
56
- def self.parse(response)
57
- begin
58
- Util.keys_to_sym MultiJson.load(response)
59
- rescue MultiJson::DecodeError => e
60
- raise handle_client_error(e)
17
+ @base_url = 'https://api.ideal-postcodes.co.uk'
18
+ @version = '1'
19
+
20
+ class << self
21
+ attr_accessor :api_key, :base_url, :version, :secret
22
+ end
23
+
24
+ def self.request(method, path, params = {})
25
+ unless @api_key
26
+ raise IdealPostcodes::AuthenticationError, 'No API Key provided. ' +
27
+ 'Set your key with IdealPostcodes.api_key = #your_key'
28
+ end
29
+
30
+ url = URI.parse(resource_url(path))
31
+ params.merge! api_key: @api_key
32
+ url.query = Util.merge_params(params)
33
+ request_options = { method: method.downcase.to_sym, url: url.to_s }
34
+
35
+ begin
36
+ response = generate_request(request_options)
37
+ rescue RestClient::ExceptionWithResponse => e
38
+ if rcode = e.http_code && rbody = e.http_body
39
+ handle_error(rcode, rbody)
40
+ else
41
+ handle_client_error(e)
42
+ end
43
+ rescue RestClient::Exception, Errno::ECONNREFUSED => e
44
+ handle_client_error(e)
45
+ end
46
+ parse response.body
47
+ end
48
+
49
+ def self.apply_secret(secret)
50
+ @secret = secret
51
+ end
52
+
53
+ def self.key_available
54
+ response = Key.lookup @api_key
55
+ response[:available]
56
+ end
57
+
58
+ def self.key_details
59
+ if @secret.nil?
60
+ raise IdealPostcodes::AuthenticationError, 'No Secret Key provided. ' +
61
+ 'Set your secret key with IdealPostcodes.apply_secret #your_key'
61
62
  end
62
- end
63
+ response = Key.lookup_details @api_key, @secret
64
+ end
65
+
66
+ def self.resource_url(path = '')
67
+ IdealPostcodes::Util.escape "#{@base_url}/v#{@version}/#{path}"
68
+ end
63
69
 
64
- def self.handle_error(http_code, http_body)
70
+ def self.generate_request(options)
71
+ RestClient::Request.execute(options)
72
+ end
73
+
74
+ def self.parse(response)
75
+ Util.keys_to_sym JSON.parse(response)
76
+ rescue JSON::ParserError => e
77
+ raise handle_client_error(e)
78
+ end
79
+
80
+ def self.handle_error(http_code, http_body)
65
81
  error = parse http_body
66
82
 
67
- ideal_code, ideal_message = error[:code], error[:message]
68
-
69
- case ideal_code
70
- when 4010
71
- raise AuthenticationError.new ideal_message, http_code, http_body, ideal_code
72
- when 4020
73
- raise TokenExhaustedError.new ideal_message, http_code, http_body, ideal_code
74
- when 4021
75
- raise LimitReachedError.new ideal_message, http_code, http_body, ideal_code
76
- when 4040
77
- raise ResourceNotFoundError.new ideal_message, http_code, http_body, ideal_code
78
- else
79
- raise IdealPostcodesError.new ideal_message, http_code, http_body, ideal_code
80
- end
81
- end
82
-
83
- def self.handle_client_error(error)
84
- raise IdealPostcodesError.new("An unexpected error occured: #{error.message})")
85
- end
86
-
87
- def self.general_error(response_code, response_body)
88
- IdealPostcodesError.new "Invalid response object", response_code, response_body
89
- end
90
-
91
- end
83
+ ideal_code = error[:code]
84
+ ideal_message = error[:message]
85
+
86
+ case ideal_code
87
+ when 4010
88
+ raise AuthenticationError.new ideal_message,
89
+ http_code,
90
+ http_body,
91
+ ideal_code
92
+ when 4020
93
+ raise TokenExhaustedError.new ideal_message,
94
+ http_code,
95
+ http_body,
96
+ ideal_code
97
+ when 4021
98
+ raise LimitReachedError.new ideal_message,
99
+ http_code,
100
+ http_body,
101
+ ideal_code
102
+ when 4040
103
+ raise ResourceNotFoundError.new ideal_message,
104
+ http_code,
105
+ http_body,
106
+ ideal_code
107
+ else
108
+ raise IdealPostcodesError.new ideal_message,
109
+ http_code,
110
+ http_body,
111
+ ideal_code
112
+ end
113
+ end
114
+
115
+ def self.handle_client_error(error)
116
+ raise IdealPostcodesError, "An unexpected error occured: #{error.message})"
117
+ end
118
+
119
+ def self.general_error(response_code, response_body)
120
+ IdealPostcodesError.new 'Invalid response object',
121
+ response_code,
122
+ response_body
123
+ end
124
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe IdealPostcodes::Address do
4
+ describe '.lookup' do
5
+ it 'returns an address for a valid UDPRN' do
6
+ address = IdealPostcodes::Address.lookup 0
7
+ expect(is_address(address)).to eq(true)
8
+ end
9
+ it 'returns nil for an invalid UDPRN' do
10
+ address = IdealPostcodes::Address.lookup -1
11
+ expect(address).to be_nil
12
+ end
13
+ it 'raises an exception if invalid key' do
14
+ IdealPostcodes.api_key = 'foo'
15
+ expect { IdealPostcodes::Address.lookup 0 }.to raise_error(
16
+ IdealPostcodes::AuthenticationError
17
+ )
18
+ end
19
+ it 'raises an exception if no lookups remaining' do
20
+ expect { IdealPostcodes::Address.lookup -2 }.to raise_error(
21
+ IdealPostcodes::TokenExhaustedError
22
+ )
23
+ end
24
+ it 'raises an exception if limit breached' do
25
+ expect { IdealPostcodes::Address.lookup -3 }.to raise_error(
26
+ IdealPostcodes::LimitReachedError
27
+ )
28
+ end
29
+ end
30
+
31
+ describe '.search' do
32
+ it 'returns results in a SearchResult object' do
33
+ results = IdealPostcodes::Address.search 'ID1 1QD'
34
+ expect(results).to be_a(IdealPostcodes::Address::SearchResult)
35
+ expect(results.addresses.length).to be > 0
36
+ results.addresses.each do |address|
37
+ expect(is_address(address)).to eq(true)
38
+ end
39
+ end
40
+ it 'is sensitive to limit' do
41
+ limit = 1
42
+ results = IdealPostcodes::Address.search 'High Street', limit: limit
43
+ expect(results.addresses.length).to equal(limit)
44
+ expect(results.limit).to equal(limit)
45
+ end
46
+ it 'is sensitive to page' do
47
+ page = 1
48
+ results = IdealPostcodes::Address.search 'High Street', page: page
49
+ expect(results.page).to equal(page)
50
+ end
51
+ it 'raises an exception if invalid key' do
52
+ IdealPostcodes.api_key = 'foo'
53
+ expect {
54
+ results = IdealPostcodes::Address.search 'ID1 1QD'
55
+ }.to raise_error(IdealPostcodes::AuthenticationError)
56
+ end
57
+ it 'raises an exception if no lookups remaining' do
58
+ expect {
59
+ results = IdealPostcodes::Address.search 'ID1 CLIP'
60
+ }.to raise_error(IdealPostcodes::TokenExhaustedError)
61
+ end
62
+ it 'raises an exception if limit breached' do
63
+ expect {
64
+ results = IdealPostcodes::Address.search 'ID1 CHOP'
65
+ }.to raise_error(IdealPostcodes::LimitReachedError)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe IdealPostcodes do
4
+ describe '#request' do
5
+ it 'generates a HTTP request' do
6
+ response = IdealPostcodes.request :get, 'postcodes/ID1 1QD'
7
+ expect(response[:code]).to eq(2000)
8
+ end
9
+ it 'raises an error if no key is provided' do
10
+ IdealPostcodes.api_key = nil
11
+ expect do
12
+ response = IdealPostcodes.request :get, 'postcodes/ID1 1QD'
13
+ end.to raise_error(IdealPostcodes::AuthenticationError)
14
+ end
15
+ it 'raises authentication error if invalid key is provided' do
16
+ IdealPostcodes.api_key = 'foo'
17
+ expect do
18
+ response = IdealPostcodes.request :get, 'postcodes/ID1 1QD'
19
+ end.to raise_error(IdealPostcodes::AuthenticationError)
20
+ end
21
+ it 'raises token exhausted error if key balance is depleted' do
22
+ expect do
23
+ response = IdealPostcodes.request :get, 'postcodes/ID1 CLIP'
24
+ end.to raise_error(IdealPostcodes::TokenExhaustedError)
25
+ end
26
+ it 'raises limit reached error if a limit has been breached' do
27
+ expect do
28
+ response = IdealPostcodes.request :get, 'postcodes/ID1 CHOP'
29
+ end.to raise_error(IdealPostcodes::LimitReachedError)
30
+ end
31
+ end
32
+
33
+ describe '.key_available' do
34
+ it 'returns true if key is available' do
35
+ IdealPostcodes.api_key = 'iddqd'
36
+ expect(IdealPostcodes.key_available).to equal(true)
37
+ end
38
+ it 'returns false if key is unavailable' do
39
+ IdealPostcodes.api_key = 'idkfa'
40
+ expect(IdealPostcodes.key_available).to equal(false)
41
+ end
42
+ end
43
+
44
+ describe '.key_details' do
45
+ it 'raises an exception if no secret is provided' do
46
+ expect { IdealPostcodes.key_details }.to raise_error(
47
+ IdealPostcodes::AuthenticationError
48
+ )
49
+ end
50
+ it 'returns key information' do
51
+ IdealPostcodes.apply_secret(secret_key)
52
+ response = IdealPostcodes.key_details
53
+ expect(is_key(response)).to eq(true)
54
+ end
55
+ end
56
+ end
data/spec/keys_spec.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe IdealPostcodes::Key do
4
+ describe '.lookup' do
5
+ it 'returns the availability status of a key (true key)' do
6
+ result = IdealPostcodes::Key.lookup 'iddqd'
7
+ expect(result[:available]).to eq(true)
8
+ end
9
+ it 'returns the availability status of a key (false key)' do
10
+ result = IdealPostcodes::Key.lookup 'idkfa'
11
+ expect(result[:available]).to eq(false)
12
+ end
13
+ end
14
+
15
+ describe '.lookup_details' do
16
+ it 'returns key details' do
17
+ result = IdealPostcodes::Key.lookup_details 'gandhi', secret_key
18
+ expect(result[:lookups_remaining]).to_not be_nil
19
+ expect(result[:daily_limit]).to_not be_nil
20
+ expect(result[:individual_limit]).to_not be_nil
21
+ expect(result[:allowed_urls]).to_not be_nil
22
+ expect(result[:notifications]).to_not be_nil
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe IdealPostcodes::Postcode do
4
+ describe '.lookup' do
5
+ it 'returns a list of addresses for a postcode' do
6
+ addresses = IdealPostcodes::Postcode.lookup 'ID1 1QD'
7
+ expect(addresses.length).to be > 0
8
+ addresses.each do |address|
9
+ expect(is_address(address)).to eq(true)
10
+ expect(address[:postcode]).to eq('ID1 1QD')
11
+ end
12
+ end
13
+ it 'returns an empty array if postcode does not exist' do
14
+ addresses = IdealPostcodes::Postcode.lookup 'ID1 KFA'
15
+ expect(addresses.length).to eq(0)
16
+ end
17
+ it 'raises an exception if key has run out of balance' do
18
+ expect { IdealPostcodes::Postcode.lookup 'ID1 CLIP' }.to raise_error(
19
+ IdealPostcodes::TokenExhaustedError
20
+ )
21
+ end
22
+ it 'raises an exception if limit has been reached' do
23
+ expect { IdealPostcodes::Postcode.lookup 'ID1 CHOP' }.to raise_error(
24
+ IdealPostcodes::LimitReachedError
25
+ )
26
+ end
27
+ it 'raises an exception if invalid key' do
28
+ IdealPostcodes.api_key = 'foo'
29
+ expect { IdealPostcodes::Postcode.lookup 'ID1 1QD' }.to raise_error(
30
+ IdealPostcodes::AuthenticationError
31
+ )
32
+ end
33
+ end
34
+ describe '.find_by_location' do
35
+ it 'returns an array of postcodes and locations' do
36
+ lon = 0.6298
37
+ lat = 51.7923
38
+ postcodes =
39
+ IdealPostcodes::Postcode.find_by_location longitude: lon, latitude: lat
40
+ expect(postcodes.length).to be > 0
41
+ postcodes.each do |postcode|
42
+ expect(is_postcode_location(postcode)).to eq(true)
43
+ end
44
+ end
45
+ it 'returns an empty array if no results are found' do
46
+ lon = 0
47
+ lat = 0
48
+ postcodes =
49
+ IdealPostcodes::Postcode.find_by_location longitude: lon, latitude: lat
50
+ expect(postcodes).to be_a(Array)
51
+ expect(postcodes.length).to eq(0)
52
+ end
53
+ it 'is sensitive to limit parameter' do
54
+ lon = 0.6298
55
+ lat = 51.7923
56
+ limit = 1
57
+ postcodes =
58
+ IdealPostcodes::Postcode.find_by_location longitude: lon,
59
+ latitude: lat,
60
+ limit: limit
61
+ expect(postcodes.length).to eq(limit)
62
+ end
63
+ it 'is sensitive to radius parament' do
64
+ lon = 0.6298
65
+ lat = 51.7923
66
+ small_radius =
67
+ IdealPostcodes::Postcode.find_by_location longitude: lon,
68
+ latitude: lat,
69
+ radius: 10
70
+ large_radius =
71
+ IdealPostcodes::Postcode.find_by_location longitude: lon,
72
+ latitude: lat,
73
+ radius: 100
74
+ expect(large_radius.length > small_radius.length).to eq(true)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,89 @@
1
+ # Enable VCR
2
+ require 'vcr'
3
+ require 'webmock'
4
+
5
+ WebMock.enable!
6
+
7
+ VCR.configure do |c|
8
+ c.cassette_library_dir = 'spec/vcr_cassettes'
9
+ c.hook_into :webmock
10
+ end
11
+
12
+ # Configure Ideal Postcodes lib
13
+ require 'ideal_postcodes'
14
+
15
+ RSpec.configure do |c|
16
+ c.before(:each) do
17
+ IdealPostcodes.base_url = 'https://localhost:1337'
18
+ IdealPostcodes.api_key = 'gandhi'
19
+ IdealPostcodes.apply_secret nil
20
+ end
21
+
22
+ c.around(:each) do |example|
23
+ VCR.use_cassette(example.metadata[:full_description]) { example.run }
24
+ end
25
+ end
26
+
27
+ def contains_attributes(attribute_list, target)
28
+ result = true
29
+ attribute_list.each { |attribute| result = false if target[attribute].nil? }
30
+ result
31
+ end
32
+
33
+ def postcode_location_elements
34
+ %i[postcode longitude latitude northings eastings]
35
+ end
36
+
37
+ def is_postcode_location(postcode)
38
+ contains_attributes postcode_location_elements, postcode
39
+ end
40
+
41
+ def address_elements
42
+ %i[
43
+ postcode
44
+ postcode_inward
45
+ postcode_outward
46
+ post_town
47
+ dependant_locality
48
+ double_dependant_locality
49
+ thoroughfare
50
+ dependant_thoroughfare
51
+ building_number
52
+ building_name
53
+ sub_building_name
54
+ po_box
55
+ department_name
56
+ organisation_name
57
+ udprn
58
+ postcode_type
59
+ su_organisation_indicator
60
+ delivery_point_suffix
61
+ line_1
62
+ line_2
63
+ line_3
64
+ premise
65
+ county
66
+ district
67
+ ward
68
+ longitude
69
+ latitude
70
+ eastings
71
+ northings
72
+ ]
73
+ end
74
+
75
+ def is_address(address)
76
+ contains_attributes address_elements, address
77
+ end
78
+
79
+ def key_elements
80
+ %i[lookups_remaining daily_limit individual_limit allowed_urls notifications]
81
+ end
82
+
83
+ def is_key(key)
84
+ contains_attributes key_elements, key
85
+ end
86
+
87
+ def secret_key
88
+ 'uk_hxp6ouk0rmyXoobVJnehrsQcdvTfb'
89
+ end