2015-04-30 23:16:19 -04:00
require 'spec_helper'
2015-12-09 05:55:49 -05:00
describe SystemNoteService , services : true do
2015-04-30 23:16:19 -04:00
let ( :project ) { create ( :project ) }
let ( :author ) { create ( :user ) }
let ( :noteable ) { create ( :issue , project : project ) }
shared_examples_for 'a system note' do
2015-05-10 23:52:46 -04:00
it 'is valid' do
expect ( subject ) . to be_valid
end
2015-04-30 23:16:19 -04:00
it 'sets the noteable model' do
expect ( subject . noteable ) . to eq noteable
end
it 'sets the project' do
expect ( subject . project ) . to eq project
end
it 'sets the author' do
expect ( subject . author ) . to eq author
end
it 'is a system note' do
expect ( subject ) . to be_system
end
end
2015-05-09 18:18:50 -04:00
describe '.add_commits' do
2015-05-10 23:52:46 -04:00
subject { described_class . add_commits ( noteable , project , author , new_commits , old_commits , oldrev ) }
2015-05-09 18:18:50 -04:00
let ( :noteable ) { create ( :merge_request , source_project : project ) }
let ( :new_commits ) { noteable . commits }
let ( :old_commits ) { [ ] }
let ( :oldrev ) { nil }
2015-04-30 23:16:19 -04:00
it_behaves_like 'a system note'
2015-05-09 18:18:50 -04:00
describe 'note body' do
let ( :note_lines ) { subject . note . split ( " \n " ) . reject ( & :blank? ) }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'without existing commits' do
it 'adds a message header' do
expect ( note_lines [ 0 ] ) . to eq " Added #{ new_commits . size } commits: "
end
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
it 'adds a message line for each commit' do
new_commits . each_with_index do | commit , i |
# Skip the header
expect ( note_lines [ i + 1 ] ) . to eq " * #{ commit . short_id } - #{ commit . title } "
end
end
2015-04-30 23:16:19 -04:00
end
2015-05-09 18:18:50 -04:00
describe 'summary line for existing commits' do
let ( :summary_line ) { note_lines [ 1 ] }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'with one existing commit' do
let ( :old_commits ) { [ noteable . commits . last ] }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
it 'includes the existing commit' do
expect ( summary_line ) . to eq " * #{ old_commits . first . short_id } - 1 commit from branch `feature` "
end
end
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'with multiple existing commits' do
let ( :old_commits ) { noteable . commits [ 3 .. - 1 ] }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'with oldrev' do
let ( :oldrev ) { noteable . commits [ 2 ] . id }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
it 'includes a commit range' do
expect ( summary_line ) . to start_with " * #{ Commit . truncate_sha ( oldrev ) } ... #{ old_commits . last . short_id } "
2015-04-30 23:16:19 -04:00
end
2015-05-09 18:18:50 -04:00
it 'includes a commit count' do
expect ( summary_line ) . to end_with " - 2 commits from branch `feature` "
2015-04-30 23:16:19 -04:00
end
end
2015-05-09 18:18:50 -04:00
context 'without oldrev' do
it 'includes a commit range' do
expect ( summary_line ) . to start_with " * #{ old_commits [ 0 ] . short_id } .. #{ old_commits [ - 1 ] . short_id } "
end
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
it 'includes a commit count' do
expect ( summary_line ) . to end_with " - 2 commits from branch `feature` "
2015-04-30 23:16:19 -04:00
end
end
2015-05-09 18:18:50 -04:00
context 'on a fork' do
before do
expect ( noteable ) . to receive ( :for_fork? ) . and_return ( true )
end
it 'includes the project namespace' do
expect ( summary_line ) . to end_with " ` #{ noteable . target_project_namespace } :feature` "
2015-04-30 23:16:19 -04:00
end
end
end
end
end
end
2015-05-09 18:18:50 -04:00
describe '.change_assignee' do
subject { described_class . change_assignee ( noteable , project , author , assignee ) }
2015-05-10 23:52:46 -04:00
let ( :assignee ) { create ( :user ) }
2015-05-09 18:18:50 -04:00
it_behaves_like 'a system note'
context 'when assignee added' do
it 'sets the note text' do
expect ( subject . note ) . to eq " Reassigned to @ #{ assignee . username } "
end
end
context 'when assignee removed' do
let ( :assignee ) { nil }
it 'sets the note text' do
expect ( subject . note ) . to eq 'Assignee removed'
end
end
end
describe '.change_label' do
2015-05-10 23:52:46 -04:00
subject { described_class . change_label ( noteable , project , author , added , removed ) }
2015-04-30 23:16:19 -04:00
let ( :labels ) { create_list ( :label , 2 ) }
let ( :added ) { [ ] }
let ( :removed ) { [ ] }
it_behaves_like 'a system note'
context 'with added labels' do
let ( :added ) { labels }
let ( :removed ) { [ ] }
it 'sets the note text' do
expect ( subject . note ) . to eq " Added ~ #{ labels [ 0 ] . id } ~ #{ labels [ 1 ] . id } labels "
end
end
context 'with removed labels' do
let ( :added ) { [ ] }
let ( :removed ) { labels }
it 'sets the note text' do
expect ( subject . note ) . to eq " Removed ~ #{ labels [ 0 ] . id } ~ #{ labels [ 1 ] . id } labels "
end
end
context 'with added and removed labels' do
let ( :added ) { [ labels [ 0 ] ] }
let ( :removed ) { [ labels [ 1 ] ] }
it 'sets the note text' do
expect ( subject . note ) . to eq " Added ~ #{ labels [ 0 ] . id } and removed ~ #{ labels [ 1 ] . id } labels "
end
end
end
2015-05-09 18:18:50 -04:00
describe '.change_milestone' do
subject { described_class . change_milestone ( noteable , project , author , milestone ) }
2015-04-30 23:16:19 -04:00
2015-05-10 23:52:46 -04:00
let ( :milestone ) { create ( :milestone , project : project ) }
2015-04-30 23:16:19 -04:00
it_behaves_like 'a system note'
context 'when milestone added' do
it 'sets the note text' do
2015-12-24 08:43:26 -05:00
expect ( subject . note ) . to eq " Milestone changed to #{ milestone . to_reference } "
2015-04-30 23:16:19 -04:00
end
end
context 'when milestone removed' do
let ( :milestone ) { nil }
it 'sets the note text' do
expect ( subject . note ) . to eq 'Milestone removed'
end
end
end
2015-05-09 18:18:50 -04:00
describe '.change_status' do
2015-05-10 23:52:46 -04:00
subject { described_class . change_status ( noteable , project , author , status , source ) }
2015-05-09 18:18:50 -04:00
let ( :status ) { 'new_status' }
let ( :source ) { nil }
2015-04-30 23:16:19 -04:00
it_behaves_like 'a system note'
2015-05-09 18:18:50 -04:00
context 'with a source' do
let ( :source ) { double ( 'commit' , gfm_reference : 'commit 123456' ) }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
it 'sets the note text' do
expect ( subject . note ) . to eq " Status changed to #{ status } by commit 123456 "
end
end
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'without a source' do
it 'sets the note text' do
expect ( subject . note ) . to eq " Status changed to #{ status } "
2015-04-30 23:16:19 -04:00
end
2015-05-09 18:18:50 -04:00
end
end
2015-04-30 23:16:19 -04:00
2015-11-18 05:17:41 -05:00
describe '.merge_when_build_succeeds' do
2016-06-03 10:22:26 -04:00
let ( :pipeline ) { build ( :ci_pipeline_without_jobs ) }
2016-04-26 07:52:18 -04:00
let ( :noteable ) do
create ( :merge_request , source_project : project , target_project : project )
end
2015-11-18 05:17:41 -05:00
2016-06-20 12:48:04 -04:00
subject { described_class . merge_when_build_succeeds ( noteable , project , author , noteable . diff_head_commit ) }
2015-11-18 05:17:41 -05:00
it_behaves_like 'a system note'
it " posts the Merge When Build Succeeds system note " do
2015-12-03 04:27:34 -05:00
expect ( subject . note ) . to match / Enabled an automatic merge when the build for ( \ w+ \/ \ w+@)?[0-9a-f]{40} succeeds /
2015-11-24 08:59:02 -05:00
end
end
describe '.cancel_merge_when_build_succeeds' do
2016-04-26 07:52:18 -04:00
let ( :noteable ) do
create ( :merge_request , source_project : project , target_project : project )
end
2015-11-24 08:59:02 -05:00
subject { described_class . cancel_merge_when_build_succeeds ( noteable , project , author ) }
2015-11-18 05:17:41 -05:00
2015-11-24 08:59:02 -05:00
it_behaves_like 'a system note'
it " posts the Merge When Build Succeeds system note " do
2015-12-07 03:59:04 -05:00
expect ( subject . note ) . to eq " Canceled the automatic merge "
2015-11-18 05:17:41 -05:00
end
end
2015-05-26 21:49:04 -04:00
describe '.change_title' do
subject { described_class . change_title ( noteable , project , author , 'Old title' ) }
context 'when noteable responds to `title`' do
it_behaves_like 'a system note'
it 'sets the note text' do
expect ( subject . note ) .
2016-04-06 15:37:09 -04:00
to eq " Changed title: **{-Old title-}** → **{+ #{ noteable . title } +}** "
2015-05-26 21:49:04 -04:00
end
end
end
2016-05-18 13:56:13 -04:00
describe '.change_issue_confidentiality' do
subject { described_class . change_issue_confidentiality ( noteable , project , author ) }
2016-04-20 18:41:11 -04:00
context 'when noteable responds to `confidential`' do
it_behaves_like 'a system note'
it 'sets the note text' do
2016-05-18 13:56:13 -04:00
expect ( subject . note ) . to eq 'Made the issue visible'
2016-04-20 18:41:11 -04:00
end
end
end
2015-05-28 21:00:37 -04:00
describe '.change_branch' do
2015-10-16 03:25:19 -04:00
subject { described_class . change_branch ( noteable , project , author , 'target' , old_branch , new_branch ) }
2015-05-28 21:00:37 -04:00
let ( :old_branch ) { 'old_branch' }
let ( :new_branch ) { 'new_branch' }
it_behaves_like 'a system note'
context 'when target branch name changed' do
it 'sets the note text' do
expect ( subject . note ) . to eq " Target branch changed from ` #{ old_branch } ` to ` #{ new_branch } ` "
end
end
end
2015-10-15 04:41:46 -04:00
describe '.change_branch_presence' do
2015-10-16 03:25:19 -04:00
subject { described_class . change_branch_presence ( noteable , project , author , :source , 'feature' , :delete ) }
2015-10-15 04:41:46 -04:00
it_behaves_like 'a system note'
context 'when source branch deleted' do
it 'sets the note text' do
2015-10-16 03:51:25 -04:00
expect ( subject . note ) . to eq " Deleted source branch `feature` "
2015-10-15 04:41:46 -04:00
end
end
end
2016-02-17 01:11:48 -05:00
describe '.new_issue_branch' do
subject { described_class . new_issue_branch ( noteable , project , author , " 1-mepmep " ) }
it_behaves_like 'a system note'
context 'when a branch is created from the new branch button' do
it 'sets the note text' do
2016-03-15 15:17:51 -04:00
expect ( subject . note ) . to match / \ AStarted branch [`1-mepmep`] /
2016-02-17 01:11:48 -05:00
end
end
end
2015-05-09 18:18:50 -04:00
describe '.cross_reference' do
subject { described_class . cross_reference ( noteable , mentioner , author ) }
2015-04-30 23:16:19 -04:00
2015-05-10 23:52:46 -04:00
let ( :mentioner ) { create ( :issue , project : project ) }
2015-05-09 18:18:50 -04:00
it_behaves_like 'a system note'
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'when cross-reference disallowed' do
before do
expect ( described_class ) . to receive ( :cross_reference_disallowed? ) . and_return ( true )
end
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
it 'returns nil' do
expect ( subject ) . to be_nil
end
end
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'when cross-reference allowed' do
before do
expect ( described_class ) . to receive ( :cross_reference_disallowed? ) . and_return ( false )
end
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
describe 'note_body' do
context 'cross-project' do
let ( :project2 ) { create ( :project ) }
let ( :mentioner ) { create ( :issue , project : project2 ) }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'from Commit' do
let ( :mentioner ) { project2 . repository . commit }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
it 'references the mentioning commit' do
2015-05-21 16:35:15 -04:00
expect ( subject . note ) . to eq " mentioned in commit #{ mentioner . to_reference ( project ) } "
2015-04-30 23:16:19 -04:00
end
end
2015-05-09 18:18:50 -04:00
context 'from non-Commit' do
it 'references the mentioning object' do
2015-05-21 16:35:15 -04:00
expect ( subject . note ) . to eq " mentioned in issue #{ mentioner . to_reference ( project ) } "
2015-04-30 23:16:19 -04:00
end
end
end
2015-05-10 23:52:46 -04:00
context 'within the same project' do
2015-05-09 18:18:50 -04:00
context 'from Commit' do
let ( :mentioner ) { project . repository . commit }
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
it 'references the mentioning commit' do
2015-05-21 16:35:15 -04:00
expect ( subject . note ) . to eq " mentioned in commit #{ mentioner . to_reference } "
2015-05-09 18:18:50 -04:00
end
end
2015-04-30 23:16:19 -04:00
2015-05-09 18:18:50 -04:00
context 'from non-Commit' do
it 'references the mentioning object' do
2015-05-21 16:35:15 -04:00
expect ( subject . note ) . to eq " mentioned in issue #{ mentioner . to_reference } "
2015-05-09 18:18:50 -04:00
end
end
end
2015-04-30 23:16:19 -04:00
end
end
end
describe '.cross_reference?' do
it 'is truthy when text begins with expected text' do
2015-05-21 16:35:15 -04:00
expect ( described_class . cross_reference? ( 'mentioned in something' ) ) . to be_truthy
2015-04-30 23:16:19 -04:00
end
it 'is falsey when text does not begin with expected text' do
expect ( described_class . cross_reference? ( 'this is a note' ) ) . to be_falsey
end
end
2015-05-10 23:51:49 -04:00
describe '.cross_reference_disallowed?' do
context 'when mentioner is not a MergeRequest' do
it 'is falsey' do
mentioner = noteable . dup
expect ( described_class . cross_reference_disallowed? ( noteable , mentioner ) ) .
to be_falsey
end
end
context 'when mentioner is a MergeRequest' do
let ( :mentioner ) { create ( :merge_request , :simple , source_project : project ) }
let ( :noteable ) { project . commit }
it 'is truthy when noteable is in commits' do
expect ( mentioner ) . to receive ( :commits ) . and_return ( [ noteable ] )
expect ( described_class . cross_reference_disallowed? ( noteable , mentioner ) ) .
to be_truthy
end
it 'is falsey when noteable is not in commits' do
expect ( mentioner ) . to receive ( :commits ) . and_return ( [ ] )
expect ( described_class . cross_reference_disallowed? ( noteable , mentioner ) ) .
to be_falsey
end
end
2015-06-14 11:41:11 -04:00
context 'when notable is an ExternalIssue' do
let ( :noteable ) { ExternalIssue . new ( 'EXT-1234' , project ) }
it 'is truthy' do
mentioner = noteable . dup
expect ( described_class . cross_reference_disallowed? ( noteable , mentioner ) ) .
to be_truthy
end
end
2015-05-10 23:51:49 -04:00
end
2015-04-30 23:16:19 -04:00
describe '.cross_reference_exists?' do
let ( :commit0 ) { project . commit }
let ( :commit1 ) { project . commit ( 'HEAD~2' ) }
context 'issue from commit' do
before do
# Mention issue (noteable) from commit0
described_class . cross_reference ( noteable , commit0 , author )
end
it 'is truthy when already mentioned' do
expect ( described_class . cross_reference_exists? ( noteable , commit0 ) ) .
to be_truthy
end
it 'is falsey when not already mentioned' do
expect ( described_class . cross_reference_exists? ( noteable , commit1 ) ) .
to be_falsey
end
end
context 'commit from commit' do
before do
# Mention commit1 from commit0
described_class . cross_reference ( commit0 , commit1 , author )
end
it 'is truthy when already mentioned' do
expect ( described_class . cross_reference_exists? ( commit0 , commit1 ) ) .
to be_truthy
end
it 'is falsey when not already mentioned' do
expect ( described_class . cross_reference_exists? ( commit1 , commit0 ) ) .
to be_falsey
end
end
2016-02-04 12:36:16 -05:00
2016-02-12 12:01:47 -05:00
context 'commit with cross-reference from fork' do
2016-02-04 12:36:16 -05:00
let ( :author2 ) { create ( :user ) }
let ( :forked_project ) { Projects :: ForkService . new ( project , author2 ) . execute }
let ( :commit2 ) { forked_project . commit }
before do
2016-02-12 12:01:47 -05:00
described_class . cross_reference ( noteable , commit0 , author2 )
2016-02-04 12:36:16 -05:00
end
2016-02-12 12:01:47 -05:00
it 'is true when a fork mentions an external issue' do
2016-02-05 11:43:05 -05:00
expect ( described_class . cross_reference_exists? ( noteable , commit2 ) ) .
2016-02-12 12:01:47 -05:00
to be true
2016-02-04 12:36:16 -05:00
end
end
2015-04-30 23:16:19 -04:00
end
2015-12-17 17:08:14 -05:00
2016-02-16 05:47:00 -05:00
describe '.noteable_moved' do
let ( :new_project ) { create ( :project ) }
let ( :new_noteable ) { create ( :issue , project : new_project ) }
2016-02-15 09:14:57 -05:00
subject do
2016-03-16 05:24:44 -04:00
described_class . noteable_moved ( noteable , project , new_noteable , author , direction : direction )
2016-02-15 09:14:57 -05:00
end
2016-02-16 05:47:00 -05:00
shared_examples 'cross project mentionable' do
include GitlabMarkdownHelper
2016-08-01 11:00:44 -04:00
it 'contains cross reference to new noteable' do
2016-02-16 05:47:00 -05:00
expect ( subject . note ) . to include cross_project_reference ( new_project , new_noteable )
end
2016-08-01 11:00:44 -04:00
it 'mentions referenced noteable' do
2016-02-16 05:47:00 -05:00
expect ( subject . note ) . to include new_noteable . to_reference
end
2016-08-01 11:00:44 -04:00
it 'mentions referenced project' do
2016-02-16 05:47:00 -05:00
expect ( subject . note ) . to include new_project . to_reference
end
end
context 'moved to' do
let ( :direction ) { :to }
it_behaves_like 'cross project mentionable'
2016-02-15 09:14:57 -05:00
2016-08-01 11:00:44 -04:00
it 'notifies about noteable being moved to' do
2016-02-16 05:47:00 -05:00
expect ( subject . note ) . to match / Moved to /
end
2016-02-15 09:14:57 -05:00
end
2016-02-16 05:47:00 -05:00
context 'moved from' do
let ( :direction ) { :from }
it_behaves_like 'cross project mentionable'
2016-08-01 11:00:44 -04:00
it 'notifies about noteable being moved from' do
2016-02-16 05:47:00 -05:00
expect ( subject . note ) . to match / Moved from /
end
2016-02-15 09:14:57 -05:00
end
2016-02-16 05:47:00 -05:00
context 'invalid direction' do
2016-02-17 09:59:25 -05:00
let ( :direction ) { :invalid }
2016-02-16 05:47:00 -05:00
2016-08-01 11:00:44 -04:00
it 'raises error' do
2016-02-16 05:47:00 -05:00
expect { subject } . to raise_error StandardError , / Invalid direction /
end
2016-02-15 09:14:57 -05:00
end
end
2016-05-07 11:41:10 -04:00
describe '.new_commit_summary' do
it 'escapes HTML titles' do
commit = double ( title : '<pre>This is a test</pre>' , short_id : '12345678' )
escaped = '* 12345678 - <pre>This is a test</pre>'
expect ( described_class . new_commit_summary ( [ commit ] ) ) . to eq ( [ escaped ] )
end
end
2015-12-17 17:08:14 -05:00
include JiraServiceHelper
describe 'JIRA integration' do
let ( :project ) { create ( :project ) }
let ( :author ) { create ( :user ) }
let ( :issue ) { create ( :issue , project : project ) }
let ( :mergereq ) { create ( :merge_request , :simple , target_project : project , source_project : project ) }
2016-06-14 16:43:31 -04:00
let ( :jira_issue ) { ExternalIssue . new ( " JIRA-1 " , project ) }
2015-12-17 17:08:14 -05:00
let ( :jira_tracker ) { project . create_jira_service if project . jira_service . nil? }
let ( :commit ) { project . commit }
context 'in JIRA issue tracker' do
before do
jira_service_settings
WebMock . stub_request ( :post , jira_api_comment_url )
end
after do
jira_tracker . destroy!
end
describe " new reference " do
before do
WebMock . stub_request ( :get , jira_api_comment_url ) . to_return ( body : jira_issue_comments )
end
subject { described_class . cross_reference ( jira_issue , commit , author ) }
it { is_expected . to eq ( jira_status_message ) }
end
describe " existing reference " do
before do
2016-03-02 13:12:16 -05:00
message = %Q{ [ #{ author . name } |http://localhost/u/ #{ author . username } ] mentioned this issue in [a commit of #{ project . path_with_namespace } |http://localhost/ #{ project . path_with_namespace } /commit/ #{ commit . id } ]: \\ n' #{ commit . title } ' }
WebMock . stub_request ( :get , jira_api_comment_url ) . to_return ( body : %Q( {"comments":[{"body":" #{ message } "}]} ) )
2015-12-17 17:08:14 -05:00
end
subject { described_class . cross_reference ( jira_issue , commit , author ) }
it { is_expected . not_to eq ( jira_status_message ) }
end
end
context 'issue from an issue' do
context 'in JIRA issue tracker' do
before do
jira_service_settings
WebMock . stub_request ( :post , jira_api_comment_url )
WebMock . stub_request ( :get , jira_api_comment_url ) . to_return ( body : jira_issue_comments )
end
after do
jira_tracker . destroy!
end
subject { described_class . cross_reference ( jira_issue , issue , author ) }
it { is_expected . to eq ( jira_status_message ) }
end
end
end
2015-04-30 23:16:19 -04:00
end