ideal_postcodes 0.1.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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