diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-24 18:14:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-24 18:14:19 +0300 |
commit | b8d516a6876de74b68a800c5b69af9448b0de140 (patch) | |
tree | 3a56c8af8b36d03c20e9de4298f30b08cba0ea5a /spec/lib | |
parent | 77b8390171a55d4593e3730551751d8348992f80 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib')
12 files changed, 311 insertions, 158 deletions
diff --git a/spec/lib/bulk_imports/common/pipelines/badges_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/badges_pipeline_spec.rb new file mode 100644 index 00000000000..6c5465c8a66 --- /dev/null +++ b/spec/lib/bulk_imports/common/pipelines/badges_pipeline_spec.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe BulkImports::Common::Pipelines::BadgesPipeline do + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project) } + + let(:entity) { create(:bulk_import_entity, group: group) } + let(:tracker) { create(:bulk_import_tracker, entity: entity) } + let(:context) { BulkImports::Pipeline::Context.new(tracker) } + + subject(:pipeline) { described_class.new(context) } + + describe '#run' do + let(:first_page) { extracted_data(has_next_page: true) } + let(:last_page) { extracted_data(name: 'badge2') } + + before do + allow_next_instance_of(BulkImports::Common::Extractors::RestExtractor) do |extractor| + allow(extractor).to receive(:extract).and_return(first_page, last_page) + end + end + + it 'imports a group badge' do + expect { pipeline.run }.to change(Badge, :count).by(2) + + badge = group.badges.last + + expect(badge.name).to eq('badge2') + expect(badge.link_url).to eq(badge_data['link_url']) + expect(badge.image_url).to eq(badge_data['image_url']) + end + + context 'when project entity' do + let(:first_page) { extracted_data(has_next_page: true) } + let(:last_page) { extracted_data(name: 'badge2', kind: 'project') } + let(:entity) { create(:bulk_import_entity, :project_entity, project: project) } + + it 'imports a project badge & skips group badge' do + expect { pipeline.run }.to change(Badge, :count).by(1) + + badge = project.badges.last + + expect(badge.name).to eq('badge2') + expect(badge.link_url).to eq(badge_data['link_url']) + expect(badge.image_url).to eq(badge_data['image_url']) + expect(badge.type).to eq('ProjectBadge') + end + end + + describe '#transform' do + it 'return transformed badge hash' do + badge = subject.transform(context, badge_data) + + expect(badge[:name]).to eq('badge') + expect(badge[:link_url]).to eq(badge_data['link_url']) + expect(badge[:image_url]).to eq(badge_data['image_url']) + expect(badge.keys).to contain_exactly(:name, :link_url, :image_url) + end + + context 'when data is blank' do + it 'does nothing when the data is blank' do + expect(subject.transform(context, nil)).to be_nil + end + end + + context 'when project entity & group badge' do + let(:entity) { create(:bulk_import_entity, :project_entity, project: project) } + + it 'returns' do + expect(subject.transform(context, { 'name' => 'test', 'kind' => 'group' })).to be_nil + end + end + end + + def badge_data(name = 'badge', kind = 'group') + { + 'name' => name, + 'link_url' => 'https://gitlab.example.com', + 'image_url' => 'https://gitlab.example.com/image.png', + 'kind' => kind + } + end + + def extracted_data(name: 'badge', kind: 'group', has_next_page: false) + page_info = { + 'has_next_page' => has_next_page, + 'next_page' => has_next_page ? '2' : nil + } + + BulkImports::Pipeline::ExtractedData.new(data: [badge_data(name, kind)], page_info: page_info) + end + end +end diff --git a/spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb b/spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb new file mode 100644 index 00000000000..0a04c0a2243 --- /dev/null +++ b/spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe BulkImports::Common::Rest::GetBadgesQuery do + describe '.to_h' do + shared_examples 'resource and page info query' do + let(:tracker) { create(:bulk_import_tracker, entity: entity) } + let(:context) { BulkImports::Pipeline::Context.new(tracker) } + let(:encoded_full_path) { ERB::Util.url_encode(entity.source_full_path) } + + it 'returns correct query and page info' do + expected = { + resource: [entity.pluralized_name, encoded_full_path, 'badges'].join('/'), + query: { + page: context.tracker.next_page + } + } + + expect(described_class.to_h(context)).to eq(expected) + end + end + + context 'when entity is group' do + let(:entity) { create(:bulk_import_entity) } + + include_examples 'resource and page info query' + end + + context 'when entity is project' do + let(:entity) { create(:bulk_import_entity, :project_entity) } + + include_examples 'resource and page info query' + end + end +end diff --git a/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb deleted file mode 100644 index 9fa35c4707d..00000000000 --- a/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb +++ /dev/null @@ -1,116 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe BulkImports::Groups::Pipelines::BadgesPipeline do - let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group) } - - let_it_be(:entity) do - create( - :bulk_import_entity, - source_full_path: 'source/full/path', - destination_name: 'My Destination Group', - destination_namespace: group.full_path, - group: group - ) - end - - let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) } - let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) } - - subject { described_class.new(context) } - - describe '#run' do - it 'imports a group badge' do - first_page = extracted_data(has_next_page: true) - last_page = extracted_data(name: 'badge2') - - allow_next_instance_of(BulkImports::Common::Extractors::RestExtractor) do |extractor| - allow(extractor) - .to receive(:extract) - .and_return(first_page, last_page) - end - - expect { subject.run }.to change(Badge, :count).by(2) - - badge = group.badges.last - - expect(badge.name).to eq('badge2') - expect(badge.link_url).to eq(badge_data['link_url']) - expect(badge.image_url).to eq(badge_data['image_url']) - end - - describe '#load' do - it 'creates a badge' do - expect { subject.load(context, badge_data) }.to change(Badge, :count).by(1) - - badge = group.badges.first - - badge_data.each do |key, value| - expect(badge[key]).to eq(value) - end - end - - it 'does nothing when the data is blank' do - expect { subject.load(context, nil) }.not_to change(Badge, :count) - end - end - - describe '#transform' do - it 'return transformed badge hash' do - badge = subject.transform(context, badge_data) - - expect(badge[:name]).to eq('badge') - expect(badge[:link_url]).to eq(badge_data['link_url']) - expect(badge[:image_url]).to eq(badge_data['image_url']) - expect(badge.keys).to contain_exactly(:name, :link_url, :image_url) - end - - context 'when data is blank' do - it 'does nothing when the data is blank' do - expect(subject.transform(context, nil)).to be_nil - end - end - end - - describe 'pipeline parts' do - it { expect(described_class).to include_module(BulkImports::Pipeline) } - it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) } - - it 'has extractors' do - expect(described_class.get_extractor) - .to eq( - klass: BulkImports::Common::Extractors::RestExtractor, - options: { - query: BulkImports::Groups::Rest::GetBadgesQuery - } - ) - end - - it 'has transformers' do - expect(described_class.transformers) - .to contain_exactly( - { klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil } - ) - end - end - - def badge_data(name = 'badge') - { - 'name' => name, - 'link_url' => 'https://gitlab.example.com', - 'image_url' => 'https://gitlab.example.com/image.png' - } - end - - def extracted_data(name: 'badge', has_next_page: false) - page_info = { - 'has_next_page' => has_next_page, - 'next_page' => has_next_page ? '2' : nil - } - - BulkImports::Pipeline::ExtractedData.new(data: [badge_data(name)], page_info: page_info) - end - end -end diff --git a/spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb b/spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb deleted file mode 100644 index eef6848e118..00000000000 --- a/spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe BulkImports::Groups::Rest::GetBadgesQuery do - describe '.to_h' do - it 'returns query resource and page info' do - entity = create(:bulk_import_entity) - tracker = create(:bulk_import_tracker, entity: entity) - context = BulkImports::Pipeline::Context.new(tracker) - encoded_full_path = ERB::Util.url_encode(entity.source_full_path) - expected = { - resource: ['groups', encoded_full_path, 'badges'].join('/'), - query: { - page: context.tracker.next_page - } - } - - expect(described_class.to_h(context)).to eq(expected) - end - end -end diff --git a/spec/lib/bulk_imports/groups/stage_spec.rb b/spec/lib/bulk_imports/groups/stage_spec.rb index 5719acac4d7..a7acd661282 100644 --- a/spec/lib/bulk_imports/groups/stage_spec.rb +++ b/spec/lib/bulk_imports/groups/stage_spec.rb @@ -13,7 +13,7 @@ RSpec.describe BulkImports::Groups::Stage do [1, BulkImports::Groups::Pipelines::MembersPipeline], [1, BulkImports::Common::Pipelines::LabelsPipeline], [1, BulkImports::Common::Pipelines::MilestonesPipeline], - [1, BulkImports::Groups::Pipelines::BadgesPipeline], + [1, BulkImports::Common::Pipelines::BadgesPipeline], [2, BulkImports::Common::Pipelines::BoardsPipeline] ] end diff --git a/spec/lib/bulk_imports/projects/stage_spec.rb b/spec/lib/bulk_imports/projects/stage_spec.rb index cbc0ea667b7..ee197cb1c29 100644 --- a/spec/lib/bulk_imports/projects/stage_spec.rb +++ b/spec/lib/bulk_imports/projects/stage_spec.rb @@ -11,6 +11,7 @@ RSpec.describe BulkImports::Projects::Stage do [1, BulkImports::Projects::Pipelines::RepositoryPipeline], [2, BulkImports::Common::Pipelines::LabelsPipeline], [2, BulkImports::Common::Pipelines::MilestonesPipeline], + [2, BulkImports::Common::Pipelines::BadgesPipeline], [3, BulkImports::Projects::Pipelines::IssuesPipeline], [3, BulkImports::Projects::Pipelines::SnippetsPipeline], [4, BulkImports::Common::Pipelines::BoardsPipeline], diff --git a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb index 9d49db1f018..e7b9c5fcd02 100644 --- a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb +++ b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb @@ -5,24 +5,24 @@ require 'spec_helper' RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do before do create_list(:project, 3) - create(:identity) + create_list(:ci_instance_variable, 2) end subject { described_class.new(models).count } describe '#count' do - let(:models) { [Project, Identity] } + let(:models) { [Project, Ci::InstanceVariable] } context 'when reltuples is up to date' do before do - ActiveRecord::Base.connection.execute('ANALYZE projects') - ActiveRecord::Base.connection.execute('ANALYZE identities') + Project.connection.execute('ANALYZE projects') + Ci::InstanceVariable.connection.execute('ANALYZE ci_instance_variables') end it 'uses statistics to do the count' do models.each { |model| expect(model).not_to receive(:count) } - expect(subject).to eq({ Project => 3, Identity => 1 }) + expect(subject).to eq({ Project => 3, Ci::InstanceVariable => 2 }) end end @@ -31,7 +31,7 @@ RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do before do models.each do |model| - ActiveRecord::Base.connection.execute("ANALYZE #{model.table_name}") + model.connection.execute("ANALYZE #{model.table_name}") end end @@ -45,7 +45,9 @@ RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do context 'insufficient permissions' do it 'returns an empty hash' do - allow(ActiveRecord::Base).to receive(:transaction).and_raise(PG::InsufficientPrivilege) + Gitlab::Database.database_base_models.each_value do |base_model| + allow(base_model).to receive(:transaction).and_raise(PG::InsufficientPrivilege) + end expect(subject).to eq({}) end diff --git a/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb b/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb index 2f261aebf02..37d3e13a7ab 100644 --- a/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb +++ b/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb @@ -5,11 +5,12 @@ require 'spec_helper' RSpec.describe Gitlab::Database::Count::TablesampleCountStrategy do before do create_list(:project, 3) + create_list(:ci_instance_variable, 2) create(:identity) create(:group) end - let(:models) { [Project, Identity, Group, Namespace] } + let(:models) { [Project, Ci::InstanceVariable, Identity, Group, Namespace] } let(:strategy) { described_class.new(models) } subject { strategy.count } @@ -20,7 +21,8 @@ RSpec.describe Gitlab::Database::Count::TablesampleCountStrategy do Project => threshold + 1, Identity => threshold - 1, Group => threshold + 1, - Namespace => threshold + 1 + Namespace => threshold + 1, + Ci::InstanceVariable => threshold + 1 } end @@ -43,12 +45,14 @@ RSpec.describe Gitlab::Database::Count::TablesampleCountStrategy do expect(Project).not_to receive(:count) expect(Group).not_to receive(:count) expect(Namespace).not_to receive(:count) + expect(Ci::InstanceVariable).not_to receive(:count) result = subject expect(result[Project]).to eq(3) expect(result[Group]).to eq(1) # 1-Group, 3 namespaces for each project and 3 project namespaces for each project expect(result[Namespace]).to eq(7) + expect(result[Ci::InstanceVariable]).to eq(2) end end diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb index c579027788d..7c34fb1a926 100644 --- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb @@ -12,6 +12,8 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do let(:email_raw) { email_fixture('emails/service_desk.eml') } let(:author_email) { 'jake@adventuretime.ooo' } + let(:message_id) { 'CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com' } + let_it_be(:group) { create(:group, :private, name: "email") } let(:expected_description) do @@ -40,6 +42,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do expect(new_issue.all_references.all).to be_empty expect(new_issue.title).to eq("The message subject! @all") expect(new_issue.description).to eq(expected_description.strip) + expect(new_issue.email&.email_message_id).to eq(message_id) end it 'creates an issue_email_participant' do @@ -72,6 +75,95 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do it_behaves_like 'a new issue request' end + context 'when replying to issue creation email' do + def receive_reply + reply_email_raw = email_fixture('emails/service_desk_reply.eml') + + second_receiver = Gitlab::Email::Receiver.new(reply_email_raw) + second_receiver.execute + end + + context 'when an issue with message_id has been found' do + before do + receiver.execute + end + + subject do + receive_reply + end + + it 'does not create an additional issue' do + expect { subject }.not_to change { Issue.count } + end + + it 'adds a comment to the created issue' do + subject + + notes = Issue.last.notes + new_note = notes.first + + expect(notes.count).to eq(1) + expect(new_note.note).to eq("Service desk reply!\n\n`/label ~label2`") + expect(new_note.author).to eql(User.support_bot) + end + + it 'does not send thank you email' do + expect(Notify).not_to receive(:service_desk_thank_you_email) + + subject + end + + context 'when issue_email_participants FF is enabled' do + it 'creates 2 issue_email_participants' do + subject + + expect(Issue.last.issue_email_participants.map(&:email)) + .to match_array(%w(alan@adventuretime.ooo jake@adventuretime.ooo)) + end + end + + context 'when issue_email_participants FF is disabled' do + before do + stub_feature_flags(issue_email_participants: false) + end + + it 'creates only 1 issue_email_participant' do + subject + + expect(Issue.last.issue_email_participants.map(&:email)) + .to match_array(%w(jake@adventuretime.ooo)) + end + end + end + + context 'when an issue with message_id has not been found' do + subject do + receive_reply + end + + it 'creates a new issue correctly' do + expect { subject }.to change { Issue.count }.by(1) + + issue = Issue.last + + expect(issue.description).to eq("Service desk reply!\n\n`/label ~label2`") + end + + it 'sends thank you email once' do + expect(Notify).to receive(:service_desk_thank_you_email).once.and_return(double(deliver_later: true)) + + subject + end + + it 'creates 1 issue_email_participant' do + subject + + expect(Issue.last.issue_email_participants.map(&:email)) + .to match_array(%w(alan@adventuretime.ooo)) + end + end + end + context 'when using issue templates' do let_it_be(:user) { create(:user) } @@ -270,6 +362,20 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do end end + context 'when issue email creation fails' do + before do + allow(::Issue::Email).to receive(:create!).and_raise(StandardError) + end + + it 'still creates a new issue' do + expect { receiver.execute }.to change { Issue.count }.by(1) + end + + it 'does not create issue email record' do + expect { receiver.execute }.not_to change { Issue::Email.count } + end + end + context 'when rate limiting is in effect', :freeze_time, :clean_gitlab_redis_rate_limiting do let(:receiver) { Gitlab::Email::Receiver.new(email_raw) } @@ -291,19 +397,19 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do rescue RateLimitedService::RateLimitedError end.to change { Issue.count }.by(1) end + end - context 'when requests are sent by different users' do - let(:email_raw_2) { email_fixture('emails/service_desk_forwarded.eml') } - let(:receiver2) { Gitlab::Email::Receiver.new(email_raw_2) } + context 'when requests are sent by different users' do + let(:email_raw_2) { email_fixture('emails/service_desk_forwarded.eml') } + let(:receiver2) { Gitlab::Email::Receiver.new(email_raw_2) } - subject do - receiver.execute - receiver2.execute - end + subject do + receiver.execute + receiver2.execute + end - it 'creates 2 issues' do - expect { subject }.to change { Issue.count }.by(2) - end + it 'creates 2 issues' do + expect { subject }.to change { Issue.count }.by(2) end end @@ -389,6 +495,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do context 'when the email is forwarded through an alias' do let(:author_email) { 'jake.g@adventuretime.ooo' } let(:email_raw) { email_fixture('emails/service_desk_forwarded.eml') } + let(:message_id) { 'CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=fdskbsf@mail.gmail.com' } it_behaves_like 'a new issue request' end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index b474f5825fd..49052623436 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -61,6 +61,7 @@ issues: - pending_escalations - customer_relations_contacts - issue_customer_relations_contacts +- email work_item_type: - issues events: diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 9daa3b32fd1..2f7db15ae29 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -33,6 +33,7 @@ Issue: - health_status - external_key - issue_type +- email_message_id Event: - id - target_type diff --git a/spec/lib/google_api/cloud_platform/client_spec.rb b/spec/lib/google_api/cloud_platform/client_spec.rb index 3dd8f7c413e..3284c9cd0d1 100644 --- a/spec/lib/google_api/cloud_platform/client_spec.rb +++ b/spec/lib/google_api/cloud_platform/client_spec.rb @@ -209,4 +209,47 @@ RSpec.describe GoogleApi::CloudPlatform::Client do expect(subject.header).to eq({ 'User-Agent': 'GitLab/10.3 (GPN:GitLab;)' }) end end + + describe '#list_projects' do + subject { client.list_projects } + + let(:list_of_projects) { [{}, {}, {}] } + let(:next_page_token) { nil } + let(:operation) { double('projects': list_of_projects, 'next_page_token': next_page_token) } + + it 'calls Google Api CloudResourceManagerService#list_projects' do + expect_any_instance_of(Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService) + .to receive(:list_projects) + .and_return(operation) + is_expected.to eq(list_of_projects) + end + end + + describe '#create_service_account' do + subject { client.create_service_account(spy, spy, spy) } + + let(:operation) { double('Service Account') } + + it 'calls Google Api IamService#create_service_account' do + expect_any_instance_of(Google::Apis::IamV1::IamService) + .to receive(:create_service_account) + .with(any_args) + .and_return(operation) + is_expected.to eq(operation) + end + end + + describe '#create_service_account_key' do + subject { client.create_service_account_key(spy, spy) } + + let(:operation) { double('Service Account Key') } + + it 'class Google Api IamService#create_service_account_key' do + expect_any_instance_of(Google::Apis::IamV1::IamService) + .to receive(:create_service_account_key) + .with(any_args) + .and_return(operation) + is_expected.to eq(operation) + end + end end |