diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-10 12:08:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-10 12:08:35 +0300 |
commit | 23ff717a29540bb1d4b0068f164b5f9df99386bf (patch) | |
tree | 1d31f1766f3a5e4748cd806cf655d72d35cb59dc /spec/models | |
parent | c2879da99d02b4e49a1394f5699a2963f2651f18 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/models')
-rw-r--r-- | spec/models/blob_viewer/go_mod_spec.rb | 63 | ||||
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 110 | ||||
-rw-r--r-- | spec/models/ci/ref_spec.rb | 153 | ||||
-rw-r--r-- | spec/models/resource_label_event_spec.rb | 44 |
4 files changed, 344 insertions, 26 deletions
diff --git a/spec/models/blob_viewer/go_mod_spec.rb b/spec/models/blob_viewer/go_mod_spec.rb new file mode 100644 index 00000000000..ba6038533ea --- /dev/null +++ b/spec/models/blob_viewer/go_mod_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe BlobViewer::GoMod do + include FakeBlobHelpers + + let(:project) { build_stubbed(:project) } + let(:data) do + <<-SPEC.strip_heredoc + module #{Settings.build_gitlab_go_url}/#{project.full_path} + SPEC + end + let(:blob) { fake_blob(path: 'go.mod', data: data) } + + subject { described_class.new(blob) } + + describe '#package_name' do + it 'returns the package name' do + expect(subject.package_name).to eq("#{Settings.build_gitlab_go_url}/#{project.full_path}") + end + end + + describe '#package_url' do + it 'returns the package URL' do + expect(subject.package_url).to eq("#{Gitlab.config.gitlab.protocol}://#{Settings.build_gitlab_go_url}/#{project.full_path}/") + end + + context 'when the homepage has an invalid URL' do + let(:data) do + <<-SPEC.strip_heredoc + module javascript:alert() + SPEC + end + + it 'returns nil' do + expect(subject.package_url).to be_nil + end + end + end + + describe '#package_type' do + it 'returns "package"' do + expect(subject.package_type).to eq('go') + end + end + + context 'when the module name does not start with the instance URL' do + let(:data) do + <<-SPEC.strip_heredoc + module example.com/foo/bar + SPEC + end + + subject { described_class.new(blob) } + + describe '#package_url' do + it 'returns the pkg.go.dev URL' do + expect(subject.package_url).to eq("https://pkg.go.dev/example.com/foo/bar") + end + end + end +end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index b5cf832b898..650f33b4e33 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -2641,38 +2641,34 @@ describe Ci::Pipeline, :mailer do end end - shared_examples 'enqueues the notification worker' do - it 'enqueues PipelineUpdateCiRefStatusWorker' do - expect(PipelineUpdateCiRefStatusWorker).to receive(:perform_async).with(pipeline.id) - expect(PipelineNotificationWorker).not_to receive(:perform_async).with(pipeline.id) + context 'with success pipeline' do + it_behaves_like 'sending a notification' do + before do + perform_enqueued_jobs do + pipeline.succeed + end + end + end + + it 'enqueues PipelineNotificationWorker' do + expect(PipelineNotificationWorker) + .to receive(:perform_async).with(pipeline.id, ref_status: :success) pipeline.succeed end - context 'when ci_pipeline_fixed_notifications is disabled' do + context 'when pipeline is not the latest' do before do - stub_feature_flags(ci_pipeline_fixed_notifications: false) + create(:ci_pipeline, :success, project: project, ci_ref: pipeline.ci_ref) end - it 'enqueues PipelineNotificationWorker' do - expect(PipelineUpdateCiRefStatusWorker).not_to receive(:perform_async).with(pipeline.id) - expect(PipelineNotificationWorker).to receive(:perform_async).with(pipeline.id) - - pipeline.succeed - end - end - end + it 'does not pass ref_status' do + expect(PipelineNotificationWorker) + .to receive(:perform_async).with(pipeline.id, ref_status: nil) - context 'with success pipeline' do - it_behaves_like 'sending a notification' do - before do - perform_enqueued_jobs do - pipeline.succeed - end + pipeline.succeed! end end - - it_behaves_like 'enqueues the notification worker' end context 'with failed pipeline' do @@ -2687,7 +2683,12 @@ describe Ci::Pipeline, :mailer do end end - it_behaves_like 'enqueues the notification worker' + it 'enqueues PipelineNotificationWorker' do + expect(PipelineNotificationWorker) + .to receive(:perform_async).with(pipeline.id, ref_status: :failed) + + pipeline.drop + end end context 'with skipped pipeline' do @@ -2711,6 +2712,69 @@ describe Ci::Pipeline, :mailer do end end + describe 'updates ci_ref when pipeline finished' do + context 'when ci_ref exists' do + let!(:pipeline) { create(:ci_pipeline, :running) } + + it 'updates the ci_ref' do + expect(pipeline.ci_ref) + .to receive(:update_status_by!).with(pipeline).and_call_original + + pipeline.succeed! + end + end + + context 'when ci_ref does not exist' do + let!(:pipeline) { create(:ci_pipeline, :running, ci_ref_presence: false) } + + it 'does not raise an exception' do + expect { pipeline.succeed! }.not_to raise_error + end + end + end + + describe '#ensure_ci_ref!' do + subject { pipeline.ensure_ci_ref! } + + shared_examples_for 'protected by feature flag' do + context 'when feature flag is disabled' do + before do + stub_feature_flags(ci_pipeline_fixed_notifications: false) + end + + it 'does not do anything' do + expect(Ci::Ref).not_to receive(:ensure_for) + + subject + end + end + end + + context 'when ci_ref does not exist yet' do + let!(:pipeline) { create(:ci_pipeline, ci_ref_presence: false) } + + it_behaves_like 'protected by feature flag' + + it 'creates a new ci_ref and assigns it' do + expect { subject }.to change { Ci::Ref.count }.by(1) + + expect(pipeline.ci_ref).to be_present + end + end + + context 'when ci_ref already exists' do + let!(:pipeline) { create(:ci_pipeline) } + + it_behaves_like 'protected by feature flag' + + it 'fetches a new ci_ref and assigns it' do + expect { subject }.not_to change { Ci::Ref.count } + + expect(pipeline.ci_ref).to be_present + end + end + end + describe '#find_job_with_archive_artifacts' do let!(:old_job) { create(:ci_build, name: 'rspec', retried: true, pipeline: pipeline) } let!(:job_without_artifacts) { create(:ci_build, name: 'rspec', pipeline: pipeline) } diff --git a/spec/models/ci/ref_spec.rb b/spec/models/ci/ref_spec.rb index aa3b8cdbc3e..3d75cb63141 100644 --- a/spec/models/ci/ref_spec.rb +++ b/spec/models/ci/ref_spec.rb @@ -4,8 +4,155 @@ require 'spec_helper' describe Ci::Ref do it { is_expected.to belong_to(:project) } - it { is_expected.to belong_to(:last_updated_by_pipeline) } - it { is_expected.to validate_inclusion_of(:status).in_array(%w[success failed fixed]) } - it { is_expected.to validate_presence_of(:last_updated_by_pipeline) } + describe '.ensure_for' do + let_it_be(:project) { create(:project, :repository) } + + subject { described_class.ensure_for(pipeline) } + + shared_examples_for 'ensures ci_ref' do + context 'when ci_ref already exists' do + let(:options) { {} } + + it 'returns an existing ci_ref' do + expect { subject }.not_to change { described_class.count } + + expect(subject).to eq(Ci::Ref.find_by(project_id: project.id, ref_path: expected_ref_path)) + end + end + + context 'when ci_ref does not exist yet' do + let(:options) { { ci_ref_presence: false } } + + it 'creates a new ci_ref' do + expect { subject }.to change { described_class.count }.by(1) + + expect(subject).to eq(Ci::Ref.find_by(project_id: project.id, ref_path: expected_ref_path)) + end + end + end + + context 'when pipeline is a branch pipeline' do + let!(:pipeline) { create(:ci_pipeline, ref: 'master', project: project, **options) } + let(:expected_ref_path) { 'refs/heads/master' } + + it_behaves_like 'ensures ci_ref' + end + + context 'when pipeline is a tag pipeline' do + let!(:pipeline) { create(:ci_pipeline, ref: 'v1.1.0', tag: true, project: project, **options) } + let(:expected_ref_path) { 'refs/tags/v1.1.0' } + + it_behaves_like 'ensures ci_ref' + end + + context 'when pipeline is a detached merge request pipeline' do + let(:merge_request) do + create(:merge_request, target_project: project, target_branch: 'master', + source_project: project, source_branch: 'feature') + end + + let!(:pipeline) do + create(:ci_pipeline, :detached_merge_request_pipeline, merge_request: merge_request, project: project, **options) + end + + let(:expected_ref_path) { 'refs/heads/feature' } + + it_behaves_like 'ensures ci_ref' + end + end + + describe '#update_status_by!' do + subject { ci_ref.update_status_by!(pipeline) } + + let!(:ci_ref) { create(:ci_ref) } + + shared_examples_for 'no-op' do + it 'does nothing and returns nil' do + expect { subject }.not_to change { ci_ref.status_name } + + is_expected.to be_nil + end + end + + context 'when pipeline status is success or failed' do + using RSpec::Parameterized::TableSyntax + + where(:pipeline_status, :current_ref_status, :expected_ref_status) do + :success | :unknown | :success + :success | :success | :success + :success | :failed | :fixed + :success | :fixed | :success + :success | :broken | :fixed + :success | :still_failing | :fixed + :failed | :unknown | :failed + :failed | :success | :broken + :failed | :failed | :still_failing + :failed | :fixed | :broken + :failed | :broken | :still_failing + :failed | :still_failing | :still_failing + end + + with_them do + let(:ci_ref) { create(:ci_ref, status: described_class.state_machines[:status].states[current_ref_status].value) } + let(:pipeline) { create(:ci_pipeline, status: pipeline_status, ci_ref: ci_ref) } + + it 'transitions the status via state machine' do + expect(subject).to eq(expected_ref_status) + expect(ci_ref.status_name).to eq(expected_ref_status) + end + end + end + + context 'when pipeline status is success' do + let(:pipeline) { create(:ci_pipeline, :success, ci_ref: ci_ref) } + + it 'updates the status' do + expect { subject }.to change { ci_ref.status_name }.from(:unknown).to(:success) + + is_expected.to eq(:success) + end + end + + context 'when pipeline status is canceled' do + let(:pipeline) { create(:ci_pipeline, status: :canceled, ci_ref: ci_ref) } + + it { is_expected.to eq(:unknown) } + end + + context 'when pipeline status is skipped' do + let(:pipeline) { create(:ci_pipeline, status: :skipped, ci_ref: ci_ref) } + + it_behaves_like 'no-op' + end + + context 'when pipeline status is not complete' do + let(:pipeline) { create(:ci_pipeline, :running, ci_ref: ci_ref) } + + it_behaves_like 'no-op' + end + + context 'when feature flag is disabled' do + let(:pipeline) { create(:ci_pipeline, :success, ci_ref: ci_ref) } + + before do + stub_feature_flags(ci_pipeline_fixed_notifications: false) + end + + it_behaves_like 'no-op' + end + + context 'when pipeline is not the latest pipeline' do + let!(:pipeline) { create(:ci_pipeline, :success, ci_ref: ci_ref) } + let!(:latest_pipeline) { create(:ci_pipeline, :success, ci_ref: ci_ref) } + + it_behaves_like 'no-op' + end + + context 'when pipeline does not belong to the ci_ref' do + let(:pipeline) { create(:ci_pipeline, :success, ci_ref: create(:ci_ref)) } + + it_behaves_like 'no-op' + end + end end diff --git a/spec/models/resource_label_event_spec.rb b/spec/models/resource_label_event_spec.rb index a1a2150f461..6a235d3aa17 100644 --- a/spec/models/resource_label_event_spec.rb +++ b/spec/models/resource_label_event_spec.rb @@ -96,4 +96,48 @@ RSpec.describe ResourceLabelEvent, type: :model do expect(subject.outdated_markdown?).to be false end end + + describe '.visible_to_user?' do + let_it_be(:user) { create(:user) } + let_it_be(:issue_project) { create(:project) } + let_it_be(:issue) { create(:issue, project: issue_project) } + + subject { described_class.visible_to_user?(user, issue.resource_label_events.inc_relations) } + + it 'returns events with labels accessible by user' do + label = create(:label, project: issue_project) + event = create_event(label) + issue_project.add_guest(user) + + expect(subject).to eq [event] + end + + it 'filters events with public project labels if issues and MRs are private' do + project = create(:project, :public, :issues_private, :merge_requests_private) + label = create(:label, project: project) + create_event(label) + + expect(subject).to be_empty + end + + it 'filters events with project labels not accessible by user' do + project = create(:project, :private) + label = create(:label, project: project) + create_event(label) + + expect(subject).to be_empty + end + + it 'filters events with group labels not accessible by user' do + group = create(:group, :private) + label = create(:group_label, group: group) + create_event(label) + + expect(subject).to be_empty + end + + def create_event(label) + create(:resource_label_event, issue: issue, label: label) + end + end end |