diff options
Diffstat (limited to 'spec/presenters')
16 files changed, 452 insertions, 32 deletions
diff --git a/spec/presenters/ci/legacy_stage_presenter_spec.rb b/spec/presenters/ci/legacy_stage_presenter_spec.rb new file mode 100644 index 00000000000..ccf4e48de6e --- /dev/null +++ b/spec/presenters/ci/legacy_stage_presenter_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Ci::LegacyStagePresenter do + let(:legacy_stage) { create(:ci_stage) } + let(:presenter) { described_class.new(legacy_stage) } + + let!(:build) { create(:ci_build, :tags, :artifacts, pipeline: legacy_stage.pipeline, stage: legacy_stage.name) } + let!(:retried_build) { create(:ci_build, :tags, :artifacts, :retried, pipeline: legacy_stage.pipeline, stage: legacy_stage.name) } + + before do + create(:generic_commit_status, pipeline: legacy_stage.pipeline, stage: legacy_stage.name) + end + + describe '#latest_ordered_statuses' do + subject(:latest_ordered_statuses) { presenter.latest_ordered_statuses } + + it 'preloads build tags' do + expect(latest_ordered_statuses.second.association(:tags)).to be_loaded + end + + it 'preloads build artifacts archive' do + expect(latest_ordered_statuses.second.association(:job_artifacts_archive)).to be_loaded + end + + it 'preloads build artifacts metadata' do + expect(latest_ordered_statuses.second.association(:metadata)).to be_loaded + end + end + + describe '#retried_ordered_statuses' do + subject(:retried_ordered_statuses) { presenter.retried_ordered_statuses } + + it 'preloads build tags' do + expect(retried_ordered_statuses.first.association(:tags)).to be_loaded + end + + it 'preloads build artifacts archive' do + expect(retried_ordered_statuses.first.association(:job_artifacts_archive)).to be_loaded + end + + it 'preloads build artifacts metadata' do + expect(retried_ordered_statuses.first.association(:metadata)).to be_loaded + end + end +end diff --git a/spec/presenters/ci/pipeline_presenter_spec.rb b/spec/presenters/ci/pipeline_presenter_spec.rb index eca5d3e05fe..fd391478eb4 100644 --- a/spec/presenters/ci/pipeline_presenter_spec.rb +++ b/spec/presenters/ci/pipeline_presenter_spec.rb @@ -62,13 +62,19 @@ describe Ci::PipelinePresenter do end end - context '#failure_reason' do - context 'when pipeline has failure reason' do - it 'represents a failure reason sentence' do - pipeline.failure_reason = :config_error + describe '#failure_reason' do + context 'when pipeline has a failure reason' do + ::Ci::PipelineEnums.failure_reasons.keys.each do |failure_reason| + context "when failure reason is #{failure_reason}" do + before do + pipeline.failure_reason = failure_reason + end - expect(presenter.failure_reason) - .to eq 'CI/CD YAML configuration error!' + it 'represents a failure reason sentence' do + expect(presenter.failure_reason).to be_an_instance_of(String) + expect(presenter.failure_reason).not_to eq(failure_reason.to_s) + end + end end end diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb index 8bc5374f2db..6a1360807b7 100644 --- a/spec/presenters/clusters/cluster_presenter_spec.rb +++ b/spec/presenters/clusters/cluster_presenter_spec.rb @@ -153,11 +153,42 @@ describe Clusters::ClusterPresenter do end end - describe '#gke_cluster_url' do - subject { described_class.new(cluster).gke_cluster_url } + describe '#provider_label' do + let(:cluster) { create(:cluster, provider_type: provider_type) } - it { is_expected.to include(cluster.provider.zone) } - it { is_expected.to include(cluster.name) } + subject { described_class.new(cluster).provider_label } + + context 'AWS provider' do + let(:provider_type) { :aws } + + it { is_expected.to eq('Elastic Kubernetes Service') } + end + + context 'GCP provider' do + let(:provider_type) { :gcp } + + it { is_expected.to eq('Google Kubernetes Engine') } + end + end + + describe '#provider_management_url' do + let(:cluster) { provider.cluster } + + subject { described_class.new(cluster).provider_management_url } + + context 'AWS provider' do + let(:provider) { create(:cluster_provider_aws) } + + it { is_expected.to include(provider.region) } + it { is_expected.to include(cluster.name) } + end + + context 'GCP provider' do + let(:provider) { create(:cluster_provider_gcp) } + + it { is_expected.to include(provider.zone) } + it { is_expected.to include(cluster.name) } + end end describe '#cluster_type_description' do diff --git a/spec/presenters/conversational_development_index/metric_presenter_spec.rb b/spec/presenters/dev_ops_score/metric_presenter_spec.rb index ac18d5203e5..b6eab3f2e74 100644 --- a/spec/presenters/conversational_development_index/metric_presenter_spec.rb +++ b/spec/presenters/dev_ops_score/metric_presenter_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -describe ConversationalDevelopmentIndex::MetricPresenter do +describe DevOpsScore::MetricPresenter do subject { described_class.new(metric) } - let(:metric) { build(:conversational_development_index_metric) } + let(:metric) { build(:dev_ops_score_metric) } describe '#cards' do it 'includes instance score, leader score and percentage score' do diff --git a/spec/presenters/group_clusterable_presenter_spec.rb b/spec/presenters/group_clusterable_presenter_spec.rb index 11a8decc9cc..d40ca856f7b 100644 --- a/spec/presenters/group_clusterable_presenter_spec.rb +++ b/spec/presenters/group_clusterable_presenter_spec.rb @@ -83,6 +83,12 @@ describe GroupClusterablePresenter do it { is_expected.to eq(update_applications_group_cluster_path(group, cluster, application)) } end + describe '#clear_cluster_cache_path' do + subject { presenter.clear_cluster_cache_path(cluster) } + + it { is_expected.to eq(clear_cache_group_cluster_path(group, cluster)) } + end + describe '#cluster_path' do subject { presenter.cluster_path(cluster) } diff --git a/spec/presenters/hooks/project_hook_presenter_spec.rb b/spec/presenters/hooks/project_hook_presenter_spec.rb new file mode 100644 index 00000000000..773e8ccf51e --- /dev/null +++ b/spec/presenters/hooks/project_hook_presenter_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ProjectHookPresenter do + let(:web_hook_log) { create(:web_hook_log) } + let(:project) { web_hook_log.web_hook.project } + let(:web_hook) { web_hook_log.web_hook } + + describe '#logs_details_path' do + subject { web_hook.present.logs_details_path(web_hook_log) } + + let(:expected_path) do + "/#{project.namespace.path}/#{project.name}/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}" + end + + it { is_expected.to eq(expected_path) } + end + + describe '#logs_retry_path' do + subject { web_hook.present.logs_details_path(web_hook_log) } + + let(:expected_path) do + "/#{project.namespace.path}/#{project.name}/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}" + end + + it { is_expected.to eq(expected_path) } + end +end diff --git a/spec/presenters/hooks/service_hook_presenter_spec.rb b/spec/presenters/hooks/service_hook_presenter_spec.rb new file mode 100644 index 00000000000..bea57768e3e --- /dev/null +++ b/spec/presenters/hooks/service_hook_presenter_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ServiceHookPresenter do + let(:web_hook_log) { create(:web_hook_log, web_hook: service_hook) } + let(:service_hook) { create(:service_hook, service: service) } + let(:service) { create(:drone_ci_service, project: project) } + let(:project) { create(:project) } + + describe '#logs_details_path' do + subject { service_hook.present.logs_details_path(web_hook_log) } + + let(:expected_path) do + "/#{project.namespace.path}/#{project.name}/-/services/#{service.to_param}/hook_logs/#{web_hook_log.id}" + end + + it { is_expected.to eq(expected_path) } + end + + describe '#logs_retry_path' do + subject { service_hook.present.logs_retry_path(web_hook_log) } + + let(:expected_path) do + "/#{project.namespace.path}/#{project.name}/-/services/#{service.to_param}/hook_logs/#{web_hook_log.id}/retry" + end + + it { is_expected.to eq(expected_path) } + end +end diff --git a/spec/presenters/instance_clusterable_presenter_spec.rb b/spec/presenters/instance_clusterable_presenter_spec.rb index 9f1268379f5..4265e2fcb69 100644 --- a/spec/presenters/instance_clusterable_presenter_spec.rb +++ b/spec/presenters/instance_clusterable_presenter_spec.rb @@ -21,17 +21,9 @@ describe InstanceClusterablePresenter do it { is_expected.to eq(authorize_aws_role_admin_clusters_path) } end - describe '#revoke_aws_role_path' do - subject { described_class.new(instance).revoke_aws_role_path } + describe '#clear_cluster_cache_path' do + subject { presenter.clear_cluster_cache_path(cluster) } - it { is_expected.to eq(revoke_aws_role_admin_clusters_path) } - end - - describe '#aws_api_proxy_path' do - let(:resource) { 'resource' } - - subject { described_class.new(instance).aws_api_proxy_path(resource) } - - it { is_expected.to eq(aws_proxy_admin_clusters_path(resource: resource)) } + it { is_expected.to eq(clear_cache_admin_cluster_path(cluster)) } end end diff --git a/spec/presenters/label_presenter_spec.rb b/spec/presenters/label_presenter_spec.rb index d566da7c872..e9f9657490d 100644 --- a/spec/presenters/label_presenter_spec.rb +++ b/spec/presenters/label_presenter_spec.rb @@ -41,6 +41,7 @@ describe LabelPresenter do describe '#filter_path' do context 'with group as context subject' do let(:label_in_group) { build_stubbed(:label, project: project).present(issuable_subject: group) } + subject { label_in_group.filter_path } it { is_expected.to eq(issues_group_path(group, label_name: [label_in_group.title])) } diff --git a/spec/presenters/project_clusterable_presenter_spec.rb b/spec/presenters/project_clusterable_presenter_spec.rb index 441c2a50fea..b3dad4abde5 100644 --- a/spec/presenters/project_clusterable_presenter_spec.rb +++ b/spec/presenters/project_clusterable_presenter_spec.rb @@ -83,6 +83,12 @@ describe ProjectClusterablePresenter do it { is_expected.to eq(update_applications_project_cluster_path(project, cluster, application)) } end + describe '#clear_cluster_cache_path' do + subject { presenter.clear_cluster_cache_path(cluster) } + + it { is_expected.to eq(clear_cache_project_cluster_path(project, cluster)) } + end + describe '#cluster_path' do subject { presenter.cluster_path(cluster) } diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb index ce095d2225f..318024bacd6 100644 --- a/spec/presenters/project_presenter_spec.rb +++ b/spec/presenters/project_presenter_spec.rb @@ -436,6 +436,7 @@ describe ProjectPresenter do describe '#repo_statistics_buttons' do let(:presenter) { described_class.new(project, current_user: user) } + subject(:empty_repo_statistics_buttons) { presenter.empty_repo_statistics_buttons } before do diff --git a/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb b/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb index de58733c8ea..b9cb60e414f 100644 --- a/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb +++ b/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb @@ -5,11 +5,6 @@ require 'spec_helper' describe Projects::Settings::DeployKeysPresenter do let(:project) { create(:project) } let(:user) { create(:user) } - let(:deploy_key) { create(:deploy_key, public: true) } - - let!(:deploy_keys_project) do - create(:deploy_keys_project, project: project, deploy_key: deploy_key) - end subject(:presenter) do described_class.new(project, current_user: user) @@ -20,6 +15,12 @@ describe Projects::Settings::DeployKeysPresenter do end describe '#enabled_keys' do + let!(:deploy_key) { create(:deploy_key, public: true) } + + let!(:deploy_keys_project) do + create(:deploy_keys_project, project: project, deploy_key: deploy_key) + end + it 'returns currently enabled keys' do expect(presenter.enabled_keys).to eq [deploy_keys_project.deploy_key] end @@ -53,4 +54,54 @@ describe Projects::Settings::DeployKeysPresenter do expect(presenter.available_project_keys_size).to eq(1) end end + + context 'prevent N + 1 queries' do + before do + create_records + + project.add_maintainer(user) + end + + def create_records + other_project = create(:project) + other_project.add_maintainer(user) + + create(:deploy_keys_project, project: project, deploy_key: create(:deploy_key)) + create(:deploy_keys_project, project: other_project, deploy_key: create(:deploy_key)) + create(:deploy_key, public: true) + end + + def execute_with_query_count + ActiveRecord::QueryRecorder.new { execute_presenter }.count + end + + def execute_presenter + described_class.new(project, current_user: user).as_json + end + + it 'returns correct counts' do + result = execute_presenter + + expect(result[:enabled_keys].size).to eq(1) + expect(result[:available_project_keys].size).to eq(1) + expect(result[:public_keys].size).to eq(1) + end + + it 'does not increase the query count' do + execute_presenter # make sure everything is cached + + count_before = execute_with_query_count + + 3.times { create_records } + + count_after = execute_with_query_count + + expect(count_after).to eq(count_before) + + result = execute_presenter + expect(result[:enabled_keys].size).to eq(4) + expect(result[:available_project_keys].size).to eq(4) + expect(result[:public_keys].size).to eq(4) + end + end end diff --git a/spec/presenters/release_presenter_spec.rb b/spec/presenters/release_presenter_spec.rb index 4d9fa7a4d75..2f978b0a036 100644 --- a/spec/presenters/release_presenter_spec.rb +++ b/spec/presenters/release_presenter_spec.rb @@ -90,10 +90,8 @@ describe ReleasePresenter do is_expected.to match /#{edit_project_release_url(project, release)}/ end - context 'when release_edit_page feature flag is disabled' do - before do - stub_feature_flags(release_edit_page: false) - end + context 'when a user is not allowed to update a release' do + let(:presenter) { described_class.new(release, current_user: guest) } it { is_expected.to be_nil } end diff --git a/spec/presenters/sentry_detailed_error_presenter_spec.rb b/spec/presenters/sentry_detailed_error_presenter_spec.rb new file mode 100644 index 00000000000..e483b6d41a1 --- /dev/null +++ b/spec/presenters/sentry_detailed_error_presenter_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SentryDetailedErrorPresenter do + let(:error) { build(:detailed_error_tracking_error) } + let(:presenter) { described_class.new(error) } + + describe '#frequency' do + subject { presenter.frequency } + + it 'returns an array of frequency structs' do + expect(subject).to include(a_kind_of(SentryDetailedErrorPresenter::FrequencyStruct)) + end + + it 'converts the times into UTC time objects' do + time = subject.first.time + + expect(time).to be_a(Time) + expect(time.strftime('%z')).to eq '+0000' + end + + it 'returns the correct counts' do + count = subject.first.count + + expect(count).to eq error.frequency.first[1] + end + end +end diff --git a/spec/presenters/snippet_presenter_spec.rb b/spec/presenters/snippet_presenter_spec.rb new file mode 100644 index 00000000000..87f2220979c --- /dev/null +++ b/spec/presenters/snippet_presenter_spec.rb @@ -0,0 +1,146 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SnippetPresenter do + include Gitlab::Routing.url_helpers + + let_it_be(:user) { create(:user) } + let_it_be(:personal_snippet) { create(:personal_snippet, author: user) } + let_it_be(:project_snippet) { create(:project_snippet, author: user) } + + let(:project) { project_snippet.project } + let(:presenter) { described_class.new(snippet, current_user: user) } + + before do + project.add_developer(user) + end + + describe '#web_url' do + subject { presenter.web_url } + + context 'with PersonalSnippet' do + let(:snippet) { personal_snippet } + + it 'returns snippet web url' do + expect(subject).to match "/snippets/#{snippet.id}" + end + end + + context 'with ProjectSnippet' do + let(:snippet) { project_snippet } + + it 'returns snippet web url' do + expect(subject).to match "/#{project.full_path}/snippets/#{snippet.id}" + end + end + end + + describe '#raw_url' do + subject { presenter.raw_url } + + context 'with PersonalSnippet' do + let(:snippet) { personal_snippet } + + it 'returns snippet web url' do + expect(subject).to match "/snippets/#{snippet.id}/raw" + end + end + + context 'with ProjectSnippet' do + let(:snippet) { project_snippet } + + it 'returns snippet web url' do + expect(subject).to match "/#{project.full_path}/snippets/#{snippet.id}/raw" + end + end + end + + describe '#can_read_snippet?' do + subject { presenter.can_read_snippet? } + + context 'with PersonalSnippet' do + let(:snippet) { personal_snippet } + + it 'checks read_personal_snippet' do + expect(presenter).to receive(:can?).with(user, :read_personal_snippet, snippet) + + subject + end + end + + context 'with ProjectSnippet' do + let(:snippet) { project_snippet } + + it 'checks read_project_snippet ' do + expect(presenter).to receive(:can?).with(user, :read_project_snippet, snippet) + + subject + end + end + end + + describe '#can_update_snippet?' do + subject { presenter.can_update_snippet? } + + context 'with PersonalSnippet' do + let(:snippet) { personal_snippet } + + it 'checks update_personal_snippet' do + expect(presenter).to receive(:can?).with(user, :update_personal_snippet, snippet) + + subject + end + end + + context 'with ProjectSnippet' do + let(:snippet) { project_snippet } + + it 'checks update_project_snippet ' do + expect(presenter).to receive(:can?).with(user, :update_project_snippet, snippet) + + subject + end + end + end + + describe '#can_admin_snippet?' do + subject { presenter.can_admin_snippet? } + + context 'with PersonalSnippet' do + let(:snippet) { personal_snippet } + + it 'checks admin_personal_snippet' do + expect(presenter).to receive(:can?).with(user, :admin_personal_snippet, snippet) + + subject + end + end + + context 'with ProjectSnippet' do + let(:snippet) { project_snippet } + + it 'checks admin_project_snippet ' do + expect(presenter).to receive(:can?).with(user, :admin_project_snippet, snippet) + + subject + end + end + end + + describe '#can_report_as_spam' do + let(:snippet) { personal_snippet } + + subject { presenter.can_report_as_spam? } + + it 'returns false if the user cannot submit the snippet as spam' do + expect(subject).to be_falsey + end + + it 'returns true if the user can submit the snippet as spam' do + allow(snippet).to receive(:submittable_as_spam_by?).and_return(true) + + expect(subject).to be_truthy + end + end +end diff --git a/spec/presenters/web_hook_log_presenter_spec.rb b/spec/presenters/web_hook_log_presenter_spec.rb new file mode 100644 index 00000000000..8812a0ba594 --- /dev/null +++ b/spec/presenters/web_hook_log_presenter_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe WebHookLogPresenter do + include Gitlab::Routing.url_helpers + + describe '#details_path' do + let(:web_hook_log) { create(:web_hook_log, web_hook: web_hook) } + let(:project) { create(:project) } + + subject { web_hook_log.present.details_path } + + context 'project hook' do + let(:web_hook) { create(:project_hook, project: project) } + + it { is_expected.to eq(project_hook_hook_log_path(project, web_hook, web_hook_log)) } + end + + context 'service hook' do + let(:web_hook) { create(:service_hook, service: service) } + let(:service) { create(:drone_ci_service, project: project) } + + it { is_expected.to eq(project_service_hook_log_path(project, service, web_hook_log)) } + end + end + + describe '#retry_path' do + let(:web_hook_log) { create(:web_hook_log, web_hook: web_hook) } + let(:project) { create(:project) } + + subject { web_hook_log.present.retry_path } + + context 'project hook' do + let(:web_hook) { create(:project_hook, project: project) } + + it { is_expected.to eq(retry_project_hook_hook_log_path(project, web_hook, web_hook_log)) } + end + + context 'service hook' do + let(:web_hook) { create(:service_hook, service: service) } + let(:service) { create(:drone_ci_service, project: project) } + + it { is_expected.to eq(retry_project_service_hook_log_path(project, service, web_hook_log)) } + end + end +end |