jfgomez86-track-r 1.0.0
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/.gitignore +5 -0
- data/README.textile +93 -0
- data/Rakefile +63 -0
- data/VERSION +1 -0
- data/config/config.yml +2 -0
- data/config/environment.rb +3 -0
- data/config/gems.yml +5 -0
- data/lib/track-r.rb +11 -0
- data/lib/track-r/project.rb +98 -0
- data/lib/track-r/story.rb +87 -0
- data/lib/track-r/token.rb +29 -0
- data/lib/track-r/tracker.rb +50 -0
- data/pkg/track-r-1.0.0.gem +0 -0
- data/test/test_config.yml.example +28 -0
- data/test/test_helper.rb +6 -0
- data/test/unit/project_test.rb +44 -0
- data/test/unit/story_test.rb +32 -0
- data/test/unit/token_test.rb +18 -0
- data/test/unit/tracker_test.rb +46 -0
- data/track-r.gemspec +60 -0
- data/vendor/install-gems/install-gems.rb +63 -0
- metadata +77 -0
data/README.textile
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
h1. What is Track-R?
|
2
|
+
|
3
|
+
Track-R is a library that intends to extend PivotalTracker's API to a higher
|
4
|
+
level using Ruby.
|
5
|
+
|
6
|
+
h2. Installation
|
7
|
+
|
8
|
+
<pre><code>
|
9
|
+
$ gem sources -a http://gems.github.com (you only have to do this once)
|
10
|
+
$ sudo gem install jfgomez86-track-r
|
11
|
+
</code></pre>
|
12
|
+
|
13
|
+
h2. Usage
|
14
|
+
|
15
|
+
To use Track-R you first need to have a valid account on
|
16
|
+
"PivotalTracker":http://www.pivotaltracker.com. You also need to have an api
|
17
|
+
token. To generate a token, use the "Create New Token" link on the My Profile
|
18
|
+
page.
|
19
|
+
|
20
|
+
If you don't want to generate a token, you can also use Track-R's token
|
21
|
+
wrapper:
|
22
|
+
|
23
|
+
<pre><code>
|
24
|
+
token = Token.new(:username => my_username, :password => my_password)
|
25
|
+
</code></pre>
|
26
|
+
|
27
|
+
And use this object to pass it to all the following methods.
|
28
|
+
|
29
|
+
The next step is to require the library itself:
|
30
|
+
|
31
|
+
<pre><code>
|
32
|
+
require 'track-r'
|
33
|
+
</code></pre>
|
34
|
+
|
35
|
+
Lastly you can fetch your project by creating a new Project instance:
|
36
|
+
|
37
|
+
<pre><code>
|
38
|
+
my_project = Project.new(:project_id => my_project_id, :token => token)
|
39
|
+
</code></pre>
|
40
|
+
|
41
|
+
Want to see it's stories? Then running this:
|
42
|
+
|
43
|
+
<pre><code>
|
44
|
+
my_project.stories
|
45
|
+
</code></pre>
|
46
|
+
|
47
|
+
Will do the job. But you probably want to fetch the backlog stories:
|
48
|
+
|
49
|
+
<pre><code>
|
50
|
+
my_project.backlog
|
51
|
+
</code></pre>
|
52
|
+
|
53
|
+
There you go.
|
54
|
+
|
55
|
+
Want to create a new story on that project? You have two choices:
|
56
|
+
|
57
|
+
<pre><code>
|
58
|
+
my_project.create_story(:story_type => value, :estimate => value, :current_state => value, :description => value, :name => value, :requested_by => value, :owned_by => value, :created_at => value, :accepted_at => value, :labels)
|
59
|
+
</code></pre>
|
60
|
+
|
61
|
+
Note that most arguments are optional, but please at least specify a name
|
62
|
+
and a description.
|
63
|
+
|
64
|
+
Want to modify the story? Try this:
|
65
|
+
|
66
|
+
<pre><code>
|
67
|
+
story = my_project.story(my_story_id)
|
68
|
+
story.name = "A new cool name"
|
69
|
+
story.story_type = "Bug"
|
70
|
+
story.description = "This is really cool"
|
71
|
+
story.save
|
72
|
+
</code></pre>
|
73
|
+
|
74
|
+
Don't like that story anymore? Delete it:
|
75
|
+
|
76
|
+
<pre><code>
|
77
|
+
story.destroy
|
78
|
+
</code></pre>
|
79
|
+
|
80
|
+
Or
|
81
|
+
|
82
|
+
<pre><code>
|
83
|
+
my_project.delete_story(story)
|
84
|
+
</code></pre>
|
85
|
+
|
86
|
+
Or
|
87
|
+
|
88
|
+
<pre><code>
|
89
|
+
my_project.delete_story(story.id)
|
90
|
+
</code></pre>
|
91
|
+
|
92
|
+
I think this should get you started. Find any bugs? Please use github's Issue
|
93
|
+
tracker.
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
$:.unshift File.join(File.dirname(__FILE__), '/vendor/')
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'rake'
|
8
|
+
require 'rake/testtask'
|
9
|
+
rescue LoadError
|
10
|
+
puts 'This script should only be accessed via the "rake" command.'
|
11
|
+
puts 'Installation: gem install rake -y'
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
require 'rake/clean'
|
15
|
+
|
16
|
+
task :default => [:test]
|
17
|
+
|
18
|
+
Rake::TestTask.new do |t|
|
19
|
+
t.libs << "test"
|
20
|
+
t.test_files = FileList['test/**/*_test.rb']
|
21
|
+
t.verbose = true
|
22
|
+
t.warning = false
|
23
|
+
#t.options = '--runner=gtk2'
|
24
|
+
end
|
25
|
+
|
26
|
+
namespace :gems do
|
27
|
+
desc "Install gems listed in config/gems.yml"
|
28
|
+
task :install do
|
29
|
+
if !`whoami`.match(/root/)
|
30
|
+
print "WARNING: You should be running this as root.\n"
|
31
|
+
print "Do you want to continue?(y/N) "
|
32
|
+
opt = STDIN.gets
|
33
|
+
fail "Not authorized" unless opt.match(/^y/i)
|
34
|
+
end
|
35
|
+
require 'install-gems/install-gems.rb'
|
36
|
+
InstallGems.new(File.join(File.dirname(__FILE__),'/config/gems.yml'))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
require 'jeweler'
|
42
|
+
Jeweler::Tasks.new do |gemspec|
|
43
|
+
gemspec.name = "track-r"
|
44
|
+
gemspec.summary = "A wrapper library for pivotal tracker's API"
|
45
|
+
gemspec.email = "moc.liamg@68zemogfj".reverse
|
46
|
+
gemspec.homepage = "http://github.com/jfgomez86/Track-R"
|
47
|
+
gemspec.description = "track-r is a library that provides wrapper classes and methods for accessing PivotalTracker's public API."
|
48
|
+
gemspec.version = "1.0.0"
|
49
|
+
gemspec.authors = [ "Jose Felix Gomez" ]
|
50
|
+
end
|
51
|
+
rescue LoadError
|
52
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
53
|
+
end
|
54
|
+
|
55
|
+
#Rake::GemPackageTask.new(spec) do |pkg|
|
56
|
+
# pkg.need_tar = true
|
57
|
+
#end
|
58
|
+
|
59
|
+
#namespace :gem do
|
60
|
+
# task :build => "pkg/#{spec.name}-#{spec.version}.gem" do
|
61
|
+
# puts "generated latest version"
|
62
|
+
# end
|
63
|
+
#end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/config/config.yml
ADDED
data/config/gems.yml
ADDED
data/lib/track-r.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
require File.join(File.dirname(__FILE__), '/../config/environment.rb')
|
3
|
+
require 'track-r/project'
|
4
|
+
require 'track-r/story'
|
5
|
+
require 'track-r/token'
|
6
|
+
require 'track-r/tracker'
|
7
|
+
require 'cgi'
|
8
|
+
require 'net/http'
|
9
|
+
|
10
|
+
# Load configuration globals
|
11
|
+
CONFIG = YAML.load_file(File.join(File.dirname(__FILE__), '/../config/config.yml'))
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# Container for project's attributes.
|
2
|
+
# Receives a hash with either :project key pointing to an hpricot object or a
|
3
|
+
# project_id and a token with which to fetch and build the project object
|
4
|
+
class Project
|
5
|
+
attr_reader :name, :iteration_length, :id, :week_start_day, :point_scale,
|
6
|
+
:api_url, :url, :token
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
if options.include?(:project_id) && options.include?(:token)
|
10
|
+
@id = options[:project_id]
|
11
|
+
@token = options[:token].to_s
|
12
|
+
@api_url = "http://www.pivotaltracker.com/services/v2/projects/#{@id}"
|
13
|
+
@url = "http://www.pivotaltracker.com/projects/#{@id}"
|
14
|
+
@project = Hpricot(open(@api_url, {"X-TrackerToken" => token}))
|
15
|
+
@stories = nil
|
16
|
+
elsif options.include?(:project)
|
17
|
+
@project = options[:project]
|
18
|
+
else
|
19
|
+
raise ArgumentError, "Valid options are: :project (receives an Hpricot Object) OR :project_id + :token"
|
20
|
+
end
|
21
|
+
build_project
|
22
|
+
end
|
23
|
+
|
24
|
+
# Builds an array containing the project's story
|
25
|
+
def stories ; @stories || get_stories ; end
|
26
|
+
|
27
|
+
# Fetches a story with given id
|
28
|
+
def story(id)
|
29
|
+
Story.new(:story_id => id, :project_id => @id, :token => @token)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Creates a story for this project. Receives a set of valid attributes.
|
33
|
+
# Returns a Story object
|
34
|
+
# TODO: Validate attributes
|
35
|
+
def create_story(attributes = {})
|
36
|
+
api_url = URI.parse("http://www.pivotaltracker.com/services/v2/projects/#{@id}/stories")
|
37
|
+
query_string = attributes.map { |key, value| "story[#{key}]=#{CGI::escape(value)}"}.join('&')
|
38
|
+
response = Net::HTTP.start(api_url.host, api_url.port) do |http|
|
39
|
+
http.post(api_url.path, query_string.concat("&token=#{@token}"))
|
40
|
+
end
|
41
|
+
|
42
|
+
story = (Hpricot(response.body)/:story)
|
43
|
+
Story.new(:story => story, :project_id => @id, :token => @token)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Deletes a story given a Story object or a story_id
|
47
|
+
def delete_story(story)
|
48
|
+
if story.is_a?(Story)
|
49
|
+
api_url = URI.parse("http://www.pivotaltracker.com/services/v2/projects/#{@id}/stories/#{story.id}")
|
50
|
+
elsif story.is_a?(Integer) || story.to_i.is_a?(Integer)
|
51
|
+
api_url = URI.parse("http://www.pivotaltracker.com/services/v2/projects/#{@id}/stories/#{story}")
|
52
|
+
else
|
53
|
+
raise ArgumentError, "Should receive a story id or a Story object."
|
54
|
+
end
|
55
|
+
response = Net::HTTP.start(api_url.host, api_url.port) do |http|
|
56
|
+
http.delete(api_url.path, {"X-TrackerToken" => @token})
|
57
|
+
end
|
58
|
+
story = (Hpricot(response.body)/:story)
|
59
|
+
Story.new(:story => story, :project_id => @id, :token => @token)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Gets the backlog's stories
|
63
|
+
def backlog
|
64
|
+
get_stories_by_iteration("backlog")
|
65
|
+
end
|
66
|
+
|
67
|
+
# Gets the current iteration's stories
|
68
|
+
def current
|
69
|
+
get_stories_by_iteration("current")
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
# Builds a project given an hpricot object stored at instance variable
|
75
|
+
# @project
|
76
|
+
def build_project
|
77
|
+
@id ||= @project.at('id').inner_html
|
78
|
+
@api_url ||= "http://www.pivotaltracker.com/services/v2/projects/#{@id}"
|
79
|
+
@url ||= "http://www.pivotaltracker.com/projects/#{@id}"
|
80
|
+
@name = @project.at('name').inner_html
|
81
|
+
@iteration_length = @project.at('iteration_length').inner_html
|
82
|
+
@week_start_day = @project.at('week_start_day').inner_html
|
83
|
+
@point_scale = @project.at('point_scale').inner_html.split(',')
|
84
|
+
end
|
85
|
+
|
86
|
+
# Builds an array containing the project's stories
|
87
|
+
def get_stories
|
88
|
+
api_url = "#{CONFIG[:api_location]}/projects/#{@id}/stories"
|
89
|
+
@stories = (Hpricot(open(api_url, {"X-TrackerToken" => @token.to_s}))/:story).map {|story| Story.new(:story => story, :project_id => @id, :token => @token)}
|
90
|
+
end
|
91
|
+
|
92
|
+
# Builds an array containing the project's stories for a given iteration
|
93
|
+
def get_stories_by_iteration(name)
|
94
|
+
api_url = "http://www.pivotaltracker.com/services/v2/projects/#{@id}/iterations/#{name}"
|
95
|
+
@stories = (Hpricot(open(api_url, {"X-TrackerToken" => @token.to_s}))/:story).map {|story| Story.new(:story => story, :project_id => @id, :token => @token)}
|
96
|
+
end
|
97
|
+
|
98
|
+
end # class Tracker::Project
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# TODO: Documentation ☻
|
2
|
+
class Story
|
3
|
+
attr_accessor :story_type, :estimate, :current_state,
|
4
|
+
:description, :name, :requested_by, :owned_by, :created_at, :accepted_at,
|
5
|
+
:labels
|
6
|
+
|
7
|
+
attr_reader :id, :url
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@token = options[:token].to_s
|
11
|
+
if options.include?(:project_id) && options.include?(:story_id) && options.include?(:token)
|
12
|
+
@id = options[:story_id]
|
13
|
+
@project_id = options[:project_id]
|
14
|
+
@url = "http://www.pivotaltracker.com/story/show/#{@id}"
|
15
|
+
@api_url = "http://www.pivotaltracker.com/services/v2/projects/#{@project_id}/stories/#{@id}"
|
16
|
+
@story = Hpricot(open(@api_url, {"X-TrackerToken" => @token}))
|
17
|
+
elsif options.include?(:story) && options.include?(:project_id) && options.include?(:token)
|
18
|
+
@project_id = options[:project_id]
|
19
|
+
@story = options[:story]
|
20
|
+
else
|
21
|
+
raise ArgumentError, "Valid options are: :story (receives an Hpricot Object) + :project_id OR :project_id + :story_id + :token"
|
22
|
+
end
|
23
|
+
build_story
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_story
|
27
|
+
@id ||= @story.at('id').inner_html
|
28
|
+
@url ||= "http://www.pivotaltracker.com/story/show/#{@id}"
|
29
|
+
@api_url ||= "http://www.pivotaltracker.com/services/v2/projects/#{@project_id}/stories/#{@id}"
|
30
|
+
@story_type = @story.at('story_type').inner_html unless @story.at('story_type').nil?
|
31
|
+
@estimate = @story.at('estimate').inner_html unless @story.at('estimate').nil?
|
32
|
+
@current_state = @story.at('current_state').inner_html unless @story.at('current_state').nil?
|
33
|
+
@description = @story.at('description').inner_html unless @story.at('description').nil?
|
34
|
+
@name = @story.at('name').inner_html unless @story.at('name').nil?
|
35
|
+
@requested_by = @story.at('requested_by').inner_html unless @story.at('requested_by').nil?
|
36
|
+
@owned_by = @story.at('owned_by').inner_html unless @story.at('owned_by').nil?
|
37
|
+
@created_at = @story.at('created_at').inner_html unless @story.at('created_at').nil?
|
38
|
+
@accepted_at = @story.at('accepted_at').inner_html unless @story.at('accepted_at').nil?
|
39
|
+
@labels = @story.at('labels').inner_html unless @story.at('labels').nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
def save
|
43
|
+
parameters = build_story_xml
|
44
|
+
api_url = URI.parse("http://www.pivotaltracker.com/services/v2/projects/#{@project_id}/stories/#{@id}")
|
45
|
+
response = Net::HTTP.start(api_url.host, api_url.port) do |http|
|
46
|
+
http.put(api_url.path, parameters, {'X-TrackerToken' => @token, 'Content-Type' => 'application/xml'})
|
47
|
+
end
|
48
|
+
|
49
|
+
@story = (Hpricot(response.body)/:story)
|
50
|
+
build_story
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO: test this method:
|
54
|
+
def destroy
|
55
|
+
api_url = URI.parse("http://www.pivotaltracker.com/services/v2/projects/#{@project_id}/stories/#{@id}")
|
56
|
+
response = Net::HTTP.start(api_url.host, api_url.port) do |http|
|
57
|
+
http.delete(api_url.path, {"X-TrackerToken" => @token})
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def to_param
|
64
|
+
query_string = attributes.map { |key, value| "story[#{key}]=#{CGI::escape(value)}" unless value.nil?}.compact.join('&')
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_story_xml
|
68
|
+
story_xml = "<story>"
|
69
|
+
attributes.each do |key, value|
|
70
|
+
story_xml << "<#{key}>#{(value.to_s)}</#{key}>" unless value.nil?
|
71
|
+
end
|
72
|
+
story_xml << "</story>"
|
73
|
+
end
|
74
|
+
|
75
|
+
def attributes
|
76
|
+
{
|
77
|
+
"story_type" => @story_type,
|
78
|
+
"estimate" => @estimate,
|
79
|
+
"current_state" => @current_state,
|
80
|
+
"description" => @description,
|
81
|
+
"name" => @name,
|
82
|
+
"requested_by" => @requested_by,
|
83
|
+
"owned_by" => @owned_by,
|
84
|
+
"labels" => @labels
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end # class Tracker::Story
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Token
|
2
|
+
def initialize(options = {})
|
3
|
+
@token = case
|
4
|
+
when options.include?(:token)
|
5
|
+
options[:token]
|
6
|
+
when options.include?(:username) &&
|
7
|
+
options.include?(:password)
|
8
|
+
# If a token is not provided, it can be generated by passing a
|
9
|
+
# hash with :user and :password keys
|
10
|
+
get_token(options[:username],
|
11
|
+
options[:password]
|
12
|
+
)
|
13
|
+
else
|
14
|
+
raise ArgumentError, "Invalid argument, expecting either <:token> or <:username> and <:password>"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
@token
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
# According to http://www.pivotaltracker.com/help/api#retrieve_token this should work:
|
25
|
+
def get_token(username, password)
|
26
|
+
(Hpricot(open("https://www.pivotaltracker.com/services/tokens/active", :http_basic_authentication => [username, password])).at('guid')).inner_html
|
27
|
+
end
|
28
|
+
|
29
|
+
end # class Tracker::Token
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# The class is a wrapper for getting projects, stories and using tokens. It's
|
2
|
+
# main purpose is relating the three allowing to interact with a project, and
|
3
|
+
# its stories using a token.
|
4
|
+
# Expects a token when initialized.
|
5
|
+
class Tracker
|
6
|
+
|
7
|
+
# To generate a token, use the "Create New Token" link on the My Profile
|
8
|
+
# page (http://www.pivotaltracker.com/profile).
|
9
|
+
def initialize(token)
|
10
|
+
@token = token
|
11
|
+
raise TypeError unless @token.is_a? Token
|
12
|
+
end
|
13
|
+
|
14
|
+
# Fetches project with given ID
|
15
|
+
# Returns a Project object
|
16
|
+
def project(project_id)
|
17
|
+
@project = Project.new(:project_id => project_id , :token => @token)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Refresh the projects from the server
|
21
|
+
# Returns an array of projects
|
22
|
+
def sync
|
23
|
+
@projects = nil
|
24
|
+
get_projects
|
25
|
+
end
|
26
|
+
|
27
|
+
# Alias for get_projects
|
28
|
+
# Returns an array of projects
|
29
|
+
def projects ; get_projects ; end
|
30
|
+
|
31
|
+
# Receives a block with the condition to find a project. Should work the
|
32
|
+
# same as Enumerable.find method
|
33
|
+
# Returns a Project object
|
34
|
+
def find_project
|
35
|
+
get_projects unless defined?(@projects) && @projects.is_a?(Array)
|
36
|
+
@projects.find do |project|
|
37
|
+
yield(project)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
# Fills @projects. NOTE: call sync method to refill/sync @projects
|
44
|
+
# Returns an Array stored in @projects
|
45
|
+
def get_projects
|
46
|
+
api_url = "#{CONFIG[:api_location]}/projects/"
|
47
|
+
@projects ||= (Hpricot(open(api_url, {"X-TrackerToken" => @token.to_s}))/:project).map {|project| Project.new(:project => project)}
|
48
|
+
end
|
49
|
+
|
50
|
+
end # class Tracker::Tracker
|
Binary file
|
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
:password: "password"
|
3
|
+
:username: an@email.com
|
4
|
+
:token: "a_token_hash"
|
5
|
+
:project_count: 2
|
6
|
+
:project_1:
|
7
|
+
:name: AProjectName
|
8
|
+
:id: "12345"
|
9
|
+
:point_scale:
|
10
|
+
- "0"
|
11
|
+
- "1"
|
12
|
+
- "2"
|
13
|
+
- "3"
|
14
|
+
:week_start_day: Monday
|
15
|
+
:iteration_length: "1"
|
16
|
+
:project_2:
|
17
|
+
:name: AnotherProjectName
|
18
|
+
:id: "6890"
|
19
|
+
:point_scale:
|
20
|
+
- "0"
|
21
|
+
- "1"
|
22
|
+
- "2"
|
23
|
+
- "3"
|
24
|
+
:week_start_day: Sunday
|
25
|
+
:iteration_length: "1"
|
26
|
+
:story_1:
|
27
|
+
:id: 12345
|
28
|
+
:name: "Some existing name"
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'shoulda'
|
3
|
+
require 'test/unit'
|
4
|
+
require File.join(File.dirname(__FILE__), '/../lib/track-r.rb')
|
5
|
+
require File.join(File.dirname(__FILE__), '/../config/environment.rb')
|
6
|
+
$config = YAML.load_file(File.join(File.dirname(__FILE__), '/test_config.yml'))
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class ProjectTest < Test::Unit::TestCase
|
4
|
+
context "A given project" do
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@project_id = $config[:project_1][:id]
|
8
|
+
token_options = {:username => $config[:username], :password => $config[:password]}
|
9
|
+
@tracker = Tracker.new(Token.new(token_options))
|
10
|
+
@project = @tracker.project(@project_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
should "show all stories for that project with @project.stories" do
|
14
|
+
assert_equal $config[:project_1][:story_count], @project.stories.size
|
15
|
+
end
|
16
|
+
|
17
|
+
should "show a story with @project.story and passing the story id as argument" do
|
18
|
+
assert_equal $config[:story_1][:name], @project.story($config[:story_1][:id]).name
|
19
|
+
end
|
20
|
+
|
21
|
+
should "be able to add and remove a story" do
|
22
|
+
story_count = @project.stories.size
|
23
|
+
attributes = { :name => "Finish Track-R (sorry for cluttering :))",
|
24
|
+
:requested_by => "Jose Felix Gomez",
|
25
|
+
:description => "This story was made with Track-R library. Sorry for the clutter, you're free to delete me." }
|
26
|
+
new_story = @project.create_story(attributes)
|
27
|
+
assert_equal "Finish Track-R (sorry for cluttering :))", new_story.name
|
28
|
+
@project.delete_story(new_story)
|
29
|
+
assert_equal story_count, @project.stories.size
|
30
|
+
end
|
31
|
+
|
32
|
+
should "be able to get the backlog stories" do
|
33
|
+
story_count = $config[:project_1][:backlog_stories]
|
34
|
+
assert_equal story_count, @project.backlog.size
|
35
|
+
end
|
36
|
+
|
37
|
+
should "be able to get the current iteration stories" do
|
38
|
+
story_count = $config[:project_1][:current_stories]
|
39
|
+
assert_equal story_count, @project.current.size
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class TestStoryTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "A given story" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
token_options = {:username => $config[:username], :password => $config[:password]}
|
9
|
+
@tracker = Tracker.new(Token.new(token_options))
|
10
|
+
@project_id = $config[:project_1][:id]
|
11
|
+
@project = @tracker.project(@project_id)
|
12
|
+
attributes = { :name => "Finish Track-R (sorry for cluttering :))",
|
13
|
+
:requested_by => "Jose Felix Gomez",
|
14
|
+
:description => "This story was made with Track-R library. Sorry for the clutter, you're free to delete me." }
|
15
|
+
@story = @project.create_story(attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
teardown do
|
19
|
+
@project.delete_story(@story)
|
20
|
+
end
|
21
|
+
|
22
|
+
should "be updated after story.save call" do
|
23
|
+
@story.name = "More power to the shields"
|
24
|
+
@story.description = "ZOMG!"
|
25
|
+
@story.save
|
26
|
+
|
27
|
+
assert_equal "More power to the shields", @project.story(@story.id).name
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class TestTokenTest < Test::Unit::TestCase
|
4
|
+
context "with a valid username and password" do
|
5
|
+
|
6
|
+
setup do
|
7
|
+
def token_options
|
8
|
+
{:username => $config[:username], :password => $config[:password]}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
should "return a valid token" do
|
13
|
+
@token = Token.new(token_options)
|
14
|
+
assert_equal $config[:token], @token.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class TestTrackerTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "with an invalid token" do
|
6
|
+
|
7
|
+
should "raise an TypeError if token is other than Token object" do
|
8
|
+
token = "token"
|
9
|
+
assert_raise(TypeError) { Tracker.new(token) }
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with a valid token" do
|
15
|
+
|
16
|
+
setup do
|
17
|
+
@project_id = $config[:project_1][:id]
|
18
|
+
def get_token
|
19
|
+
token_options = {:username => $config[:username], :password => $config[:password]}
|
20
|
+
Token.new(token_options)
|
21
|
+
end
|
22
|
+
@tracker = Tracker.new(get_token)
|
23
|
+
end
|
24
|
+
|
25
|
+
should "return a valid project by passing the id with correct attributes" do
|
26
|
+
project = @tracker.project(@project_id)
|
27
|
+
assert_equal $config[:project_1][:name], project.name
|
28
|
+
assert_equal $config[:project_1][:point_scale], project.point_scale
|
29
|
+
assert_equal $config[:project_1][:week_start_day], project.week_start_day
|
30
|
+
assert_equal $config[:project_1][:iteration_length], project.iteration_length
|
31
|
+
end
|
32
|
+
|
33
|
+
should "return an array of all my projects" do
|
34
|
+
projects = @tracker.projects
|
35
|
+
assert_equal $config[:project_count], projects.size
|
36
|
+
end
|
37
|
+
|
38
|
+
should "be able to find a project using Enumerable.find method" do
|
39
|
+
project_1 = (@tracker.find_project {|project| project.name == $config[:project_1][:name]})
|
40
|
+
project_2 = (@tracker.find_project {|project| project.id == $config[:project_2][:id]})
|
41
|
+
assert_equal $config[:project_1][:name], project_1.name, "Failed to find by name"
|
42
|
+
assert_equal $config[:project_2][:name], project_2.name, "Failed to find by id"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/track-r.gemspec
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{track-r}
|
5
|
+
s.version = "1.0.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Jose Felix Gomez"]
|
9
|
+
s.date = %q{2009-06-21}
|
10
|
+
s.description = %q{track-r is a library that provides wrapper classes and methods for accessing PivotalTracker's public API.}
|
11
|
+
s.email = %q{jfgomez86@gmail.com}
|
12
|
+
s.extra_rdoc_files = [
|
13
|
+
"README.textile"
|
14
|
+
]
|
15
|
+
s.files = [
|
16
|
+
".gitignore",
|
17
|
+
"README.textile",
|
18
|
+
"Rakefile",
|
19
|
+
"VERSION",
|
20
|
+
"config/config.yml",
|
21
|
+
"config/environment.rb",
|
22
|
+
"config/gems.yml",
|
23
|
+
"lib/track-r.rb",
|
24
|
+
"lib/track-r/project.rb",
|
25
|
+
"lib/track-r/story.rb",
|
26
|
+
"lib/track-r/token.rb",
|
27
|
+
"lib/track-r/tracker.rb",
|
28
|
+
"pkg/track-r-1.0.0.gem",
|
29
|
+
"test/test_config.yml.example",
|
30
|
+
"test/test_helper.rb",
|
31
|
+
"test/unit/project_test.rb",
|
32
|
+
"test/unit/story_test.rb",
|
33
|
+
"test/unit/token_test.rb",
|
34
|
+
"test/unit/tracker_test.rb",
|
35
|
+
"track-r.gemspec",
|
36
|
+
"vendor/install-gems/install-gems.rb"
|
37
|
+
]
|
38
|
+
s.homepage = %q{http://github.com/jfgomez86/Track-R}
|
39
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
40
|
+
s.require_paths = ["lib"]
|
41
|
+
s.rubygems_version = %q{1.3.3}
|
42
|
+
s.summary = %q{A wrapper library for pivotal tracker's API}
|
43
|
+
s.test_files = [
|
44
|
+
"test/test_helper.rb",
|
45
|
+
"test/unit/tracker_test.rb",
|
46
|
+
"test/unit/story_test.rb",
|
47
|
+
"test/unit/project_test.rb",
|
48
|
+
"test/unit/token_test.rb"
|
49
|
+
]
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
53
|
+
s.specification_version = 3
|
54
|
+
|
55
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
56
|
+
else
|
57
|
+
end
|
58
|
+
else
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#-------------------------------------------------------------------------------.
|
3
|
+
# InstallGems: Script to do the hard gem installing and letting you rest a bit. ||
|
4
|
+
# ||
|
5
|
+
# AUTHOR: Jose F. Gomez ||
|
6
|
+
# VERSION: 0.2.0 ||
|
7
|
+
# DATE: 2009-04-04 ||
|
8
|
+
# ||
|
9
|
+
# USAGE: install-gems.rb [file.yml] The yml file should have this format per ||
|
10
|
+
# gem: ||
|
11
|
+
# ||
|
12
|
+
# example.yml: ||
|
13
|
+
# --- ||
|
14
|
+
# - :source: http://gems.github.com ||
|
15
|
+
# :version: = 0.1.99.21 ||
|
16
|
+
# :name: aslakhellesoy-cucumber ||
|
17
|
+
# ||
|
18
|
+
# Note that :source and :version are optional and the script checks wheter a ||
|
19
|
+
# gem is already installed or not. ||
|
20
|
+
# ||
|
21
|
+
#-------------------------------------------------------------------------------´
|
22
|
+
# HISTORY
|
23
|
+
# 0.2.0 -- Made script require-able.
|
24
|
+
# 0.1.0 -- Initial Commit
|
25
|
+
|
26
|
+
|
27
|
+
class InstallGems
|
28
|
+
require 'yaml'
|
29
|
+
require 'rubygems'
|
30
|
+
|
31
|
+
def initialize(file)
|
32
|
+
@gems_yml = YAML.load_file(file)
|
33
|
+
install_gems
|
34
|
+
end
|
35
|
+
|
36
|
+
def install_gems
|
37
|
+
for gem in @gems_yml
|
38
|
+
install_gem(gem)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def install_gem(gem)
|
43
|
+
unless Gem.available? gem[:name]
|
44
|
+
cmd = "gem install "
|
45
|
+
cmd += "--version '%s' " % gem[:version] if gem.has_key? :version
|
46
|
+
cmd += "--source %s " % gem[:source] if gem.has_key? :source
|
47
|
+
cmd += "%s " % gem[:name] if gem.has_key? :name
|
48
|
+
puts "Installing: %+28s" % gem[:name]
|
49
|
+
out = %x[#{cmd}]
|
50
|
+
else
|
51
|
+
puts "*** [ #{gem[:name]} ] is already installed on this system."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if __FILE__ == $0
|
57
|
+
app = InstallGems.new(ARGV[0])
|
58
|
+
end
|
59
|
+
|
60
|
+
#-------------------------------------------------------------------------------.
|
61
|
+
# vim: set foldmethod:indent ||
|
62
|
+
#-------------------------------------------------------------------------------´
|
63
|
+
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jfgomez86-track-r
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jose Felix Gomez
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-21 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: track-r is a library that provides wrapper classes and methods for accessing PivotalTracker's public API.
|
17
|
+
email: jfgomez86@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.textile
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- README.textile
|
27
|
+
- Rakefile
|
28
|
+
- VERSION
|
29
|
+
- config/config.yml
|
30
|
+
- config/environment.rb
|
31
|
+
- config/gems.yml
|
32
|
+
- lib/track-r.rb
|
33
|
+
- lib/track-r/project.rb
|
34
|
+
- lib/track-r/story.rb
|
35
|
+
- lib/track-r/token.rb
|
36
|
+
- lib/track-r/tracker.rb
|
37
|
+
- pkg/track-r-1.0.0.gem
|
38
|
+
- test/test_config.yml.example
|
39
|
+
- test/test_helper.rb
|
40
|
+
- test/unit/project_test.rb
|
41
|
+
- test/unit/story_test.rb
|
42
|
+
- test/unit/token_test.rb
|
43
|
+
- test/unit/tracker_test.rb
|
44
|
+
- track-r.gemspec
|
45
|
+
- vendor/install-gems/install-gems.rb
|
46
|
+
has_rdoc: false
|
47
|
+
homepage: http://github.com/jfgomez86/Track-R
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options:
|
50
|
+
- --charset=UTF-8
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.2.0
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: A wrapper library for pivotal tracker's API
|
72
|
+
test_files:
|
73
|
+
- test/test_helper.rb
|
74
|
+
- test/unit/tracker_test.rb
|
75
|
+
- test/unit/story_test.rb
|
76
|
+
- test/unit/project_test.rb
|
77
|
+
- test/unit/token_test.rb
|