diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-11 18:06:15 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-11 18:06:15 +0000 |
commit | 0dfbcd8f8b1587a7e10eb79940a8dc13bd72c664 (patch) | |
tree | 769b7b5eaea4354498ca0b91945e4733895bba43 /spec | |
parent | cd631619f465a0eee2fe714e720f6b6312dd3e56 (diff) | |
download | gitlab-ce-0dfbcd8f8b1587a7e10eb79940a8dc13bd72c664.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/features/boards/multi_select_spec.rb | 129 | ||||
-rw-r--r-- | spec/javascripts/boards/board_card_spec.js | 14 | ||||
-rw-r--r-- | spec/javascripts/boards/boards_store_spec.js | 132 | ||||
-rw-r--r-- | spec/models/concerns/atomic_internal_id_spec.rb | 13 | ||||
-rw-r--r-- | spec/services/git/process_ref_changes_service_spec.rb | 105 | ||||
-rw-r--r-- | spec/services/issues/update_service_spec.rb | 4 | ||||
-rw-r--r-- | spec/services/merge_requests/update_service_spec.rb | 4 | ||||
-rw-r--r-- | spec/services/notes/update_service_spec.rb | 94 | ||||
-rw-r--r-- | spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb | 4 | ||||
-rw-r--r-- | spec/support/shared_examples/updating_mentions_shared_examples.rb | 80 | ||||
-rw-r--r-- | spec/workers/post_receive_spec.rb | 97 |
11 files changed, 289 insertions, 387 deletions
diff --git a/spec/features/boards/multi_select_spec.rb b/spec/features/boards/multi_select_spec.rb deleted file mode 100644 index ff3cb0271bd..00000000000 --- a/spec/features/boards/multi_select_spec.rb +++ /dev/null @@ -1,129 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe 'Multi Select Issue', :js do - include DragTo - - let(:group) { create(:group, :nested) } - let(:project) { create(:project, :public, namespace: group) } - let(:board) { create(:board, project: project) } - let(:user) { create(:user) } - - def drag(selector: '.board-list', list_from_index: 1, from_index: 0, to_index: 0, list_to_index: 1, duration: 1000) - drag_to(selector: selector, - scrollable: '#board-app', - list_from_index: list_from_index, - from_index: from_index, - to_index: to_index, - list_to_index: list_to_index, - duration: duration) - end - - def wait_for_board_cards(board_number, expected_cards) - page.within(find(".board:nth-child(#{board_number})")) do - expect(page.find('.board-header')).to have_content(expected_cards.to_s) - expect(page).to have_selector('.board-card', count: expected_cards) - end - end - - def multi_select(selector, action = 'select') - element = page.find(selector) - script = "var el = document.querySelector('#{selector}');" - script += "var mousedown = new MouseEvent('mousedown', { button: 0, bubbles: true });" - script += "var mouseup = new MouseEvent('mouseup', { ctrlKey: true, button: 0, bubbles:true });" - script += "el.dispatchEvent(mousedown); el.dispatchEvent(mouseup);" - script += "Sortable.utils.#{action}(el);" - - page.execute_script(script, element) - end - - before do - project.add_maintainer(user) - - sign_in(user) - end - - context 'with lists' do - let(:label1) { create(:label, project: project, name: 'Label 1', description: 'Test') } - let(:label2) { create(:label, project: project, name: 'Label 2', description: 'Test') } - let!(:list1) { create(:list, board: board, label: label1, position: 0) } - let!(:list2) { create(:list, board: board, label: label2, position: 1) } - let!(:issue1) { create(:labeled_issue, project: project, title: 'Issue 1', description: '', assignees: [user], labels: [label1], relative_position: 1) } - let!(:issue2) { create(:labeled_issue, project: project, title: 'Issue 2', description: '', author: user, labels: [label1], relative_position: 2) } - let!(:issue3) { create(:labeled_issue, project: project, title: 'Issue 3', description: '', labels: [label1], relative_position: 3) } - let!(:issue4) { create(:labeled_issue, project: project, title: 'Issue 4', description: '', labels: [label1], relative_position: 4) } - let!(:issue5) { create(:labeled_issue, project: project, title: 'Issue 5', description: '', labels: [label1], relative_position: 5) } - - before do - visit project_board_path(project, board) - - wait_for_requests - end - - it 'moves multiple issues to another list', :js do - multi_select('.board-card:nth-child(1)') - multi_select('.board-card:nth-child(2)') - drag(list_from_index: 1, list_to_index: 2) - - wait_for_requests - - page.within(all('.js-board-list')[2]) do - expect(find('.board-card:nth-child(1)')).to have_content(issue1.title) - expect(find('.board-card:nth-child(2)')).to have_content(issue2.title) - end - end - - it 'maintains order when moved', :js do - multi_select('.board-card:nth-child(3)') - multi_select('.board-card:nth-child(2)') - multi_select('.board-card:nth-child(1)') - - drag(list_from_index: 1, list_to_index: 2) - - wait_for_requests - - page.within(all('.js-board-list')[2]) do - expect(find('.board-card:nth-child(1)')).to have_content(issue1.title) - expect(find('.board-card:nth-child(2)')).to have_content(issue2.title) - expect(find('.board-card:nth-child(3)')).to have_content(issue3.title) - end - end - - it 'move issues in the same list', :js do - multi_select('.board-card:nth-child(3)') - multi_select('.board-card:nth-child(4)') - - drag(list_from_index: 1, list_to_index: 1, from_index: 2, to_index: 4) - - wait_for_requests - - page.within(all('.js-board-list')[1]) do - expect(find('.board-card:nth-child(1)')).to have_content(issue1.title) - expect(find('.board-card:nth-child(2)')).to have_content(issue2.title) - expect(find('.board-card:nth-child(3)')).to have_content(issue5.title) - expect(find('.board-card:nth-child(4)')).to have_content(issue3.title) - expect(find('.board-card:nth-child(5)')).to have_content(issue4.title) - end - end - - it 'adds label when issues are moved to different card', :js do - page.within(all('.js-board-list')[1]) do - expect(find('.board-card:nth-child(1)')).not_to have_content(label2.title) - expect(find('.board-card:nth-child(2)')).not_to have_content(label2.title) - end - - multi_select('.board-card:nth-child(1)') - multi_select('.board-card:nth-child(2)') - - drag(list_from_index: 1, list_to_index: 2) - - wait_for_requests - - page.within(all('.js-board-list')[2]) do - expect(find('.board-card:nth-child(1)')).to have_content(label2.title) - expect(find('.board-card:nth-child(2)')).to have_content(label2.title) - end - end - end -end diff --git a/spec/javascripts/boards/board_card_spec.js b/spec/javascripts/boards/board_card_spec.js index 9f441ca319e..13b708a03d5 100644 --- a/spec/javascripts/boards/board_card_spec.js +++ b/spec/javascripts/boards/board_card_spec.js @@ -67,16 +67,6 @@ describe('Board card', () => { expect(vm.issueDetailVisible).toBe(true); }); - it("returns false when multiSelect doesn't contain issue", () => { - expect(vm.multiSelectVisible).toBe(false); - }); - - it('returns true when multiSelect contains issue', () => { - boardsStore.multiSelect.list = [vm.issue]; - - expect(vm.multiSelectVisible).toBe(true); - }); - it('adds user-can-drag class if not disabled', () => { expect(vm.$el.classList.contains('user-can-drag')).toBe(true); }); @@ -190,7 +180,7 @@ describe('Board card', () => { triggerEvent('mousedown'); triggerEvent('mouseup'); - expect(eventHub.$emit).toHaveBeenCalledWith('newDetailIssue', vm.issue, undefined); + expect(eventHub.$emit).toHaveBeenCalledWith('newDetailIssue', vm.issue); expect(boardsStore.detail.list).toEqual(vm.list); }); @@ -213,7 +203,7 @@ describe('Board card', () => { triggerEvent('mousedown'); triggerEvent('mouseup'); - expect(eventHub.$emit).toHaveBeenCalledWith('clearDetailIssue', undefined); + expect(eventHub.$emit).toHaveBeenCalledWith('clearDetailIssue'); }); }); }); diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js index 678fe5befa8..11352140ba4 100644 --- a/spec/javascripts/boards/boards_store_spec.js +++ b/spec/javascripts/boards/boards_store_spec.js @@ -12,7 +12,6 @@ import '~/boards/services/board_service'; import boardsStore from '~/boards/stores/boards_store'; import eventHub from '~/boards/eventhub'; import { listObj, listObjDuplicate, boardsMockInterceptor, mockBoardService } from './mock_data'; -import waitForPromises from '../../frontend/helpers/wait_for_promises'; describe('Store', () => { let mock; @@ -30,13 +29,6 @@ describe('Store', () => { }), ); - spyOn(gl.boardService, 'moveMultipleIssues').and.callFake( - () => - new Promise(resolve => { - resolve(); - }), - ); - Cookies.set('issue_board_welcome_hidden', 'false', { expires: 365 * 10, path: '', @@ -384,128 +376,4 @@ describe('Store', () => { expect(state.currentBoard).toEqual(dummyBoard); }); }); - - describe('toggleMultiSelect', () => { - let basicIssueObj; - - beforeAll(() => { - basicIssueObj = { id: 987654 }; - }); - - afterEach(() => { - boardsStore.clearMultiSelect(); - }); - - it('adds issue when not present', () => { - boardsStore.toggleMultiSelect(basicIssueObj); - - const selectedIds = boardsStore.multiSelect.list.map(x => x.id); - - expect(selectedIds.includes(basicIssueObj.id)).toEqual(true); - }); - - it('removes issue when issue is present', () => { - boardsStore.toggleMultiSelect(basicIssueObj); - let selectedIds = boardsStore.multiSelect.list.map(x => x.id); - - expect(selectedIds.includes(basicIssueObj.id)).toEqual(true); - - boardsStore.toggleMultiSelect(basicIssueObj); - selectedIds = boardsStore.multiSelect.list.map(x => x.id); - - expect(selectedIds.includes(basicIssueObj.id)).toEqual(false); - }); - }); - - describe('clearMultiSelect', () => { - it('clears all the multi selected issues', () => { - const issue1 = { id: 12345 }; - const issue2 = { id: 12346 }; - - boardsStore.toggleMultiSelect(issue1); - boardsStore.toggleMultiSelect(issue2); - - expect(boardsStore.multiSelect.list.length).toEqual(2); - - boardsStore.clearMultiSelect(); - - expect(boardsStore.multiSelect.list.length).toEqual(0); - }); - }); - - describe('moveMultipleIssuesToList', () => { - it('move issues on the new index', done => { - const listOne = boardsStore.addList(listObj); - const listTwo = boardsStore.addList(listObjDuplicate); - - expect(boardsStore.state.lists.length).toBe(2); - - setTimeout(() => { - expect(listOne.issues.length).toBe(1); - expect(listTwo.issues.length).toBe(1); - - boardsStore.moveMultipleIssuesToList({ - listFrom: listOne, - listTo: listTwo, - issues: listOne.issues, - newIndex: 0, - }); - - expect(listTwo.issues.length).toBe(1); - - done(); - }, 0); - }); - }); - - describe('moveMultipleIssuesInList', () => { - it('moves multiple issues in list', done => { - const issueObj = { - title: 'Issue #1', - id: 12345, - iid: 2, - confidential: false, - labels: [], - assignees: [], - }; - const issue1 = new ListIssue(issueObj); - const issue2 = new ListIssue({ - ...issueObj, - title: 'Issue #2', - id: 12346, - }); - - const list = boardsStore.addList(listObj); - - waitForPromises() - .then(() => { - list.addIssue(issue1); - list.addIssue(issue2); - - expect(list.issues.length).toBe(3); - expect(list.issues[0].id).not.toBe(issue2.id); - - boardsStore.moveMultipleIssuesInList({ - list, - issues: [issue1, issue2], - oldIndicies: [0], - newIndex: 1, - idArray: [1, 12345, 12346], - }); - - expect(list.issues[0].id).toBe(issue1.id); - - expect(gl.boardService.moveMultipleIssues).toHaveBeenCalledWith({ - ids: [issue1.id, issue2.id], - fromListId: null, - toListId: null, - moveBeforeId: 1, - moveAfterId: null, - }); - - done(); - }) - .catch(done.fail); - }); - }); }); diff --git a/spec/models/concerns/atomic_internal_id_spec.rb b/spec/models/concerns/atomic_internal_id_spec.rb index f9ca9660bdb..80f296d8825 100644 --- a/spec/models/concerns/atomic_internal_id_spec.rb +++ b/spec/models/concerns/atomic_internal_id_spec.rb @@ -22,7 +22,7 @@ describe AtomicInternalId do end context 'when value is set by ensure_project_iid!' do - context 'with iid_always_track true' do + context 'with iid_always_track false' do before do stub_feature_flags(iid_always_track: false) end @@ -33,6 +33,17 @@ describe AtomicInternalId do milestone.ensure_project_iid! subject end + + it 'tracks the iid for the scope that is actually present' do + milestone.iid = external_iid + + expect(InternalId).to receive(:track_greatest).once.with(milestone, scope_attrs, usage, external_iid, anything) + expect(InternalId).not_to receive(:generate_next) + + # group scope is not present here, the milestone does not have a group + milestone.track_group_iid! + subject + end end context 'with iid_always_track enabled' do diff --git a/spec/services/git/process_ref_changes_service_spec.rb b/spec/services/git/process_ref_changes_service_spec.rb new file mode 100644 index 00000000000..4d394a29867 --- /dev/null +++ b/spec/services/git/process_ref_changes_service_spec.rb @@ -0,0 +1,105 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Git::ProcessRefChangesService do + let(:project) { create(:project, :repository) } + let(:user) { project.owner } + let(:params) { { changes: git_changes } } + + subject { described_class.new(project, user, params) } + + shared_examples_for 'service for processing ref changes' do |push_service_class| + let(:service) { double(execute: true) } + let(:git_changes) { double(branch_changes: [], tag_changes: []) } + + let(:changes) do + [ + { index: 0, oldrev: Gitlab::Git::BLANK_SHA, newrev: '789012', ref: "#{ref_prefix}/create" }, + { index: 1, oldrev: '123456', newrev: '789012', ref: "#{ref_prefix}/update" }, + { index: 2, oldrev: '123456', newrev: Gitlab::Git::BLANK_SHA, ref: "#{ref_prefix}/delete" } + ] + end + + before do + allow(git_changes).to receive(changes_method).and_return(changes) + end + + it "calls #{push_service_class}" do + expect(push_service_class) + .to receive(:new) + .exactly(changes.count).times + .and_return(service) + + subject.execute + end + + context 'pipeline creation' do + context 'with valid .gitlab-ci.yml' do + before do + stub_ci_pipeline_to_return_yaml_file + + allow_any_instance_of(Project) + .to receive(:commit) + .and_return(project.commit) + + allow_any_instance_of(Repository) + .to receive(:branch_exists?) + .and_return(true) + end + + context 'when git_push_create_all_pipelines is disabled' do + before do + stub_feature_flags(git_push_create_all_pipelines: false) + end + + it 'creates pipeline for branches and tags' do + subject.execute + + expect(Ci::Pipeline.pluck(:ref)).to contain_exactly('create', 'update', 'delete') + end + + it "creates exactly #{described_class::PIPELINE_PROCESS_LIMIT} pipelines" do + stub_const("#{described_class}::PIPELINE_PROCESS_LIMIT", changes.count - 1) + + expect { subject.execute }.to change { Ci::Pipeline.count }.by(described_class::PIPELINE_PROCESS_LIMIT) + end + end + + context 'when git_push_create_all_pipelines is enabled' do + before do + stub_feature_flags(git_push_create_all_pipelines: true) + end + + it 'creates all pipelines' do + expect { subject.execute }.to change { Ci::Pipeline.count }.by(changes.count) + end + end + end + + context 'with invalid .gitlab-ci.yml' do + before do + stub_ci_pipeline_yaml_file(nil) + end + + it 'does not create a pipeline' do + expect { subject.execute }.not_to change { Ci::Pipeline.count } + end + end + end + end + + context 'branch changes' do + let(:changes_method) { :branch_changes } + let(:ref_prefix) { 'refs/heads' } + + it_behaves_like 'service for processing ref changes', Git::BranchPushService + end + + context 'tag changes' do + let(:changes_method) { :tag_changes } + let(:ref_prefix) { 'refs/tags' } + + it_behaves_like 'service for processing ref changes', Git::TagPushService + end +end diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 55254b61ac8..154bfec0da2 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -6,7 +6,8 @@ describe Issues::UpdateService, :mailer do let(:user) { create(:user) } let(:user2) { create(:user) } let(:user3) { create(:user) } - let(:project) { create(:project) } + let(:group) { create(:group, :public) } + let(:project) { create(:project, :repository, group: group) } let(:label) { create(:label, project: project) } let(:label2) { create(:label) } @@ -667,6 +668,7 @@ describe Issues::UpdateService, :mailer do context 'updating mentions' do let(:mentionable) { issue } + include_examples 'updating mentions', described_class end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 9688e02d6ac..d3c4c436901 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -5,7 +5,8 @@ require 'spec_helper' describe MergeRequests::UpdateService, :mailer do include ProjectForksHelper - let(:project) { create(:project, :repository) } + let(:group) { create(:group, :public) } + let(:project) { create(:project, :repository, group: group) } let(:user) { create(:user) } let(:user2) { create(:user) } let(:user3) { create(:user) } @@ -472,6 +473,7 @@ describe MergeRequests::UpdateService, :mailer do context 'updating mentions' do let(:mentionable) { merge_request } + include_examples 'updating mentions', described_class end diff --git a/spec/services/notes/update_service_spec.rb b/spec/services/notes/update_service_spec.rb index 717eb97fa5a..73fcdd787aa 100644 --- a/spec/services/notes/update_service_spec.rb +++ b/spec/services/notes/update_service_spec.rb @@ -3,17 +3,25 @@ require 'spec_helper' describe Notes::UpdateService do - let(:project) { create(:project) } + let(:group) { create(:group, :public) } + let(:project) { create(:project, :public, group: group) } + let(:private_group) { create(:group, :private) } + let(:private_project) { create(:project, :private, group: private_group) } let(:user) { create(:user) } let(:user2) { create(:user) } let(:user3) { create(:user) } let(:issue) { create(:issue, project: project) } + let(:issue2) { create(:issue, project: private_project) } let(:note) { create(:note, project: project, noteable: issue, author: user, note: "Old note #{user2.to_reference}") } before do project.add_maintainer(user) project.add_developer(user2) project.add_developer(user3) + group.add_developer(user3) + private_group.add_developer(user) + private_group.add_developer(user2) + private_project.add_developer(user3) end describe '#execute' do @@ -46,13 +54,17 @@ describe Notes::UpdateService do end context 'todos' do - let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) } + shared_examples 'does not update todos' do + it 'keep todos' do + expect(todo.reload).to be_pending + end - context 'when the note change' do - before do - update_note({ note: "New note #{user2.to_reference} #{user3.to_reference}" }) + it 'does not create any new todos' do + expect(Todo.count).to eq(1) end + end + shared_examples 'creates one todo' do it 'marks todos as done' do expect(todo.reload).to be_done end @@ -62,17 +74,75 @@ describe Notes::UpdateService do end end - context 'when the note does not change' do - before do - update_note({ note: "Old note #{user2.to_reference}" }) + context 'when note includes a user mention' do + let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) } + + context 'when the note does not change mentions' do + before do + update_note({ note: "Old note #{user2.to_reference}" }) + end + + it_behaves_like 'does not update todos' end - it 'keep todos' do - expect(todo.reload).to be_pending + context 'when the note changes to include one more user mention' do + before do + update_note({ note: "New note #{user2.to_reference} #{user3.to_reference}" }) + end + + it_behaves_like 'creates one todo' end - it 'does not create any new todos' do - expect(Todo.count).to eq(1) + context 'when the note changes to include a group mentions' do + before do + update_note({ note: "New note #{private_group.to_reference}" }) + end + + it_behaves_like 'creates one todo' + end + end + + context 'when note includes a group mention' do + context 'when the group is public' do + let(:note) { create(:note, project: project, noteable: issue, author: user, note: "Old note #{group.to_reference}") } + let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) } + + context 'when the note does not change mentions' do + before do + update_note({ note: "Old note #{group.to_reference}" }) + end + + it_behaves_like 'does not update todos' + end + + context 'when the note changes mentions' do + before do + update_note({ note: "New note #{user2.to_reference} #{user3.to_reference}" }) + end + + it_behaves_like 'creates one todo' + end + end + + context 'when the group is private' do + let(:note) { create(:note, project: project, noteable: issue, author: user, note: "Old note #{private_group.to_reference}") } + let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) } + + context 'when the note does not change mentions' do + before do + update_note({ note: "Old note #{private_group.to_reference}" }) + end + + it_behaves_like 'does not update todos' + end + + context 'when the note changes mentions' do + before do + update_note({ note: "New note #{user2.to_reference} #{user3.to_reference}" }) + end + + it_behaves_like 'creates one todo' + end end end end diff --git a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb index b837ca87256..44f66ff47f4 100644 --- a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb +++ b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb @@ -47,6 +47,10 @@ shared_examples_for 'AtomicInternalId' do |validate_presence: true| end describe 'internal id generation' do + before do + stub_feature_flags(iid_always_track: false) + end + subject { instance.save! } it 'calls InternalId.generate_next and sets internal id attribute' do diff --git a/spec/support/shared_examples/updating_mentions_shared_examples.rb b/spec/support/shared_examples/updating_mentions_shared_examples.rb index ef385f94cc2..9a8f8012762 100644 --- a/spec/support/shared_examples/updating_mentions_shared_examples.rb +++ b/spec/support/shared_examples/updating_mentions_shared_examples.rb @@ -1,11 +1,16 @@ # frozen_string_literal: true RSpec.shared_examples 'updating mentions' do |service_class| - let(:mentioned_user) { create(:user) } - let(:service_class) { service_class } + let(:service_class) { service_class } + let(:mentioned_user) { create(:user) } + let(:group_member1) { create(:user) } + let(:group_member2) { create(:user) } + let(:external_group) { create(:group, :private) } before do project.add_developer(mentioned_user) + group.add_developer(group_member1) + group.add_developer(group_member2) end def update_mentionable(opts) @@ -16,23 +21,74 @@ RSpec.shared_examples 'updating mentions' do |service_class| mentionable.reload end - context 'in title' do - before do - update_mentionable(title: mentioned_user.to_reference) + context 'when mentioning a different user' do + context 'in title' do + before do + update_mentionable(title: "For #{mentioned_user.to_reference}") + end + + it 'emails only the newly-mentioned user' do + should_only_email(mentioned_user) + end + end + + context 'in description' do + before do + update_mentionable(description: "For #{mentioned_user.to_reference}") + end + + it 'emails only the newly-mentioned user' do + should_only_email(mentioned_user) + end + end + end + + context 'when mentioning a user and a group with access to' do + shared_examples 'updating attribute with allowed mentions' do |attribute| + before do + update_mentionable( + { attribute => "For #{group.to_reference}, cc: #{mentioned_user.to_reference}" } + ) + end + + it 'emails group members' do + should_email(mentioned_user) + should_email(group_member1) + should_email(group_member2) + end + end + + context 'when group is public' do + it_behaves_like 'updating attribute with allowed mentions', :title + it_behaves_like 'updating attribute with allowed mentions', :description end - it 'emails only the newly-mentioned user' do - should_only_email(mentioned_user) + context 'when the group is private' do + before do + group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) + end + + it_behaves_like 'updating attribute with allowed mentions', :title + it_behaves_like 'updating attribute with allowed mentions', :description end end - context 'in description' do - before do - update_mentionable(description: mentioned_user.to_reference) + context 'when mentioning a user and a group without access to' do + shared_examples 'updating attribute with not allowed mentions' do |attribute| + before do + update_mentionable( + { attribute => "For #{external_group.to_reference}, cc: #{mentioned_user.to_reference}" } + ) + end + + it 'emails mentioned user' do + should_only_email(mentioned_user) + end end - it 'emails only the newly-mentioned user' do - should_only_email(mentioned_user) + context 'when the group is private' do + it_behaves_like 'updating attribute with not allowed mentions', :title + it_behaves_like 'updating attribute with not allowed mentions', :description end end end diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index d034e962cee..6983fea021c 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -73,8 +73,7 @@ describe PostReceive do context 'empty changes' do it "does not call any PushService but runs after project hooks" do - expect(Git::BranchPushService).not_to receive(:new) - expect(Git::TagPushService).not_to receive(:new) + expect(Git::ProcessRefChangesService).not_to receive(:new) expect_next_instance_of(SystemHooksService) { |service| expect(service).to receive(:execute_hooks) } perform(changes: "") @@ -87,8 +86,7 @@ describe PostReceive do let!(:key_id) { "" } it 'returns false' do - expect(Git::BranchPushService).not_to receive(:new) - expect(Git::TagPushService).not_to receive(:new) + expect(Git::ProcessRefChangesService).not_to receive(:new) expect(perform).to be false end @@ -131,13 +129,11 @@ describe PostReceive do perform end - it 'calls Git::BranchPushService' do - expect_any_instance_of(Git::BranchPushService) do |service| + it 'calls Git::ProcessRefChangesService' do + expect_next_instance_of(Git::ProcessRefChangesService) do |service| expect(service).to receive(:execute).and_return(true) end - expect(Git::TagPushService).not_to receive(:new) - perform end @@ -174,8 +170,6 @@ describe PostReceive do 654321 210987 refs/tags/tag1 654322 210986 refs/tags/tag2 654323 210985 refs/tags/tag3 - 654324 210984 refs/tags/tag4 - 654325 210983 refs/tags/tag5 EOF end @@ -189,23 +183,19 @@ describe PostReceive do perform end - it "only invalidates tags once" do - expect(project.repository).to receive(:repository_event).exactly(5).times.with(:push_tag).and_call_original + it 'only invalidates tags once' do + expect(project.repository).to receive(:repository_event).exactly(3).times.with(:push_tag).and_call_original expect(project.repository).to receive(:expire_caches_for_tags).once.and_call_original expect(project.repository).to receive(:expire_tags_cache).once.and_call_original perform end - it "calls Git::TagPushService" do - expect(Git::BranchPushService).not_to receive(:new) - - expect_any_instance_of(Git::TagPushService) do |service| + it 'calls Git::ProcessRefChangesService' do + expect_next_instance_of(Git::ProcessRefChangesService) do |service| expect(service).to receive(:execute).and_return(true) end - expect(Git::BranchPushService).not_to receive(:new) - perform end @@ -223,8 +213,7 @@ describe PostReceive do let(:changes) { "123456 789012 refs/merge-requests/123" } it "does not call any of the services" do - expect(Git::BranchPushService).not_to receive(:new) - expect(Git::TagPushService).not_to receive(:new) + expect(Git::ProcessRefChangesService).not_to receive(:new) perform end @@ -232,72 +221,6 @@ describe PostReceive do it_behaves_like 'not updating remote mirrors' end - context "gitlab-ci.yml" do - let(:changes) do - <<-EOF.strip_heredoc - 123456 789012 refs/heads/feature - 654321 210987 refs/tags/tag - 123456 789012 refs/heads/feature2 - 123458 789013 refs/heads/feature3 - 123459 789015 refs/heads/feature4 - EOF - end - - let(:changes_count) { changes.lines.count } - - subject { perform } - - context "with valid .gitlab-ci.yml" do - before do - stub_ci_pipeline_to_return_yaml_file - - allow_any_instance_of(Project) - .to receive(:commit) - .and_return(project.commit) - - allow_any_instance_of(Repository) - .to receive(:branch_exists?) - .and_return(true) - end - - context 'when git_push_create_all_pipelines is disabled' do - before do - stub_feature_flags(git_push_create_all_pipelines: false) - end - - it "creates pipeline for branches and tags" do - subject - - expect(Ci::Pipeline.pluck(:ref)).to contain_exactly("feature", "tag", "feature2", "feature3") - end - - it "creates exactly #{described_class::PIPELINE_PROCESS_LIMIT} pipelines" do - expect(changes_count).to be > described_class::PIPELINE_PROCESS_LIMIT - - expect { subject }.to change { Ci::Pipeline.count }.by(described_class::PIPELINE_PROCESS_LIMIT) - end - end - - context 'when git_push_create_all_pipelines is enabled' do - before do - stub_feature_flags(git_push_create_all_pipelines: true) - end - - it "creates all pipelines" do - expect { subject }.to change { Ci::Pipeline.count }.by(changes_count) - end - end - end - - context "does not create a Ci::Pipeline" do - before do - stub_ci_pipeline_yaml_file(nil) - end - - it { expect { subject }.not_to change { Ci::Pipeline.count } } - end - end - context 'after project changes hooks' do let(:changes) { '123456 789012 refs/heads/tést' } let(:fake_hook_data) { Hash.new(event_name: 'repository_update') } @@ -306,7 +229,7 @@ describe PostReceive do allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data) # silence hooks so we can isolate allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true) - expect_next_instance_of(Git::BranchPushService) do |service| + expect_next_instance_of(Git::ProcessRefChangesService) do |service| expect(service).to receive(:execute).and_return(true) end end |