Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-12 21:12:15 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-12 21:12:15 +0300
commitda59ce8b217f67707b391d9fb3503dbdf8c4e511 (patch)
tree6839f806745e333f25ddb29317aead689cced15b /spec
parent3df6bfc24c8877b9442d567378b8ebd8816cd443 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/groups/group_links_controller_spec.rb9
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb8
-rw-r--r--spec/controllers/projects/group_links_controller_spec.rb9
-rw-r--r--spec/controllers/projects/merge_requests/drafts_controller_spec.rb2
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb8
-rw-r--r--spec/factories/clusters/applications/helm.rb75
-rw-r--r--spec/features/error_pages_spec.rb9
-rw-r--r--spec/features/projects/user_sees_user_popover_spec.rb2
-rw-r--r--spec/frontend/content_editor/markdown_processing_spec.js7
-rw-r--r--spec/frontend/content_editor/services/create_editor_spec.js39
-rw-r--r--spec/graphql/resolvers/repository_branch_names_resolver_spec.rb36
-rw-r--r--spec/graphql/types/repository_type_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb15
-rw-r--r--spec/migrations/move_container_registry_enabled_to_project_features2_spec.rb (renamed from spec/migrations/move_container_registry_enabled_to_project_features_spec.rb)8
-rw-r--r--spec/requests/api/notes_spec.rb2
-rw-r--r--spec/serializers/diff_file_entity_spec.rb8
-rw-r--r--spec/services/draft_notes/publish_service_spec.rb2
-rw-r--r--spec/services/merge_requests/handle_assignees_change_service_spec.rb114
-rw-r--r--spec/services/merge_requests/update_assignees_service_spec.rb29
-rw-r--r--spec/services/merge_requests/update_service_spec.rb77
-rw-r--r--spec/workers/merge_requests/assignees_change_worker_spec.rb12
-rw-r--r--spec/workers/merge_requests/handle_assignees_change_worker_spec.rb62
22 files changed, 361 insertions, 174 deletions
diff --git a/spec/controllers/groups/group_links_controller_spec.rb b/spec/controllers/groups/group_links_controller_spec.rb
index a2f7161ca41..94d3c1ffa0f 100644
--- a/spec/controllers/groups/group_links_controller_spec.rb
+++ b/spec/controllers/groups/group_links_controller_spec.rb
@@ -9,16 +9,17 @@ RSpec.describe Groups::GroupLinksController do
let(:group_member) { create(:user) }
let!(:project) { create(:project, group: shared_group) }
- around do |example|
- travel_to DateTime.new(2019, 4, 1) { example.run }
- end
-
before do
+ travel_to DateTime.new(2019, 4, 1)
sign_in(user)
shared_with_group.add_developer(group_member)
end
+ after do
+ travel_back
+ end
+
shared_examples 'placeholder is passed as `id` parameter' do |action|
it 'returns a 404' do
post(
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index aa9fd3759e5..19655687028 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -9,8 +9,12 @@ RSpec.describe Groups::GroupMembersController do
let(:group) { create(:group, :public) }
let(:membership) { create(:group_member, group: group) }
- around do |example|
- travel_to DateTime.new(2019, 4, 1) { example.run }
+ before do
+ travel_to DateTime.new(2019, 4, 1)
+ end
+
+ after do
+ travel_back
end
describe 'GET index' do
diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb
index 2fcdfbc2436..d514c486f60 100644
--- a/spec/controllers/projects/group_links_controller_spec.rb
+++ b/spec/controllers/projects/group_links_controller_spec.rb
@@ -8,15 +8,16 @@ RSpec.describe Projects::GroupLinksController do
let_it_be(:project) { create(:project, :private, group: group2) }
let_it_be(:user) { create(:user) }
- around do |example|
- travel_to DateTime.new(2019, 4, 1) { example.run }
- end
-
before do
+ travel_to DateTime.new(2019, 4, 1)
project.add_maintainer(user)
sign_in(user)
end
+ after do
+ travel_back
+ end
+
describe '#create' do
shared_context 'link project to group' do
before do
diff --git a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
index af39d4dec72..580211893dc 100644
--- a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
@@ -297,7 +297,7 @@ RSpec.describe Projects::MergeRequests::DraftsController do
expect { post :publish, params: params }.to change { Note.count }.by(0).and change { DraftNote.count }.by(0)
end
- it 'publishes a draft note with quick actions and applies them' do
+ it 'publishes a draft note with quick actions and applies them', :sidekiq_inline do
project.add_developer(user2)
create(:draft_note, merge_request: merge_request, author: user,
note: "/assign #{user2.to_reference}")
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index 53a7c2ca069..46a0fc8edb0 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -7,8 +7,12 @@ RSpec.describe Projects::ProjectMembersController do
let(:group) { create(:group, :public) }
let(:project) { create(:project, :public) }
- around do |example|
- travel_to DateTime.new(2019, 4, 1) { example.run }
+ before do
+ travel_to DateTime.new(2019, 4, 1)
+ end
+
+ after do
+ travel_back
end
describe 'GET index' do
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index db4eb961ecd..1ff1292c36e 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -4,18 +4,26 @@ FactoryBot.define do
factory :clusters_applications_helm, class: 'Clusters::Applications::Helm' do
cluster factory: %i(cluster provided_by_gcp)
- before(:create) do
- allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root)
- .and_return(
- double(
- key_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_key.key')),
- cert_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem'))
+ transient do
+ helm_installed { true }
+ end
+
+ before(:create) do |_record, evaluator|
+ if evaluator.helm_installed
+ allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root)
+ .and_return(
+ double(
+ key_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_key.key')),
+ cert_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem'))
+ )
)
- )
+ end
end
- after(:create) do
- allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root).and_call_original
+ after(:create) do |_record, evaluator|
+ if evaluator.helm_installed
+ allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root).and_call_original
+ end
end
trait :not_installable do
@@ -78,14 +86,19 @@ FactoryBot.define do
updated_at { ClusterWaitForAppInstallationWorker::TIMEOUT.ago }
end
+ # Common trait used by the apps below
+ trait :no_helm_installed do
+ cluster factory: %i(cluster provided_by_gcp)
+
+ transient do
+ helm_installed { false }
+ end
+ end
+
factory :clusters_applications_ingress, class: 'Clusters::Applications::Ingress' do
modsecurity_enabled { false }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
-
trait :modsecurity_blocking do
modsecurity_enabled { true }
modsecurity_mode { :blocking }
@@ -108,62 +121,34 @@ FactoryBot.define do
factory :clusters_applications_cert_manager, class: 'Clusters::Applications::CertManager' do
email { 'admin@example.com' }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_elastic_stack, class: 'Clusters::Applications::ElasticStack' do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_crossplane, class: 'Clusters::Applications::Crossplane' do
stack { 'gcp' }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_prometheus, class: 'Clusters::Applications::Prometheus' do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_runner, class: 'Clusters::Applications::Runner' do
runner factory: %i(ci_runner)
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_knative, class: 'Clusters::Applications::Knative' do
hostname { 'example.com' }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_jupyter, class: 'Clusters::Applications::Jupyter' do
oauth_application factory: :oauth_application
cluster factory: %i(cluster with_installed_helm provided_by_gcp project)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_fluentd, class: 'Clusters::Applications::Fluentd' do
@@ -171,18 +156,10 @@ FactoryBot.define do
waf_log_enabled { true }
cilium_log_enabled { true }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_cilium, class: 'Clusters::Applications::Cilium' do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
end
end
diff --git a/spec/features/error_pages_spec.rb b/spec/features/error_pages_spec.rb
index 77f8aa87237..8dc9e5ade46 100644
--- a/spec/features/error_pages_spec.rb
+++ b/spec/features/error_pages_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Error Pages' do
+RSpec.describe 'Error Pages', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
@@ -14,7 +14,12 @@ RSpec.describe 'Error Pages' do
it 'shows nav links' do
expect(page).to have_link("Home", href: root_path)
expect(page).to have_link("Help", href: help_path)
- expect(page).to have_link(nil, href: destroy_user_session_path)
+ end
+
+ it 'allows user to sign out' do
+ click_link 'Sign out and sign in with a different account'
+
+ expect(page).to have_current_path(new_user_session_path)
end
end
diff --git a/spec/features/projects/user_sees_user_popover_spec.rb b/spec/features/projects/user_sees_user_popover_spec.rb
index 52e65deae3b..e357824a533 100644
--- a/spec/features/projects/user_sees_user_popover_spec.rb
+++ b/spec/features/projects/user_sees_user_popover_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'User sees user popover', :js do
end
end
- it "displays user popover in system note" do
+ it 'displays user popover in system note', :sidekiq_inline do
add_note("/assign @#{user.username}")
find('.system-note-message .js-user-link').hover
diff --git a/spec/frontend/content_editor/markdown_processing_spec.js b/spec/frontend/content_editor/markdown_processing_spec.js
index 79ddfb8b125..e435af30e9f 100644
--- a/spec/frontend/content_editor/markdown_processing_spec.js
+++ b/spec/frontend/content_editor/markdown_processing_spec.js
@@ -1,13 +1,12 @@
-import createEditor from '~/content_editor/services/create_editor';
-import toMarkdown from '~/content_editor/services/to_markdown';
+import { createEditor } from '~/content_editor';
import { loadMarkdownApiExamples, loadMarkdownApiResult } from './markdown_processing_examples';
describe('markdown processing', () => {
// Ensure we generate same markdown that was provided to Markdown API.
it.each(loadMarkdownApiExamples())('correctly handles %s', async (testName, markdown) => {
const { html } = loadMarkdownApiResult(testName);
- const editor = await createEditor({ content: html });
+ const editor = await createEditor({ content: markdown, renderMarkdown: () => html });
- expect(toMarkdown(editor.state.doc)).toBe(markdown);
+ expect(editor.getSerializedContent()).toBe(markdown);
});
});
diff --git a/spec/frontend/content_editor/services/create_editor_spec.js b/spec/frontend/content_editor/services/create_editor_spec.js
new file mode 100644
index 00000000000..4cf63e608eb
--- /dev/null
+++ b/spec/frontend/content_editor/services/create_editor_spec.js
@@ -0,0 +1,39 @@
+import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '~/content_editor/constants';
+import createEditor from '~/content_editor/services/create_editor';
+import createMarkdownSerializer from '~/content_editor/services/markdown_serializer';
+
+jest.mock('~/content_editor/services/markdown_serializer');
+
+describe('content_editor/services/create_editor', () => {
+ const buildMockSerializer = () => ({
+ serialize: jest.fn(),
+ deserialize: jest.fn(),
+ });
+
+ describe('creating an editor', () => {
+ it('uses markdown serializer when a renderMarkdown function is provided', async () => {
+ const renderMarkdown = () => true;
+ const mockSerializer = buildMockSerializer();
+ createMarkdownSerializer.mockReturnValueOnce(mockSerializer);
+
+ await createEditor({ renderMarkdown });
+
+ expect(createMarkdownSerializer).toHaveBeenCalledWith({ render: renderMarkdown });
+ });
+
+ it('uses custom serializer when it is provided', async () => {
+ const mockSerializer = buildMockSerializer();
+ const serializedContent = '**bold**';
+
+ mockSerializer.serialize.mockReturnValueOnce(serializedContent);
+
+ const editor = await createEditor({ serializer: mockSerializer });
+
+ expect(editor.getSerializedContent()).toBe(serializedContent);
+ });
+
+ it('throws an error when neither a serializer or renderMarkdown fn are provided', async () => {
+ await expect(createEditor()).rejects.toThrow(PROVIDE_SERIALIZER_OR_RENDERER_ERROR);
+ });
+ });
+});
diff --git a/spec/graphql/resolvers/repository_branch_names_resolver_spec.rb b/spec/graphql/resolvers/repository_branch_names_resolver_spec.rb
new file mode 100644
index 00000000000..398dd7a2e2e
--- /dev/null
+++ b/spec/graphql/resolvers/repository_branch_names_resolver_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::RepositoryBranchNamesResolver do
+ include GraphqlHelpers
+
+ let(:project) { create(:project, :repository) }
+
+ describe '#resolve' do
+ subject(:resolve_branch_names) do
+ resolve(
+ described_class,
+ obj: project.repository,
+ args: { search_pattern: pattern },
+ ctx: { current_user: project.creator }
+ )
+ end
+
+ context 'with empty search pattern' do
+ let(:pattern) { '' }
+
+ it 'returns nil' do
+ expect(resolve_branch_names).to eq(nil)
+ end
+ end
+
+ context 'with a valid search pattern' do
+ let(:pattern) { 'mas*' }
+
+ it 'returns matching branches' do
+ expect(resolve_branch_names).to match_array(['master'])
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/repository_type_spec.rb b/spec/graphql/types/repository_type_spec.rb
index a3bb7e502f2..fa1e54dfcfa 100644
--- a/spec/graphql/types/repository_type_spec.rb
+++ b/spec/graphql/types/repository_type_spec.rb
@@ -14,4 +14,6 @@ RSpec.describe GitlabSchema.types['Repository'] do
specify { expect(described_class).to have_graphql_field(:exists, calls_gitaly?: true, complexity: 2) }
specify { expect(described_class).to have_graphql_field(:blobs) }
+
+ specify { expect(described_class).to have_graphql_field(:branch_names, calls_gitaly?: true, complexity: 170) }
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb
index 0fc46211044..3885cea2d1b 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb
@@ -23,21 +23,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Pipeline::Process do
perform
end
-
- context 'with async processing disabled' do
- before do
- stub_feature_flags(ci_async_initial_pipeline_processing: false)
- end
-
- it 'processes pipeline inline' do
- expect(::Ci::ProcessPipelineService)
- .to receive(:new)
- .with(pipeline)
- .and_call_original
-
- perform
- end
- end
end
describe '#break?' do
diff --git a/spec/migrations/move_container_registry_enabled_to_project_features_spec.rb b/spec/migrations/move_container_registry_enabled_to_project_features2_spec.rb
index c7b07f3ef37..11d43a36bc9 100644
--- a/spec/migrations/move_container_registry_enabled_to_project_features_spec.rb
+++ b/spec/migrations/move_container_registry_enabled_to_project_features2_spec.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210226120851_move_container_registry_enabled_to_project_features.rb')
+require Rails.root.join('db', 'post_migrate', '20210401131948_move_container_registry_enabled_to_project_features2.rb')
-RSpec.describe MoveContainerRegistryEnabledToProjectFeatures, :migration do
+RSpec.describe MoveContainerRegistryEnabledToProjectFeatures2, :migration do
let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
let!(:projects) do
@@ -30,6 +30,10 @@ RSpec.describe MoveContainerRegistryEnabledToProjectFeatures, :migration do
it 'schedules jobs for ranges of projects' do
migrate!
+ # Since track_jobs is true, each job should have an entry in the background_migration_jobs
+ # table.
+ expect(table(:background_migration_jobs).count).to eq(2)
+
expect(described_class::MIGRATION)
.to be_scheduled_delayed_migration(2.minutes, projects[0].id, projects[2].id)
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index baab72d106f..d4f8b841c96 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -251,7 +251,7 @@ RSpec.describe API::Notes do
expect { subject }.not_to change { Note.where(system: false).count }
end
- it 'does however create a system note about the change' do
+ it 'does however create a system note about the change', :sidekiq_inline do
expect { subject }.to change { Note.system.count }.by(1)
end
diff --git a/spec/serializers/diff_file_entity_spec.rb b/spec/serializers/diff_file_entity_spec.rb
index 1b8456e5c49..b8c5ccb9e7b 100644
--- a/spec/serializers/diff_file_entity_spec.rb
+++ b/spec/serializers/diff_file_entity_spec.rb
@@ -49,6 +49,14 @@ RSpec.describe DiffFileEntity do
expect(subject).to include(:load_collapsed_diff_url)
end
+
+ context 'when diff_view is unknown' do
+ let(:options) { { diff_view: :unknown } }
+
+ it 'hides highlighted_diff_lines and parallel_diff_lines' do
+ is_expected.not_to include(:highlighted_diff_lines, :parallel_diff_lines)
+ end
+ end
end
describe '#parallel_diff_lines' do
diff --git a/spec/services/draft_notes/publish_service_spec.rb b/spec/services/draft_notes/publish_service_spec.rb
index f83e91b683f..f93622dc25a 100644
--- a/spec/services/draft_notes/publish_service_spec.rb
+++ b/spec/services/draft_notes/publish_service_spec.rb
@@ -229,7 +229,7 @@ RSpec.describe DraftNotes::PublishService do
expect(DraftNote.count).to eq(2)
end
- context 'with quick actions' do
+ context 'with quick actions', :sidekiq_inline do
it 'performs quick actions' do
other_user = create(:user)
project.add_developer(other_user)
diff --git a/spec/services/merge_requests/handle_assignees_change_service_spec.rb b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
new file mode 100644
index 00000000000..cc595aab04b
--- /dev/null
+++ b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::HandleAssigneesChangeService do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request, author: user, source_project: project, assignees: [assignee]) }
+ let_it_be(:old_assignees) { create_list(:user, 3) }
+
+ let(:options) { {} }
+ let(:service) { described_class.new(project, user) }
+
+ before_all do
+ project.add_maintainer(user)
+ project.add_developer(assignee)
+
+ old_assignees.each do |old_assignee|
+ project.add_developer(old_assignee)
+ end
+ end
+
+ describe '#async_execute' do
+ def async_execute
+ service.async_execute(merge_request, old_assignees, options)
+ end
+
+ it 'performs MergeRequests::HandleAssigneesChangeWorker asynchronously' do
+ expect(MergeRequests::HandleAssigneesChangeWorker)
+ .to receive(:perform_async)
+ .with(
+ merge_request.id,
+ user.id,
+ old_assignees.map(&:id),
+ options
+ )
+
+ async_execute
+ end
+
+ context 'when async_handle_merge_request_assignees_change feature is disabled' do
+ before do
+ stub_feature_flags(async_handle_merge_request_assignees_change: false)
+ end
+
+ it 'calls #execute' do
+ expect(service).to receive(:execute).with(merge_request, old_assignees, options)
+
+ async_execute
+ end
+ end
+ end
+
+ describe '#execute' do
+ def execute
+ service.execute(merge_request, old_assignees, options)
+ end
+
+ it 'creates assignee note' do
+ execute
+
+ note = merge_request.notes.last
+
+ expect(note).not_to be_nil
+ expect(note.note).to include "assigned to #{assignee.to_reference} and unassigned #{old_assignees.map(&:to_reference).to_sentence}"
+ end
+
+ it 'sends email notifications to old and new assignees', :mailer, :sidekiq_inline do
+ perform_enqueued_jobs do
+ execute
+ end
+
+ should_email(assignee)
+ old_assignees.each do |old_assignee|
+ should_email(old_assignee)
+ end
+ end
+
+ it 'creates pending todo for assignee' do
+ execute
+
+ todo = assignee.todos.last
+
+ expect(todo).to be_pending
+ end
+
+ it 'tracks users assigned event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_users_assigned_to_mr).once.with(users: [assignee])
+
+ execute
+ end
+
+ it 'tracks assignees changed event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_assignees_changed_action).once.with(user: user)
+
+ execute
+ end
+
+ context 'when execute_hooks option is set to true' do
+ let(:options) { { execute_hooks: true } }
+
+ it 'execute hooks and services' do
+ expect(merge_request.project).to receive(:execute_hooks).with(anything, :merge_request_hooks)
+ expect(merge_request.project).to receive(:execute_services).with(anything, :merge_request_hooks)
+ expect(service).to receive(:enqueue_jira_connect_messages_for).with(merge_request)
+
+ execute
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/update_assignees_service_spec.rb b/spec/services/merge_requests/update_assignees_service_spec.rb
index aa6aad854a6..de03aab5418 100644
--- a/spec/services/merge_requests/update_assignees_service_spec.rb
+++ b/spec/services/merge_requests/update_assignees_service_spec.rb
@@ -37,9 +37,11 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
context 'when the parameters are valid' do
it 'updates the MR, and queues the more expensive work for later' do
- expect(MergeRequests::AssigneesChangeWorker)
- .to receive(:perform_async)
- .with(merge_request.id, user.id, [user3.id])
+ expect_next(MergeRequests::HandleAssigneesChangeService, project, user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user3], execute_hooks: true)
+ end
expect { update_merge_request }
.to change(merge_request, :assignees).to([user2])
@@ -54,9 +56,11 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
end
it 'is more efficient than using the full update-service' do
- allow(MergeRequests::AssigneesChangeWorker)
- .to receive(:perform_async)
- .with(merge_request.id, user.id, [user3.id])
+ allow_next(MergeRequests::HandleAssigneesChangeService, project, user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user3], execute_hooks: true)
+ end
other_mr = create(:merge_request, :simple, :unique_branches,
title: merge_request.title,
@@ -72,17 +76,4 @@ RSpec.describe MergeRequests::UpdateAssigneesService do
end
end
end
-
- describe '#handle_assignee_changes' do
- subject { service.handle_assignee_changes(merge_request, [user2]) }
-
- it 'calls UpdateService#handle_assignee_changes and executes hooks' do
- expect(service).to receive(:handle_assignees_change).with(merge_request, [user2])
- expect(merge_request.project).to receive(:execute_hooks).with(anything, :merge_request_hooks)
- expect(merge_request.project).to receive(:execute_services).with(anything, :merge_request_hooks)
- expect(service).to receive(:enqueue_jira_connect_messages_for).with(merge_request)
-
- subject
- end
- end
end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 579d274d910..24b7c3b933b 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -205,30 +205,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
end
- context 'assignees' do
- context 'when assignees changed' do
- it 'tracks assignees changed event' do
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
- .to receive(:track_assignees_changed_action).once.with(user: user)
-
- opts[:assignees] = [user2]
-
- MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
- end
- end
-
- context 'when assignees did not change' do
- it 'does not track assignees changed event' do
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
- .not_to receive(:track_assignees_changed_action)
-
- opts[:assignees] = merge_request.assignees
-
- MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
- end
- end
- end
-
context 'reviewers' do
context 'when reviewers changed' do
it 'tracks reviewers changed event' do
@@ -326,21 +302,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
)
end
- it 'sends email to user2 about assign of new merge request and email to user3 about merge request unassignment', :sidekiq_might_not_need_inline do
- deliveries = ActionMailer::Base.deliveries
- email = deliveries.last
- recipients = deliveries.last(2).flat_map(&:to)
- expect(recipients).to include(user2.email, user3.email)
- expect(email.subject).to include(merge_request.title)
- end
-
- it 'creates system note about merge_request reassign' do
- note = find_note('assigned to')
-
- expect(note).not_to be_nil
- expect(note.note).to include "assigned to #{user.to_reference} and unassigned #{user3.to_reference}"
- end
-
context 'with reviewers' do
let(:opts) { { reviewer_ids: [user2.id] } }
@@ -664,20 +625,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
it 'marks previous assignee pending todos as done' do
expect(pending_todo.reload).to be_done
end
-
- it 'creates a pending todo for new assignee' do
- attributes = {
- project: project,
- author: user,
- user: user2,
- target_id: merge_request.id,
- target_type: merge_request.class.name,
- action: Todo::ASSIGNED,
- state: :pending
- }
-
- expect(Todo.where(attributes).count).to eq 1
- end
end
context 'when reviewers gets changed' do
@@ -999,6 +946,8 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
it 'does not update assignee when assignee_id is invalid' do
merge_request.update!(assignee_ids: [user.id])
+ expect(MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
update_merge_request(assignee_ids: [-1])
expect(merge_request.reload.assignees).to eq([user])
@@ -1007,29 +956,35 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
it 'unassigns assignee when user id is 0' do
merge_request.update!(assignee_ids: [user.id])
+ expect_next_instance_of(MergeRequests::HandleAssigneesChangeService, project, user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user])
+ end
+
update_merge_request(assignee_ids: [0])
expect(merge_request.assignee_ids).to be_empty
end
it 'saves assignee when user id is valid' do
+ expect_next_instance_of(MergeRequests::HandleAssigneesChangeService, project, user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user3])
+ end
+
update_merge_request(assignee_ids: [user.id])
expect(merge_request.assignee_ids).to eq([user.id])
end
- it 'updates the tracking when user ids are valid' do
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
- .to receive(:track_users_assigned_to_mr)
- .with(users: [user])
-
- update_merge_request(assignee_ids: [user.id])
- end
-
it 'does not update assignee_id when user cannot read issue' do
non_member = create(:user)
original_assignees = merge_request.assignees
+ expect(MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
update_merge_request(assignee_ids: [non_member.id])
expect(merge_request.reload.assignees).to eq(original_assignees)
diff --git a/spec/workers/merge_requests/assignees_change_worker_spec.rb b/spec/workers/merge_requests/assignees_change_worker_spec.rb
index ccb0e5885ac..33478daf8d3 100644
--- a/spec/workers/merge_requests/assignees_change_worker_spec.rb
+++ b/spec/workers/merge_requests/assignees_change_worker_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe MergeRequests::AssigneesChangeWorker do
describe '#perform' do
context 'with a non-existing merge request' do
it 'does nothing' do
- expect(::MergeRequests::UpdateAssigneesService).not_to receive(:new)
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
worker.perform(non_existing_record_id, user.id, user_ids)
end
@@ -27,7 +27,7 @@ RSpec.describe MergeRequests::AssigneesChangeWorker do
context 'with a non-existing user' do
it 'does nothing' do
- expect(::MergeRequests::UpdateAssigneesService).not_to receive(:new)
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
worker.perform(merge_request.id, non_existing_record_id, user_ids)
end
@@ -35,7 +35,7 @@ RSpec.describe MergeRequests::AssigneesChangeWorker do
context 'when there are no changes' do
it 'does nothing' do
- expect(::MergeRequests::UpdateAssigneesService).not_to receive(:new)
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
worker.perform(merge_request.id, user.id, merge_request.assignee_ids)
end
@@ -43,15 +43,15 @@ RSpec.describe MergeRequests::AssigneesChangeWorker do
context 'when the old users cannot be found' do
it 'does nothing' do
- expect(::MergeRequests::UpdateAssigneesService).not_to receive(:new)
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
worker.perform(merge_request.id, user.id, [non_existing_record_id])
end
end
it 'gets MergeRequests::UpdateAssigneesService to handle the changes' do
- expect_next(::MergeRequests::UpdateAssigneesService)
- .to receive(:handle_assignee_changes).with(merge_request, match_array(old_assignees))
+ expect_next(::MergeRequests::HandleAssigneesChangeService)
+ .to receive(:execute).with(merge_request, match_array(old_assignees), execute_hooks: true)
worker.perform(merge_request.id, user.id, user_ids)
end
diff --git a/spec/workers/merge_requests/handle_assignees_change_worker_spec.rb b/spec/workers/merge_requests/handle_assignees_change_worker_spec.rb
new file mode 100644
index 00000000000..43f5196c92f
--- /dev/null
+++ b/spec/workers/merge_requests/handle_assignees_change_worker_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::HandleAssigneesChangeWorker do
+ include AfterNextHelpers
+
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:old_assignees) { create_list(:user, 3) }
+
+ let(:user_ids) { old_assignees.map(&:id).to_a }
+ let(:options) { {} }
+ let(:worker) { described_class.new }
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [merge_request.id, user.id, user_ids, options] }
+ end
+
+ describe '#perform' do
+ it 'calls MergeRequests::HandleAssigneesChangeService#execute to handle the changes' do
+ expect_next(::MergeRequests::HandleAssigneesChangeService)
+ .to receive(:execute).with(merge_request, old_assignees, options)
+
+ worker.perform(merge_request.id, user.id, user_ids, options)
+ end
+
+ context 'when there are no changes' do
+ it 'still calls MergeRequests::HandleAssigneesChangeService#execute' do
+ expect_next(::MergeRequests::HandleAssigneesChangeService)
+ .to receive(:execute).with(merge_request, [], options)
+
+ worker.perform(merge_request.id, user.id, merge_request.assignee_ids, options)
+ end
+ end
+
+ context 'when the old assignees cannot be found' do
+ it 'still calls MergeRequests::HandleAssigneesChangeService#execute' do
+ expect_next(::MergeRequests::HandleAssigneesChangeService)
+ .to receive(:execute).with(merge_request, [], options)
+
+ worker.perform(merge_request.id, user.id, [non_existing_record_id], options)
+ end
+ end
+
+ context 'with a non-existing merge request' do
+ it 'does nothing' do
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
+ worker.perform(non_existing_record_id, user.id, user_ids, options)
+ end
+ end
+
+ context 'with a non-existing user' do
+ it 'does nothing' do
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
+ worker.perform(merge_request.id, non_existing_record_id, user_ids, options)
+ end
+ end
+ end
+end