# encoding: utf-8
#--
# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#++
require File.dirname(__FILE__) + '/../test_helper'
class MergeRequestTest < ActiveSupport::TestCase
def setup
@merge_request = merge_requests(:moes_to_johans)
commits = ["9dbb89110fc45362fc4dc3f60d960381",
"6823e6622e1da9751c87380ff01a1db1",
"526fa6c0b3182116d8ca2dc80dedeafb",
"286e8afb9576366a2a43b12b94738f07"].collect do |sha|
m = mock
m.stubs(:id).returns(sha)
m
end
@merge_request.stubs(:commits_for_selection).returns(commits)
assert @merge_request.pending_acceptance_of_terms?
end
should_validate_presence_of :user, :source_repository, :target_repository
should_validate_presence_of :summary, :sequence_number
should_have_many :comments
should_not_allow_mass_assignment_of :sequence_number
should 'calculate the merge base between target branch and self' do
repo = mock("Git repo")
git = mock("Git")
repo.stubs(:git).returns(git)
@merge_request.target_repository.stubs(:git).returns(repo)
git.expects(:merge_base).with({:timeout => false},
@merge_request.target_branch, "refs/merge-requests/#{@merge_request.to_param}").returns("ffcaabd\n")
assert_equal 'ffcaabd', @merge_request.calculate_merge_base
end
should 'create a version with the merge base' do
@merge_request.expects(:calculate_merge_base).returns('ffcaabd')
version = @merge_request.create_new_version
assert_equal 1, version.version
assert_equal "ffcaabd", version.merge_base_sha
end
should 'generate valid version numbers for its version' do
version = @merge_request.build_new_version
assert version.save
assert_equal 1, version.version
version = @merge_request.build_new_version
assert version.save
assert_equal 2, version.version
end
should 'send a MQ message when being confirmed by the user' do
p = proc {@merge_request.confirmed_by_user}
message = find_message_with_queue_and_regexp('/queue/GitoriousMergeRequestCreation', /.*/) {p.call}
assert_equal({'merge_request_id' => @merge_request.id.to_s}, message)
end
should "not send messages even if notifications are on" do
assert_equal 1, @merge_request.target_repository.committerships.count
cs = @merge_request.target_repository.committerships.first
cs.build_permissions(:review); cs.save!
@merge_request.user = users(:mike)
@merge_request.save
assert_no_difference("Message.count", @merge_request.target_repository.reviewers.size) do
@merge_request.confirmed_by_user
end
end
should "not send messages the subscribers when confirmed by the user, if the target_repo has it turned off" do
@merge_request.target_repository.update_attribute(:notify_committers_on_new_merge_request, false)
assert_no_difference("Message.count") do
@merge_request.confirmed_by_user
end
end
context "default status" do
setup do
@project = @merge_request.target_repository.project
end
should "find the default state" do
assert_nil @merge_request.default_status
MergeRequestStatus.create_defaults_for_project(@project)
assert_equal @project.merge_request_statuses.first, @merge_request.default_status
end
should "use the default status (if any)" do
MergeRequestStatus.create_defaults_for_project(@project)
@project.merge_request_statuses.first.update_attribute(:name, "New")
@merge_request.confirmed_by_user
assert_equal "New", @merge_request.reload.status_tag.to_s
end
should "default to 'Open' if there's no default_status" do
@merge_request.confirmed_by_user
assert_equal "Open", @merge_request.reload.status_tag.to_s
assert_equal MergeRequest::STATUS_OPEN, @merge_request.status
end
end
context "Merge request readyness" do
should 'have a ready? method which tells whether it has been created in the background' do
assert !@merge_request.ready?
v = @merge_request.build_new_version
assert v.save
assert @merge_request.ready?
end
should "always be ready if it's a legacy merge request" do
@merge_request.versions.destroy_all
@merge_request.update_attribute(:legacy, true)
assert @merge_request.ready?
end
end
should 'be able to update from a push event' do
@merge_request.expects(:push_new_branch_to_tracking_repo).once
@merge_request.update_from_push!
@merge_request.reload
end
should "return its target repository's tracking repository" do
tracking_repo = @merge_request.target_repository.create_tracking_repository
assert_equal tracking_repo, @merge_request.tracking_repository
end
should 'create a new version with the merge base between target branch and self' do
@merge_request.expects(:calculate_merge_base).returns('ff0')
version = @merge_request.create_new_version
assert_equal 'ff0', version.merge_base_sha
end
should 'calculate commit diff from tracking repo' do
@merge_request.stubs(:calculate_merge_base).returns('ff0')
version = @merge_request.create_new_version
version.stubs(:affected_commits).returns([])
@merge_request.stubs(:versions).returns([version])
assert_equal [], @merge_request.commit_diff_from_tracking_repo(version.version)
assert_equal [], @merge_request.commit_diff_from_tracking_repo
end
should 'build the name of its merge request branch' do
@merge_request.stubs(:calculate_merge_base).returns('ff0')
version = @merge_request.create_new_version
assert_equal "refs/merge-requests/#{@merge_request.to_param}", @merge_request.merge_branch_name
assert_equal "refs/merge-requests/#{@merge_request.to_param}/1", @merge_request.merge_branch_name(1)
assert_equal "refs/merge-requests/#{@merge_request.to_param}/#{version.version}", @merge_request.merge_branch_name(:current)
end
should 'push new branch to tracking repo' do
tracking_repo = mock
tracking_repo.stubs(:full_repository_path).returns("/tmp/foo.git")
@merge_request.stubs(:tracking_repository).returns(tracking_repo)
repo = mock("Target repository")
repo.expects(:push).once.with({:timeout => false},
@merge_request.tracking_repository.full_repository_path,
"refs/merge-requests/#{@merge_request.to_param}:refs/merge-requests/#{@merge_request.to_param}/#{@merge_request.next_version_number}")
git = mock
git.stubs(:git).returns(repo)
@merge_request.target_repository.stubs(:git).returns(git)
@merge_request.stubs(:calculate_merge_base).returns('ff0')
assert_incremented_by(@merge_request.versions, :size, 1) do
@merge_request.push_new_branch_to_tracking_repo
end
end
should "has a closed? status" do
@merge_request.status = MergeRequest::STATUS_CLOSED
assert @merge_request.closed?, '@merge_request.closed? should be true'
end
should "has a open? status" do
@merge_request.status = MergeRequest::STATUS_OPEN
assert @merge_request.open?, '@merge_request.open? should be true'
end
should 'know if a specific commit has been merged or not' do
repo = mock("Git repo")
git = mock("Git backend")
repo.stubs(:git).returns(git)
@merge_request.target_repository.stubs(:git).returns(repo)
git.expects(:cherry).with({}, @merge_request.target_branch, 'ff0').returns('')
git.expects(:cherry).with({}, @merge_request.target_branch, 'ffc').returns('+ bbacd')
assert !@merge_request.commit_merged?('ffc')
assert @merge_request.commit_merged?('ff0')
end
should 'cache requests to commit_merged?' do
Rails.cache.expects(:fetch).with("merge_status_for_commit_ff0_in_repository_#{@merge_request.target_repository.id}", :expires_in => 60.minutes).returns(:true)
Rails.cache.expects(:fetch).with("merge_status_for_commit_ff1_in_repository_#{@merge_request.target_repository.id}", :expires_in => 60.minutes).returns(:false)
assert @merge_request.commit_merged?('ff0')
assert !@merge_request.commit_merged?('ff1')
end
should "has a statuses class method" do
assert_equal MergeRequest::STATUS_PENDING_ACCEPTANCE_OF_TERMS, MergeRequest.statuses["Pending"]
assert_equal MergeRequest::STATUS_OPEN, MergeRequest.statuses["Open"]
assert_equal MergeRequest::STATUS_CLOSED, MergeRequest.statuses["Closed"]
end
should "has a status_string" do
MergeRequest.statuses.each do |k,v|
@merge_request.status = v
assert_equal k.downcase, @merge_request.status_string
end
end
should "knows who can resolve itself" do
assert @merge_request.resolvable_by?(users(:johan))
@merge_request.target_repository.committerships.create_with_permissions!({
:committer => groups(:team_thunderbird)
}, Committership::CAN_REVIEW)
assert @merge_request.resolvable_by?(users(:mike))
assert !@merge_request.resolvable_by?(users(:moe))
end
should "be resolvable by the MR creator as well" do
creator = @merge_request.user = users(:mike)
@merge_request.save!
@merge_request.target_repository.committerships.each(&:destroy)
assert !creator.can_write_to?(@merge_request.target_repository)
assert @merge_request.resolvable_by?(creator), "not resolvable by creator"
assert !@merge_request.resolvable_by?(users(:moe))
end
should "have a working resolvable_by? together with fucktard authentication systems" do
assert !@merge_request.resolvable_by?(:false)
end
should "count open merge_requests" do
mr = @merge_request.clone
mr.status = MergeRequest::STATUS_CLOSED
mr.save
assert_equal 2, MergeRequest.count_open
end
should 'have a transition from pending to open' do
mr = @merge_request.clone
assert mr.pending_acceptance_of_terms?
@merge_request.oauth_consumer.valid_oauth_credentials=({:key => 'key', :secret => 'secret'})
mr.stubs(:oauth_signoff_parameters).returns({})
mr.terms_accepted
assert mr.open?
assert_equal 'valid_version_sha', mr.contribution_agreement_version
assert_equal 'Thank you for your contribution', mr.contribution_notice
end
should 'not be set to open if OAuth validation fails' do
mr = @merge_request.clone
mr.oauth_token = "key"
mr.oauth_secret = "invalid_secret"
mr.oauth_consumer.valid_oauth_credentials=({:key => 'key', :secret => 'secret'})
assert !mr.open?
end
should 'require signoff when target repository requires it' do
mr = @merge_request.clone
assert mr.acceptance_of_terms_required?
end
should 'not require signoff when target repository does not require so' do
mr = MergeRequest.new(:source_repository => repositories(:johans), :target_repository => repositories(:johans2), :ending_commit => '00ffcc')
assert !mr.acceptance_of_terms_required?
end
should "it defaults to master for the source_branch" do
mr = MergeRequest.new
assert_equal "master", mr.source_branch
mr.source_branch = "foo"
assert_equal "foo", mr.source_branch
end
should "it defaults to master for the target_branch" do
mr = MergeRequest.new
assert_equal "master", mr.target_branch
mr.target_branch = "foo"
assert_equal "foo", mr.target_branch
end
should "has a source_name" do
@merge_request.source_branch = "foo"
assert_equal "#{@merge_request.source_repository.name}:foo", @merge_request.source_name
end
should "has a target_name" do
@merge_request.target_branch = "foo"
assert_equal "#{@merge_request.target_repository.name}:foo", @merge_request.target_name
end
should "have an empty set of target branches, if the target_repository is nil" do
@merge_request.target_repository = nil
assert_equal [], @merge_request.target_branches_for_selection
end
should "have a set of target branches" do
repo = repositories(:johans)
@merge_request.target_repository = repo
grit = Grit::Repo.new(grit_test_repo("dot_git"), :is_bare => true)
repo.stubs(:git).returns(grit)
assert_equal grit.heads, @merge_request.target_branches_for_selection
end
context "with specific starting and ending commits" do
setup do
@merge_request.ending_commit = '6823e6622e1da9751c87380ff01a1db1'
end
should "not blow up if there's no target repository" do
mr = MergeRequest.new
assert_nothing_raised do
assert_equal [], mr.commits_for_selection
end
end
should "suggest relevant commits to be merged" do
assert_equal(4, @merge_request.commits_for_selection.size)
end
should 'show a list of potential commits' do
assert_equal 3, @merge_request.potential_commits.size
end
should 'access its versions by version number' do
@merge_request.stubs(:calculate_merge_base).returns('ffac')
3.times{@merge_request.create_new_version}
assert_nil @merge_request.version_number(4)
assert_equal 3, @merge_request.version_number(3).version
end
should 'use the real commits if the target branch has been updated' do
@merge_request.stubs(:calculate_merge_base).returns('ff0')
@merge_request.create_new_version
@merge_request.expects(:commit_diff_from_tracking_repo).once
@merge_request.commits_to_be_merged
end
should 'return an empty list if the target branch has not been updated' do
@merge_request.versions.destroy_all
assert_equal 4, @merge_request.commits_for_selection.size
assert_equal 3, @merge_request.commits_to_be_merged.size
end
should 'know if the specified commit exists in the source repository' do
source_git = mock('Source repository Git repo')
source_git.expects(:commit).with('ff00ddca').returns(nil)
source_git.expects(:commit).with('ff00ddcb').returns(mock("Ending commit"))
@merge_request.source_repository.stubs(:git).returns(source_git)
@merge_request.ending_commit = 'ff00ddca'
assert !@merge_request.ending_commit_exists?
@merge_request.ending_commit = 'ff00ddcb'
assert @merge_request.ending_commit_exists?
end
end
context 'The state machine' do
setup {@merge_request = merge_requests(:moes_to_johans)}
should 'allow transition to other states as long as it is not rejected or merged' do
@merge_request.open!
assert @merge_request.can_transition_to?('close')
end
should 'not allow transition to other states when rejected' do
@merge_request.open!
@merge_request.close!
assert !@merge_request.can_transition_to?('open')
end
should 'optionally take a block when performing a transition' do
@merge_request.open!
@merge_request.expects(:foo=).once
status_changed = @merge_request.transition_to('close') do
@merge_request.foo = "Hello world"
end
assert status_changed
end
should 'allow admin users to re-open' do
@user = users(:johan)
@merge_request.open
@merge_request.close
assert @merge_request.closed?
assert @merge_request.can_be_reopened_by?(@user)
assert @merge_request.reopen_with_user(@user)
assert @merge_request.open?
end
should 'not allow non-admin users to re-open' do
@user = users(:moe)
@merge_request.open
@merge_request.close
assert @merge_request.closed?
assert !@merge_request.can_be_reopened_by?(@user)
assert !@merge_request.reopen_with_user(@user)
assert !@merge_request.open?
end
should 'return false from its transition_to method if the state change is disallowed' do
@merge_request.stubs(:can_transition_to?).returns(false)
status_changed = @merge_request.transition_to(MergeRequest::STATUS_OPEN)
assert !status_changed
end
should 'deliver a status update to the user who initiated it' do
assert_incremented_by(@merge_request.user.received_messages, :count, 1) do
@merge_request.deliver_status_update(users(:moe))
end
end
should 'nullify associated messages when deleted' do
@merge_request.deliver_status_update(users(:moe))
message = @merge_request.user.received_messages.last
@merge_request.destroy
message.reload
assert_nil message.notifiable
end
should_eventually 'provide a hash of labels and values for possible next states' do
@merge_request.status = MergeRequest::STATUS_VERIFYING
assert_equal({'Merged' => 'merge', 'Rejected' => 'reject'}, @merge_request.possible_next_states_hash)
@merge_request.status = MergeRequest::STATUS_OPEN
assert_equal({'Merged' => 'merge', 'Rejected' => 'reject', 'Verifying' => 'in_verification'}, @merge_request.possible_next_states_hash)
@merge_request.status = MergeRequest::STATUS_REJECTED
assert_equal({}, @merge_request.possible_next_states_hash)
@merge_request.status = MergeRequest::STATUS_PENDING_ACCEPTANCE_OF_TERMS
assert_equal({'Open' => 'open'}, @merge_request.possible_next_states_hash)
@merge_request.status = MergeRequest::STATUS_MERGED
assert_equal({}, @merge_request.possible_next_states_hash)
end
should_eventually 'have a pseudo-open status' do
[MergeRequest::STATUS_OPEN].each do |s|
@merge_request.status = s
# TODO: get rid of #open_or_in_verification?
assert @merge_request.open_or_in_verification?
end
end
end
context 'Compatibility with existing records' do
setup do
@source_repo = repositories(:johans2)
@target_repo = repositories(:johans)
@user = users(:johan)
@merge_request = MergeRequest.new({
:source_repository => @source_repo,
:target_repository => @target_repo,
:user => @user,
:summary => 'Please, mister postman',
:proposal => 'Please, mister postman'
})
@merge_request.sequence_number = @target_repo.next_merge_request_sequence_number
end
should 'require ending_commit for new records' do
assert !@merge_request.save
assert_not_nil @merge_request.errors.on(:ending_commit)
end
should 'not consider a missing ending_commit a show stopper on update' do
@merge_request.save(false)
@merge_request.proposal = 'Yikes'
assert @merge_request.save
end
end
context 'Last updated by' do
setup do
@merge_request = merge_requests(:moes_to_johans_open)
end
should 'initially be the user' do
assert_equal users(:johan), @merge_request.updated_by
end
should 'have a setter and getter' do
@merge_request.updated_by = users(:mike)
assert_equal users(:mike), @merge_request.updated_by
end
end
should 'have a recently_added? method' do
@merge_request.versions.destroy_all
@merge_request.created_at = 3.minutes.ago
assert !@merge_request.recently_created?
@merge_request.created_at = 1.minute.ago
assert @merge_request.recently_created?
end
context "from_filter" do
setup do
@repo = repositories(:johans)
merge_requests(:mikes_to_johans).destroy
merge_requests(:moes_to_johans).update_attribute(:status, MergeRequest::STATUS_OPEN)
MergeRequestStatus.create_defaults_for_project(@repo.project)
end
should "default to open merge-requests" do
merge_requests(:moes_to_johans).update_attribute(:status_tag, 'Closed')
merge_requests(:moes_to_johans_open).update_attribute(:status_tag, 'Open')
assert !@repo.merge_requests.from_filter(nil).include?(merge_requests(:moes_to_johans))
assert_equal [merge_requests(:moes_to_johans_open)], @repo.merge_requests.from_filter(nil)
end
should "fall back to using named_scope on other filter name" do
merge_requests(:moes_to_johans).update_attribute(:status_tag, 'kittens')
assert !@repo.merge_requests.from_filter("kittens").include?(merge_requests(:moes_to_johans_open))
assert_equal [merge_requests(:moes_to_johans)], @repo.merge_requests.from_filter("kittens")
end
should "find closed merge-requests" do
merge_requests(:moes_to_johans).update_attribute(:status_tag, 'Closed')
assert !@repo.merge_requests.from_filter("Closed").include?(merge_requests(:moes_to_johans_open))
assert_equal [merge_requests(:moes_to_johans)], @repo.merge_requests.from_filter("Closed")
end
end
context 'As XML' do
setup {@merge_request = merge_requests(:moes_to_johans_open)}
should 'not include confidential information' do
assert !@merge_request.to_xml.include?('#{@merge_request.status_tag}<\/status>/,
@merge_request.to_xml)
assert_match(/~#{@merge_request.user.title}<\/username>/,
@merge_request.to_xml)
assert_match(/#{@merge_request.proposal}<\/proposal>/,
@merge_request.to_xml)
assert_match(/#{@merge_request.summary}<\/summary>/,
@merge_request.to_xml)
end
end
context 'Pushing changes to the merge request repository' do
setup do
@merge_request = merge_requests(:moes_to_johans)
end
should 'send a push command from the source repository to the tracking repository' do
merge_request_repo = @merge_request.target_repository.create_tracking_repository
merge_request_repo_path = merge_request_repo.full_repository_path
branch_spec_base = "#{@merge_request.ending_commit}:refs/merge-requests"
branch_spec = [branch_spec_base, @merge_request.to_param].join('/')
tracking_branch_spec = [branch_spec_base, @merge_request.to_param, 1].join('/')
git = mock("Git")
git_backend = mock("Source repository git")
git.stubs(:git).returns(git_backend)
@merge_request.source_repository.stubs(:git).returns(git)
@merge_request.expects(:push_new_branch_to_tracking_repo).twice
git_backend.expects(:push).with({:timeout => false},
@merge_request.target_repository.full_repository_path, branch_spec).once
@merge_request.push_to_tracking_repository!
git_backend.expects(:push).with({:force => true,:timeout => false},
@merge_request.target_repository.full_repository_path, branch_spec).once
@merge_request.push_to_tracking_repository!(true)
end
context "Update events" do
setup do
git = mock("Git")
@git_backend = mock("tracking repository git")
git.stubs(:git).returns(@git_backend)
@merge_request.target_repository.stubs(:git).returns(git)
@git_backend.stubs(:merge_base).returns("abc")
end
should "not create a 'new version' event if it's the first version" do
@git_backend.expects(:push)
assert_no_difference("Event.count") do
@merge_request.push_new_branch_to_tracking_repo
end
end
should "create a 'new version' event unless it's the first version" do
@git_backend.expects(:push)
@merge_request.create_new_version
assert_difference("Event.count") do
@merge_request.push_new_branch_to_tracking_repo
end
assert_equal Action::UPDATE_MERGE_REQUEST, Event.last.action
end
end
end
context 'Status tags' do
setup do
@merge_request = merge_requests(:moes_to_johans_open)
MergeRequestStatus.create_defaults_for_project(
@merge_request.target_repository.project)
end
should 'cascade to the actual state machine with given states' do
@merge_request.status_tag = 'closed'
assert @merge_request.reload.closed?
@merge_request.status_tag = 'open'
assert @merge_request.reload.open?
end
should "set the internal statemachine accordingly" do
project = @merge_request.target_repository.project
project.merge_request_statuses.create!(:name => "In Progress",
:state => MergeRequest::STATUS_OPEN, :color => "#000")
project.merge_request_statuses.create!(:name => "All Done",
:state => MergeRequest::STATUS_CLOSED, :color => "#ccc")
@merge_request.status_tag = "In Progress"
assert @merge_request.reload.open?
@merge_request.status_tag = "All Done"
assert @merge_request.reload.closed?
end
should "set the status_tag to open when new merge requests are created" do
new_request = MergeRequest.new(:user => @merge_request.user,
:source_repository => @merge_request.source_repository,
:target_repository => @merge_request.target_repository,
:summary => "Add a user",
:proposal => "Please add me",
:ending_commit => "a"*10, :source_branch => "master", :target_branch => "master")
assert new_request.save!
assert new_request.status_tag.blank?
new_request.confirmed_by_user
assert_instance_of StatusTag, new_request.status_tag
assert_equal "Open", new_request.status_tag.name
end
should 'build an event with from and to when changing between states' do
@merge_request.with_user(users(:johan)) do
@merge_request.status_tag = 'before'
@merge_request.status_tag = 'after'
@merge_request.create_status_change_event("Foo")
event = @merge_request.events.reload.last
exp ="State changed from before " +
"to after"
assert_equal exp, event.data
end
end
should 'build an event with only the new state' do
@merge_request.write_attribute(:status_tag, nil)
@merge_request.with_user(users(:johan)) do
@merge_request.status_tag = "Closed"
@merge_request.create_status_change_event("Setting this to closed")
event = @merge_request.events.reload.last
assert_equal "State changed to Closed", event.data
end
end
should 'create an event with a given user if such is provided' do
@merge_request.status_tag = 'before'
@merge_request.with_user(users(:johan)) do
@merge_request.status_tag = 'after'
@merge_request.create_status_change_event "Updated this"
event = @merge_request.events.reload.last
assert_equal users(:johan), event.user
end
end
end
context 'Migration of reason/status to comment/status_tag' do
setup {@merge_request = merge_requests(:moes_to_johans_open)}
should 'simply set the status tag if no reason exists' do
@merge_request.migrate_to_status_tag
assert_equal 'Open', @merge_request.reload.status_tag.to_s
end
should 'add a comment and set the state when reason exists' do
@merge_request.reason = "You're right, this is a great idea!"
@merge_request.close
@merge_request.save
@merge_request.migrate_to_status_tag
assert_equal 'closed', @merge_request.reload.status_string
assert_not_nil comment = @merge_request.comments.reload.last
assert_equal @merge_request.updated_by, comment.user
end
end
context "Soft deletion of merge requests" do
setup do
@merge_request = merge_requests(:moes_to_johans_open)
end
should "send a message when being destroyed" do
deletion_proc = proc{ @merge_request.destroy }
msg = find_message_with_queue_and_regexp('/queue/GitoriousMergeRequestBackend', /.*/) {
deletion_proc.call
}
assert_nil MergeRequest.find_by_id(@merge_request.id)
assert_equal @merge_request.id.to_s, msg["merge_request_id"]
assert_equal "delete", msg["action"]
assert_equal @merge_request.target_repository.full_repository_path, msg["target_path"]
assert_equal @merge_request.target_repository.url_path, msg["target_name"]
assert_equal @merge_request.merge_branch_name, msg["merge_branch_name"]
assert_equal @merge_request.target_repository.id, msg["target_repository_id"]
assert_equal @merge_request.source_repository.id, msg["source_repository_id"]
end
end
context "Commenting" do
setup do
@merge_request = merge_requests(:johans_to_mikes)
@comments = ["Looks good", "On the other hand..."].map do |body|
@merge_request.comments.create!({
:project => @merge_request.target_repository.project,
:body => body,
:sha1 => "ffac",
:user => User.first
})
end
end
should 'include comments on versions' do
version_comment = comments(:first_merge_request_version_comment)
assert @merge_request.cascaded_comments.include?(version_comment)
end
should 'include comments on the merge request' do
assert @merge_request.cascaded_comments.include? @comments.first
end
end
context "Sequence numbers" do
setup {
@repository = repositories(:johans)
@merge_request = @repository.merge_requests.build(
:user => users(:moe),
:source_repository => repositories(:moes),
:summary => "Please merge",
:proposal => "New window decorations",
:sha_snapshot => "ffac",
:ending_commit => "ac00"
)
}
should "set the sequence number on create" do
next_sequence = @repository.next_merge_request_sequence_number
assert @merge_request.save
assert_equal next_sequence + 1, @repository.next_merge_request_sequence_number
assert_equal(next_sequence, @merge_request.sequence_number)
end
should "require a unique sequence number for each target repo" do
assert @merge_request.save
mr2 = @merge_request.clone
assert mr2.save
mr2.sequence_number = @merge_request.sequence_number
assert_equal mr2.sequence_number, @merge_request.sequence_number
assert !mr2.save
assert_equal mr2.sequence_number, @merge_request.sequence_number
assert_not_nil mr2.errors.on(:sequence_number)
end
should "use sequence_number in to_param" do
@merge_request.update_attribute(:sequence_number, @repository.next_merge_request_sequence_number)
assert_equal @merge_request.sequence_number.to_s, @merge_request.to_param
end
end
context "Reviewers" do
setup do
@source_repository = repositories(:johans)
@user = @source_repository.user
@target_repository = repositories(:moes)
@merge_request = @target_repository.merge_requests.build(
:source_repository => @source_repository,
:summary => "Please merge",
:sha_snapshot => "ffac",
:ending_commit => "caff",
:user => @user
)
end
should "be accessible from the merge request" do
assert_equal(@merge_request.target_repository.reviewers.uniq.reject{|r|r == @merge_request.user},
@merge_request.reviewers)
end
should "add a favorite for each reviewer" do
@merge_request.expects(:add_to_reviewers_favorites).times(@merge_request.reviewers.size)
@merge_request.notify_subscribers_about_creation
end
should "add self to reviewer's favorites" do
reviewer = users(:johan)
assert_incremented_by(reviewer.favorites, :size, 1) do
@merge_request.add_to_reviewers_favorites(reviewer)
end
end
should "be able to find its event" do
creation_event = @merge_request.add_creation_event(
@target_repository.project,@user)
assert_equal creation_event, @merge_request.creation_event
end
should "return nil when no creation event exists" do
assert_nil @merge_request.creation_event
end
should "create a feed item for each watcher" do
@merge_request.add_creation_event(@target_repository.project, @user)
assert_incremented_by(FeedItem, :count, @merge_request.reviewers.size) do
@merge_request.notify_subscribers_about_creation
end
end
should "be added to creators favorites" do
assert_incremented_by(@user.favorites, :size, 1) {
@merge_request.save
}
end
end
end