zoopla 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- zoopla (0.2.0)
4
+ zoopla (0.2.2)
5
5
  curb (~> 0.7.12)
6
6
  hashie (~> 1.0.0)
7
7
  json (~> 1.4.3)
@@ -1,9 +1,13 @@
1
1
  # Zoopla API Wrapper
2
2
 
3
- Use this gem to access real estate data using zoopla.co.uk API from ruby code:
3
+ Use this gem to access real estate data using zoopla.co.uk API from ruby code.
4
4
 
5
5
  * property listings with addresses, prices, agent details etc
6
- * more to come
6
+ * request parameters are chained: `sales.in{:area => "Camden, London"}.for(200000..250000).each{|listing| puts listing.price}`
7
+ * transparent pagination: just pass a block to process listings
8
+ * error handling
9
+ * Zed-index
10
+ * integers, dates and lat/lon parameters are parsed
7
11
 
8
12
  **This gem is pre-alpha, therefore it's missing important features and it not production ready. Also, the interface may change considerably in the future**
9
13
 
@@ -38,6 +42,73 @@ To search for rentals, do a similar query:
38
42
 
39
43
  The input and output parameters for property listings are described in the [Zoopla documentation](http://developer.zoopla.com/docs/read/Property_listings)
40
44
 
45
+ ### Disambiguation
46
+
47
+ If an ambiguous area is specified, a `Zoopla::DisambiguationError` will be raised
48
+
49
+ begin
50
+ zoopla.sales.in({:area => "Whitechapel"}).each{|listing| puts l.price}
51
+ rescue Zoopla::DisambiguationError => e
52
+ puts "Which of the following did you mean?"
53
+ e.areas.each{|area| puts area} # areas is an Array of Strings
54
+ end
55
+
56
+ The output will be
57
+
58
+ Which of the following did you mean?
59
+ Whitechapel, Devon
60
+ Whitechapel, Lancashire
61
+ Whitechapel, London
62
+
63
+ ### Unknown locations
64
+
65
+ If an unknown location is specified, a `Zoopla::UnknownLocationError` will be raised. If the API can provide a spelling suggestion,
66
+ it will be available in `e.suggestion`
67
+
68
+ begin
69
+ zoopla.sales.in({:area => "Stok, Devon"}).each{|listing| puts l.price}
70
+ rescue Zoopla::UnknownLocationError => e
71
+ puts "Did you mean #{e.suggestion}" if e.suggestion
72
+ end
73
+
74
+ The output will be
75
+
76
+ Did you mean stoke, Devon
77
+
78
+ ### Zed-index
79
+
80
+ To find out the [Zed-index](http://www.zoopla.co.uk/property/estimate/about/) of a place do
81
+
82
+ $ index_set = zoopla.zed_index.in({:area => 'London', :output_type => "town"})
83
+ $ puts index_set.latest # 427646
84
+ $ puts index_set.zed_index # 427646
85
+ $ puts index_set.zed_index_3month # 430923
86
+
87
+ The full list of possible fields can be found in the [documentation](http://developer.zoopla.com/docs/read/Zed_Index_API)
88
+
89
+ ### Area value graphs
90
+
91
+ To get the list of graphs do
92
+
93
+ $ graphs = zoopla.area_value_graphs.in({:postcode => "SW1A"})
94
+ $ puts graphs.average_values_graph_url # http://www.zoopla.co.uk/dynimgs/graph/average_prices/SW1A?width=400&height=212
95
+
96
+ To specify the size, chain the methods
97
+
98
+ $ graphs = zoopla.area_value_graphs.large.in({:postcode => "SW1A"})
99
+ $ puts graphs.average_values_graph_url # http://www.zoopla.co.uk/dynimgs/graph/average_prices/SW1A?width=600&height=318
100
+
101
+ The full list of possible fields can be found in the [documentation](http://developer.zoopla.com/docs/read/Area_Value_Graphs)
102
+
103
+ ### Property rich list
104
+
105
+ In line with all other methods
106
+
107
+ $ list = zoopla.rich_list.in({:area => 'NW1', :output_type => :outcode, :area_type => :streets })
108
+ $ list.url # "http://www.zoopla.co.uk/property/richlist/london/NW1/camden-town-regents-park-marylebone-north"
109
+ $ list.lowest.first.name # "Wrotham Road, London NW1"
110
+
111
+ Valid combinations of `output_type`/`area_type` are described in the [documentation](http://developer.zoopla.com/docs/read/Property_Rich_List)
41
112
 
42
113
  ## Contributing to zoopla
43
114
 
@@ -4,8 +4,12 @@ require 'cgi'
4
4
  require 'hashie'
5
5
 
6
6
  require File.expand_path('../zoopla/version', __FILE__)
7
+ require File.expand_path('../zoopla/errors', __FILE__)
7
8
  require File.expand_path('../zoopla/api', __FILE__)
8
9
  require File.expand_path('../zoopla/listings', __FILE__)
10
+ require File.expand_path('../zoopla/zed_index', __FILE__)
11
+ require File.expand_path('../zoopla/area_value_graphs', __FILE__)
12
+ require File.expand_path('../zoopla/property_rich_list', __FILE__)
9
13
 
10
14
  class Zoopla
11
15
 
@@ -25,4 +29,23 @@ class Zoopla
25
29
  Sales.new(@api_key)
26
30
  end
27
31
 
32
+ # Delegates to the ZedIndex class
33
+ # @return [ZedIndex]
34
+ def zed_index
35
+ ZedIndex.new(@api_key)
36
+ end
37
+
38
+ # Delegates to the AreaValueGraphs class
39
+ # @return [AreaValueGraphs]
40
+ def area_value_graphs
41
+ AreaValueGraphs.new(@api_key)
42
+ end
43
+
44
+ # Delegates to the PropertyRichList class
45
+ # @return [PropertyRichList]
46
+ def property_rich_list
47
+ PropertyRichList.new(@api_key)
48
+ end
49
+ alias_method :rich_list, :property_rich_list
50
+
28
51
  end
@@ -1,43 +1,82 @@
1
1
  class Zoopla
2
2
 
3
- # Raised when Zoopla returns the HTTP status code 400
4
- class BadRequestError < StandardError; end
5
-
6
- # Raised when Zoopla returns the HTTP status code 401
7
- class UnauthorizedRequestError < StandardError; end
8
-
9
- # Raised when Zoopla returns the HTTP status code 403
10
- class ForbiddenError < StandardError; end
11
-
12
- # Raised when Zoopla returns the HTTP status code 404
13
- class NotFoundError < StandardError; end
14
-
15
- # Raised when Zoopla returns the HTTP status code 405
16
- class MethodNotAllowedError < StandardError; end
17
-
18
- # Raised when Zoopla returns the HTTP status code 500
19
- class InternalServerError < StandardError; end
20
-
21
- class API # abstract
3
+ # Abstract class that understands how to talk to the API
4
+ class API
22
5
 
23
6
  def initialize(api_key)
24
7
  @key = api_key
8
+ reset!
9
+ end
10
+
11
+ # Resets all parameters except the API key
12
+ # @return [Rentals, Sales]
13
+ def reset!
14
+ @request = default_parameters
15
+ @actual_location = nil
16
+ self
17
+ end
18
+
19
+ # Holds standard output parameters for the call to the server, if any
20
+ def actual_location
21
+ return @actual_location if @actual_location
22
+ fetch_data(@request)
25
23
  end
26
24
 
27
25
  private
28
26
 
27
+ def valid_output_types
28
+ %w(postcode street town outcode area county country)
29
+ end
30
+
31
+ def check_output_type(location)
32
+ raise InvalidOutputTypeError.new("Invalid output type: #{location[:output_type]}") unless valid_output_types.include? location[:output_type].to_s or location[:output_type].nil?
33
+ end
34
+
35
+ def extract_actual_location(reply)
36
+ @actual_location = Hashie::Mash.new
37
+ %w(area_name street town postcode county country).each {|field|
38
+ @actual_location[field] = reply[field]
39
+ }
40
+ @actual_location.bounding_box = parse_values_if_possible(reply.bounding_box)
41
+ end
42
+
43
+ def raise_error_if_necessary(code, body)
44
+ case code
45
+ when 400 then raise BadRequestError.new "Not enough parameters to produce a valid response."
46
+ when 401 then raise UnauthorizedRequestError.new "The API key could not be recognised and the request is not authorized."
47
+ when 403 then raise ForbiddenError.new "The requested method is not available for the API key specified (the API key is invalid?)."
48
+ when 404 then raise NotFoundError.new "A method was requested that is not available in the API version specified."
49
+ when 405 then raise MethodNotAllowedError.new "The HTTP request that was made requested an API method that can not process the HTTP method used."
50
+ when 500 then raise InternalServerError.new "Internal Server Error"
51
+ else
52
+ raise_api_specific_error_if_necessary(body)
53
+ end
54
+ end
55
+
56
+ def raise_api_specific_error_if_necessary(body)
57
+ return unless body && body.error_code
58
+ case body.error_code.to_i
59
+ when -1 then raise DisambiguationError.new(body.disambiguation)
60
+ when 1 then raise InsufficientArgumentsError.new(body.error_string)
61
+ when 5 then raise InvalidRequestedDataError.new(body.error_string)
62
+ when 7 then raise UnknownLocationError.new(body.suggestion)
63
+ end
64
+ end
65
+
29
66
  def fetch_data(params)
30
67
  response_code, body = call(url(params))
31
- return preprocess(body) if response_code == 200
32
- raise case response_code
33
- when 400 then BadRequestError.new "Not enough parameters to produce a valid response."
34
- when 401 then UnauthorizedRequestError.new "The API key could not be recognised and the request is not authorized."
35
- when 403 then ForbiddenError.new "The requested method is not available for the API key specified (the API key is invalid?)."
36
- when 404 then NotFoundError.new "A method was requested that is not available in the API version specified."
37
- when 405 then MethodNotAllowedError.new "The HTTP request that was made requested an API method that can not process the HTTP method used."
38
- when 500 then InternalServerError.new "Internal Server Error"
39
- else StandardError.new "Unexpected HTTP error"
40
- end
68
+ body = parse body if body
69
+ raise_error_if_necessary response_code, body
70
+ extract_actual_location(body)
71
+ preprocess body
72
+ end
73
+
74
+ def preprocess(reply)
75
+ reply
76
+ end
77
+
78
+ def default_parameters
79
+ {}
41
80
  end
42
81
 
43
82
  def call(url)
@@ -53,7 +92,11 @@ class Zoopla
53
92
  end
54
93
 
55
94
  def tryParsingInteger(field, value)
56
- (value.to_i rescue 0) if %w(price listing_id num_bathrooms num_bedrooms num_floors num_recepts).include? field
95
+ (value.to_i rescue 0) if %w(zed_index price listing_id num_bathrooms num_bedrooms num_floors num_recepts).include? field
96
+ end
97
+
98
+ def tryParsingFloat(field, value)
99
+ (value.to_f rescue 0.0) if %w(longitude_min longitude_max latitude_min latitude_max).include? field
57
100
  end
58
101
 
59
102
  def tryParsingDate(field, value)
@@ -69,10 +112,15 @@ class Zoopla
69
112
  end
70
113
 
71
114
  def parse_values_if_possible(reply)
72
- return reply if reply.is_a? String
115
+ return reply unless reply.is_a? Hash
73
116
  reply.each_pair do |field, value|
74
- reply[field] = tryParsingHash(field, value) || tryParsingArray(field, value) || tryParsingInteger(field, value) || tryParsingDate(field, value) || value
117
+ reply[field] = tryParsingHash(field, value) || tryParsingArray(field, value) || tryParsingInteger(field, value) ||tryParsingFloat(field, value) || tryParsingDate(field, value) || value
75
118
  end
119
+ reply
120
+ end
121
+
122
+ def parse(reply)
123
+ Hashie::Mash.new.deep_update(parse_values_if_possible(JSON.parse reply))
76
124
  end
77
125
 
78
126
  end
@@ -0,0 +1,57 @@
1
+ class Zoopla
2
+
3
+ class AreaValueGraphs < API
4
+
5
+ # Defines the search area. All possible params are described at http://developer.zoopla.com/docs/
6
+ # @param [Hash] Location hash
7
+ # @return [AreaValueGraphs]
8
+ def in(location)
9
+ check_output_type location
10
+ @request.merge! location
11
+ reply = fetch_data(@request)
12
+ fields = %w(area_values_url home_values_graph_url value_trend_graph_url value_ranges_graph_url average_values_graph_url)
13
+ filtered = fields.inject({}) do |result, field|
14
+ result[field] = reply[field]
15
+ result
16
+ end
17
+ Hashie::Mash.new.update filtered
18
+ end
19
+
20
+ # Sets the size of the returned images to small
21
+ # @return AreaValueGraphs
22
+ def small
23
+ @request[:size] = 'small'
24
+ self
25
+ end
26
+
27
+ # Sets the size of the returned images to medium
28
+ # @return AreaValueGraphs
29
+ def medium
30
+ @request[:size] = 'medium'
31
+ self
32
+ end
33
+
34
+ # Sets the size of the returned images to large
35
+ # @return AreaValueGraphs
36
+ def large
37
+ @request[:size] = 'large'
38
+ self
39
+ end
40
+
41
+ private
42
+
43
+ def api_call
44
+ 'area_value_graphs'
45
+ end
46
+
47
+ def default_parameters
48
+ {:output_type => 'outcode'}
49
+ end
50
+
51
+ def valid_output_types
52
+ %w(outcode)
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,54 @@
1
+ class Zoopla
2
+
3
+ # Raised when Zoopla returns the HTTP status code 400
4
+ class BadRequestError < StandardError; end
5
+
6
+ # Raised when Zoopla returns the HTTP status code 401
7
+ class UnauthorizedRequestError < StandardError; end
8
+
9
+ # Raised when Zoopla returns the HTTP status code 403
10
+ class ForbiddenError < StandardError; end
11
+
12
+ # Raised when Zoopla returns the HTTP status code 404
13
+ class NotFoundError < StandardError; end
14
+
15
+ # Raised when Zoopla returns the HTTP status code 405
16
+ class MethodNotAllowedError < StandardError; end
17
+
18
+ # Raised when Zoopla returns the HTTP status code 500
19
+ class InternalServerError < StandardError; end
20
+
21
+ # Raised when there are insufficient arguments for the API to return a result
22
+ class InsufficientArgumentsError < StandardError; end
23
+
24
+ # Raised under mysterious circumstances
25
+ class InvalidRequestedDataError < StandardError; end
26
+
27
+ # Raised when an invalid output type is specified
28
+ class InvalidOutputTypeError < StandardError; end
29
+
30
+ # Raised when an ambiguous area name is given, e.g. Whitechapel (is it in London? Devon? Lancashire?)
31
+ class DisambiguationError < StandardError
32
+
33
+ # Array of possible locations (Strings)
34
+ attr_reader :areas
35
+
36
+ def initialize(areas)
37
+ @areas = areas
38
+ end
39
+
40
+ end
41
+
42
+ # Raised when an unknown location is searched for, e.g. Stok
43
+ class UnknownLocationError < StandardError
44
+
45
+ # String, a spelling suggestion, may be nil
46
+ attr_reader :suggestion
47
+
48
+ def initialize(suggestion)
49
+ @suggestion = suggestion
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -7,6 +7,7 @@ class Zoopla
7
7
  # @param [Hash] Location hash
8
8
  # @return [Sales, Rentals]
9
9
  def in(location)
10
+ check_output_type location
10
11
  @request.merge! location
11
12
  self
12
13
  end
@@ -130,6 +131,7 @@ class Zoopla
130
131
 
131
132
  # Iterates over the results. Possible fields are described at http://developer.zoopla.com/docs/read/Property_listings
132
133
  # @yield [Hashie::Mash] a listing with data, e.g. sales.each{|listing| puts listing.price }
134
+ # @raise Zoopla::DisambiguationError if an ambiguous area is specified. Always expect this exception
133
135
  def each
134
136
  fetched_so_far, number_of_results = 0, 0
135
137
  @request[:page_number] = 1
@@ -142,14 +144,7 @@ class Zoopla
142
144
  end
143
145
  end while fetched_so_far < number_of_results
144
146
  end
145
-
146
- # Resets all parameters except the API key
147
- # @return [Rentals, Sales]
148
- def reset!
149
- @request = default_parameters
150
- self
151
- end
152
-
147
+
153
148
  private
154
149
 
155
150
  def set_limiting_value(limit, attribute, value)
@@ -173,13 +168,8 @@ class Zoopla
173
168
  end
174
169
 
175
170
  def preprocess(reply)
176
- reply = JSON.parse reply
177
- number_of_results = reply["result_count"] || 0
178
- listings = reply["listing"].inject([]) do |memo, listing|
179
- parse_values_if_possible(listing)
180
- memo << Hashie::Mash.new.update(listing)
181
- end
182
- [number_of_results, listings]
171
+ number_of_results = reply.result_count || 0
172
+ [number_of_results, reply.listing]
183
173
  end
184
174
 
185
175
  def api_call
@@ -4,12 +4,7 @@ class Zoopla
4
4
  class Rentals < API
5
5
 
6
6
  include Zoopla::Listing
7
-
8
- def initialize(*args)
9
- super(*args)
10
- reset!
11
- end
12
-
7
+
13
8
  # Include property listings that are already rented in the results
14
9
  # @return [Rentals]
15
10
  def include_rented
@@ -5,11 +5,6 @@ class Zoopla
5
5
 
6
6
  include Zoopla::Listing
7
7
 
8
- def initialize(*args)
9
- super(*args)
10
- reset!
11
- end
12
-
13
8
  # Whether to include property listings that are already sold in the results
14
9
  # @return [Sales]
15
10
  def include_sold
@@ -0,0 +1,37 @@
1
+ class Zoopla
2
+
3
+ class PropertyRichList < API
4
+
5
+ # Defines the search area. All possible params are described at http://developer.zoopla.com/docs/
6
+ # @param [Hash] Location hash
7
+ # @return [PropertyRichList]
8
+ def in(location)
9
+ check_output_type location
10
+ # check_area_type location
11
+ @request.merge! location
12
+ reply = fetch_data(@request)
13
+ result = Hashie::Mash.new
14
+ result.richlist_url = result.url = reply.richlist_url
15
+ result.highest = reply.highest
16
+ result.lowest = reply.lowest
17
+ result
18
+ end
19
+
20
+ private
21
+
22
+ def api_call
23
+ 'richlist'
24
+ end
25
+
26
+ def default_parameters
27
+ {:output_type => 'outcode'}
28
+ end
29
+
30
+ def valid_output_types
31
+ %w(outcode area town county country)
32
+ end
33
+
34
+
35
+ end
36
+
37
+ end
@@ -3,7 +3,7 @@ class Zoopla
3
3
  module Version
4
4
  MAJOR = 0
5
5
  MINOR = 2
6
- PATCH = 0
6
+ PATCH = 2
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
9
9
  end
@@ -0,0 +1,37 @@
1
+ class Zoopla
2
+
3
+ class ZedIndex < API
4
+
5
+ # Defines the search area. All possible params are described at http://developer.zoopla.com/docs/
6
+ # @param [Hash] Location hash
7
+ # @return [ZedIndex]
8
+ def in(location)
9
+ check_output_type location
10
+ @request.merge! location
11
+ reply = fetch_data(@request)
12
+ fields = %w(area_url zed_index zed_index_3month zed_index_6month zed_index_1year zed_index_2year zed_index_3year zed_index_4year zed_index_5year)
13
+ filtered = fields.inject({:latest => reply["zed_index"].to_i}) do |result, field|
14
+ reply[field] = reply[field].to_i if field =~ /zed_index/ && reply[field]
15
+ result[field] = reply[field]
16
+ result
17
+ end
18
+ Hashie::Mash.new.update filtered
19
+ end
20
+
21
+ private
22
+
23
+ def api_call
24
+ 'zed_index'
25
+ end
26
+
27
+ def default_parameters
28
+ {:output_type => 'outcode'}
29
+ end
30
+
31
+ def valid_output_types
32
+ %w(town outcode county country)
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1 @@
1
+ {"country":"England","area_name":null,"longitude":-0.146927,"street":null,"town":"","average_values_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/average_prices/NW1?width=400&height=212","latitude":51.5330895,"value_ranges_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/price_bands/NW1?width=400&height=212","value_trend_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/local_type_trends/NW1?width=400&height=212","county":"London","bounding_box":{"latitude_min":"51.518085","longitude_min":"-0.170917","longitude_max":"-0.122937","latitude_max":"51.548094"},"area_values_url":"http://www.zoopla.co.uk/home-values/london/NW1/camden-town-regents-park-marylebone-north","postcode":"NW1","home_values_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/home_value/oc/NW1?width=400&height=212"}
@@ -0,0 +1 @@
1
+ {"country":"England","area_name":null,"longitude":-0.146927,"street":null,"town":"","average_values_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/average_prices/NW1?width=600&height=318","latitude":51.5330895,"value_ranges_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/price_bands/NW1?width=600&height=318","value_trend_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/local_type_trends/NW1?width=600&height=318","county":"London","bounding_box":{"latitude_min":"51.518085","longitude_min":"-0.170917","longitude_max":"-0.122937","latitude_max":"51.548094"},"area_values_url":"http://www.zoopla.co.uk/home-values/london/NW1/camden-town-regents-park-marylebone-north","postcode":"NW1","home_values_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/home_value/oc/NW1?width=600&height=318"}
@@ -0,0 +1 @@
1
+ {"country":"England","area_name":null,"longitude":-0.146927,"street":null,"town":"","average_values_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/average_prices/NW1?width=200&height=106","latitude":51.5330895,"value_ranges_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/price_bands/NW1?width=200&height=106","value_trend_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/local_type_trends/NW1?width=200&height=106","county":"London","bounding_box":{"latitude_min":"51.518085","longitude_min":"-0.170917","longitude_max":"-0.122937","latitude_max":"51.548094"},"area_values_url":"http://www.zoopla.co.uk/home-values/london/NW1/camden-town-regents-park-marylebone-north","postcode":"NW1","home_values_graph_url":"http://www.zoopla.co.uk/dynimgs/graph/home_value/oc/NW1?width=200&height=106"}
@@ -0,0 +1 @@
1
+ {"disambiguation":["Whitechapel, Devon","Whitechapel, Lancashire","Whitechapel, London"],"error_string":"Disambiguation required.","error_code":-1}
@@ -0,0 +1 @@
1
+ {"error_string":"Insufficient arguments","error_code":"1"}
@@ -0,0 +1 @@
1
+ {"error_string":"Requested data is invalid, please refer to documentation","error_code":"5"}
@@ -0,0 +1 @@
1
+ {"error_string":"Unknown location entered.","error_code":"7"}
@@ -0,0 +1 @@
1
+ {"country":"England","area_name":null,"longitude":-0.146927,"highest":[{"zed_index":"5174714","name":"Park Square East, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/park-square-east"},{"zed_index":"3980577","name":"Cambridge Gate, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/cambridge-gate"},{"zed_index":"3909518","name":"Chester Terrace, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/chester-terrace"},{"zed_index":"2899292","name":"Gloucester Gate, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/gloucester-gate"},{"zed_index":"2719681","name":"Regents Park Terrace, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/regents-park-terrace"},{"zed_index":"2698449","name":"Kent Terrace, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/kent-terrace"},{"zed_index":"2463170","name":"Park Village West, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/park-village-west"},{"zed_index":"1917504","name":"Brunswick Place, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/brunswick-place-nw1"},{"zed_index":"1907749","name":"Chester Place, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/chester-place"},{"zed_index":"1881067","name":"York Terrace West, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/york-terrace-west"},{"zed_index":"1800075","name":"Chagford Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/chagford-street"},{"zed_index":"1779054","name":"York Terrace East, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/york-terrace-east"},{"zed_index":"1745053","name":"Cumberland Terrace, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/cumberland-terrace"},{"zed_index":"1737473","name":"Rothwell Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/rothwell-street"},{"zed_index":"1717895","name":"Prince Albert Road, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/prince-albert-road-nw1"},{"zed_index":"1668805","name":"St. Marks Crescent, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/st-marks-crescent"},{"zed_index":"1628394","name":"Chamberlain Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/chamberlain-street"},{"zed_index":"1622213","name":"Berkley Road, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/berkley-road"},{"zed_index":"1614178","name":"Chalcot Crescent, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/chalcot-crescent"},{"zed_index":"1396558","name":"Park Square Mews, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/park-square-mews"}],"street":null,"town":"","lowest":[{"zed_index":"200353","name":"Wrotham Road, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/wrotham-road-nw1"},{"zed_index":"209635","name":"Varndell Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/varndell-street"},{"zed_index":"217475","name":"Maiden Lane, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/maiden-lane-nw1"},{"zed_index":"226860","name":"Pancras Road, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/pancras-road"},{"zed_index":"231922","name":"Augustus Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/augustus-street"},{"zed_index":"236737","name":"Ferdinand Place, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/ferdinand-place"},{"zed_index":"237750","name":"Hampstead Road, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/hampstead-road"},{"zed_index":"239249","name":"Phoenix Road, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/phoenix-road-nw1"},{"zed_index":"240097","name":"George Mews, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/george-mews-nw1"},{"zed_index":"240484","name":"Penfold Place, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/penfold-place"},{"zed_index":"241605","name":"Werrington Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/werrington-street"},{"zed_index":"244254","name":"Purchese Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/purchese-street"},{"zed_index":"244336","name":"Harrington Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/harrington-street"},{"zed_index":"245213","name":"Stanhope Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/stanhope-street"},{"zed_index":"249274","name":"Bridgeway Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/bridgeway-street"},{"zed_index":"251384","name":"Ossulston Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/ossulston-street"},{"zed_index":"252863","name":"Mornington Place, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/mornington-place"},{"zed_index":"253139","name":"Osnaburgh Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/osnaburgh-street"},{"zed_index":"253787","name":"Barker Drive, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/barker-drive"},{"zed_index":"256284","name":"Farrier Street, London NW1","details_url":"http://www.zoopla.co.uk/home-values/london/farrier-street"}],"richlist_url":"http://www.zoopla.co.uk/property/richlist/london/NW1/camden-town-regents-park-marylebone-north","latitude":51.5330895,"county":"London","postcode":"NW1","bounding_box":{"latitude_min":"51.518085","longitude_min":"-0.170917","longitude_max":"-0.122937","latitude_max":"51.548094"}}
@@ -0,0 +1 @@
1
+ {"suggestion":"stoke","error_string":"Unknown location entered.","error_code":"7"}
@@ -0,0 +1 @@
1
+ {"area_url":"http://www.zoopla.co.uk/home-values/london","zed_index_1year":449379,"street":null,"zed_index":"427646","town":"","zed_index_2year":376536,"zed_index_3year":474942,"latitude":51.523591,"postcode":"","zed_index_6month":459057,"country":"England","area_name":null,"longitude":-0.105602,"zed_index_4year":463594,"zed_index_3month":430923,"county":"London","bounding_box":{"latitude_min":"51.363621","longitude_min":"-0.34844","longitude_max":"0.137236","latitude_max":"51.683561"},"zed_index_5year":416328}
@@ -6,8 +6,104 @@ class TestAPI < Test::Unit::TestCase
6
6
  @rentals = Zoopla.new('my_api_key').rentals
7
7
  end
8
8
 
9
+ def test_invalid_output_type
10
+ assert_raise Zoopla::InvalidOutputTypeError do
11
+ @rentals.in({:output_type => :block})
12
+ end
13
+ assert_nothing_raised { @rentals.in({:output_type => "street"}) }
14
+ assert_nothing_raised { @rentals.in({:output_type => :street}) }
15
+ assert_nothing_raised { @rentals.in({:output_type => :postcode}) }
16
+ assert_nothing_raised { @rentals.in({:output_type => :outcode}) }
17
+ assert_nothing_raised { @rentals.in({:output_type => :town}) }
18
+ assert_nothing_raised { @rentals.in({:output_type => :county}) }
19
+ assert_nothing_raised { @rentals.in({:output_type => :country}) }
20
+ assert_nothing_raised { @rentals.in({:output_type => :area}) }
21
+ end
22
+
23
+ def test_disambiguation
24
+ e = assert_raise Zoopla::DisambiguationError do
25
+ @rentals.send(:raise_error_if_necessary, 200, @rentals.send(:parse, api_reply('disambiguation')))
26
+ end
27
+ assert_equal ["Whitechapel, Devon", "Whitechapel, Lancashire", "Whitechapel, London"], e.areas
28
+ end
29
+
30
+ def test_insufficient_argumetns
31
+ assert_raise Zoopla::InsufficientArgumentsError do
32
+ @rentals.send(:raise_error_if_necessary, 200, @rentals.send(:parse, api_reply('insufficient_arguments')))
33
+ end
34
+ end
35
+
36
+ def test_unknown_location_with_suggestion
37
+ e = assert_raise Zoopla::UnknownLocationError do
38
+ @rentals.send(:raise_error_if_necessary, 200, @rentals.send(:parse, api_reply('suggestion')))
39
+ end
40
+ assert_equal 'stoke', e.suggestion
41
+ end
42
+
43
+ def test_unknown_location_without_suggestion
44
+ e = assert_raise Zoopla::UnknownLocationError do
45
+ @rentals.send(:raise_error_if_necessary, 200, @rentals.send(:parse, api_reply('no_suggestion')))
46
+ end
47
+ assert_nil e.suggestion
48
+ end
49
+
50
+ def test_actual_location
51
+ @rentals.send(:extract_actual_location, @rentals.send(:parse, api_reply('postcode')))
52
+ location = @rentals.actual_location
53
+ assert_equal 'London', location.county
54
+ assert_equal 'England', location.country
55
+ assert_equal 'E1W 3TJ', location.postcode
56
+ assert_equal 51.506390, location.bounding_box.latitude_min
57
+ assert_equal 51.506390, location.bounding_box.latitude_max
58
+ assert_equal -0.054738, location.bounding_box.longitude_max
59
+ assert_equal -0.054738, location.bounding_box.longitude_min
60
+ end
61
+
62
+ def test_actual_location_fallback
63
+ @rentals.expects(:fetch_data)
64
+ @rentals.actual_location
65
+ end
66
+
67
+ def test_actual_location_fallback
68
+ @rentals.send(:extract_actual_location, @rentals.send(:parse, api_reply('postcode')))
69
+ @rentals.expects(:fetch_data).never
70
+ @rentals.actual_location
71
+ end
72
+
73
+ def test_deep_parsing_the_reply
74
+ reply = @rentals.send(:parse, api_reply('postcode'))
75
+ listing = reply.listing.first
76
+ assert_equal 11695072, listing.listing_id
77
+ assert_equal 'rent', listing.listing_status
78
+ assert_equal 275, listing.price
79
+ assert_equal 'Atkinson Mcleod', listing.agent_name
80
+ assert_equal '135 Leman Street, Aldgate', listing.agent_address
81
+ assert_equal 'http://static.zoopla.co.uk/zoopla_static_agent_logo_(26302).gif', listing.agent_logo
82
+ assert_match(/^Charming one double bedroom apartment .+Our Ref: rpl\/iupload\/CTL070029$/m, listing.description)
83
+ assert_equal 'http://www.zoopla.co.uk/to-rent/details/11695072', listing.details_url
84
+ assert_equal 'Prospect Place, Wapping Wall, Wapping, London E1W', listing.displayable_address
85
+ assert_equal 'http://content.zoopla.co.uk/18d7d607146d3f0ea8cd46c48b5984084613a8ce.jpg', listing.floor_plan.first
86
+ assert_equal 'Picture No.05', listing.image_caption
87
+ assert_equal 'http://images.zoopla.co.uk/f03d30a35c97bf20825af1db8f9e52e1c936dd42_354_255.jpg', listing.image_url
88
+ assert_equal 51.50639, listing.latitude
89
+ assert_equal(-0.054738, listing.longitude)
90
+ assert_equal 0, listing.num_bathrooms
91
+ assert_equal 1, listing.num_bedrooms
92
+ assert_equal 0, listing.num_floors
93
+ assert_equal 0, listing.num_recepts
94
+ assert_equal 'E1W', listing.outcode
95
+ assert_equal 'London', listing.post_town
96
+ assert_equal 265, listing.price_change.first.price
97
+ assert_equal Date.parse('2010-07-23 19:12:46'), listing.price_change.first.date
98
+ assert_equal 275, listing.price_change.last.price
99
+ assert_equal Date.parse('2011-01-06 19:00:45'), listing.price_change.last.date
100
+ assert_equal 'Flat', listing.property_type
101
+ assert_equal 'Wapping Wall Wapping London', listing.street_name
102
+ assert_equal 'http://images.zoopla.co.uk/f03d30a35c97bf20825af1db8f9e52e1c936dd42_80_60.jpg', listing.thumbnail_url
103
+ end
104
+
9
105
  def test_no_results_returned
10
- number_of_results, reply = @rentals.send(:preprocess, api_reply('empty'))
106
+ number_of_results, reply = @rentals.send(:preprocess, @rentals.send(:parse, api_reply('empty')))
11
107
  assert_equal 0, number_of_results
12
108
  assert_equal [], reply
13
109
  end
@@ -0,0 +1,41 @@
1
+ require 'helper'
2
+
3
+ class TestAreaValueGraphs < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @area_value_graphs = Zoopla.new('my_api_key').area_value_graphs
7
+ end
8
+
9
+ def test_in
10
+ @area_value_graphs.stubs(:fetch_data).returns(@area_value_graphs.send(:parse, api_reply('area_value_graphs')))
11
+ index_set = @area_value_graphs.medium.in({:postcode => 'NW1'})
12
+ assert_equal 'http://www.zoopla.co.uk/home-values/london/NW1/camden-town-regents-park-marylebone-north', index_set.area_values_url
13
+ assert_equal 'http://www.zoopla.co.uk/dynimgs/graph/home_value/oc/NW1?width=400&height=212', index_set.home_values_graph_url
14
+ assert_equal 'http://www.zoopla.co.uk/dynimgs/graph/local_type_trends/NW1?width=400&height=212', index_set.value_trend_graph_url
15
+ assert_equal 'http://www.zoopla.co.uk/dynimgs/graph/price_bands/NW1?width=400&height=212', index_set.value_ranges_graph_url
16
+ assert_equal 'http://www.zoopla.co.uk/dynimgs/graph/average_prices/NW1?width=400&height=212', index_set.average_values_graph_url
17
+ end
18
+
19
+ def test_small_size
20
+ @area_value_graphs.stubs(:fetch_data).returns(@area_value_graphs.send(:parse, api_reply('area_value_graphs_small')))
21
+ index_set = @area_value_graphs.small.in({:postcode => 'NW1'})
22
+ assert_equal 'http://www.zoopla.co.uk/dynimgs/graph/home_value/oc/NW1?width=200&height=106', index_set.home_values_graph_url
23
+ end
24
+
25
+ def test_larse_size
26
+ @area_value_graphs.stubs(:fetch_data).returns(@area_value_graphs.send(:parse, api_reply('area_value_graphs_large')))
27
+ index_set = @area_value_graphs.large.in({:postcode => 'NW1'})
28
+ assert_equal 'http://www.zoopla.co.uk/dynimgs/graph/home_value/oc/NW1?width=600&height=318', index_set.home_values_graph_url
29
+ end
30
+
31
+ def test_invalid_output_type
32
+ assert_raise Zoopla::InvalidOutputTypeError do
33
+ @area_value_graphs.send(:check_output_type, {:output_type => :postcode})
34
+ end
35
+ assert_raise Zoopla::InvalidOutputTypeError do
36
+ @area_value_graphs.send(:check_output_type, {:output_type => :area})
37
+ end
38
+ assert_nothing_raised { @area_value_graphs.send(:check_output_type, {:output_type => :outcode}) }
39
+ end
40
+
41
+ end
@@ -140,6 +140,7 @@ class TestZooplaListings < Test::Unit::TestCase
140
140
  end
141
141
 
142
142
  def test_furnished
143
+ listing_parameter_test(:furnished, 'furnished', {:furnished => 'furnished'})
143
144
  listing_parameter_test(:furnished, 'furnished', {:furnished => 'furnished'})
144
145
  listing_parameter_test(:furnished, 'unfurnished', {:furnished => 'unfurnished'})
145
146
  listing_parameter_test(:furnished, 'part-furnished', {:furnished => 'part-furnished'})
@@ -216,46 +217,14 @@ class TestZooplaListings < Test::Unit::TestCase
216
217
  def test_requesting_multiple_results_pages_transparently
217
218
  mock = mock();
218
219
  mock.expects(:process_listing).times(12);
219
- page1 = @rentals.send :preprocess, api_reply('big_request_page1')
220
- page2 = @rentals.send :preprocess, api_reply('big_request_page2')
220
+ page1 = @rentals.send(:preprocess, @rentals.send(:parse, api_reply('big_request_page1')))
221
+ page2 = @rentals.send(:preprocess, @rentals.send(:parse, api_reply('big_request_page2')))
221
222
  @rentals.stubs(:fetch_data).returns(page1, page2)
222
223
  @rentals.in({:postcode => 'E1W 3TJ'}).within(0.1).price(300..400).each {|listing|
223
224
  mock.process_listing
224
225
  }
225
226
  end
226
227
 
227
- def test_deep_parsing_the_reply
228
- _, reply = @rentals.send(:preprocess, api_reply('postcode'))
229
- listing = reply.first
230
- assert_equal 11695072, listing.listing_id
231
- assert_equal 'rent', listing.listing_status
232
- assert_equal 275, listing.price
233
- assert_equal 'Atkinson Mcleod', listing.agent_name
234
- assert_equal '135 Leman Street, Aldgate', listing.agent_address
235
- assert_equal 'http://static.zoopla.co.uk/zoopla_static_agent_logo_(26302).gif', listing.agent_logo
236
- assert_match(/^Charming one double bedroom apartment .+Our Ref: rpl\/iupload\/CTL070029$/m, listing.description)
237
- assert_equal 'http://www.zoopla.co.uk/to-rent/details/11695072', listing.details_url
238
- assert_equal 'Prospect Place, Wapping Wall, Wapping, London E1W', listing.displayable_address
239
- assert_equal 'http://content.zoopla.co.uk/18d7d607146d3f0ea8cd46c48b5984084613a8ce.jpg', listing.floor_plan.first
240
- assert_equal 'Picture No.05', listing.image_caption
241
- assert_equal 'http://images.zoopla.co.uk/f03d30a35c97bf20825af1db8f9e52e1c936dd42_354_255.jpg', listing.image_url
242
- assert_equal 51.50639, listing.latitude
243
- assert_equal(-0.054738, listing.longitude)
244
- assert_equal 0, listing.num_bathrooms
245
- assert_equal 1, listing.num_bedrooms
246
- assert_equal 0, listing.num_floors
247
- assert_equal 0, listing.num_recepts
248
- assert_equal 'E1W', listing.outcode
249
- assert_equal 'London', listing.post_town
250
- assert_equal 265, listing.price_change.first.price
251
- assert_equal Date.parse('2010-07-23 19:12:46'), listing.price_change.first.date
252
- assert_equal 275, listing.price_change.last.price
253
- assert_equal Date.parse('2011-01-06 19:00:45'), listing.price_change.last.date
254
- assert_equal 'Flat', listing.property_type
255
- assert_equal 'Wapping Wall Wapping London', listing.street_name
256
- assert_equal 'http://images.zoopla.co.uk/f03d30a35c97bf20825af1db8f9e52e1c936dd42_80_60.jpg', listing.thumbnail_url
257
- end
258
-
259
228
  private
260
229
 
261
230
  def listing_parameter_test(param, value, result)
@@ -0,0 +1,26 @@
1
+ require 'helper'
2
+
3
+ class TestPropertyRichList < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @list = Zoopla.new('my_api_key').rich_list
7
+ end
8
+
9
+ def test_list
10
+ @list.stubs(:fetch_data).returns(@list.send(:parse, api_reply('richlist')))
11
+ richlist = @list.in({:area => 'NW1', :output_type => :outcode, :area_type => :streets })
12
+ assert_equal 'http://www.zoopla.co.uk/property/richlist/london/NW1/camden-town-regents-park-marylebone-north', richlist.richlist_url
13
+ assert_equal 'http://www.zoopla.co.uk/property/richlist/london/NW1/camden-town-regents-park-marylebone-north', richlist.url
14
+ highest = richlist.highest
15
+ lowest = richlist.lowest
16
+ assert_equal 20, highest.length
17
+ assert_equal 'Park Square East, London NW1', highest.first.name
18
+ assert_equal 5174714, highest.first.zed_index
19
+ assert_equal 'http://www.zoopla.co.uk/home-values/london/park-square-east', highest.first.details_url
20
+ assert_equal 20, lowest.length
21
+ assert_equal 'Wrotham Road, London NW1', lowest.first.name
22
+ assert_equal 200353, lowest.first.zed_index
23
+ assert_equal 'http://www.zoopla.co.uk/home-values/london/wrotham-road-nw1', lowest.first.details_url
24
+ end
25
+
26
+ end
@@ -0,0 +1,41 @@
1
+ require 'helper'
2
+
3
+ class TestZedIndex < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @zed_index = Zoopla.new('my_api_key').zed_index
7
+ end
8
+
9
+ def test_in
10
+ @zed_index.stubs(:fetch_data).returns(@zed_index.send(:parse, api_reply('zed_index')))
11
+ index_set = @zed_index.in({:area => 'London', :output_type => "town"})
12
+ assert_equal 'http://www.zoopla.co.uk/home-values/london', index_set.area_url
13
+ assert_equal 427646, index_set.latest
14
+ assert_equal 427646, index_set.zed_index
15
+ assert_equal 430923, index_set.zed_index_3month
16
+ assert_equal 459057, index_set.zed_index_6month
17
+ assert_equal 449379, index_set.zed_index_1year
18
+ assert_equal 376536, index_set.zed_index_2year
19
+ assert_equal 474942, index_set.zed_index_3year
20
+ assert_equal 463594, index_set.zed_index_4year
21
+ assert_equal 416328, index_set.zed_index_5year
22
+ end
23
+
24
+ def test_invalid_output_type
25
+ assert_raise Zoopla::InvalidOutputTypeError do
26
+ @zed_index.send(:check_output_type, {:output_type => :street})
27
+ end
28
+ assert_raise Zoopla::InvalidOutputTypeError do
29
+ @zed_index.send(:check_output_type, {:output_type => :postcode})
30
+ end
31
+ assert_raise Zoopla::InvalidOutputTypeError do
32
+ @zed_index.send(:check_output_type, {:output_type => :area})
33
+ end
34
+ assert_nothing_raised { @zed_index.send(:check_output_type, {:output_type => :outcode}) }
35
+ assert_nothing_raised { @zed_index.send(:check_output_type, {:output_type => :town}) }
36
+ assert_nothing_raised { @zed_index.send(:check_output_type, {:output_type => :county}) }
37
+ assert_nothing_raised { @zed_index.send(:check_output_type, {:output_type => :country}) }
38
+ end
39
+
40
+
41
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: zoopla
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.0
5
+ version: 0.2.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Evgeny Shadchnev
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-04 00:00:00 +00:00
13
+ date: 2011-03-06 00:00:00 +00:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -75,18 +75,35 @@ files:
75
75
  - Rakefile
76
76
  - lib/zoopla.rb
77
77
  - lib/zoopla/api.rb
78
+ - lib/zoopla/area_value_graphs.rb
79
+ - lib/zoopla/errors.rb
78
80
  - lib/zoopla/listings.rb
79
81
  - lib/zoopla/listings/listing.rb
80
82
  - lib/zoopla/listings/rentals.rb
81
83
  - lib/zoopla/listings/sales.rb
84
+ - lib/zoopla/property_rich_list.rb
82
85
  - lib/zoopla/version.rb
86
+ - lib/zoopla/zed_index.rb
87
+ - test/api_replies/area_value_graphs.js
88
+ - test/api_replies/area_value_graphs_large.js
89
+ - test/api_replies/area_value_graphs_small.js
83
90
  - test/api_replies/big_request_page1.js
84
91
  - test/api_replies/big_request_page2.js
92
+ - test/api_replies/disambiguation.js
85
93
  - test/api_replies/empty.js
94
+ - test/api_replies/insufficient_arguments.js
95
+ - test/api_replies/invalid_data.js
96
+ - test/api_replies/no_suggestion.js
86
97
  - test/api_replies/postcode.js
98
+ - test/api_replies/richlist.js
99
+ - test/api_replies/suggestion.js
100
+ - test/api_replies/zed_index.js
87
101
  - test/helper.rb
88
102
  - test/test_api.rb
89
- - test/test_zoopla_listings.rb
103
+ - test/test_area_value_graphs.rb
104
+ - test/test_listings.rb
105
+ - test/test_property_rich_list.rb
106
+ - test/test_zed_index.rb
90
107
  - zoopla.gemspec
91
108
  has_rdoc: true
92
109
  homepage: http://github.com/shadchnev/zoopla
@@ -117,10 +134,23 @@ signing_key:
117
134
  specification_version: 3
118
135
  summary: Access zoopla.co.uk API from ruby scripts
119
136
  test_files:
137
+ - test/api_replies/area_value_graphs.js
138
+ - test/api_replies/area_value_graphs_large.js
139
+ - test/api_replies/area_value_graphs_small.js
120
140
  - test/api_replies/big_request_page1.js
121
141
  - test/api_replies/big_request_page2.js
142
+ - test/api_replies/disambiguation.js
122
143
  - test/api_replies/empty.js
144
+ - test/api_replies/insufficient_arguments.js
145
+ - test/api_replies/invalid_data.js
146
+ - test/api_replies/no_suggestion.js
123
147
  - test/api_replies/postcode.js
148
+ - test/api_replies/richlist.js
149
+ - test/api_replies/suggestion.js
150
+ - test/api_replies/zed_index.js
124
151
  - test/helper.rb
125
152
  - test/test_api.rb
126
- - test/test_zoopla_listings.rb
153
+ - test/test_area_value_graphs.rb
154
+ - test/test_listings.rb
155
+ - test/test_property_rich_list.rb
156
+ - test/test_zed_index.rb