summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-10 16:46:51 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-10 16:46:51 +0000
commit04ac4180cb5ba0df460034c7e64862056fd498b3 (patch)
treeca5267d12fa2aab80c1c35593b96c8cfceaa747b /spec
parent4e9ceea7f8ff3e097ad45f6f54c1b7165248e848 (diff)
downloadgitlab-ce-04ac4180cb5ba0df460034c7e64862056fd498b3.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/profiles/preferences_controller_spec.rb3
-rw-r--r--spec/features/clusters/cluster_health_dashboard_spec.rb20
-rw-r--r--spec/features/ide_spec.rb11
-rw-r--r--spec/features/profiles/user_edit_preferences_spec.rb18
-rw-r--r--spec/frontend/admin/broadcast_messages/mock_data.js5
-rw-r--r--spec/graphql/resolvers/ci/inherited_variables_resolver_spec.rb40
-rw-r--r--spec/graphql/types/ci/inherited_ci_variable_type_spec.rb19
-rw-r--r--spec/graphql/types/project_type_spec.rb2
-rw-r--r--spec/helpers/broadcast_messages_helper_spec.rb15
-rw-r--r--spec/helpers/ide_helper_spec.rb6
-rw-r--r--spec/lib/gitlab/source_spec.rb10
-rw-r--r--spec/models/ci/group_variable_spec.rb12
-rw-r--r--spec/models/concerns/issuable_spec.rb26
-rw-r--r--spec/models/concerns/taskable_spec.rb7
-rw-r--r--spec/models/merge_request_spec.rb15
-rw-r--r--spec/models/namespace_setting_spec.rb90
-rw-r--r--spec/models/user_preference_spec.rb7
-rw-r--r--spec/models/user_spec.rb3
-rw-r--r--spec/requests/admin/abuse_reports_controller_spec.rb37
-rw-r--r--spec/requests/api/graphql/ci/inherited_ci_variables_spec.rb108
-rw-r--r--spec/requests/api/merge_requests_spec.rb2
-rw-r--r--spec/requests/api/resource_access_tokens_spec.rb78
-rw-r--r--spec/requests/ide_controller_spec.rb9
-rw-r--r--spec/requests/projects/metrics_dashboard_spec.rb12
-rw-r--r--spec/services/admin/abuse_report_update_service_spec.rb199
-rw-r--r--spec/services/task_list_toggle_service_spec.rb19
-rw-r--r--spec/views/admin/groups/_form.html.haml_spec.rb42
-rw-r--r--spec/views/help/index.html.haml_spec.rb8
28 files changed, 689 insertions, 134 deletions
diff --git a/spec/controllers/profiles/preferences_controller_spec.rb b/spec/controllers/profiles/preferences_controller_spec.rb
index 0554ab3184f..e2ade5e3de9 100644
--- a/spec/controllers/profiles/preferences_controller_spec.rb
+++ b/spec/controllers/profiles/preferences_controller_spec.rb
@@ -53,8 +53,7 @@ RSpec.describe Profiles::PreferencesController do
first_day_of_week: '1',
preferred_language: 'jp',
tab_width: '5',
- render_whitespace_in_code: 'true',
- use_legacy_web_ide: 'true'
+ render_whitespace_in_code: 'true'
}.with_indifferent_access
expect(user).to receive(:assign_attributes).with(ActionController::Parameters.new(prefs).permit!)
diff --git a/spec/features/clusters/cluster_health_dashboard_spec.rb b/spec/features/clusters/cluster_health_dashboard_spec.rb
index ebbc184eaef..e932f8c6b98 100644
--- a/spec/features/clusters/cluster_health_dashboard_spec.rb
+++ b/spec/features/clusters/cluster_health_dashboard_spec.rb
@@ -13,6 +13,8 @@ feature_category: :deployment_management do
let_it_be(:cluster_path) { project_cluster_path(clusterable, cluster) }
before do
+ stub_feature_flags(remove_monitor_metrics: false)
+
clusterable.add_maintainer(current_user)
sign_in(current_user)
@@ -28,6 +30,24 @@ feature_category: :deployment_management do
expect(page).to have_css('.cluster-health-graphs')
end
+ context 'feature remove_monitor_metrics enabled' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it 'does not show the cluster health tab' do
+ visit cluster_path
+
+ expect(page).not_to have_text('Health')
+ end
+
+ it 'does not show the cluster health section' do
+ visit project_cluster_path(clusterable, cluster, { tab: 'health' })
+
+ expect(page).not_to have_text('you must first enable Prometheus in the Integrations tab')
+ end
+ end
+
context 'no prometheus available' do
it 'shows enable Prometheus message' do
visit cluster_path
diff --git a/spec/features/ide_spec.rb b/spec/features/ide_spec.rb
index 615f2a30b34..bdf8be95415 100644
--- a/spec/features/ide_spec.rb
+++ b/spec/features/ide_spec.rb
@@ -48,17 +48,6 @@ RSpec.describe 'IDE', :js, feature_category: :web_ide do
it_behaves_like 'legacy Web IDE'
end
- context 'with vscode feature flag on and use_legacy_web_ide=true' do
- let(:vscode_ff) { true }
- let(:user) { create(:user, use_legacy_web_ide: true) }
-
- before do
- ide_visit(project)
- end
-
- it_behaves_like 'legacy Web IDE'
- end
-
describe 'sub-groups' do
let_it_be(:group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: group) }
diff --git a/spec/features/profiles/user_edit_preferences_spec.rb b/spec/features/profiles/user_edit_preferences_spec.rb
index 341eec11091..6cc926ed017 100644
--- a/spec/features/profiles/user_edit_preferences_spec.rb
+++ b/spec/features/profiles/user_edit_preferences_spec.rb
@@ -27,24 +27,6 @@ RSpec.describe 'User edit preferences profile', :js, feature_category: :user_pro
expect(field).not_to be_checked
end
- it 'allows the user to toggle using the legacy web ide' do
- field = page.find_field("user[use_legacy_web_ide]")
-
- expect(field).not_to be_checked
-
- field.click
-
- expect(field).to be_checked
- end
-
- describe 'when vscode_web_ide feature flag is disabled' do
- let(:vscode_web_ide) { false }
-
- it 'does not display the legacy web ide user preference' do
- expect(page).not_to have_field("user[use_legacy_web_ide]")
- end
- end
-
describe 'User changes tab width to acceptable value' do
it 'shows success message' do
fill_in 'Tab width', with: 9
diff --git a/spec/frontend/admin/broadcast_messages/mock_data.js b/spec/frontend/admin/broadcast_messages/mock_data.js
index 2e20b5cf638..54596fbf977 100644
--- a/spec/frontend/admin/broadcast_messages/mock_data.js
+++ b/spec/frontend/admin/broadcast_messages/mock_data.js
@@ -4,7 +4,10 @@ const generateMockMessage = (id) => ({
edit_path: `/admin/broadcast_messages/${id}/edit`,
starts_at: new Date().toISOString(),
ends_at: new Date().toISOString(),
- preview: '<div>YEET</div>',
+ broadcast_type: 'banner',
+ dismissable: true,
+ message: 'YEET',
+ theme: 'indigo',
status: 'Expired',
target_path: '*/welcome',
target_roles: 'Maintainer, Owner',
diff --git a/spec/graphql/resolvers/ci/inherited_variables_resolver_spec.rb b/spec/graphql/resolvers/ci/inherited_variables_resolver_spec.rb
new file mode 100644
index 00000000000..6837d4b0459
--- /dev/null
+++ b/spec/graphql/resolvers/ci/inherited_variables_resolver_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::InheritedVariablesResolver, feature_category: :secrets_management do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:project) { create(:project, group: subgroup) }
+ let_it_be(:project_without_group) { create(:project) }
+
+ let_it_be(:inherited_ci_variables) do
+ [
+ create(:ci_group_variable, group: group, key: 'GROUP_VAR_A'),
+ create(:ci_group_variable, group: subgroup, key: 'SUBGROUP_VAR_B')
+ ]
+ end
+
+ subject(:resolve_variables) { resolve(described_class, obj: obj, ctx: { current_user: user }, args: {}) }
+
+ context 'when project does not have a group' do
+ let_it_be(:obj) { project_without_group }
+
+ it 'returns an empty array' do
+ expect(resolve_variables.items.to_a).to match_array([])
+ end
+ end
+
+ context 'when project belongs to a group' do
+ let_it_be(:obj) { project }
+
+ it 'returns variables from parent group and ancestors' do
+ expect(resolve_variables.items.to_a).to match_array(inherited_ci_variables)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb b/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb
new file mode 100644
index 00000000000..daf80ff9978
--- /dev/null
+++ b/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['InheritedCiVariable'], feature_category: :secrets_management do
+ specify do
+ expect(described_class).to have_graphql_fields(
+ :id,
+ :key,
+ :raw,
+ :variable_type,
+ :environment_scope,
+ :masked,
+ :protected,
+ :group_name,
+ :group_ci_cd_settings_path
+ ).at_least
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 5c2e67ca787..0f980241db3 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe GitlabSchema.types['Project'] do
ci_template timelogs merge_commit_template squash_commit_template work_item_types
recent_issue_boards ci_config_path_or_default packages_cleanup_policy ci_variables
timelog_categories fork_targets branch_rules ci_config_variables pipeline_schedules languages
- incident_management_timeline_event_tags visible_forks
+ incident_management_timeline_event_tags visible_forks inherited_ci_variables
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/helpers/broadcast_messages_helper_spec.rb b/spec/helpers/broadcast_messages_helper_spec.rb
index 480aeb94876..5d6d404d24d 100644
--- a/spec/helpers/broadcast_messages_helper_spec.rb
+++ b/spec/helpers/broadcast_messages_helper_spec.rb
@@ -141,7 +141,20 @@ RSpec.describe BroadcastMessagesHelper, feature_category: :onboarding do
subject(:single_broadcast_message) { Gitlab::Json.parse(admin_broadcast_messages_data([message])).first }
it 'returns the expected messages data attributes' do
- keys = %w[id status preview starts_at ends_at target_roles target_path type edit_path delete_path]
+ keys = %w[
+ id
+ status
+ message
+ theme
+ broadcast_type
+ dismissable
+ starts_at
+ ends_at
+ target_roles
+ target_path
+ type edit_path
+ delete_path
+ ]
expect(single_broadcast_message.keys).to match(keys)
end
diff --git a/spec/helpers/ide_helper_spec.rb b/spec/helpers/ide_helper_spec.rb
index 4a184f03935..922155abf65 100644
--- a/spec/helpers/ide_helper_spec.rb
+++ b/spec/helpers/ide_helper_spec.rb
@@ -18,7 +18,6 @@ RSpec.describe IdeHelper, feature_category: :web_ide do
let(:base_data) do
{
- 'can-use-new-web-ide' => 'false',
'use-new-web-ide' => 'false',
'user-preferences-path' => profile_preferences_path,
'sign-in-path' => 'test-sign-in-path',
@@ -98,7 +97,6 @@ RSpec.describe IdeHelper, feature_category: :web_ide do
context 'with vscode_web_ide=true' do
let(:base_data) do
{
- 'can-use-new-web-ide' => 'true',
'use-new-web-ide' => 'true',
'user-preferences-path' => profile_preferences_path,
'sign-in-path' => 'test-sign-in-path',
@@ -121,8 +119,8 @@ RSpec.describe IdeHelper, feature_category: :web_ide do
.to include(base_data)
end
- it 'does not use new web ide if user.use_legacy_web_ide' do
- allow(user).to receive(:use_legacy_web_ide).and_return(true)
+ it 'does not use new web ide if feature flag is disabled' do
+ stub_feature_flags(vscode_web_ide: false)
expect(helper.ide_data(project: nil, fork_info: fork_info, params: params))
.to include('use-new-web-ide' => 'false')
diff --git a/spec/lib/gitlab/source_spec.rb b/spec/lib/gitlab/source_spec.rb
index c2ecb4dfb85..0b2515baf2b 100644
--- a/spec/lib/gitlab/source_spec.rb
+++ b/spec/lib/gitlab/source_spec.rb
@@ -28,13 +28,19 @@ RSpec.describe Gitlab::Source, feature_category: :shared do
describe '.release_url' do
subject(:release_url) { described_class.release_url }
+ def release_path
+ Gitlab::Utils.append_path(
+ described_class.send(:host_url),
+ "#{described_class.send(:group)}/#{described_class.send(:project)}")
+ end
+
context 'when not on a pre-release' do
before do
stub_version('15.0.0-ee', 'a123a123')
end
it 'returns a tag url' do
- expect(release_url).to match("https://gitlab.com/gitlab-org/gitlab(-foss)?/-/tags/v15.0.0-ee")
+ expect(release_url).to eq("#{release_path}/-/tags/v15.0.0-ee")
end
end
@@ -44,7 +50,7 @@ RSpec.describe Gitlab::Source, feature_category: :shared do
end
it 'returns a commit url' do
- expect(release_url).to match("https://gitlab.com/gitlab-org/gitlab(-foss)?/-/commits/a123a123")
+ expect(release_url).to eq("#{release_path}/-/commits/a123a123")
end
end
end
diff --git a/spec/models/ci/group_variable_spec.rb b/spec/models/ci/group_variable_spec.rb
index 0e249ec528f..a2751b9fb20 100644
--- a/spec/models/ci/group_variable_spec.rb
+++ b/spec/models/ci/group_variable_spec.rb
@@ -65,4 +65,16 @@ RSpec.describe Ci::GroupVariable, feature_category: :secrets_management do
expect(subject.audit_details).to eq(subject.key)
end
end
+
+ describe '#group_name' do
+ it "equals to the name of the group the variable belongs to" do
+ expect(subject.group_name).to eq(subject.group.name)
+ end
+ end
+
+ describe '#group_ci_cd_settings_path' do
+ it "equals to the path of the CI/CD settings of the group the variable belongs to" do
+ expect(subject.group_ci_cd_settings_path).to eq(Gitlab::Routing.url_helpers.group_settings_ci_cd_path(subject.group))
+ end
+ end
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index ea6baac455f..de46da4e27b 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -860,22 +860,16 @@ RSpec.describe Issuable do
end
end
- describe '#first_contribution?' do
+ describe '#first_contribution?', feature_category: :code_review_workflow do
let(:group) { create(:group) }
let(:project) { create(:project, namespace: group) }
let(:other_project) { create(:project) }
- let(:owner) { create(:owner) }
- let(:maintainer) { create(:user) }
- let(:reporter) { create(:user) }
let(:guest) { create(:user) }
let(:contributor) { create(:user) }
let(:first_time_contributor) { create(:user) }
before do
- group.add_owner(owner)
- project.add_maintainer(maintainer)
- project.add_reporter(reporter)
project.add_guest(guest)
project.add_guest(contributor)
project.add_guest(first_time_contributor)
@@ -886,24 +880,6 @@ RSpec.describe Issuable do
let(:merged_mr_other_project) { create(:merge_request, :merged, author: first_time_contributor, target_project: other_project, source_project: other_project) }
context "for merge requests" do
- it "is false for MAINTAINER" do
- mr = create(:merge_request, author: maintainer, target_project: project, source_project: project)
-
- expect(mr).not_to be_first_contribution
- end
-
- it "is false for OWNER" do
- mr = create(:merge_request, author: owner, target_project: project, source_project: project)
-
- expect(mr).not_to be_first_contribution
- end
-
- it "is false for REPORTER" do
- mr = create(:merge_request, author: reporter, target_project: project, source_project: project)
-
- expect(mr).not_to be_first_contribution
- end
-
it "is true when you don't have any merged MR" do
expect(open_mr).to be_first_contribution
expect(merged_mr).not_to be_first_contribution
diff --git a/spec/models/concerns/taskable_spec.rb b/spec/models/concerns/taskable_spec.rb
index 20de8995d13..dad0db2d898 100644
--- a/spec/models/concerns/taskable_spec.rb
+++ b/spec/models/concerns/taskable_spec.rb
@@ -27,6 +27,9 @@ RSpec.describe Taskable, feature_category: :team_planning do
+ [ ] Narrow no-break space (U+202F)
+ [ ] Thin space (U+2009)
+
+ 1. [ ] Numbered 1
+ 2) [x] Numbered 2
MARKDOWN
end
@@ -35,7 +38,9 @@ RSpec.describe Taskable, feature_category: :team_planning do
TaskList::Item.new('- [ ]', 'First item'),
TaskList::Item.new('- [x]', 'Second item'),
TaskList::Item.new('* [x]', 'First item'),
- TaskList::Item.new('* [ ]', 'Second item')
+ TaskList::Item.new('* [ ]', 'Second item'),
+ TaskList::Item.new('1. [ ]', 'Numbered 1'),
+ TaskList::Item.new('2) [x]', 'Numbered 2')
]
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 72420e275c5..a5e68829c5d 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -4647,18 +4647,11 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
.to(false)
end
- it 'sets first_contribution to false' do
- subject.mark_as_merged
-
- expect(subject.state).to eq('merged')
- expect(subject.first_contribution?).to be_falsey
- end
-
- context 'when it is a contribution from a project non-member' do
- let(:non_member) { create(:user) }
+ context 'when it is a first contribution' do
+ let(:new_user) { create(:user) }
before do
- subject.update!(author: non_member)
+ subject.update!(author: new_user)
end
it 'sets first_contribution' do
@@ -4669,7 +4662,7 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
end
it "doesn't set first_contribution not first contribution" do
- create(:merged_merge_request, author: non_member)
+ create(:merged_merge_request, author: new_user)
subject.mark_as_merged
diff --git a/spec/models/namespace_setting_spec.rb b/spec/models/namespace_setting_spec.rb
index e3d389a2a6e..ba0ce7d6f7f 100644
--- a/spec/models/namespace_setting_spec.rb
+++ b/spec/models/namespace_setting_spec.rb
@@ -194,7 +194,7 @@ RSpec.describe NamespaceSetting, feature_category: :subgroups, type: :model do
context 'when a group has parent groups' do
let(:grandparent) { create(:group, namespace_settings: settings) }
let(:parent) { create(:group, parent: grandparent) }
- let!(:group) { create(:group, parent: parent) }
+ let!(:group) { create(:group, parent: parent) }
context "when a parent group has disabled diff previews" do
let(:settings) { create(:namespace_settings, show_diff_preview_in_email: false) }
@@ -214,61 +214,87 @@ RSpec.describe NamespaceSetting, feature_category: :subgroups, type: :model do
end
end
- describe '#runner_registration_enabled?' do
- context 'when not a subgroup' do
- let_it_be(:settings) { create(:namespace_settings) }
- let_it_be(:group) { create(:group, namespace_settings: settings) }
+ context 'runner registration settings' do
+ shared_context 'with runner registration settings changing in hierarchy' do
+ context 'when there are no parents' do
+ let_it_be(:group) { create(:group) }
- before do
- group.update!(runner_registration_enabled: runner_registration_enabled)
+ it { is_expected.to be_truthy }
+
+ context 'when no group can register runners' do
+ before do
+ stub_application_setting(valid_runner_registrars: [])
+ end
+
+ it { is_expected.to be_falsey }
+ end
end
- context 'when :runner_registration_enabled is false' do
- let(:runner_registration_enabled) { false }
+ context 'when there are parents' do
+ let_it_be(:grandparent) { create(:group) }
+ let_it_be(:parent) { create(:group, parent: grandparent) }
+ let_it_be(:group) { create(:group, parent: parent) }
- it 'returns false' do
- expect(group.runner_registration_enabled?).to be_falsey
+ before do
+ grandparent.update!(runner_registration_enabled: grandparent_runner_registration_enabled)
end
- it 'does not query the db' do
- expect { group.runner_registration_enabled? }.not_to exceed_query_limit(0)
+ context 'when a parent group has runner registration disabled' do
+ let(:grandparent_runner_registration_enabled) { false }
+
+ it { is_expected.to be_falsey }
end
- end
- context 'when :runner_registration_enabled is true' do
- let(:runner_registration_enabled) { true }
+ context 'when all parent groups have runner registration enabled' do
+ let(:grandparent_runner_registration_enabled) { true }
- it 'returns true' do
- expect(group.runner_registration_enabled?).to be_truthy
+ it { is_expected.to be_truthy }
end
end
end
- context 'when a group has parent groups' do
- let_it_be(:grandparent) { create(:group) }
- let_it_be(:parent) { create(:group, parent: grandparent) }
- let_it_be(:group) { create(:group, parent: parent) }
+ describe '#runner_registration_enabled?' do
+ subject(:group_setting) { group.runner_registration_enabled? }
+
+ let_it_be(:settings) { create(:namespace_settings) }
+ let_it_be(:group) { create(:group, namespace_settings: settings) }
before do
- grandparent.update!(runner_registration_enabled: runner_registration_enabled)
+ group.update!(runner_registration_enabled: group_runner_registration_enabled)
end
- context 'when a parent group has runner registration disabled' do
- let(:runner_registration_enabled) { false }
+ context 'when runner registration is enabled' do
+ let(:group_runner_registration_enabled) { true }
- it 'returns false' do
- expect(group.runner_registration_enabled?).to be_falsey
- end
+ it { is_expected.to be_truthy }
+
+ it_behaves_like 'with runner registration settings changing in hierarchy'
end
- context 'when all parent groups have runner registration enabled' do
- let(:runner_registration_enabled) { true }
+ context 'when runner registration is disabled' do
+ let(:group_runner_registration_enabled) { false }
- it 'returns true' do
- expect(group.runner_registration_enabled?).to be_truthy
+ it { is_expected.to be_falsey }
+
+ it 'does not query the db' do
+ expect { group.runner_registration_enabled? }.not_to exceed_query_limit(0)
+ end
+
+ context 'when group runner registration is disallowed' do
+ before do
+ stub_application_setting(valid_runner_registrars: [])
+ end
+
+ it { is_expected.to be_falsey }
end
end
end
+
+ describe '#all_ancestors_have_runner_registration_enabled?' do
+ subject(:group_setting) { group.all_ancestors_have_runner_registration_enabled? }
+
+ it_behaves_like 'with runner registration settings changing in hierarchy'
+ end
end
describe '#allow_runner_registration_token?' do
diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb
index e085ff934b2..1d7ecb724bf 100644
--- a/spec/models/user_preference_spec.rb
+++ b/spec/models/user_preference_spec.rb
@@ -48,13 +48,6 @@ RSpec.describe UserPreference, feature_category: :user_profile do
end
end
- describe 'use_legacy_web_ide' do
- it { is_expected.to allow_value(true).for(:use_legacy_web_ide) }
- it { is_expected.to allow_value(false).for(:use_legacy_web_ide) }
- it { is_expected.not_to allow_value(nil).for(:use_legacy_web_ide) }
- it { is_expected.not_to allow_value("").for(:use_legacy_web_ide) }
- end
-
describe 'pass_user_identities_to_ci_jwt' do
it { is_expected.to allow_value(true).for(:pass_user_identities_to_ci_jwt) }
it { is_expected.to allow_value(false).for(:pass_user_identities_to_ci_jwt) }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 8b6e3199529..eaf4ecda635 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -75,9 +75,6 @@ RSpec.describe User, feature_category: :user_profile do
it { is_expected.to delegate_method(:diffs_addition_color).to(:user_preference) }
it { is_expected.to delegate_method(:diffs_addition_color=).to(:user_preference).with_arguments(:args) }
- it { is_expected.to delegate_method(:use_legacy_web_ide).to(:user_preference) }
- it { is_expected.to delegate_method(:use_legacy_web_ide=).to(:user_preference).with_arguments(:args) }
-
it { is_expected.to delegate_method(:use_new_navigation).to(:user_preference) }
it { is_expected.to delegate_method(:use_new_navigation=).to(:user_preference).with_arguments(:args) }
diff --git a/spec/requests/admin/abuse_reports_controller_spec.rb b/spec/requests/admin/abuse_reports_controller_spec.rb
index ab527ab4df6..0b5aaabaa61 100644
--- a/spec/requests/admin/abuse_reports_controller_spec.rb
+++ b/spec/requests/admin/abuse_reports_controller_spec.rb
@@ -52,4 +52,41 @@ RSpec.describe Admin::AbuseReportsController, type: :request, feature_category:
expect(assigns(:abuse_report)).to eq report
end
end
+
+ describe 'PUT #update' do
+ let(:report) { create(:abuse_report) }
+ let(:params) { { user_action: 'block_user', close: 'true', reason: 'spam', comment: 'obvious spam' } }
+ let(:expected_params) { ActionController::Parameters.new(params).permit! }
+
+ it 'invokes the Admin::AbuseReportUpdateService' do
+ expect_next_instance_of(Admin::AbuseReportUpdateService, report, admin, expected_params) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ put admin_abuse_report_path(report, params)
+ end
+ end
+
+ describe 'DELETE #destroy' do
+ let!(:report) { create(:abuse_report) }
+ let(:params) { {} }
+
+ subject { delete admin_abuse_report_path(report, params) }
+
+ it 'destroys the report' do
+ expect { subject }.to change { AbuseReport.count }.by(-1)
+ end
+
+ context 'when passing the `remove_user` parameter' do
+ let(:params) { { remove_user: true } }
+
+ it 'calls the `remove_user` method' do
+ expect_next_found_instance_of(AbuseReport) do |report|
+ expect(report).to receive(:remove_user).with(deleted_by: admin)
+ end
+
+ subject
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/ci/inherited_ci_variables_spec.rb b/spec/requests/api/graphql/ci/inherited_ci_variables_spec.rb
new file mode 100644
index 00000000000..3b4014c178c
--- /dev/null
+++ b/spec/requests/api/graphql/ci/inherited_ci_variables_spec.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Query.project(fullPath).inheritedCiVariables', feature_category: :secrets_management do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:project) { create(:project, group: subgroup) }
+
+ let(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ inheritedCiVariables {
+ nodes {
+ id
+ key
+ environmentScope
+ groupName
+ groupCiCdSettingsPath
+ masked
+ protected
+ raw
+ variableType
+ }
+ }
+ }
+ }
+ )
+ end
+
+ def create_variables
+ create(:ci_group_variable, group: group)
+ create(:ci_group_variable, group: subgroup)
+ end
+
+ context 'when user is not a project maintainer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns nothing' do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data.dig('project', 'inheritedCiVariables')).to be_nil
+ end
+ end
+
+ context 'when user is a project maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it "returns the project's CI variables inherited from its parent group and ancestors" do
+ group_var = create(:ci_group_variable, group: group, key: 'GROUP_VAR_A',
+ environment_scope: 'production', masked: false, protected: true, raw: true)
+
+ subgroup_var = create(:ci_group_variable, group: subgroup, key: 'SUBGROUP_VAR_B',
+ masked: true, protected: false, raw: false, variable_type: 'file')
+
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data.dig('project', 'inheritedCiVariables', 'nodes')).to eq([
+ {
+ 'id' => group_var.to_global_id.to_s,
+ 'key' => 'GROUP_VAR_A',
+ 'environmentScope' => 'production',
+ 'groupName' => group.name,
+ 'groupCiCdSettingsPath' => group_var.group_ci_cd_settings_path,
+ 'masked' => false,
+ 'protected' => true,
+ 'raw' => true,
+ 'variableType' => 'ENV_VAR'
+ },
+ {
+ 'id' => subgroup_var.to_global_id.to_s,
+ 'key' => 'SUBGROUP_VAR_B',
+ 'environmentScope' => '*',
+ 'groupName' => subgroup.name,
+ 'groupCiCdSettingsPath' => subgroup_var.group_ci_cd_settings_path,
+ 'masked' => true,
+ 'protected' => false,
+ 'raw' => false,
+ 'variableType' => 'FILE'
+ }
+ ])
+ end
+
+ it 'avoids N+1 database queries' do
+ create_variables
+
+ baseline = ActiveRecord::QueryRecorder.new do
+ run_with_clean_state(query, context: { current_user: user })
+ end
+
+ create_variables
+
+ multi = ActiveRecord::QueryRecorder.new do
+ run_with_clean_state(query, context: { current_user: user })
+ end
+
+ expect(multi).not_to exceed_query_limit(baseline)
+ end
+ end
+end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index d705234b616..50e70a9dc0f 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1426,7 +1426,7 @@ RSpec.describe API::MergeRequests, :aggregate_failures, feature_category: :sourc
expect(json_response['merge_error']).to eq(merge_request.merge_error)
expect(json_response['user']['can_merge']).to be_truthy
expect(json_response).not_to include('rebase_in_progress')
- expect(json_response['first_contribution']).to be false
+ expect(json_response['first_contribution']).to be true
expect(json_response['has_conflicts']).to be false
expect(json_response['blocking_discussions_resolved']).to be_truthy
expect(json_response['references']['short']).to eq("!#{merge_request.iid}")
diff --git a/spec/requests/api/resource_access_tokens_spec.rb b/spec/requests/api/resource_access_tokens_spec.rb
index 9277fa18219..a13aa48a497 100644
--- a/spec/requests/api/resource_access_tokens_spec.rb
+++ b/spec/requests/api/resource_access_tokens_spec.rb
@@ -468,10 +468,86 @@ RSpec.describe API::ResourceAccessTokens, feature_category: :system_access do
end
end
end
+
+ context "POST #{source_type}s/:id/access_tokens/:token_id/rotate" do
+ let_it_be(:project_bot) { create(:user, :project_bot) }
+ let_it_be(:token) { create(:personal_access_token, user: project_bot) }
+ let_it_be(:resource_id) { resource.id }
+ let_it_be(:token_id) { token.id }
+
+ let(:path) { "/#{source_type}s/#{resource_id}/access_tokens/#{token_id}/rotate" }
+
+ before do
+ resource.add_maintainer(project_bot)
+ resource.add_owner(user)
+ end
+
+ subject(:rotate_token) { post api(path, user) }
+
+ it "allows owner to rotate token", :freeze_time do
+ rotate_token
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['token']).not_to eq(token.token)
+ expect(json_response['expires_at']).to eq((Date.today + 1.week).to_s)
+ end
+
+ context 'without permission' do
+ it 'returns an error message' do
+ another_user = create(:user)
+ resource.add_developer(another_user)
+
+ post api(path, another_user)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when service raises an error' do
+ let(:error_message) { 'boom!' }
+
+ before do
+ allow_next_instance_of(PersonalAccessTokens::RotateService) do |service|
+ allow(service).to receive(:execute).and_return(ServiceResponse.error(message: error_message))
+ end
+ end
+
+ it 'returns the same error message' do
+ rotate_token
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to eq("400 Bad request - #{error_message}")
+ end
+ end
+
+ context 'when token does not exist' do
+ let(:invalid_path) { "/#{source_type}s/#{resource_id}/access_tokens/#{non_existing_record_id}/rotate" }
+
+ context 'for non-admin user' do
+ it 'returns unauthorized' do
+ user = create(:user)
+ resource.add_developer(user)
+
+ post api(invalid_path, user)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'for admin user', :enable_admin_mode do
+ it 'returns not found' do
+ admin = create(:admin)
+ post api(invalid_path, admin)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
end
context 'when the resource is a project' do
- let_it_be(:resource) { create(:project) }
+ let_it_be(:resource) { create(:project, group: create(:group)) }
let_it_be(:other_resource) { create(:project) }
let_it_be(:unknown_resource) { create(:project) }
diff --git a/spec/requests/ide_controller_spec.rb b/spec/requests/ide_controller_spec.rb
index f7913b58aa3..fe7210e4372 100644
--- a/spec/requests/ide_controller_spec.rb
+++ b/spec/requests/ide_controller_spec.rb
@@ -169,17 +169,14 @@ RSpec.describe IdeController, feature_category: :web_ide do
# This indirectly tests that `minimal: true` was passed to the fullscreen layout
describe 'layout' do
- where(:ff_state, :use_legacy_web_ide, :expect_top_nav) do
- false | false | true
- false | true | true
- true | true | true
- true | false | false
+ where(:ff_state, :expect_top_nav) do
+ false | true
+ true | false
end
with_them do
before do
stub_feature_flags(vscode_web_ide: ff_state)
- allow(user).to receive(:use_legacy_web_ide).and_return(use_legacy_web_ide)
subject
end
diff --git a/spec/requests/projects/metrics_dashboard_spec.rb b/spec/requests/projects/metrics_dashboard_spec.rb
index 01925f8345b..d0181275927 100644
--- a/spec/requests/projects/metrics_dashboard_spec.rb
+++ b/spec/requests/projects/metrics_dashboard_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'Projects::MetricsDashboardController', feature_category: :metric
before do
project.add_developer(user)
login_as(user)
+ stub_feature_flags(remove_monitor_metrics: false)
end
describe 'GET /:namespace/:project/-/metrics' do
@@ -37,6 +38,17 @@ RSpec.describe 'Projects::MetricsDashboardController', feature_category: :metric
expect(response).to redirect_to(dashboard_route(params.merge(environment: environment.id)))
end
+ context 'with remove_monitor_metrics returning true' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it 'renders 404 page' do
+ send_request
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
context 'with anonymous user and public dashboard visibility' do
let(:anonymous_user) { create(:user) }
let(:project) do
diff --git a/spec/services/admin/abuse_report_update_service_spec.rb b/spec/services/admin/abuse_report_update_service_spec.rb
new file mode 100644
index 00000000000..e85b516b87f
--- /dev/null
+++ b/spec/services/admin/abuse_report_update_service_spec.rb
@@ -0,0 +1,199 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::AbuseReportUpdateService, feature_category: :instance_resiliency do
+ let_it_be_with_reload(:abuse_report) { create(:abuse_report) }
+ let(:action) { 'ban_user' }
+ let(:close) { true }
+ let(:reason) { 'spam' }
+ let(:params) { { user_action: action, close: close, reason: reason, comment: 'obvious spam' } }
+ let_it_be(:admin) { create(:admin) }
+
+ let(:service) { described_class.new(abuse_report, admin, params) }
+
+ describe '#execute', :enable_admin_mode do
+ subject { service.execute }
+
+ shared_examples 'returns an error response' do |error|
+ it 'returns an error response' do
+ expect(subject.status).to eq :error
+ expect(subject.message).to eq error
+ end
+ end
+
+ shared_examples 'closes the report' do
+ it 'closes the report' do
+ expect { subject }.to change { abuse_report.closed? }.from(false).to(true)
+ end
+ end
+
+ shared_examples 'does not close the report' do
+ it 'does not close the report' do
+ subject
+ expect(abuse_report.closed?).to be(false)
+ end
+ end
+
+ shared_examples 'does not record an event' do
+ it 'does not record an event' do
+ expect { subject }.not_to change { abuse_report.events.count }
+ end
+ end
+
+ shared_examples 'records an event' do |action:|
+ it 'records the event', :aggregate_failures do
+ expect { subject }.to change { abuse_report.events.count }.by(1)
+
+ expect(abuse_report.events.last).to have_attributes(
+ action: action,
+ user: admin,
+ reason: reason,
+ comment: params[:comment]
+ )
+ end
+ end
+
+ context 'when invalid parameters are given' do
+ describe 'invalid user' do
+ describe 'when no user is given' do
+ let_it_be(:admin) { nil }
+
+ it_behaves_like 'returns an error response', 'Admin is required'
+ end
+
+ describe 'when given user is no admin' do
+ let_it_be(:admin) { create(:user) }
+
+ it_behaves_like 'returns an error response', 'Admin is required'
+ end
+ end
+
+ describe 'invalid action' do
+ describe 'when no action is given' do
+ let(:action) { '' }
+ let(:close) { 'false' }
+
+ it_behaves_like 'returns an error response', 'Action is required'
+ end
+
+ describe 'when unknown action is given' do
+ let(:action) { 'unknown' }
+ let(:close) { 'false' }
+
+ it_behaves_like 'returns an error response', 'Action is required'
+ end
+ end
+
+ describe 'invalid reason' do
+ let(:reason) { '' }
+
+ it 'sets the reason to `other`' do
+ subject
+
+ expect(abuse_report.events.last).to have_attributes(reason: 'other')
+ end
+ end
+ end
+
+ describe 'when banning the user' do
+ it 'calls the Users::BanService' do
+ expect_next_instance_of(Users::BanService, admin) do |service|
+ expect(service).to receive(:execute).with(abuse_report.user).and_return(status: :success)
+ end
+
+ subject
+ end
+
+ context 'when closing the report' do
+ it_behaves_like 'closes the report'
+ it_behaves_like 'records an event', action: 'ban_user_and_close_report'
+ end
+
+ context 'when not closing the report' do
+ let(:close) { 'false' }
+
+ it_behaves_like 'does not close the report'
+ it_behaves_like 'records an event', action: 'ban_user'
+ end
+
+ context 'when banning the user fails' do
+ before do
+ allow_next_instance_of(Users::BanService, admin) do |service|
+ allow(service).to receive(:execute).with(abuse_report.user)
+ .and_return(status: :error, message: 'Banning the user failed')
+ end
+ end
+
+ it_behaves_like 'returns an error response', 'Banning the user failed'
+ it_behaves_like 'does not close the report'
+ it_behaves_like 'does not record an event'
+ end
+ end
+
+ describe 'when blocking the user' do
+ let(:action) { 'block_user' }
+
+ it 'calls the Users::BlockService' do
+ expect_next_instance_of(Users::BlockService, admin) do |service|
+ expect(service).to receive(:execute).with(abuse_report.user).and_return(status: :success)
+ end
+
+ subject
+ end
+
+ context 'when closing the report' do
+ it_behaves_like 'closes the report'
+ it_behaves_like 'records an event', action: 'block_user_and_close_report'
+ end
+
+ context 'when not closing the report' do
+ let(:close) { 'false' }
+
+ it_behaves_like 'does not close the report'
+ it_behaves_like 'records an event', action: 'block_user'
+ end
+
+ context 'when blocking the user fails' do
+ before do
+ allow_next_instance_of(Users::BlockService, admin) do |service|
+ allow(service).to receive(:execute).with(abuse_report.user)
+ .and_return(status: :error, message: 'Blocking the user failed')
+ end
+ end
+
+ it_behaves_like 'returns an error response', 'Blocking the user failed'
+ it_behaves_like 'does not close the report'
+ it_behaves_like 'does not record an event'
+ end
+ end
+
+ describe 'when deleting the user' do
+ let(:action) { 'delete_user' }
+
+ it 'calls the delete_async method' do
+ expect(abuse_report.user).to receive(:delete_async).with(deleted_by: admin)
+ subject
+ end
+
+ context 'when closing the report' do
+ it_behaves_like 'closes the report'
+ it_behaves_like 'records an event', action: 'delete_user_and_close_report'
+ end
+
+ context 'when not closing the report' do
+ let(:close) { 'false' }
+
+ it_behaves_like 'does not close the report'
+ it_behaves_like 'records an event', action: 'delete_user'
+ end
+ end
+
+ describe 'when only closing the report' do
+ let(:action) { '' }
+
+ it_behaves_like 'closes the report'
+ it_behaves_like 'records an event', action: 'close_report'
+ end
+ end
+end
diff --git a/spec/services/task_list_toggle_service_spec.rb b/spec/services/task_list_toggle_service_spec.rb
index b0444a5ba72..5d55c1ca8de 100644
--- a/spec/services/task_list_toggle_service_spec.rb
+++ b/spec/services/task_list_toggle_service_spec.rb
@@ -18,6 +18,8 @@ RSpec.describe TaskListToggleService, feature_category: :team_planning do
with an embedded paragraph
+ [ ] No-break space (U+00A0)
+
+ 2) [ ] Another item
EOT
end
@@ -53,6 +55,11 @@ RSpec.describe TaskListToggleService, feature_category: :team_planning do
<input type="checkbox" class="task-list-item-checkbox" disabled=""> No-break space (U+00A0)
</li>
</ul>
+ <ol start="2" data-sourcepos="15:1-15:19" class="task-list" dir="auto">
+ <li data-sourcepos="15:1-15:19" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> Another item
+ </li>
+ </ol>
EOT
end
@@ -92,10 +99,20 @@ RSpec.describe TaskListToggleService, feature_category: :team_planning do
line_source: '+ [ ] No-break space (U+00A0)', line_number: 13)
expect(toggler.execute).to be_truthy
- expect(toggler.updated_markdown.lines[12]).to eq "+ [x] No-break space (U+00A0)"
+ expect(toggler.updated_markdown.lines[12]).to eq "+ [x] No-break space (U+00A0)\n"
expect(toggler.updated_markdown_html).to include('disabled checked> No-break space (U+00A0)')
end
+ it 'checks Another item' do
+ toggler = described_class.new(markdown, markdown_html,
+ toggle_as_checked: true,
+ line_source: '2) [ ] Another item', line_number: 15)
+
+ expect(toggler.execute).to be_truthy
+ expect(toggler.updated_markdown.lines[14]).to eq "2) [x] Another item"
+ expect(toggler.updated_markdown_html).to include('disabled checked> Another item')
+ end
+
it 'returns false if line_source does not match the text' do
toggler = described_class.new(markdown, markdown_html,
toggle_as_checked: false,
diff --git a/spec/views/admin/groups/_form.html.haml_spec.rb b/spec/views/admin/groups/_form.html.haml_spec.rb
new file mode 100644
index 00000000000..87929571a84
--- /dev/null
+++ b/spec/views/admin/groups/_form.html.haml_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'admin/groups/_form', feature_category: :subgroups do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:admin) { build(:user, :admin) }
+ let_it_be(:group) { build(:group, namespace_settings: build(:namespace_settings)) }
+
+ before do
+ allow(view).to receive(:current_user).and_return(admin)
+ allow(view).to receive(:visibility_level).and_return(group.visibility_level)
+ assign(:group, group)
+ end
+
+ describe 'group runner registration setting' do
+ where(:runner_registration_enabled, :valid_runner_registrars, :checked, :disabled) do
+ true | ['group'] | true | false
+ false | ['group'] | false | false
+ false | ['project'] | false | true
+ end
+
+ with_them do
+ before do
+ allow(group).to receive(:runner_registration_enabled?).and_return(runner_registration_enabled)
+ stub_application_setting(valid_runner_registrars: valid_runner_registrars)
+ end
+
+ it 'renders the checkbox correctly' do
+ render
+
+ expect(rendered).to have_field(
+ 'New group runners can be registered',
+ type: 'checkbox',
+ checked: checked,
+ disabled: disabled
+ )
+ end
+ end
+ end
+end
diff --git a/spec/views/help/index.html.haml_spec.rb b/spec/views/help/index.html.haml_spec.rb
index 73f1afd17dc..f530e6a8f8d 100644
--- a/spec/views/help/index.html.haml_spec.rb
+++ b/spec/views/help/index.html.haml_spec.rb
@@ -21,10 +21,6 @@ RSpec.describe 'help/index' do
end
context 'when logged in' do
- def version_link_regexp(path)
- %r{#{Regexp.escape(Gitlab::Saas.com_url)}/gitlab-org/(gitlab|gitlab-foss)/#{Regexp.escape(path)}}
- end
-
before do
stub_user
end
@@ -35,7 +31,7 @@ RSpec.describe 'help/index' do
render
expect(rendered).to match '8.0.2'
- expect(rendered).to have_link('8.0.2', href: version_link_regexp('-/tags/v8.0.2'))
+ expect(rendered).to have_link('8.0.2', href: Gitlab::Source.release_url)
end
it 'shows a link to the commit for pre-releases' do
@@ -44,7 +40,7 @@ RSpec.describe 'help/index' do
render
expect(rendered).to match '8.0.2'
- expect(rendered).to have_link('abcdefg', href: version_link_regexp('-/commits/abcdefg'))
+ expect(rendered).to have_link('abcdefg', href: Gitlab::Source.release_url)
end
end
end