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
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/project_services')
-rw-r--r--spec/models/project_services/bugzilla_service_spec.rb35
-rw-r--r--spec/models/project_services/buildkite_service_spec.rb151
-rw-r--r--spec/models/project_services/chat_notification_service_spec.rb282
-rw-r--r--spec/models/project_services/custom_issue_tracker_service_spec.rb35
-rw-r--r--spec/models/project_services/data_fields_spec.rb156
-rw-r--r--spec/models/project_services/discord_service_spec.rb82
-rw-r--r--spec/models/project_services/drone_ci_service_spec.rb148
-rw-r--r--spec/models/project_services/ewm_service_spec.rb61
-rw-r--r--spec/models/project_services/external_wiki_service_spec.rb59
-rw-r--r--spec/models/project_services/flowdock_service_spec.rb58
-rw-r--r--spec/models/project_services/hangouts_chat_service_spec.rb15
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb36
-rw-r--r--spec/models/project_services/irker_service_spec.rb76
-rw-r--r--spec/models/project_services/issue_tracker_data_spec.rb9
-rw-r--r--spec/models/project_services/issue_tracker_service_spec.rb34
-rw-r--r--spec/models/project_services/jenkins_service_spec.rb255
-rw-r--r--spec/models/project_services/jira_service_spec.rb976
-rw-r--r--spec/models/project_services/jira_tracker_data_spec.rb19
-rw-r--r--spec/models/project_services/mattermost_service_spec.rb7
-rw-r--r--spec/models/project_services/mattermost_slash_commands_service_spec.rb132
-rw-r--r--spec/models/project_services/microsoft_teams_service_spec.rb360
-rw-r--r--spec/models/project_services/open_project_service_spec.rb35
-rw-r--r--spec/models/project_services/open_project_tracker_data_spec.rb19
-rw-r--r--spec/models/project_services/packagist_service_spec.rb48
-rw-r--r--spec/models/project_services/pipelines_email_service_spec.rb305
-rw-r--r--spec/models/project_services/pivotaltracker_service_spec.rb101
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb27
-rw-r--r--spec/models/project_services/pushover_service_spec.rb71
-rw-r--r--spec/models/project_services/redmine_service_spec.rb53
-rw-r--r--spec/models/project_services/slack_service_spec.rb133
-rw-r--r--spec/models/project_services/slack_slash_commands_service_spec.rb50
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb334
-rw-r--r--spec/models/project_services/unify_circuit_service_spec.rb16
-rw-r--r--spec/models/project_services/webex_teams_service_spec.rb14
-rw-r--r--spec/models/project_services/youtrack_service_spec.rb45
35 files changed, 9 insertions, 4228 deletions
diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb
deleted file mode 100644
index 560c7c3ee83..00000000000
--- a/spec/models/project_services/bugzilla_service_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BugzillaService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
- it { is_expected.to validate_presence_of(:new_issue_url) }
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- it_behaves_like 'issue tracker service URL attribute', :new_issue_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- it { is_expected.not_to validate_presence_of(:new_issue_url) }
- end
- end
-end
diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb
deleted file mode 100644
index f6bf1551bf0..00000000000
--- a/spec/models/project_services/buildkite_service_spec.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BuildkiteService, :use_clean_rails_memory_store_caching do
- include ReactiveCachingHelpers
- include StubRequests
-
- let(:project) { create(:project) }
-
- subject(:service) do
- described_class.create!(
- project: project,
- properties: {
- service_hook: true,
- project_url: 'https://buildkite.com/organization-name/example-pipeline',
- token: 'secret-sauce-webhook-token:secret-sauce-status-token'
- }
- )
- end
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:token) }
- it_behaves_like 'issue tracker service URL attribute', :project_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:token) }
- end
- end
-
- describe '.supported_events' do
- it 'supports push, merge_request, and tag_push events' do
- expect(service.supported_events).to eq %w(push merge_request tag_push)
- end
- end
-
- describe 'commits methods' do
- before do
- allow(project).to receive(:default_branch).and_return('default-brancho')
- end
-
- it 'always activates SSL verification after saved' do
- service.create_service_hook(enable_ssl_verification: false)
-
- service.enable_ssl_verification = false
- service.active = true
-
- expect { service.save! }
- .to change { service.service_hook.enable_ssl_verification }.from(false).to(true)
- end
-
- describe '#webhook_url' do
- it 'returns the webhook url' do
- expect(service.webhook_url).to eq(
- 'https://webhook.buildkite.com/deliver/secret-sauce-webhook-token'
- )
- end
- end
-
- describe '#commit_status_path' do
- it 'returns the correct status page' do
- expect(service.commit_status_path('2ab7834c')).to eq(
- 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=2ab7834c'
- )
- end
- end
-
- describe '#build_page' do
- it 'returns the correct build page' do
- expect(service.build_page('2ab7834c', nil)).to eq(
- 'https://buildkite.com/organization-name/example-pipeline/builds?commit=2ab7834c'
- )
- end
- end
-
- describe '#commit_status' do
- it 'returns the contents of the reactive cache' do
- stub_reactive_cache(service, { commit_status: 'foo' }, 'sha', 'ref')
-
- expect(service.commit_status('sha', 'ref')).to eq('foo')
- end
- end
-
- describe '#calculate_reactive_cache' do
- describe '#commit_status' do
- let(:buildkite_full_url) do
- 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=123'
- end
-
- subject { service.calculate_reactive_cache('123', 'unused')[:commit_status] }
-
- it 'sets commit status to :error when status is 500' do
- stub_request(status: 500)
-
- is_expected.to eq(:error)
- end
-
- it 'sets commit status to :error when status is 404' do
- stub_request(status: 404)
-
- is_expected.to eq(:error)
- end
-
- it 'passes through build status untouched when status is 200' do
- stub_request(body: %q({"status":"Great Success"}))
-
- is_expected.to eq('Great Success')
- end
-
- Gitlab::HTTP::HTTP_ERRORS.each do |http_error|
- it "sets commit status to :error with a #{http_error.name} error" do
- WebMock.stub_request(:get, buildkite_full_url)
- .to_raise(http_error)
-
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(instance_of(http_error), project_id: project.id)
-
- is_expected.to eq(:error)
- end
- end
- end
- end
- end
-
- def stub_request(status: 200, body: nil)
- body ||= %q({"status":"success"})
-
- stub_full_request(buildkite_full_url)
- .to_return(status: status,
- headers: { 'Content-Type' => 'application/json' },
- body: body)
- end
-end
diff --git a/spec/models/project_services/chat_notification_service_spec.rb b/spec/models/project_services/chat_notification_service_spec.rb
deleted file mode 100644
index 62f97873a06..00000000000
--- a/spec/models/project_services/chat_notification_service_spec.rb
+++ /dev/null
@@ -1,282 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ChatNotificationService do
- describe 'Associations' do
- before do
- allow(subject).to receive(:activated?).and_return(true)
- end
-
- it { is_expected.to validate_presence_of :webhook }
- end
-
- describe 'validations' do
- it { is_expected.to validate_inclusion_of(:labels_to_be_notified_behavior).in_array(%w[match_any match_all]).allow_blank }
- end
-
- describe '#can_test?' do
- context 'with empty repository' do
- it 'returns true' do
- subject.project = create(:project, :empty_repo)
-
- expect(subject.can_test?).to be true
- end
- end
-
- context 'with repository' do
- it 'returns true' do
- subject.project = create(:project, :repository)
-
- expect(subject.can_test?).to be true
- end
- end
- end
-
- describe '#execute' do
- subject(:chat_service) { described_class.new }
-
- let_it_be(:project) { create(:project, :repository) }
-
- let(:user) { create(:user) }
- let(:webhook_url) { 'https://example.gitlab.com/' }
- let(:data) { Gitlab::DataBuilder::Push.build_sample(subject.project, user) }
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
-
- subject.active = true
- end
-
- context 'with a repository' do
- it 'returns true' do
- expect(chat_service).to receive(:notify).and_return(true)
- expect(chat_service.execute(data)).to be true
- end
- end
-
- context 'with an empty repository' do
- it 'returns true' do
- subject.project = create(:project, :empty_repo)
-
- expect(chat_service).to receive(:notify).and_return(true)
- expect(chat_service.execute(data)).to be true
- end
- end
-
- context 'with a project with name containing spaces' do
- it 'does not remove spaces' do
- allow(project).to receive(:full_name).and_return('Project Name')
-
- expect(chat_service).to receive(:get_message).with(any_args, hash_including(project_name: 'Project Name'))
- chat_service.execute(data)
- end
- 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(:issue) { create(:labeled_issue, project: project, labels: [label, label_2, label_3]) }
- let_it_be(:note) { create(:note, noteable: issue, project: project) }
-
- let(:data) { Gitlab::DataBuilder::Note.build(note, user) }
-
- it 'notifies the chat service' do
- expect(chat_service).to receive(:notify).with(any_args)
-
- chat_service.execute(data)
- end
-
- shared_examples 'notifies the chat service' do
- specify do
- expect(chat_service).to receive(:notify).with(any_args)
-
- chat_service.execute(data)
- end
- end
-
- shared_examples 'does not notify the chat service' do
- specify do
- expect(chat_service).not_to receive(:notify).with(any_args)
-
- chat_service.execute(data)
- end
- end
-
- context 'when labels_to_be_notified_behavior is not defined' do
- subject(:chat_service) { described_class.new(labels_to_be_notified: label_filter) }
-
- context 'no matching labels' do
- let(:label_filter) { '~some random label' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'only one label matches' do
- let(:label_filter) { '~some random label, ~Bug' }
-
- it_behaves_like 'notifies the chat service'
- end
- end
-
- context 'when labels_to_be_notified_behavior is blank' do
- subject(:chat_service) { described_class.new(labels_to_be_notified: label_filter, labels_to_be_notified_behavior: '') }
-
- context 'no matching labels' do
- let(:label_filter) { '~some random label' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'only one label matches' do
- let(:label_filter) { '~some random label, ~Bug' }
-
- it_behaves_like 'notifies the chat service'
- end
- end
-
- context 'when labels_to_be_notified_behavior is match_any' do
- subject(:chat_service) do
- described_class.new(
- labels_to_be_notified: label_filter,
- labels_to_be_notified_behavior: 'match_any'
- )
- end
-
- context 'no label filter' do
- let(:label_filter) { nil }
-
- it_behaves_like 'notifies the chat service'
- end
-
- context 'no matching labels' do
- let(:label_filter) { '~some random label' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'only one label matches' do
- let(:label_filter) { '~some random label, ~Bug' }
-
- it_behaves_like 'notifies the chat service'
- end
- end
-
- context 'when labels_to_be_notified_behavior is match_all' do
- subject(:chat_service) do
- described_class.new(
- labels_to_be_notified: label_filter,
- labels_to_be_notified_behavior: 'match_all'
- )
- end
-
- context 'no label filter' do
- let(:label_filter) { nil }
-
- it_behaves_like 'notifies the chat service'
- end
-
- context 'no matching labels' do
- let(:label_filter) { '~some random label' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'only one label matches' do
- let(:label_filter) { '~some random label, ~Bug' }
-
- it_behaves_like 'does not notify the chat service'
- end
-
- context 'labels matches exactly' do
- let(:label_filter) { '~Bug, ~Backend, ~Community contribution' }
-
- it_behaves_like 'notifies the chat service'
- end
-
- context 'labels matches but object has more' do
- let(:label_filter) { '~Bug, ~Backend' }
-
- it_behaves_like 'notifies the chat service'
- end
-
- context 'labels are distributed on multiple objects' do
- let(:label_filter) { '~Bug, ~Backend' }
- let(:data) do
- Gitlab::DataBuilder::Note.build(note, user).merge({
- issue: {
- labels: [
- { title: 'Bug' }
- ]
- },
- merge_request: {
- labels: [
- {
- title: 'Backend'
- }
- ]
- }
- })
- end
-
- it_behaves_like 'does not notify the chat service'
- end
- end
- end
-
- context 'with "channel" property' do
- before do
- allow(chat_service).to receive(:channel).and_return(channel)
- end
-
- context 'empty string' do
- let(:channel) { '' }
-
- it 'does not include the channel' do
- expect(chat_service).to receive(:notify).with(any_args, hash_excluding(:channel)).and_return(true)
- expect(chat_service.execute(data)).to be(true)
- end
- end
-
- context 'empty spaces' do
- let(:channel) { ' ' }
-
- it 'does not include the channel' do
- expect(chat_service).to receive(:notify).with(any_args, hash_excluding(:channel)).and_return(true)
- expect(chat_service.execute(data)).to be(true)
- end
- end
- end
-
- shared_examples 'with channel specified' do |channel, expected_channels|
- before do
- allow(chat_service).to receive(:push_channel).and_return(channel)
- end
-
- it 'notifies all channels' do
- expect(chat_service).to receive(:notify).with(any_args, hash_including(channel: expected_channels)).and_return(true)
- expect(chat_service.execute(data)).to be(true)
- end
- end
-
- context 'with single channel specified' do
- it_behaves_like 'with channel specified', 'slack-integration', ['slack-integration']
- end
-
- context 'with multiple channel names specified' do
- it_behaves_like 'with channel specified', 'slack-integration,#slack-test', ['slack-integration', '#slack-test']
- end
-
- context 'with multiple channel names with spaces specified' do
- it_behaves_like 'with channel specified', 'slack-integration, #slack-test, @UDLP91W0A', ['slack-integration', '#slack-test', '@UDLP91W0A']
- end
- end
-end
diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb
deleted file mode 100644
index 881ae60a680..00000000000
--- a/spec/models/project_services/custom_issue_tracker_service_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe CustomIssueTrackerService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
- it { is_expected.to validate_presence_of(:new_issue_url) }
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- it_behaves_like 'issue tracker service URL attribute', :new_issue_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- it { is_expected.not_to validate_presence_of(:new_issue_url) }
- end
- end
-end
diff --git a/spec/models/project_services/data_fields_spec.rb b/spec/models/project_services/data_fields_spec.rb
deleted file mode 100644
index d3e6afe4978..00000000000
--- a/spec/models/project_services/data_fields_spec.rb
+++ /dev/null
@@ -1,156 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe DataFields do
- let(:url) { 'http://url.com' }
- let(:username) { 'username_one' }
- let(:properties) do
- { url: url, username: username }
- end
-
- shared_examples 'data fields' do
- describe '#arg' do
- it 'returns an argument correctly' do
- expect(service.url).to eq(url)
- end
- end
-
- describe '{arg}_changed?' do
- it 'returns false when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
-
- it 'returns true when the property has been assigned a different value' do
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been assigned a different value twice' do
- service.url = "http://example.com"
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns false when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
- end
-
- describe '{arg}_touched?' do
- it 'returns false when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
-
- it 'returns true when the property has been assigned a different value' do
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been assigned a different value twice' do
- service.url = "http://example.com"
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- expect(service.url_touched?).to be_truthy
- end
-
- it 'returns false when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
- end
-
- describe 'data_fields_present?' do
- it 'returns true from the issue tracker service' do
- expect(service.data_fields_present?).to be true
- end
- end
- end
-
- context 'when data are stored in data_fields' do
- let(:service) do
- create(:jira_service, url: url, username: username)
- end
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to be_nil
- end
- end
- end
-
- context 'when service and data_fields are not persisted' do
- let(:service) do
- JiraService.new
- end
-
- describe 'data_fields_present?' do
- it 'returns true' do
- expect(service.data_fields_present?).to be true
- end
- end
- end
-
- context 'when data are stored in properties' do
- let(:service) { create(:jira_service, :without_properties_callback, properties: properties) }
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_was).to be_nil
- end
-
- it 'returns initial value when the property has been assigned a different value' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to eq('http://url.com')
- end
-
- it 'returns initial value when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_was).to eq('http://url.com')
- end
- end
- end
-
- context 'when data are stored in both properties and data_fields' do
- let(:service) do
- create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |integration|
- create(:jira_tracker_data, properties.merge(integration: integration))
- end
- end
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to be_nil
- end
- end
- end
-end
diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb
deleted file mode 100644
index ffe0a36dcdc..00000000000
--- a/spec/models/project_services/discord_service_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe DiscordService do
- it_behaves_like "chat service", "Discord notifications" do
- let(:client) { Discordrb::Webhooks::Client }
- let(:client_arguments) { { url: webhook_url } }
- let(:payload) do
- {
- embeds: [
- include(
- author: include(name: be_present),
- description: be_present
- )
- ]
- }
- end
- end
-
- describe '#execute' do
- include StubRequests
-
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:webhook_url) { "https://example.gitlab.com/" }
-
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- before do
- allow(subject).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- it 'uses the right embed parameters' do
- builder = Discordrb::Webhooks::Builder.new
-
- allow_next_instance_of(Discordrb::Webhooks::Client) do |client|
- allow(client).to receive(:execute).and_yield(builder)
- end
-
- subject.execute(sample_data)
-
- expect(builder.to_json_hash[:embeds].first).to include(
- description: start_with("#{user.name} pushed to branch [master](http://localhost/#{project.namespace.path}/#{project.path}/commits/master) of"),
- author: hash_including(
- icon_url: start_with('https://www.gravatar.com/avatar/'),
- name: user.name
- )
- )
- end
-
- context 'DNS rebind to local address' do
- before do
- stub_dns(webhook_url, ip_address: '192.168.2.120')
- end
-
- it 'does not allow DNS rebinding' do
- expect { subject.execute(sample_data) }.to raise_error(ArgumentError, /is blocked/)
- end
- end
-
- context 'when the Discord request fails' do
- before do
- WebMock.stub_request(:post, webhook_url).to_return(status: 400)
- end
-
- it 'logs an error and returns false' do
- expect(subject).to receive(:log_error).with('400 Bad Request')
- expect(subject.execute(sample_data)).to be(false)
- end
- end
- end
-end
diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb
deleted file mode 100644
index 9aaf4f7a644..00000000000
--- a/spec/models/project_services/drone_ci_service_spec.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe DroneCiService, :use_clean_rails_memory_store_caching do
- include ReactiveCachingHelpers
-
- describe 'associations' do
- it { is_expected.to belong_to(:project) }
- it { is_expected.to have_one(:service_hook) }
- end
-
- describe 'validations' do
- context 'active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:token) }
- it { is_expected.to validate_presence_of(:drone_url) }
- it_behaves_like 'issue tracker service URL attribute', :drone_url
- end
-
- context 'inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:token) }
- it { is_expected.not_to validate_presence_of(:drone_url) }
- end
- end
-
- shared_context :drone_ci_service do
- let(:drone) { DroneCiService.new }
- let(:project) { create(:project, :repository, name: 'project') }
- let(:path) { project.full_path }
- let(:drone_url) { 'http://drone.example.com' }
- let(:sha) { '2ab7834c' }
- let(:branch) { 'dev' }
- let(:token) { 'secret' }
- let(:iid) { rand(1..9999) }
-
- # URL's
- let(:build_page) { "#{drone_url}/gitlab/#{path}/redirect/commits/#{sha}?branch=#{branch}" }
- let(:commit_status_path) { "#{drone_url}/gitlab/#{path}/commits/#{sha}?branch=#{branch}&access_token=#{token}" }
-
- before do
- allow(drone).to receive_messages(
- project_id: project.id,
- project: project,
- active: true,
- drone_url: drone_url,
- token: token
- )
- end
-
- def stub_request(status: 200, body: nil)
- body ||= %q({"status":"success"})
-
- WebMock.stub_request(:get, commit_status_path).to_return(
- status: status,
- headers: { 'Content-Type' => 'application/json' },
- body: body
- )
- end
- end
-
- describe "service page/path methods" do
- include_context :drone_ci_service
-
- it { expect(drone.build_page(sha, branch)).to eq(build_page) }
- it { expect(drone.commit_status_path(sha, branch)).to eq(commit_status_path) }
- end
-
- describe '#commit_status' do
- include_context :drone_ci_service
-
- it 'returns the contents of the reactive cache' do
- stub_reactive_cache(drone, { commit_status: 'foo' }, 'sha', 'ref')
-
- expect(drone.commit_status('sha', 'ref')).to eq('foo')
- end
- end
-
- describe '#calculate_reactive_cache' do
- include_context :drone_ci_service
-
- describe '#commit_status' do
- subject { drone.calculate_reactive_cache(sha, branch)[:commit_status] }
-
- it 'sets commit status to :error when status is 500' do
- stub_request(status: 500)
-
- is_expected.to eq(:error)
- end
-
- it 'sets commit status to :error when status is 404' do
- stub_request(status: 404)
-
- is_expected.to eq(:error)
- end
-
- Gitlab::HTTP::HTTP_ERRORS.each do |http_error|
- it "sets commit status to :error with a #{http_error.name} error" do
- WebMock.stub_request(:get, commit_status_path)
- .to_raise(http_error)
-
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(instance_of(http_error), project_id: project.id)
-
- is_expected.to eq(:error)
- end
- end
-
- {
- "killed" => :canceled,
- "failure" => :failed,
- "error" => :failed,
- "success" => "success"
- }.each do |drone_status, our_status|
- it "sets commit status to #{our_status.inspect} when returned status is #{drone_status.inspect}" do
- stub_request(body: %Q({"status":"#{drone_status}"}))
-
- is_expected.to eq(our_status)
- end
- end
- end
- end
-
- describe "execute" do
- include_context :drone_ci_service
-
- let(:user) { create(:user, username: 'username') }
- let(:push_sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- it do
- service_hook = double
- expect(service_hook).to receive(:execute)
- expect(drone).to receive(:service_hook).and_return(service_hook)
-
- drone.execute(push_sample_data)
- end
- end
-end
diff --git a/spec/models/project_services/ewm_service_spec.rb b/spec/models/project_services/ewm_service_spec.rb
deleted file mode 100644
index 311c456569e..00000000000
--- a/spec/models/project_services/ewm_service_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe EwmService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
- it { is_expected.to validate_presence_of(:new_issue_url) }
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- it_behaves_like 'issue tracker service URL attribute', :new_issue_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- it { is_expected.not_to validate_presence_of(:new_issue_url) }
- end
- end
-
- describe "ReferencePatternValidation" do
- it "extracts bug" do
- expect(described_class.reference_pattern.match("This is bug 123")[:issue]).to eq("bug 123")
- end
-
- it "extracts task" do
- expect(described_class.reference_pattern.match("This is task 123.")[:issue]).to eq("task 123")
- end
-
- it "extracts work item" do
- expect(described_class.reference_pattern.match("This is work item 123 now")[:issue]).to eq("work item 123")
- end
-
- it "extracts workitem" do
- expect(described_class.reference_pattern.match("workitem 123 at the beginning")[:issue]).to eq("workitem 123")
- end
-
- it "extracts defect" do
- expect(described_class.reference_pattern.match("This is defect 123 defect")[:issue]).to eq("defect 123")
- end
-
- it "extracts rtcwi" do
- expect(described_class.reference_pattern.match("This is rtcwi 123")[:issue]).to eq("rtcwi 123")
- end
- end
-end
diff --git a/spec/models/project_services/external_wiki_service_spec.rb b/spec/models/project_services/external_wiki_service_spec.rb
deleted file mode 100644
index c6891401a0f..00000000000
--- a/spec/models/project_services/external_wiki_service_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ExternalWikiService do
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:external_wiki_url) }
- it_behaves_like 'issue tracker service URL attribute', :external_wiki_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:external_wiki_url) }
- end
- end
-
- describe 'test' do
- before do
- subject.properties['external_wiki_url'] = url
- end
-
- let(:url) { 'http://foo' }
- let(:data) { nil }
- let(:result) { subject.test(data) }
-
- context 'the URL is not reachable' do
- before do
- WebMock.stub_request(:get, url).to_return(status: 404, body: 'not a page')
- end
-
- it 'is not successful' do
- expect(result[:success]).to be_falsey
- end
- end
-
- context 'the URL is reachable' do
- before do
- WebMock.stub_request(:get, url).to_return(status: 200, body: 'foo')
- end
-
- it 'is successful' do
- expect(result[:success]).to be_truthy
- end
- end
- end
-end
diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb
deleted file mode 100644
index 94a49fb3080..00000000000
--- a/spec/models/project_services/flowdock_service_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe FlowdockService do
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:token) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:token) }
- end
- end
-
- describe "Execute" do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
-
- before do
- @flowdock_service = described_class.new
- allow(@flowdock_service).to receive_messages(
- project_id: project.id,
- project: project,
- service_hook: true,
- token: 'verySecret'
- )
- @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
- @api_url = 'https://api.flowdock.com/v1/messages'
- WebMock.stub_request(:post, @api_url)
- end
-
- it "calls FlowDock API" do
- @flowdock_service.execute(@sample_data)
- @sample_data[:commits].each do |commit|
- # One request to Flowdock per new commit
- next if commit[:id] == @sample_data[:before]
-
- expect(WebMock).to have_requested(:post, @api_url).with(
- body: /#{commit[:id]}.*#{project.path}/
- ).once
- end
- end
- end
-end
diff --git a/spec/models/project_services/hangouts_chat_service_spec.rb b/spec/models/project_services/hangouts_chat_service_spec.rb
deleted file mode 100644
index 9d3bd457fc8..00000000000
--- a/spec/models/project_services/hangouts_chat_service_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe HangoutsChatService do
- it_behaves_like "chat service", "Hangouts Chat" do
- let(:client) { HangoutsChat::Sender }
- let(:client_arguments) { webhook_url }
- let(:payload) do
- {
- text: be_present
- }
- end
- end
-end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
deleted file mode 100644
index 42368c31ba0..00000000000
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# HipchatService is partially removed and it will be remove completely
-# after the deletion of all the database records.
-# https://gitlab.com/gitlab-org/gitlab/-/issues/27954
-RSpec.describe HipchatService do
- let_it_be(:project) { create(:project) }
-
- subject(:service) { described_class.new(project: project) }
-
- it { is_expected.to be_valid }
-
- describe '#to_param' do
- subject { service.to_param }
-
- it { is_expected.to eq('hipchat') }
- end
-
- describe '#supported_events' do
- subject { service.supported_events }
-
- it { is_expected.to be_empty }
- end
-
- describe '#save' do
- it 'prevents records from being created or updated' do
- expect(service.save).to be_falsey
-
- expect(service.errors.full_messages).to include(
- 'HipChat endpoint is deprecated and should not be created or modified.'
- )
- end
- end
-end
diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb
deleted file mode 100644
index 07963947de8..00000000000
--- a/spec/models/project_services/irker_service_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require 'socket'
-require 'json'
-
-RSpec.describe IrkerService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:recipients) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:recipients) }
- end
- end
-
- describe 'Execute' do
- let(:irker) { described_class.new }
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- let(:recipients) { '#commits irc://test.net/#test ftp://bad' }
- let(:colorize_messages) { '1' }
-
- before do
- @irker_server = TCPServer.new 'localhost', 0
-
- allow(irker).to receive_messages(
- active: true,
- project: project,
- project_id: project.id,
- service_hook: true,
- server_host: @irker_server.addr[2],
- server_port: @irker_server.addr[1],
- default_irc_uri: 'irc://chat.freenode.net/',
- recipients: recipients,
- colorize_messages: colorize_messages)
-
- irker.valid?
- end
-
- after do
- @irker_server.close
- end
-
- it 'sends valid JSON messages to an Irker listener', :sidekiq_might_not_need_inline do
- irker.execute(sample_data)
-
- conn = @irker_server.accept
- conn.each_line do |line|
- msg = Gitlab::Json.parse(line.chomp("\n"))
- expect(msg.keys).to match_array(%w(to privmsg))
- expect(msg['to']).to match_array(["irc://chat.freenode.net/#commits",
- "irc://test.net/#test"])
- end
- conn.close
- end
- end
-end
diff --git a/spec/models/project_services/issue_tracker_data_spec.rb b/spec/models/project_services/issue_tracker_data_spec.rb
deleted file mode 100644
index a229285f09b..00000000000
--- a/spec/models/project_services/issue_tracker_data_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IssueTrackerData do
- describe 'associations' do
- it { is_expected.to belong_to :integration }
- end
-end
diff --git a/spec/models/project_services/issue_tracker_service_spec.rb b/spec/models/project_services/issue_tracker_service_spec.rb
deleted file mode 100644
index 5b12c7330b8..00000000000
--- a/spec/models/project_services/issue_tracker_service_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IssueTrackerService do
- describe 'Validations' do
- let(:project) { create :project }
-
- describe 'only one issue tracker per project' do
- let(:service) { RedmineService.new(project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) }
-
- before do
- create(:custom_issue_tracker_service, project: project)
- end
-
- context 'when service is changed manually by user' do
- it 'executes the validation' do
- valid = service.valid?(:manual_change)
-
- expect(valid).to be_falsey
- expect(service.errors[:base]).to include(
- 'Another issue tracker is already in use. Only one issue tracker service can be active at a time'
- )
- end
- end
-
- context 'when service is changed internally' do
- it 'does not execute the validation' do
- expect(service.valid?).to be_truthy
- end
- end
- end
- end
-end
diff --git a/spec/models/project_services/jenkins_service_spec.rb b/spec/models/project_services/jenkins_service_spec.rb
deleted file mode 100644
index 4663e41736a..00000000000
--- a/spec/models/project_services/jenkins_service_spec.rb
+++ /dev/null
@@ -1,255 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe JenkinsService do
- let(:project) { create(:project) }
- let(:jenkins_url) { 'http://jenkins.example.com/' }
- let(:jenkins_hook_url) { jenkins_url + 'project/my_project' }
- let(:jenkins_username) { 'u$er name%2520' }
- let(:jenkins_password) { 'pas$ word' }
-
- let(:jenkins_params) do
- {
- active: true,
- project: project,
- properties: {
- password: jenkins_password,
- username: jenkins_username,
- jenkins_url: jenkins_url,
- project_name: 'my_project'
- }
- }
- end
-
- let(:jenkins_authorization) { "Basic " + ::Base64.strict_encode64(jenkins_username + ':' + jenkins_password) }
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'username validation' do
- before do
- @jenkins_service = described_class.create!(
- active: active,
- project: project,
- properties: {
- jenkins_url: 'http://jenkins.example.com/',
- password: 'password',
- username: 'username',
- project_name: 'my_project'
- }
- )
- end
-
- subject { @jenkins_service }
-
- context 'when the service is active' do
- let(:active) { true }
-
- 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
-
- context 'when password was touched' do
- before do
- allow(subject).to receive(:password_touched?).and_return(true)
- end
-
- it { is_expected.to validate_presence_of :username }
- end
-
- 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 the service is inactive' do
- let(:active) { false }
-
- it { is_expected.not_to validate_presence_of :username }
- end
- end
-
- describe '#hook_url' do
- let(:username) { nil }
- let(:password) { nil }
- let(:jenkins_service) do
- described_class.new(
- project: project,
- properties: {
- jenkins_url: jenkins_url,
- project_name: 'my_project',
- username: username,
- password: password
- }
- )
- end
-
- subject { jenkins_service.hook_url }
-
- context 'when the jenkins_url has no relative path' do
- let(:jenkins_url) { 'http://jenkins.example.com/' }
-
- it { is_expected.to eq('http://jenkins.example.com/project/my_project') }
- end
-
- context 'when the jenkins_url has relative path' do
- let(:jenkins_url) { 'http://organization.example.com/jenkins' }
-
- it { is_expected.to eq('http://organization.example.com/jenkins/project/my_project') }
- end
-
- context 'userinfo is missing and username and password are set' do
- let(:jenkins_url) { 'http://organization.example.com/jenkins' }
- let(:username) { 'u$ername' }
- let(:password) { 'pas$ word' }
-
- it { is_expected.to eq('http://u%24ername:pas%24%20word@organization.example.com/jenkins/project/my_project') }
- end
-
- context 'userinfo is provided and username and password are set' do
- let(:jenkins_url) { 'http://u:p@organization.example.com/jenkins' }
- let(:username) { 'username' }
- let(:password) { 'password' }
-
- it { is_expected.to eq('http://username:password@organization.example.com/jenkins/project/my_project') }
- end
-
- context 'userinfo is provided username and password are not set' do
- let(:jenkins_url) { 'http://u:p@organization.example.com/jenkins' }
-
- it { is_expected.to eq('http://u:p@organization.example.com/jenkins/project/my_project') }
- end
- end
-
- describe '#test' do
- it 'returns the right status' do
- user = create(:user, username: 'username')
- project = create(:project, name: 'project')
- push_sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
- jenkins_service = described_class.create!(jenkins_params)
- stub_request(:post, jenkins_hook_url).with(headers: { 'Authorization' => jenkins_authorization })
-
- result = jenkins_service.test(push_sample_data)
-
- expect(result).to eq({ success: true, result: '' })
- end
- 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(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
- let(:jenkins_service) { described_class.create!(jenkins_params) }
-
- before do
- stub_request(:post, jenkins_hook_url)
- end
-
- it 'invokes the Jenkins API' do
- jenkins_service.execute(push_sample_data)
-
- expect(a_request(:post, jenkins_hook_url)).to have_been_made.once
- end
-
- it 'adds default web hook headers to the request' do
- jenkins_service.execute(push_sample_data)
-
- expect(
- a_request(:post, jenkins_hook_url)
- .with(headers: { 'X-Gitlab-Event' => 'Push Hook', 'Authorization' => jenkins_authorization })
- ).to have_been_made.once
- end
-
- it 'request url contains properly serialized username and password' do
- jenkins_service.execute(push_sample_data)
-
- expect(
- a_request(:post, 'http://jenkins.example.com/project/my_project')
- .with(headers: { 'Authorization' => jenkins_authorization })
- ).to have_been_made.once
- end
- end
-
- describe 'Stored password invalidation' do
- let(:project) { create(:project) }
-
- context 'when a password was previously set' do
- before do
- @jenkins_service = 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_service.jenkins_url = 'http://jenkins-edited.example.com/'
- @jenkins_service.save!
- expect(@jenkins_service.password).to be_nil
- end
-
- it 'resets password if username is blank' do
- @jenkins_service.username = ''
- @jenkins_service.save!
- expect(@jenkins_service.password).to be_nil
- end
-
- it 'does not reset password if username changed' do
- @jenkins_service.username = 'some_name'
- @jenkins_service.save!
- expect(@jenkins_service.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_service.jenkins_url = 'http://jenkins_edited.example.com/'
- @jenkins_service.password = 'password'
- @jenkins_service.save!
- expect(@jenkins_service.password).to eq('password')
- expect(@jenkins_service.jenkins_url).to eq('http://jenkins_edited.example.com/')
- end
-
- it 'resets password if url changed, even if setter called multiple times' do
- @jenkins_service.jenkins_url = 'http://jenkins1.example.com/'
- @jenkins_service.jenkins_url = 'http://jenkins1.example.com/'
- @jenkins_service.save!
- expect(@jenkins_service.password).to be_nil
- end
- end
-
- context 'when no password was previously set' do
- before do
- @jenkins_service = 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_service.jenkins_url = 'http://jenkins_edited.example.com/'
- @jenkins_service.password = 'password'
- @jenkins_service.save!
- expect(@jenkins_service.password).to eq('password')
- expect(@jenkins_service.jenkins_url).to eq('http://jenkins_edited.example.com/')
- end
- end
- end
-end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
deleted file mode 100644
index 73e91bf9ea8..00000000000
--- a/spec/models/project_services/jira_service_spec.rb
+++ /dev/null
@@ -1,976 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe JiraService do
- include AssetsHelpers
-
- let_it_be(:project) { create(:project, :repository) }
-
- let(:current_user) { build_stubbed(:user) }
- let(:url) { 'http://jira.example.com' }
- let(:api_url) { 'http://api-jira.example.com' }
- let(:username) { 'jira-username' }
- let(:password) { 'jira-password' }
- let(:transition_id) { 'test27' }
- let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
- let(:jira_service) do
- described_class.new(
- project: project,
- url: url,
- username: username,
- password: password
- )
- end
-
- before do
- WebMock.stub_request(:get, /serverInfo/).to_return(body: server_info_results.to_json )
- end
-
- describe '#options' do
- let(:options) do
- {
- project: project,
- active: true,
- username: 'username',
- password: 'test',
- jira_issue_transition_id: 24,
- url: 'http://jira.test.com/path/'
- }
- end
-
- let(:service) { described_class.create!(options) }
-
- it 'sets the URL properly' do
- # jira-ruby gem parses the URI and handles trailing slashes fine:
- # https://github.com/sumoheavy/jira-ruby/blob/v1.7.0/lib/jira/http_client.rb#L62
- expect(service.options[:site]).to eq('http://jira.test.com/')
- end
-
- it 'leaves out trailing slashes in context' do
- expect(service.options[:context_path]).to eq('/path')
- end
-
- context 'username with trailing whitespaces' do
- before do
- options.merge!(username: 'username ')
- end
-
- it 'leaves out trailing whitespaces in username' do
- expect(service.options[:username]).to eq('username')
- end
- end
-
- it 'provides additional cookies to allow basic auth with oracle webgate' do
- expect(service.options[:use_cookies]).to eq(true)
- expect(service.options[:additional_cookies]).to eq(['OBBasicAuth=fromDialog'])
- end
-
- context 'using api URL' do
- before do
- options.merge!(api_url: 'http://jira.test.com/api_path/')
- end
-
- it 'leaves out trailing slashes in context' do
- expect(service.options[:context_path]).to eq('/api_path')
- end
- end
- end
-
- describe '#fields' do
- let(:service) { create(:jira_service) }
-
- subject(:fields) { service.fields }
-
- it 'returns custom fields' do
- expect(fields.pluck(:name)).to eq(%w[url api_url username password])
- end
- end
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe '.reference_pattern' do
- using RSpec::Parameterized::TableSyntax
-
- where(:key, :result) do
- '#123' | ''
- '1#23#12' | ''
- 'JIRA-1234A' | 'JIRA-1234'
- 'JIRA-1234-some_tag' | 'JIRA-1234'
- 'JIRA-1234_some_tag' | 'JIRA-1234'
- 'EXT_EXT-1234' | 'EXT_EXT-1234'
- 'EXT3_EXT-1234' | 'EXT3_EXT-1234'
- '3EXT_EXT-1234' | ''
- end
-
- with_them do
- specify do
- expect(described_class.reference_pattern.match(key).to_s).to eq(result)
- end
- end
- end
-
- describe '#create' do
- let(:params) do
- {
- project: project,
- url: url, api_url: api_url,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- subject { described_class.create!(params) }
-
- it 'does not store data into properties' do
- expect(subject.properties).to be_nil
- end
-
- it 'stores data in data_fields correctly' do
- service = subject
-
- expect(service.jira_tracker_data.url).to eq(url)
- expect(service.jira_tracker_data.api_url).to eq(api_url)
- expect(service.jira_tracker_data.username).to eq(username)
- expect(service.jira_tracker_data.password).to eq(password)
- expect(service.jira_tracker_data.jira_issue_transition_id).to eq(transition_id)
- expect(service.jira_tracker_data.deployment_cloud?).to be_truthy
- end
-
- context 'when loading serverInfo' do
- let!(:jira_service) { subject }
-
- context 'Cloud instance' do
- let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
-
- it 'is detected' do
- expect(jira_service.jira_tracker_data.deployment_cloud?).to be_truthy
- end
- end
-
- context 'Server instance' do
- let(:server_info_results) { { 'deploymentType' => 'Server' } }
-
- it 'is detected' do
- expect(jira_service.jira_tracker_data.deployment_server?).to be_truthy
- end
- end
-
- context 'Unknown instance' do
- let(:server_info_results) { { 'deploymentType' => 'FutureCloud' } }
-
- it 'is detected' do
- expect(jira_service.jira_tracker_data.deployment_unknown?).to be_truthy
- end
- end
- end
- end
-
- # 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(service.url).to eq(url)
- expect(service.api_url).to eq(api_url)
- expect(service.username).to eq(username)
- expect(service.password).to eq(password)
- expect(service.jira_issue_transition_id).to eq(transition_id)
- end
- end
-
- describe '#update' do
- context 'basic update' do
- let_it_be(:new_username) { 'new_username' }
- let_it_be(:new_url) { 'http://jira-new.example.com' }
-
- before do
- service.update!(username: new_username, url: new_url)
- end
-
- it 'leaves properties field emtpy' do
- # expect(service.reload.properties).to be_empty
- end
-
- it 'stores updated data in jira_tracker_data table' do
- data = service.jira_tracker_data.reload
-
- expect(data.url).to eq(new_url)
- expect(data.api_url).to eq(api_url)
- expect(data.username).to eq(new_username)
- expect(data.password).to eq(password)
- expect(data.jira_issue_transition_id).to eq(transition_id)
- end
- end
-
- context 'when updating the url, api_url, username, or password' do
- it 'updates deployment type' do
- service.update!(url: 'http://first.url')
- service.jira_tracker_data.update!(deployment_type: 'server')
-
- expect(service.jira_tracker_data.deployment_server?).to be_truthy
-
- service.update!(api_url: 'http://another.url')
- service.jira_tracker_data.reload
-
- expect(service.jira_tracker_data.deployment_cloud?).to be_truthy
- expect(WebMock).to have_requested(:get, /serverInfo/).twice
- end
-
- it 'calls serverInfo for url' do
- service.update!(url: 'http://first.url')
-
- expect(WebMock).to have_requested(:get, /serverInfo/)
- end
-
- it 'calls serverInfo for api_url' do
- service.update!(api_url: 'http://another.url')
-
- expect(WebMock).to have_requested(:get, /serverInfo/)
- end
-
- it 'calls serverInfo for username' do
- service.update!(username: 'test-user')
-
- expect(WebMock).to have_requested(:get, /serverInfo/)
- end
-
- it 'calls serverInfo for password' do
- service.update!(password: 'test-password')
-
- expect(WebMock).to have_requested(:get, /serverInfo/)
- end
- end
-
- context 'when not updating the url, api_url, username, or password' do
- it 'does not update deployment type' do
- expect {service.update!(jira_issue_transition_id: 'jira_issue_transition_id')}.to raise_error(ActiveRecord::RecordInvalid)
-
- expect(WebMock).not_to have_requested(:get, /serverInfo/)
- end
- end
-
- context 'when not allowed to test an instance or group' do
- it 'does not update deployment type' do
- allow(service).to receive(:can_test?).and_return(false)
-
- service.update!(url: 'http://first.url')
-
- expect(WebMock).not_to have_requested(:get, /serverInfo/)
- end
- end
-
- context 'stored password invalidation' do
- context 'when a password was previously set' do
- context 'when only web url present' do
- let(:data_params) do
- {
- url: url, api_url: nil,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- it 'resets password if url changed' do
- service
- service.url = 'http://jira_edited.example.com'
- service.save!
-
- expect(service.reload.url).to eq('http://jira_edited.example.com')
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if url "changed" to the same url as before' do
- service.url = 'http://jira.example.com'
- service.save!
-
- expect(service.reload.url).to eq('http://jira.example.com')
- expect(service.password).not_to be_nil
- end
-
- it 'resets password if url not changed but api url added' do
- service.api_url = 'http://jira_edited.example.com/rest/api/2'
- service.save!
-
- expect(service.reload.api_url).to eq('http://jira_edited.example.com/rest/api/2')
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if new url is set together with password, even if it\'s the same password' do
- service.url = 'http://jira_edited.example.com'
- service.password = password
- service.save!
-
- expect(service.password).to eq(password)
- expect(service.url).to eq('http://jira_edited.example.com')
- end
-
- it 'resets password if url changed, even if setter called multiple times' do
- service.url = 'http://jira1.example.com/rest/api/2'
- service.url = 'http://jira1.example.com/rest/api/2'
- service.save!
-
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if username changed' do
- service.username = 'some_name'
- service.save!
-
- expect(service.reload.password).to eq(password)
- end
-
- it 'does not reset password if password changed' do
- service.url = 'http://jira_edited.example.com'
- service.password = 'new_password'
- service.save!
-
- expect(service.reload.password).to eq('new_password')
- end
-
- it 'does not reset password if the password is touched and same as before' do
- service.url = 'http://jira_edited.example.com'
- service.password = password
- service.save!
-
- expect(service.reload.password).to eq(password)
- end
- end
-
- context 'when both web and api url present' do
- let(:data_params) do
- {
- url: url, api_url: 'http://jira.example.com/rest/api/2',
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- it 'resets password if api url changed' do
- service.api_url = 'http://jira_edited.example.com/rest/api/2'
- service.save!
-
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if url changed' do
- service.url = 'http://jira_edited.example.com'
- service.save!
-
- expect(service.password).to eq(password)
- end
-
- it 'resets password if api url set to empty' do
- service.update!(api_url: '')
-
- expect(service.reload.password).to be_nil
- end
- end
- end
-
- context 'when no password was previously set' do
- let(:data_params) do
- {
- url: url, username: username
- }
- end
-
- it 'saves password if new url is set together with password' do
- service.url = 'http://jira_edited.example.com/rest/api/2'
- service.password = 'password'
- service.save!
- expect(service.reload.password).to eq('password')
- expect(service.reload.url).to eq('http://jira_edited.example.com/rest/api/2')
- end
- end
- end
- end
- 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!(:service) do
- create(:jira_service, :without_properties_callback, properties: properties.merge(additional: 'something'))
- end
-
- it_behaves_like 'handles jira fields'
- end
-
- context 'when data are stored in separated fields' do
- let(:service) do
- create(:jira_service, data_params.merge(properties: {}))
- 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(:service) do
- create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |integration|
- create(:jira_tracker_data, data_params.merge(integration: integration))
- end
- end
-
- it_behaves_like 'handles jira fields'
- end
- end
-
- describe '#find_issue' do
- let(:issue_key) { 'JIRA-123' }
- let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}" }
-
- before do
- stub_request(:get, issue_url).with(basic_auth: [username, password])
- end
-
- it 'call the Jira API to get the issue' do
- jira_service.find_issue(issue_key)
-
- expect(WebMock).to have_requested(:get, issue_url)
- end
-
- context 'with options' do
- let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}?expand=renderedFields,transitions" }
-
- it 'calls the Jira API with the options to get the issue' do
- jira_service.find_issue(issue_key, rendered_fields: true, transitions: true)
-
- expect(WebMock).to have_requested(:get, issue_url)
- end
- end
- end
-
- describe '#close_issue' do
- let(:custom_base_url) { 'http://custom_url' }
-
- shared_examples 'close_issue' do
- let(:issue_key) { 'JIRA-123' }
- let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}" }
- let(:transitions_url) { "#{issue_url}/transitions" }
- let(:comment_url) { "#{issue_url}/comment" }
- let(:remote_link_url) { "#{issue_url}/remotelink" }
- let(:transitions) { nil }
-
- let(:issue_fields) do
- {
- id: issue_key,
- self: issue_url,
- transitions: transitions
- }
- end
-
- subject(:close_issue) do
- jira_service.close_issue(resource, ExternalIssue.new(issue_key, project))
- end
-
- before do
- jira_service.jira_issue_transition_id = '999'
-
- # These stubs are needed to test JiraService#close_issue.
- # We close the issue then do another request to API to check if it got closed.
- # Here is stubbed the API return with a closed and an opened issues.
- open_issue = JIRA::Resource::Issue.new(jira_service.client, attrs: issue_fields.deep_stringify_keys)
- closed_issue = open_issue.dup
- allow(open_issue).to receive(:resolution).and_return(false)
- allow(closed_issue).to receive(:resolution).and_return(true)
- allow(JIRA::Resource::Issue).to receive(:find).and_return(open_issue, closed_issue)
-
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return(issue_key)
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
-
- WebMock.stub_request(:get, issue_url).with(basic_auth: %w(jira-username jira-password))
- WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password))
- WebMock.stub_request(:post, comment_url).with(basic_auth: %w(jira-username jira-password))
- WebMock.stub_request(:post, remote_link_url).with(basic_auth: %w(jira-username jira-password))
- end
-
- let(:external_issue) { ExternalIssue.new('JIRA-123', project) }
-
- def close_issue
- jira_service.close_issue(resource, external_issue, current_user)
- end
-
- it 'calls Jira API' do
- close_issue
-
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: /Issue solved with/
- ).once
- end
-
- it 'tracks usage' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter)
- .to receive(:track_event)
- .with('i_ecosystem_jira_service_close_issue', values: current_user.id)
-
- close_issue
- end
-
- it 'does not fail if remote_link.all on issue returns nil' do
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil)
-
- expect { close_issue }.not_to raise_error
- end
-
- # Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links
- # for more information
- it 'creates Remote Link reference in Jira for comment' do
- close_issue
-
- favicon_path = "http://localhost/assets/#{find_asset('favicon.png').digest_path}"
-
- # Creates comment
- expect(WebMock).to have_requested(:post, comment_url)
- # Creates Remote Link in Jira issue fields
- expect(WebMock).to have_requested(:post, remote_link_url).with(
- body: hash_including(
- GlobalID: 'GitLab',
- relationship: 'mentioned on',
- object: {
- url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}",
- title: "Solved by commit #{commit_id}.",
- icon: { title: 'GitLab', url16x16: favicon_path },
- status: { resolved: true }
- }
- )
- ).once
- end
-
- context 'when "comment_on_event_enabled" is set to false' do
- it 'creates Remote Link reference but does not create comment' do
- allow(jira_service).to receive_messages(comment_on_event_enabled: false)
- close_issue
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- expect(WebMock).to have_requested(:post, remote_link_url)
- end
- end
-
- context 'when Remote Link already exists' do
- let(:remote_link) do
- double(
- 'remote link',
- object: {
- url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}"
- }.with_indifferent_access
- )
- end
-
- it 'does not create comment' do
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return([remote_link])
-
- expect(remote_link).to receive(:save!)
-
- close_issue
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- end
- end
-
- it 'does not send comment or remote links to issues already closed' do
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(true)
-
- close_issue
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- expect(WebMock).not_to have_requested(:post, remote_link_url)
- end
-
- it 'does not send comment or remote links to issues with unknown resolution' do
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:respond_to?).with(:resolution).and_return(false)
-
- close_issue
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- expect(WebMock).not_to have_requested(:post, remote_link_url)
- end
-
- it 'references the GitLab commit' do
- stub_config_setting(base_url: custom_base_url)
-
- close_issue
-
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: %r{#{custom_base_url}/#{project.full_path}/-/commit/#{commit_id}}
- ).once
- end
-
- it 'references the GitLab commit' do
- stub_config_setting(relative_url_root: '/gitlab')
- stub_config_setting(url: Settings.send(:build_gitlab_url))
-
- allow(described_class).to receive(:default_url_options) do
- { script_name: '/gitlab' }
- end
-
- close_issue
-
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: %r{#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}}
- ).once
- end
-
- it 'logs exception when transition id is not valid' do
- allow(jira_service).to receive(:log_error)
- WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)).and_raise("Bad Request")
-
- close_issue
-
- expect(jira_service).to have_received(:log_error).with(
- "Issue transition failed",
- error: hash_including(
- exception_class: 'StandardError',
- exception_message: "Bad Request"
- ),
- client_url: "http://jira.example.com"
- )
- end
-
- it 'calls the api with jira_issue_transition_id' do
- close_issue
-
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"999"/
- ).once
- end
-
- context 'when custom transition IDs are blank' do
- before do
- jira_service.jira_issue_transition_id = ''
- end
-
- it 'does not transition the issue' do
- close_issue
-
- expect(WebMock).not_to have_requested(:post, transitions_url)
- end
- end
-
- context 'when using automatic issue transitions' do
- let(:transitions) do
- [
- { id: '1' },
- { id: '2', to: { statusCategory: { key: 'new' } } },
- { id: '3', to: { statusCategory: { key: 'done' } } },
- { id: '4', to: { statusCategory: { key: 'done' } } }
- ]
- end
-
- before do
- jira_service.jira_issue_transition_automatic = true
-
- close_issue
- end
-
- it 'uses the next transition with a status category of done' do
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"3"/
- ).once
- end
-
- context 'when no done transition is available' do
- let(:transitions) do
- [
- { id: '1', to: { statusCategory: { key: 'new' } } }
- ]
- end
-
- it 'does not attempt to transition' do
- expect(WebMock).not_to have_requested(:post, transitions_url)
- end
- end
-
- context 'when no valid transitions are returned' do
- let(:transitions) { 'foo' }
-
- it 'does not attempt to transition' do
- expect(WebMock).not_to have_requested(:post, transitions_url)
- end
- end
- end
-
- context 'when using multiple transition ids' do
- before do
- allow(jira_service).to receive_messages(jira_issue_transition_id: '1,2,3')
- end
-
- it 'calls the api with transition ids separated by comma' do
- close_issue
-
- 1.upto(3) do |transition_id|
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"#{transition_id}"/
- ).once
- end
-
- expect(WebMock).to have_requested(:post, comment_url)
- end
-
- it 'calls the api with transition ids separated by semicolon' do
- allow(jira_service).to receive_messages(jira_issue_transition_id: '1;2;3')
-
- close_issue
-
- 1.upto(3) do |transition_id|
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"#{transition_id}"/
- ).once
- end
-
- expect(WebMock).to have_requested(:post, comment_url)
- end
-
- context 'when a transition fails' do
- before do
- WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)).to_return do |request|
- { status: request.body.include?('"id":"2"') ? 500 : 200 }
- end
- end
-
- it 'stops the sequence' do
- close_issue
-
- 1.upto(2) do |transition_id|
- expect(WebMock).to have_requested(:post, transitions_url).with(
- body: /"id":"#{transition_id}"/
- )
- end
-
- expect(WebMock).not_to have_requested(:post, transitions_url).with(
- body: /"id":"3"/
- )
-
- expect(WebMock).not_to have_requested(:post, comment_url)
- end
- end
- end
- end
-
- context 'when resource is a merge request' do
- let(:resource) { create(:merge_request) }
- let(:commit_id) { resource.diff_head_sha }
-
- it_behaves_like 'close_issue'
- end
-
- context 'when resource is a commit' do
- let(:resource) { project.commit('master') }
- let(:commit_id) { resource.id }
-
- it_behaves_like 'close_issue'
- end
- end
-
- describe '#create_cross_reference_note' do
- let_it_be(:user) { build_stubbed(:user) }
-
- let(:jira_issue) { ExternalIssue.new('JIRA-123', project) }
-
- subject { jira_service.create_cross_reference_note(jira_issue, resource, user) }
-
- shared_examples 'creates a comment on Jira' do
- let(:issue_url) { "#{url}/rest/api/2/issue/JIRA-123" }
- let(:comment_url) { "#{issue_url}/comment" }
- let(:remote_link_url) { "#{issue_url}/remotelink" }
-
- before do
- allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
- stub_request(:get, issue_url).with(basic_auth: [username, password])
- stub_request(:post, comment_url).with(basic_auth: [username, password])
- stub_request(:post, remote_link_url).with(basic_auth: [username, password])
- end
-
- it 'creates a comment on Jira' do
- subject
-
- expect(WebMock).to have_requested(:post, comment_url).with(
- body: /mentioned this issue in/
- ).once
- end
-
- it 'tracks usage' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter)
- .to receive(:track_event)
- .with('i_ecosystem_jira_service_cross_reference', values: user.id)
-
- subject
- end
- end
-
- context 'when resource is a commit' do
- let(:resource) { project.commit('master') }
-
- context 'when disabled' do
- before do
- allow_next_instance_of(JiraService) do |instance|
- allow(instance).to receive(:commit_events) { false }
- end
- end
-
- it { is_expected.to eq('Events for commits are disabled.') }
- end
-
- context 'when enabled' do
- it_behaves_like 'creates a comment on Jira'
- end
- end
-
- context 'when resource is a merge request' do
- let(:resource) { build_stubbed(:merge_request, source_project: project) }
-
- context 'when disabled' do
- before do
- allow_next_instance_of(JiraService) do |instance|
- allow(instance).to receive(:merge_requests_events) { false }
- end
- end
-
- it { is_expected.to eq('Events for merge requests are disabled.') }
- end
-
- context 'when enabled' do
- it_behaves_like 'creates a comment on Jira'
- end
- end
- end
-
- describe '#test' do
- let(:server_info_results) { { 'url' => 'http://url', 'deploymentType' => 'Cloud' } }
-
- def server_info
- jira_service.test(nil)
- end
-
- context 'when the test succeeds' do
- it 'gets Jira project with URL when API URL not set' do
- expect(server_info).to eq(success: true, result: server_info_results)
- expect(WebMock).to have_requested(:get, /jira.example.com/)
- end
-
- it 'gets Jira project with API URL if set' do
- jira_service.update!(api_url: 'http://jira.api.com')
-
- expect(server_info).to eq(success: true, result: server_info_results)
- expect(WebMock).to have_requested(:get, /jira.api.com/)
- end
- end
-
- context 'when the test fails' do
- it 'returns result with the error' do
- test_url = 'http://jira.example.com/rest/api/2/serverInfo'
- error_message = 'Some specific failure.'
-
- WebMock.stub_request(:get, test_url).with(basic_auth: [username, password])
- .to_raise(JIRA::HTTPError.new(double(message: error_message)))
-
- expect(jira_service).to receive(:log_error).with(
- 'Error sending message',
- client_url: 'http://jira.example.com',
- error: error_message
- )
-
- expect(jira_service.test(nil)).to eq(success: false, result: error_message)
- end
- end
- end
-
- describe 'project and issue urls' do
- context 'when gitlab.yml was initialized' do
- it 'is prepopulated with the settings' do
- settings = {
- 'jira' => {
- 'url' => 'http://jira.sample/projects/project_a',
- 'api_url' => 'http://jira.sample/api'
- }
- }
- allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
-
- service = project.create_jira_service(active: true)
-
- expect(service.url).to eq('http://jira.sample/projects/project_a')
- expect(service.api_url).to eq('http://jira.sample/api')
- end
- end
-
- it 'removes trailing slashes from url' do
- service = described_class.new(url: 'http://jira.test.com/path/')
-
- expect(service.url).to eq('http://jira.test.com/path')
- end
- end
-
- describe 'favicon urls' do
- it 'includes the standard favicon' do
- props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title')
- expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/assets/favicon(?:-\h+).png$}
- end
-
- it 'includes returns the custom favicon' do
- create :appearance, favicon: fixture_file_upload('spec/fixtures/dk.png')
-
- props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title')
- expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/uploads/-/system/appearance/favicon/\d+/dk.png$}
- end
- end
-
- context 'generating external URLs' do
- let(:service) { described_class.new(url: 'http://jira.test.com/path/') }
-
- describe '#issues_url' do
- it 'handles trailing slashes' do
- expect(service.issues_url).to eq('http://jira.test.com/path/browse/:id')
- end
- end
-
- describe '#new_issue_url' do
- it 'handles trailing slashes' do
- expect(service.new_issue_url).to eq('http://jira.test.com/path/secure/CreateIssue!default.jspa')
- end
- end
- end
-
- describe '#issue_transition_enabled?' do
- it 'returns true if automatic transitions are enabled' do
- jira_service.jira_issue_transition_automatic = true
-
- expect(jira_service.issue_transition_enabled?).to be(true)
- end
-
- it 'returns true if custom transitions are set' do
- jira_service.jira_issue_transition_id = '1, 2, 3'
-
- expect(jira_service.issue_transition_enabled?).to be(true)
- end
-
- it 'returns false if automatic and custom transitions are disabled' do
- expect(jira_service.issue_transition_enabled?).to be(false)
- end
- end
-end
diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/project_services/jira_tracker_data_spec.rb
deleted file mode 100644
index 72bdbe40a74..00000000000
--- a/spec/models/project_services/jira_tracker_data_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe JiraTrackerData do
- describe 'associations' do
- it { is_expected.to belong_to(:integration) }
- end
-
- describe 'deployment_type' do
- it { is_expected.to define_enum_for(:deployment_type).with_values([:unknown, :server, :cloud]).with_prefix(:deployment) }
- end
-
- describe 'encrypted attributes' do
- subject { described_class.encrypted_attributes.keys }
-
- it { is_expected.to contain_exactly(:api_url, :password, :url, :username) }
- end
-end
diff --git a/spec/models/project_services/mattermost_service_spec.rb b/spec/models/project_services/mattermost_service_spec.rb
deleted file mode 100644
index af1944ea77d..00000000000
--- a/spec/models/project_services/mattermost_service_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MattermostService do
- it_behaves_like "slack or mattermost notifications", "Mattermost"
-end
diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
deleted file mode 100644
index 87befdd4303..00000000000
--- a/spec/models/project_services/mattermost_slash_commands_service_spec.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MattermostSlashCommandsService do
- it_behaves_like "chat slash commands service"
-
- context 'Mattermost API' do
- let(:project) { create(:project) }
- let(:service) { project.build_mattermost_slash_commands_service }
- let(:user) { create(:user) }
-
- before do
- session = Mattermost::Session.new(nil)
- session.base_uri = 'http://mattermost.example.com'
-
- allow_any_instance_of(Mattermost::Client).to receive(:with_session)
- .and_yield(session)
- end
-
- describe '#configure' do
- subject do
- service.configure(user, team_id: 'abc',
- trigger: 'gitlab', url: 'http://trigger.url',
- icon_url: 'http://icon.url/icon.png')
- end
-
- context 'the requests succeeds' do
- before do
- stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
- .with(body: {
- team_id: 'abc',
- trigger: 'gitlab',
- url: 'http://trigger.url',
- icon_url: 'http://icon.url/icon.png',
- auto_complete: true,
- auto_complete_desc: "Perform common operations on: #{project.full_name}",
- auto_complete_hint: '[help]',
- description: "Perform common operations on: #{project.full_name}",
- display_name: "GitLab / #{project.full_name}",
- method: 'P',
- username: 'GitLab'
- }.to_json)
- .to_return(
- status: 200,
- headers: { 'Content-Type' => 'application/json' },
- body: { token: 'token' }.to_json
- )
- end
-
- it 'saves the service' do
- expect { subject }.to change { project.integrations.count }.by(1)
- end
-
- it 'saves the token' do
- subject
-
- expect(service.reload.token).to eq('token')
- end
- end
-
- context 'an error is received' do
- before do
- stub_request(:post, 'http://mattermost.example.com/api/v4/commands')
- .to_return(
- status: 500,
- headers: { 'Content-Type' => 'application/json' },
- body: {
- id: 'api.command.duplicate_trigger.app_error',
- message: 'This trigger word is already in use. Please choose another word.',
- detailed_error: '',
- request_id: 'obc374man7bx5r3dbc1q5qhf3r',
- status_code: 500
- }.to_json
- )
- end
-
- it 'shows error messages' do
- succeeded, message = subject
-
- expect(succeeded).to be(false)
- expect(message).to eq('This trigger word is already in use. Please choose another word.')
- end
- end
- end
-
- describe '#list_teams' do
- subject do
- service.list_teams(user)
- end
-
- context 'the requests succeeds' do
- before do
- stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
- .to_return(
- status: 200,
- headers: { 'Content-Type' => 'application/json' },
- body: [{ id: 'test_team_id' }].to_json
- )
- end
-
- it 'returns a list of teams' do
- expect(subject).not_to be_empty
- end
- end
-
- context 'an error is received' do
- before do
- stub_request(:get, 'http://mattermost.example.com/api/v4/users/me/teams')
- .to_return(
- status: 500,
- headers: { 'Content-Type' => 'application/json' },
- body: {
- message: 'Failed to get team list.'
- }.to_json
- )
- end
-
- it 'shows error messages' do
- expect(subject).to eq([[], "Failed to get team list."])
- end
- end
- end
-
- describe '#chat_responder' do
- it 'returns the responder to use for Mattermost' do
- expect(described_class.new.chat_responder)
- .to eq(Gitlab::Chat::Responder::Mattermost)
- end
- end
- end
-end
diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb
deleted file mode 100644
index 5f3a94a5b99..00000000000
--- a/spec/models/project_services/microsoft_teams_service_spec.rb
+++ /dev/null
@@ -1,360 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MicrosoftTeamsService do
- let(:chat_service) { described_class.new }
- let(:webhook_url) { 'https://example.gitlab.com/' }
-
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:webhook) }
- it_behaves_like 'issue tracker service URL attribute', :webhook
- end
-
- context 'when service 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(:project) { create(:project, :repository, :wiki_repo) }
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- context 'with push events' do
- let(:push_sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- it "calls Microsoft Teams API for push events" do
- chat_service.execute(push_sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
-
- it 'specifies the webhook when it is configured' do
- expect(MicrosoftTeams::Notifier).to receive(:new).with(webhook_url).and_return(double(:microsoft_teams_service).as_null_object)
-
- chat_service.execute(push_sample_data)
- end
- end
-
- context 'with issue events' do
- let(:opts) { { title: 'Awesome issue', description: 'please fix' } }
- let(:issues_sample_data) do
- service = Issues::CreateService.new(project: project, current_user: user, params: opts)
- issue = service.execute
- service.hook_data(issue, 'open')
- end
-
- it "calls Microsoft Teams API" do
- chat_service.execute(issues_sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'with merge events' do
- let(:opts) do
- {
- title: 'Awesome merge_request',
- description: 'please fix',
- source_branch: 'feature',
- target_branch: 'master'
- }
- end
-
- let(:merge_sample_data) do
- service = MergeRequests::CreateService.new(project: project, current_user: user, params: opts)
- merge_request = service.execute
- service.hook_data(merge_request, 'open')
- end
-
- before do
- project.add_developer(user)
- end
-
- it "calls Microsoft Teams API" do
- chat_service.execute(merge_sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'with wiki page events' do
- let(:opts) do
- {
- title: "Awesome wiki_page",
- content: "Some text describing some thing or another",
- format: "md",
- message: "user created page: Awesome wiki_page"
- }
- end
-
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki, **opts) }
- let(:wiki_page_sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
-
- it "calls Microsoft Teams API" do
- chat_service.execute(wiki_page_sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
- end
-
- describe "Note events" do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, creator: user) }
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- context 'when commit comment event executed' do
- let(:commit_note) do
- create(:note_on_commit, author: user,
- project: project,
- commit_id: project.repository.commit.id,
- note: 'a comment on a commit')
- end
-
- it "calls Microsoft Teams API for commit comment events" do
- data = Gitlab::DataBuilder::Note.build(commit_note, user)
-
- chat_service.execute(data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'when merge request comment event executed' do
- let(:merge_request_note) do
- create(:note_on_merge_request, project: project,
- note: "merge request note")
- end
-
- it "calls Microsoft Teams API for merge request comment events" do
- data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
-
- chat_service.execute(data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'when issue comment event executed' do
- let(:issue_note) do
- create(:note_on_issue, project: project, note: "issue note")
- end
-
- it "calls Microsoft Teams API for issue comment events" do
- data = Gitlab::DataBuilder::Note.build(issue_note, user)
-
- chat_service.execute(data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
-
- context 'when snippet comment event executed' do
- let(:snippet_note) do
- create(:note_on_project_snippet, project: project,
- note: "snippet note")
- end
-
- it "calls Microsoft Teams API for snippet comment events" do
- data = Gitlab::DataBuilder::Note.build(snippet_note, user)
-
- chat_service.execute(data)
-
- expect(WebMock).to have_requested(:post, webhook_url).once
- end
- end
- end
-
- describe 'Pipeline events' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
-
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: status,
- sha: project.commit.sha, ref: project.default_branch)
- end
-
- before do
- allow(chat_service).to receive_messages(
- project: project,
- service_hook: true,
- webhook: webhook_url
- )
- end
-
- shared_examples 'call Microsoft Teams API' do |branches_to_be_notified: nil|
- before do
- WebMock.stub_request(:post, webhook_url)
- chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
- end
-
- it 'calls Microsoft Teams API for pipeline events' do
- data = Gitlab::DataBuilder::Pipeline.build(pipeline)
- data[:markdown] = true
-
- chat_service.execute(data)
-
- message = Integrations::ChatMessage::PipelineMessage.new(data)
-
- expect(WebMock).to have_requested(:post, webhook_url)
- .with(body: hash_including({ summary: message.summary }))
- .once
- end
- end
-
- shared_examples 'does not call Microsoft Teams API' do |branches_to_be_notified: nil|
- before do
- chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
- end
- it 'does not call Microsoft Teams API for pipeline events' do
- data = Gitlab::DataBuilder::Pipeline.build(pipeline)
- result = chat_service.execute(data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'with failed pipeline' do
- let(:status) { 'failed' }
-
- it_behaves_like 'call Microsoft Teams API'
- end
-
- context 'with succeeded pipeline' do
- let(:status) { 'success' }
-
- context 'with default to notify_only_broken_pipelines' do
- it 'does not call Microsoft Teams API for pipeline events' do
- data = Gitlab::DataBuilder::Pipeline.build(pipeline)
- result = chat_service.execute(data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'with setting notify_only_broken_pipelines to false' do
- before do
- chat_service.notify_only_broken_pipelines = false
- end
-
- it_behaves_like 'call Microsoft Teams API'
- end
- end
-
- context 'with default branch' do
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: project.default_branch)
- end
-
- context 'only notify for the default branch' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default"
- end
-
- context 'notify for only protected branches' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "protected"
- end
-
- context 'notify for only default and protected branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notify for all branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
- end
- end
-
- context 'with protected branch' do
- before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
- end
-
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: 'a-protected-branch')
- end
-
- context 'only notify for the default branch' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default"
- end
-
- context 'notify for only protected branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "protected"
- end
-
- context 'notify for only default and protected branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notify for all branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
- end
- end
-
- context 'with neither protected nor default branch' do
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: 'a-random-branch')
- end
-
- context 'only notify for the default branch' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default"
- end
-
- context 'notify for only protected branches' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "protected"
- end
-
- context 'notify for only default and protected branches' do
- it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notify for all branches' do
- it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
- end
- end
- end
-end
diff --git a/spec/models/project_services/open_project_service_spec.rb b/spec/models/project_services/open_project_service_spec.rb
deleted file mode 100644
index 1abaab0ceff..00000000000
--- a/spec/models/project_services/open_project_service_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe OpenProjectService do
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:url) }
- it { is_expected.to validate_presence_of(:token) }
- it { is_expected.to validate_presence_of(:project_identifier_code) }
-
- it_behaves_like 'issue tracker service URL attribute', :url
- it_behaves_like 'issue tracker service URL attribute', :api_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:url) }
- it { is_expected.not_to validate_presence_of(:token) }
- it { is_expected.not_to validate_presence_of(:project_identifier_code) }
- end
- end
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-end
diff --git a/spec/models/project_services/open_project_tracker_data_spec.rb b/spec/models/project_services/open_project_tracker_data_spec.rb
deleted file mode 100644
index 1f7f01cfea4..00000000000
--- a/spec/models/project_services/open_project_tracker_data_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe OpenProjectTrackerData do
- describe 'associations' do
- it { is_expected.to belong_to(:integration) }
- end
-
- describe 'closed_status_id' do
- it 'returns the set value' do
- expect(build(:open_project_tracker_data).closed_status_id).to eq('15')
- end
-
- it 'returns the default value if not set' do
- expect(build(:open_project_tracker_data, closed_status_id: nil).closed_status_id).to eq('13')
- end
- end
-end
diff --git a/spec/models/project_services/packagist_service_spec.rb b/spec/models/project_services/packagist_service_spec.rb
deleted file mode 100644
index 33b5c9809c7..00000000000
--- a/spec/models/project_services/packagist_service_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PackagistService 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) }
-
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- 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_service) { described_class.create!(packagist_params) }
-
- before do
- stub_request(:post, packagist_hook_url)
- end
-
- it 'calls Packagist API' do
- packagist_service.execute(push_sample_data)
-
- expect(a_request(:post, packagist_hook_url)).to have_been_made.once
- end
- end
-end
diff --git a/spec/models/project_services/pipelines_email_service_spec.rb b/spec/models/project_services/pipelines_email_service_spec.rb
deleted file mode 100644
index 21cc5d44558..00000000000
--- a/spec/models/project_services/pipelines_email_service_spec.rb
+++ /dev/null
@@ -1,305 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PipelinesEmailService, :mailer do
- let(:pipeline) do
- create(:ci_pipeline, :failed,
- project: project,
- sha: project.commit('master').sha,
- ref: project.default_branch
- )
- end
-
- let(:project) { create(:project, :repository) }
- let(:recipients) { 'test@gitlab.com' }
- let(:receivers) { [recipients] }
-
- let(:data) do
- Gitlab::DataBuilder::Pipeline.build(pipeline)
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:recipients) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:recipients) }
- end
- end
-
- shared_examples 'sending email' do |branches_to_be_notified: nil|
- before do
- subject.recipients = recipients
- subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
-
- perform_enqueued_jobs do
- run
- end
- end
-
- it 'sends email' do
- emails = receivers.map { |r| double(notification_email: r) }
-
- should_only_email(*emails, kind: :bcc)
- end
- end
-
- shared_examples 'not sending email' do |branches_to_be_notified: nil|
- before do
- subject.recipients = recipients
- subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
-
- perform_enqueued_jobs do
- run
- end
- end
-
- it 'does not send email' do
- should_not_email_anyone
- end
- end
-
- describe '#test' do
- def run
- subject.test(data)
- end
-
- context 'when pipeline is failed and on default branch' do
- it_behaves_like 'sending email'
- end
-
- context 'when pipeline is succeeded' do
- before do
- data[:object_attributes][:status] = 'success'
- pipeline.update!(status: 'success')
- end
-
- it_behaves_like 'sending email'
- end
-
- context 'when the pipeline failed' do
- context 'on default branch' do
- before do
- data[:object_attributes][:ref] = project.default_branch
- pipeline.update!(ref: project.default_branch)
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
-
- context 'on a protected branch' do
- before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
- data[:object_attributes][:ref] = 'a-protected-branch'
- pipeline.update!(ref: 'a-protected-branch')
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
-
- context 'on a neither protected nor default branch' do
- before do
- data[:object_attributes][:ref] = 'a-random-branch'
- pipeline.update!(ref: 'a-random-branch')
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
- end
- end
-
- describe '#execute' do
- before do
- subject.project = project
- end
-
- def run
- subject.execute(data)
- end
-
- context 'with recipients' do
- context 'with failed pipeline' do
- it_behaves_like 'sending email'
- end
-
- context 'with succeeded pipeline' do
- before do
- data[:object_attributes][:status] = 'success'
- pipeline.update!(status: 'success')
- end
-
- it_behaves_like 'not sending email'
- end
-
- context 'with notify_only_broken_pipelines on' do
- before do
- subject.notify_only_broken_pipelines = true
- end
-
- context 'with failed pipeline' do
- it_behaves_like 'sending email'
- end
-
- context 'with succeeded pipeline' do
- before do
- data[:object_attributes][:status] = 'success'
- pipeline.update!(status: 'success')
- end
-
- it_behaves_like 'not sending email'
- end
- end
-
- context 'when the pipeline failed' do
- context 'on default branch' do
- before do
- data[:object_attributes][:ref] = project.default_branch
- pipeline.update!(ref: project.default_branch)
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'not sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
-
- context 'on a protected branch' do
- before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
- data[:object_attributes][:ref] = 'a-protected-branch'
- pipeline.update!(ref: 'a-protected-branch')
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'not sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
-
- context 'on a neither protected nor default branch' do
- before do
- data[:object_attributes][:ref] = 'a-random-branch'
- pipeline.update!(ref: 'a-random-branch')
- end
-
- context 'notifications are enabled only for default branch' do
- it_behaves_like 'not sending email', branches_to_be_notified: "default"
- end
-
- context 'notifications are enabled only for protected branch' do
- it_behaves_like 'not sending email', branches_to_be_notified: "protected"
- end
-
- context 'notifications are enabled only for default and protected branches ' do
- it_behaves_like 'not sending email', branches_to_be_notified: "default_and_protected"
- end
-
- context 'notifications are enabled only for all branches' do
- it_behaves_like 'sending email', branches_to_be_notified: "all"
- end
- end
- end
- end
-
- context 'with empty recipients list' do
- let(:recipients) { ' ,, ' }
-
- context 'with failed pipeline' do
- before do
- data[:object_attributes][:status] = 'failed'
- pipeline.update!(status: 'failed')
- end
-
- it_behaves_like 'not sending email'
- end
- end
-
- context 'with recipients list separating with newlines' do
- let(:recipients) { "\ntest@gitlab.com, \r\nexample@gitlab.com\rother@gitlab.com" }
- let(:receivers) { %w[test@gitlab.com example@gitlab.com other@gitlab.com] }
-
- context 'with failed pipeline' do
- before do
- data[:object_attributes][:status] = 'failed'
- pipeline.update!(status: 'failed')
- end
-
- it_behaves_like 'sending email'
- end
- end
- end
-end
diff --git a/spec/models/project_services/pivotaltracker_service_spec.rb b/spec/models/project_services/pivotaltracker_service_spec.rb
deleted file mode 100644
index 8de85cc7fa5..00000000000
--- a/spec/models/project_services/pivotaltracker_service_spec.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PivotaltrackerService do
- include StubRequests
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:token) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:token) }
- end
- end
-
- describe 'Execute' do
- let(:service) do
- described_class.new.tap do |service|
- service.token = 'secret_api_token'
- end
- end
-
- let(:url) { PivotaltrackerService::API_ENDPOINT }
-
- def push_data(branch: 'master')
- {
- object_kind: 'push',
- ref: "refs/heads/#{branch}",
- commits: [
- {
- id: '21c12ea',
- author: {
- name: 'Some User'
- },
- url: 'https://example.com/commit',
- message: 'commit message'
- }
- ]
- }
- end
-
- before do
- stub_full_request(url, method: :post)
- end
-
- it 'posts correct message' do
- service.execute(push_data)
- expect(WebMock).to have_requested(:post, stubbed_hostname(url)).with(
- body: {
- 'source_commit' => {
- 'commit_id' => '21c12ea',
- 'author' => 'Some User',
- 'url' => 'https://example.com/commit',
- 'message' => 'commit message'
- }
- },
- headers: {
- 'Content-Type' => 'application/json',
- 'X-TrackerToken' => 'secret_api_token'
- }
- ).once
- end
-
- context 'when allowed branches is specified' do
- let(:service) do
- super().tap do |service|
- service.restrict_to_branch = 'master,v10'
- end
- end
-
- it 'posts message if branch is in the list' do
- service.execute(push_data(branch: 'master'))
- service.execute(push_data(branch: 'v10'))
-
- expect(WebMock).to have_requested(:post, stubbed_hostname(url)).twice
- end
-
- it 'does not post message if branch is not in the list' do
- service.execute(push_data(branch: 'mas'))
- service.execute(push_data(branch: 'v11'))
-
- expect(WebMock).not_to have_requested(:post, stubbed_hostname(url))
- end
- end
- end
-end
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index 37a6d49ff74..a2025388fab 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -323,9 +323,9 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
end
describe '#prometheus_available?' do
- context 'clusters with installed prometheus' do
+ context 'clusters with enabled prometheus' do
before do
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
context 'cluster belongs to project' do
@@ -340,7 +340,7 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
let_it_be(:group) { create(:group) }
let(:project) { create(:prometheus_project, group: group) }
- let(:cluster) { create(:cluster_for_group, :with_installed_helm, groups: [group]) }
+ let(:cluster) { create(:cluster_for_group, groups: [group]) }
it 'returns true' do
expect(service.prometheus_available?).to be(true)
@@ -349,8 +349,8 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
it 'avoids N+1 queries' do
service
5.times do |i|
- other_cluster = create(:cluster_for_group, :with_installed_helm, groups: [group], environment_scope: i)
- create(:clusters_applications_prometheus, :installing, cluster: other_cluster)
+ other_cluster = create(:cluster_for_group, groups: [group], environment_scope: i)
+ create(:clusters_integrations_prometheus, cluster: other_cluster)
end
expect { service.prometheus_available? }.not_to exceed_query_limit(1)
end
@@ -365,18 +365,9 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
end
end
- context 'clusters with updated prometheus' do
- let!(:cluster) { create(:cluster, projects: [project]) }
- let!(:prometheus) { create(:clusters_applications_prometheus, :updated, cluster: cluster) }
-
- it 'returns true' do
- expect(service.prometheus_available?).to be(true)
- end
- end
-
- context 'clusters without prometheus installed' do
+ context 'clusters with prometheus disabled' do
let(:cluster) { create(:cluster, projects: [project]) }
- let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) }
+ let!(:prometheus) { create(:clusters_integrations_prometheus, :disabled, cluster: cluster) }
it 'returns false' do
expect(service.prometheus_available?).to be(false)
@@ -491,13 +482,13 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
expect(service.editable?).to be(true)
end
- context 'when cluster exists with prometheus installed' do
+ context 'when cluster exists with prometheus enabled' do
let(:cluster) { create(:cluster, projects: [project]) }
before do
service.update!(manual_configuration: false)
- create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ create(:clusters_integrations_prometheus, cluster: cluster)
end
it 'remains editable' do
diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb
deleted file mode 100644
index b7d3b8987b8..00000000000
--- a/spec/models/project_services/pushover_service_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PushoverService do
- include StubRequests
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:api_key) }
- it { is_expected.to validate_presence_of(:user_key) }
- it { is_expected.to validate_presence_of(:priority) }
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:api_key) }
- it { is_expected.not_to validate_presence_of(:user_key) }
- it { is_expected.not_to validate_presence_of(:priority) }
- end
- end
-
- describe 'Execute' do
- let(:pushover) { described_class.new }
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- let(:api_key) { 'verySecret' }
- let(:user_key) { 'verySecret' }
- let(:device) { 'myDevice' }
- let(:priority) { 0 }
- let(:sound) { 'bike' }
- let(:api_url) { 'https://api.pushover.net/1/messages.json' }
-
- before do
- allow(pushover).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- api_key: api_key,
- user_key: user_key,
- device: device,
- priority: priority,
- sound: sound
- )
-
- stub_full_request(api_url, method: :post, ip_address: '8.8.8.8')
- end
-
- it 'calls Pushover API' do
- pushover.execute(sample_data)
-
- expect(WebMock).to have_requested(:post, 'https://8.8.8.8/1/messages.json').once
- end
- end
-end
diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb
deleted file mode 100644
index b9be3940d34..00000000000
--- a/spec/models/project_services/redmine_service_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe RedmineService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- # if redmine is set in setting the urls are set to defaults
- # therefore the validation passes as the values are not nil
- before do
- settings = {
- 'redmine' => {}
- }
- allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
- end
-
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
- it { is_expected.to validate_presence_of(:new_issue_url) }
-
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- it_behaves_like 'issue tracker service URL attribute', :new_issue_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- it { is_expected.not_to validate_presence_of(:new_issue_url) }
- end
- end
-
- describe '.reference_pattern' do
- it_behaves_like 'allows project key on reference pattern'
-
- it 'does allow # on the reference' do
- expect(described_class.reference_pattern.match('#123')[:issue]).to eq('123')
- end
- end
-end
diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb
deleted file mode 100644
index 2e2c1c666d9..00000000000
--- a/spec/models/project_services/slack_service_spec.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SlackService do
- it_behaves_like "slack or mattermost notifications", 'Slack'
-
- describe '#execute' do
- before do
- stub_request(:post, "https://slack.service.url/")
- end
-
- let_it_be(:slack_service) { create(:slack_service, branches_to_be_notified: 'all') }
-
- 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) }
- let_it_be(:project) { create_default(:project, :repository, :wiki_repo) }
-
- shared_examples 'increases the usage data counter' do |event_name|
- it 'increases the usage data counter' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: user.id).and_call_original
-
- slack_service.execute(data)
- 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_service.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, 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_service.execute(data)
- end
- end
- end
-end
diff --git a/spec/models/project_services/slack_slash_commands_service_spec.rb b/spec/models/project_services/slack_slash_commands_service_spec.rb
deleted file mode 100644
index 95c87ef01bc..00000000000
--- a/spec/models/project_services/slack_slash_commands_service_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SlackSlashCommandsService do
- it_behaves_like "chat slash commands service"
-
- describe '#trigger' do
- context 'when an auth url is generated' do
- let(:project) { create(:project) }
- let(:params) do
- {
- team_domain: 'http://domain.tld',
- team_id: 'T3423423',
- user_id: 'U234234',
- user_name: 'mepmep',
- token: 'token'
- }
- end
-
- let(:service) do
- project.create_slack_slash_commands_service(
- properties: { token: 'token' },
- active: true
- )
- end
-
- let(:authorize_url) do
- 'http://authorize.example.com/'
- end
-
- before do
- allow(service).to receive(:authorize_chat_name_url).and_return(authorize_url)
- end
-
- it 'uses slack compatible links' do
- response = service.trigger(params)
-
- expect(response[:text]).to include("<#{authorize_url}|connect your GitLab account>")
- end
- end
- end
-
- describe '#chat_responder' do
- it 'returns the responder to use for Slack' do
- expect(described_class.new.chat_responder)
- .to eq(Gitlab::Chat::Responder::Slack)
- end
- end
-end
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
deleted file mode 100644
index f71dad86a08..00000000000
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ /dev/null
@@ -1,334 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe TeamcityService, :use_clean_rails_memory_store_caching do
- include ReactiveCachingHelpers
- include StubRequests
-
- let(:teamcity_url) { 'http://gitlab.com/teamcity' }
- let(:teamcity_full_url) { 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,revision:123' }
- let(:project) { create(:project) }
-
- subject(:service) do
- described_class.create!(
- project: project,
- properties: {
- teamcity_url: teamcity_url,
- username: 'mic',
- password: 'password',
- build_type: 'foo'
- }
- )
- end
-
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:build_type) }
- it { is_expected.to validate_presence_of(:teamcity_url) }
- it_behaves_like 'issue tracker service URL attribute', :teamcity_url
-
- describe '#username' do
- it 'does not validate the presence of username if password is nil' do
- subject.password = nil
-
- expect(subject).not_to validate_presence_of(:username)
- end
-
- it 'validates the presence of username if password is present' do
- subject.password = 'secret'
-
- expect(subject).to validate_presence_of(:username)
- end
- end
-
- 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'
-
- expect(subject).to validate_presence_of(:password)
- end
- end
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:build_type) }
- it { is_expected.not_to validate_presence_of(:teamcity_url) }
- it { is_expected.not_to validate_presence_of(:username) }
- it { is_expected.not_to validate_presence_of(:password) }
- end
- end
-
- describe 'Callbacks' do
- describe 'before_update :reset_password' do
- context 'when a password was previously set' do
- it 'resets password if url changed' do
- teamcity_service = service
-
- teamcity_service.teamcity_url = 'http://gitlab1.com'
- teamcity_service.save!
-
- expect(teamcity_service.password).to be_nil
- end
-
- it 'does not reset password if username changed' do
- teamcity_service = service
-
- teamcity_service.username = 'some_name'
- teamcity_service.save!
-
- expect(teamcity_service.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_service = service
-
- teamcity_service.teamcity_url = 'http://gitlab_edited.com'
- teamcity_service.password = 'password'
- teamcity_service.save!
-
- expect(teamcity_service.password).to eq('password')
- expect(teamcity_service.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_service = service
- teamcity_service.password = nil
-
- teamcity_service.teamcity_url = 'http://gitlab_edited.com'
- teamcity_service.password = 'password'
- teamcity_service.save!
-
- expect(teamcity_service.password).to eq('password')
- expect(teamcity_service.teamcity_url).to eq('http://gitlab_edited.com')
- end
- end
- end
-
- describe '#build_page' do
- it 'returns the contents of the reactive cache' do
- stub_reactive_cache(service, { build_page: 'foo' }, 'sha', 'ref')
-
- expect(service.build_page('sha', 'ref')).to eq('foo')
- end
- end
-
- describe '#commit_status' do
- it 'returns the contents of the reactive cache' do
- stub_reactive_cache(service, { commit_status: 'foo' }, 'sha', 'ref')
-
- expect(service.commit_status('sha', 'ref')).to eq('foo')
- end
- end
-
- describe '#calculate_reactive_cache' do
- context 'build_page' do
- subject { service.calculate_reactive_cache('123', 'unused')[:build_page] }
-
- it 'returns a specific URL when status is 500' do
- stub_request(status: 500)
-
- is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildTypeId=foo')
- end
-
- it 'returns a build URL when teamcity_url has no trailing slash' do
- stub_request(body: %q({"build":{"id":"666"}}))
-
- is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildId=666&buildTypeId=foo')
- end
-
- context 'teamcity_url has trailing slash' do
- let(:teamcity_url) { 'http://gitlab.com/teamcity/' }
-
- it 'returns a build URL' do
- stub_request(body: %q({"build":{"id":"666"}}))
-
- is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildId=666&buildTypeId=foo')
- end
- end
-
- it 'returns the teamcity_url when teamcity is unreachable' do
- stub_full_request(teamcity_full_url).to_raise(Errno::ECONNREFUSED)
-
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
-
- is_expected.to eq(teamcity_url)
- end
- end
-
- context 'commit_status' do
- subject { service.calculate_reactive_cache('123', 'unused')[:commit_status] }
-
- it 'sets commit status to :error when status is 500' do
- stub_request(status: 500)
-
- is_expected.to eq(:error)
- end
-
- it 'sets commit status to "pending" when status is 404' do
- stub_request(status: 404)
-
- is_expected.to eq('pending')
- end
-
- it 'sets commit status to "success" when build status contains SUCCESS' do
- stub_request(build_status: 'YAY SUCCESS!')
-
- is_expected.to eq('success')
- end
-
- it 'sets commit status to "failed" when build status contains FAILURE' do
- stub_request(build_status: 'NO FAILURE!')
-
- is_expected.to eq('failed')
- end
-
- it 'sets commit status to "pending" when build status contains Pending' do
- stub_request(build_status: 'NO Pending!')
-
- is_expected.to eq('pending')
- end
-
- it 'sets commit status to :error when build status is unknown' do
- stub_request(build_status: 'FOO BAR!')
-
- is_expected.to eq(:error)
- end
-
- it 'sets commit status to :error when teamcity is unreachable' do
- stub_full_request(teamcity_full_url).to_raise(Errno::ECONNREFUSED)
-
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
-
- is_expected.to eq(:error)
- end
- end
- end
-
- describe '#execute' do
- context 'when push' do
- let(:data) do
- {
- object_kind: 'push',
- ref: 'refs/heads/dev-123_branch',
- after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e',
- total_commits_count: 1
- }
- end
-
- it 'handles push request correctly' do
- stub_post_to_build_queue(branch: 'dev-123_branch')
-
- expect(service.execute(data)).to include('Ok')
- end
-
- it 'returns nil when ref is blank' do
- data[:after] = Gitlab::Git::BLANK_SHA
-
- expect(service.execute(data)).to be_nil
- end
-
- it 'returns nil when there is no content' do
- data[:total_commits_count] = 0
-
- expect(service.execute(data)).to be_nil
- end
-
- it 'returns nil when a merge request is opened for the same ref' do
- create(:merge_request, source_project: project, source_branch: 'dev-123_branch')
-
- expect(service.execute(data)).to be_nil
- end
- end
-
- context 'when merge_request' do
- let(:data) do
- {
- object_kind: 'merge_request',
- ref: 'refs/heads/dev-123_branch',
- after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e',
- total_commits_count: 1,
- object_attributes: {
- state: 'opened',
- source_branch: 'dev-123_branch',
- merge_status: 'unchecked'
- }
- }
- end
-
- it 'handles merge request correctly' do
- stub_post_to_build_queue(branch: 'dev-123_branch')
-
- expect(service.execute(data)).to include('Ok')
- end
-
- it 'returns nil when merge request is not opened' do
- data[:object_attributes][:state] = 'closed'
-
- expect(service.execute(data)).to be_nil
- end
-
- it 'returns nil unless merge request is marked as unchecked' do
- data[:object_attributes][:merge_status] = 'can_be_merged'
-
- expect(service.execute(data)).to be_nil
- end
- end
-
- it 'returns nil when event is not supported' do
- data = { object_kind: 'foo' }
-
- expect(service.execute(data)).to be_nil
- end
- end
-
- def stub_post_to_build_queue(branch:)
- teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/buildQueue'
- body ||= %Q(<build branchName=\"#{branch}\"><buildType id=\"foo\"/></build>)
- auth = %w(mic password)
-
- stub_full_request(teamcity_full_url, method: :post).with(
- basic_auth: auth,
- body: body,
- headers: {
- 'Content-Type' => 'application/xml'
- }
- ).to_return(status: 200, body: 'Ok', headers: {})
- end
-
- def stub_request(status: 200, body: nil, build_status: 'success')
- auth = %w(mic password)
-
- body ||= %Q({"build":{"status":"#{build_status}","id":"666"}})
-
- stub_full_request(teamcity_full_url).with(basic_auth: auth).to_return(
- status: status,
- headers: { 'Content-Type' => 'application/json' },
- body: body
- )
- end
-end
diff --git a/spec/models/project_services/unify_circuit_service_spec.rb b/spec/models/project_services/unify_circuit_service_spec.rb
deleted file mode 100644
index 0c749322e07..00000000000
--- a/spec/models/project_services/unify_circuit_service_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe UnifyCircuitService do
- it_behaves_like "chat service", "Unify Circuit" do
- let(:client_arguments) { webhook_url }
- let(:payload) do
- {
- subject: project.full_name,
- text: be_present,
- markdown: true
- }
- end
- end
-end
diff --git a/spec/models/project_services/webex_teams_service_spec.rb b/spec/models/project_services/webex_teams_service_spec.rb
deleted file mode 100644
index ed63f5bc48c..00000000000
--- a/spec/models/project_services/webex_teams_service_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe WebexTeamsService do
- it_behaves_like "chat service", "Webex Teams" do
- let(:client_arguments) { webhook_url }
- let(:payload) do
- {
- markdown: be_present
- }
- end
- end
-end
diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/project_services/youtrack_service_spec.rb
deleted file mode 100644
index 4339b44e1de..00000000000
--- a/spec/models/project_services/youtrack_service_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe YoutrackService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:project_url) }
- it { is_expected.to validate_presence_of(:issues_url) }
-
- it_behaves_like 'issue tracker service URL attribute', :project_url
- it_behaves_like 'issue tracker service URL attribute', :issues_url
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:project_url) }
- it { is_expected.not_to validate_presence_of(:issues_url) }
- end
- end
-
- describe '.reference_pattern' do
- it_behaves_like 'allows project key on reference pattern'
-
- it 'does allow project prefix on the reference' do
- expect(described_class.reference_pattern.match('YT-123')[:issue]).to eq('YT-123')
- end
-
- it 'allows lowercase project key on the reference' do
- expect(described_class.reference_pattern.match('yt-123')[:issue]).to eq('yt-123')
- end
- end
-end