artisan-core 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/artisan/activity/activity_interactor.rb +18 -0
- data/lib/artisan/activity/activity_presenter.rb +35 -0
- data/lib/artisan/activity/formatters/diff_changes.rb +41 -0
- data/lib/artisan/activity/formatters/name.rb +22 -0
- data/lib/artisan/activity/formatters/source.rb +16 -0
- data/lib/artisan/activity/formatters/temporal.rb +20 -0
- data/lib/artisan/activity/iteration_auditor.rb +44 -0
- data/lib/artisan/activity/project_auditor.rb +28 -0
- data/lib/artisan/activity/story_auditor.rb +42 -0
- data/lib/artisan/callbacks.rb +27 -0
- data/lib/artisan/crud_strategy.rb +23 -0
- data/lib/artisan/event_mailer.rb +22 -0
- data/lib/artisan/inviter.rb +36 -0
- data/lib/artisan/iterations/iteration_point_calculator.rb +28 -0
- data/lib/artisan/iterations/iteration_presenter.rb +20 -0
- data/lib/artisan/iterations/iteration_workflow_interactor.rb +60 -0
- data/lib/artisan/iterations/iteration_workflow_presenter.rb +11 -0
- data/lib/artisan/iterations/iterations.rb +47 -0
- data/lib/artisan/iterations/iterations_interactor.rb +48 -0
- data/lib/artisan/iterations/move_to_backlog.rb +28 -0
- data/lib/artisan/iterations/story_tags.rb +15 -0
- data/lib/artisan/member.rb +52 -0
- data/lib/artisan/no_op_callbacks.rb +6 -0
- data/lib/artisan/projects/api_key_generator.rb +26 -0
- data/lib/artisan/projects/archive_interactor.rb +29 -0
- data/lib/artisan/projects/completed_stories_presenter.rb +20 -0
- data/lib/artisan/projects/iteration_numberer.rb +15 -0
- data/lib/artisan/projects/project_creator.rb +51 -0
- data/lib/artisan/projects/projects_interactor.rb +58 -0
- data/lib/artisan/projects/projects_presenter.rb +46 -0
- data/lib/artisan/projects/story_point_summer.rb +16 -0
- data/lib/artisan/reports/average_stat_per_iteration_data.rb +55 -0
- data/lib/artisan/reports/burn_up_chart.rb +46 -0
- data/lib/artisan/reports/high_charts_data_retriever.rb +77 -0
- data/lib/artisan/reports/high_charts_interactor.rb +31 -0
- data/lib/artisan/reports/percentage_of_commitments_met_data.rb +47 -0
- data/lib/artisan/reports/signoff/pdf.rb +161 -0
- data/lib/artisan/reports/signoff/report.rb +120 -0
- data/lib/artisan/reports/velocity_report.rb +43 -0
- data/lib/artisan/repository.rb +51 -0
- data/lib/artisan/stories/pert_calculator.rb +62 -0
- data/lib/artisan/stories/stories_interactor.rb +78 -0
- data/lib/artisan/stories/story_collection.rb +66 -0
- data/lib/artisan/stories/story_exporter.rb +45 -0
- data/lib/artisan/stories/story_numberer.rb +15 -0
- data/lib/artisan/stories/story_presenter.rb +23 -0
- data/lib/artisan/stories/story_sorter.rb +37 -0
- data/lib/artisan/story_board.rb +45 -0
- data/lib/artisan/story_column_changer.rb +71 -0
- data/lib/artisan/story_exporter.rb +14 -0
- data/lib/artisan/team.rb +50 -0
- data/spec/crud_strategy_spec.rb +100 -0
- data/spec/event_mailer_spec.rb +86 -0
- data/spec/inviter_spec.rb +58 -0
- data/spec/member_spec.rb +58 -0
- data/spec/repository_spec.rb +32 -0
- data/spec/story_board_spec.rb +36 -0
- data/spec/story_collection_spec.rb +61 -0
- data/spec/story_column_changer_spec.rb +222 -0
- data/spec/story_exporter_spec.rb +25 -0
- data/spec/story_sorter_spec.rb +67 -0
- data/spec/team_spec.rb +107 -0
- metadata +128 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
require "artisan/repository"
|
2
|
+
require "artisan/inviter"
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
class FutureUsers; end
|
6
|
+
class Invites; end
|
7
|
+
|
8
|
+
describe Inviter do
|
9
|
+
let(:email) { 'test@user.com' }
|
10
|
+
let(:name) { 'Mister Person' }
|
11
|
+
|
12
|
+
before do
|
13
|
+
Invites.stub!(:invite).and_return(mock('invites', :deliver => nil))
|
14
|
+
end
|
15
|
+
|
16
|
+
context "alerts" do
|
17
|
+
it "alerts if name and email are nil" do
|
18
|
+
inviter = Inviter.new(nil, nil)
|
19
|
+
lambda{inviter.invite}.should raise_exception("Name and email fields are required, please fill out all fields and try again.")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "alerts if name is blank" do
|
23
|
+
inviter = Inviter.new("", email)
|
24
|
+
lambda{inviter.invite}.should raise_exception("Name and email fields are required, please fill out all fields and try again.")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "alerts if email is blank" do
|
28
|
+
inviter = Inviter.new(name, "")
|
29
|
+
lambda{inviter.invite}.should raise_exception("Name and email fields are required, please fill out all fields and try again.")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "alerts if email is invalid" do
|
33
|
+
inviter = Inviter.new(name, "totallyNotAnEmail")
|
34
|
+
lambda{inviter.invite}.should raise_exception("Name and email fields are required, please fill out all fields and try again.")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "sends invitations" do
|
39
|
+
it "delivers mail with valid addressed" do
|
40
|
+
mail = mock('invite mailer')
|
41
|
+
Invites.should_receive(:invite).with(name, email).and_return(mail)
|
42
|
+
mail.should_receive(:deliver)
|
43
|
+
inviter = Inviter.new(name, email)
|
44
|
+
inviter.invite
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "future users" do
|
49
|
+
it "Adds the email to the future users table" do
|
50
|
+
project = Artisan::Repository.project.create(:name => "Test")
|
51
|
+
|
52
|
+
inviter = Inviter.new(name, email)
|
53
|
+
inviter.add_to_future_users(project)
|
54
|
+
|
55
|
+
Artisan::Repository.future_user.find_by_email(email).project_id.should == project.id
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/spec/member_spec.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "artisan/member"
|
2
|
+
require "artisan-memory-repository/models/user"
|
3
|
+
require "artisan-memory-repository/models/project"
|
4
|
+
require "artisan-memory-repository/models/member"
|
5
|
+
|
6
|
+
describe Artisan::Member do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@user = Artisan::Repository.user.new(:email => "test@gmail.com")
|
10
|
+
@project = Artisan::Repository.project.new
|
11
|
+
@member = Artisan::Repository.member.new
|
12
|
+
@member.stub!(:project).and_return(@project)
|
13
|
+
@member.stub!(:user).and_return(@user)
|
14
|
+
@members = Artisan::Member.new(@member)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "adds the member to the project's completed story email list" do
|
18
|
+
@members.member.project.project_configuration = stub(:story_completed_email_list => []).as_null_object
|
19
|
+
|
20
|
+
@members.add_to_completed_list
|
21
|
+
|
22
|
+
@project.project_configuration.story_completed_email_list.should == [@user.email]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "adds the member to the project's assigned story email list" do
|
26
|
+
@members.member.project.project_configuration = stub(:story_assigned_email_list => []).as_null_object
|
27
|
+
|
28
|
+
@members.add_to_assigned_list
|
29
|
+
|
30
|
+
@project.project_configuration.story_assigned_email_list.should == [@user.email]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "removes the member from the project's completed story email list" do
|
34
|
+
@members.member.project.project_configuration = stub(:story_completed_email_list => [@user.email]).as_null_object
|
35
|
+
|
36
|
+
@members.remove_from_completed_list
|
37
|
+
|
38
|
+
@project.project_configuration.story_completed_email_list.should == []
|
39
|
+
end
|
40
|
+
|
41
|
+
it "removes the member from the project's assigned story email list" do
|
42
|
+
@members.member.project.project_configuration = stub(:story_assigned_email_list => [@user.email]).as_null_object
|
43
|
+
|
44
|
+
@members.remove_from_assigned_list
|
45
|
+
|
46
|
+
@project.project_configuration.story_assigned_email_list.should == []
|
47
|
+
end
|
48
|
+
|
49
|
+
it "removes the member from the project's email lists" do
|
50
|
+
@members.member.project.project_configuration = stub(:story_completed_email_list => [@user.email], :story_assigned_email_list => [@user.email]).as_null_object
|
51
|
+
|
52
|
+
@members.remove_from_email_lists
|
53
|
+
|
54
|
+
@project.project_configuration.story_completed_email_list.should == []
|
55
|
+
@project.project_configuration.story_assigned_email_list.should == []
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'artisan/repository'
|
2
|
+
|
3
|
+
test_repo = Class.new(Artisan::Repository) {}
|
4
|
+
|
5
|
+
describe Artisan::Repository do
|
6
|
+
let(:fake_repo) do
|
7
|
+
Class.new do
|
8
|
+
def project
|
9
|
+
"fake-projects"
|
10
|
+
end
|
11
|
+
|
12
|
+
def story
|
13
|
+
"fake-stories"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:repo_instance) { fake_repo.new }
|
19
|
+
before { test_repo.register_repo(repo_instance) }
|
20
|
+
|
21
|
+
it "registers a top level repository" do
|
22
|
+
test_repo.repo.should == repo_instance
|
23
|
+
end
|
24
|
+
|
25
|
+
it "delegates to the given repository for stories" do
|
26
|
+
test_repo.story.should == "fake-stories"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "delegates to the given repository for stories" do
|
30
|
+
test_repo.project.should == "fake-projects"
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "artisan/story_board"
|
2
|
+
require "artisan/stories/stories_interactor"
|
3
|
+
|
4
|
+
describe Artisan::StoryBoard do
|
5
|
+
let(:repository) { stub }
|
6
|
+
let(:iteration) { Artisan::Repository.iteration.create }
|
7
|
+
|
8
|
+
before do
|
9
|
+
Artisan::Repository.stub(:story).and_return(repository)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "calculates total points for stories in backlog" do
|
13
|
+
iteration.stub!(:project).and_return(nil)
|
14
|
+
Artisan::Stories::StoriesInteractor.stub_chain(:new, :backlog, :points).and_return(5)
|
15
|
+
board = Artisan::StoryBoard.new(iteration)
|
16
|
+
board.backlog_total.should == 5
|
17
|
+
end
|
18
|
+
|
19
|
+
it "calculates total points for 'ready' stories" do
|
20
|
+
repository.should_receive(:ready).with(iteration).and_return([double(:estimate => 2), double(:estimate => 3)])
|
21
|
+
board = Artisan::StoryBoard.new(iteration)
|
22
|
+
board.ready_total.should == 5
|
23
|
+
end
|
24
|
+
|
25
|
+
it "calculates total points for 'working' stories" do
|
26
|
+
repository.should_receive(:working).with(iteration).and_return([double(:estimate => 2), double(:estimate => 3)])
|
27
|
+
board = Artisan::StoryBoard.new(iteration)
|
28
|
+
board.working_total.should == 5
|
29
|
+
end
|
30
|
+
|
31
|
+
it "calculates total points for 'complete' stories" do
|
32
|
+
repository.should_receive(:completed).with(iteration).and_return([double(:estimate => 2), double(:estimate => 3)])
|
33
|
+
board = Artisan::StoryBoard.new(iteration)
|
34
|
+
board.complete_total.should == 5
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'artisan/stories/story_collection'
|
2
|
+
|
3
|
+
describe Artisan::Stories::StoryCollection do
|
4
|
+
context "on init" do
|
5
|
+
it "has empty list of stories" do
|
6
|
+
Artisan::Stories::StoryCollection.new.stories.should == []
|
7
|
+
end
|
8
|
+
|
9
|
+
it "#new saves list of stories" do
|
10
|
+
story1, story2 = stub, stub
|
11
|
+
Artisan::Stories::StoryCollection.new([story1, story2]).all.should == [story1, story2]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "#estimated_points" do
|
16
|
+
it "sums the estimates of all stories" do
|
17
|
+
stories = [ stub(:estimate => 1.5), stub(:estimate => 2) ]
|
18
|
+
Artisan::Stories::StoryCollection.new(stories).estimated_points.should == 3.5
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "#completed_points" do
|
23
|
+
it "sums the estimates of all completed stories" do
|
24
|
+
complete = stub(:estimate => 1.5, :complete? => true)
|
25
|
+
incomplete = stub(:estimate => 3, :complete? => false)
|
26
|
+
Artisan::Stories::StoryCollection.new([complete, incomplete]).completed_points.should == 1.5
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "#billed points" do
|
31
|
+
it "sums the estimates of all billable, completed stories" do
|
32
|
+
billable = stub(:estimate => 1.5, :complete? => true, :nonbillable? => false)
|
33
|
+
nonbillable = stub(:estimate => 1.5, :complete? => true, :nonbillable? => true)
|
34
|
+
incomplete = stub(:estimate => 3, :complete? => false, :nonbillable? => false)
|
35
|
+
Artisan::Stories::StoryCollection.new([billable, nonbillable, incomplete]).billed_points.should == 1.5
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "#billable points" do
|
40
|
+
it "sums the estimates of all billable stories" do
|
41
|
+
billable = stub(:estimate => 1.5, :complete? => true, :nonbillable? => false)
|
42
|
+
nonbillable = stub(:estimate => 1.5, :complete? => true, :nonbillable? => true)
|
43
|
+
incomplete = stub(:estimate => 3, :complete? => false, :nonbillable? => false)
|
44
|
+
Artisan::Stories::StoryCollection.new([billable, nonbillable, incomplete]).billable_points.should == 4.5
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "#all_complete?" do
|
49
|
+
it "is true if all stories are complete" do
|
50
|
+
complete1 = stub(:complete? => true)
|
51
|
+
complete2 = stub(:complete? => true)
|
52
|
+
Artisan::Stories::StoryCollection.new([complete1, complete2]).all_complete?.should be_true
|
53
|
+
end
|
54
|
+
|
55
|
+
it "is false if not all stories are complete" do
|
56
|
+
complete = stub(:complete? => true)
|
57
|
+
incomplete = stub(:complete? => false)
|
58
|
+
Artisan::Stories::StoryCollection.new([complete, incomplete]).all_complete?.should be_false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require "artisan/story_column_changer"
|
2
|
+
require "spec_helper"
|
3
|
+
require "artisan-memory-repository/models/project"
|
4
|
+
require "artisan-memory-repository/models/iteration"
|
5
|
+
require "artisan-memory-repository/models/user"
|
6
|
+
require "artisan-memory-repository/models/story"
|
7
|
+
|
8
|
+
class Artisan::Activity::StoryAuditor;end;
|
9
|
+
|
10
|
+
describe Artisan::StoryColumnChanger do
|
11
|
+
let(:story_repository) { Artisan::Repository.story }
|
12
|
+
|
13
|
+
context "status changes" do
|
14
|
+
before(:each) do
|
15
|
+
@user = Artisan::Repository.user.new(:login => "mike", :password => "password", :email => "mike@example.com", :full_name => "mike jansen")
|
16
|
+
@user2 = Artisan::Repository.user.new(:login => "brimans", :password => "password", :email => "briman@thegmails.com", :full_name => "briman pratt")
|
17
|
+
|
18
|
+
@project = Artisan::Repository.project.new(:name => "Artisan")
|
19
|
+
@iteration = Artisan::Repository.iteration.new(:project_id => @project.id, :committed_points => 10, :start_date => "11/05/2010", :finish_date => "11/06/2010")
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "move to backlog" do
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
Artisan::Activity::StoryAuditor.stub!(:backlogged)
|
26
|
+
@story = Artisan::Repository.story.new(:name => 'abc', :assigned_user => @user, :complete => true, :completed_at => Date.today, :iteration => @iteration,
|
27
|
+
:accepted_at => Date.today, :accepted_by_user => @user2, :project => @project)
|
28
|
+
@project.stories = [@story]
|
29
|
+
|
30
|
+
@changer = Artisan::StoryColumnChanger.new(@story, @user)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "moves a story to the backlog" do
|
34
|
+
@changer.move_to_backlog
|
35
|
+
@story.iteration.should be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "marks story as incomplete" do
|
39
|
+
@changer.move_to_backlog
|
40
|
+
@story.should_not be_complete
|
41
|
+
end
|
42
|
+
|
43
|
+
it "clears completed at" do
|
44
|
+
@changer.move_to_backlog
|
45
|
+
@story.completed_at.should be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "drops assigned user" do
|
49
|
+
@changer.move_to_backlog
|
50
|
+
@story.assigned_user_id.should be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it "saves" do
|
54
|
+
@changer.move_to_backlog
|
55
|
+
@story.id.should_not be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it "creates a story auditor" do
|
59
|
+
Artisan::Activity::StoryAuditor.should_receive(:backlogged).with(@story.id, @project.id, @user.id)
|
60
|
+
@changer.move_to_backlog
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "move to ready" do
|
66
|
+
before :each do
|
67
|
+
@story = Artisan::Repository.story.new(:name => 'abc', :assigned_user => @user, :complete => true, :completed_at => Time.now,
|
68
|
+
:accepted_at => Time.now, :accepted_by_user => @user2, :project => @project)
|
69
|
+
|
70
|
+
@changer = Artisan::StoryColumnChanger.new(@story, @user)
|
71
|
+
Artisan::Activity::StoryAuditor.stub!(:readied)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "assigns iteration to story" do
|
75
|
+
@changer.move_to_ready(@iteration)
|
76
|
+
story_repository.ready(@iteration).should == [@story]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "disassociates assigned user from story when state is changed from working" do
|
80
|
+
@changer.move_to_ready(@iteration)
|
81
|
+
@story.assigned_user_id.should be_nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it "disassociates assigned user from story and marks story incomplete when state is changed from completed" do
|
85
|
+
@changer.move_to_ready(@iteration)
|
86
|
+
@story.should_not be_complete
|
87
|
+
end
|
88
|
+
|
89
|
+
it "disassociates assigned user from story and removes completed at time" do
|
90
|
+
@changer.move_to_ready(@iteration)
|
91
|
+
@story.completed_at.should be_nil
|
92
|
+
end
|
93
|
+
|
94
|
+
it "saves" do
|
95
|
+
@changer.move_to_ready(@iteration)
|
96
|
+
@story.id.should_not be_nil
|
97
|
+
end
|
98
|
+
|
99
|
+
it "creates a story auditor" do
|
100
|
+
Artisan::Activity::StoryAuditor.should_receive(:readied).with(@story.id, @project.id, @user.id)
|
101
|
+
@changer.move_to_ready(@iteration)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "move to working" do
|
106
|
+
before :each do
|
107
|
+
@story = Artisan::Repository.story.new(:name => 'abc', :assigned_user => @user, :complete => true, :completed_at => Time.now, :accepted_at => Time.now,
|
108
|
+
:accepted_by_user => @user, :project => @project)
|
109
|
+
Artisan::Activity::StoryAuditor.stub!(:worked)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "assigns story to an iteration" do
|
113
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
114
|
+
changer.move_to_working(@user, @iteration)
|
115
|
+
|
116
|
+
story_repository.working(@iteration).should == [@story]
|
117
|
+
end
|
118
|
+
|
119
|
+
it "assigns current user to story when state is changed from ready" do
|
120
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
121
|
+
changer.move_to_working(@user, @iteration)
|
122
|
+
|
123
|
+
@story.assigned_user.should == @user
|
124
|
+
end
|
125
|
+
|
126
|
+
it "marks story incomplete when state is changed from complete" do
|
127
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
128
|
+
changer.move_to_working(@user, @iteration)
|
129
|
+
|
130
|
+
@story.should_not be_complete
|
131
|
+
end
|
132
|
+
|
133
|
+
it "marks story completed at time as nil when state is changed from complete" do
|
134
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
135
|
+
changer.move_to_working(@user, @iteration)
|
136
|
+
|
137
|
+
@story.completed_at.should be_nil
|
138
|
+
end
|
139
|
+
|
140
|
+
it "marks only if there is no current user" do
|
141
|
+
@story.update_attributes(:assigned_user => @user2)
|
142
|
+
|
143
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
144
|
+
changer.move_to_working(@user, @iteration)
|
145
|
+
|
146
|
+
@story.assigned_user.should == @user2
|
147
|
+
end
|
148
|
+
|
149
|
+
it "saves" do
|
150
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
151
|
+
changer.move_to_working(@user, @iteration)
|
152
|
+
|
153
|
+
@story.id.should_not be_nil
|
154
|
+
end
|
155
|
+
|
156
|
+
it "creates a story auditor" do
|
157
|
+
Artisan::Activity::StoryAuditor.should_receive(:worked).with(@story.id, @project.id, @user.id)
|
158
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
159
|
+
changer.move_to_working(@user, @iteration)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "move to completed" do
|
164
|
+
before :each do
|
165
|
+
Artisan::Activity::StoryAuditor.stub!(:completed)
|
166
|
+
Artisan::Activity::StoryAuditor.stub!(:worked)
|
167
|
+
Artisan::Activity::StoryAuditor.stub!(:accepted)
|
168
|
+
@story = Artisan::Repository.story.new(:name => 'abc', :project => @project)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "saves" do
|
172
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
173
|
+
changer.move_to_completed(@user, @iteration)
|
174
|
+
|
175
|
+
@story.id.should_not be_nil
|
176
|
+
end
|
177
|
+
|
178
|
+
it "assigns story to iteration" do
|
179
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
180
|
+
changer.move_to_completed(@user, @iteration)
|
181
|
+
|
182
|
+
story_repository.completed(@iteration).should == [@story]
|
183
|
+
end
|
184
|
+
|
185
|
+
it "marks story complete" do
|
186
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
187
|
+
changer.move_to_completed(@user, @iteration)
|
188
|
+
|
189
|
+
@story.should be_complete
|
190
|
+
end
|
191
|
+
|
192
|
+
it "marks story completed at time" do
|
193
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
194
|
+
changer.move_to_completed(@user, @iteration)
|
195
|
+
|
196
|
+
@story.completed_at.should_not be_nil
|
197
|
+
end
|
198
|
+
|
199
|
+
it "sets assigned user if not set" do
|
200
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
201
|
+
changer.move_to_completed(@user, @iteration)
|
202
|
+
|
203
|
+
@story.assigned_user.should == @user
|
204
|
+
end
|
205
|
+
|
206
|
+
it "marks only if there is no current user" do
|
207
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
208
|
+
changer.move_to_working(@user2, @iteration)
|
209
|
+
|
210
|
+
changer.move_to_completed(@user, @iteration)
|
211
|
+
|
212
|
+
@story.assigned_user.should == @user2
|
213
|
+
end
|
214
|
+
|
215
|
+
it "creates a story auditor" do
|
216
|
+
Artisan::Activity::StoryAuditor.should_receive(:completed).with(@story.id, @project.id, @user.id)
|
217
|
+
changer = Artisan::StoryColumnChanger.new(@story, @user)
|
218
|
+
changer.move_to_completed(@user, @iteration)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|