run_keeper 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Tate Johnson <tate@tatey.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -0,0 +1,83 @@
1
+ # RunKeeper Client API
2
+
3
+ ## Installation
4
+
5
+ RunKeeper is available from rubygems.org.
6
+
7
+ ``` sh
8
+ $ gem install run_keeper
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ``` ruby
14
+ require 'run_keeper'
15
+
16
+ runkeeper = RunKeeper.new 'client_id', 'client_secret'
17
+ runkeeper.authorize_url 'http://your.com/callback/url'
18
+ # => 'https://runkeeper.com/apps/authorize?response_type=code&client_id=client_id&redirect_uri=http%3A%2F%2Fyour.com%2Fcallback%2Furl'
19
+
20
+ runkeeper.token = runkeeper.get_token 'authorization_code_value', 'http://your.com/callback/url'
21
+
22
+ # return the users profile
23
+ runkeeper.profile
24
+ # => RunKeeper::Profile
25
+ ```
26
+
27
+ ### Fitness Activities
28
+
29
+ Fitness Activities (http://developer.runkeeper.com/healthgraph/fitness-activities) are a list of past activities completed by a user. Calling `fitness_activities` without any options will get all activities since the user signed up to RunKeeper.
30
+
31
+ ``` ruby
32
+ runkeeper.fitness_activities
33
+ # => [RunKeeper::Activity, ...]
34
+ ```
35
+
36
+ Fitness Activities takes a series of arguments in the form of an options hash. Supported arguments: `start`, `finish` and `limit`:
37
+
38
+ ``` ruby
39
+ # Get all activities starting from the 1st Jan, 2011
40
+ runkeeper.fitness_activities(:start => '2011-01-01')
41
+
42
+ # Get all activities between 1st Jan, 2011 and 1st Feb, 2011
43
+ runkeeper.fitness_activities(:start => '2011-01-01', :finish => '2011-02-01')
44
+
45
+ # Get the last 10 activities
46
+ runkeeper.fitness_activities(:limit => 10)
47
+ ```
48
+
49
+ ## Dates
50
+
51
+ RunKeeper doesn't store users time zones, they rely on the device sending the information for the correct time. Because of this I have decided to format all dates as UTC.
52
+
53
+ ## Using RunKeeper mock requests in your App
54
+
55
+ While developing RunKeeper a few mocked responses were used and have been made available for your test suite.
56
+
57
+ ``` ruby
58
+ # helper.rb
59
+ require 'run_keeper/mock_requests'
60
+ include MockRequests
61
+ ```
62
+
63
+ ## Errors
64
+
65
+ All errors are a wrapper around the `OAuth2::Error` class. Errors will be raised on all requests that do not return a 200 or 304 response code.
66
+
67
+ ## Final Notes
68
+
69
+ Do not be afraid to open up the source code and peek inside. The library is built on top of the wonderful [OAuth2](https://github.com/intridea/oauth2/) gem and should be fairly easy to debug.
70
+
71
+ ## Contributing
72
+
73
+ Patches welcome!
74
+
75
+ 1. Fork the repository
76
+ 2. Create a topic branch
77
+ 3. Write tests and make changes
78
+ 4. Make sure the tests pass by running `rake`
79
+ 5. Push and send a pull request on GitHub
80
+
81
+ ## Copyright
82
+
83
+ Copyright © 2011 Tim Cooper. RunKeeper is released under the MIT license. See LICENSE for details.
data/Rakefile CHANGED
@@ -1 +1,24 @@
1
- require 'bundler/gem_tasks'
1
+ begin
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ rescue LoadError
5
+ raise 'Could not load the bundler gem. Install it with `gem install bundler`.'
6
+ end
7
+
8
+ begin
9
+ Bundler.setup
10
+ rescue Bundler::GemNotFound
11
+ raise RuntimeError, "Bundler couldn't find some gems." +
12
+ "Did you run `bundle install`?"
13
+ end
14
+
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ require 'rake/testtask'
18
+
19
+ Rake::TestTask.new(:test) do |test|
20
+ test.libs << 'test'
21
+ test.pattern = 'test/**/*_test.rb'
22
+ end
23
+
24
+ task :default => :test
data/lib/run_keeper.rb CHANGED
@@ -1,13 +1,17 @@
1
- require "active_support"
1
+ require "date"
2
2
  require "oauth2"
3
- require "run_keeper/activity"
4
3
  require "run_keeper/base"
4
+ require "run_keeper/activity"
5
+ require "run_keeper/activity_request"
5
6
  require "run_keeper/profile"
7
+ require "run_keeper/request"
6
8
  require "run_keeper/user"
7
9
  require "run_keeper/version"
8
10
 
9
11
  module RunKeeper
10
- def self.new client_id, client_secret
11
- Base.new client_id, client_secret
12
+ def self.new client_id, client_secret, token = nil
13
+ Request.new client_id, client_secret, token
12
14
  end
15
+
16
+ class Error < OAuth2::Error; end
13
17
  end
@@ -1,20 +1,16 @@
1
1
  module RunKeeper
2
- class Activity
3
- attr_accessor :type, :total_distance, :duration, :uri
2
+ class Activity < Base
3
+ attr_accessor :type, :total_distance, :duration, :uri, :id
4
4
  attr_reader :start_time
5
5
 
6
6
  def initialize attributes = {}
7
- attributes.each do |attribute, value|
8
- send :"#{attribute}=", value
9
- end
10
- end
11
-
12
- def id
13
- uri.split('/').last.to_i
7
+ super
8
+ self.id = uri.split('/').last.to_i if uri
14
9
  end
15
10
 
16
11
  def start_time= value
17
- @start_time = Time.zone.parse value
12
+ datetime = DateTime.parse value
13
+ @start_time = Time.utc datetime.year, datetime.month, datetime.day, datetime.hour, datetime.min, datetime.sec
18
14
  end
19
15
  end
20
16
  end
@@ -0,0 +1,48 @@
1
+ module RunKeeper
2
+ class ActivityRequest
3
+ def initialize runkeeper, options
4
+ @runkeeper, @options = runkeeper, parse_options(options)
5
+ end
6
+
7
+ def get_activities
8
+ @options[:limit] ? limit_results(request) : request
9
+ end
10
+
11
+ private
12
+ def limit_results activities
13
+ activities[0..@options[:limit] - 1]
14
+ end
15
+
16
+ def request activities = nil
17
+ response = @runkeeper.request('fitness_activities', @options[:params])
18
+ activities = response.parsed['items'].map { |activity| Activity.new(activity) }
19
+
20
+ if @options[:start]
21
+ activities -= activities.reject { |activity| (activity.start_time > @options[:start]) && (activity.start_time < @options[:finish]) }
22
+ end
23
+
24
+ if response.parsed['next']
25
+ if @options[:limit]
26
+ if activities.size < @options[:limit]
27
+ @options[:params].update(:page => response.parsed['next'].split('=').last)
28
+ activities + request(activities)
29
+ else
30
+ activities
31
+ end
32
+ else
33
+ @options[:params].update(:page => response.parsed['next'].split('=').last)
34
+ activities + request(activities)
35
+ end
36
+ else
37
+ activities
38
+ end
39
+ end
40
+
41
+ def parse_options options
42
+ options[:params] = {}
43
+ options[:start] = Time.utc(*options[:start].split('-')) if options[:start]
44
+ options[:finish] = options[:start] && options[:finish] ? Time.utc(*options[:finish].split('-'), 23, 59, 59) : Time.now.utc
45
+ options
46
+ end
47
+ end
48
+ end
@@ -1,48 +1,9 @@
1
1
  module RunKeeper
2
2
  class Base
3
- HEADERS = {
4
- 'fitness_activities' => 'application/vnd.com.runkeeper.FitnessActivityFeed+json',
5
- 'profile' => 'application/vnd.com.runkeeper.Profile+json',
6
- 'user' => 'application/vnd.com.runkeeper.User+json'
7
- }
8
-
9
- attr_reader :token
10
-
11
- def initialize client_id, client_secret, token
12
- @client_id, @client_secret, @token = client_id, client_secret, token
13
- user
14
- end
15
-
16
- def request endpoint
17
- response = access_token.get user.send(endpoint), :headers => {'Accept' => HEADERS[endpoint]}, :parse => :json
18
- end
19
-
20
- def fitness_activities
21
- response = request 'fitness_activities'
22
- response.parsed['items'].inject([]) do |activities, activity|
23
- activities << RunKeeper::Activity.new(activity)
3
+ def initialize attributes = {}
4
+ attributes.each do |attribute, value|
5
+ send :"#{attribute}=", value if respond_to? :"#{attribute}="
24
6
  end
25
7
  end
26
-
27
- def profile
28
- response = request 'profile'
29
- RunKeeper::Profile.new response.parsed.merge(:userid => user.userid)
30
- end
31
-
32
- def user
33
- @user ||= begin
34
- response = access_token.get '/user', :headers => {'Accept' => HEADERS['user']}, :parse => :json
35
- User.new response.parsed
36
- end
37
- end
38
-
39
- private
40
- def access_token
41
- OAuth2::AccessToken.new client, token
42
- end
43
-
44
- def client
45
- OAuth2::Client.new @client_id, @client_secret, :site => 'https://api.runkeeper.com', :authorize_url => '/apps/authorize', :token_url => '/apps/token', :raise_errors => false
46
- end
47
8
  end
48
9
  end
@@ -0,0 +1,61 @@
1
+ module MockRequests
2
+ def stub_successful_runkeeper_fitness_activities_request
3
+ stub_successful_runkeeper_user_request
4
+ stub_successful_runkeeper_fitness_activities_page_2_request
5
+ stub_runkeeper_fitness_activities_request.to_return :status => 200, :body => {"size" => "4", "items" => [{"type" => "Running", "start_time" => "Thu, 25 Aug 2011 17:41:28", "total_distance" => "5492.22273600001", "duration" => "1743.946", "uri" => "/activities/39"}, {"type" => "Running", "start_time" => "Thu, 1 Sep 2011 17:41:28", "total_distance" => "5492.22273600001", "duration" => "1743.946", "uri" => "/activities/40"}, {"type" => "Running", "start_time" => "Fri, 2 Sep 2011 17:41:28", "total_distance" => "5492.22273600001", "duration" => "2090.123", "uri" => "/activities/41"}, {"type" => "Running", "start_time" => "Wed, 7 Sep 2011 17:41:28", "total_distance" => "5492.22273600001", "duration" => "1743.946", "uri" => "/activities/42"}], "next" => "/fitnessActivities?page=1"}, :headers => {"content-type" => "application/vnd.com.runkeeper.FitnessActivityFeed+json;charset=ISO-8859-1"}
6
+ end
7
+
8
+ def stub_successful_runkeeper_profile_request
9
+ stub_successful_runkeeper_user_request
10
+ stub_runkeeper_profile_request.to_return :status => 200, :body => {"name" => "John Doe", "location" => "Anytown, USA", "athlete_type" => "Runner", "goal" => "To get off the couch", "gender" => "M", "birthday" => "Sat, Jan 1 2011 00:00:00", "elite" => "true", "profile" => "http://www.runkeeper.com/user/JohnDoe", "small_picture" => "http://www.runkeeper.com/user/JohnDoe/small.jpg", "normal_picture" => "http://www.runkeeper.com/user/JohnDoe/normal.jpg", "medium_picture" => "http://www.runkeeper.com/user/JohnDoe/medium.jpg", "large_picture" => "http://www.runkeeper.com/user/JohnDoe/large.jpg"}, :headers => {"content-type" => "application/vnd.com.runkeeper.profile+json;charset=ISO-8859-1"}
11
+ end
12
+
13
+ def stub_successful_runkeeper_token_request
14
+ stub_runkeeper_token_request.to_return :status => 200, :body => {'access_token' => 'my_token', 'token_type' => 'Bearer'}, :headers => {"content-type" => "application/json;charset=ISO-8859-1"}
15
+ end
16
+
17
+ def stub_successful_runkeeper_user_request
18
+ stub_runkeeper_user_request.to_return :status => 200, :body => {"userID" => /\d+/, "profile" => "/profile", "settings" => "/settings", "fitness_activities" => "/fitnessActivities", "background_activities" => "/backgroundActivities", "sleep" => "/sleep", "nutrition" => "/nutrition", "weight" => "/weight", "general_measurements" => "/generalMeasurements", "diabetes" => "/diabetes", "records" => "/records", "team" => "/team", "strength_training_activities" => "/strengthTrainingActivities"}, :headers => {'content-type' => 'application/vnd.com.runkeeper.user+json;charset=ISO-8859-1'}
19
+ end
20
+
21
+ def stub_unsuccessful_runkeeper_profile_request
22
+ stub_successful_runkeeper_user_request
23
+ stub_runkeeper_profile_request.to_return :status => 500, :body => {}, :headers => {}
24
+ end
25
+
26
+ def stub_unsuccessful_runkeeper_token_request
27
+ stub_runkeeper_token_request.to_return :status => 500, :body => {}, :headers => {}
28
+ end
29
+
30
+ def stub_unsuccessful_runkeeper_user_request
31
+ stub_runkeeper_user_request.to_return :status => 500, :body => {}, :headers => {}
32
+ end
33
+
34
+ private
35
+ def stub_successful_runkeeper_fitness_activities_page_2_request
36
+ stub_request(:get, "https://api.runkeeper.com/fitnessActivities?page=1").
37
+ with(:headers => {'Accept' => 'application/vnd.com.runkeeper.FitnessActivityFeed+json', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => /Bearer \w+/, 'User-Agent'=>'Ruby'}).
38
+ to_return(:status => 200, :body => {"size" => "2", "items" => [{"type" => "Running", "start_time" => "Tue, 23 Aug 2011 17:41:28", "total_distance" => "5492.22273600001", "duration" => "1743.946", "uri" => "/activities/38"}, {"type" => "Running", "start_time" => "Sun, 21 Aug 2011 17:41:28", "total_distance" => "5492.22273600001", "duration" => "1743.946", "uri" => "/activities/37"}]}, :headers => {"content-type" => "application/vnd.com.runkeeper.FitnessActivityFeed+json;charset=ISO-8859-1"})
39
+ end
40
+
41
+ def stub_runkeeper_fitness_activities_request
42
+ stub_request(:get, "https://api.runkeeper.com/fitnessActivities").
43
+ with :headers => {'Accept'=>'application/vnd.com.runkeeper.FitnessActivityFeed+json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => /Bearer \w+/, 'User-Agent'=>'Ruby'}
44
+ end
45
+
46
+ def stub_runkeeper_profile_request
47
+ stub_request(:get, "https://api.runkeeper.com/profile").
48
+ with :headers => {'Accept'=>'application/vnd.com.runkeeper.Profile+json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => /Bearer \w+/, 'User-Agent'=>'Ruby'}
49
+ end
50
+
51
+ def stub_runkeeper_token_request
52
+ stub_request(:post, "https://runkeeper.com/apps/token").
53
+ with :body => {"grant_type" => "authorization_code", "code" => /\w+/, "client_id" => /\w+/, "client_secret" => /\w+/, "redirect_uri" => /\w+/},
54
+ :headers => {'Accept' => '*/*', 'Content-Type' => 'application/x-www-form-urlencoded', 'User-Agent' => 'Ruby'}
55
+ end
56
+
57
+ def stub_runkeeper_user_request
58
+ stub_request(:get, "https://api.runkeeper.com/user").
59
+ with :headers => {'Accept'=>'application/vnd.com.runkeeper.User+json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization' => /Bearer \w+/, 'User-Agent'=>'Ruby'}
60
+ end
61
+ end
@@ -1,21 +1,20 @@
1
1
  module RunKeeper
2
- class Profile
2
+ class Profile < Base
3
3
  attr_accessor :name, :location, :athlete_type, :goal, :gender, :birthday, :elite, :profile, :small_picture, :normal_picture, :medium_picture, :large_picture, :userid
4
4
  attr_reader :username
5
5
 
6
6
  def initialize attributes = {}
7
- attributes.each do |attribute, value|
8
- send :"#{attribute}=", value
9
- end
7
+ super attributes
10
8
  self.username = profile
11
9
  end
12
10
 
13
11
  def birthday= value
14
- @birthday = Time.zone.parse value
12
+ datetime = DateTime.parse value
13
+ @birthday = Time.utc datetime.year, datetime.month, datetime.day, datetime.hour, datetime.min, datetime.sec
15
14
  end
16
15
 
17
16
  def username= profile
18
- @username = profile.split('/').last
17
+ @username = profile.split('/').last if profile
19
18
  end
20
19
  end
21
20
  end
@@ -0,0 +1,62 @@
1
+ module RunKeeper
2
+ class Request
3
+ HEADERS = {
4
+ 'fitness_activities' => 'application/vnd.com.runkeeper.FitnessActivityFeed+json',
5
+ 'profile' => 'application/vnd.com.runkeeper.Profile+json',
6
+ 'user' => 'application/vnd.com.runkeeper.User+json'
7
+ }
8
+
9
+ def initialize client_id, client_secret, token
10
+ @client_id, @client_secret, @token = client_id, client_secret, token
11
+ end
12
+
13
+ def authorize_url redirect_uri
14
+ client('https://runkeeper.com').auth_code.authorize_url :redirect_uri => redirect_uri
15
+ end
16
+
17
+ def fitness_activities options = {}
18
+ ActivityRequest.new(self, options).get_activities
19
+ end
20
+
21
+ def get_token code, redirect_uri
22
+ client('https://runkeeper.com').auth_code.get_token(code, :redirect_uri => redirect_uri).token
23
+ rescue OAuth2::Error => e
24
+ raise Error.new(e.response)
25
+ end
26
+
27
+ def profile
28
+ Profile.new request('profile').parsed.merge(:userid => @user.userid)
29
+ end
30
+
31
+ def request endpoint, params = {}
32
+ response = access_token.get(user.send(endpoint), :headers => {'Accept' => HEADERS[endpoint]}, :parse => :json) do |request|
33
+ request.params = params
34
+ end
35
+ parse_response response
36
+ end
37
+
38
+ def user
39
+ @user ||= begin
40
+ response = access_token.get('/user', :headers => {'Accept' => HEADERS['user']}, :parse => :json)
41
+ User.new parse_response(response).parsed
42
+ end
43
+ end
44
+
45
+ private
46
+ def access_token
47
+ OAuth2::AccessToken.new client, @token
48
+ end
49
+
50
+ def client site = 'https://api.runkeeper.com'
51
+ OAuth2::Client.new @client_id, @client_secret, :site => site, :authorize_url => '/apps/authorize', :token_url => '/apps/token', :raise_errors => false
52
+ end
53
+
54
+ def parse_response response
55
+ if [200, 304].include? response.status
56
+ response
57
+ else
58
+ raise Error.new(response)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,12 +1,15 @@
1
1
  module RunKeeper
2
- class User
3
- attr_accessor :userID, :profile, :settings, :fitness_activities, :background_activities, :sleep, :nutrition, :weight, :general_measurements, :diabetes, :records, :team, :strength_training_activities
2
+ class User < Base
3
+ attr_accessor :profile, :settings, :fitness_activities, :background_activities, :sleep, :nutrition, :weight, :general_measurements, :diabetes, :records, :team, :strength_training_activities
4
+ attr_reader :userid
4
5
 
5
6
  def initialize attributes = {}
6
- attributes.each do |attribute, value|
7
- send :"#{attribute}=", value
8
- end
7
+ super attributes
8
+ self.userid = attributes['userID'] if attributes['userID']
9
+ end
10
+
11
+ def userid= value
12
+ @userid = value
9
13
  end
10
- alias :userid :userID
11
14
  end
12
15
  end
@@ -1,3 +1,3 @@
1
1
  module RunKeeper
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/run_keeper.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
17
  s.require_paths = ["lib"]
18
18
 
19
- s.add_dependency 'activesupport', '~> 3.1.0'
19
+ s.add_development_dependency 'rake', '~> 0.9.2'
20
+ s.add_development_dependency 'webmock', '~> 1.7.6'
20
21
  s.add_dependency 'oauth2', '~> 0.5.0'
21
22
  end
@@ -0,0 +1,19 @@
1
+ require 'helper'
2
+
3
+ class ActivityRequestTest < MiniTest::Unit::TestCase
4
+ def test_limit_request_returns_subset_of_results
5
+ assert_equal 1, ActivityRequest.new(Object.new, :limit => 1).send(:limit_results, [1, 2, 3]).size
6
+ end
7
+
8
+ def test_parse_options_has_default_keys
9
+ assert_equal [:params, :finish].sort, ActivityRequest.new(Object.new, {}).send(:parse_options, {}).keys.sort
10
+ end
11
+
12
+ def test_parse_options_includes_limit
13
+ assert_equal [:limit, :params, :finish].sort, ActivityRequest.new(Object.new, {:limit => 1}).send(:parse_options, {:limit => 1}).keys.sort
14
+ end
15
+
16
+ def test_parse_options_includes_start
17
+ assert_equal [:params, :start, :finish].sort, ActivityRequest.new(Object.new, {:start => '2011-01-01'}).send(:parse_options, {:start => '2011-01-01'}).keys.sort
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'helper'
2
+
3
+ class ActivityTest < MiniTest::Unit::TestCase
4
+ def test_id_is_nil_when_no_uri
5
+ assert_nil Activity.new.id
6
+ end
7
+
8
+ def test_id_returns_an_integer_from_uri
9
+ assert_instance_of Fixnum, Activity.new('uri' => '/profile/12345').id
10
+ end
11
+
12
+ def test_id_returns_id_from_uri
13
+ assert_equal 12345, Activity.new('uri' => '/profile/12345').id
14
+ end
15
+
16
+ def test_start_time_is_UTC
17
+ assert Activity.new('start_time' => 'Thu, 1 Sep 2011 17:41:28').start_time.utc?
18
+ end
19
+ end
data/test/base_test.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class UserTest < MiniTest::Unit::TestCase
4
+ def test_initailization_ignores_unknown_attributes
5
+ refute_includes Activity.new('foo' => 'bar').instance_variables, :@foo
6
+ end
7
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'minitest/autorun'
2
+ require 'run_keeper'
3
+ require 'run_keeper/mock_requests'
4
+ require 'webmock/minitest'
5
+
6
+ include RunKeeper
7
+ include MockRequests
@@ -0,0 +1,21 @@
1
+ require 'helper'
2
+
3
+ class ProfileTest < MiniTest::Unit::TestCase
4
+ def test_initailization_sets_username_if_profile
5
+ profile = Profile.new('profile' => 'http://www.runkeeper.com/user/JohnDoe')
6
+ assert_includes profile.instance_variables, :@username
7
+ assert_equal 'JohnDoe', profile.username
8
+ end
9
+
10
+ def test_initailization_sets_username_to_nil_if_no_profile
11
+ assert_nil Profile.new.username
12
+ end
13
+
14
+ def test_birthday_is_UTC
15
+ assert Profile.new('birthday' => 'Sat, Jan 1 2011 00:00:00').birthday.utc?
16
+ end
17
+
18
+ def test_birthday_is_nil_if_not_provided
19
+ assert_nil Profile.new.birthday
20
+ end
21
+ end
@@ -0,0 +1,108 @@
1
+ require 'helper'
2
+
3
+ class RequestTest < MiniTest::Unit::TestCase
4
+ def test_initialization_sets_client_id_and_client_secret
5
+ assert_includes runkeeper.instance_variables, :@client_id
6
+ assert_includes runkeeper.instance_variables, :@client_secret
7
+ assert_includes runkeeper.instance_variables, :@token
8
+ end
9
+
10
+ def test_authorize_url_creates_a_valid_runkeeper_authorize_url
11
+ assert_equal 'https://runkeeper.com/apps/authorize?response_type=code&client_id=client_id&redirect_uri=http%3A%2F%2Fgoogle.com', runkeeper(nil).authorize_url('http://google.com')
12
+ end
13
+
14
+ def test_get_token_returns_a_token
15
+ stub_successful_runkeeper_token_request
16
+ assert_equal 'my_token', runkeeper(nil).get_token('code', 'http://google.com')
17
+ end
18
+
19
+ def test_get_token_raises_an_error_when_it_fails
20
+ stub_unsuccessful_runkeeper_token_request
21
+ assert_raises RunKeeper::Error do
22
+ runkeeper(nil).get_token('code', 'http://google.com')
23
+ end
24
+ end
25
+
26
+ def test_fitness_activities_with_a_valid_token_returns_an_array
27
+ stub_successful_runkeeper_fitness_activities_request
28
+ assert_instance_of Array, runkeeper.fitness_activities(:limit => 1)
29
+ end
30
+
31
+ def test_fitness_activities_with_a_valid_token_returns_runkeeper_activities
32
+ stub_successful_runkeeper_fitness_activities_request
33
+ assert_instance_of RunKeeper::Activity, runkeeper.fitness_activities(:limit => 1).first
34
+ end
35
+
36
+ def test_fitness_activities_with_limit
37
+ stub_successful_runkeeper_fitness_activities_request
38
+ assert_equal 1, runkeeper.fitness_activities(:limit => 1).size
39
+ end
40
+
41
+ def test_fitness_activities_without_arguments
42
+ stub_successful_runkeeper_fitness_activities_request
43
+ assert_equal 6, runkeeper.fitness_activities.size
44
+ end
45
+
46
+ def test_fitness_activities_by_start_date_range
47
+ stub_successful_runkeeper_fitness_activities_request
48
+ assert_equal 5, runkeeper.fitness_activities(:start => '2011-08-22').size
49
+ end
50
+
51
+ def test_fitness_activities_by_date_range
52
+ stub_successful_runkeeper_fitness_activities_request
53
+ assert_equal 4, runkeeper.fitness_activities(:start => '2011-08-22', :finish => '2011-09-02').size
54
+ end
55
+
56
+ def test_fitness_activities_by_date_range_and_limit
57
+ stub_successful_runkeeper_fitness_activities_request
58
+ assert_equal 2, runkeeper.fitness_activities(:start => '2011-08-22', :finish => '2011-09-02', :limit => 2).size
59
+ end
60
+
61
+ def test_fitness_activities_by_date_range_and_limit_where_limit_is_greater_than_returned_results
62
+ stub_successful_runkeeper_fitness_activities_request
63
+ assert_equal 6, runkeeper.fitness_activities(:start => '2011-08-01', :limit => 7).size
64
+ end
65
+
66
+ def test_user_returns_an_instance_of_user
67
+ stub_successful_runkeeper_user_request
68
+ assert_instance_of RunKeeper::User, runkeeper.user
69
+ end
70
+
71
+ def test_profile_returns_and_instance_of_profile
72
+ stub_successful_runkeeper_profile_request
73
+ assert_instance_of RunKeeper::Profile, runkeeper.profile
74
+ end
75
+
76
+ def test_parse_response_raises_exception_unless_response_status_is_200_or_304
77
+ assert_raises RunKeeper::Error do
78
+ runkeeper.send :parse_response, mock_response(400)
79
+ end
80
+ end
81
+
82
+ def test_parse_response_returns_response_when_status_200
83
+ response = mock_response 200
84
+ assert_equal response, runkeeper.send(:parse_response, response)
85
+ end
86
+
87
+ def test_parse_response_returns_response_when_status_304
88
+ response = mock_response 304
89
+ assert_equal response, runkeeper.send(:parse_response, response)
90
+ end
91
+
92
+ private
93
+ def mock_response status
94
+ Object.new.tap do |response|
95
+ response.extend Module.new {
96
+ define_method :status do
97
+ status
98
+ end
99
+ def error=(value); end
100
+ def parsed; end
101
+ }
102
+ end
103
+ end
104
+
105
+ def runkeeper token = 'valid_token'
106
+ Request.new 'client_id', 'client_secret', token
107
+ end
108
+ end
data/test/user_test.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'helper'
2
+
3
+ class UserTest < MiniTest::Unit::TestCase
4
+ def test_initailization_sets_userid_if_userID_attribute_provided
5
+ user = User.new('userID' => '123')
6
+ assert_includes user.instance_variables, :@userid
7
+ assert_equal '123', user.userid
8
+ end
9
+
10
+ def test_initailization_does_not_set_userid_if_userID_not_provided
11
+ refute_includes User.new.instance_variables, :@userid
12
+ end
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: run_keeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,23 +9,34 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-07 00:00:00.000000000 +10:00
12
+ date: 2011-09-13 00:00:00.000000000 +10:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: activesupport
17
- requirement: &70142886557480 !ruby/object:Gem::Requirement
16
+ name: rake
17
+ requirement: &70113469141360 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: 3.1.0
23
- type: :runtime
22
+ version: 0.9.2
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *70113469141360
26
+ - !ruby/object:Gem::Dependency
27
+ name: webmock
28
+ requirement: &70113469140860 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.7.6
34
+ type: :development
24
35
  prerelease: false
25
- version_requirements: *70142886557480
36
+ version_requirements: *70113469140860
26
37
  - !ruby/object:Gem::Dependency
27
38
  name: oauth2
28
- requirement: &70142886556980 !ruby/object:Gem::Requirement
39
+ requirement: &70113469140400 !ruby/object:Gem::Requirement
29
40
  none: false
30
41
  requirements:
31
42
  - - ~>
@@ -33,7 +44,7 @@ dependencies:
33
44
  version: 0.5.0
34
45
  type: :runtime
35
46
  prerelease: false
36
- version_requirements: *70142886556980
47
+ version_requirements: *70113469140400
37
48
  description: Run Keeper API client
38
49
  email:
39
50
  - coop@latrobest.com
@@ -43,15 +54,26 @@ extra_rdoc_files: []
43
54
  files:
44
55
  - .gitignore
45
56
  - Gemfile
57
+ - LICENSE
46
58
  - README.md
47
59
  - Rakefile
48
60
  - lib/run_keeper.rb
49
61
  - lib/run_keeper/activity.rb
62
+ - lib/run_keeper/activity_request.rb
50
63
  - lib/run_keeper/base.rb
64
+ - lib/run_keeper/mock_requests.rb
51
65
  - lib/run_keeper/profile.rb
66
+ - lib/run_keeper/request.rb
52
67
  - lib/run_keeper/user.rb
53
68
  - lib/run_keeper/version.rb
54
69
  - run_keeper.gemspec
70
+ - test/activity_request_test.rb
71
+ - test/activity_test.rb
72
+ - test/base_test.rb
73
+ - test/helper.rb
74
+ - test/profile_test.rb
75
+ - test/request_test.rb
76
+ - test/user_test.rb
55
77
  has_rdoc: true
56
78
  homepage: http://github.com/coop/run_keeper
57
79
  licenses: []
@@ -65,16 +87,29 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
87
  - - ! '>='
66
88
  - !ruby/object:Gem::Version
67
89
  version: '0'
90
+ segments:
91
+ - 0
92
+ hash: -639340336627056513
68
93
  required_rubygems_version: !ruby/object:Gem::Requirement
69
94
  none: false
70
95
  requirements:
71
96
  - - ! '>='
72
97
  - !ruby/object:Gem::Version
73
98
  version: '0'
99
+ segments:
100
+ - 0
101
+ hash: -639340336627056513
74
102
  requirements: []
75
103
  rubyforge_project:
76
104
  rubygems_version: 1.6.2
77
105
  signing_key:
78
106
  specification_version: 3
79
107
  summary: Run Keeper API client
80
- test_files: []
108
+ test_files:
109
+ - test/activity_request_test.rb
110
+ - test/activity_test.rb
111
+ - test/base_test.rb
112
+ - test/helper.rb
113
+ - test/profile_test.rb
114
+ - test/request_test.rb
115
+ - test/user_test.rb