summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-10-11 18:06:15 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-10-11 18:06:15 +0000
commit0dfbcd8f8b1587a7e10eb79940a8dc13bd72c664 (patch)
tree769b7b5eaea4354498ca0b91945e4733895bba43 /spec
parentcd631619f465a0eee2fe714e720f6b6312dd3e56 (diff)
downloadgitlab-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.rb129
-rw-r--r--spec/javascripts/boards/board_card_spec.js14
-rw-r--r--spec/javascripts/boards/boards_store_spec.js132
-rw-r--r--spec/models/concerns/atomic_internal_id_spec.rb13
-rw-r--r--spec/services/git/process_ref_changes_service_spec.rb105
-rw-r--r--spec/services/issues/update_service_spec.rb4
-rw-r--r--spec/services/merge_requests/update_service_spec.rb4
-rw-r--r--spec/services/notes/update_service_spec.rb94
-rw-r--r--spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/updating_mentions_shared_examples.rb80
-rw-r--r--spec/workers/post_receive_spec.rb97
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