topprospect-pivotal-tracker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.gitignore +9 -0
  2. data/Gemfile +15 -0
  3. data/Gemfile.lock +40 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +77 -0
  6. data/Rakefile +49 -0
  7. data/VERSION +1 -0
  8. data/lib/pivotal-tracker.rb +38 -0
  9. data/lib/pivotal-tracker/activity.rb +45 -0
  10. data/lib/pivotal-tracker/attachment.rb +16 -0
  11. data/lib/pivotal-tracker/client.rb +35 -0
  12. data/lib/pivotal-tracker/extensions.rb +11 -0
  13. data/lib/pivotal-tracker/iteration.rb +34 -0
  14. data/lib/pivotal-tracker/membership.rb +20 -0
  15. data/lib/pivotal-tracker/note.rb +58 -0
  16. data/lib/pivotal-tracker/project.rb +58 -0
  17. data/lib/pivotal-tracker/proxy.rb +66 -0
  18. data/lib/pivotal-tracker/story.rb +149 -0
  19. data/lib/pivotal-tracker/task.rb +53 -0
  20. data/lib/pivotal-tracker/validation.rb +68 -0
  21. data/lib/pivotal_tracker.rb +2 -0
  22. data/pivotal-tracker.gemspec +120 -0
  23. data/spec/fixtures/activity.xml +177 -0
  24. data/spec/fixtures/created_note.xml +14 -0
  25. data/spec/fixtures/created_story.xml +14 -0
  26. data/spec/fixtures/iterations_all.xml +237 -0
  27. data/spec/fixtures/iterations_backlog.xml +163 -0
  28. data/spec/fixtures/iterations_current.xml +47 -0
  29. data/spec/fixtures/iterations_done.xml +33 -0
  30. data/spec/fixtures/memberships.xml +42 -0
  31. data/spec/fixtures/notes.xml +33 -0
  32. data/spec/fixtures/project.xml +51 -0
  33. data/spec/fixtures/project_activity.xml +177 -0
  34. data/spec/fixtures/projects.xml +103 -0
  35. data/spec/fixtures/stale_fish.yml +100 -0
  36. data/spec/fixtures/stories.xml +293 -0
  37. data/spec/fixtures/tasks.xml +24 -0
  38. data/spec/spec.opts +1 -0
  39. data/spec/spec_helper.rb +31 -0
  40. data/spec/support/stale_fish_fixtures.rb +67 -0
  41. data/spec/unit/pivotal-tracker/activity_spec.rb +23 -0
  42. data/spec/unit/pivotal-tracker/attachment_spec.rb +62 -0
  43. data/spec/unit/pivotal-tracker/iteration_spec.rb +52 -0
  44. data/spec/unit/pivotal-tracker/membership_spec.rb +20 -0
  45. data/spec/unit/pivotal-tracker/note_spec.rb +61 -0
  46. data/spec/unit/pivotal-tracker/project_spec.rb +55 -0
  47. data/spec/unit/pivotal-tracker/story_spec.rb +185 -0
  48. data/spec/unit/pivotal-tracker/task_spec.rb +21 -0
  49. metadata +246 -0
