zoopla 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
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,3 @@
1
+ require File.expand_path('listings/listing', File.dirname(__FILE__))
2
+ require File.expand_path('listings/rentals', File.dirname(__FILE__))
3
+ require File.expand_path('listings/sales', File.dirname(__FILE__))
@@ -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,11 @@
1
+ module Zoopla
2
+
3
+ module Version
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ PATCH = 0
7
+
8
+ STRING = [MAJOR, MINOR, PATCH].compact.join('.')
9
+ end
10
+
11
+ 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