artisan-core 0.0.1
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/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
|