diff options
Diffstat (limited to 'spec/models/project_services')
26 files changed, 177 insertions, 2549 deletions
diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb deleted file mode 100644 index 7a6fe4b1537..00000000000 --- a/spec/models/project_services/asana_service_spec.rb +++ /dev/null @@ -1,114 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe AsanaService do - 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 :api_key } - end - end - - describe 'Execute' do - let(:user) { create(:user) } - let(:project) { create(:project) } - let(:gid) { "123456789ABCD" } - - def create_data_for_commits(*messages) - { - object_kind: 'push', - ref: 'master', - user_name: user.name, - commits: messages.map do |m| - { - message: m, - url: 'https://gitlab.com/' - } - end - } - end - - before do - @asana = described_class.new - allow(@asana).to receive_messages( - project: project, - project_id: project.id, - service_hook: true, - api_key: 'verySecret', - restrict_to_branch: 'master' - ) - end - - it 'calls Asana service to create a story' do - data = create_data_for_commits("Message from commit. related to ##{gid}") - expected_message = "#{data[:user_name]} pushed to branch #{data[:ref]} of #{project.full_name} ( #{data[:commits][0][:url]} ): #{data[:commits][0][:message]}" - - d1 = double('Asana::Resources::Task') - expect(d1).to receive(:add_comment).with(text: expected_message) - expect(Asana::Resources::Task).to receive(:find_by_id).with(anything, gid).once.and_return(d1) - - @asana.execute(data) - end - - it 'calls Asana service to create a story and close a task' do - data = create_data_for_commits('fix #456789') - d1 = double('Asana::Resources::Task') - expect(d1).to receive(:add_comment) - expect(d1).to receive(:update).with(completed: true) - expect(Asana::Resources::Task).to receive(:find_by_id).with(anything, '456789').once.and_return(d1) - - @asana.execute(data) - end - - it 'is able to close via url' do - data = create_data_for_commits('closes https://app.asana.com/19292/956299/42') - d1 = double('Asana::Resources::Task') - expect(d1).to receive(:add_comment) - expect(d1).to receive(:update).with(completed: true) - expect(Asana::Resources::Task).to receive(:find_by_id).with(anything, '42').once.and_return(d1) - - @asana.execute(data) - end - - it 'allows multiple matches per line' do - message = <<-EOF - minor bigfix, refactoring, fixed #123 and Closes #456 work on #789 - ref https://app.asana.com/19292/956299/42 and closing https://app.asana.com/19292/956299/12 - EOF - data = create_data_for_commits(message) - d1 = double('Asana::Resources::Task') - expect(d1).to receive(:add_comment) - expect(d1).to receive(:update).with(completed: true) - expect(Asana::Resources::Task).to receive(:find_by_id).with(anything, '123').once.and_return(d1) - - d2 = double('Asana::Resources::Task') - expect(d2).to receive(:add_comment) - expect(d2).to receive(:update).with(completed: true) - expect(Asana::Resources::Task).to receive(:find_by_id).with(anything, '456').once.and_return(d2) - - d3 = double('Asana::Resources::Task') - expect(d3).to receive(:add_comment) - expect(Asana::Resources::Task).to receive(:find_by_id).with(anything, '789').once.and_return(d3) - - d4 = double('Asana::Resources::Task') - expect(d4).to receive(:add_comment) - expect(Asana::Resources::Task).to receive(:find_by_id).with(anything, '42').once.and_return(d4) - - d5 = double('Asana::Resources::Task') - expect(d5).to receive(:add_comment) - expect(d5).to receive(:update).with(completed: true) - expect(Asana::Resources::Task).to receive(:find_by_id).with(anything, '12').once.and_return(d5) - - @asana.execute(data) - end - end -end diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb deleted file mode 100644 index 207add6f090..00000000000 --- a/spec/models/project_services/assembla_service_spec.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe AssemblaService do - include StubRequests - - 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) } - - before do - @assembla_service = described_class.new - allow(@assembla_service).to receive_messages( - project_id: project.id, - project: project, - service_hook: true, - token: 'verySecret', - subdomain: 'project_name' - ) - @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user) - @api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret' - stub_full_request(@api_url, method: :post) - end - - it "calls Assembla API" do - @assembla_service.execute(@sample_data) - expect(WebMock).to have_requested(:post, stubbed_hostname(@api_url)).with( - body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/ - ).once - end - end -end diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb deleted file mode 100644 index 45afbcca96d..00000000000 --- a/spec/models/project_services/bamboo_service_spec.rb +++ /dev/null @@ -1,287 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe BambooService, :use_clean_rails_memory_store_caching do - include ReactiveCachingHelpers - include StubRequests - - let(:bamboo_url) { 'http://gitlab.com/bamboo' } - - let_it_be(:project) { create(:project) } - - subject(:service) do - described_class.create!( - project: project, - properties: { - bamboo_url: bamboo_url, - username: 'mic', - password: 'password', - build_key: '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_key) } - it { is_expected.to validate_presence_of(:bamboo_url) } - it_behaves_like 'issue tracker service URL attribute', :bamboo_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_key) } - it { is_expected.not_to validate_presence_of(:bamboo_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 - bamboo_service = service - - bamboo_service.bamboo_url = 'http://gitlab1.com' - bamboo_service.save! - - expect(bamboo_service.password).to be_nil - end - - it 'does not reset password if username changed' do - bamboo_service = service - - bamboo_service.username = 'some_name' - bamboo_service.save! - - expect(bamboo_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 - bamboo_service = service - - bamboo_service.bamboo_url = 'http://gitlab_edited.com' - bamboo_service.password = 'password' - bamboo_service.save! - - expect(bamboo_service.password).to eq('password') - expect(bamboo_service.bamboo_url).to eq('http://gitlab_edited.com') - end - end - - it 'saves password if new url is set together with password when no password was previously set' do - bamboo_service = service - bamboo_service.password = nil - - bamboo_service.bamboo_url = 'http://gitlab_edited.com' - bamboo_service.password = 'password' - bamboo_service.save! - - expect(bamboo_service.password).to eq('password') - expect(bamboo_service.bamboo_url).to eq('http://gitlab_edited.com') - end - end - end - - describe '#execute' do - it 'runs update and build action' do - stub_update_and_build_request - - subject.execute(Gitlab::DataBuilder::Push::SAMPLE_DATA) - 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 - - shared_examples 'reactive cache calculation' do - describe '#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/bamboo/browse/foo') - end - - it 'returns a specific URL when response has no results' do - stub_request(body: %q({"results":{"results":{"size":"0"}}})) - - is_expected.to eq('http://gitlab.com/bamboo/browse/foo') - end - - it 'returns a build URL when bamboo_url has no trailing slash' do - stub_request(body: bamboo_response) - - is_expected.to eq('http://gitlab.com/bamboo/browse/42') - end - - context 'bamboo_url has trailing slash' do - let(:bamboo_url) { 'http://gitlab.com/bamboo/' } - - it 'returns a build URL' do - stub_request(body: bamboo_response) - - is_expected.to eq('http://gitlab.com/bamboo/browse/42') - end - end - end - - describe '#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 "pending" when response has no results' do - stub_request(body: %q({"results":{"results":{"size":"0"}}})) - - is_expected.to eq('pending') - end - - it 'sets commit status to "success" when build state contains Success' do - stub_request(body: bamboo_response(build_state: 'YAY Success!')) - - is_expected.to eq('success') - end - - it 'sets commit status to "failed" when build state contains Failed' do - stub_request(body: bamboo_response(build_state: 'NO Failed!')) - - is_expected.to eq('failed') - end - - it 'sets commit status to "pending" when build state contains Pending' do - stub_request(body: bamboo_response(build_state: 'NO Pending!')) - - is_expected.to eq('pending') - end - - it 'sets commit status to :error when build state is unknown' do - stub_request(body: bamboo_response(build_state: 'FOO BAR!')) - - 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, 'http://gitlab.com/bamboo/rest/api/latest/result/byChangeset/123?os_authType=basic') - .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 - - describe '#calculate_reactive_cache' do - context 'when Bamboo API returns single result' do - let(:bamboo_response_template) do - %q({"results":{"results":{"size":"1","result":{"buildState":"%{build_state}","planResultKey":{"key":"42"}}}}}) - end - - it_behaves_like 'reactive cache calculation' - end - - context 'when Bamboo API returns an array of results and we only consider the last one' do - let(:bamboo_response_template) do - %q({"results":{"results":{"size":"2","result":[{"buildState":"%{build_state}","planResultKey":{"key":"41"}},{"buildState":"%{build_state}","planResultKey":{"key":"42"}}]}}}) - end - - it_behaves_like 'reactive cache calculation' - end - end - - def stub_update_and_build_request(status: 200, body: nil) - bamboo_full_url = 'http://gitlab.com/bamboo/updateAndBuild.action?buildKey=foo&os_authType=basic' - - stub_bamboo_request(bamboo_full_url, status, body) - end - - def stub_request(status: 200, body: nil) - bamboo_full_url = 'http://gitlab.com/bamboo/rest/api/latest/result/byChangeset/123?os_authType=basic' - - stub_bamboo_request(bamboo_full_url, status, body) - end - - def stub_bamboo_request(url, status, body) - stub_full_request(url).to_return( - status: status, - headers: { 'Content-Type' => 'application/json' }, - body: body - ).with(basic_auth: %w(mic password)) - end - - def bamboo_response(build_state: 'success') - # reference: https://docs.atlassian.com/atlassian-bamboo/REST/6.2.5/#d2e786 - bamboo_response_template % { build_state: build_state } - end -end diff --git a/spec/models/project_services/campfire_service_spec.rb b/spec/models/project_services/campfire_service_spec.rb deleted file mode 100644 index ea3990b339b..00000000000 --- a/spec/models/project_services/campfire_service_spec.rb +++ /dev/null @@ -1,87 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe CampfireService 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(:user) { create(:user) } - let(:project) { create(:project, :repository) } - - before do - @campfire_service = described_class.new - allow(@campfire_service).to receive_messages( - project_id: project.id, - project: project, - service_hook: true, - token: 'verySecret', - subdomain: 'project-name', - room: 'test-room' - ) - @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user) - @rooms_url = 'https://project-name.campfirenow.com/rooms.json' - @auth = %w(verySecret X) - @headers = { 'Content-Type' => 'application/json; charset=utf-8' } - end - - it "calls Campfire API to get a list of rooms and speak in a room" do - # make sure a valid list of rooms is returned - body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms.json') - - stub_full_request(@rooms_url).with(basic_auth: @auth).to_return( - body: body, - status: 200, - headers: @headers - ) - - # stub the speak request with the room id found in the previous request's response - speak_url = 'https://project-name.campfirenow.com/room/123/speak.json' - stub_full_request(speak_url, method: :post).with(basic_auth: @auth) - - @campfire_service.execute(@sample_data) - - expect(WebMock).to have_requested(:get, stubbed_hostname(@rooms_url)).once - expect(WebMock).to have_requested(:post, stubbed_hostname(speak_url)) - .with(body: /#{project.path}.*#{@sample_data[:before]}.*#{@sample_data[:after]}/).once - end - - it "calls Campfire API to get a list of rooms but shouldn't speak in a room" do - # return a list of rooms that do not contain a room named 'test-room' - body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms2.json') - stub_full_request(@rooms_url).with(basic_auth: @auth).to_return( - body: body, - status: 200, - headers: @headers - ) - - @campfire_service.execute(@sample_data) - - expect(WebMock).to have_requested(:get, 'https://8.8.8.9/rooms.json').once - expect(WebMock).not_to have_requested(:post, '*/room/.*/speak.json') - end - end -end diff --git a/spec/models/project_services/chat_message/alert_message_spec.rb b/spec/models/project_services/chat_message/alert_message_spec.rb deleted file mode 100644 index 4d400990789..00000000000 --- a/spec/models/project_services/chat_message/alert_message_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ChatMessage::AlertMessage do - subject { described_class.new(args) } - - let_it_be(:start_time) { Time.current } - - let(:alert) { create(:alert_management_alert, started_at: start_time) } - - let(:args) do - { - project_name: 'project_name', - project_url: 'http://example.com' - }.merge(Gitlab::DataBuilder::Alert.build(alert)) - end - - describe '#message' do - it 'returns the correct message' do - expect(subject.message).to eq("Alert firing in #{args[:project_name]}") - end - end - - describe '#attachments' do - it 'returns an array of one' do - expect(subject.attachments).to be_a(Array) - expect(subject.attachments.size).to eq(1) - end - - it 'contains the correct attributes' do - attachments_item = subject.attachments.first - expect(attachments_item).to have_key(:title) - expect(attachments_item).to have_key(:title_link) - expect(attachments_item).to have_key(:color) - expect(attachments_item).to have_key(:fields) - end - - it 'returns the correct color' do - expect(subject.attachments.first[:color]).to eq("#C95823") - end - - it 'returns the correct attachment fields' do - attachments_item = subject.attachments.first - fields = attachments_item[:fields].map { |h| h[:title] } - - expect(fields).to match_array(['Severity', 'Events', 'Status', 'Start time']) - end - - it 'returns the correctly formatted time' do - time_item = subject.attachments.first[:fields].detect { |h| h[:title] == 'Start time' } - - expected_time = start_time.strftime("%B #{start_time.day.ordinalize}, %Y %l:%M%p %Z") - - expect(time_item[:value]).to eq(expected_time) - end - end -end diff --git a/spec/models/project_services/chat_message/base_message_spec.rb b/spec/models/project_services/chat_message/base_message_spec.rb deleted file mode 100644 index a7ddf230758..00000000000 --- a/spec/models/project_services/chat_message/base_message_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ChatMessage::BaseMessage do - let(:base_message) { described_class.new(args) } - let(:args) { { project_url: 'https://gitlab-domain.com' } } - - describe '#fallback' do - subject { base_message.fallback } - - before do - allow(base_message).to receive(:message).and_return(message) - end - - context 'without relative links' do - let(:message) { 'Just another *markdown* message' } - - it { is_expected.to eq(message) } - end - - context 'with relative links' do - let(:message) { 'Check this out ![Screenshot1](/uploads/Screenshot1.png)' } - - it { is_expected.to eq('Check this out https://gitlab-domain.com/uploads/Screenshot1.png') } - end - - context 'with multiple relative links' do - let(:message) { 'Check this out ![Screenshot1](/uploads/Screenshot1.png). And this ![Screenshot2](/uploads/Screenshot2.png)' } - - it { is_expected.to eq('Check this out https://gitlab-domain.com/uploads/Screenshot1.png. And this https://gitlab-domain.com/uploads/Screenshot2.png') } - end - end -end diff --git a/spec/models/project_services/chat_message/deployment_message_spec.rb b/spec/models/project_services/chat_message/deployment_message_spec.rb deleted file mode 100644 index 6bdf2120b36..00000000000 --- a/spec/models/project_services/chat_message/deployment_message_spec.rb +++ /dev/null @@ -1,164 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ChatMessage::DeploymentMessage do - describe '#pretext' do - it 'returns a message with the data returned by the deployment data builder' do - environment = create(:environment, name: "myenvironment") - project = create(:project, :repository) - commit = project.commit('HEAD') - deployment = create(:deployment, status: :success, environment: environment, project: project, sha: commit.sha) - data = Gitlab::DataBuilder::Deployment.build(deployment) - - message = described_class.new(data) - - expect(message.pretext).to eq("Deploy to myenvironment succeeded") - end - - it 'returns a message for a successful deployment' do - data = { - status: 'success', - environment: 'production' - } - - message = described_class.new(data) - - expect(message.pretext).to eq('Deploy to production succeeded') - end - - it 'returns a message for a failed deployment' do - data = { - status: 'failed', - environment: 'production' - } - - message = described_class.new(data) - - expect(message.pretext).to eq('Deploy to production failed') - end - - it 'returns a message for a canceled deployment' do - data = { - status: 'canceled', - environment: 'production' - } - - message = described_class.new(data) - - expect(message.pretext).to eq('Deploy to production canceled') - end - - it 'returns a message for a deployment to another environment' do - data = { - status: 'success', - environment: 'staging' - } - - message = described_class.new(data) - - expect(message.pretext).to eq('Deploy to staging succeeded') - end - - it 'returns a message for a deployment with any other status' do - data = { - status: 'unknown', - environment: 'staging' - } - - message = described_class.new(data) - - expect(message.pretext).to eq('Deploy to staging unknown') - end - - it 'returns a message for a running deployment' do - data = { - status: 'running', - environment: 'production' - } - - message = described_class.new(data) - - expect(message.pretext).to eq('Starting deploy to production') - end - end - - describe '#attachments' do - def deployment_data(params) - { - object_kind: "deployment", - status: "success", - deployable_id: 3, - deployable_url: "deployable_url", - environment: "sandbox", - project: { - name: "greatproject", - web_url: "project_web_url", - path_with_namespace: "project_path_with_namespace" - }, - user: { - name: "Jane Person", - username: "jane" - }, - user_url: "user_url", - short_sha: "12345678", - commit_url: "commit_url", - commit_title: "commit title text" - }.merge(params) - end - - it 'returns attachments with the data returned by the deployment data builder' do - user = create(:user, name: "John Smith", username: "smith") - namespace = create(:namespace, name: "myspace") - project = create(:project, :repository, namespace: namespace, name: "myproject") - commit = project.commit('HEAD') - environment = create(:environment, name: "myenvironment", project: project) - ci_build = create(:ci_build, project: project) - deployment = create(:deployment, :success, deployable: ci_build, environment: environment, project: project, user: user, sha: commit.sha) - job_url = Gitlab::Routing.url_helpers.project_job_url(project, ci_build) - commit_url = Gitlab::UrlBuilder.build(deployment.commit) - user_url = Gitlab::Routing.url_helpers.user_url(user) - data = Gitlab::DataBuilder::Deployment.build(deployment) - - message = described_class.new(data) - - expect(message.attachments).to eq([{ - text: "[myspace/myproject](#{project.web_url}) with job [##{ci_build.id}](#{job_url}) by [John Smith (smith)](#{user_url})\n[#{deployment.short_sha}](#{commit_url}): #{commit.title}", - color: "good" - }]) - end - - it 'returns attachments for a failed deployment' do - data = deployment_data(status: 'failed') - - message = described_class.new(data) - - expect(message.attachments).to eq([{ - text: "[project_path_with_namespace](project_web_url) with job [#3](deployable_url) by [Jane Person (jane)](user_url)\n[12345678](commit_url): commit title text", - color: "danger" - }]) - end - - it 'returns attachments for a canceled deployment' do - data = deployment_data(status: 'canceled') - - message = described_class.new(data) - - expect(message.attachments).to eq([{ - text: "[project_path_with_namespace](project_web_url) with job [#3](deployable_url) by [Jane Person (jane)](user_url)\n[12345678](commit_url): commit title text", - color: "warning" - }]) - end - - it 'uses a neutral color for a deployment with any other status' do - data = deployment_data(status: 'some-new-status-we-make-in-the-future') - - message = described_class.new(data) - - expect(message.attachments).to eq([{ - text: "[project_path_with_namespace](project_web_url) with job [#3](deployable_url) by [Jane Person (jane)](user_url)\n[12345678](commit_url): commit title text", - color: "#334455" - }]) - end - end -end diff --git a/spec/models/project_services/chat_message/issue_message_spec.rb b/spec/models/project_services/chat_message/issue_message_spec.rb deleted file mode 100644 index 4701ef3e49e..00000000000 --- a/spec/models/project_services/chat_message/issue_message_spec.rb +++ /dev/null @@ -1,124 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ChatMessage::IssueMessage do - subject { described_class.new(args) } - - let(:args) do - { - user: { - name: 'Test User', - username: 'test.user', - avatar_url: 'http://someavatar.com' - }, - project_name: 'project_name', - project_url: 'http://somewhere.com', - - object_attributes: { - title: 'Issue title', - id: 10, - iid: 100, - assignee_id: 1, - url: 'http://url.com', - action: 'open', - state: 'opened', - description: 'issue description' - } - } - end - - context 'without markdown' do - let(:color) { '#C95823' } - - describe '#initialize' do - before do - args[:object_attributes][:description] = nil - end - - it 'returns a non-null description' do - expect(subject.description).to eq('') - end - end - - context 'open' do - it 'returns a message regarding opening of issues' do - expect(subject.pretext).to eq( - '[<http://somewhere.com|project_name>] Issue <http://url.com|#100 Issue title> opened by Test User (test.user)') - expect(subject.attachments).to eq([ - { - title: "#100 Issue title", - title_link: "http://url.com", - text: "issue description", - color: color - } - ]) - end - end - - context 'close' do - before do - args[:object_attributes][:action] = 'close' - args[:object_attributes][:state] = 'closed' - end - - it 'returns a message regarding closing of issues' do - expect(subject.pretext). to eq( - '[<http://somewhere.com|project_name>] Issue <http://url.com|#100 Issue title> closed by Test User (test.user)') - expect(subject.attachments).to be_empty - end - end - - context 'reopen' do - before do - args[:object_attributes][:action] = 'reopen' - args[:object_attributes][:state] = 'opened' - end - - it 'returns a message regarding reopening of issues' do - expect(subject.pretext) - .to eq('[<http://somewhere.com|project_name>] Issue <http://url.com|#100 Issue title> opened by Test User (test.user)') - expect(subject.attachments).to be_empty - end - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - context 'open' do - it 'returns a message regarding opening of issues' do - expect(subject.pretext).to eq( - '[[project_name](http://somewhere.com)] Issue [#100 Issue title](http://url.com) opened by Test User (test.user)') - expect(subject.attachments).to eq('issue description') - expect(subject.activity).to eq({ - title: 'Issue opened by Test User (test.user)', - subtitle: 'in [project_name](http://somewhere.com)', - text: '[#100 Issue title](http://url.com)', - image: 'http://someavatar.com' - }) - end - end - - context 'close' do - before do - args[:object_attributes][:action] = 'close' - args[:object_attributes][:state] = 'closed' - end - - it 'returns a message regarding closing of issues' do - expect(subject.pretext). to eq( - '[[project_name](http://somewhere.com)] Issue [#100 Issue title](http://url.com) closed by Test User (test.user)') - expect(subject.attachments).to be_empty - expect(subject.activity).to eq({ - title: 'Issue closed by Test User (test.user)', - subtitle: 'in [project_name](http://somewhere.com)', - text: '[#100 Issue title](http://url.com)', - image: 'http://someavatar.com' - }) - end - end - end -end diff --git a/spec/models/project_services/chat_message/merge_message_spec.rb b/spec/models/project_services/chat_message/merge_message_spec.rb deleted file mode 100644 index 71cfe3ff45b..00000000000 --- a/spec/models/project_services/chat_message/merge_message_spec.rb +++ /dev/null @@ -1,144 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ChatMessage::MergeMessage do - subject { described_class.new(args) } - - let(:args) do - { - user: { - name: 'Test User', - username: 'test.user', - avatar_url: 'http://someavatar.com' - }, - project_name: 'project_name', - project_url: 'http://somewhere.com', - - object_attributes: { - title: "Merge request title\nSecond line", - id: 10, - iid: 100, - assignee_id: 1, - url: 'http://url.com', - state: 'opened', - description: 'merge request description', - source_branch: 'source_branch', - target_branch: 'target_branch' - } - } - end - - context 'without markdown' do - let(:color) { '#345' } - - context 'open' do - it 'returns a message regarding opening of merge requests' do - expect(subject.pretext).to eq( - 'Test User (test.user) opened merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> in <http://somewhere.com|project_name>') - expect(subject.attachments).to be_empty - end - end - - context 'close' do - before do - args[:object_attributes][:state] = 'closed' - end - it 'returns a message regarding closing of merge requests' do - expect(subject.pretext).to eq( - 'Test User (test.user) closed merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> in <http://somewhere.com|project_name>') - expect(subject.attachments).to be_empty - end - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - context 'open' do - it 'returns a message regarding opening of merge requests' do - expect(subject.pretext).to eq( - 'Test User (test.user) opened merge request [!100 *Merge request title*](http://somewhere.com/-/merge_requests/100) in [project_name](http://somewhere.com)') - expect(subject.attachments).to be_empty - expect(subject.activity).to eq({ - title: 'Merge request opened by Test User (test.user)', - subtitle: 'in [project_name](http://somewhere.com)', - text: '[!100 *Merge request title*](http://somewhere.com/-/merge_requests/100)', - image: 'http://someavatar.com' - }) - end - end - - context 'close' do - before do - args[:object_attributes][:state] = 'closed' - end - - it 'returns a message regarding closing of merge requests' do - expect(subject.pretext).to eq( - 'Test User (test.user) closed merge request [!100 *Merge request title*](http://somewhere.com/-/merge_requests/100) in [project_name](http://somewhere.com)') - expect(subject.attachments).to be_empty - expect(subject.activity).to eq({ - title: 'Merge request closed by Test User (test.user)', - subtitle: 'in [project_name](http://somewhere.com)', - text: '[!100 *Merge request title*](http://somewhere.com/-/merge_requests/100)', - image: 'http://someavatar.com' - }) - end - end - end - - context 'approved' do - before do - args[:object_attributes][:action] = 'approved' - end - - it 'returns a message regarding completed approval of merge requests' do - expect(subject.pretext).to eq( - 'Test User (test.user) approved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> '\ - 'in <http://somewhere.com|project_name>') - expect(subject.attachments).to be_empty - end - end - - context 'unapproved' do - before do - args[:object_attributes][:action] = 'unapproved' - end - - it 'returns a message regarding revocation of completed approval of merge requests' do - expect(subject.pretext).to eq( - 'Test User (test.user) unapproved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> '\ - 'in <http://somewhere.com|project_name>') - expect(subject.attachments).to be_empty - end - end - - context 'approval' do - before do - args[:object_attributes][:action] = 'approval' - end - - it 'returns a message regarding added approval of merge requests' do - expect(subject.pretext).to eq( - 'Test User (test.user) added their approval to merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> '\ - 'in <http://somewhere.com|project_name>') - expect(subject.attachments).to be_empty - end - end - - context 'unapproval' do - before do - args[:object_attributes][:action] = 'unapproval' - end - - it 'returns a message regarding revoking approval of merge requests' do - expect(subject.pretext).to eq( - 'Test User (test.user) removed their approval from merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> '\ - 'in <http://somewhere.com|project_name>') - expect(subject.attachments).to be_empty - end - end -end diff --git a/spec/models/project_services/chat_message/note_message_spec.rb b/spec/models/project_services/chat_message/note_message_spec.rb deleted file mode 100644 index 6a741365d55..00000000000 --- a/spec/models/project_services/chat_message/note_message_spec.rb +++ /dev/null @@ -1,192 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ChatMessage::NoteMessage do - subject { described_class.new(args) } - - let(:color) { '#345' } - let(:args) do - { - user: { - name: 'Test User', - username: 'test.user', - avatar_url: 'http://fakeavatar' - }, - project_name: 'project_name', - project_url: 'http://somewhere.com', - repository: { - name: 'project_name', - url: 'http://somewhere.com' - }, - object_attributes: { - id: 10, - note: 'comment on a commit', - url: 'http://url.com', - noteable_type: 'Commit' - } - } - end - - context 'commit notes' do - before do - args[:object_attributes][:note] = 'comment on a commit' - args[:object_attributes][:noteable_type] = 'Commit' - args[:commit] = { - id: '5f163b2b95e6f53cbd428f5f0b103702a52b9a23', - message: "Added a commit message\ndetails\n123\n" - } - end - - context 'without markdown' do - it 'returns a message regarding notes on commits' do - expect(subject.pretext).to eq("Test User (test.user) <http://url.com|commented on " \ - "commit 5f163b2b> in <http://somewhere.com|project_name>: " \ - "*Added a commit message*") - expect(subject.attachments).to eq([{ - text: 'comment on a commit', - color: color - }]) - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding notes on commits' do - expect(subject.pretext).to eq( - 'Test User (test.user) [commented on commit 5f163b2b](http://url.com) in [project_name](http://somewhere.com): *Added a commit message*' - ) - expect(subject.attachments).to eq('comment on a commit') - expect(subject.activity).to eq({ - title: 'Test User (test.user) [commented on commit 5f163b2b](http://url.com)', - subtitle: 'in [project_name](http://somewhere.com)', - text: 'Added a commit message', - image: 'http://fakeavatar' - }) - end - end - end - - context 'merge request notes' do - before do - args[:object_attributes][:note] = 'comment on a merge request' - args[:object_attributes][:noteable_type] = 'MergeRequest' - args[:merge_request] = { - id: 1, - iid: 30, - title: "merge request title\ndetails\n" - } - end - - context 'without markdown' do - it 'returns a message regarding notes on a merge request' do - expect(subject.pretext).to eq("Test User (test.user) <http://url.com|commented on " \ - "merge request !30> in <http://somewhere.com|project_name>: " \ - "*merge request title*") - expect(subject.attachments).to eq([{ - text: 'comment on a merge request', - color: color - }]) - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding notes on a merge request' do - expect(subject.pretext).to eq( - 'Test User (test.user) [commented on merge request !30](http://url.com) in [project_name](http://somewhere.com): *merge request title*') - expect(subject.attachments).to eq('comment on a merge request') - expect(subject.activity).to eq({ - title: 'Test User (test.user) [commented on merge request !30](http://url.com)', - subtitle: 'in [project_name](http://somewhere.com)', - text: 'merge request title', - image: 'http://fakeavatar' - }) - end - end - end - - context 'issue notes' do - before do - args[:object_attributes][:note] = 'comment on an issue' - args[:object_attributes][:noteable_type] = 'Issue' - args[:issue] = { - id: 1, - iid: 20, - title: "issue title\ndetails\n" - } - end - - context 'without markdown' do - it 'returns a message regarding notes on an issue' do - expect(subject.pretext).to eq( - "Test User (test.user) <http://url.com|commented on " \ - "issue #20> in <http://somewhere.com|project_name>: " \ - "*issue title*") - expect(subject.attachments).to eq([{ - text: 'comment on an issue', - color: color - }]) - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding notes on an issue' do - expect(subject.pretext).to eq( - 'Test User (test.user) [commented on issue #20](http://url.com) in [project_name](http://somewhere.com): *issue title*') - expect(subject.attachments).to eq('comment on an issue') - expect(subject.activity).to eq({ - title: 'Test User (test.user) [commented on issue #20](http://url.com)', - subtitle: 'in [project_name](http://somewhere.com)', - text: 'issue title', - image: 'http://fakeavatar' - }) - end - end - end - - context 'project snippet notes' do - before do - args[:object_attributes][:note] = 'comment on a snippet' - args[:object_attributes][:noteable_type] = 'Snippet' - args[:snippet] = { - id: 5, - title: "snippet title\ndetails\n" - } - end - - context 'without markdown' do - it 'returns a message regarding notes on a project snippet' do - expect(subject.pretext).to eq("Test User (test.user) <http://url.com|commented on " \ - "snippet $5> in <http://somewhere.com|project_name>: " \ - "*snippet title*") - expect(subject.attachments).to eq([{ - text: 'comment on a snippet', - color: color - }]) - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding notes on a project snippet' do - expect(subject.pretext).to eq( - 'Test User (test.user) [commented on snippet $5](http://url.com) in [project_name](http://somewhere.com): *snippet title*') - expect(subject.attachments).to eq('comment on a snippet') - end - end - end -end diff --git a/spec/models/project_services/chat_message/pipeline_message_spec.rb b/spec/models/project_services/chat_message/pipeline_message_spec.rb deleted file mode 100644 index 4eb2f57315b..00000000000 --- a/spec/models/project_services/chat_message/pipeline_message_spec.rb +++ /dev/null @@ -1,378 +0,0 @@ -# frozen_string_literal: true -require 'spec_helper' - -RSpec.describe ChatMessage::PipelineMessage do - subject { described_class.new(args) } - - let(:args) do - { - object_attributes: { - id: 123, - sha: '97de212e80737a608d939f648d959671fb0a0142', - tag: false, - ref: 'develop', - status: 'success', - detailed_status: nil, - duration: 7210, - finished_at: "2019-05-27 11:56:36 -0300" - }, - project: { - id: 234, - name: "project_name", - path_with_namespace: 'group/project_name', - web_url: 'http://example.gitlab.com', - avatar_url: 'http://example.com/project_avatar' - }, - user: { - id: 345, - name: "The Hacker", - username: "hacker", - email: "hacker@example.gitlab.com", - avatar_url: "http://example.com/avatar" - }, - commit: { - id: "abcdef" - }, - builds: nil, - markdown: false - } - end - - let(:has_yaml_errors) { false } - - before do - test_commit = double("A test commit", committer: args[:user], title: "A test commit message") - test_project = double("A test project", commit_by: test_commit, name: args[:project][:name], web_url: args[:project][:web_url]) - allow(test_project).to receive(:avatar_url).with(no_args).and_return("/avatar") - allow(test_project).to receive(:avatar_url).with(only_path: false).and_return(args[:project][:avatar_url]) - allow(Project).to receive(:find) { test_project } - - test_pipeline = double("A test pipeline", has_yaml_errors?: has_yaml_errors, - yaml_errors: "yaml error description here") - allow(Ci::Pipeline).to receive(:find) { test_pipeline } - - allow(Gitlab::UrlBuilder).to receive(:build).with(test_commit).and_return("http://example.com/commit") - allow(Gitlab::UrlBuilder).to receive(:build).with(args[:user]).and_return("http://example.gitlab.com/hacker") - end - - it 'returns an empty pretext' do - expect(subject.pretext).to be_empty - end - - it "returns the pipeline summary in the activity's title" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/-/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/-/commits/develop)" \ - " by The Hacker (hacker) has passed" - ) - end - - context "when the pipeline failed" do - before do - args[:object_attributes][:status] = 'failed' - end - - it "returns the summary with a 'failed' status" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/-/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/-/commits/develop)" \ - " by The Hacker (hacker) has failed" - ) - end - end - - context "when the pipeline passed with warnings" do - before do - args[:object_attributes][:detailed_status] = 'passed with warnings' - end - - it "returns the summary with a 'passed with warnings' status" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/-/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/-/commits/develop)" \ - " by The Hacker (hacker) has passed with warnings" - ) - end - end - - context 'when no user is provided because the pipeline was triggered by the API' do - before do - args[:user] = nil - end - - it "returns the summary with 'API' as the username" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/-/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/-/commits/develop)" \ - " by API has passed" - ) - end - end - - it "returns a link to the project in the activity's subtitle" do - expect(subject.activity[:subtitle]).to eq("in [project_name](http://example.gitlab.com)") - end - - it "returns the build duration in the activity's text property" do - expect(subject.activity[:text]).to eq("in 02:00:10") - end - - it "returns the user's avatar image URL in the activity's image property" do - expect(subject.activity[:image]).to eq("http://example.com/avatar") - end - - context 'when the user does not have an avatar' do - before do - args[:user][:avatar_url] = nil - end - - it "returns an empty string in the activity's image property" do - expect(subject.activity[:image]).to be_empty - end - end - - it "returns the pipeline summary as the attachment's fallback property" do - expect(subject.attachments.first[:fallback]).to eq( - "<http://example.gitlab.com|project_name>:" \ - " Pipeline <http://example.gitlab.com/-/pipelines/123|#123>" \ - " of branch <http://example.gitlab.com/-/commits/develop|develop>" \ - " by The Hacker (hacker) has passed in 02:00:10" - ) - end - - it "returns 'good' as the attachment's color property" do - expect(subject.attachments.first[:color]).to eq('good') - end - - context "when the pipeline failed" do - before do - args[:object_attributes][:status] = 'failed' - end - - it "returns 'danger' as the attachment's color property" do - expect(subject.attachments.first[:color]).to eq('danger') - end - end - - context "when the pipeline passed with warnings" do - before do - args[:object_attributes][:detailed_status] = 'passed with warnings' - end - - it "returns 'warning' as the attachment's color property" do - expect(subject.attachments.first[:color]).to eq('warning') - end - end - - it "returns the committer's name and username as the attachment's author_name property" do - expect(subject.attachments.first[:author_name]).to eq('The Hacker (hacker)') - end - - it "returns the committer's avatar URL as the attachment's author_icon property" do - expect(subject.attachments.first[:author_icon]).to eq('http://example.com/avatar') - end - - it "returns the committer's GitLab profile URL as the attachment's author_link property" do - expect(subject.attachments.first[:author_link]).to eq('http://example.gitlab.com/hacker') - end - - context 'when no user is provided because the pipeline was triggered by the API' do - before do - args[:user] = nil - end - - it "returns the committer's name and username as the attachment's author_name property" do - expect(subject.attachments.first[:author_name]).to eq('API') - end - - it "returns nil as the attachment's author_icon property" do - expect(subject.attachments.first[:author_icon]).to be_nil - end - - it "returns nil as the attachment's author_link property" do - expect(subject.attachments.first[:author_link]).to be_nil - end - end - - it "returns the pipeline ID, status, and duration as the attachment's title property" do - expect(subject.attachments.first[:title]).to eq("Pipeline #123 has passed in 02:00:10") - end - - it "returns the pipeline URL as the attachment's title_link property" do - expect(subject.attachments.first[:title_link]).to eq("http://example.gitlab.com/-/pipelines/123") - end - - it "returns two attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(2) - end - - it "returns the commit message as the attachment's second field property" do - expect(subject.attachments.first[:fields][0]).to eq({ - title: "Branch", - value: "<http://example.gitlab.com/-/commits/develop|develop>", - short: true - }) - end - - it "returns the ref name and link as the attachment's second field property" do - expect(subject.attachments.first[:fields][1]).to eq({ - title: "Commit", - value: "<http://example.com/commit|A test commit message>", - short: true - }) - end - - context "when a job in the pipeline fails" do - before do - args[:builds] = [ - { id: 1, name: "rspec", status: "failed", stage: "test" }, - { id: 2, name: "karma", status: "success", stage: "test" } - ] - end - - it "returns four attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(4) - end - - it "returns the stage name and link to the 'Failed jobs' tab on the pipeline's page as the attachment's third field property" do - expect(subject.attachments.first[:fields][2]).to eq({ - title: "Failed stage", - value: "<http://example.gitlab.com/-/pipelines/123/failures|test>", - short: true - }) - end - - it "returns the job name and link as the attachment's fourth field property" do - expect(subject.attachments.first[:fields][3]).to eq({ - title: "Failed job", - value: "<http://example.gitlab.com/-/jobs/1|rspec>", - short: true - }) - end - end - - context "when lots of jobs across multiple stages fail" do - before do - args[:builds] = (1..25).map do |i| - { id: i, name: "job-#{i}", status: "failed", stage: "stage-" + ((i % 3) + 1).to_s } - end - end - - it "returns the stage names and links to the 'Failed jobs' tab on the pipeline's page as the attachment's third field property" do - expect(subject.attachments.first[:fields][2]).to eq({ - title: "Failed stages", - value: "<http://example.gitlab.com/-/pipelines/123/failures|stage-2>, <http://example.gitlab.com/-/pipelines/123/failures|stage-1>, <http://example.gitlab.com/-/pipelines/123/failures|stage-3>", - short: true - }) - end - - it "returns the job names and links as the attachment's fourth field property" do - expected_jobs = 25.downto(16).map do |i| - "<http://example.gitlab.com/-/jobs/#{i}|job-#{i}>" - end - - expected_jobs << "and <http://example.gitlab.com/-/pipelines/123/failures|15 more>" - - expect(subject.attachments.first[:fields][3]).to eq({ - title: "Failed jobs", - value: expected_jobs.join(", "), - short: true - }) - end - end - - context "when jobs succeed on retries" do - before do - args[:builds] = [ - { id: 1, name: "job-1", status: "failed", stage: "stage-1" }, - { id: 2, name: "job-2", status: "failed", stage: "stage-2" }, - { id: 3, name: "job-3", status: "failed", stage: "stage-3" }, - { id: 7, name: "job-1", status: "failed", stage: "stage-1" }, - { id: 8, name: "job-1", status: "success", stage: "stage-1" } - ] - end - - it "do not return a job which succeeded on retry" do - expected_jobs = [ - "<http://example.gitlab.com/-/jobs/3|job-3>", - "<http://example.gitlab.com/-/jobs/2|job-2>" - ] - - expect(subject.attachments.first[:fields][3]).to eq( - title: "Failed jobs", - value: expected_jobs.join(", "), - short: true - ) - end - end - - context "when jobs failed even on retries" do - before do - args[:builds] = [ - { id: 1, name: "job-1", status: "failed", stage: "stage-1" }, - { id: 2, name: "job-2", status: "failed", stage: "stage-2" }, - { id: 3, name: "job-3", status: "failed", stage: "stage-3" }, - { id: 7, name: "job-1", status: "failed", stage: "stage-1" }, - { id: 8, name: "job-1", status: "failed", stage: "stage-1" } - ] - end - - it "returns only first instance of the failed job" do - expected_jobs = [ - "<http://example.gitlab.com/-/jobs/3|job-3>", - "<http://example.gitlab.com/-/jobs/2|job-2>", - "<http://example.gitlab.com/-/jobs/1|job-1>" - ] - - expect(subject.attachments.first[:fields][3]).to eq( - title: "Failed jobs", - value: expected_jobs.join(", "), - short: true - ) - end - end - - context "when the CI config file contains a YAML error" do - let(:has_yaml_errors) { true } - - it "returns three attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(3) - end - - it "returns the YAML error deatils as the attachment's third field property" do - expect(subject.attachments.first[:fields][2]).to eq({ - title: "Invalid CI config YAML file", - value: "yaml error description here", - short: false - }) - end - end - - it "returns the project's name as the attachment's footer property" do - expect(subject.attachments.first[:footer]).to eq("project_name") - end - - it "returns the project's avatar URL as the attachment's footer_icon property" do - expect(subject.attachments.first[:footer_icon]).to eq("http://example.com/project_avatar") - end - - it "returns the pipeline's timestamp as the attachment's ts property" do - expected_ts = Time.parse(args[:object_attributes][:finished_at]).to_i - expect(subject.attachments.first[:ts]).to eq(expected_ts) - end - - context 'when rendering markdown' do - before do - args[:markdown] = true - end - - it 'returns the pipeline summary as the attachments in markdown format' do - expect(subject.attachments).to eq( - "[project_name](http://example.gitlab.com):" \ - " Pipeline [#123](http://example.gitlab.com/-/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/-/commits/develop)" \ - " by The Hacker (hacker) has passed in 02:00:10" - ) - end - end -end diff --git a/spec/models/project_services/chat_message/push_message_spec.rb b/spec/models/project_services/chat_message/push_message_spec.rb deleted file mode 100644 index e3ba4c2aefe..00000000000 --- a/spec/models/project_services/chat_message/push_message_spec.rb +++ /dev/null @@ -1,215 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ChatMessage::PushMessage do - subject { described_class.new(args) } - - let(:args) do - { - after: 'after', - before: 'before', - project_name: 'project_name', - ref: 'refs/heads/master', - user_name: 'test.user', - user_avatar: 'http://someavatar.com', - project_url: 'http://url.com' - } - end - - let(:color) { '#345' } - - context 'push' do - before do - args[:commits] = [ - { message: 'message1', title: 'message1', url: 'http://url1.com', id: 'abcdefghijkl', author: { name: 'author1' } }, - { - message: 'message2' + ' w' * 100 + "\nsecondline", - title: 'message2 w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ...', - url: 'http://url2.com', - id: '123456789012', - author: { name: 'author2' } - } - ] - end - - context 'without markdown' do - it 'returns a message regarding pushes' do - expect(subject.pretext).to eq( - 'test.user pushed to branch <http://url.com/commits/master|master> of '\ - '<http://url.com|project_name> (<http://url.com/compare/before...after|Compare changes>)') - expect(subject.attachments).to eq([{ - text: "<http://url1.com|abcdefgh>: message1 - author1\n\n"\ - "<http://url2.com|12345678>: message2 w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ... - author2", - color: color - }]) - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding pushes' do - expect(subject.pretext).to eq( - 'test.user pushed to branch [master](http://url.com/commits/master) of [project_name](http://url.com) ([Compare changes](http://url.com/compare/before...after))') - expect(subject.attachments).to eq( - "[abcdefgh](http://url1.com): message1 - author1\n\n[12345678](http://url2.com): message2 w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ... - author2") - expect(subject.activity).to eq( - title: 'test.user pushed to branch [master](http://url.com/commits/master)', - subtitle: 'in [project_name](http://url.com)', - text: '[Compare changes](http://url.com/compare/before...after)', - image: 'http://someavatar.com' - ) - end - end - end - - context 'tag push' do - let(:args) do - { - after: 'after', - before: Gitlab::Git::BLANK_SHA, - project_name: 'project_name', - ref: 'refs/tags/new_tag', - user_name: 'test.user', - user_avatar: 'http://someavatar.com', - project_url: 'http://url.com' - } - end - - context 'without markdown' do - it 'returns a message regarding pushes' do - expect(subject.pretext).to eq('test.user pushed new tag ' \ - '<http://url.com/-/tags/new_tag|new_tag> to ' \ - '<http://url.com|project_name>') - expect(subject.attachments).to be_empty - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding pushes' do - expect(subject.pretext).to eq( - 'test.user pushed new tag [new_tag](http://url.com/-/tags/new_tag) to [project_name](http://url.com)') - expect(subject.attachments).to be_empty - expect(subject.activity).to eq( - title: 'test.user pushed new tag [new_tag](http://url.com/-/tags/new_tag)', - subtitle: 'in [project_name](http://url.com)', - text: '[Compare changes](http://url.com/compare/0000000000000000000000000000000000000000...after)', - image: 'http://someavatar.com' - ) - end - end - end - - context 'removed tag' do - let(:args) do - { - after: Gitlab::Git::BLANK_SHA, - before: 'before', - project_name: 'project_name', - ref: 'refs/tags/new_tag', - user_name: 'test.user', - user_avatar: 'http://someavatar.com', - project_url: 'http://url.com' - } - end - - context 'without markdown' do - it 'returns a message regarding removal of tags' do - expect(subject.pretext).to eq('test.user removed tag ' \ - 'new_tag from ' \ - '<http://url.com|project_name>') - expect(subject.attachments).to be_empty - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding removal of tags' do - expect(subject.pretext).to eq( - 'test.user removed tag new_tag from [project_name](http://url.com)') - expect(subject.attachments).to be_empty - expect(subject.activity).to eq( - title: 'test.user removed tag new_tag', - subtitle: 'in [project_name](http://url.com)', - text: '[Compare changes](http://url.com/compare/before...0000000000000000000000000000000000000000)', - image: 'http://someavatar.com' - ) - end - end - end - - context 'new branch' do - before do - args[:before] = Gitlab::Git::BLANK_SHA - end - - context 'without markdown' do - it 'returns a message regarding a new branch' do - expect(subject.pretext).to eq( - 'test.user pushed new branch <http://url.com/commits/master|master> to '\ - '<http://url.com|project_name>') - expect(subject.attachments).to be_empty - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding a new branch' do - expect(subject.pretext).to eq( - 'test.user pushed new branch [master](http://url.com/commits/master) to [project_name](http://url.com)') - expect(subject.attachments).to be_empty - expect(subject.activity).to eq( - title: 'test.user pushed new branch [master](http://url.com/commits/master)', - subtitle: 'in [project_name](http://url.com)', - text: '[Compare changes](http://url.com/compare/0000000000000000000000000000000000000000...after)', - image: 'http://someavatar.com' - ) - end - end - end - - context 'removed branch' do - before do - args[:after] = Gitlab::Git::BLANK_SHA - end - - context 'without markdown' do - it 'returns a message regarding a removed branch' do - expect(subject.pretext).to eq( - 'test.user removed branch master from <http://url.com|project_name>') - expect(subject.attachments).to be_empty - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - it 'returns a message regarding a removed branch' do - expect(subject.pretext).to eq( - 'test.user removed branch master from [project_name](http://url.com)') - expect(subject.attachments).to be_empty - expect(subject.activity).to eq( - title: 'test.user removed branch master', - subtitle: 'in [project_name](http://url.com)', - text: '[Compare changes](http://url.com/compare/before...0000000000000000000000000000000000000000)', - image: 'http://someavatar.com' - ) - end - end - end -end diff --git a/spec/models/project_services/chat_message/wiki_page_message_spec.rb b/spec/models/project_services/chat_message/wiki_page_message_spec.rb deleted file mode 100644 index 04c9e5934be..00000000000 --- a/spec/models/project_services/chat_message/wiki_page_message_spec.rb +++ /dev/null @@ -1,171 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ChatMessage::WikiPageMessage do - subject { described_class.new(args) } - - let(:args) do - { - user: { - name: 'Test User', - username: 'test.user', - avatar_url: 'http://someavatar.com' - }, - project_name: 'project_name', - project_url: 'http://somewhere.com', - object_attributes: { - title: 'Wiki page title', - url: 'http://url.com', - content: 'Wiki page content', - message: 'Wiki page commit message' - } - } - end - - context 'without markdown' do - describe '#pretext' do - context 'when :action == "create"' do - before do - args[:object_attributes][:action] = 'create' - end - - it 'returns a message that a new wiki page was created' do - expect(subject.pretext).to eq( - 'Test User (test.user) created <http://url.com|wiki page> in <http://somewhere.com|project_name>: '\ - '*Wiki page title*') - end - end - - context 'when :action == "update"' do - before do - args[:object_attributes][:action] = 'update' - end - - it 'returns a message that a wiki page was updated' do - expect(subject.pretext).to eq( - 'Test User (test.user) edited <http://url.com|wiki page> in <http://somewhere.com|project_name>: '\ - '*Wiki page title*') - end - end - end - - describe '#attachments' do - let(:color) { '#345' } - - context 'when :action == "create"' do - before do - args[:object_attributes][:action] = 'create' - end - - it 'returns the commit message for a new wiki page' do - expect(subject.attachments).to eq([ - { - text: "Wiki page commit message", - color: color - } - ]) - end - end - - context 'when :action == "update"' do - before do - args[:object_attributes][:action] = 'update' - end - - it 'returns the commit message for an updated wiki page' do - expect(subject.attachments).to eq([ - { - text: "Wiki page commit message", - color: color - } - ]) - end - end - end - end - - context 'with markdown' do - before do - args[:markdown] = true - end - - describe '#pretext' do - context 'when :action == "create"' do - before do - args[:object_attributes][:action] = 'create' - end - - it 'returns a message that a new wiki page was created' do - expect(subject.pretext).to eq( - 'Test User (test.user) created [wiki page](http://url.com) in [project_name](http://somewhere.com): *Wiki page title*') - end - end - - context 'when :action == "update"' do - before do - args[:object_attributes][:action] = 'update' - end - - it 'returns a message that a wiki page was updated' do - expect(subject.pretext).to eq( - 'Test User (test.user) edited [wiki page](http://url.com) in [project_name](http://somewhere.com): *Wiki page title*') - end - end - end - - describe '#attachments' do - context 'when :action == "create"' do - before do - args[:object_attributes][:action] = 'create' - end - - it 'returns the commit message for a new wiki page' do - expect(subject.attachments).to eq('Wiki page commit message') - end - end - - context 'when :action == "update"' do - before do - args[:object_attributes][:action] = 'update' - end - - it 'returns the commit message for an updated wiki page' do - expect(subject.attachments).to eq('Wiki page commit message') - end - end - end - - describe '#activity' do - context 'when :action == "create"' do - before do - args[:object_attributes][:action] = 'create' - end - - it 'returns the attachment for a new wiki page' do - expect(subject.activity).to eq({ - title: 'Test User (test.user) created [wiki page](http://url.com)', - subtitle: 'in [project_name](http://somewhere.com)', - text: 'Wiki page title', - image: 'http://someavatar.com' - }) - end - end - - context 'when :action == "update"' do - before do - args[:object_attributes][:action] = 'update' - end - - it 'returns the attachment for an updated wiki page' do - expect(subject.activity).to eq({ - title: 'Test User (test.user) edited [wiki page](http://url.com)', - subtitle: 'in [project_name](http://somewhere.com)', - text: 'Wiki page title', - image: 'http://someavatar.com' - }) - end - end - end - end -end diff --git a/spec/models/project_services/chat_notification_service_spec.rb b/spec/models/project_services/chat_notification_service_spec.rb index 476d99364b6..62f97873a06 100644 --- a/spec/models/project_services/chat_notification_service_spec.rb +++ b/spec/models/project_services/chat_notification_service_spec.rb @@ -11,6 +11,10 @@ RSpec.describe ChatNotificationService do 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 @@ -32,8 +36,9 @@ RSpec.describe ChatNotificationService do describe '#execute' do subject(:chat_service) { described_class.new } + let_it_be(:project) { create(:project, :repository) } + let(:user) { create(:user) } - let(:project) { create(:project, :repository) } let(:webhook_url) { 'https://example.gitlab.com/' } let(:data) { Gitlab::DataBuilder::Push.build_sample(subject.project, user) } @@ -76,9 +81,12 @@ RSpec.describe ChatNotificationService do end context 'when the data object has a label' do - let(:label) { create(:label, project: project, name: 'Bug')} - let(:issue) { create(:labeled_issue, project: project, labels: [label]) } - let(:note) { create(:note, noteable: issue, project: project)} + 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 @@ -87,23 +95,139 @@ RSpec.describe ChatNotificationService do chat_service.execute(data) end - context 'and the chat_service has a label filter that does not matches the label' do - subject(:chat_service) { described_class.new(labels_to_be_notified: '~some random label') } + shared_examples 'notifies the chat service' do + specify do + expect(chat_service).to receive(:notify).with(any_args) + + chat_service.execute(data) + end + end - it 'does not notify the chat service' do - expect(chat_service).not_to receive(:notify) + 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 'and the chat_service has a label filter that matches the label' do - subject(:chat_service) { described_class.new(labels_to_be_notified: '~Backend, ~Bug') } + context 'when labels_to_be_notified_behavior is not defined' do + subject(:chat_service) { described_class.new(labels_to_be_notified: label_filter) } - it 'notifies the chat service' do - expect(chat_service).to receive(:notify).with(any_args) + context 'no matching labels' do + let(:label_filter) { '~some random label' } - chat_service.execute(data) + 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 diff --git a/spec/models/project_services/confluence_service_spec.rb b/spec/models/project_services/confluence_service_spec.rb deleted file mode 100644 index 6c7ba2c9f32..00000000000 --- a/spec/models/project_services/confluence_service_spec.rb +++ /dev/null @@ -1,90 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ConfluenceService do - describe 'Associations' do - it { is_expected.to belong_to :project } - it { is_expected.to have_one :service_hook } - end - - describe 'Validations' do - before do - subject.active = active - end - - context 'when service is active' do - let(:active) { true } - - it { is_expected.not_to allow_value('https://example.com').for(:confluence_url) } - it { is_expected.not_to allow_value('example.com').for(:confluence_url) } - it { is_expected.not_to allow_value('foo').for(:confluence_url) } - it { is_expected.not_to allow_value('ftp://example.atlassian.net/wiki').for(:confluence_url) } - it { is_expected.not_to allow_value('https://example.atlassian.net').for(:confluence_url) } - it { is_expected.not_to allow_value('https://.atlassian.net/wiki').for(:confluence_url) } - it { is_expected.not_to allow_value('https://example.atlassian.net/wikifoo').for(:confluence_url) } - it { is_expected.not_to allow_value('').for(:confluence_url) } - it { is_expected.not_to allow_value(nil).for(:confluence_url) } - it { is_expected.not_to allow_value('😊').for(:confluence_url) } - it { is_expected.to allow_value('https://example.atlassian.net/wiki').for(:confluence_url) } - it { is_expected.to allow_value('http://example.atlassian.net/wiki').for(:confluence_url) } - it { is_expected.to allow_value('https://example.atlassian.net/wiki/').for(:confluence_url) } - it { is_expected.to allow_value('http://example.atlassian.net/wiki/').for(:confluence_url) } - it { is_expected.to allow_value('https://example.atlassian.net/wiki/foo').for(:confluence_url) } - - it { is_expected.to validate_presence_of(:confluence_url) } - end - - context 'when service is inactive' do - let(:active) { false } - - it { is_expected.not_to validate_presence_of(:confluence_url) } - it { is_expected.to allow_value('foo').for(:confluence_url) } - end - end - - describe '#help' do - it 'can correctly return a link to the project wiki when active' do - project = create(:project) - subject.project = project - subject.active = true - - expect(subject.help).to include(Gitlab::Routing.url_helpers.project_wikis_url(project)) - end - - context 'when the project wiki is not enabled' do - it 'returns nil when both active or inactive', :aggregate_failures do - project = create(:project, :wiki_disabled) - subject.project = project - - [true, false].each do |active| - subject.active = active - - expect(subject.help).to be_nil - end - end - end - end - - describe 'Caching has_confluence on project_settings' do - let(:project) { create(:project) } - - subject { project.project_setting.has_confluence? } - - it 'sets the property to true when service is active' do - create(:confluence_service, project: project, active: true) - - is_expected.to be(true) - end - - it 'sets the property to false when service is not active' do - create(:confluence_service, project: project, active: false) - - is_expected.to be(false) - end - - it 'creates a project_setting record if one was not already created' do - expect { create(:confluence_service) }.to change { ProjectSetting.count }.by(1) - end - end -end diff --git a/spec/models/project_services/data_fields_spec.rb b/spec/models/project_services/data_fields_spec.rb index 9a3042f9f8d..d3e6afe4978 100644 --- a/spec/models/project_services/data_fields_spec.rb +++ b/spec/models/project_services/data_fields_spec.rb @@ -138,8 +138,8 @@ RSpec.describe DataFields do 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 |service| - create(:jira_tracker_data, properties.merge(service: service)) + create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |integration| + create(:jira_tracker_data, properties.merge(integration: integration)) end end diff --git a/spec/models/project_services/datadog_service_spec.rb b/spec/models/project_services/datadog_service_spec.rb deleted file mode 100644 index d15ea1f351b..00000000000 --- a/spec/models/project_services/datadog_service_spec.rb +++ /dev/null @@ -1,185 +0,0 @@ -# frozen_string_literal: true -require 'securerandom' - -require 'spec_helper' - -RSpec.describe DatadogService, :model do - let_it_be(:project) { create(:project) } - let_it_be(:pipeline) { create(:ci_pipeline, project: project) } - let_it_be(:build) { create(:ci_build, project: project) } - - let(:active) { true } - let(:dd_site) { 'datadoghq.com' } - let(:default_url) { 'https://webhooks-http-intake.logs.datadoghq.com/v1/input/' } - let(:api_url) { '' } - let(:api_key) { SecureRandom.hex(32) } - let(:dd_env) { 'ci' } - let(:dd_service) { 'awesome-gitlab' } - - let(:expected_hook_url) { default_url + api_key + "?env=#{dd_env}&service=#{dd_service}" } - - let(:instance) do - described_class.new( - active: active, - project: project, - datadog_site: dd_site, - api_url: api_url, - api_key: api_key, - datadog_env: dd_env, - datadog_service: dd_service - ) - end - - let(:saved_instance) do - instance.save! - instance - end - - let(:pipeline_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } - let(:build_data) { Gitlab::DataBuilder::Build.build(build) } - - describe 'associations' do - it { is_expected.to belong_to(:project) } - it { is_expected.to have_one(:service_hook) } - end - - describe 'validations' do - subject { instance } - - context 'when service is active' do - let(:active) { true } - - it { is_expected.to validate_presence_of(:api_key) } - it { is_expected.to allow_value(api_key).for(:api_key) } - it { is_expected.not_to allow_value('87dab2403c9d462 87aec4d9214edb1e').for(:api_key) } - it { is_expected.not_to allow_value('................................').for(:api_key) } - - context 'when selecting site' do - let(:dd_site) { 'datadoghq.com' } - let(:api_url) { '' } - - it { is_expected.to validate_presence_of(:datadog_site) } - it { is_expected.not_to validate_presence_of(:api_url) } - it { is_expected.not_to allow_value('datadog hq.com').for(:datadog_site) } - end - - context 'with custom api_url' do - let(:dd_site) { '' } - let(:api_url) { 'https://webhooks-http-intake.logs.datad0g.com/v1/input/' } - - it { is_expected.not_to validate_presence_of(:datadog_site) } - it { is_expected.to validate_presence_of(:api_url) } - it { is_expected.to allow_value(api_url).for(:api_url) } - it { is_expected.not_to allow_value('example.com').for(:api_url) } - end - - context 'when missing site and api_url' do - let(:dd_site) { '' } - let(:api_url) { '' } - - it { is_expected.not_to be_valid } - it { is_expected.to validate_presence_of(:datadog_site) } - it { is_expected.to validate_presence_of(:api_url) } - end - - context 'when providing both site and api_url' do - let(:dd_site) { 'datadoghq.com' } - let(:api_url) { default_url } - - it { is_expected.not_to allow_value('datadog hq.com').for(:datadog_site) } - it { is_expected.not_to allow_value('example.com').for(:api_url) } - end - end - - context 'when service is not active' do - let(:active) { false } - - it { is_expected.to be_valid } - it { is_expected.not_to validate_presence_of(:api_key) } - end - end - - describe '#hook_url' do - subject { instance.hook_url } - - context 'with standard site URL' do - it { is_expected.to eq(expected_hook_url) } - end - - context 'with custom URL' do - let(:api_url) { 'https://webhooks-http-intake.logs.datad0g.com/v1/input/' } - - it { is_expected.to eq(api_url + api_key + "?env=#{dd_env}&service=#{dd_service}") } - - context 'blank' do - let(:api_url) { '' } - - it { is_expected.to eq(expected_hook_url) } - end - end - - context 'without optional params' do - let(:dd_service) { '' } - let(:dd_env) { '' } - - it { is_expected.to eq(default_url + api_key) } - end - end - - describe '#api_keys_url' do - subject { instance.api_keys_url } - - it { is_expected.to eq("https://app.#{dd_site}/account/settings#api") } - - context 'with unset datadog_site' do - let(:dd_site) { '' } - - it { is_expected.to eq("https://docs.datadoghq.com/account_management/api-app-keys/") } - end - end - - describe '#test' do - context 'when request is succesful' do - subject { saved_instance.test(pipeline_data) } - - before do - stub_request(:post, expected_hook_url).to_return(body: 'OK') - end - it { is_expected.to eq({ success: true, result: 'OK' }) } - end - - context 'when request fails' do - subject { saved_instance.test(pipeline_data) } - - before do - stub_request(:post, expected_hook_url).to_return(body: 'CRASH!!!', status: 500) - end - it { is_expected.to eq({ success: false, result: 'CRASH!!!' }) } - end - end - - describe '#execute' do - before do - stub_request(:post, expected_hook_url) - saved_instance.execute(data) - end - - context 'with pipeline data' do - let(:data) { pipeline_data } - let(:expected_headers) do - { WebHookService::GITLAB_EVENT_HEADER => 'Pipeline Hook' } - end - - it { expect(a_request(:post, expected_hook_url).with(headers: expected_headers)).to have_been_made } - end - - context 'with job data' do - let(:data) { build_data } - let(:expected_headers) do - { WebHookService::GITLAB_EVENT_HEADER => 'Job Hook' } - end - - it { expect(a_request(:post, expected_hook_url).with(headers: expected_headers)).to have_been_made } - end - end -end diff --git a/spec/models/project_services/emails_on_push_service_spec.rb b/spec/models/project_services/emails_on_push_service_spec.rb deleted file mode 100644 index c5927503eec..00000000000 --- a/spec/models/project_services/emails_on_push_service_spec.rb +++ /dev/null @@ -1,163 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe EmailsOnPushService do - let_it_be(:project) { create_default(:project).freeze } - - 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 - - describe 'validates number of recipients' do - before do - stub_const("#{described_class}::RECIPIENTS_LIMIT", 2) - end - - subject(:service) { described_class.new(project: project, recipients: recipients, active: true) } - - context 'valid number of recipients' do - let(:recipients) { 'foo@bar.com duplicate@example.com Duplicate@example.com invalid-email' } - - it 'does not count duplicates and invalid emails' do - is_expected.to be_valid - end - end - - context 'invalid number of recipients' do - let(:recipients) { 'foo@bar.com bar@foo.com bob@gitlab.com' } - - it { is_expected.not_to be_valid } - - it 'adds an error message' do - service.valid? - - expect(service.errors).to contain_exactly('Recipients can\'t exceed 2') - end - - context 'when service is not active' do - before do - service.active = false - end - - it { is_expected.to be_valid } - end - end - end - end - - describe '.new' do - context 'when properties is missing branches_to_be_notified' do - subject { described_class.new(properties: {}) } - - it 'sets the default value to all' do - expect(subject.branches_to_be_notified).to eq('all') - end - end - - context 'when branches_to_be_notified is already set' do - subject { described_class.new(properties: { branches_to_be_notified: 'protected' }) } - - it 'does not overwrite it with the default value' do - expect(subject.branches_to_be_notified).to eq('protected') - end - end - end - - describe '.valid_recipients' do - let(:recipients) { '<invalid> foobar Valid@recipient.com Dup@lica.te dup@lica.te Dup@Lica.te' } - - it 'removes invalid email addresses and removes duplicates by keeping the original capitalization' do - expect(described_class.valid_recipients(recipients)).to contain_exactly('Valid@recipient.com', 'Dup@lica.te') - end - end - - describe '#execute' do - let(:push_data) { { object_kind: 'push' } } - let(:project) { create(:project, :repository) } - let(:service) { create(:emails_on_push_service, project: project) } - let(:recipients) { 'test@gitlab.com' } - - before do - subject.recipients = recipients - end - - shared_examples 'sending email' do |branches_to_be_notified, branch_being_pushed_to| - let(:push_data) { { object_kind: 'push', object_attributes: { ref: branch_being_pushed_to } } } - - before do - subject.branches_to_be_notified = branches_to_be_notified - end - - it 'sends email' do - expect(EmailsOnPushWorker).not_to receive(:perform_async) - - service.execute(push_data) - end - end - - shared_examples 'not sending email' do |branches_to_be_notified, branch_being_pushed_to| - let(:push_data) { { object_kind: 'push', object_attributes: { ref: branch_being_pushed_to } } } - - before do - subject.branches_to_be_notified = branches_to_be_notified - end - - it 'does not send email' do - expect(EmailsOnPushWorker).not_to receive(:perform_async) - - service.execute(push_data) - end - end - - context 'when emails are disabled on the project' do - it 'does not send emails' do - expect(project).to receive(:emails_disabled?).and_return(true) - expect(EmailsOnPushWorker).not_to receive(:perform_async) - - service.execute(push_data) - end - end - - context 'when emails are enabled on the project' do - before do - create(:protected_branch, project: project, name: 'a-protected-branch') - expect(project).to receive(:emails_disabled?).and_return(true) - end - - using RSpec::Parameterized::TableSyntax - - where(:case_name, :branches_to_be_notified, :branch_being_pushed_to, :expected_action) do - 'pushing to a random branch and notification configured for all branches' | 'all' | 'random' | 'sending email' - 'pushing to the default branch and notification configured for all branches' | 'all' | 'master' | 'sending email' - 'pushing to a protected branch and notification configured for all branches' | 'all' | 'a-protected-branch' | 'sending email' - 'pushing to a random branch and notification configured for default branch only' | 'default' | 'random' | 'not sending email' - 'pushing to the default branch and notification configured for default branch only' | 'default' | 'master' | 'sending email' - 'pushing to a protected branch and notification configured for default branch only' | 'default' | 'a-protected-branch' | 'not sending email' - 'pushing to a random branch and notification configured for protected branches only' | 'protected' | 'random' | 'not sending email' - 'pushing to the default branch and notification configured for protected branches only' | 'protected' | 'master' | 'not sending email' - 'pushing to a protected branch and notification configured for protected branches only' | 'protected' | 'a-protected-branch' | 'sending email' - 'pushing to a random branch and notification configured for default and protected branches only' | 'default_and_protected' | 'random' | 'not sending email' - 'pushing to the default branch and notification configured for default and protected branches only' | 'default_and_protected' | 'master' | 'sending email' - 'pushing to a protected branch and notification configured for default and protected branches only' | 'default_and_protected' | 'a-protected-branch' | 'sending email' - end - - with_them do - include_examples params[:expected_action], branches_to_be_notified: params[:branches_to_be_notified], branch_being_pushed_to: params[:branch_being_pushed_to] - end - end - end -end diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb index 82a4cde752b..42368c31ba0 100644 --- a/spec/models/project_services/hipchat_service_spec.rb +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -2,91 +2,35 @@ 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 - describe "Associations" do - it { is_expected.to belong_to :project } - it { is_expected.to have_one :service_hook } - end + let_it_be(:project) { create(:project) } - describe 'Validations' do - context 'when service is active' do - before do - subject.active = true - end + subject(:service) { described_class.new(project: project) } - it { is_expected.to validate_presence_of(:token) } - end + it { is_expected.to be_valid } - context 'when service is inactive' do - before do - subject.active = false - end + describe '#to_param' do + subject { service.to_param } - it { is_expected.not_to validate_presence_of(:token) } - end + it { is_expected.to eq('hipchat') } end - describe "Execute" do - let(:hipchat) { described_class.new } - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:api_url) { 'https://hipchat.example.com/v2/room/123456/notification?auth_token=verySecret' } - let(:project_name) { project.full_name.gsub(/\s/, '') } - let(:token) { 'verySecret' } - let(:server_url) { 'https://hipchat.example.com'} - let(:push_sample_data) do - Gitlab::DataBuilder::Push.build_sample(project, user) - end - - before do - allow(hipchat).to receive_messages( - project_id: project.id, - project: project, - room: 123456, - server: server_url, - token: token - ) - WebMock.stub_request(:post, api_url) - end - - it 'does nothing' do - expect { hipchat.execute(push_sample_data) }.not_to raise_error - end + describe '#supported_events' do + subject { service.supported_events } - describe "#message_options" do - it "is set to the defaults" do - expect(hipchat.__send__(:message_options)).to eq({ notify: false, color: 'yellow' }) - end - - it "sets notify to true" do - allow(hipchat).to receive(:notify).and_return('1') - - expect(hipchat.__send__(:message_options)).to eq({ notify: true, color: 'yellow' }) - end - - it "sets the color" do - allow(hipchat).to receive(:color).and_return('red') - - expect(hipchat.__send__(:message_options)).to eq({ notify: false, color: 'red' }) - end - - context 'with a successful build' do - it 'uses the green color' do - data = { object_kind: 'pipeline', - object_attributes: { status: 'success' } } - - expect(hipchat.__send__(:message_options, data)).to eq({ notify: false, color: 'green' }) - end - end + it { is_expected.to be_empty } + end - context 'with a failed build' do - it 'uses the red color' do - data = { object_kind: 'pipeline', - object_attributes: { status: 'failed' } } + describe '#save' do + it 'prevents records from being created or updated' do + expect(service.save).to be_falsey - expect(hipchat.__send__(:message_options, data)).to eq({ notify: false, color: 'red' }) - end - end + 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/issue_tracker_data_spec.rb b/spec/models/project_services/issue_tracker_data_spec.rb index 3ddb7d9250f..a229285f09b 100644 --- a/spec/models/project_services/issue_tracker_data_spec.rb +++ b/spec/models/project_services/issue_tracker_data_spec.rb @@ -3,9 +3,7 @@ require 'spec_helper' RSpec.describe IssueTrackerData do - let(:service) { create(:custom_issue_tracker_service, active: false, properties: {}) } - - describe 'Associations' do - it { is_expected.to belong_to :service } + describe 'associations' do + it { is_expected.to belong_to :integration } end end diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index b50fa1edbc3..73e91bf9ea8 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -433,8 +433,8 @@ RSpec.describe JiraService do 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 |service| - create(:jira_tracker_data, data_params.merge(service: service)) + create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |integration| + create(:jira_tracker_data, data_params.merge(integration: integration)) end end diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/project_services/jira_tracker_data_spec.rb index a698d3fce5f..72bdbe40a74 100644 --- a/spec/models/project_services/jira_tracker_data_spec.rb +++ b/spec/models/project_services/jira_tracker_data_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe JiraTrackerData do describe 'associations' do - it { is_expected.to belong_to(:service) } + it { is_expected.to belong_to(:integration) } end describe 'deployment_type' do diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb index 4fff3bc56cc..87befdd4303 100644 --- a/spec/models/project_services/mattermost_slash_commands_service_spec.rb +++ b/spec/models/project_services/mattermost_slash_commands_service_spec.rb @@ -49,7 +49,7 @@ RSpec.describe MattermostSlashCommandsService do end it 'saves the service' do - expect { subject }.to change { project.services.count }.by(1) + expect { subject }.to change { project.integrations.count }.by(1) end it 'saves the token' do diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb index 53ab63ef030..5f3a94a5b99 100644 --- a/spec/models/project_services/microsoft_teams_service_spec.rb +++ b/spec/models/project_services/microsoft_teams_service_spec.rb @@ -73,7 +73,7 @@ RSpec.describe MicrosoftTeamsService do context 'with issue events' do let(:opts) { { title: 'Awesome issue', description: 'please fix' } } let(:issues_sample_data) do - service = Issues::CreateService.new(project, user, opts) + service = Issues::CreateService.new(project: project, current_user: user, params: opts) issue = service.execute service.hook_data(issue, 'open') end @@ -96,7 +96,7 @@ RSpec.describe MicrosoftTeamsService do end let(:merge_sample_data) do - service = MergeRequests::CreateService.new(project, user, opts) + service = MergeRequests::CreateService.new(project: project, current_user: user, params: opts) merge_request = service.execute service.hook_data(merge_request, 'open') end @@ -240,7 +240,7 @@ RSpec.describe MicrosoftTeamsService do chat_service.execute(data) - message = ChatMessage::PipelineMessage.new(data) + message = Integrations::ChatMessage::PipelineMessage.new(data) expect(WebMock).to have_requested(:post, webhook_url) .with(body: hash_including({ summary: message.summary })) diff --git a/spec/models/project_services/open_project_tracker_data_spec.rb b/spec/models/project_services/open_project_tracker_data_spec.rb index e6a3963ba87..1f7f01cfea4 100644 --- a/spec/models/project_services/open_project_tracker_data_spec.rb +++ b/spec/models/project_services/open_project_tracker_data_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' RSpec.describe OpenProjectTrackerData do - describe 'Associations' do - it { is_expected.to belong_to(:service) } + describe 'associations' do + it { is_expected.to belong_to(:integration) } end describe 'closed_status_id' do diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb index 688a59fcf09..2e2c1c666d9 100644 --- a/spec/models/project_services/slack_service_spec.rb +++ b/spec/models/project_services/slack_service_spec.rb @@ -59,16 +59,22 @@ RSpec.describe SlackService do context 'deployment notification' do let_it_be(:deployment) { create(:deployment, user: user) } - let(:data) { Gitlab::DataBuilder::Deployment.build(deployment) } + 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_it_be(:wiki_page) { create(:wiki_page, wiki: project.wiki, message: 'user created page: Awesome wiki_page') } + 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 |