diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-28 15:10:02 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-28 15:10:02 +0300 |
commit | effda22b3e6367cefd12666463b8409bf7e24cef (patch) | |
tree | 004fa8a4a79ea8922e864b21d2d741a19250cff3 /spec/lib | |
parent | 15b34520549c1f67bd92469003fe5a9260e34e43 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/gitlab/ci/pipeline/seed/build_spec.rb | 10 | ||||
-rw-r--r-- | spec/lib/gitlab/cycle_analytics/events_spec.rb | 273 | ||||
-rw-r--r-- | spec/lib/gitlab/database/with_lock_retries_spec.rb | 64 | ||||
-rw-r--r-- | spec/lib/gitlab/lfs/client_spec.rb | 99 | ||||
-rw-r--r-- | spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb | 40 | ||||
-rw-r--r-- | spec/lib/gitlab/usage_data_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/pager_duty/webhook_payload_parser_spec.rb | 84 |
7 files changed, 320 insertions, 252 deletions
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb index 34df0e86a18..0b961336f3f 100644 --- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb @@ -3,9 +3,9 @@ require 'spec_helper' RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do - let(:project) { create(:project, :repository) } - let(:head_sha) { project.repository.head_commit.id } - let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: head_sha) } + let_it_be(:project) { create(:project, :repository) } + let_it_be(:head_sha) { project.repository.head_commit.id } + let(:pipeline) { build(:ci_empty_pipeline, project: project, sha: head_sha) } let(:attributes) { { name: 'rspec', ref: 'master', scheduling_type: :stage } } let(:previous_stages) { [] } @@ -503,7 +503,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do using RSpec::Parameterized let(:pipeline) do - build(:ci_empty_pipeline, ref: 'deploy', tag: false, source: source) + build(:ci_empty_pipeline, ref: 'deploy', tag: false, source: source, project: project) end context 'matches' do @@ -766,7 +766,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do context 'with a matching changes: rule' do let(:pipeline) do - create(:ci_pipeline, project: project).tap do |pipeline| + build(:ci_pipeline, project: project).tap do |pipeline| stub_pipeline_modified_paths(pipeline, %w[app/models/ci/pipeline.rb spec/models/ci/pipeline_spec.rb .gitlab-ci.yml]) end end diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index e0a8e2c17a3..a31f34d82d7 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -2,16 +2,20 @@ require 'spec_helper' -RSpec.describe 'cycle analytics events' do - let(:project) { create(:project, :repository) } +RSpec.describe 'cycle analytics events', :aggregate_failures do + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user, :admin) } let(:from_date) { 10.days.ago } - let(:user) { create(:user, :admin) } let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } let(:events) do - CycleAnalytics::ProjectLevel.new(project, options: { from: from_date, current_user: user })[stage].events + CycleAnalytics::ProjectLevel + .new(project, options: { from: from_date, current_user: user })[stage] + .events end + let(:event) { events.first } + before do setup(context) end @@ -19,36 +23,15 @@ RSpec.describe 'cycle analytics events' do describe '#issue_events' do let(:stage) { :issue } - it 'has the total time' do - expect(events.first[:total_time]).not_to be_empty - end - - it 'has a title' do - expect(events.first[:title]).to eq(context.title) - end - - it 'has the URL' do - expect(events.first[:url]).not_to be_nil - end - - it 'has an iid' do - expect(events.first[:iid]).to eq(context.iid.to_s) - end - - it 'has a created_at timestamp' do - expect(events.first[:created_at]).to end_with('ago') - end - - it "has the author's URL" do - expect(events.first[:author][:web_url]).not_to be_nil - end - - it "has the author's avatar URL" do - expect(events.first[:author][:avatar_url]).not_to be_nil - end - - it "has the author's name" do - expect(events.first[:author][:name]).to eq(context.author.name) + it 'has correct attributes' do + expect(event[:total_time]).not_to be_empty + expect(event[:title]).to eq(context.title) + expect(event[:url]).not_to be_nil + expect(event[:iid]).to eq(context.iid.to_s) + expect(event[:created_at]).to end_with('ago') + expect(event[:author][:web_url]).not_to be_nil + expect(event[:author][:avatar_url]).not_to be_nil + expect(event[:author][:name]).to eq(context.author.name) end end @@ -59,36 +42,15 @@ RSpec.describe 'cycle analytics events' do create_commit_referencing_issue(context) end - it 'has the total time' do - expect(events.first[:total_time]).not_to be_empty - end - - it 'has a title' do - expect(events.first[:title]).to eq(context.title) - end - - it 'has the URL' do - expect(events.first[:url]).not_to be_nil - end - - it 'has an iid' do - expect(events.first[:iid]).to eq(context.iid.to_s) - end - - it 'has a created_at timestamp' do - expect(events.first[:created_at]).to end_with('ago') - end - - it "has the author's URL" do - expect(events.first[:author][:web_url]).not_to be_nil - end - - it "has the author's avatar URL" do - expect(events.first[:author][:avatar_url]).not_to be_nil - end - - it "has the author's name" do - expect(events.first[:author][:name]).to eq(context.author.name) + it 'has correct attributes' do + expect(event[:total_time]).not_to be_empty + expect(event[:title]).to eq(context.title) + expect(event[:url]).not_to be_nil + expect(event[:iid]).to eq(context.iid.to_s) + expect(event[:created_at]).to end_with('ago') + expect(event[:author][:web_url]).not_to be_nil + expect(event[:author][:avatar_url]).not_to be_nil + expect(event[:author][:name]).to eq(context.author.name) end end @@ -100,32 +62,14 @@ RSpec.describe 'cycle analytics events' do create_commit_referencing_issue(context) end - it 'has the total time' do - expect(events.first[:total_time]).not_to be_empty - end - - it 'has a title' do - expect(events.first[:title]).to eq('Awesome merge_request') - end - - it 'has an iid' do - expect(events.first[:iid]).to eq(context.iid.to_s) - end - - it 'has a created_at timestamp' do - expect(events.first[:created_at]).to end_with('ago') - end - - it "has the author's URL" do - expect(events.first[:author][:web_url]).not_to be_nil - end - - it "has the author's avatar URL" do - expect(events.first[:author][:avatar_url]).not_to be_nil - end - - it "has the author's name" do - expect(events.first[:author][:name]).to eq(MergeRequest.first.author.name) + it 'has correct attributes' do + expect(event[:total_time]).not_to be_empty + expect(event[:title]).to eq('Awesome merge_request') + expect(event[:iid]).to eq(context.iid.to_s) + expect(event[:created_at]).to end_with('ago') + expect(event[:author][:web_url]).not_to be_nil + expect(event[:author][:avatar_url]).not_to be_nil + expect(event[:author][:name]).to eq(MergeRequest.first.author.name) end end @@ -152,40 +96,16 @@ RSpec.describe 'cycle analytics events' do merge_merge_requests_closing_issue(user, project, context) end - it 'has the name' do - expect(events.first[:name]).not_to be_nil - end - - it 'has the ID' do - expect(events.first[:id]).not_to be_nil - end - - it 'has the URL' do - expect(events.first[:url]).not_to be_nil - end - - it 'has the branch name' do - expect(events.first[:branch]).not_to be_nil - end - - it 'has the branch URL' do - expect(events.first[:branch][:url]).not_to be_nil - end - - it 'has the short SHA' do - expect(events.first[:short_sha]).not_to be_nil - end - - it 'has the commit URL' do - expect(events.first[:commit_url]).not_to be_nil - end - - it 'has the date' do - expect(events.first[:date]).not_to be_nil - end - - it 'has the total time' do - expect(events.first[:total_time]).not_to be_empty + it 'has correct attributes' do + expect(event[:name]).not_to be_nil + expect(event[:id]).not_to be_nil + expect(event[:url]).not_to be_nil + expect(event[:branch]).not_to be_nil + expect(event[:branch][:url]).not_to be_nil + expect(event[:short_sha]).not_to be_nil + expect(event[:commit_url]).not_to be_nil + expect(event[:date]).not_to be_nil + expect(event[:total_time]).not_to be_empty end end @@ -197,40 +117,16 @@ RSpec.describe 'cycle analytics events' do merge_merge_requests_closing_issue(user, project, context) end - it 'has the total time' do - expect(events.first[:total_time]).not_to be_empty - end - - it 'has a title' do - expect(events.first[:title]).to eq('Awesome merge_request') - end - - it 'has an iid' do - expect(events.first[:iid]).to eq(context.iid.to_s) - end - - it 'has the URL' do - expect(events.first[:url]).not_to be_nil - end - - it 'has a state' do - expect(events.first[:state]).not_to be_nil - end - - it 'has a created_at timestamp' do - expect(events.first[:created_at]).not_to be_nil - end - - it "has the author's URL" do - expect(events.first[:author][:web_url]).not_to be_nil - end - - it "has the author's avatar URL" do - expect(events.first[:author][:avatar_url]).not_to be_nil - end - - it "has the author's name" do - expect(events.first[:author][:name]).to eq(MergeRequest.first.author.name) + it 'has correct attributes' do + expect(event[:total_time]).not_to be_empty + expect(event[:title]).to eq('Awesome merge_request') + expect(event[:iid]).to eq(context.iid.to_s) + expect(event[:url]).not_to be_nil + expect(event[:state]).not_to be_nil + expect(event[:created_at]).not_to be_nil + expect(event[:author][:web_url]).not_to be_nil + expect(event[:author][:avatar_url]).not_to be_nil + expect(event[:author][:name]).to eq(MergeRequest.first.author.name) end end @@ -257,58 +153,25 @@ RSpec.describe 'cycle analytics events' do deploy_master(user, project) end - it 'has the name' do - expect(events.first[:name]).not_to be_nil - end - - it 'has the ID' do - expect(events.first[:id]).not_to be_nil - end - - it 'has the URL' do - expect(events.first[:url]).not_to be_nil - end - - it 'has the branch name' do - expect(events.first[:branch]).not_to be_nil - end - - it 'has the branch URL' do - expect(events.first[:branch][:url]).not_to be_nil - end - - it 'has the short SHA' do - expect(events.first[:short_sha]).not_to be_nil - end - - it 'has the commit URL' do - expect(events.first[:commit_url]).not_to be_nil - end - - it 'has the date' do - expect(events.first[:date]).not_to be_nil - end - - it 'has the total time' do - expect(events.first[:total_time]).not_to be_empty - end - - it "has the author's URL" do - expect(events.first[:author][:web_url]).not_to be_nil - end - - it "has the author's avatar URL" do - expect(events.first[:author][:avatar_url]).not_to be_nil - end - - it "has the author's name" do - expect(events.first[:author][:name]).to eq(MergeRequest.first.author.name) + it 'has correct attributes' do + expect(event[:name]).not_to be_nil + expect(event[:id]).not_to be_nil + expect(event[:url]).not_to be_nil + expect(event[:branch]).not_to be_nil + expect(event[:branch][:url]).not_to be_nil + expect(event[:short_sha]).not_to be_nil + expect(event[:commit_url]).not_to be_nil + expect(event[:date]).not_to be_nil + expect(event[:total_time]).not_to be_empty + expect(event[:author][:web_url]).not_to be_nil + expect(event[:author][:avatar_url]).not_to be_nil + expect(event[:author][:name]).to eq(MergeRequest.first.author.name) end end def setup(context) milestone = create(:milestone, project: project) - context.update(milestone: milestone) + context.update!(milestone: milestone) mr = create_merge_request_closing_issue(user, project, context, commit_message: "References #{context.to_reference}") ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.to_hash) diff --git a/spec/lib/gitlab/database/with_lock_retries_spec.rb b/spec/lib/gitlab/database/with_lock_retries_spec.rb index 2cc6e175500..220ae705e71 100644 --- a/spec/lib/gitlab/database/with_lock_retries_spec.rb +++ b/spec/lib/gitlab/database/with_lock_retries_spec.rb @@ -104,9 +104,69 @@ RSpec.describe Gitlab::Database::WithLockRetries do end context 'after 3 iterations' do - let(:retry_count) { 4 } + it_behaves_like 'retriable exclusive lock on `projects`' do + let(:retry_count) { 4 } + end + + context 'setting the idle transaction timeout' do + context 'when there is no outer transaction: disable_ddl_transaction! is set in the migration' do + it 'does not disable the idle transaction timeout' do + allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) + allow(subject).to receive(:run_block_with_transaction).once.and_raise(ActiveRecord::LockWaitTimeout) + allow(subject).to receive(:run_block_with_transaction).once + + expect(subject).not_to receive(:disable_idle_in_transaction_timeout) + + subject.run {} + end + end - it_behaves_like 'retriable exclusive lock on `projects`' + context 'when there is outer transaction: disable_ddl_transaction! is not set in the migration' do + it 'disables the idle transaction timeout so the code can sleep and retry' do + allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(true) + + n = 0 + allow(subject).to receive(:run_block_with_transaction).twice do + n += 1 + raise(ActiveRecord::LockWaitTimeout) if n == 1 + end + + expect(subject).to receive(:disable_idle_in_transaction_timeout).once + + subject.run {} + end + end + end + end + + context 'after the retries are exhausted' do + let(:timing_configuration) do + [ + [1.second, 1.second] + ] + end + + context 'when there is no outer transaction: disable_ddl_transaction! is set in the migration' do + it 'does not disable the lock_timeout' do + allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) + allow(subject).to receive(:run_block_with_transaction).once.and_raise(ActiveRecord::LockWaitTimeout) + + expect(subject).not_to receive(:disable_lock_timeout) + + subject.run {} + end + end + + context 'when there is outer transaction: disable_ddl_transaction! is not set in the migration' do + it 'disables the lock_timeout' do + allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(true) + allow(subject).to receive(:run_block_with_transaction).once.and_raise(ActiveRecord::LockWaitTimeout) + + expect(subject).to receive(:disable_lock_timeout) + + subject.run {} + end + end end context 'after the retries, without setting lock_timeout' do diff --git a/spec/lib/gitlab/lfs/client_spec.rb b/spec/lib/gitlab/lfs/client_spec.rb index 03563a632d6..b34f2ac0d80 100644 --- a/spec/lib/gitlab/lfs/client_spec.rb +++ b/spec/lib/gitlab/lfs/client_spec.rb @@ -7,6 +7,7 @@ RSpec.describe Gitlab::Lfs::Client do let(:username) { 'user' } let(:password) { 'password' } let(:credentials) { { user: username, password: password, auth_method: 'password' } } + let(:git_lfs_content_type) { 'application/vnd.git-lfs+json' } let(:basic_auth_headers) do { 'Authorization' => "Basic #{Base64.strict_encode64("#{username}:#{password}")}" } @@ -21,6 +22,15 @@ RSpec.describe Gitlab::Lfs::Client do } end + let(:verify_action) do + { + "href" => "#{base_url}/some/file/verify", + "header" => { + "Key" => "value" + } + } + end + subject(:lfs_client) { described_class.new(base_url, credentials: credentials) } describe '#batch' do @@ -34,10 +44,10 @@ RSpec.describe Gitlab::Lfs::Client do ).to_return( status: 200, body: { 'objects' => 'anything', 'transfer' => 'basic' }.to_json, - headers: { 'Content-Type' => 'application/vnd.git-lfs+json' } + headers: { 'Content-Type' => git_lfs_content_type } ) - result = lfs_client.batch('upload', objects) + result = lfs_client.batch!('upload', objects) expect(stub).to have_been_requested expect(result).to eq('objects' => 'anything', 'transfer' => 'basic') @@ -48,7 +58,7 @@ RSpec.describe Gitlab::Lfs::Client do it 'raises an error' do stub_batch(objects: objects, headers: basic_auth_headers).to_return(status: 400) - expect { lfs_client.batch('upload', objects) }.to raise_error(/Failed/) + expect { lfs_client.batch!('upload', objects) }.to raise_error(/Failed/) end end @@ -56,7 +66,7 @@ RSpec.describe Gitlab::Lfs::Client do it 'raises an error' do stub_batch(objects: objects, headers: basic_auth_headers).to_return(status: 400) - expect { lfs_client.batch('upload', objects) }.to raise_error(/Failed/) + expect { lfs_client.batch!('upload', objects) }.to raise_error(/Failed/) end end @@ -68,17 +78,22 @@ RSpec.describe Gitlab::Lfs::Client do ).to_return( status: 200, body: { 'transfer' => 'carrier-pigeon' }.to_json, - headers: { 'Content-Type' => 'application/vnd.git-lfs+json' } + headers: { 'Content-Type' => git_lfs_content_type } ) - expect { lfs_client.batch('upload', objects) }.to raise_error(/Unsupported transfer/) + expect { lfs_client.batch!('upload', objects) }.to raise_error(/Unsupported transfer/) end end def stub_batch(objects:, headers:, operation: 'upload', transfer: 'basic') - objects = objects.map { |o| { oid: o.oid, size: o.size } } + objects = objects.as_json(only: [:oid, :size]) body = { operation: operation, 'transfers': [transfer], objects: objects }.to_json + headers = { + 'Accept' => git_lfs_content_type, + 'Content-Type' => git_lfs_content_type + }.merge(headers) + stub_request(:post, base_url + '/info/lfs/objects/batch').with(body: body, headers: headers) end end @@ -90,7 +105,7 @@ RSpec.describe Gitlab::Lfs::Client do it "makes an HTTP PUT with expected parameters" do stub_upload(object: object, headers: upload_action['header']).to_return(status: 200) - lfs_client.upload(object, upload_action, authenticated: true) + lfs_client.upload!(object, upload_action, authenticated: true) end end @@ -101,7 +116,7 @@ RSpec.describe Gitlab::Lfs::Client do headers: basic_auth_headers.merge(upload_action['header']) ).to_return(status: 200) - lfs_client.upload(object, upload_action, authenticated: false) + lfs_client.upload!(object, upload_action, authenticated: false) expect(stub).to have_been_requested end @@ -110,13 +125,13 @@ RSpec.describe Gitlab::Lfs::Client do context 'LFS object has no file' do let(:object) { LfsObject.new } - it 'makes an HJTT PUT with expected parameters' do + it 'makes an HTTP PUT with expected parameters' do stub = stub_upload( object: object, headers: upload_action['header'] ).to_return(status: 200) - lfs_client.upload(object, upload_action, authenticated: true) + lfs_client.upload!(object, upload_action, authenticated: true) expect(stub).to have_been_requested end @@ -126,7 +141,7 @@ RSpec.describe Gitlab::Lfs::Client do it 'raises an error' do stub_upload(object: object, headers: upload_action['header']).to_return(status: 400) - expect { lfs_client.upload(object, upload_action, authenticated: true) }.to raise_error(/Failed/) + expect { lfs_client.upload!(object, upload_action, authenticated: true) }.to raise_error(/Failed/) end end @@ -134,15 +149,73 @@ RSpec.describe Gitlab::Lfs::Client do it 'raises an error' do stub_upload(object: object, headers: upload_action['header']).to_return(status: 500) - expect { lfs_client.upload(object, upload_action, authenticated: true) }.to raise_error(/Failed/) + expect { lfs_client.upload!(object, upload_action, authenticated: true) }.to raise_error(/Failed/) end end def stub_upload(object:, headers:) + headers = { + 'Content-Type' => 'application/octet-stream', + 'Content-Length' => object.size.to_s + }.merge(headers) + stub_request(:put, upload_action['href']).with( body: object.file.read, headers: headers.merge('Content-Length' => object.size.to_s) ) end end + + describe "#verify" do + let_it_be(:object) { create(:lfs_object) } + + context 'server returns 200 OK to an authenticated request' do + it "makes an HTTP POST with expected parameters" do + stub_verify(object: object, headers: verify_action['header']).to_return(status: 200) + + lfs_client.verify!(object, verify_action, authenticated: true) + end + end + + context 'server returns 200 OK to an unauthenticated request' do + it "makes an HTTP POST with expected parameters" do + stub = stub_verify( + object: object, + headers: basic_auth_headers.merge(upload_action['header']) + ).to_return(status: 200) + + lfs_client.verify!(object, verify_action, authenticated: false) + + expect(stub).to have_been_requested + end + end + + context 'server returns 400 error' do + it 'raises an error' do + stub_verify(object: object, headers: verify_action['header']).to_return(status: 400) + + expect { lfs_client.verify!(object, verify_action, authenticated: true) }.to raise_error(/Failed/) + end + end + + context 'server returns 500 error' do + it 'raises an error' do + stub_verify(object: object, headers: verify_action['header']).to_return(status: 500) + + expect { lfs_client.verify!(object, verify_action, authenticated: true) }.to raise_error(/Failed/) + end + end + + def stub_verify(object:, headers:) + headers = { + 'Accept' => git_lfs_content_type, + 'Content-Type' => git_lfs_content_type + }.merge(headers) + + stub_request(:post, verify_action['href']).with( + body: object.to_json(only: [:oid, :size]), + headers: headers + ) + end + end end diff --git a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb index 479fe36bcdd..a295bdac3d8 100644 --- a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb @@ -92,6 +92,46 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git end end + context 'for Issue created actions' do + it_behaves_like 'tracks and counts action' do + let(:action) { described_class::ISSUE_CREATED } + + def track_action(params) + described_class.track_issue_created_action(params) + end + end + end + + context 'for Issue closed actions' do + it_behaves_like 'tracks and counts action' do + let(:action) { described_class::ISSUE_CLOSED } + + def track_action(params) + described_class.track_issue_closed_action(params) + end + end + end + + context 'for Issue reopened actions' do + it_behaves_like 'tracks and counts action' do + let(:action) { described_class::ISSUE_REOPENED } + + def track_action(params) + described_class.track_issue_reopened_action(params) + end + end + end + + context 'for Issue label changed actions' do + it_behaves_like 'tracks and counts action' do + let(:action) { described_class::ISSUE_LABEL_CHANGED } + + def track_action(params) + described_class.track_issue_label_changed_action(params) + end + end + end + it 'can return the count of actions per user deduplicated', :aggregate_failures do described_class.track_issue_title_changed_action(author: user1) described_class.track_issue_description_changed_action(author: user1) diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index e54082b4521..f22809bb9a8 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -1020,7 +1020,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do end end - def for_defined_days_back(days: [29, 2]) + def for_defined_days_back(days: [31, 3]) days.each do |n| Timecop.travel(n.days.ago) do yield diff --git a/spec/lib/pager_duty/webhook_payload_parser_spec.rb b/spec/lib/pager_duty/webhook_payload_parser_spec.rb index 0010165318d..54c61b9121c 100644 --- a/spec/lib/pager_duty/webhook_payload_parser_spec.rb +++ b/spec/lib/pager_duty/webhook_payload_parser_spec.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'fast_spec_helper' +require 'json_schemer' RSpec.describe PagerDuty::WebhookPayloadParser do describe '.call' do @@ -8,36 +9,36 @@ RSpec.describe PagerDuty::WebhookPayloadParser do File.read(File.join(File.dirname(__FILE__), '../../fixtures/pager_duty/webhook_incident_trigger.json')) end + let(:triggered_event) do + { + 'event' => 'incident.trigger', + 'incident' => { + 'url' => 'https://webdemo.pagerduty.com/incidents/PRORDTY', + 'incident_number' => 33, + 'title' => 'My new incident', + 'status' => 'triggered', + 'created_at' => '2017-09-26T15:14:36Z', + 'urgency' => 'high', + 'incident_key' => nil, + 'assignees' => [{ + 'summary' => 'Laura Haley', + 'url' => 'https://webdemo.pagerduty.com/users/P553OPV' + }], + 'impacted_services' => [{ + 'summary' => 'Production XDB Cluster', + 'url' => 'https://webdemo.pagerduty.com/services/PN49J75' + }] + } + } + end + subject(:parse) { described_class.call(payload) } context 'when payload is a correct PagerDuty payload' do let(:payload) { Gitlab::Json.parse(fixture_file) } it 'returns parsed payload' do - is_expected.to eq( - [ - { - 'event' => 'incident.trigger', - 'incident' => { - 'url' => 'https://webdemo.pagerduty.com/incidents/PRORDTY', - 'incident_number' => 33, - 'title' => 'My new incident', - 'status' => 'triggered', - 'created_at' => '2017-09-26T15:14:36Z', - 'urgency' => 'high', - 'incident_key' => nil, - 'assignees' => [{ - 'summary' => 'Laura Haley', - 'url' => 'https://webdemo.pagerduty.com/users/P553OPV' - }], - 'impacted_services' => [{ - 'summary' => 'Production XDB Cluster', - 'url' => 'https://webdemo.pagerduty.com/services/PN49J75' - }] - } - } - ] - ) + is_expected.to eq([triggered_event]) end context 'when assignments summary and html_url are blank' do @@ -69,11 +70,42 @@ RSpec.describe PagerDuty::WebhookPayloadParser do end end - context 'when payload has no incidents' do + context 'when payload schema is invalid' do let(:payload) { { 'messages' => [{ 'event' => 'incident.trigger' }] } } it 'returns payload with blank incidents' do - is_expected.to eq([{ 'event' => 'incident.trigger', 'incident' => {} }]) + is_expected.to eq([]) + end + end + + context 'when payload consists of two messages' do + context 'when one of the messages has no incident data' do + let(:payload) do + valid_payload = Gitlab::Json.parse(fixture_file) + event = { 'event' => 'incident.trigger' } + valid_payload['messages'] = valid_payload['messages'].append(event) + valid_payload + end + + it 'returns parsed payload with valid events only' do + is_expected.to eq([triggered_event]) + end + end + + context 'when one of the messages has unknown event' do + let(:payload) do + valid_payload = Gitlab::Json.parse(fixture_file) + event = { 'event' => 'incident.unknown', 'incident' => valid_payload['messages'].first['incident'] } + valid_payload['messages'] = valid_payload['messages'].append(event) + valid_payload + end + + it 'returns parsed payload' do + unknown_event = triggered_event.dup + unknown_event['event'] = 'incident.unknown' + + is_expected.to contain_exactly(triggered_event, unknown_event) + end end end end |