fireeagle 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.6.2
2
+
3
+ * Offload heavy lifting to OAuth for tokens and signing requests
4
+ * Add time parameter to Client#recent
5
+ * Change lookup params from :cid to :cellid to follow Fire Eagle
6
+ * Cleaned up specs
7
+
1
8
  == 0.6.1
2
9
 
3
10
  * Remove 'not implemented' message
@@ -2,10 +2,11 @@ require 'fileutils'
2
2
  include FileUtils
3
3
 
4
4
  require 'rubygems'
5
- %w[rake hoe newgem rubigen].each do |req_gem|
5
+ %w[rake hoe newgem rubigen oauth geo_ruby].each do |req_gem|
6
6
  begin
7
7
  require req_gem
8
8
  rescue LoadError
9
+ req_gem = 'GeoRuby' if req_gem == 'geo_ruby' # gem not the same name
9
10
  puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
11
  puts "Installation: gem install #{req_gem} -y"
11
12
  exit
data/lib/fireeagle.rb CHANGED
@@ -20,7 +20,7 @@ class FireEagle
20
20
  RECENT_API_PATH = "/api/0.1/recent"
21
21
  WITHIN_API_PATH = "/api/0.1/within"
22
22
  FORMAT_XML = "xml"
23
- UPDATE_PARAMS = :lat, :lon, :woeid, :place_id, :address, :mnc, :mcc, :lac, :cid, :postal, :city, :state, :country, :q, :label
23
+ UPDATE_PARAMS = :lat, :lon, :woeid, :place_id, :address, :mnc, :mcc, :lac, :cellid, :postal, :city, :state, :country, :q, :label
24
24
  # not yet supported
25
25
  #,:geom, :upcoming_venue_id, :yahoo_local_id, :plazes_id
26
26
 
@@ -34,9 +34,9 @@ class FireEagle
34
34
  end
35
35
  end
36
36
 
37
- #FireEagle additions to the <code>Hash</code> class
37
+ # FireEagle additions to the <code>Hash</code> class
38
38
  class Hash
39
- #Returns <code>true</code> if the ALL or NONE of the given keys are present in <i>hsh</i>.
39
+ # Returns <code>true</code> if the ALL or NONE of the given keys are present in <i>my_keys</i>.
40
40
  def has_all_or_none_keys?(*my_keys)
41
41
  size = my_keys.length
42
42
  false_count = 0
@@ -47,7 +47,19 @@ class Hash
47
47
  end
48
48
  end
49
49
 
50
+ # FireEagle addition to the <code>OAuth::Consumer</code> class
51
+ class OAuth::Consumer
52
+ alias_method :create_http_with_verify, :create_http
53
+ # Monkey patch to silence the SSL warnings
54
+ def create_http_without_verify #:nodoc:
55
+ http_object = create_http_with_verify
56
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE if uri.scheme=="https"
57
+ http_object
58
+ end
59
+ alias_method :create_http, :create_http_without_verify
60
+ end
61
+
50
62
  require File.dirname(__FILE__) + '/fireeagle/client'
51
63
  require File.dirname(__FILE__) + '/fireeagle/location'
52
64
  require File.dirname(__FILE__) + '/fireeagle/user'
53
- require File.dirname(__FILE__) + '/fireeagle/response'
65
+ require File.dirname(__FILE__) + '/fireeagle/response'
@@ -76,23 +76,23 @@ class FireEagle
76
76
  :debug => false,
77
77
  :format => FireEagle::FORMAT_XML
78
78
  }.merge(options)
79
-
79
+
80
80
  # symbolize keys
81
81
  options.map do |k,v|
82
82
  options[k.to_sym] = v
83
83
  end
84
84
  raise FireEagle::ArgumentError, "OAuth Consumer Key and Secret required" if options[:consumer_key].nil? || options[:consumer_secret].nil?
85
- @consumer = OAuth::Consumer.new(options[:consumer_key], options[:consumer_secret])
86
- @debug = options[:debug]
87
- @format = options[:format]
88
- @app_id = options[:app_id]
85
+ @consumer = OAuth::Consumer.new(options[:consumer_key], options[:consumer_secret], :site => FireEagle::API_SERVER, :authorize_url => FireEagle::AUTHORIZATION_URL)
86
+ @debug = options[:debug]
87
+ @format = options[:format]
88
+ @app_id = options[:app_id]
89
89
  if options[:access_token] && options[:access_token_secret]
90
- @access_token = OAuth::Token.new(options[:access_token], options[:access_token_secret])
90
+ @access_token = OAuth::AccessToken.new(@consumer, options[:access_token], options[:access_token_secret])
91
91
  else
92
92
  @access_token = nil
93
93
  end
94
94
  if options[:request_token] && options[:request_token_secret]
95
- @request_token = OAuth::Token.new(options[:request_token], options[:request_token_secret])
95
+ @request_token = OAuth::RequestToken.new(@consumer, options[:request_token], options[:request_token_secret])
96
96
  else
