Commit 0752dd48 authored by Sean McGivern's avatar Sean McGivern

Merge branch '1979-2-1' into 'master'

Feature switch layer around Approvable and VisibleApprovable

See merge request gitlab-org/gitlab-ee!9147
parents 339a9173 9ba45b78
......@@ -9,7 +9,7 @@ module EE
def preload_for_collection
@preload_for_collection ||= case collection_type
when 'MergeRequest'
super.push(:approvals)
super.push(:approvals, :approval_rules)
else
super
end
......
......@@ -39,4 +39,9 @@ class ApprovalMergeRequestRule < ApplicationRecord
self.approved_approver_ids = merge_request.approvals.map(&:user_id) & approvers.map(&:id)
end
def regular
!code_owner?
end
alias_method :regular?, :regular
end
......@@ -9,6 +9,11 @@ class ApprovalProjectRule < ApplicationRecord
scope :regular, -> { all }
scope :code_owner, -> { none }
def regular
true
end
alias_method :regular?, :regular
def code_owner
false
end
......
......@@ -36,8 +36,9 @@ class ApprovalState
end
def approval_rules_overwritten?
merge_request.approval_rules.regular.exists?
merge_request.approval_rules.any?(&:regular?)
end
alias_method :approvers_overwritten?, :approval_rules_overwritten?
def approval_needed?
return false unless project.feature_available?(:merge_request_approvers)
......@@ -134,10 +135,10 @@ class ApprovalState
def regular_rules
strong_memoize(:regular_rules) do
rule_source = approval_rules_overwritten? ? merge_request : project
rules = rule_source.approval_rules.regular
rules = rule_source.approval_rules.select(&:regular?)
unless project.feature_available?(:multiple_approval_rules)
rules = rules.order(id: :asc).limit(1)
rules = rules[0, 1]
end
wrap_rules(rules)
......@@ -146,7 +147,7 @@ class ApprovalState
def code_owner_rules
strong_memoize(:code_owner_rules) do
wrap_rules(merge_request.approval_rules.code_owner)
wrap_rules(merge_request.approval_rules.select(&:code_owner?))
end
end
......
# frozen_string_literal: true
module ApprovableForRule
include VisibleApprovableForRule
FORWARDABLE_METHODS = %w{
approval_needed?
approved?
approvals_left
can_approve?
has_approved?
any_approver_allowed?
authors_can_approve?
approvers_overwritten?
}.freeze
FORWARDABLE_METHODS.each do |method|
define_method(method) do |*args|
return super(*args) if approval_rules_disabled?
approval_state.public_send(method, *args) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
# frozen_string_literal: true
# This module may only be used by presenters or modules
# that include the Approvable concern
module VisibleApprovableForRule
def approvers_left
return super if approval_rules_disabled?
approval_state.unactioned_approvers
end
def overall_approvers(exclude_code_owners: false)
return super if approval_rules_disabled?
options = { target: :users }
options[:code_owner] = false if exclude_code_owners
approvers = approval_state.filtered_approvers(options)
approvers.uniq!
approvers
end
def all_approvers_including_groups
return super if approval_rules_disabled?
approval_state.approvers
end
def approvers_from_groups
return super if approval_rules_disabled?
groups = approval_state.wrapped_approval_rules.flat_map(&:groups)
User.joins(:group_members).where(members: { source_id: groups })
end
def approval_rules_disabled?
::Feature.disabled?(:approval_rules, project)
end
end
......@@ -7,6 +7,7 @@ module EE
include ::Approvable
include ::Gitlab::Utils::StrongMemoize
prepend ApprovableForRule
prepended do
include Elastic::MergeRequestsSearch
......@@ -56,11 +57,16 @@ module EE
strong_memoize(:participant_approvers) do
next [] unless approval_needed?
approvers = []
approvers.concat(overall_approvers(exclude_code_owners: true))
approvers.concat(approvers_from_groups)
if ::Feature.enabled?(:approval_rules, project)
approval_state.filtered_approvers(code_owner: false, unactioned: true)
else
approvers = [
*overall_approvers(exclude_code_owners: true),
*approvers_from_groups
]
::User.where(id: approvers.map(&:id)).where.not(id: approved_by_users.select(:id))
::User.where(id: approvers.map(&:id)).where.not(id: approved_by_users.select(:id))
end
end
end
......
# frozen_string_literal: true
class ApprovalRulePresenter < Gitlab::View::Presenter::Delegated
def groups
super.public_or_visible_to_user(current_user)
end
end
......@@ -3,6 +3,7 @@
module EE
module MergeRequestPresenter
include ::VisibleApprovable
prepend VisibleApprovableForRule
def approvals_path
if requires_approve?
......
......@@ -47,6 +47,7 @@ module EE
# TODO remove after #1979 is closed
def sync_approval_rules(merge_request)
return if ::Feature.enabled?(:approval_rules, merge_request.target_project)
return if merge_request.merged?
return unless merge_request.previous_changes.include?(:approvals_before_merge)
......
......@@ -77,6 +77,7 @@ module EE
# TODO remove after #1979 is closed
def sync_approval_rules
return if ::Feature.enabled?(:approval_rules, project)
return unless project.previous_changes.include?(:approvals_before_merge)
project.approval_rules.update_all(approvals_required: project.approvals_before_merge)
......
......@@ -100,6 +100,7 @@ describe Projects::MergeRequestsController do
let(:viewer) { user }
before do
stub_feature_flags(approval_rules: false)
sign_in(viewer)
end
......
......@@ -61,6 +61,7 @@ describe 'Merge request > User approves', :js do
context 'when CI is running but no approval given' do
before do
stub_feature_flags(approval_rules: false) # TODO check in !9001 when feature enabled
create :approver_group, group: group, target: merge_request
pipeline = create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch)
merge_request.update(head_pipeline: pipeline)
......
......@@ -53,6 +53,7 @@ describe 'Merge request > User sets approvers', :js do
let(:other_user) { create(:user) }
before do
stub_feature_flags(approval_rules: false) # TODO https://gitlab.com/gitlab-org/gitlab-ee/issues/9430
project.add_developer(user)
project.add_developer(other_user)
......@@ -108,6 +109,7 @@ describe 'Merge request > User sets approvers', :js do
let(:merge_request) { create(:merge_request, source_project: project) }
before do
stub_feature_flags(approval_rules: false) # TODO https://gitlab.com/gitlab-org/gitlab-ee/issues/9430
project.add_developer(user)
sign_in(user)
......
......@@ -14,6 +14,7 @@ describe 'User approves a merge request', :js do
context 'when user can approve' do
before do
stub_feature_flags(approval_rules: false) # TODO check in !9001 when feature enabled
visit(merge_request_path(merge_request))
end
......@@ -30,6 +31,7 @@ describe 'User approves a merge request', :js do
context 'when a merge request is approved additionally' do
before do
stub_feature_flags(approval_rules: false) # TODO check in !9001 when feature enabled
project.add_developer(user2)
project.add_developer(user3)
end
......@@ -73,6 +75,7 @@ describe 'User approves a merge request', :js do
context 'when user cannot approve' do
before do
stub_feature_flags(approval_rules: false) # TODO check in !9001 when feature enabled
merge_request.approvers.create(user_id: user2.id)
visit(merge_request_path(merge_request))
......
......@@ -5,6 +5,10 @@ describe Approvable do
let(:project) { merge_request.project }
let(:author) { merge_request.author }
before do
stub_feature_flags(approval_rules: false)
end
describe '#approvers_overwritten?' do
subject { merge_request.approvers_overwritten? }
......
......@@ -14,6 +14,22 @@ describe ApprovalMergeRequestRule do
end
end
describe '#regular' do
it 'returns true for regular records' do
subject = create(:approval_merge_request_rule, merge_request: merge_request)
expect(subject.regular).to eq(true)
expect(subject.regular?).to eq(true)
end
it 'returns false for code owner records' do
subject = create(:approval_merge_request_rule, merge_request: merge_request, code_owner: true)
expect(subject.regular).to eq(false)
expect(subject.regular?).to eq(false)
end
end
describe '#approvers' do
before do
create(:group) do |group|
......
......@@ -21,6 +21,13 @@ describe ApprovalProjectRule do
end
end
describe '#regular' do
it 'returns true' do
expect(subject.regular).to eq(true)
expect(subject.regular?).to eq(true)
end
end
describe '#code_owner' do
it 'returns false' do
expect(subject.code_owner).to eq(false)
......
......@@ -16,11 +16,282 @@ describe MergeRequest do
it { is_expected.to have_many(:approved_by_users) }
end
describe 'approvals' do
shared_examples_for 'authors self-approval authorization' do
context 'when authors are authorized to approve their own MRs' do
before do
project.update!(merge_requests_author_approval: true)
end
it 'allows the author to approve the MR if within the approvers list' do
expect(merge_request.can_approve?(author)).to be_truthy
end
it 'does not allow the author to approve the MR if not within the approvers list' do
merge_request.approvers.delete_all
expect(merge_request.can_approve?(author)).to be_falsey
end
end
context 'when authors are not authorized to approve their own MRs' do
it 'does not allow the author to approve the MR' do
expect(merge_request.can_approve?(author)).to be_falsey
end
end
end
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, source_project: project, author: author) }
let(:author) { create(:user) }
let(:approver) { create(:user) }
let(:approver_2) { create(:user) }
let(:developer) { create(:user) }
let(:other_developer) { create(:user) }
let(:reporter) { create(:user) }
let(:stranger) { create(:user) }
before do
stub_feature_flags(approval_rules: false)
project.add_developer(author)
project.add_developer(approver)
project.add_developer(approver_2)
project.add_developer(developer)
project.add_developer(other_developer)
project.add_reporter(reporter)
end
context 'when there is one approver required' do
before do
project.update(approvals_before_merge: 1)
end
context 'when that approver is the MR author' do
before do
create(:approver, user: author, target: merge_request)
end
it_behaves_like 'authors self-approval authorization'
it 'requires one approval' do
expect(merge_request.approvals_left).to eq(1)
end
it 'allows any other project member with write access to approve the MR' do
expect(merge_request.can_approve?(developer)).to be_truthy
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
end
it 'does not allow a logged-out user to approve the MR' do
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
context 'when that approver is not the MR author' do
before do
create(:approver, user: approver, target: merge_request)
end
it 'requires one approval' do
expect(merge_request.approvals_left).to eq(1)
end
it 'only allows the approver to approve the MR' do
expect(merge_request.can_approve?(approver)).to be_truthy
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(developer)).to be_falsey
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
end
context 'when there are multiple approvers required' do
before do
project.update(approvals_before_merge: 3)
end
context 'when one of those approvers is the MR author' do
before do
create(:approver, user: author, target: merge_request)
create(:approver, user: approver, target: merge_request)
create(:approver, user: approver_2, target: merge_request)
end
it_behaves_like 'authors self-approval authorization'
it 'requires the original number of approvals' do
expect(merge_request.approvals_left).to eq(3)
end
it 'allows any other other approver to approve the MR' do
expect(merge_request.can_approve?(approver)).to be_truthy
end
it 'does not allow a logged-out user to approve the MR' do
expect(merge_request.can_approve?(nil)).to be_falsey
end
context 'when self-approval is disabled and all of the valid approvers have approved the MR' do
before do
create(:approval, user: approver, merge_request: merge_request)
create(:approval, user: approver_2, merge_request: merge_request)
end
it 'requires the original number of approvals' do
expect(merge_request.approvals_left).to eq(1)
end
it 'does not allow the author to approve the MR' do
expect(merge_request.can_approve?(author)).to be_falsey
end
it 'does not allow the approvers to approve the MR again' do
expect(merge_request.can_approve?(approver)).to be_falsey
expect(merge_request.can_approve?(approver_2)).to be_falsey
end
it 'allows any other project member with write access to approve the MR' do
expect(merge_request.can_approve?(developer)).to be_truthy
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
context 'when self-approval is enabled and all of the valid approvers have approved the MR' do
before do
project.update!(merge_requests_author_approval: true)
create(:approval, user: author, merge_request: merge_request)
create(:approval, user: approver_2, merge_request: merge_request)
end
it 'requires the original number of approvals' do
expect(merge_request.approvals_left).to eq(1)
end
it 'does not allow the approvers to approve the MR again' do
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(approver_2)).to be_falsey
end
it 'allows any other project member with write access to approve the MR' do
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
context 'when more than the number of approvers have approved the MR' do
before do
create(:approval, user: approver, merge_request: merge_request)
create(:approval, user: approver_2, merge_request: merge_request)
create(:approval, user: developer, merge_request: merge_request)
end
it 'marks the MR as approved' do
expect(merge_request).to be_approved
end
it 'clamps the approvals left at zero' do
expect(merge_request.approvals_left).to eq(0)
end
end
end
context 'when the approvers do not contain the MR author' do
before do
create(:approver, user: developer, target: merge_request)
create(:approver, user: approver, target: merge_request)
create(:approver, user: approver_2, target: merge_request)
end
it 'requires the original number of approvals' do
expect(merge_request.approvals_left).to eq(3)
end
it 'only allows the approvers to approve the MR' do
expect(merge_request.can_approve?(developer)).to be_truthy
expect(merge_request.can_approve?(approver)).to be_truthy
expect(merge_request.can_approve?(approver_2)).to be_truthy
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
context 'when only 1 approval approved' do
it 'only allows the approvers to approve the MR' do
create(:approval, user: approver, merge_request: merge_request)
expect(merge_request.can_approve?(developer)).to be_truthy
expect(merge_request.can_approve?(approver)).to be_falsey
expect(merge_request.can_approve?(approver_2)).to be_truthy
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(other_developer)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
context 'when all approvals received' do
it 'allows anyone with write access except for author to approve the MR' do
create(:approval, user: approver, merge_request: merge_request)
create(:approval, user: approver_2, merge_request: merge_request)
create(:approval, user: developer, merge_request: merge_request)
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(other_developer)).to be_truthy
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
end
end
end
describe '#participant_approvers' do
let(:approvers) { create_list(:user, 2) }
let(:code_owners) { create_list(:user, 2) }
let!(:regular_rule) { create(:approval_merge_request_rule, merge_request: merge_request, users: approvers) }
let!(:code_owner_rule) { create(:approval_merge_request_rule, merge_request: merge_request, users: code_owners, code_owner: true) }
let!(:approval) { create(:approval, merge_request: merge_request, user: approvers.last) }
before do
allow(subject).to receive(:code_owners).and_return(code_owners)
end
it 'returns empty array if approval not needed' do
allow(subject).to receive(:approval_needed?).and_return(false)
expect(subject.participant_approvers).to be_empty
end
it 'returns approvers if approval is needed, excluding code owners' do
allow(subject).to receive(:approval_needed?).and_return(true)
expect(subject.participant_approvers).to contain_exactly(approvers.first)
end
end
describe '#participant_approvers with approval_rules disabled' do
let!(:approver) { create(:approver, target: project) }
let(:code_owners) { [double(:code_owner)] }
before do
stub_feature_flags(approval_rules: false)
allow(subject).to receive(:code_owners).and_return(code_owners)
end
......@@ -217,4 +488,201 @@ describe MergeRequest do
end
end
end
describe '#mergeable_with_quick_action?' do
def create_pipeline(status)
pipeline = create(:ci_pipeline_with_one_job,
project: project,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha,
status: status,
head_pipeline_of: merge_request)
pipeline
end
let(:project) { create(:project, :public, :repository, only_allow_merge_if_pipeline_succeeds: true) }
let(:developer) { create(:user) }
let(:user) { create(:user) }
let(:merge_request) { create(:merge_request, source_project: project) }
let(:mr_sha) { merge_request.diff_head_sha }
before do
project.add_developer(developer)
end
context 'when autocomplete_precheck is set to false' do
context 'with approvals' do
before do
merge_request.target_project.update(approvals_before_merge: 1)
end
it 'is not mergeable when not approved' do
expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_falsey
end
it 'is mergeable when approved' do
merge_request.approvals.create(user: user)
expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
end
end
end
end
describe "#approvers_left" do
let(:merge_request) {create :merge_request}
it "returns correct value" do
user = create(:user)
user1 = create(:user)
create(:approver, target: merge_request, user: user)
create(:approver, target: merge_request, user: user1)
merge_request.approvals.create(user_id: user1.id)
expect(merge_request.approvers_left).to eq [user]
end
it "returns correct value when there is a group approver" do
user = create(:user)
user1 = create(:user)
user2 = create(:user)
group = create(:group)
group.add_developer(user2)
create(:approver_group, target: merge_request, group: group)
create(:approver, target: merge_request, user: user)
create(:approver, target: merge_request, user: user1)
merge_request.approvals.create(user_id: user1.id)
expect(merge_request.approvers_left).to match_array [user, user2]
end
it "returns correct value when there is only a group approver" do
user = create(:user)
group = create(:group)
group.add_developer(user)
merge_request.approver_groups.create(group: group)
expect(merge_request.approvers_left).to eq [user]
end
end
describe "#overall_approver_groups" do
it 'returns a merge request group approver' do
project = create :project
create :approver_group, target: project
merge_request = create :merge_request, target_project: project, source_project: project
approver_group2 = create :approver_group, target: merge_request
expect(merge_request.overall_approver_groups).to eq([approver_group2])
end
it 'returns a project group approver' do
project = create :project
approver_group1 = create :approver_group, target: project
merge_request = create :merge_request, target_project: project, source_project: project
expect(merge_request.overall_approver_groups).to eq([approver_group1])
end
it 'returns a merge request approver if there is no project group approver' do
project = create :project
merge_request = create :merge_request, target_project: project, source_project: project
approver_group1 = create :approver_group, target: merge_request
expect(merge_request.overall_approver_groups).to eq([approver_group1])
end
end
describe '#all_approvers_including_groups' do
it 'returns correct set of users' do
user = create :user
user1 = create :user
user2 = create :user
create :user
project = create :project
group = create :group
group.add_maintainer user
create :approver_group, target: project, group: group
merge_request = create :merge_request, target_project: project, source_project: project
group1 = create :group
group1.add_maintainer user1
create :approver_group, target: merge_request, group: group1
create(:approver, user: user2, target: merge_request)
expect(merge_request.all_approvers_including_groups).to match_array([user1, user2])
end
end
describe '#approver_group_ids=' do
it 'create approver_groups' do
group = create :group
group1 = create :group
merge_request = create :merge_request
merge_request.approver_group_ids = "#{group.id}, #{group1.id}"
merge_request.save!
expect(merge_request.approver_groups.map(&:group)).to match_array([group, group1])
end
end
describe "#approvals_required" do
let(:merge_request) { build(:merge_request) }
before do
merge_request.target_project.update(approvals_before_merge: 3)
end
context "when the MR has approvals_before_merge set" do
before do
merge_request.update(approvals_before_merge: 1)
end
it "uses the approvals_before_merge from the MR" do
expect(merge_request.approvals_required).to eq(1)
end
end
context "when the MR doesn't have approvals_before_merge set" do
it "takes approvals_before_merge from the target project" do
expect(merge_request.approvals_required).to eq(3)
end
end
end
describe '#mergeable?' do
let(:project) { create(:project) }
subject { create(:merge_request, source_project: project) }
context 'when using approvals' do
let(:user) { create(:user) }
before do
allow(subject).to receive(:mergeable_state?).and_return(true)
subject.target_project.update(approvals_before_merge: 1)
project.add_developer(user)
end
it 'return false if not approved' do
expect(subject.mergeable?).to be_falsey
end
it 'return true if approved' do
subject.approvals.create(user: user)
expect(subject.mergeable?).to be_truthy
end
end
end
end
......@@ -5,6 +5,10 @@ describe VisibleApprovable do
let!(:project) { create(:project, :repository) }
let!(:user) { project.creator }
before do
stub_feature_flags(approval_rules: false)
end
describe '#requires_approve' do
subject { resource.requires_approve? }
......
# frozen_string_literal: true
require 'spec_helper'
describe ApprovalRulePresenter do
describe '#groups' do
set(:user) { create(:user) }
set(:public_group) { create(:group) }
set(:private_group) { create(:group, :private) }
let(:groups) { [public_group, private_group] }
shared_examples 'filtering private group' do
subject { described_class.new(rule, current_user: user) }
context 'when user has no access to private group' do
it 'excludes private group' do
expect(subject.groups).to contain_exactly(public_group)
end
end
context 'when user has access to private group' do
it 'includes private group' do
private_group.add_owner(user)
expect(subject.groups).to contain_exactly(*groups)
end
end
end
context 'project rule' do
let(:rule) { create(:approval_project_rule, groups: groups) }
it_behaves_like 'filtering private group'
end
context 'wrapped approval rule' do
let(:rule) do
mr_rule = create(:approval_merge_request_rule, groups: groups)
ApprovalWrappedRule.new(mr_rule.merge_request, mr_rule)
end
it_behaves_like 'filtering private group'
end
end
end
......@@ -21,6 +21,7 @@ describe MergeRequestPresenter do
let!(:approver) { create(:approver, target: resource) }
before do
stub_feature_flags(approval_rules: false)
resource.approvals.create!(user: approver.user)
end
......@@ -69,6 +70,10 @@ describe MergeRequestPresenter do
subject { described_class.new(resource, current_user: user).all_approvers_including_groups }
before do
stub_feature_flags(approval_rules: false)
end
it { is_expected.to match_array(public_approver_group.users + [approver.user]) }
context 'when user has access to private group' do
......
......@@ -9,6 +9,8 @@ describe API::MergeRequestApprovals do
before do
project.update_attribute(:approvals_before_merge, 2)
stub_feature_flags(approval_rules: false)
end
describe 'GET :id/merge_requests/:merge_request_iid/approvals' do
......
......@@ -10,6 +10,10 @@ describe API::ProjectApprovals do
let(:url) { "/projects/#{project.id}/approvals" }
before do
stub_feature_flags(approval_rules: false)
end
describe 'GET /projects/:id/approvers' do
context 'when the request is correct' do
before do
......
......@@ -73,12 +73,14 @@ describe MergeRequests::RefreshService do
end
end
context 'when code owners enabled' do
context 'when code owners enabled, with approval_rule disabled' do
let(:old_owners) { [] }
let(:new_owners) { [] }
let(:relevant_merge_requests) { [merge_request, another_merge_request] }
before do
stub_feature_flags(approval_rules: false)
relevant_merge_requests.each do |merge_request|
expect(::Gitlab::CodeOwners).to receive(:for_merge_request).with(merge_request).and_return(new_owners)
expect(::Gitlab::CodeOwners).to receive(:for_merge_request).with(merge_request, merge_request_diff: anything).and_wrap_original do |m, *args|
......
......@@ -509,4 +509,120 @@ describe EE::NotificationService, :mailer do
# Make the watcher a subscriber to detect dupes
issuable.subscriptions.create(user: @watcher_and_subscriber, subscribed: true)
end
context 'Merge Requests' do
let(:notification) { NotificationService.new }
let(:assignee) { create(:user) }
let(:group) { create(:group) }
let(:project) { create(:project, :public, :repository, namespace: group) }
let(:another_project) { create(:project, :public, namespace: group) }
let(:merge_request) { create :merge_request, source_project: project, assignee: create(:user), description: 'cc @participant' }
around do |example|
perform_enqueued_jobs do
example.run
end
end
before do
stub_feature_flags(approval_rules: false)
project.add_maintainer(merge_request.author)
project.add_maintainer(merge_request.assignee)
build_team(merge_request.target_project)
add_users_with_subscription(merge_request.target_project, merge_request)
update_custom_notification(:new_merge_request, @u_guest_custom, resource: project)
update_custom_notification(:new_merge_request, @u_custom_global)
reset_delivered_emails!
end
describe '#new_merge_request' do
context 'when the target project has approvers set' do
let(:project_approvers) { create_list(:user, 3) }
before do
merge_request.target_project.update(approvals_before_merge: 1)
project_approvers.each { |approver| create(:approver, user: approver, target: merge_request.target_project) }
reset_delivered_emails!
end
it 'emails the approvers' do
notification.new_merge_request(merge_request, @u_disabled)
project_approvers.each { |approver| should_email(approver) }
end
it 'does not email the approvers when approval is not necessary' do
merge_request.target_project.update(approvals_before_merge: 0)
notification.new_merge_request(merge_request, @u_disabled)
project_approvers.each { |approver| should_not_email(approver) }
end
context 'when the merge request has approvers set' do
let(:mr_approvers) { create_list(:user, 3) }
before do
mr_approvers.each { |approver| create(:approver, user: approver, target: merge_request) }
reset_delivered_emails!
end
it 'emails the MR approvers' do
notification.new_merge_request(merge_request, @u_disabled)
mr_approvers.each { |approver| should_email(approver) }
end
it 'does not email approvers set on the project who are not approvers of this MR' do
notification.new_merge_request(merge_request, @u_disabled)
project_approvers.each { |approver| should_not_email(approver) }
end
end
end
end
def build_team(project)
@u_watcher = create_global_setting_for(create(:user), :watch)
@u_participating = create_global_setting_for(create(:user), :participating)
@u_participant_mentioned = create_global_setting_for(create(:user, username: 'participant'), :participating)
@u_disabled = create_global_setting_for(create(:user), :disabled)
@u_mentioned = create_global_setting_for(create(:user, username: 'mention'), :mention)
@u_committer = create(:user, username: 'committer')
@u_not_mentioned = create_global_setting_for(create(:user, username: 'regular'), :participating)
@u_outsider_mentioned = create(:user, username: 'outsider')
@u_custom_global = create_global_setting_for(create(:user, username: 'custom_global'), :custom)
# User to be participant by default
# This user does not contain any record in notification settings table
# It should be treated with a :participating notification_level
@u_lazy_participant = create(:user, username: 'lazy-participant')
@u_guest_watcher = create_user_with_notification(:watch, 'guest_watching')
@u_guest_custom = create_user_with_notification(:custom, 'guest_custom')
[@u_watcher, @u_participating, @u_participant_mentioned, @u_disabled, @u_mentioned, @u_committer, @u_not_mentioned, @u_lazy_participant, @u_custom_global].each do |user|
project.add_maintainer(user)
end
end
def add_users_with_subscription(project, issuable)
@subscriber = create :user
@unsubscriber = create :user
@unsubscribed_mentioned = create :user, username: 'unsubscribed_mentioned'
@subscribed_participant = create_global_setting_for(create(:user, username: 'subscribed_participant'), :participating)
@watcher_and_subscriber = create_global_setting_for(create(:user), :watch)
[@subscribed_participant, @subscriber, @unsubscriber, @watcher_and_subscriber, @unsubscribed_mentioned].each do |user|
project.add_maintainer(user)
end
issuable.subscriptions.create(user: @unsubscribed_mentioned, project: project, subscribed: false)
issuable.subscriptions.create(user: @subscriber, project: project, subscribed: true)
issuable.subscriptions.create(user: @subscribed_participant, project: project, subscribed: true)
issuable.subscriptions.create(user: @unsubscriber, project: project, subscribed: false)
# Make the watcher a subscriber to detect dupes
issuable.subscriptions.create(user: @watcher_and_subscriber, project: project, subscribed: true)
end
end
end
......@@ -8,6 +8,10 @@ describe MergeRequests::RemoveApprovalService do
subject(:service) { described_class.new(project, user) }
before do
stub_feature_flags(approval_rules: false)
end
def execute!
service.execute(merge_request)
end
......
......@@ -60,24 +60,157 @@ describe MergeRequests::UpdateService, :mailer do
context 'when approvals_before_merge changes' do
using RSpec::Parameterized::TableSyntax
where(:project_value, :mr_before_value, :mr_after_value, :result) do
3 | 4 | 5 | 5
3 | 4 | nil | 3
3 | nil | 5 | 5
context 'when approval_rules is disabled' do
before do
stub_feature_flags(approval_rules: false)
end
where(:project_value, :mr_before_value, :mr_after_value, :result) do
3 | 4 | 5 | 5
3 | 4 | nil | 3
3 | nil | 5 | 5
end
with_them do
let(:project) { create(:project, :repository, approvals_before_merge: project_value) }
it "updates approval_rules' approvals_required" do
merge_request.update(approvals_before_merge: mr_before_value)
rule = create(:approval_merge_request_rule, merge_request: merge_request)
update_merge_request(approvals_before_merge: mr_after_value)
expect(rule.reload.approvals_required).to eq(result)
end
end
end
with_them do
let(:project) { create(:project, :repository, approvals_before_merge: project_value) }
context 'when approval_rules is enabled' do
where(:project_value, :mr_before_value, :mr_after_value, :result) do
3 | 4 | 5 | 5
3 | 4 | nil | 3
3 | nil | 5 | 5
end
with_them do
let(:project) { create(:project, :repository, approvals_before_merge: project_value) }
it "updates approval_rules' approvals_required" do
merge_request.update(approvals_before_merge: mr_before_value)
rule = create(:approval_merge_request_rule, merge_request: merge_request)
it "does not update" do
merge_request.update(approvals_before_merge: mr_before_value)
rule = create(:approval_merge_request_rule, merge_request: merge_request)
update_merge_request(approvals_before_merge: mr_after_value)
update_merge_request(approvals_before_merge: mr_after_value)
expect(rule.reload.approvals_required).to eq(result)
expect(rule.reload.approvals_required).to eq(0)
end
end
end
end
context 'merge' do
before do
stub_feature_flags(approval_rules: false)
end
let(:opts) { { merge: merge_request.diff_head_sha } }
context 'when not approved' do
before do
merge_request.update(approvals_before_merge: 1)
perform_enqueued_jobs do
update_merge_request(opts)
@merge_request = MergeRequest.find(merge_request.id)
end
end
it { expect(@merge_request).to be_valid }
it { expect(@merge_request.state).to eq('opened') }
end
context 'when approved' do
before do
merge_request.update(approvals_before_merge: 1)
merge_request.approvals.create(user: user)
perform_enqueued_jobs do
update_merge_request(opts)
@merge_request = MergeRequest.find(merge_request.id)
end
end
it { expect(@merge_request).to be_valid }
it { expect(@merge_request.state).to eq('merged') }
end
end
context 'when the approvers change' do
let(:existing_approver) { create(:user) }
let(:removed_approver) { create(:user) }
let(:new_approver) { create(:user) }
before do
stub_feature_flags(approval_rules: false)
project.add_developer(existing_approver)
project.add_developer(removed_approver)
project.add_developer(new_approver)
perform_enqueued_jobs do
update_merge_request(approver_ids: [existing_approver, removed_approver].map(&:id).join(','))
end
Todo.where(action: Todo::APPROVAL_REQUIRED).destroy_all # rubocop: disable DestroyAll
ActionMailer::Base.deliveries.clear
end
context 'when an approver is added and an approver is removed' do
before do
perform_enqueued_jobs do
update_merge_request(approver_ids: [new_approver, existing_approver].map(&:id).join(','))
end
end
it 'adds todos for and sends emails to the new approvers' do
expect(Todo.where(user: new_approver, action: Todo::APPROVAL_REQUIRED)).not_to be_empty
should_email(new_approver)
end
it 'does not add todos for or send emails to the existing approvers' do
expect(Todo.where(user: existing_approver, action: Todo::APPROVAL_REQUIRED)).to be_empty
should_not_email(existing_approver)
end
it 'does not add todos for or send emails to the removed approvers' do
expect(Todo.where(user: removed_approver, action: Todo::APPROVAL_REQUIRED)).to be_empty
should_not_email(removed_approver)
end
end
context 'when the approvers are set to the same values' do
it 'does not create any todos' do
expect do
update_merge_request(approver_ids: [existing_approver, removed_approver].map(&:id).join(','))
end.not_to change { Todo.count }
end
it 'does not send any emails' do
expect do
update_merge_request(approver_ids: [existing_approver, removed_approver].map(&:id).join(','))
end.not_to change { ActionMailer::Base.deliveries.count }
end
end
end
context 'updating target_branch' do
it 'resets approvals when target_branch is changed' do
merge_request.target_project.update(reset_approvals_on_push: true)
merge_request.approvals.create(user_id: user2.id)
update_merge_request(target_branch: 'video')
expect(merge_request.reload.approvals).to be_empty
end
end
end
end
......@@ -230,12 +230,26 @@ describe Projects::UpdateService, '#execute' do
end
context 'with approval_rules' do
it "updates approval_rules' approvals_required" do
rule = create(:approval_project_rule, project: project)
context 'when approval_rules is disabled' do
it "updates approval_rules' approvals_required" do
stub_feature_flags(approval_rules: false)
update_project(project, user, approvals_before_merge: 42)
rule = create(:approval_project_rule, project: project)
expect(rule.reload.approvals_required).to eq(42)
update_project(project, user, approvals_before_merge: 42)
expect(rule.reload.approvals_required).to eq(42)
end
end
context 'when approval_rules is enabled' do
it 'does not update' do
rule = create(:approval_project_rule, project: project)
update_project(project, user, approvals_before_merge: 42)
expect(rule.reload.approvals_required).to eq(0)
end
end
end
......
......@@ -879,136 +879,6 @@ describe MergeRequest do
end
end
describe "#approvers_left" do
let(:merge_request) {create :merge_request}
it "returns correct value" do
user = create(:user)
user1 = create(:user)
merge_request.approvers.create(user_id: user.id)
merge_request.approvers.create(user_id: user1.id)
merge_request.approvals.create(user_id: user1.id)
expect(merge_request.approvers_left).to eq [user]
end
it "returns correct value when there is a group approver" do
user = create(:user)
user1 = create(:user)
user2 = create(:user)
group = create(:group)
group.add_developer(user2)
merge_request.approver_groups.create(group: group)
merge_request.approvers.create(user_id: user.id)
merge_request.approvers.create(user_id: user1.id)
merge_request.approvals.create(user_id: user1.id)
expect(merge_request.approvers_left).to match_array [user, user2]
end
it "returns correct value when there is only a group approver" do
user = create(:user)
group = create(:group)
group.add_developer(user)
merge_request.approver_groups.create(group: group)
expect(merge_request.approvers_left).to eq [user]
end
end
describe "#overall_approver_groups" do
it 'returns a merge request group approver' do
project = create :project
create :approver_group, target: project
merge_request = create :merge_request, target_project: project, source_project: project
approver_group2 = create :approver_group, target: merge_request
expect(merge_request.overall_approver_groups).to eq([approver_group2])
end
it 'returns a project group approver' do
project = create :project
approver_group1 = create :approver_group, target: project
merge_request = create :merge_request, target_project: project, source_project: project
expect(merge_request.overall_approver_groups).to eq([approver_group1])
end
it 'returns a merge request approver if there is no project group approver' do
project = create :project
merge_request = create :merge_request, target_project: project, source_project: project
approver_group1 = create :approver_group, target: merge_request
expect(merge_request.overall_approver_groups).to eq([approver_group1])
end
end
describe '#all_approvers_including_groups' do
it 'returns correct set of users' do
user = create :user
user1 = create :user
user2 = create :user
create :user
project = create :project
group = create :group
group.add_maintainer user
create :approver_group, target: project, group: group
merge_request = create :merge_request, target_project: project, source_project: project
group1 = create :group
group1.add_maintainer user1
create :approver_group, target: merge_request, group: group1
create(:approver, user: user2, target: merge_request)
expect(merge_request.all_approvers_including_groups).to match_array([user1, user2])
end
end
describe '#approver_group_ids=' do
it 'create approver_groups' do
group = create :group
group1 = create :group
merge_request = create :merge_request
merge_request.approver_group_ids = "#{group.id}, #{group1.id}"
merge_request.save!
expect(merge_request.approver_groups.map(&:group)).to match_array([group, group1])
end
end
describe "#approvals_required" do
let(:merge_request) { build(:merge_request) }
before do
merge_request.target_project.update(approvals_before_merge: 3)
end
context "when the MR has approvals_before_merge set" do
before do
merge_request.update(approvals_before_merge: 1)
end
it "uses the approvals_before_merge from the MR" do
expect(merge_request.approvals_required).to eq(1)
end
end
context "when the MR doesn't have approvals_before_merge set" do
it "takes approvals_before_merge from the target project" do
expect(merge_request.approvals_required).to eq(3)
end
end
end
describe '#can_remove_source_branch?' do
set(:user) { create(:user) }
set(:merge_request) { create(:merge_request, :simple) }
......@@ -2054,26 +1924,6 @@ describe MergeRequest do
expect(subject.mergeable?).to be_truthy
end
context 'when using approvals' do
let(:user) { create(:user) }
before do
allow(subject).to receive(:mergeable_state?).and_return(true)
subject.target_project.update(approvals_before_merge: 1)
project.add_developer(user)
end
it 'return false if not approved' do
expect(subject.mergeable?).to be_falsey
end
it 'return true if approved' do
subject.approvals.create(user: user)
expect(subject.mergeable?).to be_truthy
end
end
end
describe '#mergeable_state?' do
......@@ -2406,248 +2256,6 @@ describe MergeRequest do
end
end
describe 'approvals' do
shared_examples_for 'authors self-approval authorization' do
context 'when authors are authorized to approve their own MRs' do
before do
project.update!(merge_requests_author_approval: true)
end
it 'allows the author to approve the MR if within the approvers list' do
expect(merge_request.can_approve?(author)).to be_truthy
end
it 'does not allow the author to approve the MR if not within the approvers list' do
merge_request.approvers.delete_all
expect(merge_request.can_approve?(author)).to be_falsey
end
end
context 'when authors are not authorized to approve their own MRs' do
it 'does not allow the author to approve the MR' do
expect(merge_request.can_approve?(author)).to be_falsey
end
end
end
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, source_project: project, author: author) }
let(:author) { create(:user) }
let(:approver) { create(:user) }
let(:approver_2) { create(:user) }
let(:developer) { create(:user) }
let(:other_developer) { create(:user) }
let(:reporter) { create(:user) }
let(:stranger) { create(:user) }
before do
project.add_developer(author)
project.add_developer(approver)
project.add_developer(approver_2)
project.add_developer(developer)
project.add_developer(other_developer)
project.add_reporter(reporter)
end
context 'when there is one approver required' do
before do
project.update(approvals_before_merge: 1)
end
context 'when that approver is the MR author' do
before do
create(:approver, user: author, target: merge_request)
end
it_behaves_like 'authors self-approval authorization'
it 'requires one approval' do
expect(merge_request.approvals_left).to eq(1)
end
it 'allows any other project member with write access to approve the MR' do
expect(merge_request.can_approve?(developer)).to be_truthy
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
end
it 'does not allow a logged-out user to approve the MR' do
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
context 'when that approver is not the MR author' do
before do
create(:approver, user: approver, target: merge_request)
end
it 'requires one approval' do
expect(merge_request.approvals_left).to eq(1)
end
it 'only allows the approver to approve the MR' do
expect(merge_request.can_approve?(approver)).to be_truthy
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(developer)).to be_falsey
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
end
context 'when there are multiple approvers required' do
before do
project.update(approvals_before_merge: 3)
end
context 'when one of those approvers is the MR author' do
before do
create(:approver, user: author, target: merge_request)
create(:approver, user: approver, target: merge_request)
create(:approver, user: approver_2, target: merge_request)
end
it_behaves_like 'authors self-approval authorization'
it 'requires the original number of approvals' do
expect(merge_request.approvals_left).to eq(3)
end
it 'allows any other other approver to approve the MR' do
expect(merge_request.can_approve?(approver)).to be_truthy
end
it 'does not allow a logged-out user to approve the MR' do
expect(merge_request.can_approve?(nil)).to be_falsey
end
context 'when self-approval is disabled and all of the valid approvers have approved the MR' do
before do
create(:approval, user: approver, merge_request: merge_request)
create(:approval, user: approver_2, merge_request: merge_request)
end
it 'requires the original number of approvals' do
expect(merge_request.approvals_left).to eq(1)
end
it 'does not allow the author to approve the MR' do
expect(merge_request.can_approve?(author)).to be_falsey
end
it 'does not allow the approvers to approve the MR again' do
expect(merge_request.can_approve?(approver)).to be_falsey
expect(merge_request.can_approve?(approver_2)).to be_falsey
end
it 'allows any other project member with write access to approve the MR' do
expect(merge_request.can_approve?(developer)).to be_truthy
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
context 'when self-approval is enabled and all of the valid approvers have approved the MR' do
before do
project.update!(merge_requests_author_approval: true)
create(:approval, user: author, merge_request: merge_request)
create(:approval, user: approver_2, merge_request: merge_request)
end
it 'requires the original number of approvals' do
expect(merge_request.approvals_left).to eq(1)
end
it 'does not allow the approvers to approve the MR again' do
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(approver_2)).to be_falsey
end
it 'allows any other project member with write access to approve the MR' do
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
context 'when more than the number of approvers have approved the MR' do
before do
create(:approval, user: approver, merge_request: merge_request)
create(:approval, user: approver_2, merge_request: merge_request)
create(:approval, user: developer, merge_request: merge_request)
end
it 'marks the MR as approved' do
expect(merge_request).to be_approved
end
it 'clamps the approvals left at zero' do
expect(merge_request.approvals_left).to eq(0)
end
end
end
context 'when the approvers do not contain the MR author' do
before do
create(:approver, user: developer, target: merge_request)
create(:approver, user: approver, target: merge_request)
create(:approver, user: approver_2, target: merge_request)
end
it 'requires the original number of approvals' do
expect(merge_request.approvals_left).to eq(3)
end
it 'only allows the approvers to approve the MR' do
expect(merge_request.can_approve?(developer)).to be_truthy
expect(merge_request.can_approve?(approver)).to be_truthy
expect(merge_request.can_approve?(approver_2)).to be_truthy
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
context 'when only 1 approval approved' do
it 'only allows the approvers to approve the MR' do
create(:approval, user: approver, merge_request: merge_request)
expect(merge_request.can_approve?(developer)).to be_truthy
expect(merge_request.can_approve?(approver)).to be_falsey
expect(merge_request.can_approve?(approver_2)).to be_truthy
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(other_developer)).to be_falsey
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
context 'when all approvals received' do
it 'allows anyone with write access except for author to approve the MR' do
create(:approval, user: approver, merge_request: merge_request)
create(:approval, user: approver_2, merge_request: merge_request)
create(:approval, user: developer, merge_request: merge_request)
expect(merge_request.can_approve?(author)).to be_falsey
expect(merge_request.can_approve?(reporter)).to be_falsey
expect(merge_request.can_approve?(other_developer)).to be_truthy
expect(merge_request.can_approve?(stranger)).to be_falsey
expect(merge_request.can_approve?(nil)).to be_falsey
end
end
end
end
end
describe '#branch_merge_base_commit' do
context 'source and target branch exist' do
it { expect(subject.branch_merge_base_commit.sha).to eq('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') }
......@@ -2948,22 +2556,6 @@ describe MergeRequest do
expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
end
end
context 'with approvals' do
before do
merge_request.target_project.update(approvals_before_merge: 1)
end
it 'is not mergeable when not approved' do
expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_falsey
end
it 'is mergeable when approved' do
merge_request.approvals.create(user: user)
expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
end
end
end
end
......
......@@ -258,35 +258,6 @@ describe MergeRequests::UpdateService, :mailer do
it { expect(@merge_request.state).to eq('opened') }
end
context 'when not approved' do
before do
merge_request.update(approvals_before_merge: 1)
perform_enqueued_jobs do
service.execute(merge_request)
@merge_request = MergeRequest.find(merge_request.id)
end
end
it { expect(@merge_request).to be_valid }
it { expect(@merge_request.state).to eq('opened') }
end
context 'when approved' do
before do
merge_request.update(approvals_before_merge: 1)
merge_request.approvals.create(user: user)
perform_enqueued_jobs do
service.execute(merge_request)
@merge_request = MergeRequest.find(merge_request.id)
end
end
it { expect(@merge_request).to be_valid }
it { expect(@merge_request.state).to eq('merged') }
end
end
context 'todos' do
......@@ -483,58 +454,6 @@ describe MergeRequests::UpdateService, :mailer do
end
end
context 'when the approvers change' do
let(:existing_approver) { create(:user) }
let(:removed_approver) { create(:user) }
let(:new_approver) { create(:user) }
before do
perform_enqueued_jobs do
update_merge_request(approver_ids: [existing_approver, removed_approver].map(&:id).join(','))
end
Todo.where(action: Todo::APPROVAL_REQUIRED).destroy_all # rubocop: disable DestroyAll
ActionMailer::Base.deliveries.clear
end
context 'when an approver is added and an approver is removed' do
before do
perform_enqueued_jobs do
update_merge_request(approver_ids: [new_approver, existing_approver].map(&:id).join(','))
end
end
it 'adds todos for and sends emails to the new approvers' do
expect(Todo.where(user: new_approver, action: Todo::APPROVAL_REQUIRED)).not_to be_empty
should_email(new_approver)
end
it 'does not add todos for or send emails to the existing approvers' do
expect(Todo.where(user: existing_approver, action: Todo::APPROVAL_REQUIRED)).to be_empty
should_not_email(existing_approver)
end
it 'does not add todos for or send emails to the removed approvers' do
expect(Todo.where(user: removed_approver, action: Todo::APPROVAL_REQUIRED)).to be_empty
should_not_email(removed_approver)
end
end
context 'when the approvers are set to the same values' do
it 'does not create any todos' do
expect do
update_merge_request(approver_ids: [existing_approver, removed_approver].map(&:id).join(','))
end.not_to change { Todo.count }
end
it 'does not send any emails' do
expect do
update_merge_request(approver_ids: [existing_approver, removed_approver].map(&:id).join(','))
end.not_to change { ActionMailer::Base.deliveries.count }
end
end
end
context 'updating mentions' do
let(:mentionable) { merge_request }
include_examples 'updating mentions', described_class
......@@ -620,17 +539,6 @@ describe MergeRequests::UpdateService, :mailer do
end
end
context 'updating target_branch' do
it 'resets approvals when target_branch is changed' do
merge_request.target_project.update(reset_approvals_on_push: true)
merge_request.approvals.create(user_id: user2.id)
update_merge_request(target_branch: 'video')
expect(merge_request.reload.approvals).to be_empty
end
end
context 'updating asssignee_id' do
it 'does not update assignee when assignee_id is invalid' do
merge_request.update(assignee_id: user.id)
......
......@@ -1304,48 +1304,6 @@ describe NotificationService, :mailer do
should_email(user_4)
end
context 'when the target project has approvers set' do
let(:project_approvers) { create_list(:user, 3) }
before do
merge_request.target_project.update(approvals_before_merge: 1)
project_approvers.each { |approver| create(:approver, user: approver, target: merge_request.target_project) }
end
it 'emails the approvers' do
notification.new_merge_request(merge_request, @u_disabled)
project_approvers.each { |approver| should_email(approver) }
end
it 'does not email the approvers when approval is not necessary' do
merge_request.target_project.update(approvals_before_merge: 0)
notification.new_merge_request(merge_request, @u_disabled)
project_approvers.each { |approver| should_not_email(approver) }
end
context 'when the merge request has approvers set' do
let(:mr_approvers) { create_list(:user, 3) }
before do
mr_approvers.each { |approver| create(:approver, user: approver, target: merge_request) }
end
it 'emails the MR approvers' do
notification.new_merge_request(merge_request, @u_disabled)
mr_approvers.each { |approver| should_email(approver) }
end
it 'does not email approvers set on the project who are not approvers of this MR' do
notification.new_merge_request(merge_request, @u_disabled)
project_approvers.each { |approver| should_not_email(approver) }
end
end
end
context 'participating' do
it_should_behave_like 'participating by assignee notification' do
let(:participant) { create(:user, username: 'user-participant')}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment