pivotal_tracker 0.1.0 → 0.2.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/README.rdoc +36 -2
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/lib/pivotal_tracker/error.rb +16 -0
- data/lib/pivotal_tracker.rb +101 -9
- data/pivotal_tracker.gemspec +13 -4
- data/spec/fixtures/activities.xml +19 -0
- data/spec/fixtures/iterations.xml +24 -0
- data/spec/fixtures/memberships.xml +29 -0
- data/spec/fixtures/projects.xml +46 -0
- data/spec/fixtures/stories.xml +17 -0
- data/spec/fixtures/story.xml +12 -0
- data/spec/pivotal_tracker_spec.rb +91 -32
- metadata +20 -4
- data/lib/pivotal_tracker/data.rb +0 -18
data/README.rdoc
CHANGED
@@ -1,12 +1,46 @@
|
|
1
1
|
= pivotal_tracker
|
2
2
|
|
3
|
-
This is a simple ruby wrapper for the Pivotal Tracker API.
|
3
|
+
This is a simple ruby wrapper for the Pivotal Tracker V2 API utilizing HTTParty and Crack::XML.
|
4
|
+
|
5
|
+
== Setup
|
6
|
+
|
7
|
+
Make sure you have gemcutter
|
8
|
+
sudo gem install gemcutter
|
9
|
+
gem tumble
|
10
|
+
|
11
|
+
Install the gem
|
12
|
+
sudo gem install pivotal_tracker
|
13
|
+
|
14
|
+
== Usage
|
15
|
+
|
16
|
+
Create a PivotalTracker object with your API key:
|
17
|
+
tracker = PivotalTracker.new('API_KEY')
|
18
|
+
|
19
|
+
Use any of the currently implemented methods and access them like access the resources returned.
|
20
|
+
Notice that all data returned is parsed and built into Mash objects/arrays for you:
|
21
|
+
projects = tracker.get_all_projects
|
22
|
+
projects.first.memberships.first.person.name
|
23
|
+
=> "Joslyn Esser"
|
24
|
+
|
25
|
+
== Currently implemented methods (More to come!)
|
26
|
+
|
27
|
+
* get_all_activities
|
28
|
+
* get_all_project_activities(project_id)
|
29
|
+
* get_all_projects
|
30
|
+
* get_project(project_id)
|
31
|
+
* create_project(name, options = {})
|
32
|
+
* get_all_project_memberships(project_id)
|
33
|
+
* get_project_membership(project_id, membership_id)
|
34
|
+
* add_project_membership(project_id, role, email, options = {})
|
35
|
+
* remove_project_membership(project_id, membership_id)
|
36
|
+
* get_all_project_iterations(project_id)
|
37
|
+
* get_all_project_stories(project_id)
|
4
38
|
|
5
39
|
== Note on Patches/Pull Requests
|
6
40
|
|
7
41
|
* Fork the project.
|
8
42
|
* Make your feature addition or bug fix.
|
9
|
-
* Add
|
43
|
+
* Add specs for it. This is important so I don't break it in a
|
10
44
|
future version unintentionally.
|
11
45
|
* Commit, do not mess with rakefile, version, or history.
|
12
46
|
(if you want to have your own version, that is fine but
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ begin
|
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "pivotal_tracker"
|
8
|
-
gem.summary = %Q{
|
8
|
+
gem.summary = %Q{Ruby wrapper for the Pivotal Tracker V2 API utilizing HTTParty and Crack XML parsing}
|
9
9
|
gem.email = "joslyn.esser@gmail.com"
|
10
10
|
gem.homepage = "http://github.com/joslynesser/pivotal_tracker"
|
11
11
|
gem.authors = ["Joslyn Esser"]
|
@@ -14,6 +14,7 @@ begin
|
|
14
14
|
gem.add_development_dependency "fakeweb", ">= 1.2.7"
|
15
15
|
|
16
16
|
gem.add_dependency "httparty", ">= 0.4.5"
|
17
|
+
gem.add_dependency "mash", ">= 0.0.3"
|
17
18
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
19
|
end
|
19
20
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class PivotalTracker::Error < StandardError
|
2
|
+
attr_reader :data
|
3
|
+
|
4
|
+
def initialize(data)
|
5
|
+
@data = data
|
6
|
+
super
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class PivotalTracker::BadRequest < PivotalTracker::Error; end
|
11
|
+
class PivotalTracker::Unauthorized < PivotalTracker::Error; end
|
12
|
+
|
13
|
+
class PivotalTracker::General < StandardError; end
|
14
|
+
class PivotalTracker::Unavailable < StandardError; end
|
15
|
+
class PivotalTracker::InformPivotal < StandardError; end
|
16
|
+
class PivotalTracker::ResourceNotFound < StandardError; end
|
data/lib/pivotal_tracker.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'httparty'
|
3
|
+
require 'mash'
|
3
4
|
|
4
5
|
class PivotalTracker
|
6
|
+
|
5
7
|
include HTTParty
|
6
8
|
base_uri 'www.pivotaltracker.com/services/v2'
|
7
9
|
format :xml
|
@@ -10,20 +12,110 @@ class PivotalTracker
|
|
10
12
|
self.class.headers 'X-TrackerToken' => api_token
|
11
13
|
end
|
12
14
|
|
15
|
+
def get_all_activities
|
16
|
+
response = self.class.get("/activities")
|
17
|
+
raise_errors(response)
|
18
|
+
parse_response(response, 'activities')
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_all_project_activities(project_id)
|
22
|
+
response = self.class.get("/projects/#{project_id}/activities")
|
23
|
+
raise_errors(response)
|
24
|
+
parse_response(response, 'activities')
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_all_projects
|
28
|
+
response = self.class.get("/projects")
|
29
|
+
raise_errors(response)
|
30
|
+
parse_response(response, 'projects')
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_project(project_id)
|
34
|
+
response = self.class.get("/projects/#{project_id}")
|
35
|
+
raise_errors(response)
|
36
|
+
parse_response(response, 'project')
|
37
|
+
end
|
38
|
+
|
13
39
|
def create_project(name, options = {})
|
14
|
-
|
15
|
-
|
40
|
+
response = self.class.post('/projects', :body => {:project => options.merge(:name => name)})
|
41
|
+
raise_errors(response)
|
42
|
+
parse_response(response, 'project')
|
16
43
|
end
|
17
44
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
45
|
+
def get_all_project_memberships(project_id)
|
46
|
+
response = self.class.get("/projects/#{project_id}/memberships")
|
47
|
+
raise_errors(response)
|
48
|
+
parse_response(response, 'memberships')
|
21
49
|
end
|
22
50
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
51
|
+
def get_project_membership(project_id, membership_id)
|
52
|
+
response = self.class.get("/projects/#{project_id}/memberships/#{membership_id}")
|
53
|
+
raise_errors(response)
|
54
|
+
parse_response(response, 'membership')
|
26
55
|
end
|
56
|
+
|
57
|
+
def add_project_membership(project_id, role, email, options = {})
|
58
|
+
response = self.class.post("/projects/#{project_id}/memberships", :body => {:membership => {:role => role, :person => options.merge(:email => email)}})
|
59
|
+
raise_errors(response)
|
60
|
+
parse_response(response, 'membership')
|
61
|
+
end
|
62
|
+
|
63
|
+
def remove_project_membership(project_id, membership_id)
|
64
|
+
response = self.class.delete("/projects/#{project_id}/memberships/#{membership_id}")
|
65
|
+
raise_errors(response)
|
66
|
+
parse_response(response, 'membership')
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_all_project_iterations(project_id)
|
70
|
+
response = self.class.get("/projects/#{project_id}/iterations")
|
71
|
+
raise_errors(response)
|
72
|
+
parse_response(response, 'iterations')
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_all_project_stories(project_id)
|
76
|
+
response = self.class.get("/projects/#{project_id}/stories")
|
77
|
+
raise_errors(response)
|
78
|
+
parse_response(response, 'stories')
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def raise_errors(response)
|
84
|
+
case response.code.to_i
|
85
|
+
when 400
|
86
|
+
raise PivotalTracker::BadRequest.new(response), "(#{response.code}): #{response.message} - #{response['message'] if response}"
|
87
|
+
when 401
|
88
|
+
raise PivotalTracker::Unauthorized.new(response), "(#{response.code}): #{response.message} - #{response.body if response}"
|
89
|
+
when 403
|
90
|
+
raise PivotalTracker::General, "(#{response.code}): #{response.message}"
|
91
|
+
when 404
|
92
|
+
raise PivotalTracker::ResourceNotFound, "(#{response.code}): #{response.message}"
|
93
|
+
when 500
|
94
|
+
raise PivotalTracker::InformPivotal, "Pivotal Tracker had an internal error. Please let them know. (#{response.code}): #{response.message}"
|
95
|
+
when 502..503
|
96
|
+
raise PivotalTracker::Unavailable, "(#{response.code}): #{response.message}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Create Mash objects from response data for the given resource(s)
|
101
|
+
def parse_response(response, resource)
|
102
|
+
response = cleanup_pivotal_data(response.body)
|
103
|
+
data = response[resource]
|
104
|
+
if data.is_a?(Array)
|
105
|
+
data.collect {|object| Mash.new(object)}
|
106
|
+
else
|
107
|
+
Mash.new(data)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Make Crack's XML parsing happy by correctly defining Pivotal's nested collections as arrays
|
112
|
+
# This can be removed when all collections returned by Pivotal Tracker's API have the type=array attribute set
|
113
|
+
def cleanup_pivotal_data(body)
|
114
|
+
%w{ projects memberships iterations stories }.each do |resource|
|
115
|
+
body.gsub!("<#{resource}>", "<#{resource} type=\"array\">")
|
116
|
+
end
|
117
|
+
response = Crack::XML.parse(body)
|
118
|
+
end
|
27
119
|
end
|
28
120
|
|
29
|
-
require File.dirname(__FILE__) + '/pivotal_tracker/
|
121
|
+
require File.dirname(__FILE__) + '/pivotal_tracker/error'
|
data/pivotal_tracker.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{pivotal_tracker}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Joslyn Esser"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-06}
|
13
13
|
s.email = %q{joslyn.esser@gmail.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
@@ -23,10 +23,16 @@ Gem::Specification.new do |s|
|
|
23
23
|
"Rakefile",
|
24
24
|
"VERSION",
|
25
25
|
"lib/pivotal_tracker.rb",
|
26
|
-
"lib/pivotal_tracker/
|
26
|
+
"lib/pivotal_tracker/error.rb",
|
27
27
|
"pivotal_tracker.gemspec",
|
28
|
+
"spec/fixtures/activities.xml",
|
29
|
+
"spec/fixtures/iterations.xml",
|
28
30
|
"spec/fixtures/membership.xml",
|
31
|
+
"spec/fixtures/memberships.xml",
|
29
32
|
"spec/fixtures/project.xml",
|
33
|
+
"spec/fixtures/projects.xml",
|
34
|
+
"spec/fixtures/stories.xml",
|
35
|
+
"spec/fixtures/story.xml",
|
30
36
|
"spec/pivotal_tracker_spec.rb",
|
31
37
|
"spec/spec.opts",
|
32
38
|
"spec/spec_helper.rb"
|
@@ -35,7 +41,7 @@ Gem::Specification.new do |s|
|
|
35
41
|
s.rdoc_options = ["--charset=UTF-8"]
|
36
42
|
s.require_paths = ["lib"]
|
37
43
|
s.rubygems_version = %q{1.3.5}
|
38
|
-
s.summary = %q{
|
44
|
+
s.summary = %q{Ruby wrapper for the Pivotal Tracker V2 API utilizing HTTParty and Crack XML parsing}
|
39
45
|
s.test_files = [
|
40
46
|
"spec/pivotal_tracker_spec.rb",
|
41
47
|
"spec/spec_helper.rb"
|
@@ -49,15 +55,18 @@ Gem::Specification.new do |s|
|
|
49
55
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
50
56
|
s.add_development_dependency(%q<fakeweb>, [">= 1.2.7"])
|
51
57
|
s.add_runtime_dependency(%q<httparty>, [">= 0.4.5"])
|
58
|
+
s.add_runtime_dependency(%q<mash>, [">= 0.0.3"])
|
52
59
|
else
|
53
60
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
54
61
|
s.add_dependency(%q<fakeweb>, [">= 1.2.7"])
|
55
62
|
s.add_dependency(%q<httparty>, [">= 0.4.5"])
|
63
|
+
s.add_dependency(%q<mash>, [">= 0.0.3"])
|
56
64
|
end
|
57
65
|
else
|
58
66
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
59
67
|
s.add_dependency(%q<fakeweb>, [">= 1.2.7"])
|
60
68
|
s.add_dependency(%q<httparty>, [">= 0.4.5"])
|
69
|
+
s.add_dependency(%q<mash>, [">= 0.0.3"])
|
61
70
|
end
|
62
71
|
end
|
63
72
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<activities type="array">
|
3
|
+
<activity>
|
4
|
+
<id type="integer">1031</id>
|
5
|
+
<project>Sample Project</project>
|
6
|
+
<story>More power to shields</story>
|
7
|
+
<description>James Kirk accepted "More power to shields"</description>
|
8
|
+
<author>James Kirk </author>
|
9
|
+
<when>06/01/2009 08:22 AM</when>
|
10
|
+
</activity>
|
11
|
+
<activity>
|
12
|
+
<id type="integer">1030</id>
|
13
|
+
<project>Another Sample Project</project>
|
14
|
+
<story>Warp speed</story>
|
15
|
+
<description>Montgomery Scott rejected "Warp speend" with comments: "Warp speed isn't working"</description>
|
16
|
+
<author>Montgomery Scott</author>
|
17
|
+
<when>06/01/2009 12:22 AM</when>
|
18
|
+
</activity>
|
19
|
+
</activities>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<iterations type="array">
|
3
|
+
<iteration>
|
4
|
+
<id type="integer">1</id>
|
5
|
+
<number type="integer">1</number>
|
6
|
+
<start type="datetime">2009/03/16 00:00:00 UTC</start>
|
7
|
+
<finish type="datetime">2009/03/23 00:00:00 UTC</finish>
|
8
|
+
<stories>
|
9
|
+
<story>
|
10
|
+
<id type="integer">1</id>
|
11
|
+
<story_type>feature</story_type>
|
12
|
+
<url>STORY_URL</url>
|
13
|
+
<estimate type="integer">2</estimate>
|
14
|
+
<current_state>accepted</current_state>
|
15
|
+
<description>Windoze Save Dialog thingy</description>
|
16
|
+
<name>The Save Dialog</name>
|
17
|
+
<requested_by>Dana Deer</requested_by>
|
18
|
+
<owned_by>Rob</owned_by>
|
19
|
+
<created_at type="datetime">2009/03/16 16:55:04 UTC</created_at>
|
20
|
+
<accepted_at type="datetime">2009/03/19 19:00:00 UTC</accepted_at>
|
21
|
+
</story>
|
22
|
+
</stories>
|
23
|
+
</iteration>
|
24
|
+
</iterations>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<memberships type="array">
|
3
|
+
<membership>
|
4
|
+
<id>1</id>
|
5
|
+
<person>
|
6
|
+
<email>picard@earth.ufp</email>
|
7
|
+
<name>Jean-Luc Picard</name>
|
8
|
+
<initials>jlp</initials>
|
9
|
+
</person>
|
10
|
+
<role>Owner</role>
|
11
|
+
<project>
|
12
|
+
<id>1</id>
|
13
|
+
<name>Warp Engine Upgrades</name>
|
14
|
+
</project>
|
15
|
+
</membership>
|
16
|
+
<membership>
|
17
|
+
<id>2</id>
|
18
|
+
<person>
|
19
|
+
<email>jadzia@trill.ufp</email>
|
20
|
+
<name>Jadzia Dax</name>
|
21
|
+
<initials>JD</initials>
|
22
|
+
</person>
|
23
|
+
<role>Member</role>
|
24
|
+
<project>
|
25
|
+
<id>1</id>
|
26
|
+
<name>Warp Engine Upgrades</name>
|
27
|
+
</project>
|
28
|
+
</membership>
|
29
|
+
</memberships>
|
@@ -0,0 +1,46 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<projects type="array">
|
3
|
+
<project>
|
4
|
+
<id>1</id>
|
5
|
+
<name>Sample Project</name>
|
6
|
+
<iteration_length type="integer">2</iteration_length>
|
7
|
+
<week_start_day>Monday</week_start_day>
|
8
|
+
<point_scale>0,1,2,3</point_scale>
|
9
|
+
<velocity_scheme>Average of 4 iterations</velocity_scheme>
|
10
|
+
<initial_velocity>10</initial_velocity>
|
11
|
+
<number_of_done_iterations_to_show>12</number_of_done_iterations_to_show>
|
12
|
+
<allow_attachments>true</allow_attachments>
|
13
|
+
<public>false</public>
|
14
|
+
<use_https>true</use_https>
|
15
|
+
<bugs_and_chores_are_estimatable>false</bugs_and_chores_are_estimatable>
|
16
|
+
<commit_mode>false</commit_mode>
|
17
|
+
<memberships>
|
18
|
+
<membership>
|
19
|
+
<id>1006</id>
|
20
|
+
<person>
|
21
|
+
<email>kirkybaby@earth.ufp</email>
|
22
|
+
<name>James T. Kirk</name>
|
23
|
+
<initials>JTK</initials>
|
24
|
+
</person>
|
25
|
+
<role>Owner</role>
|
26
|
+
</membership>
|
27
|
+
</memberships>
|
28
|
+
</project>
|
29
|
+
<project>
|
30
|
+
<id>2</id>
|
31
|
+
<name>Sample Project 2</name>
|
32
|
+
<iteration_length type="integer">4</iteration_length>
|
33
|
+
<week_start_day>Monday</week_start_day>
|
34
|
+
<point_scale>0,1,2,3</point_scale>
|
35
|
+
<velocity_scheme>Average of 4 iterations</velocity_scheme>
|
36
|
+
<initial_velocity>10</initial_velocity>
|
37
|
+
<number_of_done_iterations_to_show>12</number_of_done_iterations_to_show>
|
38
|
+
<allow_attachments>false</allow_attachments>
|
39
|
+
<public>true</public>
|
40
|
+
<use_https>false</use_https>
|
41
|
+
<bugs_and_chores_are_estimatable>false</bugs_and_chores_are_estimatable>
|
42
|
+
<commit_mode>false</commit_mode>
|
43
|
+
<memberships>
|
44
|
+
</memberships>
|
45
|
+
</project>
|
46
|
+
</projects>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<stories type="array" count="10" total="10">
|
3
|
+
<story>
|
4
|
+
<id type="integer">STORY_ID</id>
|
5
|
+
<story_type>feature</story_type>
|
6
|
+
<url>http://www.pivotaltracker.com/story/show/STORY_ID</url>
|
7
|
+
<estimate type="integer">1</estimate>
|
8
|
+
<current_state>accepted</current_state>
|
9
|
+
<description></description>
|
10
|
+
<name>More power to shields</name>
|
11
|
+
<requested_by>James Kirk</requested_by>
|
12
|
+
<owned_by>Montgomery Scott</owned_by>
|
13
|
+
<created_at type="datetime">2008/12/10 00:00:00 UTC</created_at>
|
14
|
+
<accepted_at type="datetime">2008/12/10 00:00:00 UTC</accepted_at>
|
15
|
+
<labels>label 1,label 2,label 3</labels>
|
16
|
+
</story>
|
17
|
+
</stories>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<story>
|
3
|
+
<id type="integer">2751</id>
|
4
|
+
<story_type>feature</story_type>
|
5
|
+
<url>http://www.pivotaltracker.com/story/show/2751</url>
|
6
|
+
<estimate type="integer">-1</estimate>
|
7
|
+
<current_state>unscheduled</current_state>
|
8
|
+
<description></description>
|
9
|
+
<name>Fire torpedoes</name>
|
10
|
+
<requested_by>James Kirk</requested_by>
|
11
|
+
<created_at type="datetime">2008/12/10 00:00:00 UTC</created_at>
|
12
|
+
</story>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe PivotalTracker do
|
4
4
|
|
5
5
|
describe "Initialization" do
|
6
6
|
it "should require an API token" do
|
@@ -13,52 +13,111 @@ describe "PivotalTracker" do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe "
|
16
|
+
describe "API" do
|
17
17
|
before(:each) do
|
18
|
-
@
|
18
|
+
@tracker = PivotalTracker.new('12345')
|
19
19
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
|
21
|
+
describe "Activities" do
|
22
|
+
it "should get all recent activities" do
|
23
|
+
stub_get('/activities', 'activities.xml')
|
24
|
+
activities = @tracker.get_all_activities
|
25
|
+
activities.first.description.should == "James Kirk accepted \"More power to shields\""
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should get all recent activities for a given project" do
|
29
|
+
stub_get('/projects/1/activities', 'activities.xml')
|
30
|
+
activities = @tracker.get_all_project_activities(1)
|
31
|
+
activities.first.description.should == "James Kirk accepted \"More power to shields\""
|
32
|
+
end
|
23
33
|
end
|
24
34
|
|
25
|
-
|
26
|
-
|
35
|
+
describe "Projects" do
|
36
|
+
it "should get all projects" do
|
37
|
+
stub_get('/projects', 'projects.xml')
|
38
|
+
projects = @tracker.get_all_projects
|
39
|
+
projects.first.name.should == 'Sample Project'
|
40
|
+
projects.first.memberships.first.person.name.should == 'James T. Kirk'
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should get a project" do
|
44
|
+
stub_get("/projects/27", 'project.xml')
|
45
|
+
project = @tracker.get_project(27)
|
46
|
+
project.name.should == 'Cardassian War Plans'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should create a project" do
|
50
|
+
stub_post('/projects', 'project.xml')
|
51
|
+
project = @tracker.create_project('Cardassian War Plans')
|
52
|
+
project.name.should == 'Cardassian War Plans'
|
53
|
+
end
|
27
54
|
end
|
28
|
-
end
|
29
55
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
56
|
+
describe "Memberships" do
|
57
|
+
it "should get all memberships for a given project" do
|
58
|
+
stub_get('/projects/1/memberships', 'memberships.xml')
|
59
|
+
memberships = @tracker.get_all_project_memberships(1)
|
60
|
+
memberships.first.person.name.should == 'Jean-Luc Picard'
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should get a single membership for a given project" do
|
64
|
+
stub_get('/projects/1/memberships/15007', 'membership.xml')
|
65
|
+
membership = @tracker.get_project_membership(1, 15007)
|
66
|
+
membership.person.name.should == 'Jadzia Dax'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should add memberships to a given project" do
|
70
|
+
stub_post('/projects/12345/memberships', 'membership.xml')
|
71
|
+
membership = @tracker.add_project_membership(12345, 'Member', 'jadzia@trill.ufp')
|
72
|
+
membership.person.name.should == 'Jadzia Dax'
|
73
|
+
end
|
34
74
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "Memberships" do
|
43
|
-
before(:each) do
|
44
|
-
@tracker = PivotalTracker.new('12345')
|
75
|
+
it "should remove memberships from a given project" do
|
76
|
+
stub_delete('/projects/12345/memberships/15007', 'membership.xml')
|
77
|
+
membership = @tracker.remove_project_membership(12345, 15007)
|
78
|
+
membership.person.name.should == 'Jadzia Dax'
|
79
|
+
end
|
45
80
|
end
|
46
81
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
82
|
+
describe "Iterations" do
|
83
|
+
it "should get all iterations for a given project" do
|
84
|
+
stub_get('/projects/1/iterations', 'iterations.xml')
|
85
|
+
iterations = @tracker.get_all_project_iterations(1)
|
86
|
+
iterations.first.stories.first.story_type.should == 'feature'
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should get iterations filtered by done, current, or backlog" do
|
90
|
+
pending
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should get iterations by limit and offset" do
|
94
|
+
pending
|
95
|
+
end
|
51
96
|
end
|
52
97
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
98
|
+
describe "Stories" do
|
99
|
+
it "should get all stories for a given project" do
|
100
|
+
stub_get('/projects/1/stories', 'stories.xml')
|
101
|
+
stories = @tracker.get_all_project_stories(1)
|
102
|
+
stories.first.owned_by.should == 'Montgomery Scott'
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should get all stories for a project based on a given filter" do
|
106
|
+
pending
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should get all stories for a project paginated by a limit and offset" do
|
110
|
+
pending
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should create a new story for a given project" do
|
114
|
+
pending
|
115
|
+
end
|
57
116
|
end
|
58
117
|
end
|
59
118
|
|
60
119
|
describe "Error Handling" do
|
61
|
-
it "should be
|
120
|
+
it "should be spec'd" do
|
62
121
|
pending
|
63
122
|
end
|
64
123
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pivotal_tracker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joslyn Esser
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-06 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,6 +42,16 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 0.4.5
|
44
44
|
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: mash
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.0.3
|
54
|
+
version:
|
45
55
|
description:
|
46
56
|
email: joslyn.esser@gmail.com
|
47
57
|
executables: []
|
@@ -59,10 +69,16 @@ files:
|
|
59
69
|
- Rakefile
|
60
70
|
- VERSION
|
61
71
|
- lib/pivotal_tracker.rb
|
62
|
-
- lib/pivotal_tracker/
|
72
|
+
- lib/pivotal_tracker/error.rb
|
63
73
|
- pivotal_tracker.gemspec
|
74
|
+
- spec/fixtures/activities.xml
|
75
|
+
- spec/fixtures/iterations.xml
|
64
76
|
- spec/fixtures/membership.xml
|
77
|
+
- spec/fixtures/memberships.xml
|
65
78
|
- spec/fixtures/project.xml
|
79
|
+
- spec/fixtures/projects.xml
|
80
|
+
- spec/fixtures/stories.xml
|
81
|
+
- spec/fixtures/story.xml
|
66
82
|
- spec/pivotal_tracker_spec.rb
|
67
83
|
- spec/spec.opts
|
68
84
|
- spec/spec_helper.rb
|
@@ -93,7 +109,7 @@ rubyforge_project:
|
|
93
109
|
rubygems_version: 1.3.5
|
94
110
|
signing_key:
|
95
111
|
specification_version: 3
|
96
|
-
summary:
|
112
|
+
summary: Ruby wrapper for the Pivotal Tracker V2 API utilizing HTTParty and Crack XML parsing
|
97
113
|
test_files:
|
98
114
|
- spec/pivotal_tracker_spec.rb
|
99
115
|
- spec/spec_helper.rb
|
data/lib/pivotal_tracker/data.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
|
3
|
-
class PivotalTracker
|
4
|
-
class Data < OpenStruct
|
5
|
-
def initialize(data)
|
6
|
-
@table = {}
|
7
|
-
if data
|
8
|
-
for key, value in data
|
9
|
-
@table[key.to_sym] = value.instance_of?(Hash) ? Data.new(value) : value
|
10
|
-
new_ostruct_member(key)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class Project < Data; end
|
17
|
-
class Membership < Data; end
|
18
|
-
end
|