@@ -0,0 +1,67 @@
1
+ module StaleFishFixtures
2
+ class << self
3
+
4
+ def update_projects_fixture
5
+ connection["/projects"].get
6
+ end
7
+
8
+ def update_project_fixture
9
+ connection["/projects/102622"].get
10
+ end
11
+
12
+ def update_stories_fixture
13
+ connection["/projects/102622/stories?limit=20"].get
14
+ end
15
+
16
+ def update_memberships_fixture
17
+ connection["/projects/102622/memberships"].get
18
+ end
19
+
20
+ def update_tasks_fixture
21
+ connection["/projects/102622/stories/4459994/tasks"].get
22
+ end
23
+
24
+ def update_activity_fixture
25
+ connection["/activities"].get
26
+ end
27
+
28
+ def update_project_activity_fixture
29
+ connection["/projects/102622/activities"].get
30
+ end
31
+
32
+ def update_iterations_all_fixture
33
+ connection["/projects/102622/iterations"].get
34
+ end
35
+
36
+ def update_iterations_current_fixture
37
+ connection["/projects/102622/iterations/current"].get
38
+ end
39
+
40
+ def update_iterations_backlog_fixture
41
+ connection["/projects/102622/iterations/backlog"].get
42
+ end
43
+
44
+ def update_iterations_done_fixture
45
+ connection["/projects/102622/iterations/done"].get
46
+ end
47
+
48
+ def create_new_story
49
+ connection["/projects/102622/stories"].post("<story><name>Create stuff</name></story>", :content_type => 'application/xml')
50
+ end
51
+
52
+ def update_notes_fixture
53
+ connection["/projects/102622/stories/4460038/notes"].get
54
+ end
55
+
56
+ # def upload_attachment_fixture
57
+ # connection["/projects/102622/stories/4473735/attachments"].post(:Filedata => File.new(File.dirname(__FILE__) + '/../../LICENSE'))
58
+ # end
59
+
60
+ protected
61
+
62
+ def connection
63
+ @connection ||= RestClient::Resource.new('http://www.pivotaltracker.com/services/v3', :headers => {'X-TrackerToken' => TOKEN, 'Content-Type' => 'application/xml'})
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe PivotalTracker::Activity do
4
+
5
+ context "without a specified project" do
6
+ it "should return an array of activities" do
7
+ PivotalTracker::Activity.all.should be_a(Array)
8
+ PivotalTracker::Activity.all.first.should be_a(PivotalTracker::Activity)
9
+ end
10
+ end
11
+
12
+ context "with a specified project" do
13
+ before do
14
+ @project = PivotalTracker::Project.find(PROJECT_ID)
15
+ end
16
+
17
+ it "should return an array of activities" do
18
+ @project.activities.all.should be_a(Array)
19
+ @project.activities.all.first.should be_a(PivotalTracker::Activity)
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe PivotalTracker::Attachment do
4
+
5
+ before do
6
+ PivotalTracker::Client.token = TOKEN
7
+ @project = PivotalTracker::Project.find(102622)
8
+ @story = @project.stories.find(4460598)
9
+ end
10
+
11
+ context "always" do
12
+ it "should return an integer id" do
13
+ @story.attachments.first.id.should be_a(Integer)
14
+ end
15
+
16
+ it "should return a string for url" do
17
+ @story.attachments.first.url.should be_a(String)
18
+ end
19
+
20
+ it "should return a string for filename" do
21
+ @story.attachments.first.filename.should be_a(String)
22
+ end
23
+
24
+ it "should return a string for uploaded_by" do
25
+ @story.attachments.first.uploaded_by.should be_a(String)
26
+ end
27
+
28
+ it "should return a datetime for uploaded_at" do
29
+ @story.attachments.first.uploaded_at.should be_a(DateTime)
30
+ end
31
+ end
32
+
33
+ context "without description" do
34
+ it "should have a blank string for the description" do
35
+ @story.attachments.first.description.should be_a(String)
36
+ @story.attachments.first.description.should be_blank
37
+ end
38
+ end
39
+
40
+ context "with description" do
41
+ it "should have a non-blank string for the description" do
42
+ @story.attachments.first.description.should be_a(String)
43
+ @story.attachments.last.description.should_not be_blank
44
+ end
45
+ end
46
+
47
+ context "uploading" do
48
+
49
+ before do
50
+ @target_story = @project.stories.find(4473735)
51
+ @orig_net_lock = FakeWeb.allow_net_connect?
52
+ end
53
+
54
+ it "should return an attachment object with a pending status" do
55
+ FakeWeb.allow_net_connect = true
56
+ resource = @target_story.upload_attachment(File.dirname(__FILE__) + '/../../../LICENSE')
57
+ FakeWeb.allow_net_connect = @orig_net_lock
58
+ resource.should be_a(PivotalTracker::Attachment)
59
+ resource.status.should == 'Pending'
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe PivotalTracker::Iteration do
4
+ before do
5
+ @project = PivotalTracker::Project.find(PROJECT_ID)
6
+ end
7
+
8
+ describe ".all" do
9
+ before do
10
+ @iterations = PivotalTracker::Iteration.all(@project)
11
+ end
12
+
13
+ it "should return an array of Iterations for the given Project" do
14
+ @iterations.should be_a(Array)
15
+ @iterations.first.should be_a(PivotalTracker::Iteration)
16
+ end
17
+ end
18
+
19
+ describe ".current" do
20
+ before do
21
+ @iteration = PivotalTracker::Iteration.current(@project)
22
+ end
23
+
24
+ it "should return a single Iteration" do
25
+ @iteration.should be_a(PivotalTracker::Iteration)
26
+ end
27
+ end
28
+
29
+ describe ".backlog" do
30
+ before do
31
+ @iterations = PivotalTracker::Iteration.backlog(@project)
32
+ end
33
+
34
+ it "should return an array of Iterations for the given Project" do
35
+ @iterations.should be_a(Array)
36
+ @iterations.first.should be_a(PivotalTracker::Iteration)
37
+ end
38
+ end
39
+
40
+ describe ".done" do
41
+ before do
42
+ @iterations = PivotalTracker::Iteration.done(@project)
43
+ end
44
+
45
+ it "should return an array of Iterations for the given Project" do
46
+ @iterations.should be_a(Array)
47
+ @iterations.first.should be_a(PivotalTracker::Iteration)
48
+ end
49
+ end
50
+
51
+ end
52
+
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe PivotalTracker::Project do
4
+ before do
5
+ @project = PivotalTracker::Project.find(102622)
6
+ end
7
+
8
+ context ".all" do
9
+ it "should return an array of memberships" do
10
+ @project.memberships.all.should be_a(Array)
11
+ @project.memberships.all.first.should be_a(PivotalTracker::Membership)
12
+ end
13
+ end
14
+
15
+ context ".find" do
16
+ it "should return the given membership" do
17
+ @project.memberships.find(331832).should be_a(PivotalTracker::Membership)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe PivotalTracker::Note do
4
+ before do
5
+ @project = PivotalTracker::Project.find(102622)
6
+ @story = @project.stories.find(4460038)
7
+ end
8
+
9
+ context ".all" do
10
+ it "should return an array of notes" do
11
+ @story.notes.all.should be_a(Array)
12
+ @story.notes.all.first.should be_a(PivotalTracker::Note)
13
+ end
14
+ end
15
+
16
+ #context ".find" do
17
+ # it "should return a given task" do
18
+ # @story.tasks.find(179025).should be_a(PivotalTracker::Task)
19
+ # end
20
+ #end
21
+
22
+ context ".create" do
23
+ it "should return the created note" do
24
+ @story.notes.create(:text => 'Test note')
25
+ end
26
+ end
27
+
28
+ context ".new" do
29
+
30
+ def note_for(attrs)
31
+ note = @story.notes.new(attrs)
32
+ @note = Hash.from_xml(note.send(:to_xml))['note']
33
+ end
34
+
35
+ describe "attributes that are not sent to the tracker" do
36
+
37
+ it "should include id" do
38
+ note_for(:id => 10)["id"].should be_nil
39
+ end
40
+
41
+ it "should include author" do
42
+ note_for(:author => "somebody")["author"].should be_nil
43
+ end
44
+
45
+ end
46
+
47
+ describe "attributes that are sent to the tracker" do
48
+
49
+ it "should include text" do
50
+ note_for(:text => "A comment...")["text"].should == "A comment..."
51
+ end
52
+
53
+ it "should include noted_at" do
54
+ note_for(:noted_at => "timestamp")["noted_at"].should == "timestamp"
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe PivotalTracker::Project do
4
+ context ".all" do
5
+ before do
6
+ @projects = PivotalTracker::Project.all
7
+ end
8
+
9
+ it "should return an array of available projects" do
10
+ @projects.should be_a(Array)
11
+ end
12
+
13
+ it "should be a project instance" do
14
+ @projects.first.should be_a(PivotalTracker::Project)
15
+ end
16
+ end
17
+
18
+ context ".find" do
19
+ before do
20
+ @project = PivotalTracker::Project.find(102622)
21
+ end
22
+
23
+ it "should be an instance of Project" do
24
+ @project.should be_a(PivotalTracker::Project)
25
+ end
26
+
27
+ it "should have a use_https attribute" do
28
+ @project.respond_to?(:use_https).should be_true
29
+ end
30
+
31
+ it "should have false for use_https" do
32
+ @project.use_https.should be_false
33
+ end
34
+ end
35
+
36
+ context ".stories" do
37
+ before do
38
+ @project = PivotalTracker::Project.find(102622)
39
+ end
40
+
41
+ it "should have a stories association" do
42
+ @project.respond_to?(:stories).should be_true
43
+ end
44
+ end
45
+
46
+ context ".memberships" do
47
+ before do
48
+ @project = PivotalTracker::Project.find(102622)
49
+ end
50
+
51
+ it "should have a memberships association" do
52
+ @project.respond_to?(:memberships).should be_true
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,185 @@
1
+ require 'spec_helper'
2
+
3
+ describe PivotalTracker::Story do
4
+ before do
5
+ @project = PivotalTracker::Project.find(102622)
6
+ end
7
+
8
+ context ".all" do
9
+ it "should return all stories" do
10
+ @project.stories.all.should be_a(Array)
11
+ @project.stories.all.first.should be_a(PivotalTracker::Story)
12
+ end
13
+ end
14
+
15
+ context ".find" do
16
+ it "should return the matching story" do
17
+ @project.stories.find(4459994).should be_a(PivotalTracker::Story)
18
+ end
19
+ end
20
+
21
+ context ".create" do
22
+ it "should return the created story" do
23
+ @project.stories.create(:name => 'Create Stuff').should be_a(PivotalTracker::Story)
24
+ end
25
+
26
+ context "on failure" do
27
+ before do
28
+ FakeWeb.register_uri(:post, "http://www.pivotaltracker.com/services/v3/projects/#{@project.id}/stories",
29
+ :body => %{<?xml version="1.0" encoding="UTF-8"?>
30
+ <errors>
31
+ <error>error#1 message</error>
32
+ <error>error#2 message</error>
33
+ </errors>%},
34
+ :status => "422")
35
+ end
36
+
37
+ it "should not raise an exception" do
38
+ expect { @project.stories.create }.to_not raise_error(Exception)
39
+ end
40
+
41
+ it "should report errors encountered" do
42
+ story = @project.stories.create :name => "Invalid story"
43
+ story.errors.messages.should =~ ["error#1 message", "error#2 message"]
44
+ end
45
+ end
46
+ end
47
+
48
+ context ".attachments" do
49
+ it "should return an array of attachments" do
50
+ @story = @project.stories.find(4460598)
51
+ @story.attachments.should be_a(Array)
52
+ @story.attachments.first.should be_a(PivotalTracker::Attachment)
53
+ end
54
+ end
55
+
56
+ context ".move_to_project" do
57
+ before(:each) do
58
+ @orig_net_lock = FakeWeb.allow_net_connect?
59
+ FakeWeb.allow_net_connect = true
60
+ @target_project = PivotalTracker::Project.find(103014)
61
+ @movable_story = @project.stories.find(4490874)
62
+ end
63
+
64
+ it "should return an updated story from the target project when passed a PivotalTracker::Story" do
65
+ target_story = @target_project.stories.find(4477972)
66
+ response = @movable_story.move_to_project(target_story)
67
+ response.project_id.should == target_story.project_id
68
+ end
69
+
70
+ it "should return an updated story from the target project when passed a PivotalTracker::Project" do
71
+ response = @movable_story.move_to_project(@target_project)
72
+ response.project_id.should == @target_project.id
73
+ end
74
+
75
+ it "should return an updated story from the target project when passed a String" do
76
+ response = @movable_story.move_to_project('103014')
77
+ response.project_id.should == 103014
78
+ end
79
+
80
+ it "should return an updated story from the target project when passed an Integer"do
81
+ response = @movable_story.move_to_project(103014)
82
+ response.project_id.should == 103014
83
+ end
84
+
85
+ after (:each) do
86
+ @movable_story = @target_project.stories.find(4490874)
87
+ response = @movable_story.move_to_project(102622)
88
+ FakeWeb.allow_net_connect = @orig_net_lock
89
+ response.project_id.should == 102622
90
+ end
91
+ end
92
+
93
+ context ".new" do
94
+
95
+ def story_for(attrs)
96
+ story = @project.stories.new(attrs)
97
+ @story = Hash.from_xml(story.send(:to_xml))['story']
98
+ end
99
+
100
+ describe "attributes that are not sent to the tracker" do
101
+
102
+ it "should include id" do
103
+ story_for(:id => 10)["id"].should be_nil
104
+ end
105
+
106
+ it "should include url" do
107
+ story_for(:url => "somewhere")["url"].should be_nil
108
+ end
109
+
110
+ end
111
+
112
+ describe "attributes that are sent to the tracker" do
113
+
114
+ it "should include name" do
115
+ story_for(:name => "A user should...")["name"].should == "A user should..."
116
+ end
117
+
118
+ it "should include description" do
119
+ story_for(:description => "desc...")["description"].should == "desc..."
120
+ end
121
+
122
+ it "should include story_type" do
123
+ story_for(:story_type => "feature")["story_type"].should == "feature"
124
+ end
125
+
126
+ it "should include estimate" do
127
+ story_for(:estimate => 5)["estimate"].should == "5"
128
+ end
129
+
130
+ it "should include current_state" do
131
+ story_for(:current_state => "accepted")["current_state"].should == "accepted"
132
+ end
133
+
134
+ it "should include requested_by" do
135
+ story_for(:requested_by => "Joe Doe")["requested_by"].should == "Joe Doe"
136
+ end
137
+
138
+ it "should include owned_by" do
139
+ story_for(:owned_by => "Joe Doe")["owned_by"].should == "Joe Doe"
140
+ end
141
+
142
+ it "should include labels" do
143
+ story_for(:labels => "abc")["labels"].should == "abc"
144
+ end
145
+
146
+ it "should include other_id" do
147
+ story_for(:other_id => 10)["other_id"].should == "10"
148
+ end
149
+
150
+ it "should include integration_id" do
151
+ story_for(:integration_id => 1000)["integration_id"].should == '1000'
152
+ end
153
+
154
+ # the tracker returns 422 when this is included, even if it is not used
155
+ # it "should include jira_id" do
156
+ # story_for(:jira_id => 10)["jira_id"].should == "10"
157
+ # end
158
+ #
159
+ # it "should include jira_url" do
160
+ # story_for(:jira_url => "somewhere")["jira_url"].should == "somewhere"
161
+ # end
162
+
163
+ [:created_at, :accepted_at].each do |date_attribute|
164
+ it "should include #{date_attribute} date when given a string" do
165
+ story_for(:created_at => '9/20/1984, 10:23am UTC')["created_at"].should == "1984-09-20T10:23:00+00:00"
166
+ end
167
+
168
+ it "should include #{date_attribute} date when given a Time" do
169
+ story_for(:created_at => Time.parse('9/20/1984, 10:23am UTC'))["created_at"].should == "1984-09-20T10:23:00+00:00"
170
+ end
171
+
172
+ it "should include #{date_attribute} date when given a DateTime" do
173
+ story_for(:created_at => DateTime.parse('9/20/1984, 10:23am UTC'))["created_at"].should == "1984-09-20T10:23:00+00:00"
174
+ end
175
+
176
+ it "should include #{date_attribute} date when given a Date" do
177
+ # Dates don't have time zones, but the time will be in local time, so we convert the date to create the expectation
178
+ story_for(:created_at => Date.parse('9/20/1984'))["created_at"].should == DateTime.parse('9/20/1984').to_s
179
+ end
180
+ end
181
+ end
182
+
183
+ end
184
+
185
+ end