97
97
  @request_token = nil
98
98
  end
@@ -101,8 +101,7 @@ class FireEagle
101
101
  # Obtain an <strong>new</strong> unauthorized OAuth Request token
102
102
  def get_request_token(force_token_regeneration = false)
103
103
  if force_token_regeneration || @request_token.nil?
104
- response = get(FireEagle::REQUEST_TOKEN_PATH, :token => nil)
105
- @request_token = create_token(response)
104
+ @request_token = consumer.get_request_token
106
105
  end
107
106
  @request_token
108
107
  end
@@ -116,14 +115,13 @@ class FireEagle
116
115
  # The URL the user must access to authorize this token. request_token must be called first. For use by web-based and desktop-based applications.
117
116
  def authorization_url
118
117
  raise FireEagle::ArgumentError, "call #get_request_token first" if @request_token.nil?
119
- "#{FireEagle::AUTHORIZATION_URL}?oauth_token=#{@request_token.token}"
118
+ request_token.authorize_url
120
119
  end
121
120
 
122
121
  #Exchange an authorized OAuth Request token for an access token. For use by desktop-based and mobile applications.
123
122
  def convert_to_access_token
124
123
  raise FireEagle::ArgumentError, "call #get_request_token and have user authorize the token first" if @request_token.nil?
125
- response = get(FireEagle::ACCESS_TOKEN_PATH, :token => @request_token)
126
- @access_token = create_token(response)
124
+ @access_token = request_token.get_access_token
127
125
  end
128
126
 
129
127
  # Disambiguates potential values for update query. Results from lookup can be passed to
@@ -133,19 +131,19 @@ class FireEagle
133
131
  #
134
132
  # There is a specific order for looking up locations. For example, if you provide lat, lon, and address,
135
133
  # FireEagle will use the the latitude and longitude geo-coordinates and ignore the address.
136
- #
134
+ #
137
135
  # Location Hash keys, in order of priority:
138
- #
139
- # [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
140
- # [<tt>(:woeid)</tt>] Where on Earth ID
141
- # [<tt>:place_id</tt>] Place ID (via Flickr/Upcomoing); deprecated in favor of WOE IDs when possible
142
- # [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
143
- # [<tt>(:mnc, :mcc, :lac, :cid)</tt>] cell tower information, all required (as integers) for a valid tower location
144
- # [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
145
- # [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
146
- # [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
147
- # [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
148
- # [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
136
+ #
137
+ # [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
138
+ # [<tt>(:woeid)</tt>] Where on Earth ID
139
+ # [<tt>:place_id</tt>] Place ID (via Flickr/Upcomoing); deprecated in favor of WOE IDs when possible
140
+ # [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
141
+ # [<tt>(:mnc, :mcc, :lac, :cellid)</tt>] cell tower information, all required (as integers) for a valid tower location
142
+ # [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
143
+ # [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
144
+ # [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
145
+ # [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
146
+ # [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
149
147
  #
150
148
  # Not yet supported:
151
149
  #
@@ -154,9 +152,7 @@ class FireEagle
154
152
  # * <tt>plazes_id</tt>
155
153
  def lookup(params)
156
154
  raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
157
-
158
155
  response = get(FireEagle::LOOKUP_API_PATH + ".#{format}", :params => params)
159
-
160
156
  FireEagle::Response.new(response.body).locations
161
157
  end
162
158
 
@@ -167,18 +163,18 @@ class FireEagle
167
163
  #
168
164
  # There is a specific order for looking up locations. For example, if you provide lat, lon, and address,
169
165
  # FireEagle will use the the latitude and longitude geo-coordinates and ignore the address.
170
- #
166
+ #
171
167
  # Location Hash keys, in order of priority:
172
- #
173
- # [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
174
- # [<tt>:place_id</tt>] Place ID - valid values decrypts to an integer value
175
- # [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
176
- # [<tt>(:mnc, :mcc, :lac, :cid)</tt>] cell tower information, all required (as integers) for a valid tower location
177
- # [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
178
- # [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
179
- # [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
180
- # [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
181
- # [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
168
+ #
169
+ # [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
170
+ # [<tt>:place_id</tt>] Place ID - valid values decrypts to an integer value
171
+ # [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
172
+ # [<tt>(:mnc, :mcc, :lac, :cellid)</tt>] cell tower information, all required (as integers) for a valid tower location
173
+ # [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
174
+ # [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
175
+ # [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
176
+ # [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
177
+ # [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
182
178
  #
183
179
  # Not yet supported:
184
180
  #
@@ -187,50 +183,48 @@ class FireEagle
187
183
  # * <tt>plazes_id</tt>
188
184
  def update(location = {})
189
185
  raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
190
-
191
186
  location = sanitize_location_hash(location)
192
-
193
187
  response = post(FireEagle::UPDATE_API_PATH + ".#{format}", :params => location)
