zoopla 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +31 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +53 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/zoopla.rb +12 -0
- data/lib/zoopla/api.rb +52 -0
- data/lib/zoopla/listings.rb +3 -0
- data/lib/zoopla/listings/listing.rb +194 -0
- data/lib/zoopla/listings/rentals.rb +40 -0
- data/lib/zoopla/listings/sales.rb +32 -0
- data/lib/zoopla/version.rb +11 -0
- data/test/api_replies/big_request_page1.js +1 -0
- data/test/api_replies/big_request_page2.js +1 -0
- data/test/api_replies/postcode.js +1 -0
- data/test/helper.rb +24 -0
- data/test/test_zoopla_listings.rb +274 -0
- data/zoopla.gemspec +83 -0
- metadata +166 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
zoopla (0.1.0)
|
5
|
+
curb
|
6
|
+
hashie (>= 1.0.0)
|
7
|
+
hashie (>= 1.0.0)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
curb (0.7.12)
|
13
|
+
git (1.2.5)
|
14
|
+
hashie (1.0.0)
|
15
|
+
jeweler (1.5.2)
|
16
|
+
bundler (~> 1.0.0)
|
17
|
+
git (>= 1.2.5)
|
18
|
+
rake
|
19
|
+
mocha (0.9.12)
|
20
|
+
rake (0.8.7)
|
21
|
+
rcov (0.9.9)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
bundler (~> 1.0.0)
|
28
|
+
jeweler (~> 1.5.2)
|
29
|
+
mocha (>= 0.9.12)
|
30
|
+
rcov
|
31
|
+
zoopla!
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Evgeny Shadchnev
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Zoopla API Wrapper
|
2
|
+
|
3
|
+
Use this gem to access real estate data using zoopla.co.uk API from ruby code:
|
4
|
+
|
5
|
+
* property listings with addresses, prices, agent details etc
|
6
|
+
* more to come
|
7
|
+
|
8
|
+
## Documentation
|
9
|
+
The gem documentation can be found on [Rdoc.info](http://rdoc.info/github/shadchnev/zoopla/master/frames)
|
10
|
+
|
11
|
+
The API documentation can be found on the [Zoopla Website](http://developer.zoopla.com/docs)
|
12
|
+
|
13
|
+
## Usage examples
|
14
|
+
|
15
|
+
### Property listings
|
16
|
+
|
17
|
+
First, initialise the object with the API key [you got from Zoopla](http://developer.zoopla.com/member/register/)
|
18
|
+
|
19
|
+
$ sales = Zoopla::Listings::Sales.new('my_api_key')
|
20
|
+
|
21
|
+
Then chain the parameter calls and provide a block to process the listings
|
22
|
+
|
23
|
+
$ sales.houses.in({:postcode => 'NW1 0DU'}).within(0.5).each{|l| puts "#{l.num_bedrooms}-bedrooms house for #{l.price} at #{l.displayable_address}"}
|
24
|
+
|
25
|
+
This will produce
|
26
|
+
|
27
|
+
4-bedrooms house for 1525000 at Arlington Road, London
|
28
|
+
2-bedrooms house for 1250000 at Rochester Mews, London
|
29
|
+
4-bedrooms house for 999000 at Bonny Street, Camden Town, London
|
30
|
+
...
|
31
|
+
|
32
|
+
To search for rentals, do a similar query:
|
33
|
+
|
34
|
+
$ rentals = Zoopla::Listings::Rentals.new('my_api_key')
|
35
|
+
$ rentals.flats.in({:postcode => 'NW1 0DU'}).within(0.5).price(300..350).each{|l| puts "#{l.num_bedrooms}-bedrooms flat for #{l.price}/week at #{l.displayable_address}"}
|
36
|
+
|
37
|
+
The input and output parameters for property listings are described in the [Zoopla documentation](http://developer.zoopla.com/docs/read/Property_listings)
|
38
|
+
|
39
|
+
|
40
|
+
## Contributing to zoopla
|
41
|
+
|
42
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
43
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
44
|
+
* Fork the project
|
45
|
+
* Start a feature/bugfix branch
|
46
|
+
* Commit and push until you are happy with your contribution
|
47
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
48
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
49
|
+
|
50
|
+
## Copyright
|
51
|
+
|
52
|
+
Copyright (c) 2011 Evgeny Shadchnev. See LICENSE.txt for further details.
|
53
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require './lib/zoopla'
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
require 'rake'
|
12
|
+
|
13
|
+
require 'jeweler'
|
14
|
+
Jeweler::Tasks.new do |gem|
|
15
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
16
|
+
gem.name = "zoopla"
|
17
|
+
gem.homepage = "http://github.com/shadchnev/zoopla"
|
18
|
+
gem.license = "MIT"
|
19
|
+
gem.summary = %Q{Access zoopla.co.uk API from ruby scripts}
|
20
|
+
gem.description = %Q{Access zoopla.co.uk API from ruby scripts. Fetch sales and rental properties for the UK}
|
21
|
+
gem.email = "evgeny.shadchnev@gmail.com"
|
22
|
+
gem.authors = ["Evgeny Shadchnev"]
|
23
|
+
gem.version = Zoopla::Version::STRING
|
24
|
+
gem.add_runtime_dependency 'hashie', '>= 1.0.0'
|
25
|
+
gem.add_development_dependency 'mocha', '>= 0.9.12'
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
Rake::TestTask.new(:test) do |test|
|
31
|
+
test.libs << 'lib' << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'rcov/rcovtask'
|
37
|
+
Rcov::RcovTask.new do |test|
|
38
|
+
test.libs << 'test'
|
39
|
+
test.pattern = 'test/**/test_*.rb'
|
40
|
+
test.verbose = true
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = Zoopla::Version::STRING
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "zoopla #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/zoopla.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'curl'
|
2
|
+
require 'json'
|
3
|
+
require 'cgi'
|
4
|
+
require 'hashie'
|
5
|
+
|
6
|
+
require File.expand_path('../zoopla/version', __FILE__)
|
7
|
+
require File.expand_path('../zoopla/api', __FILE__)
|
8
|
+
require File.expand_path('../zoopla/listings', __FILE__)
|
9
|
+
|
10
|
+
module Zoopla
|
11
|
+
|
12
|
+
end
|
data/lib/zoopla/api.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Zoopla
|
2
|
+
|
3
|
+
class API # abstract
|
4
|
+
|
5
|
+
def initialize(api_key)
|
6
|
+
@key = api_key
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def fetch_data(params)
|
12
|
+
preprocess call(url(params))
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(url)
|
16
|
+
curl = Curl::Easy.new(url)
|
17
|
+
curl.perform
|
18
|
+
JSON.parse curl.body_str
|
19
|
+
end
|
20
|
+
|
21
|
+
def url(params)
|
22
|
+
params.inject("http://api.zoopla.co.uk/api/v1/#{api_call}.js?api_key=#{@key}") do |memo, item|
|
23
|
+
memo += "&#{item.first}=#{CGI::escape item.last.to_s}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def tryParsingInteger(field, value)
|
28
|
+
(value.to_i rescue 0) if %w(price listing_id num_bathrooms num_bedrooms num_floors num_recepts).include? field
|
29
|
+
end
|
30
|
+
|
31
|
+
def tryParsingDate(field, value)
|
32
|
+
(Date.parse(value) rescue value) if field == 'date'
|
33
|
+
end
|
34
|
+
|
35
|
+
def tryParsingHash(field, value)
|
36
|
+
parse_values_if_possible(value) if value.is_a? Hash
|
37
|
+
end
|
38
|
+
|
39
|
+
def tryParsingArray(field, value)
|
40
|
+
value.inject([]) {|memo, item| memo << parse_values_if_possible(item) } if value.is_a? Array
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_values_if_possible(reply)
|
44
|
+
return reply if reply.is_a? String
|
45
|
+
reply.each_pair do |field, value|
|
46
|
+
reply[field] = tryParsingHash(field, value) || tryParsingArray(field, value) || tryParsingInteger(field, value) || tryParsingDate(field, value) || value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
module Zoopla
|
2
|
+
|
3
|
+
module Listings
|
4
|
+
|
5
|
+
# Common methods for Sales and Rentals classes
|
6
|
+
module Listing
|
7
|
+
|
8
|
+
# Defines the search area. All possible params are described at http://developer.zoopla.com/docs/
|
9
|
+
# @param [Hash] Location hash
|
10
|
+
# @return [Sales, Rentals]
|
11
|
+
def in(location)
|
12
|
+
@request.merge! location
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
# Sets the price range
|
17
|
+
# @param [Range] price range (weekly in case of rentals), e.g. 200..300
|
18
|
+
# @return [Sales, Rentals]
|
19
|
+
def price(price_range)
|
20
|
+
set_range_parameter(:price, price_range)
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method :for, :price
|
24
|
+
|
25
|
+
# Sets the number of bedrooms range
|
26
|
+
# @param [Range] bedrooms range, e.g. 2..3
|
27
|
+
# @return [Sales, Rentals]
|
28
|
+
def beds(beds_range)
|
29
|
+
set_range_parameter(:beds, beds_range)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Defines the size of the search area in miles. E.g. 2 miles around a location
|
33
|
+
# @param [Fixum] radius in miles
|
34
|
+
# @return [Sales, Rentals]
|
35
|
+
def within(miles)
|
36
|
+
ensure_valid_parameter('radius', miles, lambda {|p| (p.is_a? Float or p.is_a? Fixnum) and p >= 0})
|
37
|
+
@request[:radius] = miles
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
alias_method :radius, :within
|
42
|
+
|
43
|
+
# The field by which the results should be ordered, either :price or :age of listing.
|
44
|
+
# @param [Symbol, String] sorting field
|
45
|
+
# @return [Sales, Rentals]
|
46
|
+
def order_by(field)
|
47
|
+
ensure_valid_parameter('sorting order', field, %w(price age))
|
48
|
+
@request[:order_by] = field.to_s
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
# Sort order for the listings returned. Either :descending or :ascending
|
53
|
+
# @param [Symbol, String] sorting order
|
54
|
+
# @return [Sales, Rentals]
|
55
|
+
def ordering(order)
|
56
|
+
ensure_valid_parameter('ordering', order, %w(ascending descending))
|
57
|
+
@request[:ordering] = order.to_s
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
# Property type. Either :houses or :flats
|
62
|
+
# @param [Symbol, String] property type
|
63
|
+
# @return [Sales, Rentals]
|
64
|
+
def property_type(type)
|
65
|
+
ensure_valid_parameter('property type', type, %w(houses flats))
|
66
|
+
@request[:property_type] = type.to_s
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
# Search only for houses
|
71
|
+
# @return [Sales, Rentals]
|
72
|
+
def houses
|
73
|
+
@request[:property_type] = 'houses'
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
# Search only for flats
|
78
|
+
# @return [Sales, Rentals]
|
79
|
+
def flats
|
80
|
+
@request[:property_type] = 'flats'
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
# Keywords to search for within the listing description.
|
85
|
+
# @param [Array, String] keywords
|
86
|
+
# @return [Sales, Rentals]
|
87
|
+
def keywords(keywords)
|
88
|
+
ensure_valid_parameter('keywords', keywords, lambda {|k| k.is_a? Array or k.is_a? String})
|
89
|
+
keywords = keywords.join(' ') if keywords.is_a? Array
|
90
|
+
@request[:keywords] = keywords
|
91
|
+
self
|
92
|
+
end
|
93
|
+
|
94
|
+
# Sets the minimum price. Weekly prices in case of rentals
|
95
|
+
# @param [Fixnum] price
|
96
|
+
# @return [Sales, Rentals]
|
97
|
+
def minimum_price(price)
|
98
|
+
set_limiting_value(:minimum, :price, price)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Sets the maximum price. Weekly prices in case of rentals
|
102
|
+
# @param [Fixnum] price
|
103
|
+
# @return [Sales, Rentals]
|
104
|
+
def maximum_price(price)
|
105
|
+
set_limiting_value(:maximum, :price, price)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Sets the minimum number of bedrooms
|
109
|
+
# @param [Fixnum] number of bedrooms
|
110
|
+
# @return [Sales, Rentals]
|
111
|
+
def minimum_beds(beds)
|
112
|
+
set_limiting_value(:minimum, :beds, beds)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Sets the maximum number of bedrooms
|
116
|
+
# @param [Fixnum] number of bedrooms
|
117
|
+
# @return [Sales, Rentals]
|
118
|
+
def maximum_beds(beds)
|
119
|
+
set_limiting_value(:maximum, :beds, beds)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Adds another listing id to the query. Calling this function multiple times will add multiple ids.
|
123
|
+
# Please note that other provided arguments will still be taken into account when filtering listings
|
124
|
+
# @param [Fixnum] listing id
|
125
|
+
# @return [Sales, Rentals]
|
126
|
+
def listing_id(listing_id)
|
127
|
+
ensure_valid_parameter('listing id', listing_id, lambda {|k| k.is_a? Fixnum and k >= 0})
|
128
|
+
@request[:listing_id] ||= []
|
129
|
+
@request[:listing_id] << listing_id
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
133
|
+
# Iterates over the results. Possible fields are described at http://developer.zoopla.com/docs/read/Property_listings
|
134
|
+
# @yield [Hashie::Mash] a listing with data, e.g. sales.each{|listing| puts listing.price }
|
135
|
+
def each
|
136
|
+
fetched_so_far, number_of_results = 0, 0
|
137
|
+
@request[:page_number] = 1
|
138
|
+
begin
|
139
|
+
number_of_results, listings = fetch_data(@request)
|
140
|
+
fetched_so_far += listings.size
|
141
|
+
@request[:page_number] += 1
|
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)
|
182
|
+
end
|
183
|
+
[number_of_results, listings]
|
184
|
+
end
|
185
|
+
|
186
|
+
def api_call
|
187
|
+
'property_listings'
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Zoopla
|
2
|
+
|
3
|
+
module Listings
|
4
|
+
|
5
|
+
# Searches for rental listings
|
6
|
+
class Rentals < API
|
7
|
+
|
8
|
+
include Zoopla::Listings::Listing
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
super(*args)
|
12
|
+
reset!
|
13
|
+
end
|
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
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Zoopla
|
2
|
+
|
3
|
+
module Listings
|
4
|
+
|
5
|
+
# Searches for sales listings
|
6
|
+
class Sales < API
|
7
|
+
|
8
|
+
include Zoopla::Listings::Listing
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
super(*args)
|
12
|
+
reset!
|
13
|
+
end
|
14
|
+
|
15
|
+
# Whether to include property listings that are already sold in the results
|
16
|
+
# @return [Sales]
|
17
|
+
def include_sold
|
18
|
+
@request[:include_sold] = '1'
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def default_parameters
|
25
|
+
{:listing_status => 'sale'}
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"result_count":12,"country":"England","area_name":null,"longitude":-0.054738,"listing":[{"image_caption":"","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"DAA Residential","latitude":51.50675,"num_recepts":"0","agent_address":"61 Garnet Street Wapping","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Riverside Mansions, Milk Yard, Wapping E1W ","floor_plan":[],"street_name":"","num_bathrooms":"0","thumbnail_url":"http://images.zoopla.co.uk/c92297fba9dd2d7c2c7e1b326054ad4c1da3e176_80_60.jpg","description":"Stunning two bedrooms apartment situated in the heart of Wapping. The property benefits from wooden flooring, modern fitted kitchen, modern fitted bathroom and a balcony. This spacious apartment is furnished to a good standard and has an allocated parking space. Located just minutes walk from Wapping overground station and all local amenities. Viewing is highly advised.","post_town":"London","price_change":[{"date":"2011-02-18 18:12:20","price":"385"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/14103688","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(39922).jpeg","outcode":"E1W","agent_phone":"020 3318 6038","image_url":"http://images.zoopla.co.uk/c92297fba9dd2d7c2c7e1b326054ad4c1da3e176_354_255.jpg","price":"385","county":"London","listing_id":"14103688"},{"image_caption":"","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"DAA Residential","latitude":51.50675,"num_recepts":"0","agent_address":"61 Garnet Street Wapping","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Riverside Mansions, Milk Yard E1W ","floor_plan":[],"street_name":"","thumbnail_url":"http://images.zoopla.co.uk/739ed95a0c622ebf405dd2d60156f2d83989f301_80_60.jpg","num_bathrooms":"0","description":"Fabulous 2 bedroom split level apartment located in the heart of Wapping. The property benefits of wooden floor, modern fitted kitchen, modern fitted bathroom and a balcony. This spacious apartment is furnished to a very high standard. The property is located 5 minutes walking from Wapping station and all amenities. Viewing is highly advised.","post_town":"London","price_change":[{"date":"2010-06-03 07:46:51","price":"380"},{"date":"2010-07-03 15:55:21","price":"370"},{"date":"2011-01-29 10:26:47","price":"365"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/11143019","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(39922).jpeg","outcode":"E1W","agent_phone":"020 3318 6038","image_url":"http://images.zoopla.co.uk/739ed95a0c622ebf405dd2d60156f2d83989f301_354_255.jpg","price":"365","county":"London","listing_id":"11143019"},{"image_caption":"","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"Ludlowthompson.com - City / Docklands","latitude":51.50675,"num_recepts":"0","agent_address":"3 - 5 Dock Street","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Milk Yard, London E1W","floor_plan":[],"street_name":"Milk Yard","thumbnail_url":"http://images.zoopla.co.uk/25b8e2939d105d9c52e3bcf4bb29d729d0d9da94_80_60.jpg","num_bathrooms":"0","description":"Are delighted to present this stunning 2 bedroom in the sought after Riverside Mansions in Wapping. This flat is very tasteful and is of a high standard. Close to all transport and amenities and within a minutes walk to the river, this property is sure to go soon. This property is also offered with an allocated parkign space and the development has a residents gym. Call the team on to arrange viewingsbedroom 2nd aspect","post_town":"London","price_change":[{"date":"2011-02-23 22:07:34","price":"360"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/14131677","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(48990).gif","outcode":"E1W","agent_phone":"020 3318 8254","image_url":"http://images.zoopla.co.uk/25b8e2939d105d9c52e3bcf4bb29d729d0d9da94_354_255.jpg","price":"360","county":"London","listing_id":"14131677"},{"image_caption":"","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"Ea2","latitude":51.50675,"num_recepts":"0","agent_address":"Heritage Court 8-10 Sampson Street","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Riverside Mansions Milk Yard, Wapping, Wapping","floor_plan":[],"street_name":"","thumbnail_url":"http://images.zoopla.co.uk/5eec9be8a3a2fc8e12759f1c9bbe0123d31e6521_80_60.jpg","num_bathrooms":"0","description":"Re-furbished 2 double bedroom duplex apartment within this secure day porterage development.Benefiting from a reception, fitted kitchen/ diner, first floor bathroom and timber flooring.Use of communal gymnasium. Within easy access to the City or Docklands.\n\n \n\n","post_town":"London","price_change":[{"date":"2010-11-29 20:03:20","price":"350"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/13660947","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(27804).gif","outcode":"E1W","agent_phone":"020 3318 7006","image_url":"http://images.zoopla.co.uk/5eec9be8a3a2fc8e12759f1c9bbe0123d31e6521_354_255.jpg","price":"350","county":"London","listing_id":"13660947"},{"image_caption":"Picture No.01","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"Atkinson Mcleod","latitude":51.50675,"num_recepts":"0","agent_address":"135 Leman Street, Aldgate","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Riverside Mansions, Milk Yard, London E1W","floor_plan":["http://content.zoopla.co.uk/a4818c686f0ee9922cab90019ca2be5d7c6e1595.jpg"],"street_name":"Milk Yard London","thumbnail_url":"http://images.zoopla.co.uk/3ba654b063c87144e75036c5d75bf289a2a3f072_80_60.jpg","num_bathrooms":"0","description":"Bright and spacious two bedroom split level apartment located in an attractive Wapping development with a gym. This property will suit a couple or sharers!\n\nOur Ref: rpl/iupload/CTY110751","post_town":"London","price_change":[{"date":"2011-02-01 19:01:08","price":"350"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/13982466","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(26302).gif","outcode":"E1W","agent_phone":"020 3318 9246","image_url":"http://images.zoopla.co.uk/3ba654b063c87144e75036c5d75bf289a2a3f072_354_255.jpg","price":"350","county":"London","listing_id":"13982466"},{"image_caption":"living room","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"Oliver Franklin","latitude":51.50675,"num_recepts":"0","agent_address":"452 Roman Road","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Milk Yard, London","floor_plan":[],"street_name":"Riverside Mansions","thumbnail_url":"http://images.zoopla.co.uk/c3ffd074745bef6bd0d878affd5bb37f7d5945e4_80_60.jpg","num_bathrooms":"1","description":"Oliver Franklin are pleased to offer you this 2 double bedroom apartment in Wapping. Located on the second floor (with lift) in a private development with a well looked after communal garden.\n\n* Two Double Bedrooms With Double Beds And Double Wardrobes\n\n* Spacious Living Room With Real Wood Flooring\n\n* Separate Kitchen And Dining Room With All Appliances\n\n* Ceramic Tiled Luxury Bathroom With Shower\n\n* Only A Few Minutes Walk To The Station\n\n* Close To Shops\n\n","post_town":"London","price_change":[{"date":"2010-09-01 10:10:02","price":"350"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/11999097","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(42235).jpeg","outcode":"E1W","agent_phone":"020 3463 0153","image_url":"http://images.zoopla.co.uk/c3ffd074745bef6bd0d878affd5bb37f7d5945e4_354_255.jpg","price":"350","county":"London","listing_id":"11999097"},{"image_caption":"","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"Future Pad London","latitude":51.50675,"num_recepts":"0","agent_address":"70 Commercial Street","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Milk Yard, London","floor_plan":[],"street_name":"","thumbnail_url":"http://images.zoopla.co.uk/f1171c10b389ca6825abc249cad52ee92694bf54_80_60.jpg","num_bathrooms":"0","description":"Light and airy, newly painted, spacious two double bedroomed, split level apartment with stripped wooden flooring, new beds and bedding, situated in private residential development in the heart of Wapping, said residential development having gym and porter on site.","post_town":"London","price_change":[{"date":"2010-04-07 18:12:06","price":"350"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/4311103","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(45169).jpeg","outcode":"E1W","agent_phone":"020 3318 6552","image_url":"http://images.zoopla.co.uk/f1171c10b389ca6825abc249cad52ee92694bf54_354_255.jpg","price":"350","county":"London","listing_id":"4311103"},{"image_caption":"Picture No.02","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"Atkinson Mcleod","latitude":51.50675,"num_recepts":"0","agent_address":"135 Leman Street, Aldgate","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Riverside Mansions, Milk Yard, Wapping, London E1W","floor_plan":["http://content.zoopla.co.uk/e285e706908f968037fe9d038fdf7850da01fb9d.jpg"],"street_name":"Milk Yard Wapping London","thumbnail_url":"http://images.zoopla.co.uk/727bd23897b078a29af28b96790f22c879cb6b17_80_60.jpg","num_bathrooms":"0","description":"A bright and spacious two bed duplex apartment, set within a popular development. 5 minutes walk to the tube & excellent bus links to the city and Liverpool street. Available now call today to be the first to view this fantastic two bed. Our Ref: rpl/iupload/CTY110750","post_town":"London","price_change":[{"date":"2011-02-01 19:01:08","price":"345"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/13982465","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(26302).gif","outcode":"E1W","agent_phone":"020 3318 9246","image_url":"http://images.zoopla.co.uk/727bd23897b078a29af28b96790f22c879cb6b17_354_255.jpg","price":"345","county":"London","listing_id":"13982465"},{"image_caption":"","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"Sector One Properties","latitude":51.50675,"num_recepts":"0","agent_address":"Berkeley Business Centre Crown House","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Milk Yard, London","floor_plan":[],"street_name":"Milk Yard","thumbnail_url":"http://images.zoopla.co.uk/6f4c5176c85cf210222a5ed2f013f4b799280364_80_60.jpg","num_bathrooms":"0","description":"We are pleased to offer for rent this 2 bedroom duplex apartment in the popular Riverside Mansions, Wapping. The property comprises of 2 double bedrooms, bathroom, reception, balcony and a separate kitchen. Secure parking and gym facility. Minutes from Wapping & Shadwell Station with excellent transport links. Call now to arrange a viewing and avoid disappointment.\n\n","post_town":"London","price_change":[{"date":"2011-02-24 12:00:02","price":"340"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/14137087","agent_logo":null,"outcode":"E1W","agent_phone":"020 3318 8407","image_url":"http://images.zoopla.co.uk/6f4c5176c85cf210222a5ed2f013f4b799280364_354_255.jpg","price":"340","county":"London","listing_id":"14137087"},{"image_caption":"","num_floors":"0","listing_status":"rent","num_bedrooms":"1","agent_name":"Cluttons","latitude":51.50549,"num_recepts":"1","agent_address":"3 Wapping High Street Wapping","property_type":"Flat","country":null,"longitude":-0.054776,"displayable_address":"New Crane Place, London","floor_plan":[],"street_name":"New Crane Wharf, New Crane Place","thumbnail_url":"http://images.zoopla.co.uk/f70ddb4b505d2b723734c36e742de11d43f18846_80_60.jpg","num_bathrooms":"1","description":"A delightful one bedroom apartment situated on the 3rd floor of this popular riverside warehouse conversion. The accommodation comprises reception room, open-plan fitted kitchen, double bedroom, bathroom. New Crane Wharf further benefits from secure parking and 24 hour concierge and is ideally located for access to the City and Canary Wharf via the local bus routes D3 and 100 and is just moments from Wapping Overground station.\n","post_town":"London","price_change":[{"date":"2011-01-21 18:45:33","price":"325"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/13911134","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(37477).data","outcode":"E1W","agent_phone":"020 3318 6830","image_url":"http://images.zoopla.co.uk/f70ddb4b505d2b723734c36e742de11d43f18846_354_255.jpg","price":"325","county":"London","listing_id":"13911134"}],"street":null,"radius":"0.1","town":"","latitude":51.50639,"county":"London","postcode":"E1W 3TJ","bounding_box":{"latitude_min":51.5049442933003,"longitude_min":-0.0561837066996885,"longitude_max":-0.0532922933003115,"latitude_max":51.5078357066997}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"result_count":12,"country":"England","area_name":null,"longitude":-0.054738,"listing":[{"image_caption":"","num_floors":"0","listing_status":"rent","num_bedrooms":"2","agent_name":"City Hive","latitude":51.50675,"agent_address":"149A Cannon Street Road","num_recepts":"1","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Milk Yard, London","floor_plan":[],"street_name":"","num_bathrooms":"1","thumbnail_url":"http://images.zoopla.co.uk/7232217d10ec6af5e4223626cb2aa6109901d5a9_80_60.jpg","description":"City Hive are pleased to introduce this fantastic 2 bedroom Flat within 5 minutes of Wapping and Tower Hill station. Offered fully furnished, the property comprises of a bright spacious living area, Fitted Kitchen that benefits from fridge/freezer. There is 2 good sized double room, wooded flooring, and wardrobes and bathroom. Easy walking distance to the world famous Tower Bridge and the London riverside. The location has a great bars and restaurants to offer. Excellent transport link to move around London quickly with numerous tube and bus routes and very close to local amenities. Easy travel to Canary Wharf and London Bridge. Tube lines:\n\nLondon Overground\n\nFrom Tower Hill (Dlr, District line, Hammersmith & City line)\n\nNational Rail\n\nLondon Fenchurch Street\n\nBus routes:\n\nBus 100, Bus D3 and from Tower Hill Bus 15, Bus 25, Bus 42, Bus 78, Bus RV1\n\nUniversities nearby:\n\nThe London Metropolitan University\n\nCity Of London College\n\nBusiness School Of London\n\nKings College\n\nImperial College\n\nLondon South Bank University\n\nQueen Mary College\n\nUniversity College London (Ucl)\n\nUniversity Of Greenwich\n\nWapping E1W\n\nShadwell E1\n\nTower Hill E1","post_town":"London","price_change":[{"date":"2011-01-10 19:05:03","price":"320"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/13835518","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(49600).jpeg","outcode":"E1W","agent_phone":"020 8166 1405","image_url":"http://images.zoopla.co.uk/7232217d10ec6af5e4223626cb2aa6109901d5a9_354_255.jpg","price":"320","county":"London","listing_id":"13835518"},{"image_caption":"","num_floors":"1","listing_status":"rent","num_bedrooms":"2","agent_name":"Sector One Properties","latitude":51.50675,"num_recepts":"1","agent_address":"Berkeley Business Centre Crown House","property_type":"Flat","country":null,"longitude":-0.0547228,"displayable_address":"Milk Yard, London E1W","floor_plan":[],"street_name":"","thumbnail_url":"http://images.zoopla.co.uk/12908108b6041d2399a6dfaa0af928961ab78670_80_60.jpg","num_bathrooms":"1","description":"We are delighted to offer for rent this lovely 2 bedroom flat in Wapping. The property boasts 2 bedrooms, fitted kitchen, large bathroom with easy access to Docklands and The City. Call now to avoid disappointment!","post_town":"London","price_change":[{"date":"2011-01-10 11:25:02","price":"319"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/13833828","agent_logo":null,"outcode":"E1W","agent_phone":"020 3318 8407","image_url":"http://images.zoopla.co.uk/12908108b6041d2399a6dfaa0af928961ab78670_354_255.jpg","price":"319","county":"London","listing_id":"13833828"}],"street":null,"radius":"0.1","town":"","latitude":51.50639,"county":"London","postcode":"E1W 3TJ","bounding_box":{"latitude_min":51.5049442933003,"longitude_min":-0.0561837066996885,"longitude_max":-0.0532922933003115,"latitude_max":51.5078357066997}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"result_count":1,"country":"England","area_name":null,"longitude":-0.054738,"listing":[{"image_caption":"Picture No.05","num_floors":"0","listing_status":"rent","num_bedrooms":"1","agent_name":"Atkinson Mcleod","latitude":51.50639,"num_recepts":"0","agent_address":"135 Leman Street, Aldgate","property_type":"Flat","country":null,"longitude":-0.054738,"displayable_address":"Prospect Place, Wapping Wall, Wapping, London E1W","floor_plan":["http://content.zoopla.co.uk/18d7d607146d3f0ea8cd46c48b5984084613a8ce.jpg"],"street_name":"Wapping Wall Wapping London","thumbnail_url":"http://images.zoopla.co.uk/f03d30a35c97bf20825af1db8f9e52e1c936dd42_80_60.jpg","num_bathrooms":"0","description":"Charming one double bedroom apartment in popular modern development in the heart of Wapping. Recently refurbished, the apartment is bright and spacious and also benefits from secure parking and views of landscaped gardens. Call now!!\n\nOur Ref: rpl/iupload/CTL070029","post_town":"London","price_change":[{"date":"2010-07-23 19:12:46","price":"265"},{"date":"2011-01-06 19:00:45","price":"275"}],"details_url":"http://www.zoopla.co.uk/to-rent/details/11695072","agent_logo":"http://static.zoopla.co.uk/zoopla_static_agent_logo_(26302).gif","outcode":"E1W","agent_phone":"020 3318 9246","image_url":"http://images.zoopla.co.uk/f03d30a35c97bf20825af1db8f9e52e1c936dd42_354_255.jpg","price":"275","county":"London","listing_id":"11695072"}],"street":null,"town":"","latitude":51.50639,"county":"London","postcode":"E1W 3TJ","bounding_box":{"latitude_min":"51.506390","longitude_min":"-0.054738","longitude_max":"-0.054738","latitude_max":"51.506390"}}
|
data/test/helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'mocha'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', '..'))
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
16
|
+
require 'zoopla'
|
17
|
+
|
18
|
+
class Test::Unit::TestCase
|
19
|
+
|
20
|
+
def api_reply(name)
|
21
|
+
File.read("api_replies/#{name}.js")
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,274 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestZooplaListings < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@rentals = Zoopla::Listings::Rentals.new('abcdef123')
|
7
|
+
@sales = Zoopla::Listings::Sales.new('abcdef123')
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_reset_for_sales
|
11
|
+
@sales.include_sold
|
12
|
+
assert_equal({:listing_status=>"sale", :include_sold => '1'}, @sales.instance_variable_get('@request'))
|
13
|
+
@sales.reset!
|
14
|
+
assert_equal({:listing_status=>"sale"}, @sales.instance_variable_get('@request'))
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_reset_for_rentals
|
18
|
+
@rentals.include_rented
|
19
|
+
assert_equal({:listing_status=>"rent", :include_rented => '1'}, @rentals.instance_variable_get('@request'))
|
20
|
+
@rentals.reset!
|
21
|
+
assert_equal({:listing_status=>"rent"}, @rentals.instance_variable_get('@request'))
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_in
|
25
|
+
listing_parameter_test(:in, {:postcode => 'E1W 3TJ'}, {:postcode => 'E1W 3TJ'})
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_within
|
29
|
+
listing_parameter_test(:within, 2, {:radius => 2})
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_radius
|
33
|
+
listing_parameter_test(:radius, 2, {:radius => 2})
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_order_by
|
37
|
+
listing_parameter_test(:order_by, :age, {:order_by => 'age'})
|
38
|
+
listing_parameter_test(:order_by, :price, {:order_by => 'price'})
|
39
|
+
assert_raise RuntimeError do
|
40
|
+
listing_parameter_test(:order_by, :blah, {})
|
41
|
+
end
|
42
|
+
assert_raise RuntimeError do
|
43
|
+
listing_parameter_test(:order_by, nil, {})
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_ordering
|
48
|
+
listing_parameter_test(:ordering, :ascending, {:ordering => 'ascending'})
|
49
|
+
listing_parameter_test(:ordering, :descending, {:ordering => 'descending'})
|
50
|
+
assert_raise RuntimeError do
|
51
|
+
listing_parameter_test(:ordering, :blah, {})
|
52
|
+
end
|
53
|
+
assert_raise RuntimeError do
|
54
|
+
listing_parameter_test(:ordering, nil, {})
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_include_sold
|
59
|
+
@sales.include_sold
|
60
|
+
expected = {:listing_status=>"sale", :include_sold => '1'}
|
61
|
+
assert_equal expected, @sales.instance_variable_get('@request')
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_include_rented
|
65
|
+
@rentals.include_rented
|
66
|
+
expected = {:listing_status=>"rent", :include_rented => '1'}
|
67
|
+
assert_equal expected, @rentals.instance_variable_get('@request')
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_minimum_price
|
71
|
+
listing_parameter_test(:minimum_price, 300, {:minimum_price => 300})
|
72
|
+
assert_raise RuntimeError do
|
73
|
+
listing_parameter_test(:minimum_price, nil, {})
|
74
|
+
end
|
75
|
+
assert_raise RuntimeError do
|
76
|
+
listing_parameter_test(:minimum_price, -200, {})
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_maximum_price
|
81
|
+
listing_parameter_test(:maximum_price, 500, {:maximum_price => 500})
|
82
|
+
assert_raise RuntimeError do
|
83
|
+
listing_parameter_test(:maximum_price, nil, {})
|
84
|
+
end
|
85
|
+
assert_raise RuntimeError do
|
86
|
+
listing_parameter_test(:maximum_price, -200, {})
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_price
|
91
|
+
listing_parameter_test(:for, 200..500, {:minimum_price => 200, :maximum_price => 500})
|
92
|
+
listing_parameter_test(:price, 200..500, {:minimum_price => 200, :maximum_price => 500})
|
93
|
+
listing_parameter_test(:price, 200..200, {:minimum_price => 200, :maximum_price => 200})
|
94
|
+
listing_parameter_test(:price, 200, {:minimum_price => 200, :maximum_price => 200})
|
95
|
+
assert_raise RuntimeError do
|
96
|
+
listing_parameter_test(:price, -200, {})
|
97
|
+
end
|
98
|
+
assert_raise RuntimeError do
|
99
|
+
listing_parameter_test(:price, 500..200, {})
|
100
|
+
end
|
101
|
+
assert_raise RuntimeError do
|
102
|
+
listing_parameter_test(:price, nil, {})
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_minimum_beds
|
107
|
+
listing_parameter_test(:minimum_beds, 3, {:minimum_beds => 3})
|
108
|
+
assert_raise RuntimeError do
|
109
|
+
listing_parameter_test(:minimum_beds, nil, {})
|
110
|
+
end
|
111
|
+
assert_raise RuntimeError do
|
112
|
+
listing_parameter_test(:minimum_beds, -2, {})
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_maximum_beds
|
117
|
+
listing_parameter_test(:maximum_beds, 5, {:maximum_beds => 5})
|
118
|
+
assert_raise RuntimeError do
|
119
|
+
listing_parameter_test(:maximum_beds, nil, {})
|
120
|
+
end
|
121
|
+
assert_raise RuntimeError do
|
122
|
+
listing_parameter_test(:maximum_beds, -2, {})
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_beds
|
127
|
+
listing_parameter_test(:beds, 2..5, {:minimum_beds => 2, :maximum_beds => 5})
|
128
|
+
listing_parameter_test(:beds, 2..2, {:minimum_beds => 2, :maximum_beds => 2})
|
129
|
+
listing_parameter_test(:beds, 2, {:minimum_beds => 2, :maximum_beds => 2})
|
130
|
+
assert_raise RuntimeError do
|
131
|
+
listing_parameter_test(:beds, -2, {})
|
132
|
+
end
|
133
|
+
assert_raise RuntimeError do
|
134
|
+
listing_parameter_test(:beds, 5..2, {})
|
135
|
+
end
|
136
|
+
assert_raise RuntimeError do
|
137
|
+
listing_parameter_test(:beds, nil, {})
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_furnished
|
142
|
+
listing_parameter_test(:furnished, 'furnished', {:furnished => 'furnished'})
|
143
|
+
listing_parameter_test(:furnished, 'unfurnished', {:furnished => 'unfurnished'})
|
144
|
+
listing_parameter_test(:furnished, 'part-furnished', {:furnished => 'part-furnished'})
|
145
|
+
assert_raise RuntimeError do
|
146
|
+
listing_parameter_test(:furnished, 'semi-furnished', {})
|
147
|
+
end
|
148
|
+
assert_raise RuntimeError do
|
149
|
+
listing_parameter_test(:furnished, nil, {})
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_property_type
|
154
|
+
listing_parameter_test(:property_type, 'houses', {:property_type => 'houses'})
|
155
|
+
listing_parameter_test(:property_type, 'flats', {:property_type => 'flats'})
|
156
|
+
assert_raise RuntimeError do
|
157
|
+
listing_parameter_test(:property_type, nil, {})
|
158
|
+
end
|
159
|
+
assert_raise RuntimeError do
|
160
|
+
listing_parameter_test(:property_type, 'igloos', {})
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_houses
|
165
|
+
@sales.houses
|
166
|
+
expected = {:listing_status=>"sale", :property_type => 'houses'}
|
167
|
+
assert_equal expected, @sales.instance_variable_get('@request')
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_flats
|
171
|
+
@sales.flats
|
172
|
+
expected = {:listing_status=>"sale", :property_type => 'flats'}
|
173
|
+
assert_equal expected, @sales.instance_variable_get('@request')
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_keywords
|
177
|
+
listing_parameter_test(:keywords, 'very cheap centrally located spacious modern duplex', {:keywords => 'very cheap centrally located spacious modern duplex'})
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_listing_id
|
181
|
+
listing_parameter_test(:listing_id, 7, {:listing_id => [7]})
|
182
|
+
listing_parameter_test(:listing_id, 11, {:listing_id => [7, 11]})
|
183
|
+
listing_parameter_test(:listing_id, 13, {:listing_id => [7, 11, 13]})
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_forming_the_request_by_chaining
|
187
|
+
@rentals.flats
|
188
|
+
.in({:postcode => 'E1W 3TJ'})
|
189
|
+
.within(2)
|
190
|
+
.price(200..400)
|
191
|
+
.beds(1..2)
|
192
|
+
.furnished('furnished')
|
193
|
+
.include_rented
|
194
|
+
.order_by(:price)
|
195
|
+
.ordering(:descending)
|
196
|
+
expected = { :listing_status=>"rent",
|
197
|
+
:property_type=>"flats",
|
198
|
+
:postcode=>"E1W 3TJ",
|
199
|
+
:radius=>2,
|
200
|
+
:minimum_price=>200,
|
201
|
+
:maximum_price=>400,
|
202
|
+
:minimum_beds=>1,
|
203
|
+
:maximum_beds=>2,
|
204
|
+
:furnished=>"furnished",
|
205
|
+
:include_rented=>"1",
|
206
|
+
:order_by=>"price",
|
207
|
+
:ordering=>"descending"}
|
208
|
+
assert_equal expected, @rentals.instance_variable_get('@request')
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_only_correct_listing_types_requested_for_sales
|
212
|
+
@sales.in({:postcode => 'E1W 3TJ'})
|
213
|
+
expected = {:listing_status=>"sale", :postcode => 'E1W 3TJ'}
|
214
|
+
assert_equal expected, @sales.instance_variable_get('@request')
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_only_correct_listing_types_requested_for_rentals
|
218
|
+
@rentals.in({:postcode => 'E1W 3TJ'})
|
219
|
+
expected = {:listing_status=>"rent", :postcode => 'E1W 3TJ'}
|
220
|
+
assert_equal expected, @rentals.instance_variable_get('@request')
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_requesting_multiple_results_pages_transparently
|
224
|
+
mock = mock();
|
225
|
+
mock.expects(:process_listing).times(12);
|
226
|
+
page1 = @rentals.send :preprocess, JSON.parse(api_reply('big_request_page1'))
|
227
|
+
page2 = @rentals.send :preprocess, JSON.parse(api_reply('big_request_page2'))
|
228
|
+
@rentals.stubs(:fetch_data).returns(page1, page2)
|
229
|
+
@rentals.in({:postcode => 'E1W 3TJ'}).within(0.1).price(300..400).each {|listing|
|
230
|
+
mock.process_listing
|
231
|
+
}
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_deep_parsing_the_reply
|
235
|
+
_, reply = @rentals.send(:preprocess, JSON.parse(api_reply('postcode')))
|
236
|
+
listing = reply.first
|
237
|
+
assert_equal 11695072, listing.listing_id
|
238
|
+
assert_equal 'rent', listing.listing_status
|
239
|
+
assert_equal 275, listing.price
|
240
|
+
assert_equal 'Atkinson Mcleod', listing.agent_name
|
241
|
+
assert_equal '135 Leman Street, Aldgate', listing.agent_address
|
242
|
+
assert_equal 'http://static.zoopla.co.uk/zoopla_static_agent_logo_(26302).gif', listing.agent_logo
|
243
|
+
assert_match(/^Charming one double bedroom apartment .+Our Ref: rpl\/iupload\/CTL070029$/m, listing.description)
|
244
|
+
assert_equal 'http://www.zoopla.co.uk/to-rent/details/11695072', listing.details_url
|
245
|
+
assert_equal 'Prospect Place, Wapping Wall, Wapping, London E1W', listing.displayable_address
|
246
|
+
assert_equal 'http://content.zoopla.co.uk/18d7d607146d3f0ea8cd46c48b5984084613a8ce.jpg', listing.floor_plan.first
|
247
|
+
assert_equal 'Picture No.05', listing.image_caption
|
248
|
+
assert_equal 'http://images.zoopla.co.uk/f03d30a35c97bf20825af1db8f9e52e1c936dd42_354_255.jpg', listing.image_url
|
249
|
+
assert_equal 51.50639, listing.latitude
|
250
|
+
assert_equal(-0.054738, listing.longitude)
|
251
|
+
assert_equal 0, listing.num_bathrooms
|
252
|
+
assert_equal 1, listing.num_bedrooms
|
253
|
+
assert_equal 0, listing.num_floors
|
254
|
+
assert_equal 0, listing.num_recepts
|
255
|
+
assert_equal 'E1W', listing.outcode
|
256
|
+
assert_equal 'London', listing.post_town
|
257
|
+
assert_equal 265, listing.price_change.first.price
|
258
|
+
assert_equal Date.parse('2010-07-23 19:12:46'), listing.price_change.first.date
|
259
|
+
assert_equal 275, listing.price_change.last.price
|
260
|
+
assert_equal Date.parse('2011-01-06 19:00:45'), listing.price_change.last.date
|
261
|
+
assert_equal 'Flat', listing.property_type
|
262
|
+
assert_equal 'Wapping Wall Wapping London', listing.street_name
|
263
|
+
assert_equal 'http://images.zoopla.co.uk/f03d30a35c97bf20825af1db8f9e52e1c936dd42_80_60.jpg', listing.thumbnail_url
|
264
|
+
end
|
265
|
+
|
266
|
+
private
|
267
|
+
|
268
|
+
def listing_parameter_test(param, value, result)
|
269
|
+
@rentals.send(param, value)
|
270
|
+
expected = {:listing_status=>"rent"}.merge! result
|
271
|
+
assert_equal expected, @rentals.instance_variable_get('@request')
|
272
|
+
end
|
273
|
+
|
274
|
+
end
|
data/zoopla.gemspec
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{zoopla}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Evgeny Shadchnev"]
|
12
|
+
s.date = %q{2011-03-03}
|
13
|
+
s.description = %q{Access zoopla.co.uk API from ruby scripts. Fetch sales and rental properties for the UK}
|
14
|
+
s.email = %q{evgeny.shadchnev@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"Gemfile",
|
21
|
+
"Gemfile.lock",
|
22
|
+
"LICENSE.txt",
|
23
|
+
"README.markdown",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/zoopla.rb",
|
27
|
+
"lib/zoopla/api.rb",
|
28
|
+
"lib/zoopla/listings.rb",
|
29
|
+
"lib/zoopla/listings/listing.rb",
|
30
|
+
"lib/zoopla/listings/rentals.rb",
|
31
|
+
"lib/zoopla/listings/sales.rb",
|
32
|
+
"lib/zoopla/version.rb",
|
33
|
+
"test/api_replies/big_request_page1.js",
|
34
|
+
"test/api_replies/big_request_page2.js",
|
35
|
+
"test/api_replies/postcode.js",
|
36
|
+
"test/helper.rb",
|
37
|
+
"test/test_zoopla_listings.rb",
|
38
|
+
"zoopla.gemspec"
|
39
|
+
]
|
40
|
+
s.homepage = %q{http://github.com/shadchnev/zoopla}
|
41
|
+
s.licenses = ["MIT"]
|
42
|
+
s.require_paths = ["lib"]
|
43
|
+
s.rubygems_version = %q{1.5.2}
|
44
|
+
s.summary = %q{Access zoopla.co.uk API from ruby scripts}
|
45
|
+
s.test_files = [
|
46
|
+
"test/helper.rb",
|
47
|
+
"test/test_zoopla_listings.rb"
|
48
|
+
]
|
49
|
+
|
50
|
+
if s.respond_to? :specification_version then
|
51
|
+
s.specification_version = 3
|
52
|
+
|
53
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
54
|
+
s.add_runtime_dependency(%q<zoopla>, [">= 0"])
|
55
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
56
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
57
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
58
|
+
s.add_development_dependency(%q<mocha>, [">= 0.9.12"])
|
59
|
+
s.add_development_dependency(%q<mocha>, [">= 0.9.12"])
|
60
|
+
s.add_runtime_dependency(%q<hashie>, [">= 1.0.0"])
|
61
|
+
s.add_development_dependency(%q<mocha>, [">= 0.9.12"])
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<zoopla>, [">= 0"])
|
64
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
65
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
66
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
67
|
+
s.add_dependency(%q<mocha>, [">= 0.9.12"])
|
68
|
+
s.add_dependency(%q<mocha>, [">= 0.9.12"])
|
69
|
+
s.add_dependency(%q<hashie>, [">= 1.0.0"])
|
70
|
+
s.add_dependency(%q<mocha>, [">= 0.9.12"])
|
71
|
+
end
|
72
|
+
else
|
73
|
+
s.add_dependency(%q<zoopla>, [">= 0"])
|
74
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
75
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
76
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
77
|
+
s.add_dependency(%q<mocha>, [">= 0.9.12"])
|
78
|
+
s.add_dependency(%q<mocha>, [">= 0.9.12"])
|
79
|
+
s.add_dependency(%q<hashie>, [">= 1.0.0"])
|
80
|
+
s.add_dependency(%q<mocha>, [">= 0.9.12"])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zoopla
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Evgeny Shadchnev
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-03-03 00:00:00 +00:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: zoopla
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.0.0
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: jeweler
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.5.2
|
46
|
+
type: :development
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rcov
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: mocha
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.9.12
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: mocha
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 0.9.12
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *id006
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: hashie
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.0.0
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: *id007
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: mocha
|
95
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 0.9.12
|
101
|
+
type: :development
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: *id008
|
104
|
+
description: Access zoopla.co.uk API from ruby scripts. Fetch sales and rental properties for the UK
|
105
|
+
email: evgeny.shadchnev@gmail.com
|
106
|
+
executables: []
|
107
|
+
|
108
|
+
extensions: []
|
109
|
+
|
110
|
+
extra_rdoc_files:
|
111
|
+
- LICENSE.txt
|
112
|
+
- README.markdown
|
113
|
+
files:
|
114
|
+
- Gemfile
|
115
|
+
- Gemfile.lock
|
116
|
+
- LICENSE.txt
|
117
|
+
- README.markdown
|
118
|
+
- Rakefile
|
119
|
+
- VERSION
|
120
|
+
- lib/zoopla.rb
|
121
|
+
- lib/zoopla/api.rb
|
122
|
+
- lib/zoopla/listings.rb
|
123
|
+
- lib/zoopla/listings/listing.rb
|
124
|
+
- lib/zoopla/listings/rentals.rb
|
125
|
+
- lib/zoopla/listings/sales.rb
|
126
|
+
- lib/zoopla/version.rb
|
127
|
+
- test/api_replies/big_request_page1.js
|
128
|
+
- test/api_replies/big_request_page2.js
|
129
|
+
- test/api_replies/postcode.js
|
130
|
+
- test/helper.rb
|
131
|
+
- test/test_zoopla_listings.rb
|
132
|
+
- zoopla.gemspec
|
133
|
+
has_rdoc: true
|
134
|
+
homepage: http://github.com/shadchnev/zoopla
|
135
|
+
licenses:
|
136
|
+
- MIT
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
hash: -2640295004611012173
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
version: "0"
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: "0"
|
157
|
+
requirements: []
|
158
|
+
|
159
|
+
rubyforge_project:
|
160
|
+
rubygems_version: 1.5.2
|
161
|
+
signing_key:
|
162
|
+
specification_version: 3
|
163
|
+
summary: Access zoopla.co.uk API from ruby scripts
|
164
|
+
test_files:
|
165
|
+
- test/helper.rb
|
166
|
+
- test/test_zoopla_listings.rb
|