zoopla 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.markdown +5 -3
- data/lib/zoopla.rb +17 -1
- data/lib/zoopla/api.rb +32 -4
- data/lib/zoopla/listings/listing.rb +187 -190
- data/lib/zoopla/listings/rentals.rb +30 -34
- data/lib/zoopla/listings/sales.rb +22 -25
- data/lib/zoopla/version.rb +3 -3
- data/test/api_replies/empty.js +1 -0
- data/test/test_api.rb +63 -0
- data/test/test_zoopla_listings.rb +6 -5
- metadata +6 -2
data/Gemfile.lock
CHANGED
data/README.markdown
CHANGED
@@ -4,6 +4,8 @@ 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
6
|
* more to come
|
7
|
+
|
8
|
+
**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**
|
7
9
|
|
8
10
|
## Documentation
|
9
11
|
The gem documentation can be found on [Rdoc.info](http://rdoc.info/github/shadchnev/zoopla/master/frames)
|
@@ -16,7 +18,7 @@ The API documentation can be found on the [Zoopla Website](http://developer.zoop
|
|
16
18
|
|
17
19
|
First, initialise the object with the API key [you got from Zoopla](http://developer.zoopla.com/member/register/)
|
18
20
|
|
19
|
-
$ sales = Zoopla
|
21
|
+
$ sales = Zoopla.new('my_api_key').sales
|
20
22
|
|
21
23
|
Then chain the parameter calls and provide a block to process the listings
|
22
24
|
|
@@ -31,8 +33,8 @@ This will produce
|
|
31
33
|
|
32
34
|
To search for rentals, do a similar query:
|
33
35
|
|
34
|
-
$ rentals = Zoopla
|
35
|
-
$ rentals.flats.in({:postcode => 'NW1 0DU'}).within(0.5).
|
36
|
+
$ rentals = Zoopla.new('my_api_key').rentals
|
37
|
+
$ rentals.flats.in({:postcode => 'NW1 0DU'}).within(0.5).for(300..350).each{|l| puts "#{l.num_bedrooms}-bedrooms flat for #{l.price}/week at #{l.displayable_address}"}
|
36
38
|
|
37
39
|
The input and output parameters for property listings are described in the [Zoopla documentation](http://developer.zoopla.com/docs/read/Property_listings)
|
38
40
|
|
data/lib/zoopla.rb
CHANGED
@@ -7,6 +7,22 @@ require File.expand_path('../zoopla/version', __FILE__)
|
|
7
7
|
require File.expand_path('../zoopla/api', __FILE__)
|
8
8
|
require File.expand_path('../zoopla/listings', __FILE__)
|
9
9
|
|
10
|
-
|
10
|
+
class Zoopla
|
11
|
+
|
12
|
+
def initialize(key)
|
13
|
+
@api_key = key
|
14
|
+
end
|
15
|
+
|
16
|
+
# Delegates to the Rentals class
|
17
|
+
# @return [Rentals]
|
18
|
+
def rentals
|
19
|
+
Rentals.new(@api_key)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Delegates to the Sales class
|
23
|
+
# @return [Sales]
|
24
|
+
def sales
|
25
|
+
Sales.new(@api_key)
|
26
|
+
end
|
11
27
|
|
12
28
|
end
|
data/lib/zoopla/api.rb
CHANGED
@@ -1,6 +1,24 @@
|
|
1
|
-
|
1
|
+
class Zoopla
|
2
2
|
|
3
|
-
|
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
|
4
22
|
|
5
23
|
def initialize(api_key)
|
6
24
|
@key = api_key
|
@@ -9,13 +27,23 @@ module Zoopla
|
|
9
27
|
private
|
10
28
|
|
11
29
|
def fetch_data(params)
|
12
|
-
|
30
|
+
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
|
13
41
|
end
|
14
42
|
|
15
43
|
def call(url)
|
16
44
|
curl = Curl::Easy.new(url)
|
17
45
|
curl.perform
|
18
|
-
|
46
|
+
[curl.response_code, curl.body_str]
|
19
47
|
end
|
20
48
|
|
21
49
|
def url(params)
|
@@ -1,194 +1,191 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
listings.each do |listing|
|
143
|
-
yield listing
|
144
|
-
end
|
145
|
-
end while fetched_so_far < number_of_results
|
146
|
-
end
|
147
|
-
|
148
|
-
# Resets all parameters except the API key
|
149
|
-
# @return [Rentals, Sales]
|
150
|
-
def reset!
|
151
|
-
@request = default_parameters
|
152
|
-
self
|
153
|
-
end
|
154
|
-
|
155
|
-
private
|
156
|
-
|
157
|
-
def set_limiting_value(limit, attribute, value)
|
158
|
-
ensure_valid_parameter("#{limit} #{attribute}", value, lambda {|p| p.is_a? Fixnum and p >= 0})
|
159
|
-
@request["#{limit}_#{attribute}".to_sym] = value
|
160
|
-
self
|
161
|
-
end
|
162
|
-
|
163
|
-
def set_range_parameter(attribute, value)
|
164
|
-
ensure_valid_parameter(attribute.to_s, value, lambda {|pr| pr.is_a? Fixnum or (pr.is_a?(Range) and pr.first <= pr.last)})
|
165
|
-
value = value..value if value.is_a? Fixnum
|
166
|
-
self.send("minimum_#{attribute}", value.first)
|
167
|
-
self.send("maximum_#{attribute}", value.last)
|
168
|
-
self
|
169
|
-
end
|
170
|
-
|
171
|
-
def ensure_valid_parameter(parameter, value, valid_options)
|
172
|
-
raise "#{parameter} not specified" unless value
|
173
|
-
raise "Unknown #{parameter}: #{value}" if valid_options.is_a? Array and !valid_options.include?(value.to_s)
|
174
|
-
raise "Invalid #{parameter}: #{value}" if valid_options.is_a? Proc and !valid_options.call(value)
|
175
|
-
end
|
176
|
-
|
177
|
-
def preprocess(reply)
|
178
|
-
number_of_results = reply["result_count"]
|
179
|
-
listings = reply["listing"].inject([]) do |memo, listing|
|
180
|
-
parse_values_if_possible(listing)
|
181
|
-
memo << Hashie::Mash.new.update(listing)
|
1
|
+
class Zoopla
|
2
|
+
|
3
|
+
# Common methods for Sales and Rentals classes
|
4
|
+
module Listing
|
5
|
+
|
6
|
+
# Defines the search area. All possible params are described at http://developer.zoopla.com/docs/
|
7
|
+
# @param [Hash] Location hash
|
8
|
+
# @return [Sales, Rentals]
|
9
|
+
def in(location)
|
10
|
+
@request.merge! location
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
# Sets the price range
|
15
|
+
# @param [Range] price range (weekly in case of rentals), e.g. 200..300
|
16
|
+
# @return [Sales, Rentals]
|
17
|
+
def price(price_range)
|
18
|
+
set_range_parameter(:price, price_range)
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method :for, :price
|
22
|
+
|
23
|
+
# Sets the number of bedrooms range
|
24
|
+
# @param [Range] bedrooms range, e.g. 2..3
|
25
|
+
# @return [Sales, Rentals]
|
26
|
+
def beds(beds_range)
|
27
|
+
set_range_parameter(:beds, beds_range)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Defines the size of the search area in miles. E.g. 2 miles around a location
|
31
|
+
# @param [Fixum] radius in miles
|
32
|
+
# @return [Sales, Rentals]
|
33
|
+
def within(miles)
|
34
|
+
ensure_valid_parameter('radius', miles, lambda {|p| (p.is_a? Float or p.is_a? Fixnum) and p >= 0})
|
35
|
+
@request[:radius] = miles
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
alias_method :radius, :within
|
40
|
+
|
41
|
+
# The field by which the results should be ordered, either :price or :age of listing.
|
42
|
+
# @param [Symbol, String] sorting field
|
43
|
+
# @return [Sales, Rentals]
|
44
|
+
def order_by(field)
|
45
|
+
ensure_valid_parameter('sorting order', field, %w(price age))
|
46
|
+
@request[:order_by] = field.to_s
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Sort order for the listings returned. Either :descending or :ascending
|
51
|
+
# @param [Symbol, String] sorting order
|
52
|
+
# @return [Sales, Rentals]
|
53
|
+
def ordering(order)
|
54
|
+
ensure_valid_parameter('ordering', order, %w(ascending descending))
|
55
|
+
@request[:ordering] = order.to_s
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
# Property type. Either :houses or :flats
|
60
|
+
# @param [Symbol, String] property type
|
61
|
+
# @return [Sales, Rentals]
|
62
|
+
def property_type(type)
|
63
|
+
ensure_valid_parameter('property type', type, %w(houses flats))
|
64
|
+
@request[:property_type] = type.to_s
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Search only for houses
|
69
|
+
# @return [Sales, Rentals]
|
70
|
+
def houses
|
71
|
+
@request[:property_type] = 'houses'
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
# Search only for flats
|
76
|
+
# @return [Sales, Rentals]
|
77
|
+
def flats
|
78
|
+
@request[:property_type] = 'flats'
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
# Keywords to search for within the listing description.
|
83
|
+
# @param [Array, String] keywords
|
84
|
+
# @return [Sales, Rentals]
|
85
|
+
def keywords(keywords)
|
86
|
+
ensure_valid_parameter('keywords', keywords, lambda {|k| k.is_a? Array or k.is_a? String})
|
87
|
+
keywords = keywords.join(' ') if keywords.is_a? Array
|
88
|
+
@request[:keywords] = keywords
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sets the minimum price. Weekly prices in case of rentals
|
93
|
+
# @param [Fixnum] price
|
94
|
+
# @return [Sales, Rentals]
|
95
|
+
def minimum_price(price)
|
96
|
+
set_limiting_value(:minimum, :price, price)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Sets the maximum price. Weekly prices in case of rentals
|
100
|
+
# @param [Fixnum] price
|
101
|
+
# @return [Sales, Rentals]
|
102
|
+
def maximum_price(price)
|
103
|
+
set_limiting_value(:maximum, :price, price)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Sets the minimum number of bedrooms
|
107
|
+
# @param [Fixnum] number of bedrooms
|
108
|
+
# @return [Sales, Rentals]
|
109
|
+
def minimum_beds(beds)
|
110
|
+
set_limiting_value(:minimum, :beds, beds)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Sets the maximum number of bedrooms
|
114
|
+
# @param [Fixnum] number of bedrooms
|
115
|
+
# @return [Sales, Rentals]
|
116
|
+
def maximum_beds(beds)
|
117
|
+
set_limiting_value(:maximum, :beds, beds)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Adds another listing id to the query. Calling this function multiple times will add multiple ids.
|
121
|
+
# Please note that other provided arguments will still be taken into account when filtering listings
|
122
|
+
# @param [Fixnum] listing id
|
123
|
+
# @return [Sales, Rentals]
|
124
|
+
def listing_id(listing_id)
|
125
|
+
ensure_valid_parameter('listing id', listing_id, lambda {|k| k.is_a? Fixnum and k >= 0})
|
126
|
+
@request[:listing_id] ||= []
|
127
|
+
@request[:listing_id] << listing_id
|
128
|
+
self
|
129
|
+
end
|
130
|
+
|
131
|
+
# Iterates over the results. Possible fields are described at http://developer.zoopla.com/docs/read/Property_listings
|
132
|
+
# @yield [Hashie::Mash] a listing with data, e.g. sales.each{|listing| puts listing.price }
|
133
|
+
def each
|
134
|
+
fetched_so_far, number_of_results = 0, 0
|
135
|
+
@request[:page_number] = 1
|
136
|
+
begin
|
137
|
+
number_of_results, listings = fetch_data(@request)
|
138
|
+
fetched_so_far += listings.size
|
139
|
+
@request[:page_number] += 1
|
140
|
+
listings.each do |listing|
|
141
|
+
yield listing
|
182
142
|
end
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
143
|
+
end while fetched_so_far < number_of_results
|
144
|
+
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
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def set_limiting_value(limit, attribute, value)
|
156
|
+
ensure_valid_parameter("#{limit} #{attribute}", value, lambda {|p| p.is_a? Fixnum and p >= 0})
|
157
|
+
@request["#{limit}_#{attribute}".to_sym] = value
|
158
|
+
self
|
190
159
|
end
|
191
160
|
|
192
|
-
|
193
|
-
|
161
|
+
def set_range_parameter(attribute, value)
|
162
|
+
ensure_valid_parameter(attribute.to_s, value, lambda {|pr| pr.is_a? Fixnum or (pr.is_a?(Range) and pr.first <= pr.last)})
|
163
|
+
value = value..value if value.is_a? Fixnum
|
164
|
+
self.send("minimum_#{attribute}", value.first)
|
165
|
+
self.send("maximum_#{attribute}", value.last)
|
166
|
+
self
|
167
|
+
end
|
168
|
+
|
169
|
+
def ensure_valid_parameter(parameter, value, valid_options)
|
170
|
+
raise "#{parameter} not specified" unless value
|
171
|
+
raise "Unknown #{parameter}: #{value}" if valid_options.is_a? Array and !valid_options.include?(value.to_s)
|
172
|
+
raise "Invalid #{parameter}: #{value}" if valid_options.is_a? Proc and !valid_options.call(value)
|
173
|
+
end
|
174
|
+
|
175
|
+
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]
|
183
|
+
end
|
184
|
+
|
185
|
+
def api_call
|
186
|
+
'property_listings'
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
194
191
|
end
|
@@ -1,40 +1,36 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
class Zoopla
|
2
|
+
|
3
|
+
# Searches for rental listings
|
4
|
+
class Rentals < API
|
5
|
+
|
6
|
+
include Zoopla::Listing
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# Include property listings that are already rented in the results
|
16
|
-
# @return [Rentals]
|
17
|
-
def include_rented
|
18
|
-
@request[:include_rented] = '1'
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
|
-
# Specify whether or not the apartment is "furnished", "unfurnished" or "part-furnished".
|
23
|
-
# @return [Rentals]
|
24
|
-
def furnished(value)
|
25
|
-
ensure_valid_parameter('furnished', value, %w(furnished unfurnished part-furnished))
|
26
|
-
@request[:furnished] = value.to_s
|
27
|
-
self
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def default_parameters
|
33
|
-
{:listing_status => 'rent'}
|
34
|
-
end
|
35
|
-
|
8
|
+
def initialize(*args)
|
9
|
+
super(*args)
|
10
|
+
reset!
|
11
|
+
end
|
12
|
+
|
13
|
+
# Include property listings that are already rented in the results
|
14
|
+
# @return [Rentals]
|
15
|
+
def include_rented
|
16
|
+
@request[:include_rented] = '1'
|
17
|
+
self
|
36
18
|
end
|
37
19
|
|
20
|
+
# Specify whether or not the apartment is "furnished", "unfurnished" or "part-furnished".
|
21
|
+
# @return [Rentals]
|
22
|
+
def furnished(value)
|
23
|
+
ensure_valid_parameter('furnished', value, %w(furnished unfurnished part-furnished))
|
24
|
+
@request[:furnished] = value.to_s
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def default_parameters
|
31
|
+
{:listing_status => 'rent'}
|
32
|
+
end
|
33
|
+
|
38
34
|
end
|
39
35
|
|
40
36
|
end
|
@@ -1,32 +1,29 @@
|
|
1
|
-
|
1
|
+
class Zoopla
|
2
2
|
|
3
|
-
|
3
|
+
# Searches for sales listings
|
4
|
+
class Sales < API
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def default_parameters
|
25
|
-
{:listing_status => 'sale'}
|
26
|
-
end
|
27
|
-
|
6
|
+
include Zoopla::Listing
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
super(*args)
|
10
|
+
reset!
|
11
|
+
end
|
12
|
+
|
13
|
+
# Whether to include property listings that are already sold in the results
|
14
|
+
# @return [Sales]
|
15
|
+
def include_sold
|
16
|
+
@request[:include_sold] = '1'
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def default_parameters
|
23
|
+
{:listing_status => 'sale'}
|
28
24
|
end
|
29
25
|
|
30
26
|
end
|
31
27
|
|
28
|
+
|
32
29
|
end
|
data/lib/zoopla/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
{"result_count":null,"country":"England","area_name":null,"longitude":-0.137052,"listing":[],"street":null,"town":"","latitude":51.537402,"county":"London","postcode":"NW1 0DU","bounding_box":{"latitude_min":"51.537402","longitude_min":"-0.137052","longitude_max":"-0.137052","latitude_max":"51.537402"}}
|
data/test/test_api.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestAPI < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@rentals = Zoopla.new('my_api_key').rentals
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_no_results_returned
|
10
|
+
number_of_results, reply = @rentals.send(:preprocess, api_reply('empty'))
|
11
|
+
assert_equal 0, number_of_results
|
12
|
+
assert_equal [], reply
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_bad_request
|
16
|
+
Curl::Easy.any_instance.stubs(:perform)
|
17
|
+
Curl::Easy.any_instance.stubs(:response_code).returns(400)
|
18
|
+
assert_raises Zoopla::BadRequestError do
|
19
|
+
@rentals.each{}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_unauthorised_request
|
24
|
+
Curl::Easy.any_instance.stubs(:perform)
|
25
|
+
Curl::Easy.any_instance.stubs(:response_code).returns(401)
|
26
|
+
assert_raises Zoopla::UnauthorizedRequestError do
|
27
|
+
@rentals.each{}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_wrong_api_key
|
32
|
+
Curl::Easy.any_instance.stubs(:perform)
|
33
|
+
Curl::Easy.any_instance.stubs(:response_code).returns(403)
|
34
|
+
assert_raises Zoopla::ForbiddenError do
|
35
|
+
@rentals.each{}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_not_found
|
40
|
+
Curl::Easy.any_instance.stubs(:perform)
|
41
|
+
Curl::Easy.any_instance.stubs(:response_code).returns(404)
|
42
|
+
assert_raises Zoopla::NotFoundError do
|
43
|
+
@rentals.each{}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_method_not_allowed
|
48
|
+
Curl::Easy.any_instance.stubs(:perform)
|
49
|
+
Curl::Easy.any_instance.stubs(:response_code).returns(405)
|
50
|
+
assert_raises Zoopla::MethodNotAllowedError do
|
51
|
+
@rentals.each{}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_internal_server_error
|
56
|
+
Curl::Easy.any_instance.stubs(:perform)
|
57
|
+
Curl::Easy.any_instance.stubs(:response_code).returns(500)
|
58
|
+
assert_raises Zoopla::InternalServerError do
|
59
|
+
@rentals.each{}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -3,8 +3,9 @@ require 'helper'
|
|
3
3
|
class TestZooplaListings < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def setup
|
6
|
-
|
7
|
-
@
|
6
|
+
zoopla = Zoopla.new('my_api_key')
|
7
|
+
@rentals = zoopla.rentals
|
8
|
+
@sales = zoopla.sales
|
8
9
|
end
|
9
10
|
|
10
11
|
def test_reset_for_sales
|
@@ -215,8 +216,8 @@ class TestZooplaListings < Test::Unit::TestCase
|
|
215
216
|
def test_requesting_multiple_results_pages_transparently
|
216
217
|
mock = mock();
|
217
218
|
mock.expects(:process_listing).times(12);
|
218
|
-
page1 = @rentals.send :preprocess,
|
219
|
-
page2 = @rentals.send :preprocess,
|
219
|
+
page1 = @rentals.send :preprocess, api_reply('big_request_page1')
|
220
|
+
page2 = @rentals.send :preprocess, api_reply('big_request_page2')
|
220
221
|
@rentals.stubs(:fetch_data).returns(page1, page2)
|
221
222
|
@rentals.in({:postcode => 'E1W 3TJ'}).within(0.1).price(300..400).each {|listing|
|
222
223
|
mock.process_listing
|
@@ -224,7 +225,7 @@ class TestZooplaListings < Test::Unit::TestCase
|
|
224
225
|
end
|
225
226
|
|
226
227
|
def test_deep_parsing_the_reply
|
227
|
-
_, reply = @rentals.send(:preprocess,
|
228
|
+
_, reply = @rentals.send(:preprocess, api_reply('postcode'))
|
228
229
|
listing = reply.first
|
229
230
|
assert_equal 11695072, listing.listing_id
|
230
231
|
assert_equal 'rent', listing.listing_status
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: zoopla
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
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-
|
13
|
+
date: 2011-03-04 00:00:00 +00:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -82,8 +82,10 @@ files:
|
|
82
82
|
- lib/zoopla/version.rb
|
83
83
|
- test/api_replies/big_request_page1.js
|
84
84
|
- test/api_replies/big_request_page2.js
|
85
|
+
- test/api_replies/empty.js
|
85
86
|
- test/api_replies/postcode.js
|
86
87
|
- test/helper.rb
|
88
|
+
- test/test_api.rb
|
87
89
|
- test/test_zoopla_listings.rb
|
88
90
|
- zoopla.gemspec
|
89
91
|
has_rdoc: true
|
@@ -117,6 +119,8 @@ summary: Access zoopla.co.uk API from ruby scripts
|
|
117
119
|
test_files:
|
118
120
|
- test/api_replies/big_request_page1.js
|
119
121
|
- test/api_replies/big_request_page2.js
|
122
|
+
- test/api_replies/empty.js
|
120
123
|
- test/api_replies/postcode.js
|
121
124
|
- test/helper.rb
|
125
|
+
- test/test_api.rb
|
122
126
|
- test/test_zoopla_listings.rb
|