194
-
195
188
  FireEagle::Response.new(response.body)
196
189
  end
197
190
 
198
191
  # Returns the Location of a User.
199
192
  def user
200
193
  raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
201
-
202
194
  response = get(FireEagle::USER_API_PATH + ".#{format}")
203
-
204
195
  FireEagle::Response.new(response.body).users.first
205
196
  end
206
197
  alias_method :location, :user
207
198
 
208
- # Query for Users of an Application who have updated their Location recently. Returns a list of
199
+ # Query for Users of an Application who have updated their Location recently. Returns a list of
209
200
  # Users for the Application with recently updated locations.
210
- def recent(count = 10, start = 0)
201
+ #
202
+ # == Optional parameters:
203
+ #
204
+ # <tt>count</tt> Number of users to return per page. (default: 10)
205
+ # <tt>start</tt> The page number at which to start returning the list of users. Pages are 0-indexed, each page contains the per_page number of users. (default: 0)
206
+ # <tt>time</tt> The time to start looking at recent updates from. Value is flexible, supported forms are 'now', 'yesterday', '12:00', '13:00', '1:00pm' and '2008-03-12 12:34:56'. (default: 'now')
207
+ def recent(count = 10, start = 0, time = 'now')
211
208
  raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
212
-
213
- params = { :count => count, :start => start }
214
-
209
+ params = { :count => count, :start => start, :time => time }
215
210
  response = get(FireEagle::RECENT_API_PATH + ".#{format}", :params => params)
216
-
217
211
  FireEagle::Response.new(response.body).users
218
212
  end
219
213
 
220
214
  # Takes a Place ID or a Location and returns a list of users of your application who are within the bounding box of that Location.
221
215
  #
222
216
  # Location Hash keys, in order of priority:
223
- #
224
- # [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
225
- # [<tt>:woeid</tt>] Where on Earth ID
226
- # [<tt>:place_id</tt>] Place ID
227
- # [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
228
- # [<tt>(:mnc, :mcc, :lac, :cid)</tt>] cell tower information, all required (as integers) for a valid tower location
229
- # [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
230
- # [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
231
- # [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
232
- # [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
233
- # [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
217
+ #
218
+ # [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
219
+ # [<tt>:woeid</tt>] Where on Earth ID
220
+ # [<tt>:place_id</tt>] Place ID
221
+ # [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
222
+ # [<tt>(:mnc, :mcc, :lac, :cellid)</tt>] cell tower information, all required (as integers) for a valid tower location
223
+ # [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
224
+ # [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
225
+ # [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
226
+ # [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
227
+ # [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
234
228
  #
235
229
  # Not yet supported:
236
230
  #
@@ -239,12 +233,9 @@ class FireEagle
239
233
  # * <tt>plazes_id</tt>
240
234
  def within(location = {}, count = 10, start = 0)
241
235
  raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
242
-
243
236
  location = sanitize_location_hash(location)
244
237
  params = { :count => count, :start => start }.merge(location)
245
-
246
238
  response = get(FireEagle::WITHIN_API_PATH + ".#{format}", :params => params)
247
-
248
239
  FireEagle::Response.new(response.body).users
249
240
  end
250
241
 
@@ -257,24 +248,10 @@ class FireEagle
257
248
 
258
249
  location = location.reject { |key, value| !FireEagle::UPDATE_PARAMS.include?(key) }
259
250
  raise FireEagle::ArgumentError, "Requires all or none of :lat, :lon" unless location.has_all_or_none_keys?(:lat, :lon)
260
- raise FireEagle::ArgumentError, "Requires all or none of :mnc, :mcc, :lac, :cellid" unless location.has_all_or_none_keys?(:mnc, :mcc, :lac, :cid)
251
+ raise FireEagle::ArgumentError, "Requires all or none of :mnc, :mcc, :lac, :cellid" unless location.has_all_or_none_keys?(:mnc, :mcc, :lac, :cellid)
261
252
  location
262
253
  end
263
254
 
264
- def xml? #:nodoc:
265
- format == FireEagle::FORMAT_XML
266
- end
267
-
268
- def create_token(response) #:nodoc:
269
- token = Hash[*response.body.split("&").map { |x| x.split("=") }.flatten]
270
- OAuth::Token.new(token["oauth_token"], token["oauth_token_secret"])
271
- end
272
-
273
- # Is the Client in debug mode?
274
- def debug?
275
- @debug == true
276
- end
277
-
278
255
  def get(url, options = {}) #:nodoc:
279
256
  request(:get, url, options)
280
257
  end
@@ -284,33 +261,21 @@ class FireEagle
284
261
  end
285
262
 
286
263
  def request(method, url, options) #:nodoc:
