diff options
Diffstat (limited to 'spec')
15 files changed, 311 insertions, 135 deletions
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index 1f8e96258ca..383e8112315 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -150,7 +150,7 @@ RSpec.describe Projects::NotesController do context 'when user cannot read commit' do before do allow(Ability).to receive(:allowed?).and_call_original - allow(Ability).to receive(:allowed?).with(user, :download_code, project).and_return(false) + allow(Ability).to receive(:allowed?).with(user, :read_code, project).and_return(false) end it 'renders 404' do diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index 8775f68a5de..489461d8876 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -552,6 +552,39 @@ RSpec.describe RegistrationsController do end end end + + context 'when the first or last name is not "present?"' do + using RSpec::Parameterized::TableSyntax + + render_views + + shared_examples 'a user without present first name or last name' do + it 'renders the form with errors' do + subject + expect(controller.current_user).to be_nil + expect(response).to render_template(:new) + expect(response.body).to include(_('name cannot be blank')) # include 'First name' or 'Last name' or both + end + end + + where(:first_name, :last_name) do + nil | 'last' + '' | 'last' + ' ' | 'last' + 'first' | nil + 'first' | '' + 'first' | ' ' + '' | '' + end + + with_them do + before do + base_user_params.merge!({ first_name: first_name, last_name: last_name }) + end + + it_behaves_like 'a user without present first name or last name' + end + end end describe '#destroy' do diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index ad49a763361..2a81e77aee2 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -33,15 +33,26 @@ RSpec.describe 'Database schema' do boards: %w[milestone_id iteration_id], chat_names: %w[chat_id team_id user_id], chat_teams: %w[team_id], + ci_build_needs: %w[partition_id], + ci_build_pending_states: %w[partition_id], + ci_build_report_results: %w[partition_id], + ci_build_trace_chunks: %w[partition_id], + ci_build_trace_metadata: %w[partition_id], ci_builds: %w[erased_by_id trigger_request_id partition_id], + ci_builds_runner_session: %w[partition_id], p_ci_builds_metadata: %w[partition_id], ci_job_artifacts: %w[partition_id], + ci_job_variables: %w[partition_id], ci_namespace_monthly_usages: %w[namespace_id], + ci_pending_builds: %w[partition_id], ci_pipeline_variables: %w[partition_id], ci_pipelines: %w[partition_id], ci_runner_projects: %w[runner_id], + ci_running_builds: %w[partition_id], + ci_sources_pipelines: %w[partition_id], ci_stages: %w[partition_id], ci_trigger_requests: %w[commit_id], + ci_unit_test_failures: %w[partition_id], cluster_providers_aws: %w[security_group_id vpc_id access_key_id], cluster_providers_gcp: %w[gcp_project_id operation_id], compliance_management_frameworks: %w[group_id], diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb index 11de19cfdbc..61be90b267a 100644 --- a/spec/finders/notes_finder_spec.rb +++ b/spec/finders/notes_finder_spec.rb @@ -328,6 +328,16 @@ RSpec.describe NotesFinder do it 'returns the commit' do expect(subject.target).to eq(commit) end + + context 'user does not have permission to read_code' do + before do + allow(Ability).to receive(:allowed?).with(user, :read_code, project).and_return false + end + + it 'returns nil' do + expect(subject.target).to be_nil + end + end end context 'target_iid' do diff --git a/spec/frontend/work_items/components/work_item_description_spec.js b/spec/frontend/work_items/components/work_item_description_spec.js index c79b049442d..be21e9c3834 100644 --- a/spec/frontend/work_items/components/work_item_description_spec.js +++ b/spec/frontend/work_items/components/work_item_description_spec.js @@ -38,7 +38,7 @@ describe('WorkItemDescription', () => { const subscriptionHandler = jest.fn().mockResolvedValue(workItemDescriptionSubscriptionResponse); const workItemByIidResponseHandler = jest.fn().mockResolvedValue(projectWorkItemResponse); let workItemResponseHandler; - let workItemsMvc2; + let workItemsMvc; const findMarkdownField = () => wrapper.findComponent(MarkdownField); const findMarkdownEditor = () => wrapper.findComponent(MarkdownEditor); @@ -46,7 +46,7 @@ describe('WorkItemDescription', () => { const findEditedAt = () => wrapper.findComponent(EditedAt); const editDescription = (newText) => { - if (workItemsMvc2) { + if (workItemsMvc) { return findMarkdownEditor().vm.$emit('input', newText); } return wrapper.find('textarea').setValue(newText); @@ -82,7 +82,7 @@ describe('WorkItemDescription', () => { }, provide: { glFeatures: { - workItemsMvc2, + workItemsMvc, }, }, stubs: { @@ -104,11 +104,11 @@ describe('WorkItemDescription', () => { }); describe.each([true, false])( - 'editing description with workItemsMvc2 %workItemsMvc2Enabled', - (workItemsMvc2Enabled) => { + 'editing description with workItemsMvc %workItemsMvcEnabled', + (workItemsMvcEnabled) => { beforeEach(() => { beforeEach(() => { - workItemsMvc2 = workItemsMvc2Enabled; + workItemsMvc = workItemsMvcEnabled; }); }); diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js index 635a1f326f8..67fda49919a 100644 --- a/spec/frontend/work_items/mock_data.js +++ b/spec/frontend/work_items/mock_data.js @@ -97,6 +97,12 @@ export const workItemQueryResponse = { id: 'gid://gitlab/WorkItem/444', createdAt: '2022-08-03T12:41:54Z', closedAt: null, + confidential: false, + title: '123', + state: 'OPEN', + workItemType: { + id: '1', + }, }, ], }, @@ -142,6 +148,14 @@ export const updateWorkItemMutationResponse = { nodes: [ { id: 'gid://gitlab/WorkItem/444', + createdAt: '2022-08-03T12:41:54Z', + closedAt: null, + confidential: false, + title: '123', + state: 'OPEN', + workItemType: { + id: '1', + }, }, ], }, @@ -318,6 +332,12 @@ export const workItemResponseFactory = ({ id: 'gid://gitlab/WorkItem/444', createdAt: '2022-08-03T12:41:54Z', closedAt: null, + confidential: false, + title: '123', + state: 'OPEN', + workItemType: { + id: '1', + }, }, ], }, diff --git a/spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb index 6c7fc4d5b15..3bf1976ee10 100644 --- a/spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb @@ -109,7 +109,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequests::ReviewRequestsImpor expect(Gitlab::GithubImport::PullRequests::ImportReviewRequestWorker) .to receive(:bulk_perform_in).with( 1.second, - expected_worker_payload, + match_array(expected_worker_payload), batch_size: 1000, batch_delay: 1.minute ) diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index d8f50fa27bb..1418adb535f 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -602,31 +602,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do ) end - context 'with existing container expiration policies' do - let_it_be(:disabled) { create(:container_expiration_policy, enabled: false) } - let_it_be(:enabled) { create(:container_expiration_policy, enabled: true) } - - ::ContainerExpirationPolicy.older_than_options.keys.each do |value| - let_it_be("container_expiration_policy_with_older_than_set_to_#{value}") { create(:container_expiration_policy, older_than: value) } - end - - let_it_be('container_expiration_policy_with_older_than_set_to_null') { create(:container_expiration_policy, older_than: nil) } - - let(:inactive_policies) { ::ContainerExpirationPolicy.where(enabled: false) } - let(:active_policies) { ::ContainerExpirationPolicy.active } - - subject { described_class.data[:counts] } - - it 'gathers usage data' do - expect(subject[:projects_with_expiration_policy_enabled_with_older_than_unset]).to eq 1 - expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_7d]).to eq 1 - expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_14d]).to eq 1 - expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_30d]).to eq 1 - expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_60d]).to eq 1 - expect(subject[:projects_with_expiration_policy_enabled_with_older_than_set_to_90d]).to eq 2 - end - end - context 'when queries time out' do let(:metric_method) { :count } diff --git a/spec/models/integrations/base_slack_notification_spec.rb b/spec/models/integrations/base_slack_notification_spec.rb new file mode 100644 index 00000000000..8f7f4e8858d --- /dev/null +++ b/spec/models/integrations/base_slack_notification_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Integrations::BaseSlackNotification do + # This spec should only contain tests that cannot be tested through + # `base_slack_notification_shared_examples.rb`. + + describe '#metrics_key_prefix (private method)' do + it 'raises a NotImplementedError error when not defined' do + subclass = Class.new(described_class) + + expect { subclass.new.send(:metrics_key_prefix) }.to raise_error(NotImplementedError) + end + end +end diff --git a/spec/requests/groups/observability_controller_spec.rb b/spec/requests/groups/observability_controller_spec.rb index a08231fe939..ea6e05435d5 100644 --- a/spec/requests/groups/observability_controller_spec.rb +++ b/spec/requests/groups/observability_controller_spec.rb @@ -3,13 +3,12 @@ require 'spec_helper' RSpec.describe Groups::ObservabilityController do - include ContentSecurityPolicyHelpers - let_it_be(:group) { create(:group) } let_it_be(:user) { create(:user) } let(:observability_url) { Gitlab::Observability.observability_url } - let(:expected_observability_path) { "/" } + let(:path) { nil } + let(:expected_observability_path) { nil } shared_examples 'observability route request' do subject do @@ -17,6 +16,10 @@ RSpec.describe Groups::ObservabilityController do response end + it_behaves_like 'observability csp policy' do + let(:tested_path) { path } + end + context 'when user is not authenticated' do it 'returns 404' do expect(subject).to have_gitlab_http_status(:not_found) @@ -88,83 +91,4 @@ RSpec.describe Groups::ObservabilityController do it_behaves_like 'observability route request' end - - describe 'CSP' do - before do - setup_csp_for_controller(described_class, csp) - end - - subject do - get group_observability_dashboards_path(group) - response.headers['Content-Security-Policy'] - end - - context 'when there is no CSP config' do - let(:csp) { ActionDispatch::ContentSecurityPolicy.new } - - it 'does not add any csp header' do - expect(subject).to be_blank - end - end - - context 'when frame-src exists in the CSP config' do - let(:csp) do - ActionDispatch::ContentSecurityPolicy.new do |p| - p.frame_src 'https://something.test' - end - end - - it 'appends the proper url to frame-src CSP directives' do - expect(subject).to include( - "frame-src https://something.test #{observability_url} 'self'") - end - end - - context 'when self is already present in the policy' do - let(:csp) do - ActionDispatch::ContentSecurityPolicy.new do |p| - p.frame_src "'self'" - end - end - - it 'does not append self again' do - expect(subject).to include( - "frame-src 'self' #{observability_url};") - end - end - - context 'when default-src exists in the CSP config' do - let(:csp) do - ActionDispatch::ContentSecurityPolicy.new do |p| - p.default_src 'https://something.test' - end - end - - it 'does not change default-src' do - expect(subject).to include( - "default-src https://something.test;") - end - - it 'appends the proper url to frame-src CSP directives' do - expect(subject).to include( - "frame-src https://something.test #{observability_url} 'self'") - end - end - - context 'when frame-src and default-src exist in the CSP config' do - let(:csp) do - ActionDispatch::ContentSecurityPolicy.new do |p| - p.default_src 'https://something_default.test' - p.frame_src 'https://something.test' - end - end - - it 'appends to frame-src CSP directives' do - expect(subject).to include( - "frame-src https://something.test #{observability_url} 'self'") - expect(subject).to include( - "default-src https://something_default.test") - end - end - end end diff --git a/spec/requests/jira_connect/oauth_application_ids_controller_spec.rb b/spec/requests/jira_connect/oauth_application_ids_controller_spec.rb index 1d772e973ff..3d1f14a681b 100644 --- a/spec/requests/jira_connect/oauth_application_ids_controller_spec.rb +++ b/spec/requests/jira_connect/oauth_application_ids_controller_spec.rb @@ -38,9 +38,9 @@ RSpec.describe JiraConnect::OauthApplicationIdsController do end end - context 'when jira_connect_oauth_self_managed disabled' do + context 'when jira_connect_oauth_self_managed_setting disabled' do before do - stub_feature_flags(jira_connect_oauth_self_managed: false) + stub_feature_flags(jira_connect_oauth_self_managed_setting: false) end it 'renders not found' do diff --git a/spec/rubocop/cop/migration/batch_migrations_post_only_spec.rb b/spec/rubocop/cop/migration/batch_migrations_post_only_spec.rb new file mode 100644 index 00000000000..b5e2e83e788 --- /dev/null +++ b/spec/rubocop/cop/migration/batch_migrations_post_only_spec.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'rubocop_spec_helper' +require_relative '../../../../rubocop/cop/migration/batch_migrations_post_only' + +RSpec.describe RuboCop::Cop::Migration::BatchMigrationsPostOnly do + let(:cop) { described_class.new } + + before do + allow(cop).to receive(:in_post_deployment_migration?).and_return post_migration? + end + + context 'when methods appear in a regular migration' do + let(:post_migration?) { false } + + it "does not allow 'ensure_batched_background_migration_is_finished' to be called" do + expect_offense(<<~CODE) + ensure_batched_background_migration_is_finished + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This method must only be used in post-deployment migrations. + CODE + end + + it "does not allow 'queue_batched_background_migration' to be called" do + expect_offense(<<~CODE) + queue_batched_background_migration + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This method must only be used in post-deployment migrations. + CODE + end + + it "does not allow 'delete_batched_background_migration' to be called" do + expect_offense(<<~CODE) + delete_batched_background_migration + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This method must only be used in post-deployment migrations. + CODE + end + + it "does not allow 'ensure_batched_background_migration_is_finished' to be called" do + expect_offense(<<~CODE) + finalize_batched_background_migration + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This method must only be used in post-deployment migrations. + CODE + end + + it 'allows arbitrary other method to be called' do + expect_no_offenses(<<~CODE) + foo + CODE + end + end + + context 'when methods appear in a post-deployment migration' do + let(:post_migration?) { true } + + it "allows 'ensure_batched_background_migration_is_finished' to be called" do + expect_no_offenses(<<~CODE) + ensure_batched_background_migration_is_finished + CODE + end + + it "allows 'queue_batched_background_migration' to be called" do + expect_no_offenses(<<~CODE) + queue_batched_background_migration + CODE + end + + it "allows 'delete_batched_background_migration' to be called" do + expect_no_offenses(<<~CODE) + delete_batched_background_migration + CODE + end + + it "allows 'ensure_batched_background_migration_is_finished' to be called" do + expect_no_offenses(<<~CODE) + finalize_batched_background_migration + CODE + end + + it 'allows arbitrary other method to be called' do + expect_no_offenses(<<~CODE) + foo + CODE + end + end +end diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb index 92a946db337..71171ad0593 100644 --- a/spec/support/helpers/usage_data_helpers.rb +++ b/spec/support/helpers/usage_data_helpers.rb @@ -67,12 +67,6 @@ module UsageDataHelpers projects_with_repositories_enabled projects_with_error_tracking_enabled projects_with_enabled_alert_integrations - projects_with_expiration_policy_enabled_with_older_than_unset - projects_with_expiration_policy_enabled_with_older_than_set_to_7d - projects_with_expiration_policy_enabled_with_older_than_set_to_14d - projects_with_expiration_policy_enabled_with_older_than_set_to_30d - projects_with_expiration_policy_enabled_with_older_than_set_to_60d - projects_with_expiration_policy_enabled_with_older_than_set_to_90d projects_with_terraform_reports projects_with_terraform_states pages_domains diff --git a/spec/support/shared_examples/models/concerns/integrations/base_slack_notification_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/base_slack_notification_shared_examples.rb index f0581333b28..1d0278682d4 100644 --- a/spec/support/shared_examples/models/concerns/integrations/base_slack_notification_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/integrations/base_slack_notification_shared_examples.rb @@ -9,10 +9,16 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| stub_request(:post, integration.webhook) end + def usage_tracking_key(action) + prefix = integration.send(:metrics_key_prefix) + + "#{prefix}_#{action}_notification" + end + it 'uses only known events', :aggregate_failures do described_class::SUPPORTED_EVENTS_FOR_USAGE_LOG.each do |action| expect( - Gitlab::UsageDataCounters::HLLRedisCounter.known_event?("i_ecosystem_slack_service_#{action}_notification") + Gitlab::UsageDataCounters::HLLRedisCounter.known_event?(usage_tracking_key(action)) ).to be true end end @@ -20,7 +26,9 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| context 'when hook data includes a user object' do let_it_be(:user) { create_default(:user) } - shared_examples 'increases the usage data counter' do |event_name| + shared_examples 'increases the usage data counter' do |event| + let(:event_name) { usage_tracking_key(event) } + subject(:execute) { integration.execute(data) } it 'increases the usage data counter' do @@ -47,7 +55,7 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| it 'does not increase the usage data counter' do expect(Gitlab::UsageDataCounters::HLLRedisCounter) - .not_to receive(:track_event).with('i_ecosystem_slack_service_pipeline_notification', values: user.id) + .not_to receive(:track_event).with(usage_tracking_key(:pipeline), values: user.id) integration.execute(data) end @@ -58,13 +66,13 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| let(:data) { issue.to_hook_data(user) } - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_issue_notification' + it_behaves_like 'increases the usage data counter', :issue end context 'for push notification' do let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) } - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_push_notification' + it_behaves_like 'increases the usage data counter', :push end context 'for deployment notification' do @@ -72,7 +80,7 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| let(:data) { Gitlab::DataBuilder::Deployment.build(deployment, deployment.status, Time.current) } - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_deployment_notification' + it_behaves_like 'increases the usage data counter', :deployment end context 'for wiki_page notification' do @@ -88,7 +96,7 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| allow(project.wiki).to receive(:after_wiki_activity) end - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_wiki_page_notification' + it_behaves_like 'increases the usage data counter', :wiki_page end context 'for merge_request notification' do @@ -96,7 +104,7 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| let(:data) { merge_request.to_hook_data(user) } - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_merge_request_notification' + it_behaves_like 'increases the usage data counter', :merge_request end context 'for note notification' do @@ -104,7 +112,7 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) } - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_note_notification' + it_behaves_like 'increases the usage data counter', :note end context 'for tag_push notification' do @@ -115,7 +123,7 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| Git::TagHooksService.new(project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref }).send(:push_data) end - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_tag_push_notification' + it_behaves_like 'increases the usage data counter', :tag_push end context 'for confidential note notification' do @@ -125,7 +133,7 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| let(:data) { Gitlab::DataBuilder::Note.build(confidential_issue_note, user) } - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_note_notification' + it_behaves_like 'increases the usage data counter', :confidential_note end context 'for confidential issue notification' do @@ -133,7 +141,7 @@ RSpec.shared_examples Integrations::BaseSlackNotification do |factory:| let(:data) { issue.to_hook_data(user) } - it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_issue_notification' + it_behaves_like 'increases the usage data counter', :confidential_issue end end diff --git a/spec/support/shared_examples/observability/csp_shared_examples.rb b/spec/support/shared_examples/observability/csp_shared_examples.rb new file mode 100644 index 00000000000..f41aa8daa9b --- /dev/null +++ b/spec/support/shared_examples/observability/csp_shared_examples.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +# Verifies that the proper CSP rules for Observabilty UI are applied to a given controller/path +# +# The path under test needs to be declared with `let(:tested_path) { .. }` in the context including this example +# +# ``` +# it_behaves_like "observability csp policy" do +# let(:tested_path) { ....the path under test } +# end +# ``` +# +# It optionally supports specifying the controller class handling the tested path as a parameter, e.g. +# +# ``` +# it_behaves_like "observability csp policy", Groups::ObservabilityController +# ``` +# (If not specified it will default to `described_class`) +# +RSpec.shared_examples 'observability csp policy' do |controller_class = described_class| + include ContentSecurityPolicyHelpers + + let(:observability_url) { Gitlab::Observability.observability_url } + + before do + setup_csp_for_controller(described_class, csp) + end + + subject do + get tested_path + response.headers['Content-Security-Policy'] + end + + context 'when there is no CSP config' do + let(:csp) { ActionDispatch::ContentSecurityPolicy.new } + + it 'does not add any csp header' do + expect(subject).to be_blank + end + end + + context 'when frame-src exists in the CSP config' do + let(:csp) do + ActionDispatch::ContentSecurityPolicy.new do |p| + p.frame_src 'https://something.test' + end + end + + it 'appends the proper url to frame-src CSP directives' do + expect(subject).to include( + "frame-src https://something.test #{observability_url} 'self'") + end + end + + context 'when self is already present in the policy' do + let(:csp) do + ActionDispatch::ContentSecurityPolicy.new do |p| + p.frame_src "'self'" + end + end + + it 'does not append self again' do + expect(subject).to include( + "frame-src 'self' #{observability_url};") + end + end + + context 'when default-src exists in the CSP config' do + let(:csp) do + ActionDispatch::ContentSecurityPolicy.new do |p| + p.default_src 'https://something.test' + end + end + + it 'does not change default-src' do + expect(subject).to include( + "default-src https://something.test;") + end + + it 'appends the proper url to frame-src CSP directives' do + expect(subject).to include( + "frame-src https://something.test #{observability_url} 'self'") + end + end + + context 'when frame-src and default-src exist in the CSP config' do + let(:csp) do + ActionDispatch::ContentSecurityPolicy.new do |p| + p.default_src 'https://something_default.test' + p.frame_src 'https://something.test' + end + end + + it 'appends to frame-src CSP directives' do + expect(subject).to include( + "frame-src https://something.test #{observability_url} 'self'") + expect(subject).to include( + "default-src https://something_default.test") + end + end +end |