fireeagle 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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