287
- options = {
288
- :params => {},
289
- :token => @access_token
290
- }.merge(options)
291
-
292
- request_uri = URI.parse(FireEagle::API_SERVER + url)
293
- http = Net::HTTP.new(request_uri.host, request_uri.port)
294
- http.set_debug_output $stderr if debug?
295
- if FireEagle::API_SERVER =~ /https:/
296
- http.use_ssl = true
297
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
264
+ response = case method
265
+ when :post
266
+ access_token.request(:post, url, options[:params])
267
+ when :get
268
+ qs = options[:params].collect { |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join("&")
269
+ access_token.request(:get, "#{url}?#{qs}")
270
+ else
271
+ raise ArgumentError, "method #{method} not supported"
298
272
  end
299
273
 
300
- request = nil
301
- if method == :post
302
- request = Net::HTTP::Post.new(request_uri.path)
303
- request.set_form_data(options[:params])
304
- elsif method == :get
305
- qs = options[:params].collect { |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join("&")
306
- request = Net::HTTP::Get.new(request_uri.path + "?" + qs)
274
+ case response.code
275
+ when '500'; then raise FireEagle::FireEagleException, "Internal Server Error"
276
+ when '400'; then raise FireEagle::FireEagleException, "Method Not Implemented Yet"
277
+ else response
307
278
  end
308
- request.oauth!(http, consumer, options[:token])
309
- response = http.request(request)
310
- raise FireEagle::FireEagleException, "Internal Server Error" if response.code == '500'
311
- raise FireEagle::FireEagleException, "Method Not Implemented Yet" if response.code == '400'
312
- response
313
279
  end
314
-
315
280
  end
316
- end
281
+ end
@@ -2,7 +2,7 @@ class FireEagle #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 6
5
- TINY = 1
5
+ TINY = 2
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -8,7 +8,7 @@ describe "FireEagle Location" do
8
8
  end
9
9
 
10
10
  it "should know if this is a best guess" do
11
- @location.best_guess?.should == false
11
+ @location.should_not be_best_guess
12
12
  end
13
13
 
14
14
  it "should represent the level" do
@@ -30,7 +30,7 @@ describe "FireEagle Location" do
30
30
  it "should represent the location's timestamp" do
31
31
  @location.located_at.should == Time.parse("2008-01-22T14:23:11-08:00")
32
32
  end
33
-
33
+
34
34
  it "should use the name for #to_s" do
35
35
  @location.to_s.should == @location.name
36
36
  end
@@ -40,19 +40,19 @@ describe "FireEagle Location" do
40
40
  it "should represent a bounding box as a GeoRuby Envelope" do
41
41
  location = Hpricot.XML(XML_LOCATION_CHUNK)
42
42
  @location = FireEagle::Location.new(location)
43
- @location.geom.class.should == GeoRuby::SimpleFeatures::Envelope
43
+ @location.geom.should be_an_instance_of(GeoRuby::SimpleFeatures::Envelope)
44
44
  end
45
45
 
46
46
  it "should represent an exact point as a GeoRuby Point" do
47
47
  location = Hpricot.XML(XML_EXACT_LOCATION_CHUNK)
48
48
  @location = FireEagle::Location.new(location)
49
- @location.geom.class.should == GeoRuby::SimpleFeatures::Point
49
+ @location.geom.should be_an_instance_of(GeoRuby::SimpleFeatures::Point)
50
50
  end
51
51
 
52
52
  it "should be aliased as 'geo'" do
53
53
  location = Hpricot.XML(XML_EXACT_LOCATION_CHUNK)
54
54
  @location = FireEagle::Location.new(location)
55
- @location.geo.class.should == GeoRuby::SimpleFeatures::Point
55
+ @location.geo.should be_an_instance_of(GeoRuby::SimpleFeatures::Point)
56
56
  end
57
57
 
58
58
  end
@@ -7,29 +7,29 @@ describe "FireEagle Response" do
7
7
  before(:each) do
8
8
  @response = FireEagle::Response.new(XML_LOCATION_RESPONSE)
9
9
  end
10
-
10
+
11
11
  it "should indicate success" do
12
- @response.success?.should == true
12
+ @response.should be_success
13
13
  end
14
14
 
15
15
  it "should have an array of users" do
16
- @response.users.size.should == 1
16
+ @response.should have(1).users
17
17
  end
18
-
18
+
19
19
  it "should have each users' token" do
20
20
  @response.users.first.token.should == "16w3z6ysudxt"
21
21
  end
22
-
22
+
23
23
  it "should flag the best guess" do
24
24
  @response.users.first.best_guess.name.should == "Yolo County, California"
25
25
  end
26
-
27
- it "should have users' loactions" do
28
- @response.users.first.locations.size.should == 4
26
+
27
+ it "should have users' locations" do
28
+ @response.users.first.should have(4).locations
29
29
  end
30
30
 
31
31
  end
32
-
32
+
33
33
  describe "location parsing" do
34
34
 
35
35
  before(:each) do
@@ -37,11 +37,11 @@ describe "FireEagle Response" do
37
37
  end
38
38
 
39
39
  it "should indicate success" do
40
- @response.success?.should == true
40
+ @response.should be_success
41
41
  end
42
42
 
43
43
  it "should have an array of locations" do
44
- @response.locations.size.should == 9
44
+ @response.should have(9).locations
45
45
  end
46
46
 
47
47
  it "should have each location's place_id" do
@@ -12,7 +12,7 @@ describe "FireEagle" do
12
12
 
13
13
  it "should initialize an OAuth::Consumer" do
14
14
  @consumer = mock(OAuth::Consumer)
15
- OAuth::Consumer.should_receive(:new).and_return(@consumer)
15
+ OAuth::Consumer.should_receive(:new).with('key', 'sekret', :site => FireEagle::API_SERVER, :authorize_url => FireEagle::AUTHORIZATION_URL).and_return(@consumer)
16
16
  client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret')
17
17
  end
18
18
 
@@ -20,16 +20,16 @@ describe "FireEagle" do
20
20
 
21
21
  describe "web app authentication scenario" do
22
22
 
23
- it "should initialize a OAuth::Token if given it's token and secret" do
24
- @access_token = mock(OAuth::Token)
25
- OAuth::Token.stub!(:new).and_return(@access_token)
23
+ it "should initialize an OAuth::AccessToken if given its token and secret" do
24
+ @access_token = mock(OAuth::AccessToken)
25
+ OAuth::AccessToken.stub!(:new).and_return(@access_token)
26
26
  client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
27
27
  client.access_token.should == @access_token
28
28
  end
29
29
 
30
- it "should initialize a request token if given one" do
31
- @request_token = mock(OAuth::Token)
32
- OAuth::Token.stub!(:new).and_return(@request_token)
30
+ it "should initialize an OAuth::RequestToken if given its token and secret" do
31
+ @request_token = mock(OAuth::RequestToken)
32
+ OAuth::RequestToken.stub!(:new).and_return(@request_token)
33
33
  client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :request_token => 'toke', :request_token_secret => 'sekret')
34
34
  client.request_token.should == @request_token
35
35
  end
@@ -38,7 +38,7 @@ describe "FireEagle" do
38
38
  describe "request token scenario" do
39
39
  it "shouldn't initialize with a access_token" do
40
40
  client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret')
41
- client.access_token.should == nil
41
+ client.access_token.should be_nil
42
42
  end
43
43
 
44
44
  it "should require token exchange before calling any API methods" do
@@ -49,12 +49,15 @@ describe "FireEagle" do
49
49
  end
50
50
 
51
51
  it "should generate a Request Token URL" do
52
+ consumer = mock(OAuth::Consumer)
53
+ token = mock(OAuth::RequestToken)
54
+ consumer.should_receive(:get_request_token).and_return(token)
55
+ token.should_receive(:authorize_url)
56
+
52
57
  client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret')
53
- @token = mock("token", :token => 'foo')
54
- client.stub!(:get).and_return('')
55
- client.stub!(:create_token).and_return(@token)
58
+ client.should_receive(:consumer).and_return(consumer)
56
59
  client.get_request_token
57
- client.authorization_url.should =~ /\?oauth_token=foo/
60
+ client.authorization_url
58
61
  end
59
62
 
60
63
  it "should require #get_request_token be called before #convert_to_access_token" do
@@ -71,14 +74,19 @@ describe "FireEagle" do
71
74
  end.should raise_error(FireEagle::ArgumentError)
72
75
  end
73
76
 
74
- it "should generate a Request Token URL" do
77
+ it "should generate an Access Token" do
78
+ consumer = mock(OAuth::Consumer)
79
+ req_token = mock(OAuth::RequestToken)
80
+ acc_token = mock(OAuth::AccessToken)
81
+ consumer.should_receive(:get_request_token).and_return(req_token)
82
+ req_token.should_receive(:get_access_token).and_return(acc_token)
83
+
75
84
  client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret')
76
- @token = mock("token", :token => 'foo')
77
- client.stub!(:get).and_return('')
78
- client.stub!(:create_token).and_return(@token)
85
+ client.should_receive(:consumer).and_return(consumer)
86
+
79
87
  client.get_request_token
80
88
  client.convert_to_access_token
81
- client.access_token.should == @token
89
+ client.access_token.should == acc_token
82
90
  end
83
91
 
84
92
  end
@@ -87,7 +95,7 @@ describe "FireEagle" do
87
95
 
88
96
  before(:each) do
89
97
  @client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
90
- @response = mock('response', :body => XML_SUCCESS_RESPONSE)
98
+ @response = stub('response', :body => XML_SUCCESS_RESPONSE)
91
99
  @client.stub!(:request).and_return(@response)
92
100
  end
93
101
 
@@ -96,13 +104,13 @@ describe "FireEagle" do
96
104
  lambda { @client.update(:lat => 1, :lon => 2) }.should_not raise_error(FireEagle::ArgumentError)
97
105
  end
98
106
 
99
- it "requires all or none of :mnc, :mcc, :lac, :cid" do
100
- lambda { @client.update(:mcc => 123, :lac => "whatever", :cid => true) }.should raise_error(FireEagle::ArgumentError)
101
- lambda { @client.update(:mcc => 123, :mnc => 123123, :lac => "whatever", :cid => true) }.should_not raise_error(FireEagle::ArgumentError)
107
+ it "requires all or none of :mnc, :mcc, :lac, :cellid" do
108
+ lambda { @client.update(:mcc => 123, :lac => "whatever", :cellid => true) }.should raise_error(FireEagle::ArgumentError)
109
+ lambda { @client.update(:mcc => 123, :mnc => 123123, :lac => "whatever", :cellid => true) }.should_not raise_error(FireEagle::ArgumentError)
102
110
  end
103
111
 
104
112
  it "should wrap the result" do
105
- @client.update(:mcc => 123, :mnc => 123123, :lac => "whatever", :cid => true).users.first.token.should == "16w3z6ysudxt"
113
+ @client.update(:mcc => 123, :mnc => 123123, :lac => "whatever", :cellid => true).users.first.token.should == "16w3z6ysudxt"
106
114
  end
107
115
 
108
116
  end
@@ -110,9 +118,9 @@ describe "FireEagle" do
110
118
  describe "user method" do
111
119
 
112
120
  before(:each) do
113
- @client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
114
- @response = mock('response', :body => XML_LOCATION_RESPONSE)
115
- @client.stub!(:request).and_return(@response)
121
+ @client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
122
+ response = stub('response', :body => XML_LOCATION_RESPONSE)
123
+ @client.stub!(:request).and_return(response)
116
124
  end
117
125
 
118
126
  it "should return a best guess" do
@@ -120,21 +128,21 @@ describe "FireEagle" do
120
128
  end
121
129
 
122
130
  it "should return several locations" do
123
- @client.user.locations.size.should == 4
131
+ @client.user.should have(4).locations
124
132
  end
125
133
 
126
134
  end
127
-
135
+
128
136
  describe "lookup method" do
129
137
 
130
138
  before(:each) do
131
139
  @client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
132
- @response = mock('response', :body => XML_LOOKUP_RESPONSE)
140
+ @response = stub('response', :body => XML_LOOKUP_RESPONSE)
133
141
  @client.stub!(:request).and_return(@response)
134
142
  end
135
143
 
136
144
  it "should return an array of Locations" do
137
- @client.lookup(:q => "30022").size.should == 9
145
+ @client.lookup(:q => "30022").should have(9).items
138
146
  end
139
147
 
140
148
  it "should return a place id for each" do
@@ -147,4 +155,36 @@ describe "FireEagle" do
147
155
 
148
156
  end
149
157
 
150
- end
158
+ describe "within method" do
159
+ before do
160
+ @client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
161
+ @response = stub('response', :body => XML_WITHIN_RESPONSE)
162
+ @client.stub!(:request).and_return(@response)
163
+ end
164
+
165
+ it "should return an array of Users" do
166
+ @client.within(:woe => "12796255").should have(2).users
167
+ end
168
+
169
+ it "should return an array of Locations for each" do
170
+ @client.within(:woe => "12796255").first.should have(5).locations
171
+ end
172
+ end
173
+
174
+ describe "recent method" do
175
+ before do
176
+ @client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
177
+ @response = stub('response', :body => XML_RECENT_RESPONSE)
178
+ @client.stub!(:request).and_return(@response)
179
+ end
180
+
181
+ it "should return an array of Users" do
182
+ @client.recent(2, 1, 'yesterday').should have(2).users
183
+ end
184
+
185
+ it "should return an array of Locations for each" do
186
+ @client.recent(2, 1, 'yesterday').first.should have(5).locations
187
+ end
188
+ end
189
+
190
+ end
data/spec/spec_helper.rb CHANGED
@@ -124,5 +124,236 @@ XML_LOOKUP_RESPONSE = <<-RESPONSE
124
124
  </rsp>
125
125
  RESPONSE
126
126
 
127
+ XML_WITHIN_RESPONSE = <<-RESPONSE
128
+ <?xml version="1.0" encoding="UTF-8"?>
129
+ <rsp stat="ok">
130
+ <users>
131
+ <user token="MQdDrJgXMNJi">
132
+ <location-hierarchy>
133
+ <location best-guess="true">
134
+ <id>111541</id>
135
+ <georss:point>32.7093315125 -117.1650772095</georss:point>
136
+ <level>0</level>
137
+ <level-name>exact</level-name>
138
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
139
+ <name>333 W Harbor Dr, San Diego, CA</name>
140
+ </location>
141
+ <location best-guess="false">
142
+ <id>111551</id>
143
+ <georss:box>
144
+ 32.6916618347 -117.2174377441 32.744140625 -117.1458892822
145
+ </georss:box>
146
+ <level>1</level>
147
+ <level-name>postal</level-name>
148
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
149
+ <name>San Diego, CA 92101</name>
150
+ <place-id>NpiXqwmYA5viX3K3Ew</place-id>
151
+ <woeid>12796255</woeid>
152
+ </location>
153
+ <location best-guess="false">
154
+ <id>111561</id>
155
+ <georss:box>
156
+ 32.5349388123 -117.2884292603 33.1128082275 -116.9142913818
157
+ </georss:box>
158
+ <level>3</level>
159
+ <level-name>city</level-name>
160
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
161
+ <name>San Diego, CA</name>
162
+ <place-id>Nm4O.DebBZTYKUsu</place-id>
163
+ <woeid>2487889</woeid>
164
+ </location>
165
+ <location best-guess="false">
166
+ <id>111571</id>
167
+ <georss:box>
168
+ 32.5342788696 -124.4150238037 42.0093803406 -114.1308135986
169
+ </georss:box>
170
+ <level>5</level>
171
+ <level-name>state</level-name>
172
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
173
+ <name>California</name>
174
+ <place-id>SVrAMtCbAphCLAtP</place-id>
175
+ <woeid>2347563</woeid>
176
+ </location>
177
+ <location best-guess="false">
178
+ <id>111581</id>
179
+ <georss:box>
180
+ 18.9108390808 -167.2764129639 72.8960571289 -66.6879425049
181
+ </georss:box>
182
+ <level>6</level>
183
+ <level-name>country</level-name>
184
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
185
+ <name>United States</name>
186
+ <place-id>4KO02SibApitvSBieQ</place-id>
187
+ <woeid>23424977</woeid>
188
+ </location>
189
+ </location-hierarchy>
190
+ </user>
191
+ <user token="MQdDrJgXMNJi">
192
+ <location-hierarchy>
193
+ <location best-guess="true">
194
+ <id>111541</id>
195
+ <georss:point>32.7093315125 -117.1650772095</georss:point>
196
+ <level>0</level>
197
+ <level-name>exact</level-name>
198
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
199
+ <name>333 W Harbor Dr, San Diego, CA</name>
200
+ </location>
201
+ <location best-guess="false">
202
+ <id>111551</id>
203
+ <georss:box>
204
+ 32.6916618347 -117.2174377441 32.744140625 -117.1458892822
205
+ </georss:box>
206
+ <level>1</level>
207
+ <level-name>postal</level-name>
208
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
209
+ <name>San Diego, CA 92101</name>
210
+ <place-id>NpiXqwmYA5viX3K3Ew</place-id>
211
+ <woeid>12796255</woeid>
212
+ </location>
213
+ <location best-guess="false">
214
+ <id>111561</id>
215
+ <georss:box>
216
+ 32.5349388123 -117.2884292603 33.1128082275 -116.9142913818
217
+ </georss:box>
218
+ <level>3</level>
219
+ <level-name>city</level-name>
220
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
221
+ <name>San Diego, CA</name>
222
+ <place-id>Nm4O.DebBZTYKUsu</place-id>
223
+ <woeid>2487889</woeid>
224
+ </location>
225
+ <location best-guess="false">
226
+ <id>111571</id>
227
+ <georss:box>
228
+ 32.5342788696 -124.4150238037 42.0093803406 -114.1308135986
229
+ </georss:box>
230
+ <level>5</level>
231
+ <level-name>state</level-name>
232
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
233
+ <name>California</name>
234
+ <place-id>SVrAMtCbAphCLAtP</place-id>
235
+ <woeid>2347563</woeid>
236
+ </location>
237
+ <location best-guess="false">
238
+ <id>111581</id>
239
+ <georss:box>
240
+ 18.9108390808 -167.2764129639 72.8960571289 -66.6879425049
241
+ </georss:box>
242
+ <level>6</level>
243
+ <level-name>country</level-name>
244
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
245
+ <name>United States</name>
246
+ <place-id>4KO02SibApitvSBieQ</place-id>
247
+ <woeid>23424977</woeid>
248
+ </location>
249
+ </location-hierarchy>
250
+ </user>
251
+ </users>
252
+ </rsp>
253
+ RESPONSE
254
+
255
+ XML_RECENT_RESPONSE = <<-RESPONSE
256
+ <?xml version="1.0" encoding="UTF-8"?>
257
+ <rsp stat="ok" xmlns:georss="http://www.georss.org/georss">
258
+ <users>
259
+ <user token="MQdDrJgXMNJi">
260
+ <location-hierarchy>
261
+ <location best-guess="true">
262
+ <id>111541</id>
263
+ <georss:point>32.7093315125 -117.1650772095</georss:point>
264
+ <level>0</level>
265
+ <level-name>exact</level-name>
266
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
267
+ <name>333 W Harbor Dr, San Diego, CA</name>
268
+ </location>
269
+ <location best-guess="false">
270
+ <id>111551</id>
271
+ <georss:box>32.6916618347 -117.2174377441 32.744140625 -117.1458892822</georss:box>
272
+ <level>1</level>
273
+ <level-name>postal</level-name>
274
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
275
+ <name>San Diego, CA 92101</name>
276
+ <place-id>NpiXqwmYA5viX3K3Ew</place-id>
277
+ <woeid>12796255</woeid>
278
+ </location>
279
+ <location best-guess="false">
280
+ <id>111561</id>
281
+ <georss:box>32.5349388123 -117.2884292603 33.1128082275 -116.9142913818</georss:box>
282
+ <level>3</level>
283
+ <level-name>city</level-name>
284
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
285
+ <name>San Diego, CA</name>
286
+ <place-id>Nm4O.DebBZTYKUsu</place-id>
287
+ <woeid>2487889</woeid>
288
+ </location>
289
+ <location best-guess="false">
290
+ <id>111571</id>
291
+ <georss:box>32.5342788696 -124.4150238037 42.0093803406 -114.1308135986</georss:box>
292
+ <level>5</level>
293
+ <level-name>state</level-name>
294
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
295
+ <name>California</name>
296
+ <place-id>SVrAMtCbAphCLAtP</place-id>
297
+ <woeid>2347563</woeid>
298
+ </location>
299
+ <location best-guess="false">
300
+ <id>111581</id>
301
+ <georss:box>18.9108390808 -167.2764129639 72.8960571289 -66.6879425049</georss:box>
302
+ <level>6</level>
303
+ <level-name>country</level-name>
304
+ <located-at>2008-03-03T09:05:16-08:00</located-at>
305
+ <name>United States</name>
306
+ <place-id>4KO02SibApitvSBieQ</place-id>
307
+ <woeid>23424977</woeid>
308
+ </location>
309
+ </location-hierarchy>
310
+ </user>
311
+ <user token="XMoZaTjZJiOQ">
312
+ <location-hierarchy>
313
+ <location best-guess="true">
314
+ <id>113221</id>
315
+ <georss:box>32.8155899048 -96.8162918091 32.8511695862 -96.7717132568</georss:box>
316
+ <level>1</level>
317
+ <level-name>postal</level-name>
318
+ <located-at>2008-03-03T10:24:24-08:00</located-at>
319
+ <name>Dallas, TX 75205</name>
320
+ <place-id>1KTPxFCYA5vlcics6A</place-id>
321
+ <woeid>12790441</woeid>
322
+ </location>
323
+ <location best-guess="false">
324
+ <id>113231</id>
325
+ <georss:box>32.6209487915 -96.9988708496 33.0258712769 -96.4660263062</georss:box>
326
+ <level>3</level>
327
+ <level-name>city</level-name>
328
+ <located-at>2008-03-03T10:24:24-08:00</located-at>
329
+ <name>Dallas, TX</name>
330
+ <place-id>bgWooz.bApRFBRNK</place-id>
331
+ <woeid>2388929</woeid>
332
+ </location>
333
+ <location best-guess="false">
334
+ <id>113241</id>
335
+ <georss:box>25.8372898102 -106.645652771 36.5006904602 -93.5079269409</georss:box>
336
+ <level>5</level>
337
+ <level-name>state</level-name>
338
+ <located-at>2008-03-03T10:24:24-08:00</located-at>
339
+ <name>Texas</name>
340
+ <place-id>b1Yi6qubApjz6jWW</place-id>
341
+ <woeid>2347602</woeid>
342
+ </location>
343
+ <location best-guess="false">
344
+ <id>113251</id>
345
+ <georss:box>18.9108390808 -167.2764129639 72.8960571289 -66.6879425049</georss:box>
346
+ <level>6</level>
347
+ <level-name>country</level-name>
348
+ <located-at>2008-03-03T10:24:24-08:00</located-at>
349
+ <name>United States</name>
350
+ <place-id>4KO02SibApitvSBieQ</place-id>
351
+ <woeid>23424977</woeid>
352
+ </location>
353
+ </location-hierarchy>
354
+ </user>
355
+ </users>
356
+ </rsp>
357
+ RESPONSE
127
358
 
128
359
  require File.dirname(__FILE__) + '/../lib/fireeagle'
data/tasks/rspec.rake CHANGED
@@ -19,3 +19,14 @@ Spec::Rake::SpecTask.new do |t|
19
19
  t.spec_opts = ['--options', "spec/spec.opts"]
20
20
  t.spec_files = FileList['spec/*_spec.rb']
21
21
  end
22
+
23
+ # Make spec the default task
24
+ # from http://blog.subterfusion.net/2008/rake-hacks-overriding-tasks-quick-binary-run-intelligent-irb/
25
+ Rake::TaskManager.class_eval do
26
+ def remove_task(task_name)
27
+ @tasks.delete(task_name.to_s)
28
+ end
29
+ end
30
+
31
+ Rake.application.remove_task :default
32
+ task :default => :spec
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fireeagle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Newland
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-03-06 00:00:00 -05:00
12
+ date: 2008-03-13 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency