summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-11-17 00:09:56 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-11-17 00:09:56 +0000
commitcc626f14115f740bd4aa247cf3ac42dfb2082a4e (patch)
treeb5c7f25711903177ea0e756b1fabd8eef2a9ca14 /spec
parent19db7fd1fefc4e4249d4e55f409f321fdb85aed1 (diff)
downloadgitlab-ce-cc626f14115f740bd4aa247cf3ac42dfb2082a4e.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb2
-rw-r--r--spec/controllers/registrations_controller_spec.rb33
-rw-r--r--spec/db/schema_spec.rb11
-rw-r--r--spec/finders/notes_finder_spec.rb10
-rw-r--r--spec/frontend/work_items/components/work_item_description_spec.js12
-rw-r--r--spec/frontend/work_items/mock_data.js20
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests/review_requests_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb25
-rw-r--r--spec/models/integrations/base_slack_notification_spec.rb16
-rw-r--r--spec/requests/groups/observability_controller_spec.rb88
-rw-r--r--spec/requests/jira_connect/oauth_application_ids_controller_spec.rb4
-rw-r--r--spec/rubocop/cop/migration/batch_migrations_post_only_spec.rb84
-rw-r--r--spec/support/helpers/usage_data_helpers.rb6
-rw-r--r--spec/support/shared_examples/models/concerns/integrations/base_slack_notification_shared_examples.rb32
-rw-r--r--spec/support/shared_examples/observability/csp_shared_examples.rb101
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