diff options
Diffstat (limited to 'spec/models/integrations')
29 files changed, 254 insertions, 481 deletions
diff --git a/spec/models/integrations/assembla_spec.rb b/spec/models/integrations/assembla_spec.rb index 960dfea3dc4..e9f4274952d 100644 --- a/spec/models/integrations/assembla_spec.rb +++ b/spec/models/integrations/assembla_spec.rb @@ -5,6 +5,10 @@ require 'spec_helper' RSpec.describe Integrations::Assembla do include StubRequests + it_behaves_like Integrations::ResetSecretFields do + let(:integration) { described_class.new } + end + describe "Execute" do let(:user) { create(:user) } let(:project) { create(:project, :repository) } diff --git a/spec/models/integrations/bamboo_spec.rb b/spec/models/integrations/bamboo_spec.rb index e92226d109f..1d2c90dad51 100644 --- a/spec/models/integrations/bamboo_spec.rb +++ b/spec/models/integrations/bamboo_spec.rb @@ -23,6 +23,10 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching do ) end + it_behaves_like Integrations::BaseCi + + it_behaves_like Integrations::ResetSecretFields + include_context Integrations::EnableSslVerification describe 'Validations' do @@ -77,48 +81,6 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching do end end - describe 'Callbacks' do - describe 'before_validation :reset_password' do - context 'when a password was previously set' do - it 'resets password if url changed' do - integration.bamboo_url = 'http://gitlab1.com' - - expect(integration).not_to be_valid - expect(integration.password).to be_nil - end - - it 'does not reset password if username changed' do - integration.username = 'some_name' - - expect(integration).to be_valid - expect(integration.password).to eq('password') - end - - it "does not reset password if new url is set together with password, even if it's the same password" do - integration.bamboo_url = 'http://gitlab_edited.com' - integration.password = 'password' - - expect(integration).to be_valid - expect(integration.password).to eq('password') - expect(integration.bamboo_url).to eq('http://gitlab_edited.com') - end - end - - it 'saves password if new url is set together with password when no password was previously set' do - integration.password = nil - - integration.bamboo_url = 'http://gitlab_edited.com' - integration.password = 'password' - integration.save! - - expect(integration.reload).to have_attributes( - bamboo_url: 'http://gitlab_edited.com', - password: 'password' - ) - end - end - end - describe '#execute' do it 'runs update and build action' do stub_update_and_build_request diff --git a/spec/models/integrations/base_chat_notification_spec.rb b/spec/models/integrations/base_chat_notification_spec.rb index eb503e501d6..b959ead2cae 100644 --- a/spec/models/integrations/base_chat_notification_spec.rb +++ b/spec/models/integrations/base_chat_notification_spec.rb @@ -3,11 +3,15 @@ require 'spec_helper' RSpec.describe Integrations::BaseChatNotification do + describe 'default values' do + it { expect(subject.category).to eq(:chat) } + end + describe 'validations' do before do allow(subject).to receive(:activated?).and_return(true) allow(subject).to receive(:default_channel_placeholder).and_return('placeholder') - allow(subject).to receive(:webhook_placeholder).and_return('placeholder') + allow(subject).to receive(:webhook_help).and_return('help') end it { is_expected.to validate_presence_of :webhook } @@ -19,7 +23,7 @@ RSpec.describe Integrations::BaseChatNotification do let_it_be(:project) { create(:project, :repository) } - let(:user) { create(:user) } + let(:user) { build_stubbed(:user) } let(:webhook_url) { 'https://example.gitlab.com/' } let(:data) { Gitlab::DataBuilder::Push.build_sample(subject.project, user) } @@ -44,7 +48,7 @@ RSpec.describe Integrations::BaseChatNotification do context 'with an empty repository' do it 'returns true' do - subject.project = create(:project, :empty_repo) + subject.project = build_stubbed(:project, :empty_repo) expect(chat_integration).to receive(:notify).and_return(true) expect(chat_integration.execute(data)).to be true @@ -61,9 +65,9 @@ RSpec.describe Integrations::BaseChatNotification do end context 'when the data object has a label' do - let_it_be(:label) { create(:label, name: 'Bug') } - let_it_be(:label_2) { create(:label, name: 'Community contribution') } - let_it_be(:label_3) { create(:label, name: 'Backend') } + let_it_be(:label) { create(:label, project: project, name: 'Bug') } + let_it_be(:label_2) { create(:label, project: project, name: 'Community contribution') } + let_it_be(:label_3) { create(:label, project: project, name: 'Backend') } let_it_be(:issue) { create(:labeled_issue, project: project, labels: [label, label_2, label_3]) } let_it_be(:note) { create(:note, noteable: issue, project: project) } @@ -93,7 +97,7 @@ RSpec.describe Integrations::BaseChatNotification do it_behaves_like 'notifies the chat integration' context 'MergeRequest events' do - let(:data) { create(:merge_request, labels: [label]).to_hook_data(user) } + let(:data) { build_stubbed(:merge_request, source_project: project, labels: [label]).to_hook_data(user) } it_behaves_like 'notifies the chat integration' end @@ -280,9 +284,9 @@ RSpec.describe Integrations::BaseChatNotification do end end - describe '#webhook_placeholder' do + describe '#webhook_help' do it 'raises an error' do - expect { subject.webhook_placeholder }.to raise_error(NotImplementedError) + expect { subject.webhook_help }.to raise_error(NotImplementedError) end end diff --git a/spec/models/integrations/base_issue_tracker_spec.rb b/spec/models/integrations/base_issue_tracker_spec.rb index 37f7d99717c..e1a764cd7cb 100644 --- a/spec/models/integrations/base_issue_tracker_spec.rb +++ b/spec/models/integrations/base_issue_tracker_spec.rb @@ -7,6 +7,10 @@ RSpec.describe Integrations::BaseIssueTracker do let_it_be_with_refind(:project) { create :project } + describe 'default values' do + it { expect(subject.category).to eq(:issue_tracker) } + end + describe 'Validations' do describe 'only one issue tracker per project' do before do diff --git a/spec/models/integrations/base_third_party_wiki_spec.rb b/spec/models/integrations/base_third_party_wiki_spec.rb index 11e044c2a18..dbead636cb9 100644 --- a/spec/models/integrations/base_third_party_wiki_spec.rb +++ b/spec/models/integrations/base_third_party_wiki_spec.rb @@ -3,6 +3,10 @@ require 'spec_helper' RSpec.describe Integrations::BaseThirdPartyWiki do + describe 'default values' do + it { expect(subject.category).to eq(:third_party_wiki) } + end + describe 'Validations' do let_it_be_with_reload(:project) { create(:project) } diff --git a/spec/models/integrations/buildkite_spec.rb b/spec/models/integrations/buildkite_spec.rb index c720dc6d418..5f62c68bd2b 100644 --- a/spec/models/integrations/buildkite_spec.rb +++ b/spec/models/integrations/buildkite_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do include ReactiveCachingHelpers include StubRequests - let(:project) { create(:project) } + let_it_be(:project) { create(:project) } subject(:integration) do described_class.create!( @@ -18,6 +18,10 @@ RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do ) end + it_behaves_like Integrations::BaseCi + + it_behaves_like Integrations::ResetSecretFields + it_behaves_like Integrations::HasWebHook do let(:hook_url) { 'https://webhook.buildkite.com/deliver/{webhook_token}' } end diff --git a/spec/models/integrations/campfire_spec.rb b/spec/models/integrations/campfire_spec.rb index a6bcd22b6f6..ae923cd38fc 100644 --- a/spec/models/integrations/campfire_spec.rb +++ b/spec/models/integrations/campfire_spec.rb @@ -34,8 +34,8 @@ RSpec.describe Integrations::Campfire do end describe "#execute" do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } + let(:user) { build_stubbed(:user) } + let(:project) { build_stubbed(:project, :repository) } before do @campfire_integration = described_class.new diff --git a/spec/models/integrations/chat_message/pipeline_message_spec.rb b/spec/models/integrations/chat_message/pipeline_message_spec.rb index a63cc0b6d83..f3388853b37 100644 --- a/spec/models/integrations/chat_message/pipeline_message_spec.rb +++ b/spec/models/integrations/chat_message/pipeline_message_spec.rb @@ -44,13 +44,18 @@ RSpec.describe Integrations::ChatMessage::PipelineMessage do before do test_commit = double("A test commit", committer: args[:user], title: "A test commit message") - test_project = double("A test project", commit_by: test_commit, name: args[:project][:name], web_url: args[:project][:web_url]) + test_project = build(:project, name: args[:project][:name]) + + allow(test_project).to receive(:commit_by).and_return(test_commit) + allow(test_project).to receive(:web_url).and_return(args[:project][:web_url]) allow(test_project).to receive(:avatar_url).with(no_args).and_return("/avatar") allow(test_project).to receive(:avatar_url).with(only_path: false).and_return(args[:project][:avatar_url]) allow(Project).to receive(:find) { test_project } - test_pipeline = double("A test pipeline", - has_yaml_errors?: has_yaml_errors, yaml_errors: "yaml error description here") + test_pipeline = build(:ci_empty_pipeline, name: 'Build pipeline') + + allow(test_pipeline).to receive(:has_yaml_errors?).and_return(has_yaml_errors) + allow(test_pipeline).to receive(:yaml_errors).and_return("yaml error description here") allow(Ci::Pipeline).to receive(:find) { test_pipeline } allow(Gitlab::UrlBuilder).to receive(:build).with(test_commit).and_return("http://example.com/commit") @@ -69,6 +74,24 @@ RSpec.describe Integrations::ChatMessage::PipelineMessage do ) end + it 'returns pipeline name' do + name_field = subject.attachments.first[:fields].find { |a| a[:title] == 'Pipeline name' } + + expect(name_field[:value]).to eq('Build pipeline') + end + + context 'when pipeline_name feature flag is disabled' do + before do + stub_feature_flags(pipeline_name: false) + end + + it 'does not return pipeline name' do + name_field = subject.attachments.first[:fields].find { |a| a[:title] == 'Pipeline name' } + + expect(name_field).to be nil + end + end + context "when the pipeline failed" do before do args[:object_attributes][:status] = 'failed' @@ -204,8 +227,8 @@ RSpec.describe Integrations::ChatMessage::PipelineMessage do expect(subject.attachments.first[:title_link]).to eq("http://example.gitlab.com/-/pipelines/123") end - it "returns two attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(2) + it "returns three attachment fields" do + expect(subject.attachments.first[:fields].count).to eq(3) end it "returns the commit message as the attachment's second field property" do @@ -232,8 +255,8 @@ RSpec.describe Integrations::ChatMessage::PipelineMessage do ] end - it "returns four attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(4) + it "returns five attachment fields" do + expect(subject.attachments.first[:fields].count).to eq(5) end it "returns the stage name and link to the 'Failed jobs' tab on the pipeline's page as the attachment's third field property" do @@ -337,8 +360,8 @@ RSpec.describe Integrations::ChatMessage::PipelineMessage do context "when the CI config file contains a YAML error" do let(:has_yaml_errors) { true } - it "returns three attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(3) + it "returns four attachment fields" do + expect(subject.attachments.first[:fields].count).to eq(4) end it "returns the YAML error deatils as the attachment's third field property" do diff --git a/spec/models/integrations/confluence_spec.rb b/spec/models/integrations/confluence_spec.rb index e2f9316bc95..999a532527d 100644 --- a/spec/models/integrations/confluence_spec.rb +++ b/spec/models/integrations/confluence_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Integrations::Confluence do + let_it_be(:project) { create(:project) } + describe 'Validations' do before do subject.active = active @@ -40,7 +42,6 @@ RSpec.describe Integrations::Confluence do describe '#help' do it 'can correctly return a link to the project wiki when active' do - project = create(:project) subject.project = project subject.active = true @@ -62,8 +63,6 @@ RSpec.describe Integrations::Confluence do end describe 'Caching has_confluence on project_settings' do - let(:project) { create(:project) } - subject { project.project_setting.has_confluence? } it 'sets the property to true when integration is active' do diff --git a/spec/models/integrations/datadog_spec.rb b/spec/models/integrations/datadog_spec.rb index 71a5bbc4db1..65ecd9bee83 100644 --- a/spec/models/integrations/datadog_spec.rb +++ b/spec/models/integrations/datadog_spec.rb @@ -73,7 +73,15 @@ RSpec.describe Integrations::Datadog do it { is_expected.to validate_presence_of(:datadog_site) } it { is_expected.not_to validate_presence_of(:api_url) } + it { is_expected.to allow_value('data-dog-hq.com').for(:datadog_site) } + it { is_expected.to allow_value('dataDOG.com').for(:datadog_site) } it { is_expected.not_to allow_value('datadog hq.com').for(:datadog_site) } + it { is_expected.not_to allow_value('-datadoghq.com').for(:datadog_site) } + it { is_expected.not_to allow_value('.datadoghq.com').for(:datadog_site) } + it { is_expected.not_to allow_value('datadoghq.com_').for(:datadog_site) } + it { is_expected.not_to allow_value('data-dog').for(:datadog_site) } + it { is_expected.not_to allow_value('datadoghq.com-').for(:datadog_site) } + it { is_expected.not_to allow_value('datadoghq.com.').for(:datadog_site) } end context 'with custom api_url' do diff --git a/spec/models/integrations/discord_spec.rb b/spec/models/integrations/discord_spec.rb index eb90acc73be..138a56d1872 100644 --- a/spec/models/integrations/discord_spec.rb +++ b/spec/models/integrations/discord_spec.rb @@ -25,7 +25,7 @@ RSpec.describe Integrations::Discord do let_it_be(:project) { create(:project, :repository) } - let(:user) { create(:user) } + let(:user) { build_stubbed(:user) } let(:webhook_url) { "https://example.gitlab.com/" } let(:sample_data) do Gitlab::DataBuilder::Push.build_sample(project, user) diff --git a/spec/models/integrations/drone_ci_spec.rb b/spec/models/integrations/drone_ci_spec.rb index f3203a6e69d..6ff6888e0d3 100644 --- a/spec/models/integrations/drone_ci_spec.rb +++ b/spec/models/integrations/drone_ci_spec.rb @@ -7,6 +7,10 @@ RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do subject(:integration) { described_class.new } + let_it_be(:project) { create(:project, :repository, name: 'project') } + + it_behaves_like Integrations::BaseCi + it_behaves_like Integrations::ResetSecretFields do let(:integration) { subject } end @@ -43,7 +47,6 @@ RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do ) end - let(:project) { create(:project, :repository, name: 'project') } let(:path) { project.full_path } let(:drone_url) { 'http://drone.example.com' } let(:sha) { '2ab7834c' } @@ -192,7 +195,7 @@ RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do describe "execute" do include_context :drone_ci_integration - let(:user) { create(:user, username: 'username') } + let(:user) { build(:user, username: 'username') } let(:push_sample_data) do Gitlab::DataBuilder::Push.build_sample(project, user) end diff --git a/spec/models/integrations/emails_on_push_spec.rb b/spec/models/integrations/emails_on_push_spec.rb index 15aa105e379..b3fe6bf9506 100644 --- a/spec/models/integrations/emails_on_push_spec.rb +++ b/spec/models/integrations/emails_on_push_spec.rb @@ -87,8 +87,8 @@ RSpec.describe Integrations::EmailsOnPush do end describe '#execute' do + let_it_be(:project) { create(:project, :repository) } let(:push_data) { { object_kind: 'push' } } - let(:project) { create(:project, :repository) } let(:integration) { create(:emails_on_push_integration, project: project) } let(:recipients) { 'test@gitlab.com' } diff --git a/spec/models/integrations/hangouts_chat_spec.rb b/spec/models/integrations/hangouts_chat_spec.rb index 828bcdf5d8f..288478b494e 100644 --- a/spec/models/integrations/hangouts_chat_spec.rb +++ b/spec/models/integrations/hangouts_chat_spec.rb @@ -46,7 +46,7 @@ RSpec.describe Integrations::HangoutsChat do end context 'with issue events' do - let(:issues_sample_data) { create(:issue).to_hook_data(user) } + let(:issues_sample_data) { create(:issue, project: project).to_hook_data(user) } it "adds thread key for issue events" do expect(chat_integration.execute(issues_sample_data)).to be(true) @@ -58,7 +58,7 @@ RSpec.describe Integrations::HangoutsChat do end context 'with merge events' do - let(:merge_sample_data) { create(:merge_request).to_hook_data(user) } + let(:merge_sample_data) { create(:merge_request, source_project: project).to_hook_data(user) } it "adds thread key for merge events" do expect(chat_integration.execute(merge_sample_data)).to be(true) @@ -71,7 +71,7 @@ RSpec.describe Integrations::HangoutsChat do context 'with wiki page events' do let(:wiki_page_sample_data) do - Gitlab::DataBuilder::WikiPage.build(create(:wiki_page, message: 'foo'), user, 'create') + Gitlab::DataBuilder::WikiPage.build(create(:wiki_page, project: project, message: 'foo'), user, 'create') end it "adds thread key for wiki page events" do diff --git a/spec/models/integrations/harbor_spec.rb b/spec/models/integrations/harbor_spec.rb index 9ab37a92e89..b4580028112 100644 --- a/spec/models/integrations/harbor_spec.rb +++ b/spec/models/integrations/harbor_spec.rb @@ -70,7 +70,7 @@ RSpec.describe Integrations::Harbor do end context 'ci variables' do - let(:harbor_integration) { create(:harbor_integration) } + let(:harbor_integration) { build_stubbed(:harbor_integration) } it 'returns vars when harbor_integration is activated' do ci_vars = [ @@ -85,9 +85,12 @@ RSpec.describe Integrations::Harbor do expect(harbor_integration.ci_variables).to match_array(ci_vars) end - it 'returns [] when harbor_integration is inactive' do - harbor_integration.update!(active: false) - expect(harbor_integration.ci_variables).to match_array([]) + context 'when harbor_integration is inactive' do + let(:harbor_integration) { build_stubbed(:harbor_integration, active: false) } + + it 'returns []' do + expect(harbor_integration.ci_variables).to match_array([]) + end end context 'with robot username' do diff --git a/spec/models/integrations/jenkins_spec.rb b/spec/models/integrations/jenkins_spec.rb index 200de1305e2..0264982f0dc 100644 --- a/spec/models/integrations/jenkins_spec.rb +++ b/spec/models/integrations/jenkins_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Integrations::Jenkins do - let(:project) { create(:project) } + let_it_be(:project) { create(:project) } let(:jenkins_integration) { described_class.new(jenkins_params) } let(:jenkins_url) { 'http://jenkins.example.com/' } let(:jenkins_hook_url) { jenkins_url + 'project/my_project' } @@ -23,6 +23,12 @@ RSpec.describe Integrations::Jenkins do } end + it_behaves_like Integrations::BaseCi + + it_behaves_like Integrations::ResetSecretFields do + let(:integration) { jenkins_integration } + end + include_context Integrations::EnableSslVerification do let(:integration) { jenkins_integration } end @@ -38,7 +44,7 @@ RSpec.describe Integrations::Jenkins do expect(jenkins_integration.tag_push_events).to eq(false) end - describe 'username validation' do + describe 'Validations' do let(:jenkins_integration) do described_class.create!( active: active, @@ -57,28 +63,44 @@ RSpec.describe Integrations::Jenkins do context 'when the integration is active' do let(:active) { true } - context 'when password was not touched' do - before do - allow(subject).to receive(:password_touched?).and_return(false) + describe '#username' do + context 'when password was not touched' do + before do + allow(subject).to receive(:password_touched?).and_return(false) + end + + it { is_expected.not_to validate_presence_of :username } end - it { is_expected.not_to validate_presence_of :username } - end + context 'when password was touched' do + before do + allow(subject).to receive(:password_touched?).and_return(true) + end - context 'when password was touched' do - before do - allow(subject).to receive(:password_touched?).and_return(true) + it { is_expected.to validate_presence_of :username } end - it { is_expected.to validate_presence_of :username } + context 'when password is blank' do + it 'does not validate the username' do + expect(subject).not_to validate_presence_of :username + + subject.password = '' + subject.save! + end + end end - context 'when password is blank' do - it 'does not validate the username' do - expect(subject).not_to validate_presence_of :username + describe '#password' do + it 'does not validate the presence of password if username is nil' do + subject.username = nil + + expect(subject).not_to validate_presence_of(:password) + end + + it 'validates the presence of password if username is present' do + subject.username = 'john' - subject.password = '' - subject.save! + expect(subject).to validate_presence_of(:password) end end end @@ -87,6 +109,7 @@ RSpec.describe Integrations::Jenkins do let(:active) { false } it { is_expected.not_to validate_presence_of :username } + it { is_expected.not_to validate_presence_of :password } end end @@ -144,8 +167,7 @@ RSpec.describe Integrations::Jenkins do describe '#test' do it 'returns the right status' do - user = create(:user, username: 'username') - project = create(:project, name: 'project') + user = build(:user, username: 'username') push_sample_data = Gitlab::DataBuilder::Push.build_sample(project, user) jenkins_integration = described_class.create!(jenkins_params) stub_request(:post, jenkins_hook_url).with(headers: { 'Authorization' => jenkins_authorization }) @@ -157,9 +179,9 @@ RSpec.describe Integrations::Jenkins do end describe '#execute' do - let(:user) { create(:user, username: 'username') } - let(:namespace) { create(:group, :private) } - let(:project) { create(:project, :private, name: 'project', namespace: namespace) } + let(:user) { build(:user, username: 'username') } + let_it_be(:namespace) { create(:group, :private) } + let_it_be(:project) { create(:project, :private, name: 'project', namespace: namespace) } let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) } let(:jenkins_integration) { described_class.create!(jenkins_params) } @@ -191,82 +213,4 @@ RSpec.describe Integrations::Jenkins do ).to have_been_made.once end end - - describe 'Stored password invalidation' do - let(:project) { create(:project) } - - context 'when a password was previously set' do - let(:jenkins_integration) do - described_class.create!( - project: project, - properties: { - jenkins_url: 'http://jenkins.example.com/', - username: 'jenkins', - password: 'password' - } - ) - end - - it 'resets password if url changed' do - jenkins_integration.jenkins_url = 'http://jenkins-edited.example.com/' - jenkins_integration.valid? - - expect(jenkins_integration.password).to be_nil - end - - it 'resets password if username is blank' do - jenkins_integration.username = '' - jenkins_integration.valid? - - expect(jenkins_integration.password).to be_nil - end - - it 'does not reset password if username changed' do - jenkins_integration.username = 'some_name' - jenkins_integration.valid? - - expect(jenkins_integration.password).to eq('password') - end - - it 'does not reset password if new url is set together with password, even if it\'s the same password' do - jenkins_integration.jenkins_url = 'http://jenkins_edited.example.com/' - jenkins_integration.password = 'password' - jenkins_integration.valid? - - expect(jenkins_integration.password).to eq('password') - expect(jenkins_integration.jenkins_url).to eq('http://jenkins_edited.example.com/') - end - - it 'resets password if url changed, even if setter called multiple times' do - jenkins_integration.jenkins_url = 'http://jenkins1.example.com/' - jenkins_integration.jenkins_url = 'http://jenkins1.example.com/' - jenkins_integration.valid? - - expect(jenkins_integration.password).to be_nil - end - end - - context 'when no password was previously set' do - let(:jenkins_integration) do - described_class.create!( - project: create(:project), - properties: { - jenkins_url: 'http://jenkins.example.com/', - username: 'jenkins' - } - ) - end - - it 'saves password if new url is set together with password' do - jenkins_integration.jenkins_url = 'http://jenkins_edited.example.com/' - jenkins_integration.password = 'password' - jenkins_integration.save! - - expect(jenkins_integration.reload).to have_attributes( - jenkins_url: 'http://jenkins_edited.example.com/', - password: 'password' - ) - end - end - end end diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb index 9f928442b28..819dad9d46d 100644 --- a/spec/models/integrations/jira_spec.rb +++ b/spec/models/integrations/jira_spec.rb @@ -26,7 +26,7 @@ RSpec.describe Integrations::Jira do end before do - WebMock.stub_request(:get, /serverInfo/).to_return(body: server_info_results.to_json ) + WebMock.stub_request(:get, /serverInfo/).to_return(body: server_info_results.to_json) end it_behaves_like Integrations::ResetSecretFields do @@ -162,7 +162,7 @@ RSpec.describe Integrations::Jira do end describe '#fields' do - let(:integration) { create(:jira_integration) } + let(:integration) { jira_integration } subject(:fields) { integration.fields } @@ -172,7 +172,7 @@ RSpec.describe Integrations::Jira do end describe '#sections' do - let(:integration) { create(:jira_integration) } + let(:integration) { jira_integration } subject(:sections) { integration.sections.map { |s| s[:type] } } @@ -332,28 +332,7 @@ RSpec.describe Integrations::Jira do # we need to make sure we are able to read both from properties and jira_tracker_data table # TODO: change this as part of https://gitlab.com/gitlab-org/gitlab/issues/29404 context 'overriding properties' do - let(:access_params) do - { url: url, api_url: api_url, username: username, password: password, - jira_issue_transition_id: transition_id } - end - - let(:data_params) do - { - url: url, api_url: api_url, - username: username, password: password, - jira_issue_transition_id: transition_id - } - end - shared_examples 'handles jira fields' do - let(:data_params) do - { - url: url, api_url: api_url, - username: username, password: password, - jira_issue_transition_id: transition_id - } - end - context 'reading data' do it 'reads data correctly' do expect(integration.url).to eq(url) @@ -449,32 +428,40 @@ RSpec.describe Integrations::Jira do end # this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404 - context 'when data are stored in properties' do - let(:properties) { data_params } - let!(:integration) do - create(:jira_integration, :without_properties_callback, properties: properties.merge(additional: 'something')) + context 'with properties' do + let(:data_params) do + { + url: url, api_url: api_url, + username: username, password: password, + jira_issue_transition_id: transition_id + } end - it_behaves_like 'handles jira fields' - end + context 'when data are stored in properties' do + let(:integration) do + create(:jira_integration, :without_properties_callback, project: project, properties: data_params.merge(additional: 'something')) + end - context 'when data are stored in separated fields' do - let(:integration) do - create(:jira_integration, data_params.merge(properties: {})) + it_behaves_like 'handles jira fields' end - it_behaves_like 'handles jira fields' - end - - context 'when data are stored in both properties and separated fields' do - let(:properties) { data_params } - let(:integration) do - create(:jira_integration, :without_properties_callback, properties: properties).tap do |integration| - create(:jira_tracker_data, data_params.merge(integration: integration)) + context 'when data are stored in separated fields' do + let(:integration) do + create(:jira_integration, data_params.merge(properties: {}, project: project)) end + + it_behaves_like 'handles jira fields' end - it_behaves_like 'handles jira fields' + context 'when data are stored in both properties and separated fields' do + let(:integration) do + create(:jira_integration, :without_properties_callback, properties: data_params, project: project).tap do |integration| + create(:jira_tracker_data, data_params.merge(integration: integration)) + end + end + + it_behaves_like 'handles jira fields' + end end end @@ -872,7 +859,7 @@ RSpec.describe Integrations::Jira do end context 'when resource is a merge request' do - let(:resource) { create(:merge_request) } + let_it_be(:resource) { create(:merge_request, source_project: project) } let(:commit_id) { resource.diff_head_sha } it_behaves_like 'close_issue' @@ -1084,7 +1071,7 @@ RSpec.describe Integrations::Jira do end it 'removes trailing slashes from url' do - integration = described_class.new(url: 'http://jira.test.com/path/') + integration = described_class.new(url: 'http://jira.test.com/path/', project: project) expect(integration.url).to eq('http://jira.test.com/path') end @@ -1105,7 +1092,7 @@ RSpec.describe Integrations::Jira do end context 'generating external URLs' do - let(:integration) { described_class.new(url: 'http://jira.test.com/path/') } + let(:integration) { described_class.new(url: 'http://jira.test.com/path/', project: project) } describe '#web_url' do it 'handles paths, slashes, and query string' do diff --git a/spec/models/integrations/mattermost_slash_commands_spec.rb b/spec/models/integrations/mattermost_slash_commands_spec.rb index b6abe00469b..070adb9ba93 100644 --- a/spec/models/integrations/mattermost_slash_commands_spec.rb +++ b/spec/models/integrations/mattermost_slash_commands_spec.rb @@ -6,9 +6,9 @@ RSpec.describe Integrations::MattermostSlashCommands do it_behaves_like Integrations::BaseSlashCommands describe 'Mattermost API' do - let(:project) { create(:project) } + let_it_be_with_reload(:project) { create(:project) } let(:integration) { project.build_mattermost_slash_commands_integration } - let(:user) { create(:user) } + let(:user) { build_stubbed(:user) } before do session = ::Mattermost::Session.new(nil) diff --git a/spec/models/integrations/microsoft_teams_spec.rb b/spec/models/integrations/microsoft_teams_spec.rb index b6de2bb7176..c61cc732372 100644 --- a/spec/models/integrations/microsoft_teams_spec.rb +++ b/spec/models/integrations/microsoft_teams_spec.rb @@ -17,35 +17,8 @@ RSpec.describe Integrations::MicrosoftTeams do let(:chat_integration) { described_class.new } let(:webhook_url) { 'https://example.gitlab.com/' } - describe 'Validations' do - context 'when integration is active' do - before do - subject.active = true - end - - it { is_expected.to validate_presence_of(:webhook) } - - it_behaves_like 'issue tracker integration URL attribute', :webhook - end - - context 'when integration is inactive' do - before do - subject.active = false - end - - it { is_expected.not_to validate_presence_of(:webhook) } - end - end - - describe '.supported_events' do - it 'does not support deployment_events' do - expect(described_class.supported_events).not_to include('deployment') - end - end - describe "#execute" do - let(:user) { create(:user) } - + let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :repository, :wiki_repo) } before do @@ -145,8 +118,8 @@ RSpec.describe Integrations::MicrosoftTeams do end describe "Note events" do - let(:user) { create(:user) } - let(:project) { create(:project, :repository, creator: user) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository, creator: user) } before do allow(chat_integration).to receive_messages( @@ -221,8 +194,7 @@ RSpec.describe Integrations::MicrosoftTeams do end describe 'Pipeline events' do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } + let_it_be_with_reload(:project) { create(:project, :repository) } let(:pipeline) do create(:ci_pipeline, diff --git a/spec/models/integrations/mock_ci_spec.rb b/spec/models/integrations/mock_ci_spec.rb index d29c63b3a97..83954812bfe 100644 --- a/spec/models/integrations/mock_ci_spec.rb +++ b/spec/models/integrations/mock_ci_spec.rb @@ -7,6 +7,8 @@ RSpec.describe Integrations::MockCi do subject(:integration) { described_class.new(project: project, mock_service_url: generate(:url)) } + it_behaves_like Integrations::BaseCi + include_context Integrations::EnableSslVerification describe '#commit_status' do diff --git a/spec/models/integrations/packagist_spec.rb b/spec/models/integrations/packagist_spec.rb index e078debd126..e00de0f7418 100644 --- a/spec/models/integrations/packagist_spec.rb +++ b/spec/models/integrations/packagist_spec.rb @@ -3,50 +3,76 @@ require 'spec_helper' RSpec.describe Integrations::Packagist do - let(:packagist_params) do - { - active: true, - project: project, - properties: { - username: packagist_username, - token: packagist_token, - server: packagist_server - } - } - end - - let(:packagist_hook_url) do - "#{packagist_server}/api/update-package?username=#{packagist_username}&apiToken=#{packagist_token}" - end - - let(:packagist_token) { 'verySecret' } - let(:packagist_username) { 'theUser' } - let(:packagist_server) { 'https://packagist.example.com' } - let(:project) { create(:project) } - it_behaves_like Integrations::HasWebHook do - let(:integration) { described_class.new(packagist_params) } - let(:hook_url) { "#{packagist_server}/api/update-package?username={username}&apiToken={token}" } + let_it_be(:project) { create(:project) } + + let(:integration) { build(:packagist_integration, project: project) } + let(:hook_url) { "#{integration.server}/api/update-package?username={username}&apiToken={token}" } end it_behaves_like Integrations::ResetSecretFields do - let(:integration) { described_class.new(packagist_params) } + let(:integration) { build(:packagist_integration) } end describe '#execute' do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) } - let(:packagist_integration) { described_class.create!(packagist_params) } + let(:project) { build(:project) } + let(:integration) { build(:packagist_integration, project: project) } + + let(:packagist_hook_url) do + "#{integration.server}/api/update-package?username=#{integration.username}&apiToken=#{integration.token}" + end before do stub_request(:post, packagist_hook_url) end it 'calls Packagist API' do - packagist_integration.execute(push_sample_data) + user = create(:user) + push_sample_data = Gitlab::DataBuilder::Push.build_sample(project, user) + integration.execute(push_sample_data) expect(a_request(:post, packagist_hook_url)).to have_been_made.once end end + + describe '#test' do + let(:integration) { build(:packagist_integration) } + let(:test_data) { { foo: 'bar' } } + + subject(:result) { integration.test(test_data) } + + context 'when test request executes without errors' do + before do + allow(integration).to receive(:execute).with(test_data).and_return( + ServiceResponse.success(message: 'success message', payload: { http_status: http_status }) + ) + end + + context 'when response is a 200' do + let(:http_status) { 200 } + + it 'return failure result' do + is_expected.to eq(success: false, result: 'success message') + end + end + + context 'when response is a 202' do + let(:http_status) { 202 } + + it 'return success result' do + is_expected.to eq(success: true, result: 'success message') + end + end + end + + context 'when test request executes with errors' do + before do + allow(integration).to receive(:execute).with(test_data).and_raise(StandardError, 'error message') + end + + it 'return failure result' do + is_expected.to eq(success: false, result: 'error message') + end + end + end end diff --git a/spec/models/integrations/pipelines_email_spec.rb b/spec/models/integrations/pipelines_email_spec.rb index d70f104b965..37a3849a768 100644 --- a/spec/models/integrations/pipelines_email_spec.rb +++ b/spec/models/integrations/pipelines_email_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Integrations::PipelinesEmail, :mailer do ) end - let(:project) { create(:project, :repository) } + let_it_be_with_reload(:project) { create(:project, :repository) } let(:recipients) { 'test@gitlab.com' } let(:receivers) { [recipients] } diff --git a/spec/models/integrations/prometheus_spec.rb b/spec/models/integrations/prometheus_spec.rb index 3971511872b..3c3850854b3 100644 --- a/spec/models/integrations/prometheus_spec.rb +++ b/spec/models/integrations/prometheus_spec.rb @@ -12,6 +12,8 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching, let(:integration) { project.prometheus_integration } + it_behaves_like Integrations::BaseMonitoring + context 'redirects' do it 'does not follow redirects' do redirect_to = 'https://redirected.example.com' @@ -217,7 +219,7 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching, expect(integration.prometheus_client).to be_nil end - context 'with self monitoring project and internal Prometheus URL' do + context 'with self-monitoring project and internal Prometheus URL' do before do stub_application_setting(allow_local_requests_from_web_hooks_and_services: false) stub_application_setting(self_monitoring_project_id: project.id) @@ -308,7 +310,7 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching, end context 'cluster belongs to project' do - let(:cluster) { create(:cluster, projects: [project]) } + let_it_be(:cluster) { create(:cluster, projects: [project]) } it 'returns true' do expect(integration.prometheus_available?).to be(true) @@ -319,7 +321,7 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching, let_it_be(:group) { create(:group) } let(:project) { create(:project, :with_prometheus_integration, group: group) } - let(:cluster) { create(:cluster_for_group, groups: [group]) } + let_it_be(:cluster) { create(:cluster_for_group, groups: [group]) } it 'returns true' do expect(integration.prometheus_available?).to be(true) diff --git a/spec/models/integrations/pushover_spec.rb b/spec/models/integrations/pushover_spec.rb index 716a00c5bcf..8286fd20669 100644 --- a/spec/models/integrations/pushover_spec.rb +++ b/spec/models/integrations/pushover_spec.rb @@ -29,8 +29,8 @@ RSpec.describe Integrations::Pushover do describe 'Execute' do let(:pushover) { described_class.new } - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } + let(:user) { build_stubbed(:user) } + let(:project) { build_stubbed(:project, :repository) } let(:sample_data) do Gitlab::DataBuilder::Push.build_sample(project, user) end diff --git a/spec/models/integrations/shimo_spec.rb b/spec/models/integrations/shimo_spec.rb index 41f3f3c0c16..be626012ab2 100644 --- a/spec/models/integrations/shimo_spec.rb +++ b/spec/models/integrations/shimo_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe ::Integrations::Shimo do describe '#fields' do - let(:shimo_integration) { create(:shimo_integration) } + let(:shimo_integration) { build(:shimo_integration) } it 'returns custom fields' do expect(shimo_integration.fields.pluck(:name)).to eq(%w[external_wiki_url]) @@ -12,7 +12,7 @@ RSpec.describe ::Integrations::Shimo do end describe '#create' do - let(:project) { create(:project, :repository) } + let_it_be(:project) { create(:project, :repository) } let(:external_wiki_url) { 'https://shimo.example.com/desktop' } let(:params) { { active: true, project: project, external_wiki_url: external_wiki_url } } @@ -40,7 +40,7 @@ RSpec.describe ::Integrations::Shimo do end describe 'Caching has_shimo on project_settings' do - let(:project) { create(:project) } + let_it_be(:project) { create(:project) } subject { project.project_setting.has_shimo? } diff --git a/spec/models/integrations/slack_slash_commands_spec.rb b/spec/models/integrations/slack_slash_commands_spec.rb index ff89d2c6a40..22cbaa777cd 100644 --- a/spec/models/integrations/slack_slash_commands_spec.rb +++ b/spec/models/integrations/slack_slash_commands_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Integrations::SlackSlashCommands do describe '#trigger' do context 'when an auth url is generated' do - let(:project) { create(:project) } + let_it_be(:project) { create(:project) } let(:params) do { team_domain: 'http://domain.tld', diff --git a/spec/models/integrations/slack_spec.rb b/spec/models/integrations/slack_spec.rb index ed282f1d39d..a12bc7f4831 100644 --- a/spec/models/integrations/slack_spec.rb +++ b/spec/models/integrations/slack_spec.rb @@ -3,142 +3,6 @@ require 'spec_helper' RSpec.describe Integrations::Slack do - it_behaves_like Integrations::SlackMattermostNotifier, "Slack" - - describe '#execute' do - let(:slack_integration) { create(:integrations_slack, branches_to_be_notified: 'all', project_id: project.id) } - let(:project) { create_default(:project, :repository, :wiki_repo) } - - before do - stub_request(:post, slack_integration.webhook) - end - - it 'uses only known events', :aggregate_failures do - described_class::SUPPORTED_EVENTS_FOR_USAGE_LOG.each do |action| - expect(Gitlab::UsageDataCounters::HLLRedisCounter.known_event?("i_ecosystem_slack_service_#{action}_notification")).to be true - end - end - - context 'hook data includes a user object' do - let_it_be(:user) { create_default(:user) } - - shared_examples 'increases the usage data counter' do |event_name| - subject(:execute) { slack_integration.execute(data) } - - it 'increases the usage data counter' do - expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: user.id).and_call_original - - execute - end - - it_behaves_like 'Snowplow event tracking' do - let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } - let(:category) { 'Integrations::Slack' } - let(:action) { 'perform_integrations_action' } - let(:namespace) { project.namespace } - let(:label) { 'redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly' } - let(:property) { event_name } - end - end - - context 'event is not supported for usage log' do - let_it_be(:pipeline) { create(:ci_pipeline) } - - let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } - - it 'does not increase the usage data counter' do - expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with('i_ecosystem_slack_service_pipeline_notification', values: user.id) - - slack_integration.execute(data) - end - end - - context 'issue notification' do - let_it_be(:issue) { create(:issue) } - - let(:data) { issue.to_hook_data(user) } - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_issue_notification' - end - - context 'push notification' do - let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) } - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_push_notification' - end - - context 'deployment notification' do - let_it_be(:deployment) { create(:deployment, user: user) } - - let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, deployment.status, Time.current) } - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_deployment_notification' - end - - context 'wiki_page notification' do - let(:wiki_page) { create(:wiki_page, wiki: project.wiki, message: 'user created page: Awesome wiki_page') } - - let(:data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') } - - before do - # Skip this method that is not relevant to this test to prevent having - # to update project which is frozen - allow(project.wiki).to receive(:after_wiki_activity) - end - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_wiki_page_notification' - end - - context 'merge_request notification' do - let_it_be(:merge_request) { create(:merge_request) } - - let(:data) { merge_request.to_hook_data(user) } - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_merge_request_notification' - end - - context 'note notification' do - let_it_be(:issue_note) { create(:note_on_issue, note: 'issue note') } - - let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) } - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_note_notification' - end - - context 'tag_push notification' do - let(:oldrev) { Gitlab::Git::BLANK_SHA } - let(:newrev) { '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b' } # gitlab-test: git rev-parse refs/tags/v1.1.0 - let(:ref) { 'refs/tags/v1.1.0' } - let(:data) { Git::TagHooksService.new(project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref }).send(:push_data) } - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_tag_push_notification' - end - - context 'confidential note notification' do - let_it_be(:confidential_issue_note) { create(:note_on_issue, note: 'issue note', confidential: true) } - - let(:data) { Gitlab::DataBuilder::Note.build(confidential_issue_note, user) } - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_note_notification' - end - - context 'confidential issue notification' do - let_it_be(:issue) { create(:issue, confidential: true) } - - let(:data) { issue.to_hook_data(user) } - - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_issue_notification' - end - end - - context 'hook data does not include a user' do - let(:data) { Gitlab::DataBuilder::Pipeline.build(create(:ci_pipeline)) } - - it 'does not increase the usage data counter' do - expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event) - - slack_integration.execute(data) - end - end - end + it_behaves_like Integrations::SlackMattermostNotifier, 'Slack' + it_behaves_like Integrations::BaseSlackNotification, factory: :integrations_slack end diff --git a/spec/models/integrations/teamcity_spec.rb b/spec/models/integrations/teamcity_spec.rb index da559264c1e..e32088a2f79 100644 --- a/spec/models/integrations/teamcity_spec.rb +++ b/spec/models/integrations/teamcity_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do let(:teamcity_url) { 'https://gitlab.teamcity.com' } let(:teamcity_full_url) { 'https://gitlab.teamcity.com/httpAuth/app/rest/builds/branch:unspecified:any,revision:123' } - let(:project) { create(:project) } + let_it_be(:project) { create(:project) } subject(:integration) do described_class.create!( @@ -22,6 +22,10 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do ) end + it_behaves_like Integrations::BaseCi + + it_behaves_like Integrations::ResetSecretFields + include_context Integrations::EnableSslVerification do describe '#enable_ssl_verification' do before do @@ -120,50 +124,6 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do end end - describe 'Callbacks' do - let(:teamcity_integration) { integration } - - describe 'before_validation :reset_password' do - context 'when a password was previously set' do - it 'resets password if url changed' do - teamcity_integration.teamcity_url = 'http://gitlab1.com' - teamcity_integration.valid? - - expect(teamcity_integration.password).to be_nil - end - - it 'does not reset password if username changed' do - teamcity_integration.username = 'some_name' - teamcity_integration.valid? - - expect(teamcity_integration.password).to eq('password') - end - - it "does not reset password if new url is set together with password, even if it's the same password" do - teamcity_integration.teamcity_url = 'http://gitlab_edited.com' - teamcity_integration.password = 'password' - teamcity_integration.valid? - - expect(teamcity_integration.password).to eq('password') - expect(teamcity_integration.teamcity_url).to eq('http://gitlab_edited.com') - end - end - - it 'saves password if new url is set together with password when no password was previously set' do - teamcity_integration.password = nil - - teamcity_integration.teamcity_url = 'http://gitlab_edited.com' - teamcity_integration.password = 'password' - teamcity_integration.save! - - expect(teamcity_integration.reload).to have_attributes( - teamcity_url: 'http://gitlab_edited.com', - password: 'password' - ) - end - end - end - describe '#build_page' do it 'returns the contents of the reactive cache' do stub_reactive_cache(integration, { build_page: 'foo' }, 'sha', 'ref') diff --git a/spec/models/integrations/zentao_spec.rb b/spec/models/integrations/zentao_spec.rb index 1a32453819d..2fa4df0e900 100644 --- a/spec/models/integrations/zentao_spec.rb +++ b/spec/models/integrations/zentao_spec.rb @@ -7,15 +7,14 @@ RSpec.describe Integrations::Zentao do let(:api_url) { 'https://jihudemo.zentao.net' } let(:api_token) { 'ZENTAO_TOKEN' } let(:zentao_product_xid) { '3' } - let(:zentao_integration) { create(:zentao_integration) } + let(:zentao_integration) { build(:zentao_integration, project: project) } + let_it_be(:project) { create(:project, :repository) } it_behaves_like Integrations::ResetSecretFields do let(:integration) { zentao_integration } end describe 'set_default_data' do - let(:project) { create(:project, :repository) } - context 'when gitlab.yml was initialized' do it 'is prepopulated with the settings' do settings = { @@ -35,7 +34,6 @@ RSpec.describe Integrations::Zentao do end describe '#create' do - let(:project) { create(:project, :repository) } let(:params) do { project: project, |