Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

mock http calls

  • Loading branch information...
commit a01f1584570230c933cf15cfca4ac5d974e7353e 1 parent 98c8dce
@darrinholst darrinholst authored
View
2  Gemfile
@@ -8,4 +8,6 @@ gem 'json'
group :test do
gem 'rake'
gem 'rspec'
+ gem 'vcr'
+ gem 'webmock'
end
View
9 Gemfile.lock
@@ -4,6 +4,8 @@ GEM
addressable (2.3.5)
atomic (1.1.14)
buftok (0.2.0)
+ crack (0.4.2)
+ safe_yaml (~> 1.0.0)
descendants_tracker (0.0.3)
diff-lcs (1.2.5)
equalizer (0.0.9)
@@ -31,6 +33,7 @@ GEM
rspec-expectations (2.14.5)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.5)
+ safe_yaml (1.0.1)
simple-rss (1.3.1)
simple_oauth (0.2.0)
thread_safe (0.1.3)
@@ -50,6 +53,10 @@ GEM
json (>= 1.8.0)
mime-types (>= 1.16)
oauth (>= 0.4.7)
+ vcr (2.8.0)
+ webmock (1.15.2)
+ addressable (>= 2.2.7)
+ crack (>= 0.3.2)
PLATFORMS
ruby
@@ -61,3 +68,5 @@ DEPENDENCIES
rspec
twitter (~> 5.3.0)
twitter_oauth
+ vcr
+ webmock
View
84 plugins_disabled/stravalogger.rb
@@ -3,55 +3,55 @@
Description: Creates separate entries for rides and runs you finished today
Author: [Patrick Walsh](http://twitter.com/zmre)
Configuration:
- strava_athleteid: "yourid"
+ strava_access_token: "your access token"
strava_tags: "#social #sports"
strava_unit "metric" || "imperial"
Notes:
- - strava_athleteid is a number you can find in the URL when viewing your profile
+ - strava_access_token is an oauth access token for your account. You can obtain one at https://www.strava.com/settings/api
- strava_tags are tags you want to add to every entry, e.g. "#social #sports #cycling #training"
- strava_units determine what units to display data in: "metric" or "imperial"
=end
+
require 'rexml/document';
+
config = {
- 'description' => ['strava_athleteid is a number you can find in the URL when viewing your profile',
+ 'description' => ['strava_access_token is an oauth access token for your account. You can obtain one at https://www.strava.com/settings/api',
'strava_tags are tags you want to add to every entry, e.g. "#social #sports #cycling #training"',
'strava_units determine what units to display data in: "metric" or "imperial"'],
- 'strava_athleteid' => '',
+ 'strava_access_token' => '',
'strava_tags' => '#social #sports',
'strava_unit' => 'metric'
}
+
$slog.register_plugin({ 'class' => 'StravaLogger', 'config' => config })
class StravaLogger < Slogger
+ NOT_CONFIGURED = 'Strava has not been configured or is invalid, please edit your slogger_config file.'
+ NO_ACCESS_TOKEN = 'Strava access token has not been configured, please edit your slogger_config file.'
def do_log
- #feed = 'http://pipes.yahoo.com/pipes/pipe.run?_id=04c9130284062eff525dae9f9519bc38&_render=rss&athleteId='
- #feed = 'http://pipes.yahoo.com/pipes/pipe.run?_id=04c9130284062eff525dae9f9519bc38&_render=json&athleteId='
- feed = 'http://www.strava.com/api/v1/rides?athleteId='
- if @config.key?(self.class.name)
- @grconfig = @config[self.class.name]
- if !@grconfig.key?('strava_athleteid') || @grconfig['strava_athleteid'] == ''
- @log.warn("Strava athlete ID has not been configured or is invalid, please edit your slogger_config file.")
- return
- else
- feed += @grconfig['strava_athleteid']
- end
- else
- @log.warn("Strava has not been configured or is invalid, please edit your slogger_config file.")
- return
- end
+ @grconfig = @config[self.class.name]
+ return @log.warn(NOT_CONFIGURED) if @grconfig.nil?
+
+ access_token = @grconfig['strava_access_token']
+ return @log.warn(NO_ACCESS_TOKEN) if access_token.nil? || access_token.strip.empty?
+
+ feed = "https://www.strava.com/api/v3/athlete/activities?access_token=#{access_token}"
+
@log.info("Logging activities from Strava")
retries = 0
success = false
+
until success
if parse_feed(feed)
- success = true
+ success = true
else
break if $options[:max_retries] == retries
retries += 1
@log.error("Error parsing Strava feed, retrying (#{retries}/#{$options[:max_retries]})")
sleep 2
end
+
unless success
@log.fatal("Could not parse feed #{feed}")
end
@@ -65,47 +65,48 @@ def parse_feed(rss_feed)
begin
res = Net::HTTP.get_response(URI.parse(rss_feed))
rescue Exception => e
- p e
raise "ERROR retrieving Strava ride list url: #{rss_feed}"
end
return false if res.nil?
begin
- rides_json = JSON.parse(res.body)
- rides_json['rides'].each {|rides|
- output = ''
+ JSON.parse(res.body)['rides'].each {|rides|
@log.info("Examining ride #{rides['id']}: #{rides['name']}")
+
begin
res2 = Net::HTTP.get_response(URI.parse("http://www.strava.com/api/v1/rides/#{rides['id']}"));
rescue Exception => e
- p e
raise "ERROR retrieving Strava ride #{rides['id']}: http://www.strava.com/api/v1/rides/#{rides['id']}"
end
+
ride_json = JSON.parse(res2.body)
@log.info("Parsed ride #{rides['id']}")
strava = ride_json['ride']
date = Time.parse(strava['startDate'])
+
if date > @timespan
- # link
movingTime = Integer(strava['movingTime'])
movingTimeMM, movingTimeSS = movingTime.divmod(60)
movingTimeHH, movingTimeMM = movingTimeMM.divmod(60)
elapsedTime = Integer(strava['elapsedTime'])
elapsedTimeMM, elapsedTimeSS = elapsedTime.divmod(60)
elapsedTimeHH, elapsedTimeMM = elapsedTimeMM.divmod(60)
+
if @grconfig['strava_unit'] == 'imperial'
- unit = ['ft', 'mi', 'mph']
- strava['distance'] *= 0.000621371 #mi
- strava['averageSpeed'] *= 2.23694 #mi
- strava['maximumSpeed'] *= 0.000621371 #mi
- strava['elevationGain'] *= 3.28084 #ft
+ unit = ['ft', 'mi', 'mph']
+ strava['distance'] *= 0.000621371 #mi
+ strava['averageSpeed'] *= 2.23694 #mi
+ strava['maximumSpeed'] *= 0.000621371 #mi
+ strava['elevationGain'] *= 3.28084 #ft
elsif @grconfig['strava_unit'] == 'metric'
- unit = ['m', 'km', 'kph']
- strava['distance'] *= 0.001001535 #km
- strava['averageSpeed'] *= 3.611940299 #km
- strava['maximumSpeed'] *= 0.001000553 #km
+ unit = ['m', 'km', 'kph']
+ strava['distance'] *= 0.001001535 #km
+ strava['averageSpeed'] *= 3.611940299 #km
+ strava['maximumSpeed'] *= 0.001000553 #km
end
+
+ output = ''
output += "# Strava Ride - %.2f %s - %dh %dm %ds - %.1f %s - %s\n\n" % [strava['distance'], unit[1], movingTimeHH, movingTimeMM, movingTimeSS, strava['averageSpeed'], unit[2], strava['name']] unless strava['name'].nil?
output += "* **Description**: #{strava['description']}\n" unless strava['description'].nil?
output += "* **Distance**: %.2f %s\n" % [strava['distance'], unit[1]] unless strava['distance'].nil?
@@ -117,22 +118,23 @@ def parse_feed(rss_feed)
output += "* **Elapsed Time**: %02d:%02d:%02d\n" % [elapsedTimeHH, elapsedTimeMM, elapsedTimeSS] unless strava['elapsedTime'].nil?
output += "* **Moving Time**: %02d:%02d:%02d\n" % [movingTimeHH, movingTimeMM, movingTimeSS] unless strava['movingTime'].nil?
output += "* **Link**: http://app.strava.com/rides/#{rides['id']}\n\n"
+
options = {}
options['content'] = "#{output}\n\n#{tags}"
options['datestamp'] = date.utc.iso8601
options['starred'] = false
- # TODO: turn location into a Day One location
- options['uuid'] = %x{uuidgen}.gsub(/-/,'').strip
- sl = DayOne.new
- sl.to_dayone(options)
+ options['uuid'] = %x{uuidgen}.gsub(/-/,'').strip #TODO: turn location into a Day One location
+
+ DayOne.new.to_dayone(options)
else
break
end
}
rescue Exception => e
- p e
- raise "ERROR parsing Strava results from #{rss_feed}"
+ @log.error("ERROR parsing Strava results from #{rss_feed}")
+ raise e
end
+
return true
end
end
View
66 spec/plugins/fixtures/strava.yml
@@ -0,0 +1,66 @@
+---
+http_interactions:
+- request:
+ method: get
+ uri: https://www.strava.com/api/v3/athlete/activities?access_token=the_access_token
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - '*/*'
+ User-Agent:
+ - Ruby
+ Host:
+ - www.strava.com
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Content-Type:
+ - application/json; charset=utf-8
+ Status:
+ - '200'
+ X-Ratelimit-Limit:
+ - '600,30000'
+ X-Ratelimit-Usage:
+ - '1,4'
+ X-Ua-Compatible:
+ - IE=Edge,chrome=1
+ Content-Length:
+ - '1481'
+ Connection:
+ - keep-alive
+ body:
+ encoding: UTF-8
+ string: '[{"id":114100845,"resource_state":2,"external_id":null,"upload_id":null,"athlete":{"id":3880480,"resource_state":1},"name":"Afternoon
+ Walk","distance":3218.7,"moving_time":1894,"elapsed_time":1894,"total_elevation_gain":0.0,"type":"Walk","start_date":"2014-02-17T23:59:58Z","start_date_local":"2014-02-17T17:59:58Z","timezone":"(GMT-06:00)
+ America/Chicago","start_latlng":null,"end_latlng":null,"location_city":null,"location_state":null,"location_country":"United
+ States","start_latitude":null,"start_longitude":null,"achievement_count":0,"kudos_count":0,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a114100845","summary_polyline":null,"resource_state":2},"trainer":false,"commute":false,"manual":true,"private":false,"flagged":false,"gear_id":null,"average_speed":1.7,"max_speed":0.0,"calories":0,"truncated":null,"has_kudoed":false},{"id":113800428,"resource_state":2,"external_id":"3E31A010-63C0-45C2-B5F3-1102EBEE44CF","upload_id":124431086,"athlete":{"id":3880480,"resource_state":1},"name":"Afternoon
+ Walk","distance":3161.5,"moving_time":2018,"elapsed_time":2357,"total_elevation_gain":0.0,"type":"Walk","start_date":"2014-02-16T19:02:12Z","start_date_local":"2014-02-16T13:02:12Z","timezone":"(GMT-06:00)
+ America/Chicago","start_latlng":[41.85,-94.02],"end_latlng":[41.85,-94.02],"location_city":"Bouton","location_state":"IA","location_country":"United
+ States","start_latitude":41.85,"start_longitude":-94.02,"achievement_count":0,"kudos_count":0,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a113800428","summary_polyline":"_km~Fjlz|PbBsl@bLoAQ{EqK??w[rDf@f@bGtDf@P~WoKnAkCnn@","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"flagged":false,"gear_id":null,"average_speed":1.6,"max_speed":4.1,"calories":0,"truncated":null,"has_kudoed":false},{"id":113752860,"resource_state":2,"external_id":null,"upload_id":null,"athlete":{"id":3880480,"resource_state":1},"name":"Evening
+ Walk","distance":3252.8,"moving_time":1910,"elapsed_time":1894,"total_elevation_gain":0.0,"type":"Walk","start_date":"2014-02-16T01:00:33Z","start_date_local":"2014-02-15T19:00:33Z","timezone":"(GMT-06:00)
+ America/Chicago","start_latlng":null,"end_latlng":null,"location_city":null,"location_state":null,"location_country":"United
+ States","start_latitude":null,"start_longitude":null,"achievement_count":0,"kudos_count":0,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a113752860","summary_polyline":null,"resource_state":2},"trainer":false,"commute":false,"manual":true,"private":false,"flagged":false,"gear_id":null,"average_speed":1.7,"max_speed":0.0,"calories":0,"truncated":null,"has_kudoed":false},{"id":113076174,"resource_state":2,"external_id":"D59F06A8-7387-4AD3-9C76-EF39B4813111","upload_id":123558962,"athlete":{"id":3880480,"resource_state":1},"name":"Lunch
+ Walk","distance":4484.5,"moving_time":2587,"elapsed_time":2587,"total_elevation_gain":0.0,"type":"Walk","start_date":"2014-02-13T18:41:26Z","start_date_local":"2014-02-13T12:41:26Z","timezone":"(GMT-06:00)
+ America/Chicago","start_latlng":[41.85,-94.02],"end_latlng":[41.85,-94.02],"location_city":"Bouton","location_state":"IA","location_country":"United
+ States","start_latitude":41.85,"start_longitude":-94.02,"achievement_count":0,"kudos_count":0,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a113076174","summary_polyline":"_km~Ffnz|PRs]bBkMg@s]{aASnbARRr]oAfJ{@v`@","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"flagged":false,"gear_id":null,"average_speed":1.7,"max_speed":3.1,"calories":0,"truncated":null,"has_kudoed":false},{"id":112905173,"resource_state":2,"external_id":"6C0D08FC-189F-4AD9-AED3-00D7C55C799C","upload_id":123352438,"athlete":{"id":3880480,"resource_state":1},"name":"Afternoon
+ Walk","distance":3384.6,"moving_time":2014,"elapsed_time":2014,"total_elevation_gain":0.0,"type":"Walk","start_date":"2014-02-12T21:11:04Z","start_date_local":"2014-02-12T15:11:04Z","timezone":"(GMT-06:00)
+ America/Chicago","start_latlng":[41.85,-94.02],"end_latlng":[41.85,-94.02],"location_city":"Bouton","location_state":"IA","location_country":"United
+ States","start_latitude":41.85,"start_longitude":-94.02,"achievement_count":0,"kudos_count":0,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a112905173","summary_polyline":"_km~Fznz|PRw`@nAkMpK{@?{EqK{@S_XrDg@z@bGfJf@RbQeERUbG{JRcBnn@","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"flagged":false,"gear_id":null,"average_speed":1.7,"max_speed":7.0,"calories":0,"truncated":null,"has_kudoed":false},{"id":112702592,"resource_state":2,"external_id":"C8238E5D-837F-4A95-B5C8-2E60E1842758","upload_id":123116909,"athlete":{"id":3880480,"resource_state":1},"name":"Afternoon
+ Walk","distance":3349.9,"moving_time":1938,"elapsed_time":1938,"total_elevation_gain":0.0,"type":"Walk","start_date":"2014-02-11T21:30:08Z","start_date_local":"2014-02-11T15:30:08Z","timezone":"(GMT-06:00)
+ America/Chicago","start_latlng":[41.85,-94.02],"end_latlng":[41.85,-94.02],"location_city":"Bouton","location_state":"IA","location_country":"United
+ States","start_latitude":41.85,"start_longitude":-94.02,"achievement_count":0,"kudos_count":0,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a112702592","summary_polyline":"_km~Ffnz|PRg^nAgOpKoA?gE}J?SoFbQS?sIoAoA?gEsNRRrg@oAbG{@v`@","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"flagged":false,"gear_id":null,"average_speed":1.7,"max_speed":2.9,"calories":0,"truncated":null,"has_kudoed":false},{"id":112251289,"resource_state":2,"external_id":"28631CE6-F79A-4A06-ADD7-9F43DED34719","upload_id":122594361,"athlete":{"id":3880480,"resource_state":1},"name":"Afternoon
+ Walk","distance":2898.8,"moving_time":1699,"elapsed_time":1699,"total_elevation_gain":0.0,"type":"Walk","start_date":"2014-02-09T19:10:57Z","start_date_local":"2014-02-09T13:10:57Z","timezone":"(GMT-06:00)
+ America/Chicago","start_latlng":[41.85,-94.02],"end_latlng":[41.85,-94.02],"location_city":"Bouton","location_state":"IA","location_country":"United
+ States","start_latitude":41.85,"start_longitude":-94.02,"achievement_count":0,"kudos_count":0,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a112251289","summary_polyline":"skm~Ffnz|PvBon@zJSToFdEg@SoFqDSUkRsDR?nFgER?v`@{@vG{@n_@","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"flagged":false,"gear_id":null,"average_speed":1.7,"max_speed":2.5,"calories":0,"truncated":null,"has_kudoed":false},{"id":111773831,"resource_state":2,"external_id":"77F8DFC8-A154-40FD-B82F-A16C07CB468B","upload_id":122077587,"athlete":{"id":3880480,"resource_state":1},"name":"Afternoon
+ Walk","distance":2936.9,"moving_time":1684,"elapsed_time":1768,"total_elevation_gain":0.0,"type":"Walk","start_date":"2014-02-07T19:48:46Z","start_date_local":"2014-02-07T13:48:46Z","timezone":"(GMT-06:00)
+ America/Chicago","start_latlng":[41.85,-94.02],"end_latlng":[41.85,-94.02],"location_city":"Bouton","location_state":"IA","location_country":"United
+ States","start_latitude":41.85,"start_longitude":-94.02,"achievement_count":0,"kudos_count":0,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a111773831","summary_polyline":"_km~Fnoz|PvBwo@fJSf@cGrDS?cQoA{@SoFsNf@Rzh@oAvGg@b`@","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"flagged":false,"gear_id":null,"average_speed":1.7,"max_speed":3.5,"calories":0,"truncated":null,"has_kudoed":false}]'
+ http_version:
+ recorded_at: Tue, 18 Feb 2014 13:01:34 GMT
+recorded_with: VCR 2.8.0
View
12 spec/plugins/mock_slogger.rb
@@ -0,0 +1,12 @@
+class Slogger
+ RSpec::Mocks::setup(self)
+ $slog = double.as_null_object
+
+ attr_accessor :config, :log
+
+ def initialize
+ RSpec::Mocks::setup(self)
+ @config = {}
+ @log = double.as_null_object
+ end
+end
View
19 spec/plugins/spec_helper.rb
@@ -1,17 +1,16 @@
+$:.unshift File.join(File.dirname(__FILE__))
+$:.unshift File.join(File.dirname(__FILE__), '..', '..', 'plugins')
$:.unshift File.join(File.dirname(__FILE__), '..', '..', 'plugins_disabled')
-require 'rspec/mocks/standalone'
-$slog = double.as_null_object
+require 'mock_slogger'
+require 'vcr'
-RSpec.configure do |config|
- config.color_enabled = true
+VCR.configure do |c|
+ c.cassette_library_dir = File.join(File.dirname(__FILE__), 'fixtures')
+ c.hook_into :webmock
end
-class Slogger
- def initialize
- RSpec::Mocks::setup(self)
- @config = {}
- @log = double.as_null_object
- end
+RSpec.configure do |config|
+ config.color_enabled = true
end
View
24 spec/plugins/stravalogger_spec.rb
@@ -3,10 +3,30 @@
describe StravaLogger do
let(:strava) {
- StravaLogger.new
+ StravaLogger.new.tap do |strava|
+ strava.config = {
+ 'StravaLogger' => {
+ }
+ }
+ end
}
- it "grabs the feed and posts new entries" do
+ it 'warns if config not found' do
+ strava.config.delete('StravaLogger')
+ strava.log.should_receive(:warn).with('Strava has not been configured or is invalid, please edit your slogger_config file.')
strava.do_log
end
+
+ it 'warns if access_token is not set' do
+ strava.config['StravaLogger']['strava_access_token'] = ' '
+ strava.log.should_receive(:warn).with('Strava access token has not been configured, please edit your slogger_config file.')
+ strava.do_log
+ end
+
+ it 'grabs the feed' do
+ VCR.use_cassette('strava') do
+ strava.config['StravaLogger']['strava_access_token'] = 'the_access_token'
+ strava.do_log
+ end
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.