lrd-pivotal-tracker 0.5.14
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.
- checksums.yaml +7 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +94 -0
- data/LICENSE +21 -0
- data/README.rdoc +82 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/lib/pivotal-tracker.rb +49 -0
- data/lib/pivotal-tracker/activity.rb +68 -0
- data/lib/pivotal-tracker/attachment.rb +16 -0
- data/lib/pivotal-tracker/author.rb +16 -0
- data/lib/pivotal-tracker/client.rb +84 -0
- data/lib/pivotal-tracker/extensions.rb +11 -0
- data/lib/pivotal-tracker/iteration.rb +40 -0
- data/lib/pivotal-tracker/membership.rb +20 -0
- data/lib/pivotal-tracker/note.rb +58 -0
- data/lib/pivotal-tracker/project.rb +98 -0
- data/lib/pivotal-tracker/proxy.rb +64 -0
- data/lib/pivotal-tracker/story.rb +153 -0
- data/lib/pivotal-tracker/task.rb +71 -0
- data/lib/pivotal-tracker/validation.rb +69 -0
- data/lib/pivotal_tracker.rb +2 -0
- data/lrd-pivotal-tracker.gemspec +68 -0
- data/spec/fixtures/vcr_cassettes/default_vcr_cassette.yml +6936 -0
- data/spec/pivotal-tracker/activity_spec.rb +53 -0
- data/spec/pivotal-tracker/attachment_spec.rb +63 -0
- data/spec/pivotal-tracker/client_spec.rb +156 -0
- data/spec/pivotal-tracker/iteration_spec.rb +76 -0
- data/spec/pivotal-tracker/membership_spec.rb +21 -0
- data/spec/pivotal-tracker/note_spec.rb +62 -0
- data/spec/pivotal-tracker/project_spec.rb +105 -0
- data/spec/pivotal-tracker/story_spec.rb +248 -0
- data/spec/pivotal-tracker/task_spec.rb +34 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/vcr_config.rb +10 -0
- metadata +169 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PivotalTracker::Activity do
|
4
|
+
|
5
|
+
before do
|
6
|
+
PivotalTracker::Client.token = TOKEN
|
7
|
+
end
|
8
|
+
|
9
|
+
context "without a specified project" do
|
10
|
+
it "should return an array of activities" do
|
11
|
+
PivotalTracker::Activity.all.should be_a(Array)
|
12
|
+
PivotalTracker::Activity.all.first.should be_a(PivotalTracker::Activity)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "with a specified project" do
|
17
|
+
before do
|
18
|
+
@project = PivotalTracker::Project.find(PROJECT_ID)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return an array of activities" do
|
22
|
+
@project.activities.all.should be_a(Array)
|
23
|
+
@project.activities.all.first.should be_a(PivotalTracker::Activity)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with a project and autopage" do
|
29
|
+
before do
|
30
|
+
PivotalTracker::Client.api_version = 4
|
31
|
+
@page_project = PivotalTracker::Project.find(PAGE_PROJECT_ID)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should be able to page through activities" do
|
35
|
+
@page_project.activities.all(:auto_page => true).size.should > 100
|
36
|
+
end
|
37
|
+
|
38
|
+
after do
|
39
|
+
PivotalTracker::Client.api_version = 3
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with a specified occurred since date filter" do
|
45
|
+
it "should correctly url encode the occurred since date filter in the API call" do
|
46
|
+
PivotalTracker::Client.stub!(:connection).and_return connection = double("Client Connection")
|
47
|
+
url = "/activities?limit=100&occurred_since_date=2010/07/29%2019:13:00%20+00:00"
|
48
|
+
connection.should_receive(:[]).with(url).and_return double("Connection", :get => '<blah></blah>')
|
49
|
+
PivotalTracker::Activity.all nil, :limit => 100, :occurred_since_date => DateTime.parse("2010/7/29 19:13:00 UTC")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
describe PivotalTracker::Attachment do
|
5
|
+
|
6
|
+
before do
|
7
|
+
PivotalTracker::Client.token = TOKEN
|
8
|
+
@project = PivotalTracker::Project.find(PROJECT_ID)
|
9
|
+
@story = @project.stories.find(ATTACHMENT_STORY)
|
10
|
+
end
|
11
|
+
|
12
|
+
context "always" do
|
13
|
+
it "should return an integer id" do
|
14
|
+
@story.attachments.first.id.should be_a(Integer)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return a string for url" do
|
18
|
+
@story.attachments.first.url.should be_a(String)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return a string for filename" do
|
22
|
+
@story.attachments.first.filename.should be_a(String)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return a string for uploaded_by" do
|
26
|
+
@story.attachments.first.uploaded_by.should be_a(String)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return a datetime for uploaded_at" do
|
30
|
+
@story.attachments.first.uploaded_at.should be_a(DateTime)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "without description" do
|
35
|
+
it "should have a blank string for the description" do
|
36
|
+
@story.attachments.first.description.should be_a(String)
|
37
|
+
@story.attachments.first.description.should be_empty
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with description" do
|
42
|
+
it "should have a non-blank string for the description" do
|
43
|
+
@story.attachments.first.description.should be_a(String)
|
44
|
+
@story.attachments.last.description.should_not be_empty
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "uploading" do
|
49
|
+
|
50
|
+
before do
|
51
|
+
@target_story = @project.stories.find(UPLOAD_STORY)
|
52
|
+
@orig_net_lock = FakeWeb.allow_net_connect?
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return an attachment object with a pending status" do
|
56
|
+
FakeWeb.allow_net_connect = true
|
57
|
+
resource = @target_story.upload_attachment(File.dirname(__FILE__) + '/../../LICENSE')
|
58
|
+
FakeWeb.allow_net_connect = @orig_net_lock
|
59
|
+
resource.should be_a(PivotalTracker::Attachment)
|
60
|
+
resource.status.should == 'Pending'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe PivotalTracker::Client do
|
4
|
+
|
5
|
+
describe ".connection" do
|
6
|
+
|
7
|
+
context "with no existing token" do
|
8
|
+
|
9
|
+
before do
|
10
|
+
PivotalTracker::Client.token = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it "raises a NoToken exception" do
|
14
|
+
lambda { PivotalTracker::Client.connection }.should raise_error(PivotalTracker::Client::NoToken)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "after setting a new token" do
|
18
|
+
|
19
|
+
before do
|
20
|
+
PivotalTracker::Client.token = "anewtoken"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "called to RestClient::Resource using the new token" do
|
24
|
+
RestClient::Resource.should_receive(:new).
|
25
|
+
with(PivotalTracker::Client.api_url, :headers => { 'X-TrackerToken' => "anewtoken", 'Content-Type' => 'application/xml' })
|
26
|
+
|
27
|
+
PivotalTracker::Client.connection
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returned the connection for the new token" do
|
31
|
+
@resource = Object.new
|
32
|
+
|
33
|
+
RestClient::Resource.should_receive(:new).
|
34
|
+
with(PivotalTracker::Client.api_url, :headers => { 'X-TrackerToken' => "anewtoken", 'Content-Type' => 'application/xml' }).
|
35
|
+
and_return(@resource)
|
36
|
+
|
37
|
+
PivotalTracker::Client.connection.should == @resource
|
38
|
+
|
39
|
+
# We need to clear the connections or it causes later spec failures
|
40
|
+
PivotalTracker::Client.clear_connections
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with an existing token" do
|
48
|
+
|
49
|
+
before do
|
50
|
+
PivotalTracker::Client.token = "abc123"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returned a RestClient::Resource using the token" do
|
54
|
+
@resource = Object.new
|
55
|
+
|
56
|
+
RestClient::Resource.should_receive(:new).
|
57
|
+
with(PivotalTracker::Client.api_url, :headers => { 'X-TrackerToken' => "abc123", 'Content-Type' => 'application/xml' }).
|
58
|
+
and_return(@resource)
|
59
|
+
|
60
|
+
PivotalTracker::Client.connection.should == @resource
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "after setting a new token" do
|
64
|
+
|
65
|
+
before do
|
66
|
+
PivotalTracker::Client.token = "anewtoken"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "called to RestClient::Resource using the new token" do
|
70
|
+
RestClient::Resource.should_receive(:new).
|
71
|
+
with(PivotalTracker::Client.api_url, :headers => { 'X-TrackerToken' => "anewtoken", 'Content-Type' => 'application/xml' })
|
72
|
+
|
73
|
+
PivotalTracker::Client.connection
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returned the connection for the new token" do
|
77
|
+
@resource = Object.new
|
78
|
+
|
79
|
+
RestClient::Resource.should_receive(:new).
|
80
|
+
with(PivotalTracker::Client.api_url, :headers => { 'X-TrackerToken' => "anewtoken", 'Content-Type' => 'application/xml' }).
|
81
|
+
and_return(@resource)
|
82
|
+
|
83
|
+
PivotalTracker::Client.connection.should == @resource
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe ".tracker_host" do
|
92
|
+
it "returns www.pivotaltracker.com by default" do
|
93
|
+
PivotalTracker::Client.tracker_host.should == 'www.pivotaltracker.com'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe ".tracker_host=" do
|
98
|
+
it "sets the tracker_host" do
|
99
|
+
tracker_host_url = 'http://some_other_tracker_tracker_host_url'
|
100
|
+
PivotalTracker::Client.tracker_host = tracker_host_url
|
101
|
+
PivotalTracker::Client.tracker_host.should == tracker_host_url
|
102
|
+
PivotalTracker::Client.tracker_host = nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#api_ssl_url" do
|
107
|
+
context "when not passed a username and password" do
|
108
|
+
before do
|
109
|
+
PivotalTracker::Client.tracker_host = nil
|
110
|
+
PivotalTracker::Client.use_ssl = true
|
111
|
+
end
|
112
|
+
it "returns https://www.pivotaltracker.com/services/v3" do
|
113
|
+
PivotalTracker::Client.api_ssl_url.should == 'https://www.pivotaltracker.com/services/v3'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
context "when passed a username and password" do
|
117
|
+
before do
|
118
|
+
PivotalTracker::Client.tracker_host = nil
|
119
|
+
PivotalTracker::Client.use_ssl = false
|
120
|
+
end
|
121
|
+
it "returns https://USER:PASSWORD@www.pivotaltracker.com/services/v3" do
|
122
|
+
PivotalTracker::Client.api_ssl_url('USER', 'PASSWORD').should == 'https://USER:PASSWORD@www.pivotaltracker.com/services/v3'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#api_url" do
|
128
|
+
context "when not passed a username and password" do
|
129
|
+
before do
|
130
|
+
PivotalTracker::Client.tracker_host = nil
|
131
|
+
PivotalTracker::Client.use_ssl = true
|
132
|
+
end
|
133
|
+
it "returns https://www.pivotaltracker.com/services/v3" do
|
134
|
+
PivotalTracker::Client.api_ssl_url.should == 'https://www.pivotaltracker.com/services/v3'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
context "when passed a username and password" do
|
138
|
+
before do
|
139
|
+
PivotalTracker::Client.tracker_host = nil
|
140
|
+
PivotalTracker::Client.use_ssl = false
|
141
|
+
end
|
142
|
+
it "returns https://www.pivotaltracker.com/services/v3" do
|
143
|
+
PivotalTracker::Client.api_ssl_url('user', 'password').should == 'https://user:password@www.pivotaltracker.com/services/v3'
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "#api_version" do
|
149
|
+
it "sets the api_version" do
|
150
|
+
PivotalTracker::Client.api_version = 4
|
151
|
+
PivotalTracker::Client.api_version.should == 4
|
152
|
+
PivotalTracker::Client.api_version = 3
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PivotalTracker::Iteration do
|
4
|
+
before do
|
5
|
+
PivotalTracker::Client.token = TOKEN
|
6
|
+
@project = PivotalTracker::Project.find(PAGE_PROJECT_ID)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".all" do
|
10
|
+
before do
|
11
|
+
@iterations = PivotalTracker::Iteration.all(@project)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return an array of Iterations for the given Project" do
|
15
|
+
@iterations.should be_a(Array)
|
16
|
+
@iterations.first.should be_a(PivotalTracker::Iteration)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".current" do
|
21
|
+
before do
|
22
|
+
@iteration = PivotalTracker::Iteration.current(@project)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return a single Iteration" do
|
26
|
+
@iteration.should be_a(PivotalTracker::Iteration)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".backlog" do
|
31
|
+
before do
|
32
|
+
@iterations = PivotalTracker::Iteration.backlog(@project)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return an array of Iterations for the given Project" do
|
36
|
+
@iterations.should be_a(Array)
|
37
|
+
@iterations.first.should be_a(PivotalTracker::Iteration)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".done" do
|
42
|
+
before do
|
43
|
+
@iterations = PivotalTracker::Iteration.done(@project)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return an array of Iterations for the given Project" do
|
47
|
+
@iterations.should be_a(Array)
|
48
|
+
@iterations.first.should be_a(PivotalTracker::Iteration)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe ".current_backlog" do
|
53
|
+
before do
|
54
|
+
@iterations = PivotalTracker::Iteration.current_backlog(@project)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return an array of Iterations for the given Project" do
|
58
|
+
@iterations.should be_a(Array)
|
59
|
+
@iterations.first.should be_a(PivotalTracker::Iteration)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe ".team_strength" do
|
64
|
+
before do
|
65
|
+
@iteration = PivotalTracker::Iteration.current(@project)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should return a Float" do
|
69
|
+
@iteration.should respond_to(:team_strength)
|
70
|
+
@iteration.team_strength.should be_a(Float)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PivotalTracker::Project do
|
4
|
+
before do
|
5
|
+
PivotalTracker::Client.token = TOKEN
|
6
|
+
@project = PivotalTracker::Project.find(PROJECT_ID)
|
7
|
+
end
|
8
|
+
|
9
|
+
context ".all" do
|
10
|
+
it "should return an array of memberships" do
|
11
|
+
@project.memberships.all.should be_a(Array)
|
12
|
+
@project.memberships.all.first.should be_a(PivotalTracker::Membership)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context ".find" do
|
17
|
+
it "should return the given membership" do
|
18
|
+
@project.memberships.find(MEMBER).should be_a(PivotalTracker::Membership)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PivotalTracker::Note do
|
4
|
+
before do
|
5
|
+
PivotalTracker::Client.token = TOKEN
|
6
|
+
@project = PivotalTracker::Project.find(PROJECT_ID)
|
7
|
+
@story = @project.stories.find(ATTACHMENT_STORY)
|
8
|
+
end
|
9
|
+
|
10
|
+
context ".all" do
|
11
|
+
it "should return an array of notes" do
|
12
|
+
@story.notes.all.should be_a(Array)
|
13
|
+
@story.notes.all.first.should be_a(PivotalTracker::Note)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
#context ".find" do
|
18
|
+
# it "should return a given task" do
|
19
|
+
# @story.tasks.find(179025).should be_a(PivotalTracker::Task)
|
20
|
+
# end
|
21
|
+
#end
|
22
|
+
|
23
|
+
context ".create" do
|
24
|
+
it "should return the created note" do
|
25
|
+
@story.notes.create(:text => 'Test note')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context ".new" do
|
30
|
+
|
31
|
+
def note_for(attrs)
|
32
|
+
note = @story.notes.new(attrs)
|
33
|
+
@note = Crack::XML.parse(note.send(:to_xml))['note']
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "attributes that are not sent to the tracker" do
|
37
|
+
|
38
|
+
it "should include id" do
|
39
|
+
note_for(:id => 10)["id"].should be_nil
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should include author" do
|
43
|
+
note_for(:author => "somebody")["author"].should be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "attributes that are sent to the tracker" do
|
49
|
+
|
50
|
+
it "should include text" do
|
51
|
+
note_for(:text => "A comment...")["text"].should == "A comment..."
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should include noted_at" do
|
55
|
+
note_for(:noted_at => "timestamp")["noted_at"].should == "timestamp"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PivotalTracker::Project do
|
4
|
+
|
5
|
+
before do
|
6
|
+
PivotalTracker::Client.token = TOKEN
|
7
|
+
end
|
8
|
+
|
9
|
+
context ".all" do
|
10
|
+
before do
|
11
|
+
@projects = PivotalTracker::Project.all
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return an array of available projects" do
|
15
|
+
@projects.should be_a(Array)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be a project instance" do
|
19
|
+
@projects.first.should be_a(PivotalTracker::Project)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context ".find" do
|
24
|
+
before do
|
25
|
+
@project = PivotalTracker::Project.find(PROJECT_ID)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be an instance of Project" do
|
29
|
+
@project.should be_a(PivotalTracker::Project)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have a use_https attribute" do
|
33
|
+
@project.respond_to?(:use_https).should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have false for use_https" do
|
37
|
+
@project.use_https.should be_false
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should have first_iteration_start_time attribute" do
|
41
|
+
@project.respond_to?(:first_iteration_start_time).should be_true
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have current_iteration_number attribute" do
|
45
|
+
@project.respond_to?(:current_iteration_number).should be_true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context ".stories" do
|
50
|
+
before do
|
51
|
+
PivotalTracker::Client.token = TOKEN
|
52
|
+
@project = PivotalTracker::Project.find(PROJECT_ID)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should have a stories association" do
|
56
|
+
@project.respond_to?(:stories).should be_true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context ".memberships" do
|
61
|
+
before do
|
62
|
+
PivotalTracker::Client.token = TOKEN
|
63
|
+
@project = PivotalTracker::Project.find(PROJECT_ID)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should have a memberships association" do
|
67
|
+
@project.respond_to?(:memberships).should be_true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context ".create" do
|
72
|
+
before do
|
73
|
+
PivotalTracker::Client.token = TOKEN
|
74
|
+
@project = PivotalTracker::Project.new(:name => 'Pivotal Tracker API Gem')
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should return the created project" do
|
78
|
+
@project.create
|
79
|
+
@project.should be_a(PivotalTracker::Project)
|
80
|
+
@project.name.should == 'Pivotal Tracker API Gem'
|
81
|
+
end
|
82
|
+
|
83
|
+
context "on failure" do
|
84
|
+
before do
|
85
|
+
FakeWeb.register_uri(:post, "#{PivotalTracker::Client.api_url}/projects",
|
86
|
+
:body => %{<?xml version="1.0" encoding="UTF-8"?>
|
87
|
+
<errors>
|
88
|
+
<error>error#1 message</error>
|
89
|
+
<error>error#2 message</error>
|
90
|
+
</errors>%},
|
91
|
+
:status => "422")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not raise an exception" do
|
95
|
+
expect { @project.create }.to_not raise_error(Exception)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should report errors encountered" do
|
99
|
+
@project.create
|
100
|
+
@project.errors.messages.should =~ ["error#1 message", "error#2 message"]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|