Commit b45e9aefd3207c00f9d83a0cbfcca457c9562a59
1 parent
f9729659
Exists in
master
and in
4 other branches
Merge Request uses StateMachine now
Showing
15 changed files
with
107 additions
and
132 deletions
Show diff stats
app/contexts/merge_requests_load_context.rb
| @@ -14,7 +14,7 @@ class MergeRequestsLoadContext < BaseContext | @@ -14,7 +14,7 @@ class MergeRequestsLoadContext < BaseContext | ||
| 14 | end | 14 | end |
| 15 | 15 | ||
| 16 | merge_requests = merge_requests.page(params[:page]).per(20) | 16 | merge_requests = merge_requests.page(params[:page]).per(20) |
| 17 | - merge_requests = merge_requests.includes(:author, :project).order("closed, created_at desc") | 17 | + merge_requests = merge_requests.includes(:author, :project).order("state, created_at desc") |
| 18 | 18 | ||
| 19 | # Filter by specific assignee_id (or lack thereof)? | 19 | # Filter by specific assignee_id (or lack thereof)? |
| 20 | if params[:assignee_id].present? | 20 | if params[:assignee_id].present? |
app/controllers/merge_requests_controller.rb
| @@ -80,7 +80,7 @@ class MergeRequestsController < ProjectResourceController | @@ -80,7 +80,7 @@ class MergeRequestsController < ProjectResourceController | ||
| 80 | 80 | ||
| 81 | def automerge | 81 | def automerge |
| 82 | return access_denied! unless can?(current_user, :accept_mr, @project) | 82 | return access_denied! unless can?(current_user, :accept_mr, @project) |
| 83 | - if @merge_request.open? && @merge_request.can_be_merged? | 83 | + if @merge_request.opened? && @merge_request.can_be_merged? |
| 84 | @merge_request.should_remove_source_branch = params[:should_remove_source_branch] | 84 | @merge_request.should_remove_source_branch = params[:should_remove_source_branch] |
| 85 | @merge_request.automerge!(current_user) | 85 | @merge_request.automerge!(current_user) |
| 86 | @status = true | 86 | @status = true |
app/helpers/merge_requests_helper.rb
| @@ -12,7 +12,7 @@ module MergeRequestsHelper | @@ -12,7 +12,7 @@ module MergeRequestsHelper | ||
| 12 | 12 | ||
| 13 | def mr_css_classes mr | 13 | def mr_css_classes mr |
| 14 | classes = "merge_request" | 14 | classes = "merge_request" |
| 15 | - classes << " closed" if mr.closed | 15 | + classes << " closed" if mr.closed? |
| 16 | classes << " merged" if mr.merged? | 16 | classes << " merged" if mr.merged? |
| 17 | classes | 17 | classes |
| 18 | end | 18 | end |
app/models/merge_request.rb
| @@ -9,15 +9,14 @@ | @@ -9,15 +9,14 @@ | ||
| 9 | # author_id :integer | 9 | # author_id :integer |
| 10 | # assignee_id :integer | 10 | # assignee_id :integer |
| 11 | # title :string(255) | 11 | # title :string(255) |
| 12 | -# closed :boolean default(FALSE), not null | 12 | +# state :string(255) not null |
| 13 | # created_at :datetime not null | 13 | # created_at :datetime not null |
| 14 | # updated_at :datetime not null | 14 | # updated_at :datetime not null |
| 15 | # st_commits :text(2147483647) | 15 | # st_commits :text(2147483647) |
| 16 | # st_diffs :text(2147483647) | 16 | # st_diffs :text(2147483647) |
| 17 | -# merged :boolean default(FALSE), not null | ||
| 18 | # merge_status :integer default(1), not null | 17 | # merge_status :integer default(1), not null |
| 19 | -# milestone_id :integer | ||
| 20 | # | 18 | # |
| 19 | +# milestone_id :integer | ||
| 21 | 20 | ||
| 22 | require Rails.root.join("app/models/commit") | 21 | require Rails.root.join("app/models/commit") |
| 23 | require Rails.root.join("lib/static_model") | 22 | require Rails.root.join("lib/static_model") |
| @@ -25,11 +24,33 @@ require Rails.root.join("lib/static_model") | @@ -25,11 +24,33 @@ require Rails.root.join("lib/static_model") | ||
| 25 | class MergeRequest < ActiveRecord::Base | 24 | class MergeRequest < ActiveRecord::Base |
| 26 | include Issuable | 25 | include Issuable |
| 27 | 26 | ||
| 28 | - attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch, :milestone_id, | 27 | + attr_accessible :title, :assignee_id, :target_branch, :source_branch, :milestone_id, |
| 29 | :author_id_of_changes | 28 | :author_id_of_changes |
| 30 | 29 | ||
| 31 | attr_accessor :should_remove_source_branch | 30 | attr_accessor :should_remove_source_branch |
| 32 | 31 | ||
| 32 | + state_machine :state, :initial => :opened do | ||
| 33 | + event :close do | ||
| 34 | + transition [:reopened, :opened] => :closed | ||
| 35 | + end | ||
| 36 | + | ||
| 37 | + event :merge do | ||
| 38 | + transition [:reopened, :opened] => :merged | ||
| 39 | + end | ||
| 40 | + | ||
| 41 | + event :reopen do | ||
| 42 | + transition :closed => :reopened | ||
| 43 | + end | ||
| 44 | + | ||
| 45 | + state :opened | ||
| 46 | + | ||
| 47 | + state :reopened | ||
| 48 | + | ||
| 49 | + state :closed | ||
| 50 | + | ||
| 51 | + state :merged | ||
| 52 | + end | ||
| 53 | + | ||
| 33 | BROKEN_DIFF = "--broken-diff" | 54 | BROKEN_DIFF = "--broken-diff" |
| 34 | 55 | ||
| 35 | UNCHECKED = 1 | 56 | UNCHECKED = 1 |
| @@ -43,6 +64,8 @@ class MergeRequest < ActiveRecord::Base | @@ -43,6 +64,8 @@ class MergeRequest < ActiveRecord::Base | ||
| 43 | validates :target_branch, presence: true | 64 | validates :target_branch, presence: true |
| 44 | validate :validate_branches | 65 | validate :validate_branches |
| 45 | 66 | ||
| 67 | + scope :merged, -> { with_state(:merged) } | ||
| 68 | + | ||
| 46 | def self.find_all_by_branch(branch_name) | 69 | def self.find_all_by_branch(branch_name) |
| 47 | where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name) | 70 | where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name) |
| 48 | end | 71 | end |
| @@ -98,7 +121,7 @@ class MergeRequest < ActiveRecord::Base | @@ -98,7 +121,7 @@ class MergeRequest < ActiveRecord::Base | ||
| 98 | end | 121 | end |
| 99 | 122 | ||
| 100 | def reloaded_diffs | 123 | def reloaded_diffs |
| 101 | - if open? && unmerged_diffs.any? | 124 | + if opened? && unmerged_diffs.any? |
| 102 | self.st_diffs = unmerged_diffs | 125 | self.st_diffs = unmerged_diffs |
| 103 | self.save | 126 | self.save |
| 104 | end | 127 | end |
| @@ -128,10 +151,6 @@ class MergeRequest < ActiveRecord::Base | @@ -128,10 +151,6 @@ class MergeRequest < ActiveRecord::Base | ||
| 128 | commits.first | 151 | commits.first |
| 129 | end | 152 | end |
| 130 | 153 | ||
| 131 | - def merged? | ||
| 132 | - merged && merge_event | ||
| 133 | - end | ||
| 134 | - | ||
| 135 | def merge_event | 154 | def merge_event |
| 136 | self.project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last | 155 | self.project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last |
| 137 | end | 156 | end |
| @@ -146,17 +165,7 @@ class MergeRequest < ActiveRecord::Base | @@ -146,17 +165,7 @@ class MergeRequest < ActiveRecord::Base | ||
| 146 | 165 | ||
| 147 | def probably_merged? | 166 | def probably_merged? |
| 148 | unmerged_commits.empty? && | 167 | unmerged_commits.empty? && |
| 149 | - commits.any? && open? | ||
| 150 | - end | ||
| 151 | - | ||
| 152 | - def open? | ||
| 153 | - !closed | ||
| 154 | - end | ||
| 155 | - | ||
| 156 | - def mark_as_merged! | ||
| 157 | - self.merged = true | ||
| 158 | - self.closed = true | ||
| 159 | - save | 168 | + commits.any? && opened? |
| 160 | end | 169 | end |
| 161 | 170 | ||
| 162 | def mark_as_unmergable | 171 | def mark_as_unmergable |
| @@ -165,7 +174,7 @@ class MergeRequest < ActiveRecord::Base | @@ -165,7 +174,7 @@ class MergeRequest < ActiveRecord::Base | ||
| 165 | end | 174 | end |
| 166 | 175 | ||
| 167 | def reloaded_commits | 176 | def reloaded_commits |
| 168 | - if open? && unmerged_commits.any? | 177 | + if opened? && unmerged_commits.any? |
| 169 | self.st_commits = unmerged_commits | 178 | self.st_commits = unmerged_commits |
| 170 | save | 179 | save |
| 171 | end | 180 | end |
| @@ -181,7 +190,8 @@ class MergeRequest < ActiveRecord::Base | @@ -181,7 +190,8 @@ class MergeRequest < ActiveRecord::Base | ||
| 181 | end | 190 | end |
| 182 | 191 | ||
| 183 | def merge!(user_id) | 192 | def merge!(user_id) |
| 184 | - self.mark_as_merged! | 193 | + self.merge |
| 194 | + | ||
| 185 | Event.create( | 195 | Event.create( |
| 186 | project: self.project, | 196 | project: self.project, |
| 187 | action: Event::MERGED, | 197 | action: Event::MERGED, |
app/observers/merge_request_observer.rb
| @@ -7,15 +7,20 @@ class MergeRequestObserver < ActiveRecord::Observer | @@ -7,15 +7,20 @@ class MergeRequestObserver < ActiveRecord::Observer | ||
| 7 | end | 7 | end |
| 8 | end | 8 | end |
| 9 | 9 | ||
| 10 | - def after_update(merge_request) | 10 | + def after_close(merge_request, transition) |
| 11 | send_reassigned_email(merge_request) if merge_request.is_being_reassigned? | 11 | send_reassigned_email(merge_request) if merge_request.is_being_reassigned? |
| 12 | 12 | ||
| 13 | - status = nil | ||
| 14 | - status = 'closed' if merge_request.is_being_closed? | ||
| 15 | - status = 'reopened' if merge_request.is_being_reopened? | ||
| 16 | - if status | ||
| 17 | - Note.create_status_change_note(merge_request, current_user, status) | ||
| 18 | - end | 13 | + Note.create_status_change_note(merge_request, current_user, merge_request.state) |
| 14 | + end | ||
| 15 | + | ||
| 16 | + def after_reopen(merge_request, transition) | ||
| 17 | + send_reassigned_email(merge_request) if merge_request.is_being_reassigned? | ||
| 18 | + | ||
| 19 | + Note.create_status_change_note(merge_request, current_user, merge_request.state) | ||
| 20 | + end | ||
| 21 | + | ||
| 22 | + def after_update(merge_request) | ||
| 23 | + send_reassigned_email(merge_request) if merge_request.is_being_reassigned? | ||
| 19 | end | 24 | end |
| 20 | 25 | ||
| 21 | protected | 26 | protected |
app/views/merge_requests/show/_mr_accept.html.haml
| @@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
| 3 | %strong Only masters can accept MR | 3 | %strong Only masters can accept MR |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | -- if @merge_request.open? && @commits.any? && can?(current_user, :accept_mr, @project) | 6 | +- if @merge_request.opened? && @commits.any? && can?(current_user, :accept_mr, @project) |
| 7 | .automerge_widget.can_be_merged{style: "display:none"} | 7 | .automerge_widget.can_be_merged{style: "display:none"} |
| 8 | .alert.alert-success | 8 | .alert.alert-success |
| 9 | %span | 9 | %span |
app/views/merge_requests/show/_mr_box.html.haml
| 1 | .ui-box.ui-box-show | 1 | .ui-box.ui-box-show |
| 2 | .ui-box-head | 2 | .ui-box-head |
| 3 | %h4.box-title | 3 | %h4.box-title |
| 4 | - - if @merge_request.merged | 4 | + - if @merge_request.merged? |
| 5 | .error.status_info | 5 | .error.status_info |
| 6 | %i.icon-ok | 6 | %i.icon-ok |
| 7 | Merged | 7 | Merged |
| 8 | - - elsif @merge_request.closed | 8 | + - elsif @merge_request.closed? |
| 9 | .error.status_info Closed | 9 | .error.status_info Closed |
| 10 | = gfm escape_once(@merge_request.title) | 10 | = gfm escape_once(@merge_request.title) |
| 11 | 11 | ||
| @@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
| 21 | %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone) | 21 | %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone) |
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | - - if @merge_request.closed | 24 | + - if @merge_request.closed? |
| 25 | .ui-box-bottom | 25 | .ui-box-bottom |
| 26 | - if @merge_request.merged? | 26 | - if @merge_request.merged? |
| 27 | %span | 27 | %span |
app/views/merge_requests/show/_mr_ci.html.haml
app/views/merge_requests/show/_mr_title.html.haml
| @@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
| 7 | 7 | ||
| 8 | %span.pull-right | 8 | %span.pull-right |
| 9 | - if can?(current_user, :modify_merge_request, @merge_request) | 9 | - if can?(current_user, :modify_merge_request, @merge_request) |
| 10 | - - if @merge_request.open? | 10 | + - if @merge_request.opened? |
| 11 | .left.btn-group | 11 | .left.btn-group |
| 12 | %a.btn.grouped.dropdown-toggle{ data: {toggle: :dropdown} } | 12 | %a.btn.grouped.dropdown-toggle{ data: {toggle: :dropdown} } |
| 13 | %i.icon-download-alt | 13 | %i.icon-download-alt |
app/views/milestones/show.html.haml
| @@ -77,7 +77,7 @@ | @@ -77,7 +77,7 @@ | ||
| 77 | %li=link_to('All Merge Requests', '#') | 77 | %li=link_to('All Merge Requests', '#') |
| 78 | %ul.well-list | 78 | %ul.well-list |
| 79 | - @merge_requests.each do |merge_request| | 79 | - @merge_requests.each do |merge_request| |
| 80 | - %li{data: {closed: merge_request.closed}} | 80 | + %li{data: {closed: merge_request.closed?}} |
| 81 | = link_to [@project, merge_request] do | 81 | = link_to [@project, merge_request] do |
| 82 | %span.badge.badge-info ##{merge_request.id} | 82 | %span.badge.badge-info ##{merge_request.id} |
| 83 | – | 83 | – |
spec/factories.rb
| @@ -67,10 +67,6 @@ FactoryGirl.define do | @@ -67,10 +67,6 @@ FactoryGirl.define do | ||
| 67 | source_branch "master" | 67 | source_branch "master" |
| 68 | target_branch "stable" | 68 | target_branch "stable" |
| 69 | 69 | ||
| 70 | - trait :closed do | ||
| 71 | - closed true | ||
| 72 | - end | ||
| 73 | - | ||
| 74 | # pick 3 commits "at random" (from bcf03b5d~3 to bcf03b5d) | 70 | # pick 3 commits "at random" (from bcf03b5d~3 to bcf03b5d) |
| 75 | trait :with_diffs do | 71 | trait :with_diffs do |
| 76 | target_branch "master" # pretend bcf03b5d~3 | 72 | target_branch "master" # pretend bcf03b5d~3 |
| @@ -85,7 +81,16 @@ FactoryGirl.define do | @@ -85,7 +81,16 @@ FactoryGirl.define do | ||
| 85 | end | 81 | end |
| 86 | end | 82 | end |
| 87 | 83 | ||
| 84 | + trait :closed do | ||
| 85 | + state :closed | ||
| 86 | + end | ||
| 87 | + | ||
| 88 | + trait :reopened do | ||
| 89 | + state :reopened | ||
| 90 | + end | ||
| 91 | + | ||
| 88 | factory :closed_merge_request, traits: [:closed] | 92 | factory :closed_merge_request, traits: [:closed] |
| 93 | + factory :reopened_merge_request, traits: [:reopened] | ||
| 89 | factory :merge_request_with_diffs, traits: [:with_diffs] | 94 | factory :merge_request_with_diffs, traits: [:with_diffs] |
| 90 | end | 95 | end |
| 91 | 96 |
spec/models/merge_request_spec.rb
| @@ -37,6 +37,10 @@ describe MergeRequest do | @@ -37,6 +37,10 @@ describe MergeRequest do | ||
| 37 | end | 37 | end |
| 38 | 38 | ||
| 39 | describe "#mr_and_commit_notes" do | 39 | describe "#mr_and_commit_notes" do |
| 40 | + | ||
| 41 | + end | ||
| 42 | + | ||
| 43 | + describe "#mr_and_commit_notes" do | ||
| 40 | let!(:merge_request) { create(:merge_request) } | 44 | let!(:merge_request) { create(:merge_request) } |
| 41 | 45 | ||
| 42 | before do | 46 | before do |
spec/models/milestone_spec.rb
| @@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
| 7 | # project_id :integer not null | 7 | # project_id :integer not null |
| 8 | # description :text | 8 | # description :text |
| 9 | # due_date :date | 9 | # due_date :date |
| 10 | -# closed :boolean default(FALSE), not null | 10 | +# state :string default(FALSE), not null |
| 11 | # created_at :datetime not null | 11 | # created_at :datetime not null |
| 12 | # updated_at :datetime not null | 12 | # updated_at :datetime not null |
| 13 | # | 13 | # |
spec/models/project_spec.rb
| @@ -121,10 +121,7 @@ describe Project do | @@ -121,10 +121,7 @@ describe Project do | ||
| 121 | let(:project) { create(:project) } | 121 | let(:project) { create(:project) } |
| 122 | 122 | ||
| 123 | before do | 123 | before do |
| 124 | - @merge_request = create(:merge_request, | ||
| 125 | - project: project, | ||
| 126 | - merged: false, | ||
| 127 | - closed: false) | 124 | + @merge_request = create(:merge_request, project: project) |
| 128 | @key = create(:key, user_id: project.owner.id) | 125 | @key = create(:key, user_id: project.owner.id) |
| 129 | end | 126 | end |
| 130 | 127 | ||
| @@ -133,8 +130,7 @@ describe Project do | @@ -133,8 +130,7 @@ describe Project do | ||
| 133 | @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" | 130 | @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" |
| 134 | project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.user) | 131 | project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.user) |
| 135 | @merge_request.reload | 132 | @merge_request.reload |
| 136 | - @merge_request.merged.should be_true | ||
| 137 | - @merge_request.closed.should be_true | 133 | + @merge_request.merged?.should be_true |
| 138 | end | 134 | end |
| 139 | 135 | ||
| 140 | it "should update merge request commits with new one if pushed to source branch" do | 136 | it "should update merge request commits with new one if pushed to source branch" do |
spec/observers/merge_request_observer_spec.rb
| 1 | require 'spec_helper' | 1 | require 'spec_helper' |
| 2 | 2 | ||
| 3 | describe MergeRequestObserver do | 3 | describe MergeRequestObserver do |
| 4 | - let(:some_user) { double(:user, id: 1) } | ||
| 5 | - let(:assignee) { double(:user, id: 2) } | ||
| 6 | - let(:author) { double(:user, id: 3) } | ||
| 7 | - let(:mr) { double(:merge_request, id: 42, assignee: assignee, author: author) } | 4 | + let(:some_user) { create :user } |
| 5 | + let(:assignee) { create :user } | ||
| 6 | + let(:author) { create :user } | ||
| 7 | + let(:mr_mock) { double(:merge_request, id: 42, assignee: assignee, author: author) } | ||
| 8 | + let(:assigned_mr) { create(:merge_request, assignee: assignee, author: author) } | ||
| 9 | + let(:unassigned_mr) { create(:merge_request, author: author) } | ||
| 10 | + let(:closed_assigned_mr) { create(:closed_merge_request, assignee: assignee, author: author) } | ||
| 11 | + let(:closed_unassigned_mr) { create(:closed_merge_request, author: author) } | ||
| 8 | 12 | ||
| 9 | before(:each) { subject.stub(:current_user).and_return(some_user) } | 13 | before(:each) { subject.stub(:current_user).and_return(some_user) } |
| 10 | 14 | ||
| @@ -21,23 +25,21 @@ describe MergeRequestObserver do | @@ -21,23 +25,21 @@ describe MergeRequestObserver do | ||
| 21 | end | 25 | end |
| 22 | 26 | ||
| 23 | it 'sends an email to the assignee' do | 27 | it 'sends an email to the assignee' do |
| 24 | - Notify.should_receive(:new_merge_request_email).with(mr.id) | ||
| 25 | - subject.after_create(mr) | 28 | + Notify.should_receive(:new_merge_request_email).with(mr_mock.id) |
| 29 | + subject.after_create(mr_mock) | ||
| 26 | end | 30 | end |
| 27 | 31 | ||
| 28 | it 'does not send an email to the assignee if assignee created the merge request' do | 32 | it 'does not send an email to the assignee if assignee created the merge request' do |
| 29 | subject.stub(:current_user).and_return(assignee) | 33 | subject.stub(:current_user).and_return(assignee) |
| 30 | Notify.should_not_receive(:new_merge_request_email) | 34 | Notify.should_not_receive(:new_merge_request_email) |
| 31 | 35 | ||
| 32 | - subject.after_create(mr) | 36 | + subject.after_create(mr_mock) |
| 33 | end | 37 | end |
| 34 | end | 38 | end |
| 35 | 39 | ||
| 36 | context '#after_update' do | 40 | context '#after_update' do |
| 37 | before(:each) do | 41 | before(:each) do |
| 38 | - mr.stub(:is_being_reassigned?).and_return(false) | ||
| 39 | - mr.stub(:is_being_closed?).and_return(false) | ||
| 40 | - mr.stub(:is_being_reopened?).and_return(false) | 42 | + mr_mock.stub(:is_being_reassigned?).and_return(false) |
| 41 | end | 43 | end |
| 42 | 44 | ||
| 43 | it 'is called when a merge request is changed' do | 45 | it 'is called when a merge request is changed' do |
| @@ -52,97 +54,50 @@ describe MergeRequestObserver do | @@ -52,97 +54,50 @@ describe MergeRequestObserver do | ||
| 52 | 54 | ||
| 53 | context 'a reassigned email' do | 55 | context 'a reassigned email' do |
| 54 | it 'is sent if the merge request is being reassigned' do | 56 | it 'is sent if the merge request is being reassigned' do |
| 55 | - mr.should_receive(:is_being_reassigned?).and_return(true) | ||
| 56 | - subject.should_receive(:send_reassigned_email).with(mr) | 57 | + mr_mock.should_receive(:is_being_reassigned?).and_return(true) |
| 58 | + subject.should_receive(:send_reassigned_email).with(mr_mock) | ||
| 57 | 59 | ||
| 58 | - subject.after_update(mr) | 60 | + subject.after_update(mr_mock) |
| 59 | end | 61 | end |
| 60 | 62 | ||
| 61 | it 'is not sent if the merge request is not being reassigned' do | 63 | it 'is not sent if the merge request is not being reassigned' do |
| 62 | - mr.should_receive(:is_being_reassigned?).and_return(false) | 64 | + mr_mock.should_receive(:is_being_reassigned?).and_return(false) |
| 63 | subject.should_not_receive(:send_reassigned_email) | 65 | subject.should_not_receive(:send_reassigned_email) |
| 64 | 66 | ||
| 65 | - subject.after_update(mr) | 67 | + subject.after_update(mr_mock) |
| 66 | end | 68 | end |
| 67 | end | 69 | end |
| 68 | 70 | ||
| 71 | + end | ||
| 72 | + | ||
| 73 | + context '#after_close' do | ||
| 69 | context 'a status "closed"' do | 74 | context 'a status "closed"' do |
| 70 | it 'note is created if the merge request is being closed' do | 75 | it 'note is created if the merge request is being closed' do |
| 71 | - mr.should_receive(:is_being_closed?).and_return(true) | ||
| 72 | - Note.should_receive(:create_status_change_note).with(mr, some_user, 'closed') | ||
| 73 | - | ||
| 74 | - subject.after_update(mr) | ||
| 75 | - end | ||
| 76 | - | ||
| 77 | - it 'note is not created if the merge request is not being closed' do | ||
| 78 | - mr.should_receive(:is_being_closed?).and_return(false) | ||
| 79 | - Note.should_not_receive(:create_status_change_note).with(mr, some_user, 'closed') | ||
| 80 | - | ||
| 81 | - subject.after_update(mr) | ||
| 82 | - end | ||
| 83 | - | ||
| 84 | - it 'notification is delivered if the merge request being closed' do | ||
| 85 | - mr.stub(:is_being_closed?).and_return(true) | ||
| 86 | - Note.should_receive(:create_status_change_note).with(mr, some_user, 'closed') | ||
| 87 | - | ||
| 88 | - subject.after_update(mr) | ||
| 89 | - end | ||
| 90 | - | ||
| 91 | - it 'notification is not delivered if the merge request not being closed' do | ||
| 92 | - mr.stub(:is_being_closed?).and_return(false) | ||
| 93 | - Note.should_not_receive(:create_status_change_note).with(mr, some_user, 'closed') | 76 | + Note.should_receive(:create_status_change_note).with(assigned_mr, some_user, 'closed') |
| 94 | 77 | ||
| 95 | - subject.after_update(mr) | 78 | + assigned_mr.close |
| 96 | end | 79 | end |
| 97 | 80 | ||
| 98 | it 'notification is delivered only to author if the merge request is being closed' do | 81 | it 'notification is delivered only to author if the merge request is being closed' do |
| 99 | - mr_without_assignee = double(:merge_request, id: 42, author: author, assignee: nil) | ||
| 100 | - mr_without_assignee.stub(:is_being_reassigned?).and_return(false) | ||
| 101 | - mr_without_assignee.stub(:is_being_closed?).and_return(true) | ||
| 102 | - mr_without_assignee.stub(:is_being_reopened?).and_return(false) | ||
| 103 | - Note.should_receive(:create_status_change_note).with(mr_without_assignee, some_user, 'closed') | 82 | + Note.should_receive(:create_status_change_note).with(unassigned_mr, some_user, 'closed') |
| 104 | 83 | ||
| 105 | - subject.after_update(mr_without_assignee) | 84 | + unassigned_mr.close |
| 106 | end | 85 | end |
| 107 | end | 86 | end |
| 87 | + end | ||
| 108 | 88 | ||
| 89 | + context '#after_reopen' do | ||
| 109 | context 'a status "reopened"' do | 90 | context 'a status "reopened"' do |
| 110 | it 'note is created if the merge request is being reopened' do | 91 | it 'note is created if the merge request is being reopened' do |
| 111 | - mr.should_receive(:is_being_reopened?).and_return(true) | ||
| 112 | - Note.should_receive(:create_status_change_note).with(mr, some_user, 'reopened') | ||
| 113 | - | ||
| 114 | - subject.after_update(mr) | ||
| 115 | - end | ||
| 116 | - | ||
| 117 | - it 'note is not created if the merge request is not being reopened' do | ||
| 118 | - mr.should_receive(:is_being_reopened?).and_return(false) | ||
| 119 | - Note.should_not_receive(:create_status_change_note).with(mr, some_user, 'reopened') | ||
| 120 | - | ||
| 121 | - subject.after_update(mr) | ||
| 122 | - end | ||
| 123 | - | ||
| 124 | - it 'notification is delivered if the merge request being reopened' do | ||
| 125 | - mr.stub(:is_being_reopened?).and_return(true) | ||
| 126 | - Note.should_receive(:create_status_change_note).with(mr, some_user, 'reopened') | ||
| 127 | - | ||
| 128 | - subject.after_update(mr) | ||
| 129 | - end | ||
| 130 | - | ||
| 131 | - it 'notification is not delivered if the merge request is not being reopened' do | ||
| 132 | - mr.stub(:is_being_reopened?).and_return(false) | ||
| 133 | - Note.should_not_receive(:create_status_change_note).with(mr, some_user, 'reopened') | 92 | + Note.should_receive(:create_status_change_note).with(closed_assigned_mr, some_user, 'reopened') |
| 134 | 93 | ||
| 135 | - subject.after_update(mr) | 94 | + closed_assigned_mr.reopen |
| 136 | end | 95 | end |
| 137 | 96 | ||
| 138 | it 'notification is delivered only to author if the merge request is being reopened' do | 97 | it 'notification is delivered only to author if the merge request is being reopened' do |
| 139 | - mr_without_assignee = double(:merge_request, id: 42, author: author, assignee: nil) | ||
| 140 | - mr_without_assignee.stub(:is_being_reassigned?).and_return(false) | ||
| 141 | - mr_without_assignee.stub(:is_being_closed?).and_return(false) | ||
| 142 | - mr_without_assignee.stub(:is_being_reopened?).and_return(true) | ||
| 143 | - Note.should_receive(:create_status_change_note).with(mr_without_assignee, some_user, 'reopened') | 98 | + Note.should_receive(:create_status_change_note).with(closed_unassigned_mr, some_user, 'reopened') |
| 144 | 99 | ||
| 145 | - subject.after_update(mr_without_assignee) | 100 | + closed_unassigned_mr.reopen |
| 146 | end | 101 | end |
| 147 | end | 102 | end |
| 148 | end | 103 | end |
| @@ -151,23 +106,23 @@ describe MergeRequestObserver do | @@ -151,23 +106,23 @@ describe MergeRequestObserver do | ||
| 151 | let(:previous_assignee) { double(:user, id: 3) } | 106 | let(:previous_assignee) { double(:user, id: 3) } |
| 152 | 107 | ||
| 153 | before(:each) do | 108 | before(:each) do |
| 154 | - mr.stub(:assignee_id).and_return(assignee.id) | ||
| 155 | - mr.stub(:assignee_id_was).and_return(previous_assignee.id) | 109 | + mr_mock.stub(:assignee_id).and_return(assignee.id) |
| 110 | + mr_mock.stub(:assignee_id_was).and_return(previous_assignee.id) | ||
| 156 | end | 111 | end |
| 157 | 112 | ||
| 158 | def it_sends_a_reassigned_email_to(recipient) | 113 | def it_sends_a_reassigned_email_to(recipient) |
| 159 | - Notify.should_receive(:reassigned_merge_request_email).with(recipient, mr.id, previous_assignee.id) | 114 | + Notify.should_receive(:reassigned_merge_request_email).with(recipient, mr_mock.id, previous_assignee.id) |
| 160 | end | 115 | end |
| 161 | 116 | ||
| 162 | def it_does_not_send_a_reassigned_email_to(recipient) | 117 | def it_does_not_send_a_reassigned_email_to(recipient) |
| 163 | - Notify.should_not_receive(:reassigned_merge_request_email).with(recipient, mr.id, previous_assignee.id) | 118 | + Notify.should_not_receive(:reassigned_merge_request_email).with(recipient, mr_mock.id, previous_assignee.id) |
| 164 | end | 119 | end |
| 165 | 120 | ||
| 166 | it 'sends a reassigned email to the previous and current assignees' do | 121 | it 'sends a reassigned email to the previous and current assignees' do |
| 167 | it_sends_a_reassigned_email_to assignee.id | 122 | it_sends_a_reassigned_email_to assignee.id |
| 168 | it_sends_a_reassigned_email_to previous_assignee.id | 123 | it_sends_a_reassigned_email_to previous_assignee.id |
| 169 | 124 | ||
| 170 | - subject.send(:send_reassigned_email, mr) | 125 | + subject.send(:send_reassigned_email, mr_mock) |
| 171 | end | 126 | end |
| 172 | 127 | ||
| 173 | context 'does not send an email to the user who made the reassignment' do | 128 | context 'does not send an email to the user who made the reassignment' do |
| @@ -176,14 +131,14 @@ describe MergeRequestObserver do | @@ -176,14 +131,14 @@ describe MergeRequestObserver do | ||
| 176 | it_sends_a_reassigned_email_to previous_assignee.id | 131 | it_sends_a_reassigned_email_to previous_assignee.id |
| 177 | it_does_not_send_a_reassigned_email_to assignee.id | 132 | it_does_not_send_a_reassigned_email_to assignee.id |
| 178 | 133 | ||
| 179 | - subject.send(:send_reassigned_email, mr) | 134 | + subject.send(:send_reassigned_email, mr_mock) |
| 180 | end | 135 | end |
| 181 | it 'if the user is the previous assignee' do | 136 | it 'if the user is the previous assignee' do |
| 182 | subject.stub(:current_user).and_return(previous_assignee) | 137 | subject.stub(:current_user).and_return(previous_assignee) |
| 183 | it_sends_a_reassigned_email_to assignee.id | 138 | it_sends_a_reassigned_email_to assignee.id |
| 184 | it_does_not_send_a_reassigned_email_to previous_assignee.id | 139 | it_does_not_send_a_reassigned_email_to previous_assignee.id |
| 185 | 140 | ||
| 186 | - subject.send(:send_reassigned_email, mr) | 141 | + subject.send(:send_reassigned_email, mr_mock) |
| 187 | end | 142 | end |
| 188 | end | 143 | end |
| 189 | end | 144 | end |