Commit 07720a8f0ef44457bdbb8030894211f69e0201af
1 parent
4e7477d1
Exists in
master
and in
1 other branch
* Major reorganization of issue tracker specs. Migrated specs out of the errs_co…
…ntroller into their respective models. * Wrote specs for Fogbugz. Turns out that the Fogbugz API used the 'Crack' gem which happened to break mongoid by playing with the String class. See here for details: [ https://github.com/mongoid/mongoid/issues/618 ]. * This is why I had to upgrade mongoid to version 2.1.1, which included the 'Crack' fix. Upgrading Mongoid to 2.1.1 required the following changes: ** Fixing a counter_cache test on Err model ** Namespacing all of the subclassed IssueTracker models based on their parent directory ** Setting `config.mongoid.preload_models = true` in config/application.rb
Showing
22 changed files
with
180 additions
and
195 deletions
Show diff stats
Gemfile
Gemfile.lock
... | ... | @@ -94,7 +94,7 @@ GEM |
94 | 94 | mime-types (1.16) |
95 | 95 | mongo (1.3.1) |
96 | 96 | bson (>= 1.3.1) |
97 | - mongoid (2.0.2) | |
97 | + mongoid (2.1.1) | |
98 | 98 | activemodel (~> 3.0) |
99 | 99 | mongo (~> 1.3) |
100 | 100 | tzinfo (~> 0.3.22) |
... | ... | @@ -208,7 +208,7 @@ DEPENDENCIES |
208 | 208 | hoptoad_notifier (~> 2.3) |
209 | 209 | inherited_resources |
210 | 210 | lighthouse-api |
211 | - mongoid (= 2.0.2) | |
211 | + mongoid (= 2.1.1) | |
212 | 212 | mongoid_rails_migrations |
213 | 213 | nokogiri |
214 | 214 | octokit | ... | ... |
app/models/issue_trackers/fogbugz_tracker.rb
app/models/issue_trackers/github_tracker.rb
app/models/issue_trackers/lighthouse_tracker.rb
app/models/issue_trackers/mingle_tracker.rb
app/models/issue_trackers/pivotal_labs_tracker.rb
app/models/issue_trackers/redmine_tracker.rb
config/application.rb
... | ... | @@ -46,6 +46,9 @@ module Errbit |
46 | 46 | g.test_framework :rspec, :fixture => false |
47 | 47 | end |
48 | 48 | |
49 | + # IssueTracker subclasses use inheritance, so preloading models provides querying consistency in dev mode. | |
50 | + config.mongoid.preload_models = true | |
51 | + | |
49 | 52 | # Configure the default encoding used in templates for Ruby 1.9. |
50 | 53 | config.encoding = "utf-8" |
51 | 54 | ... | ... |
config/initializers/issue_tracker_apis.rb
spec/controllers/errs_controller_spec.rb
... | ... | @@ -269,178 +269,16 @@ describe ErrsController do |
269 | 269 | number = 5 |
270 | 270 | @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml" |
271 | 271 | body = "<ticket><number type=\"integer\">#{number}</number></ticket>" |
272 | - stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | |
273 | - | |
274 | - post :create_issue, :app_id => err.app.id, :id => err.id | |
275 | - err.reload | |
276 | - end | |
277 | - | |
278 | - it "should make request to Lighthouseapp with err params" do | |
279 | - requested = have_requested(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml") | |
280 | - WebMock.should requested.with(:headers => {'X-Lighthousetoken' => tracker.api_token}) | |
281 | - WebMock.should requested.with(:body => /<tag>errbit<\/tag>/) | |
282 | - WebMock.should requested.with(:body => /<title>\[#{ err.environment }\]\[#{err.where}\] #{err.message.to_s.truncate(100)}<\/title>/) | |
283 | - WebMock.should requested.with(:body => /<body>.+<\/body>/m) | |
284 | - end | |
285 | - | |
286 | - it "should redirect to err page" do | |
287 | - response.should redirect_to( app_err_path(err.app, err) ) | |
288 | - end | |
289 | - | |
290 | - it "should create issue link for err" do | |
291 | - err.issue_link.should == @issue_link.sub(/\.xml$/, '') | |
292 | - end | |
293 | - end | |
294 | - | |
295 | - context "redmine tracker" do | |
296 | - let(:notice) { Factory :notice } | |
297 | - let(:tracker) { Factory :redmine_tracker, :app => notice.err.app } | |
298 | - let(:err) { notice.err } | |
299 | - | |
300 | - before(:each) do | |
301 | - number = 5 | |
302 | - @issue_link = "#{tracker.account}/issues/#{number}.xml?project_id=#{tracker.project_id}" | |
303 | - body = "<issue><subject>my subject</subject><id>#{number}</id></issue>" | |
304 | - stub_request(:post, "#{tracker.account}/issues.xml").to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | |
305 | - | |
306 | - post :create_issue, :app_id => err.app.id, :id => err.id | |
307 | - err.reload | |
308 | - end | |
309 | - | |
310 | - it "should make request to Redmine with err params" do | |
311 | - requested = have_requested(:post, "#{tracker.account}/issues.xml") | |
312 | - WebMock.should requested.with(:headers => {'X-Redmine-API-Key' => tracker.api_token}) | |
313 | - WebMock.should requested.with(:body => /<project-id>#{tracker.project_id}<\/project-id>/) | |
314 | - WebMock.should requested.with(:body => /<subject>\[#{ err.environment }\]\[#{err.where}\] #{err.message.to_s.truncate(100)}<\/subject>/) | |
315 | - WebMock.should requested.with(:body => /<description>.+<\/description>/m) | |
316 | - end | |
317 | - | |
318 | - it "should redirect to err page" do | |
319 | - response.should redirect_to( app_err_path(err.app, err) ) | |
320 | - end | |
321 | - | |
322 | - it "should create issue link for err" do | |
323 | - err.issue_link.should == @issue_link.sub(/\.xml/, '') | |
324 | - end | |
325 | - end | |
326 | - | |
327 | - context "pivotal tracker" do | |
328 | - let(:notice) { Factory :notice } | |
329 | - let(:tracker) { Factory :pivotal_labs_tracker, :app => notice.err.app, :project_id => 10 } | |
330 | - let(:err) { notice.err } | |
331 | - | |
332 | - before(:each) do | |
333 | - story_id = 5 | |
334 | - @issue_link = "https://www.pivotaltracker.com/story/show/#{story_id}" | |
335 | - | |
336 | - project_body = "<project><id>#{tracker.project_id}</id><name>TestProject</name></project>" | |
337 | - stub_request(:get, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}"). | |
338 | - to_return(:status => 200, :headers => {'Location' => @issue_link}, :body => project_body ) | |
339 | - | |
340 | - story_body = "<story><name>Test Story</name><id>#{story_id}</id></story>" | |
341 | - stub_request(:post, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}/stories"). | |
342 | - to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => story_body ) | |
343 | - | |
344 | - post :create_issue, :app_id => err.app.id, :id => err.id | |
345 | - err.reload | |
346 | - end | |
347 | - | |
348 | - it "should make request to Pivotal Tracker with err params" do | |
349 | - requested = have_requested(:post, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}/stories") | |
350 | - WebMock.should requested.with(:headers => {'X-Trackertoken' => tracker.api_token}) | |
351 | - WebMock.should requested.with(:body => /See this exception on Errbit/) | |
352 | - WebMock.should requested.with(:body => /<name>\[#{ err.environment }\]\[#{err.where}\] #{err.message.to_s.truncate(100)}<\/name>/) | |
353 | - WebMock.should requested.with(:body => /<description>.+<\/description>/m) | |
354 | - end | |
355 | - | |
356 | - it "should redirect to err page" do | |
357 | - response.should redirect_to( app_err_path(err.app, err) ) | |
358 | - end | |
359 | - | |
360 | - it "should create issue link for err" do | |
361 | - err.issue_link.should == @issue_link | |
362 | - end | |
363 | - end | |
364 | - | |
365 | - context "mingle tracker" do | |
366 | - let(:notice) { Factory :notice } | |
367 | - let(:tracker) { Factory :mingle_tracker, :app => notice.err.app } | |
368 | - let(:err) { notice.err } | |
369 | - | |
370 | - before(:each) do | |
371 | - number = 5 | |
372 | - @issue_link = "#{tracker.account}/projects/#{tracker.project_id}/cards/#{number}.xml" | |
373 | - @basic_auth = tracker.account.gsub("://", "://#{tracker.username}:#{tracker.password}@") | |
374 | - body = "<card><id type=\"integer\">#{number}</id></card>" | |
375 | - stub_request(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml"). | |
272 | + stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml"). | |
376 | 273 | to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) |
377 | 274 | |
378 | 275 | post :create_issue, :app_id => err.app.id, :id => err.id |
379 | 276 | err.reload |
380 | 277 | end |
381 | 278 | |
382 | - it "should make request to Mingle with err params" do | |
383 | - requested = have_requested(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml") | |
384 | - WebMock.should requested.with(:headers => {'Content-Type' => 'application/xml'}) | |
385 | - WebMock.should requested.with(:body => /FooError: Too Much Bar/) | |
386 | - WebMock.should requested.with(:body => /See this exception on Errbit/) | |
387 | - WebMock.should requested.with(:body => /<card-type-name>Defect<\/card-type-name>/) | |
388 | - end | |
389 | - | |
390 | - it "should redirect to err page" do | |
391 | - response.should redirect_to( app_err_path(err.app, err) ) | |
392 | - end | |
393 | - | |
394 | - it "should create issue link for err" do | |
395 | - err.issue_link.should == @issue_link.sub(/\.xml$/, '') | |
396 | - end | |
397 | - end | |
398 | - | |
399 | - context "github issues tracker" do | |
400 | - let(:notice) { Factory :notice } | |
401 | - let(:tracker) { Factory :github_tracker, :app => notice.err.app } | |
402 | - let(:err) { notice.err } | |
403 | - | |
404 | - before(:each) do | |
405 | - number = 5 | |
406 | - @issue_link = "https://github.com/#{tracker.project_id}/issues/#{number}" | |
407 | - body = <<EOF | |
408 | -{ | |
409 | - "issue": { | |
410 | - "position": 1.0, | |
411 | - "number": #{number}, | |
412 | - "votes": 0, | |
413 | - "created_at": "2010/01/21 13:45:59 -0800", | |
414 | - "comments": 0, | |
415 | - "body": "Test Body", | |
416 | - "title": "Test Issue", | |
417 | - "user": "test_user", | |
418 | - "state": "open", | |
419 | - "html_url": "#{@issue_link}" | |
420 | - } | |
421 | -} | |
422 | -EOF | |
423 | - stub_request(:post, "https://#{tracker.username}%2Ftoken:#{tracker.api_token}@github.com/api/v2/json/issues/open/#{tracker.project_id}"). | |
424 | - to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | |
425 | - | |
426 | - post :create_issue, :app_id => err.app.id, :id => err.id | |
427 | - err.reload | |
428 | - end | |
429 | - | |
430 | - it "should make request to Github with err params" do | |
431 | - requested = have_requested(:post, "https://#{tracker.username}%2Ftoken:#{tracker.api_token}@github.com/api/v2/json/issues/open/#{tracker.project_id}") | |
432 | - WebMock.should requested.with(:headers => {'Content-Type' => 'application/x-www-form-urlencoded'}) | |
433 | - WebMock.should requested.with(:body => /title=%5Bproduction%5D%5Bfoo%23bar%5D%20FooError%3A%20Too%20Much%20Bar/) | |
434 | - WebMock.should requested.with(:body => /See%20this%20exception%20on%20Errbit/) | |
435 | - end | |
436 | - | |
437 | 279 | it "should redirect to err page" do |
438 | 280 | response.should redirect_to( app_err_path(err.app, err) ) |
439 | 281 | end |
440 | - | |
441 | - it "should create issue link for err" do | |
442 | - err.issue_link.should == @issue_link | |
443 | - end | |
444 | 282 | end |
445 | 283 | end |
446 | 284 | ... | ... |
spec/factories/err_factories.rb
spec/factories/issue_tracker_factories.rb
spec/models/err_spec.rb
... | ... | @@ -162,9 +162,11 @@ describe Err do |
162 | 162 | notice1 = Factory(:notice, :err => @err, :message => 'ERR 1') |
163 | 163 | lambda { |
164 | 164 | @err.notices.first.destroy |
165 | + @err.reload | |
165 | 166 | }.should change(@err, :notices_count).from(1).to(0) |
166 | 167 | end |
167 | 168 | end |
168 | 169 | |
169 | 170 | |
170 | 171 | end |
172 | + | ... | ... |
spec/models/issue_tracker_spec.rb
spec/models/issue_trackers/fogbugz_tracker_spec.rb
1 | -# encoding: utf-8 | |
2 | 1 | require 'spec_helper' |
3 | 2 | |
4 | 3 | describe FogbugzTracker do |
5 | - let(:notice) { Factory :notice } | |
6 | - let(:tracker) { Factory :fogbugz_tracker, :password => "password", :app => notice.err.app } | |
7 | - let(:err) { notice.err } | |
4 | + it "should create an issue on Fogbugz with err params, and set issue link for err" do | |
5 | + notice = Factory :notice | |
6 | + tracker = Factory :fogbugz_tracker, :app => notice.err.app | |
7 | + err = notice.err | |
8 | 8 | |
9 | - before do | |
10 | 9 | number = 123 |
11 | 10 | @issue_link = "https://#{tracker.account}.fogbugz.com/default.asp?#{number}" |
12 | - auth_response = "<response><token>12345</token></response>" | |
13 | - command_response = "<response><case><ixBug>123</ixBug></case></response>" | |
11 | + response = "<response><token>12345</token><case><ixBug>123</ixBug></case></response>" | |
14 | 12 | http_mock = mock() |
15 | 13 | http_mock.should_receive(:new).and_return(http_mock) |
16 | - http_mock.should_receive(:request).with(:logon, {:params=>{:email=>"test@example.com", :password=>"password"}}). | |
17 | - and_return(auth_response) | |
18 | - http_mock.should_receive(:request). | |
19 | - and_return(command_response) | |
14 | + http_mock.should_receive(:request).twice.and_return(response) | |
20 | 15 | Fogbugz.adapter[:http] = http_mock |
21 | - end | |
22 | 16 | |
23 | - it "should create an issue on Fogbugz with err params, and set issue link for err" do | |
24 | 17 | err.app.issue_tracker.create_issue(err) |
25 | 18 | err.reload |
26 | 19 | ... | ... |
... | ... | @@ -0,0 +1,41 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe GithubTracker do | |
4 | + it "should create an issue on Github Issues with err params, and set issue link for err" do | |
5 | + notice = Factory :notice | |
6 | + tracker = Factory :github_tracker, :app => notice.err.app | |
7 | + err = notice.err | |
8 | + | |
9 | + number = 5 | |
10 | + @issue_link = "https://github.com/#{tracker.project_id}/issues/#{number}" | |
11 | + body = <<EOF | |
12 | +{ | |
13 | + "issue": { | |
14 | + "position": 1.0, | |
15 | + "number": #{number}, | |
16 | + "votes": 0, | |
17 | + "created_at": "2010/01/21 13:45:59 -0800", | |
18 | + "comments": 0, | |
19 | + "body": "Test Body", | |
20 | + "title": "Test Issue", | |
21 | + "user": "test_user", | |
22 | + "state": "open", | |
23 | + "html_url": "#{@issue_link}" | |
24 | + } | |
25 | +} | |
26 | +EOF | |
27 | + stub_request(:post, "https://#{tracker.username}%2Ftoken:#{tracker.api_token}@github.com/api/v2/json/issues/open/#{tracker.project_id}"). | |
28 | + to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | |
29 | + | |
30 | + err.app.issue_tracker.create_issue(err) | |
31 | + err.reload | |
32 | + | |
33 | + requested = have_requested(:post, "https://#{tracker.username}%2Ftoken:#{tracker.api_token}@github.com/api/v2/json/issues/open/#{tracker.project_id}") | |
34 | + WebMock.should requested.with(:headers => {'Content-Type' => 'application/x-www-form-urlencoded'}) | |
35 | + WebMock.should requested.with(:body => /title=%5Bproduction%5D%5Bfoo%23bar%5D%20FooError%3A%20Too%20Much%20Bar/) | |
36 | + WebMock.should requested.with(:body => /See%20this%20exception%20on%20Errbit/) | |
37 | + | |
38 | + err.issue_link.should == @issue_link | |
39 | + end | |
40 | +end | |
41 | + | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe LighthouseTracker do | |
4 | + it "should create an issue on Lighthouse with err params, and set issue link for err" do | |
5 | + notice = Factory :notice | |
6 | + tracker = Factory :lighthouse_tracker, :app => notice.err.app | |
7 | + err = notice.err | |
8 | + | |
9 | + number = 5 | |
10 | + @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml" | |
11 | + body = "<ticket><number type=\"integer\">#{number}</number></ticket>" | |
12 | + stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml"). | |
13 | + to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | |
14 | + | |
15 | + err.app.issue_tracker.create_issue(err) | |
16 | + err.reload | |
17 | + | |
18 | + requested = have_requested(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml") | |
19 | + WebMock.should requested.with(:headers => {'X-Lighthousetoken' => tracker.api_token}) | |
20 | + WebMock.should requested.with(:body => /<tag>errbit<\/tag>/) | |
21 | + WebMock.should requested.with(:body => /<title>\[#{ err.environment }\]\[#{err.where}\] #{err.message.to_s.truncate(100)}<\/title>/) | |
22 | + WebMock.should requested.with(:body => /<body>.+<\/body>/m) | |
23 | + | |
24 | + err.issue_link.should == @issue_link.sub(/\.xml$/, '') | |
25 | + end | |
26 | +end | |
27 | + | ... | ... |
... | ... | @@ -0,0 +1,28 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe MingleTracker do | |
4 | + it "should create an issue on Mingle with err params, and set issue link for err" do | |
5 | + notice = Factory :notice | |
6 | + tracker = Factory :mingle_tracker, :app => notice.err.app | |
7 | + err = notice.err | |
8 | + | |
9 | + number = 5 | |
10 | + @issue_link = "#{tracker.account}/projects/#{tracker.project_id}/cards/#{number}.xml" | |
11 | + @basic_auth = tracker.account.gsub("://", "://#{tracker.username}:#{tracker.password}@") | |
12 | + body = "<card><id type=\"integer\">#{number}</id></card>" | |
13 | + stub_request(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml"). | |
14 | + to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | |
15 | + | |
16 | + err.app.issue_tracker.create_issue(err) | |
17 | + err.reload | |
18 | + | |
19 | + requested = have_requested(:post, "#{@basic_auth}/api/v1/projects/#{tracker.project_id}/cards.xml") | |
20 | + WebMock.should requested.with(:headers => {'Content-Type' => 'application/xml'}) | |
21 | + WebMock.should requested.with(:body => /FooError: Too Much Bar/) | |
22 | + WebMock.should requested.with(:body => /See this exception on Errbit/) | |
23 | + WebMock.should requested.with(:body => /<card-type-name>Defect<\/card-type-name>/) | |
24 | + | |
25 | + err.issue_link.should == @issue_link.sub(/\.xml$/, '') | |
26 | + end | |
27 | +end | |
28 | + | ... | ... |
... | ... | @@ -0,0 +1,30 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe PivotalLabsTracker do | |
4 | + it "should create an issue on Pivotal Tracker with err params, and set issue link for err" do | |
5 | + notice = Factory :notice | |
6 | + tracker = Factory :pivotal_labs_tracker, :app => notice.err.app, :project_id => 10 | |
7 | + err = notice.err | |
8 | + | |
9 | + story_id = 5 | |
10 | + @issue_link = "https://www.pivotaltracker.com/story/show/#{story_id}" | |
11 | + project_body = "<project><id>#{tracker.project_id}</id><name>TestProject</name></project>" | |
12 | + stub_request(:get, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}"). | |
13 | + to_return(:status => 200, :headers => {'Location' => @issue_link}, :body => project_body ) | |
14 | + story_body = "<story><name>Test Story</name><id>#{story_id}</id></story>" | |
15 | + stub_request(:post, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}/stories"). | |
16 | + to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => story_body ) | |
17 | + | |
18 | + err.app.issue_tracker.create_issue(err) | |
19 | + err.reload | |
20 | + | |
21 | + requested = have_requested(:post, "https://www.pivotaltracker.com/services/v3/projects/#{tracker.project_id}/stories") | |
22 | + WebMock.should requested.with(:headers => {'X-Trackertoken' => tracker.api_token}) | |
23 | + WebMock.should requested.with(:body => /See this exception on Errbit/) | |
24 | + WebMock.should requested.with(:body => /<name>\[#{ err.environment }\]\[#{err.where}\] #{err.message.to_s.truncate(100)}<\/name>/) | |
25 | + WebMock.should requested.with(:body => /<description>.+<\/description>/m) | |
26 | + | |
27 | + err.issue_link.should == @issue_link | |
28 | + end | |
29 | +end | |
30 | + | ... | ... |
... | ... | @@ -0,0 +1,26 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe RedmineTracker do | |
4 | + it "should create an issue on Redmine with err params, and set issue link for err" do | |
5 | + notice = Factory :notice | |
6 | + tracker = Factory :redmine_tracker, :app => notice.err.app, :project_id => 10 | |
7 | + err = notice.err | |
8 | + number = 5 | |
9 | + @issue_link = "#{tracker.account}/issues/#{number}.xml?project_id=#{tracker.project_id}" | |
10 | + body = "<issue><subject>my subject</subject><id>#{number}</id></issue>" | |
11 | + stub_request(:post, "#{tracker.account}/issues.xml"). | |
12 | + to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | |
13 | + | |
14 | + err.app.issue_tracker.create_issue(err) | |
15 | + err.reload | |
16 | + | |
17 | + requested = have_requested(:post, "#{tracker.account}/issues.xml") | |
18 | + WebMock.should requested.with(:headers => {'X-Redmine-API-Key' => tracker.api_token}) | |
19 | + WebMock.should requested.with(:body => /<project-id>#{tracker.project_id}<\/project-id>/) | |
20 | + WebMock.should requested.with(:body => /<subject>\[#{ err.environment }\]\[#{err.where}\] #{err.message.to_s.truncate(100)}<\/subject>/) | |
21 | + WebMock.should requested.with(:body => /<description>.+<\/description>/m) | |
22 | + | |
23 | + err.issue_link.should == @issue_link.sub(/\.xml/, '') | |
24 | + end | |
25 | +end | |
26 | + | ... | ... |