diff options
Diffstat (limited to 'spec/lib/gitlab/ci/reports/security/report_spec.rb')
-rw-r--r-- | spec/lib/gitlab/ci/reports/security/report_spec.rb | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/spec/lib/gitlab/ci/reports/security/report_spec.rb b/spec/lib/gitlab/ci/reports/security/report_spec.rb new file mode 100644 index 00000000000..5a85c3f19fc --- /dev/null +++ b/spec/lib/gitlab/ci/reports/security/report_spec.rb @@ -0,0 +1,224 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Ci::Reports::Security::Report do + let_it_be(:pipeline) { create(:ci_pipeline) } + + let(:created_at) { 2.weeks.ago } + + subject(:report) { described_class.new('sast', pipeline, created_at) } + + it { expect(report.type).to eq('sast') } + it { is_expected.to delegate_method(:project_id).to(:pipeline) } + + describe '#add_scanner' do + let(:scanner) { create(:ci_reports_security_scanner, external_id: 'find_sec_bugs') } + + subject { report.add_scanner(scanner) } + + it 'stores given scanner params in the map' do + subject + + expect(report.scanners).to eq({ 'find_sec_bugs' => scanner }) + end + + it 'returns the added scanner' do + expect(subject).to eq(scanner) + end + end + + describe '#add_identifier' do + let(:identifier) { create(:ci_reports_security_identifier) } + + subject { report.add_identifier(identifier) } + + it 'stores given identifier params in the map' do + subject + + expect(report.identifiers).to eq({ identifier.fingerprint => identifier }) + end + + it 'returns the added identifier' do + expect(subject).to eq(identifier) + end + end + + describe '#add_finding' do + let(:finding) { create(:ci_reports_security_finding) } + + it 'enriches given finding and stores it in the collection' do + report.add_finding(finding) + + expect(report.findings).to eq([finding]) + end + end + + describe '#clone_as_blank' do + let(:report) do + create( + :ci_reports_security_report, + findings: [create(:ci_reports_security_finding)], + scanners: [create(:ci_reports_security_scanner)], + identifiers: [create(:ci_reports_security_identifier)] + ) + end + + it 'creates a blank report with copied type and pipeline' do + clone = report.clone_as_blank + + expect(clone.type).to eq(report.type) + expect(clone.pipeline).to eq(report.pipeline) + expect(clone.created_at).to eq(report.created_at) + expect(clone.findings).to eq([]) + expect(clone.scanners).to eq({}) + expect(clone.identifiers).to eq({}) + end + end + + describe '#replace_with!' do + let(:report) do + create( + :ci_reports_security_report, + findings: [create(:ci_reports_security_finding)], + scanners: [create(:ci_reports_security_scanner)], + identifiers: [create(:ci_reports_security_identifier)] + ) + end + + let(:other_report) do + create( + :ci_reports_security_report, + findings: [create(:ci_reports_security_finding, compare_key: 'other_finding')], + scanners: [create(:ci_reports_security_scanner, external_id: 'other_scanner', name: 'Other Scanner')], + identifiers: [create(:ci_reports_security_identifier, external_id: 'other_id', name: 'other_scanner')] + ) + end + + before do + report.replace_with!(other_report) + end + + it 'replaces report contents with other reports contents' do + expect(report.findings).to eq(other_report.findings) + expect(report.scanners).to eq(other_report.scanners) + expect(report.identifiers).to eq(other_report.identifiers) + end + end + + describe '#merge!' do + let(:merged_report) { double('Report') } + + before do + merge_reports_service = double('MergeReportsService') + + allow(::Security::MergeReportsService).to receive(:new).and_return(merge_reports_service) + allow(merge_reports_service).to receive(:execute).and_return(merged_report) + allow(report).to receive(:replace_with!) + end + + subject { report.merge!(described_class.new('sast', pipeline, created_at)) } + + it 'invokes the merge with other report and then replaces this report contents by merge result' do + subject + + expect(report).to have_received(:replace_with!).with(merged_report) + end + end + + describe '#primary_scanner' do + let(:scanner_1) { create(:ci_reports_security_scanner, external_id: 'external_id_1') } + let(:scanner_2) { create(:ci_reports_security_scanner, external_id: 'external_id_2') } + + subject { report.primary_scanner } + + before do + report.add_scanner(scanner_1) + report.add_scanner(scanner_2) + end + + it { is_expected.to eq(scanner_1) } + end + + describe '#add_error' do + context 'when the message is not given' do + it 'adds a new error to report with the generic error message' do + expect { report.add_error('foo') }.to change { report.errors } + .from([]) + .to([{ type: 'foo', message: 'An unexpected error happened!' }]) + end + end + + context 'when the message is given' do + it 'adds a new error to report' do + expect { report.add_error('foo', 'bar') }.to change { report.errors } + .from([]) + .to([{ type: 'foo', message: 'bar' }]) + end + end + end + + describe 'errored?' do + subject { report.errored? } + + context 'when the report does not have any errors' do + it { is_expected.to be_falsey } + end + + context 'when the report has errors' do + before do + report.add_error('foo', 'bar') + end + + it { is_expected.to be_truthy } + end + end + + describe '#primary_scanner_order_to' do + let(:scanner_1) { build(:ci_reports_security_scanner) } + let(:scanner_2) { build(:ci_reports_security_scanner) } + let(:report_1) { described_class.new('sast', pipeline, created_at) } + let(:report_2) { described_class.new('sast', pipeline, created_at) } + + subject(:compare_based_on_primary_scanners) { report_1.primary_scanner_order_to(report_2) } + + context 'when the primary scanner of the receiver is nil' do + context 'when the primary scanner of the other is nil' do + it { is_expected.to be(1) } + end + + context 'when the primary scanner of the other is not nil' do + before do + report_2.add_scanner(scanner_2) + end + + it { is_expected.to be(1) } + end + end + + context 'when the primary scanner of the receiver is not nil' do + before do + report_1.add_scanner(scanner_1) + end + + context 'when the primary scanner of the other is nil' do + let(:scanner_2) { nil } + + it { is_expected.to be(-1) } + end + + context 'when the primary scanner of the other is not nil' do + before do + report_2.add_scanner(scanner_2) + + allow(scanner_1).to receive(:<=>).and_return(0) + end + + it 'compares two scanners' do + expect(compare_based_on_primary_scanners).to be(0) + expect(scanner_1).to have_received(:<=>).with(scanner_2) + end + end + end + end +end |