diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-10 16:46:51 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-10 16:46:51 +0000 |
commit | 04ac4180cb5ba0df460034c7e64862056fd498b3 (patch) | |
tree | ca5267d12fa2aab80c1c35593b96c8cfceaa747b /spec | |
parent | 4e9ceea7f8ff3e097ad45f6f54c1b7165248e848 (diff) | |
download | gitlab-ce-04ac4180cb5ba0df460034c7e64862056fd498b3.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
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 |