Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-21 15:09:17 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-21 15:09:17 +0300
commit0c4570435d417b69efd433057f95f01810618837 (patch)
tree4e402832206b83da2d73671977c1e5f7cae9074a /spec
parent49abdb108a4d3c3f2ef9b27c7c4dcde43da1016a (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/oauth/authorizations_controller_spec.rb11
-rw-r--r--spec/features/groups/milestones/gfm_autocomplete_spec.rb6
-rw-r--r--spec/features/groups/participants_autocomplete_spec.rb50
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb9
-rw-r--r--spec/features/issues/user_comments_on_issue_spec.rb7
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb4
-rw-r--r--spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb22
-rw-r--r--spec/features/merge_request/user_resolves_wip_mr_spec.rb22
-rw-r--r--spec/features/merge_request/user_sees_deployment_widget_spec.rb6
-rw-r--r--spec/features/merge_request/user_sees_discussions_navigation_spec.rb44
-rw-r--r--spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb24
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb51
-rw-r--r--spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb11
-rw-r--r--spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb18
-rw-r--r--spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb21
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb23
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb24
-rw-r--r--spec/features/participants_autocomplete_spec.rb8
-rw-r--r--spec/features/projects/milestones/gfm_autocomplete_spec.rb6
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js11
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap6
-rw-r--r--spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js73
-rw-r--r--spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js12
-rw-r--r--spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js13
-rw-r--r--spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js10
-rw-r--r--spec/helpers/groups_helper_spec.rb14
-rw-r--r--spec/helpers/sidebars_helper_spec.rb27
-rw-r--r--spec/lib/api/entities/plan_limit_spec.rb1
-rw-r--r--spec/models/group_spec.rb32
-rw-r--r--spec/models/integration_spec.rb10
-rw-r--r--spec/models/plan_limits_spec.rb144
-rw-r--r--spec/models/project_spec.rb30
-rw-r--r--spec/models/user_spec.rb23
-rw-r--r--spec/requests/api/admin/plan_limits_spec.rb10
-rw-r--r--spec/serializers/diff_viewer_entity_spec.rb48
-rw-r--r--spec/services/admin/plan_limits/update_service_spec.rb24
-rw-r--r--spec/services/git/base_hooks_service_spec.rb17
-rw-r--r--spec/services/groups/participants_service_spec.rb61
-rw-r--r--spec/services/spam/spam_verdict_service_spec.rb32
-rw-r--r--spec/services/users/allow_possible_spam_service_spec.rb24
-rw-r--r--spec/services/users/disallow_possible_spam_service_spec.rb34
-rw-r--r--spec/support/helpers/features/autocomplete_helpers.rb13
44 files changed, 785 insertions, 255 deletions
diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb
index 3476c7b8465..4772c3f3487 100644
--- a/spec/controllers/oauth/authorizations_controller_spec.rb
+++ b/spec/controllers/oauth/authorizations_controller_spec.rb
@@ -298,4 +298,15 @@ RSpec.describe Oauth::AuthorizationsController do
it 'includes Two-factor enforcement concern' do
expect(described_class.included_modules.include?(EnforcesTwoFactorAuthentication)).to eq(true)
end
+
+ describe 'Gon variables' do
+ it 'adds Gon variables' do
+ expect(controller).to receive(:add_gon_variables)
+ get :new, params: params
+ end
+
+ it 'includes GonHelper module' do
+ expect(controller).to be_a(Gitlab::GonHelper)
+ end
+ end
end
diff --git a/spec/features/groups/milestones/gfm_autocomplete_spec.rb b/spec/features/groups/milestones/gfm_autocomplete_spec.rb
index 8df097dde88..9245323d1f7 100644
--- a/spec/features/groups/milestones/gfm_autocomplete_spec.rb
+++ b/spec/features/groups/milestones/gfm_autocomplete_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'GFM autocomplete', :js, feature_category: :team_planning do
+ include Features::AutocompleteHelpers
+
let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
let_it_be(:group) { create(:group, name: 'Ancestor') }
let_it_be(:project) { create(:project, :repository, group: group) }
@@ -69,10 +71,6 @@ RSpec.describe 'GFM autocomplete', :js, feature_category: :team_planning do
private
- def find_autocomplete_menu
- find('.atwho-view ul', visible: true)
- end
-
def expect_autocomplete_entry(entry)
page.within('.atwho-container') do
expect(page).to have_content(entry)
diff --git a/spec/features/groups/participants_autocomplete_spec.rb b/spec/features/groups/participants_autocomplete_spec.rb
new file mode 100644
index 00000000000..a94f95c3ced
--- /dev/null
+++ b/spec/features/groups/participants_autocomplete_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Group member autocomplete', :js, feature_category: :groups_and_projects do
+ include Features::AutocompleteHelpers
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+
+ before_all do
+ group.add_developer user
+ end
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when editing description of a group milestone' do
+ let_it_be(:noteable) { create(:milestone, group: group) }
+
+ it 'suggests group members' do
+ visit edit_group_milestone_path(group, noteable)
+
+ fill_in 'Description', with: '@'
+
+ expect(find_autocomplete_menu).to have_text(user.username)
+ end
+
+ context 'for a member of a private group invited to the group' do
+ let_it_be(:private_group) { create(:group, :private) }
+ let_it_be(:private_group_member) { create(:user, username: 'private-a') }
+
+ before_all do
+ private_group.add_developer private_group_member
+
+ create(:group_group_link, shared_group: group, shared_with_group: private_group)
+ end
+
+ it 'suggests member of private group as well' do
+ visit edit_group_milestone_path(group, noteable)
+
+ fill_in 'Description', with: '@'
+
+ expect(find_autocomplete_menu).to have_text(private_group_member.username)
+ expect(find_autocomplete_menu).to have_text(user.username)
+ end
+ end
+ end
+end
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 665c7307231..a1f2275df6e 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'GFM autocomplete', :js, feature_category: :team_planning do
include CookieHelper
+ include Features::AutocompleteHelpers
let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
let_it_be(:user2) { create(:user, name: 'Marge Simpson', username: 'msimpson') }
@@ -453,12 +454,4 @@ RSpec.describe 'GFM autocomplete', :js, feature_category: :team_planning do
wait_for_requests
end
-
- def find_autocomplete_menu
- find('.atwho-view ul', visible: true)
- end
-
- def find_highlighted_autocomplete_item
- find('.atwho-view li.cur', visible: true)
- end
end
diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb
index 3ace560fb40..d954a1d15ff 100644
--- a/spec/features/issues/user_comments_on_issue_spec.rb
+++ b/spec/features/issues/user_comments_on_issue_spec.rb
@@ -3,6 +3,7 @@
require "spec_helper"
RSpec.describe "User comments on issue", :js, feature_category: :team_planning do
+ include Features::AutocompleteHelpers
include Features::NotesHelpers
let_it_be(:project) { create(:project, :public) }
@@ -92,10 +93,4 @@ RSpec.describe "User comments on issue", :js, feature_category: :team_planning d
end
end
end
-
- private
-
- def find_highlighted_autocomplete_item
- find('.atwho-view li.cur', visible: true)
- end
end
diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
index 5da9f4a1f19..4bdef20304a 100644
--- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
+++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
@@ -10,9 +10,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js, feat
let!(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request, note: "| Markdown | Table |\n|-------|---------|\n| first | second |") }
let(:path) { "files/ruby/popen.rb" }
let(:position) do
- build(:text_diff_position,
- file: path, old_line: nil, new_line: 9,
- diff_refs: merge_request.diff_refs)
+ build(:text_diff_position, file: path, old_line: nil, new_line: 9, diff_refs: merge_request.diff_refs)
end
before do
diff --git a/spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb b/spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb
index 5c41ac79552..cb57f1fd549 100644
--- a/spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb
+++ b/spec/features/merge_request/user_resolves_outdated_diff_discussions_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Merge request > User resolves outdated diff discussions',
- :js, feature_category: :code_review_workflow do
+ :js, feature_category: :code_review_workflow do
let(:project) { create(:project, :repository, :public) }
let(:merge_request) do
@@ -30,17 +30,21 @@ RSpec.describe 'Merge request > User resolves outdated diff discussions',
end
let!(:outdated_discussion) do
- create(:diff_note_on_merge_request,
- project: project,
- noteable: merge_request,
- position: outdated_position).to_discussion
+ create(
+ :diff_note_on_merge_request,
+ project: project,
+ noteable: merge_request,
+ position: outdated_position
+ ).to_discussion
end
let!(:current_discussion) do
- create(:diff_note_on_merge_request,
- noteable: merge_request,
- project: project,
- position: current_position).to_discussion
+ create(
+ :diff_note_on_merge_request,
+ noteable: merge_request,
+ project: project,
+ position: current_position
+ ).to_discussion
end
before do
diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
index 01cc6bd5167..15a7755429b 100644
--- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb
+++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
@@ -6,17 +6,23 @@ RSpec.describe 'Merge request > User resolves Draft', :js, feature_category: :co
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
let(:merge_request) do
- create(:merge_request_with_diffs, source_project: project,
- author: user,
- title: 'Draft: Bug NS-04',
- merge_params: { force_remove_source_branch: '1' })
+ create(
+ :merge_request_with_diffs,
+ source_project: project,
+ author: user,
+ title: 'Draft: Bug NS-04',
+ merge_params: { force_remove_source_branch: '1' }
+ )
end
let(:pipeline) do
- create(:ci_pipeline, project: project,
- sha: merge_request.diff_head_sha,
- ref: merge_request.source_branch,
- head_pipeline_of: merge_request)
+ create(
+ :ci_pipeline,
+ project: project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch,
+ head_pipeline_of: merge_request
+ )
end
before do
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index 6dcebad300c..44660b247a1 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -115,8 +115,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js, feature_categ
context 'with stop action' do
let(:manual) do
- create(:ci_build, :manual, pipeline: pipeline,
- name: 'close_app', environment: environment.name)
+ create(:ci_build, :manual, pipeline: pipeline, name: 'close_app', environment: environment.name)
end
before do
@@ -146,8 +145,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js, feature_categ
context 'with stop action with the review_apps_redeploy_mr_widget feature flag turned on' do
let(:manual) do
- create(:ci_build, :manual, pipeline: pipeline,
- name: 'close_app', environment: environment.name)
+ create(:ci_build, :manual, pipeline: pipeline, name: 'close_app', environment: environment.name)
end
before do
diff --git a/spec/features/merge_request/user_sees_discussions_navigation_spec.rb b/spec/features/merge_request/user_sees_discussions_navigation_spec.rb
index 338e4329190..4cce40972e9 100644
--- a/spec/features/merge_request/user_sees_discussions_navigation_spec.rb
+++ b/spec/features/merge_request/user_sees_discussions_navigation_spec.rb
@@ -13,27 +13,30 @@ RSpec.describe 'Merge request > User sees discussions navigation', :js, feature_
describe 'Code discussions' do
let!(:position) do
- build(:text_diff_position, :added,
- file: "files/images/wm.svg",
- new_line: 1,
- diff_refs: merge_request.diff_refs
+ build(
+ :text_diff_position, :added,
+ file: "files/images/wm.svg",
+ new_line: 1,
+ diff_refs: merge_request.diff_refs
)
end
let!(:first_discussion) do
- create(:diff_note_on_merge_request,
- noteable: merge_request,
- project: project,
- position: position
- ).to_discussion
+ create(
+ :diff_note_on_merge_request,
+ noteable: merge_request,
+ project: project,
+ position: position
+ ).to_discussion
end
let!(:second_discussion) do
- create(:diff_note_on_merge_request,
- noteable: merge_request,
- project: project,
- position: position
- ).to_discussion
+ create(
+ :diff_note_on_merge_request,
+ noteable: merge_request,
+ project: project,
+ position: position
+ ).to_discussion
end
let(:first_discussion_selector) { ".discussion[data-discussion-id='#{first_discussion.id}']" }
@@ -74,11 +77,12 @@ RSpec.describe 'Merge request > User sees discussions navigation', :js, feature_
context 'with resolved threads' do
let!(:resolved_discussion) do
- create(:diff_note_on_merge_request,
- noteable: merge_request,
- project: project,
- position: position
- ).to_discussion
+ create(
+ :diff_note_on_merge_request,
+ noteable: merge_request,
+ project: project,
+ position: position
+ ).to_discussion
end
let(:resolved_discussion_selector) { ".discussion[data-discussion-id='#{resolved_discussion.id}']" }
@@ -92,7 +96,7 @@ RSpec.describe 'Merge request > User sees discussions navigation', :js, feature_
end
it 'excludes resolved threads during navigation',
- quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/383687' do
+ quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/383687' do
goto_next_thread
goto_next_thread
goto_next_thread
diff --git a/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb b/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb
index 476be5ab599..9955c13b769 100644
--- a/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Merge request > User sees merge button depending on unresolved threads', :js,
-feature_category: :code_review_workflow do
+ feature_category: :code_review_workflow do
let(:project) { create(:project, :repository) }
let(:user) { project.creator }
let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) }
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index ca12e0e2b65..fba25b41b83 100644
--- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
@@ -36,11 +36,13 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when a user created a merge request in the parent project' do
let!(:merge_request) do
- create(:merge_request,
- source_project: project,
- target_project: project,
- source_branch: 'feature',
- target_branch: 'master')
+ create(
+ :merge_request,
+ source_project: project,
+ target_project: project,
+ source_branch: 'feature',
+ target_branch: 'master'
+ )
end
let!(:push_pipeline) do
@@ -263,11 +265,13 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when a user created a merge request from a forked project to the parent project', :sidekiq_might_not_need_inline do
let(:merge_request) do
- create(:merge_request,
- source_project: forked_project,
- target_project: project,
- source_branch: 'feature',
- target_branch: 'master')
+ create(
+ :merge_request,
+ source_project: forked_project,
+ target_project: project,
+ source_branch: 'feature',
+ target_branch: 'master'
+ )
end
let!(:push_pipeline) do
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index cb56e79fcc0..33694c056a0 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -118,12 +118,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
context 'view merge request with failed GitLab CI pipelines' do
before do
commit_status = create(:commit_status, project: project, status: 'failed')
- pipeline = create(:ci_pipeline, project: project,
- sha: merge_request.diff_head_sha,
- ref: merge_request.source_branch,
- status: 'failed',
- statuses: [commit_status],
- head_pipeline_of: merge_request)
+ pipeline = create(
+ :ci_pipeline,
+ project: project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch,
+ status: 'failed',
+ statuses: [commit_status],
+ head_pipeline_of: merge_request
+ )
create(:ci_build, :pending, pipeline: pipeline)
visit project_merge_request_path(project, merge_request)
@@ -278,12 +281,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
context 'view merge request with MWBS button' do
before do
commit_status = create(:commit_status, project: project, status: 'pending')
- pipeline = create(:ci_pipeline, project: project,
- sha: merge_request.diff_head_sha,
- ref: merge_request.source_branch,
- status: 'pending',
- statuses: [commit_status],
- head_pipeline_of: merge_request)
+ pipeline = create(
+ :ci_pipeline,
+ project: project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch,
+ status: 'pending',
+ statuses: [commit_status],
+ head_pipeline_of: merge_request
+ )
create(:ci_build, :pending, pipeline: pipeline)
visit project_merge_request_path(project, merge_request)
@@ -298,9 +304,12 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
context 'view merge request where there is no pipeline yet' do
before do
- pipeline = create(:ci_pipeline, project: project,
- sha: merge_request.diff_head_sha,
- ref: merge_request.source_branch)
+ pipeline = create(
+ :ci_pipeline,
+ project: project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch
+ )
create(:ci_build, pipeline: pipeline)
visit project_merge_request_path(project, merge_request)
@@ -510,11 +519,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
context 'when merge request has test reports' do
let!(:head_pipeline) do
- create(:ci_pipeline,
- :success,
- project: project,
- ref: merge_request.source_branch,
- sha: merge_request.diff_head_sha)
+ create(
+ :ci_pipeline,
+ :success,
+ project: project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha
+ )
end
let!(:build) { create(:ci_build, :success, pipeline: head_pipeline, project: project) }
diff --git a/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb b/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb
index fac0a84f155..7b8ac50f1ae 100644
--- a/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb
+++ b/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb
@@ -3,16 +3,19 @@
require 'spec_helper'
RSpec.describe 'Merge request > User sees MR from deleted forked project',
- :js, feature_category: :code_review_workflow do
+ :js, feature_category: :code_review_workflow do
include ProjectForksHelper
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
let(:forked_project) { fork_project(project, nil, repository: true) }
let!(:merge_request) do
- create(:merge_request_with_diffs, source_project: forked_project,
- target_project: project,
- description: 'Test merge request')
+ create(
+ :merge_request_with_diffs,
+ source_project: forked_project,
+ target_project: project,
+ description: 'Test merge request'
+ )
end
before do
diff --git a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
index 9b46cf37648..29a76768774 100644
--- a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
+++ b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
@@ -6,7 +6,7 @@ require 'spec_helper'
# message to be shown by JavaScript when the source branch was deleted.
# Please do not remove ":js".
RSpec.describe 'Merge request > User sees MR with deleted source branch',
- :js, feature_category: :code_review_workflow do
+ :js, feature_category: :code_review_workflow do
let(:project) { create(:project, :public, :repository) }
let(:merge_request) { create(:merge_request, source_project: project) }
let(:user) { project.creator }
diff --git a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
index ac195dd9873..92bedc47718 100644
--- a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
+++ b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
@@ -9,15 +9,21 @@ RSpec.describe 'Merge request > User sees notes from forked project', :js, featu
let(:user) { project.creator }
let(:forked_project) { fork_project(project, nil, repository: true) }
let!(:merge_request) do
- create(:merge_request_with_diffs, source_project: forked_project,
- target_project: project,
- description: 'Test merge request')
+ create(
+ :merge_request_with_diffs,
+ source_project: forked_project,
+ target_project: project,
+ description: 'Test merge request'
+ )
end
before do
- create(:note_on_commit, note: 'A commit comment',
- project: forked_project,
- commit_id: merge_request.commit_shas.first)
+ create(
+ :note_on_commit,
+ note: 'A commit comment',
+ project: forked_project,
+ commit_id: merge_request.commit_shas.first
+ )
sign_in(user)
end
diff --git a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb
index 0816b14f9a5..5801e8a1a11 100644
--- a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb
@@ -3,23 +3,28 @@
require 'spec_helper'
RSpec.describe 'Merge request > User sees pipelines from forked project', :js,
-feature_category: :continuous_integration do
+ feature_category: :continuous_integration do
include ProjectForksHelper
let(:target_project) { create(:project, :public, :repository) }
let(:user) { target_project.creator }
let(:forked_project) { fork_project(target_project, nil, repository: true) }
let!(:merge_request) do
- create(:merge_request_with_diffs, source_project: forked_project,
- target_project: target_project,
- description: 'Test merge request')
+ create(
+ :merge_request_with_diffs,
+ source_project: forked_project,
+ target_project: target_project,
+ description: 'Test merge request'
+ )
end
let(:pipeline) do
- create(:ci_pipeline,
- project: forked_project,
- sha: merge_request.diff_head_sha,
- ref: merge_request.source_branch)
+ create(
+ :ci_pipeline,
+ project: forked_project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch
+ )
end
before do
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index faa46ff4df1..88c718fac13 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -15,11 +15,13 @@ RSpec.describe 'Merge request > User sees pipelines', :js, feature_category: :co
context 'with pipelines' do
let!(:pipeline) do
- create(:ci_pipeline,
- :success,
- project: merge_request.source_project,
- ref: merge_request.source_branch,
- sha: merge_request.diff_head_sha)
+ create(
+ :ci_pipeline,
+ :success,
+ project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha
+ )
end
let!(:manual_job) { create(:ci_build, :manual, name: 'job1', stage: 'deploy', pipeline: pipeline) }
@@ -116,9 +118,14 @@ RSpec.describe 'Merge request > User sees pipelines', :js, feature_category: :co
let_it_be(:reporter_in_parent_and_developer_in_fork) { create(:user) }
let(:merge_request) do
- create(:merge_request, :with_detached_merge_request_pipeline,
- source_project: forked_project, source_branch: 'feature',
- target_project: parent_project, target_branch: 'master')
+ create(
+ :merge_request,
+ :with_detached_merge_request_pipeline,
+ source_project: forked_project,
+ source_branch: 'feature',
+ target_project: parent_project,
+ target_branch: 'master'
+ )
end
let(:config) do
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index 91f8fd13681..715cc2f73be 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -57,9 +57,9 @@ RSpec.describe 'Merge request > User sees versions', :js, feature_category: :cod
end
it_behaves_like 'allows commenting',
- file_name: '.gitmodules',
- line_text: '[submodule "six"]',
- comment: 'Typo, please fix.'
+ file_name: '.gitmodules',
+ line_text: '[submodule "six"]',
+ comment: 'Typo, please fix.'
end
describe 'switch between versions' do
@@ -105,9 +105,9 @@ RSpec.describe 'Merge request > User sees versions', :js, feature_category: :cod
end
it_behaves_like 'allows commenting',
- file_name: '.gitmodules',
- line_text: 'path = six',
- comment: 'Typo, please fix.'
+ file_name: '.gitmodules',
+ line_text: 'path = six',
+ comment: 'Typo, please fix.'
end
describe 'compare with older version' do
@@ -172,9 +172,9 @@ RSpec.describe 'Merge request > User sees versions', :js, feature_category: :cod
end
it_behaves_like 'allows commenting',
- file_name: '.gitmodules',
- line_text: '[submodule "gitlab-shell"]',
- comment: 'Typo, please fix.'
+ file_name: '.gitmodules',
+ line_text: '[submodule "gitlab-shell"]',
+ comment: 'Typo, please fix.'
end
describe 'compare with same version' do
@@ -239,8 +239,8 @@ RSpec.describe 'Merge request > User sees versions', :js, feature_category: :cod
end
it_behaves_like 'allows commenting',
- file_name: 'files/ruby/popen.rb',
- line_text: 'RuntimeError',
- comment: 'Typo, please fix.'
+ file_name: 'files/ruby/popen.rb',
+ line_text: 'RuntimeError',
+ comment: 'Typo, please fix.'
end
end
diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb
index 084bf609a0d..d8501116134 100644
--- a/spec/features/participants_autocomplete_spec.rb
+++ b/spec/features/participants_autocomplete_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Member autocomplete', :js, feature_category: :groups_and_projects do
+ include Features::AutocompleteHelpers
+
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { create(:user) }
let_it_be(:author) { create(:user) }
@@ -85,10 +87,4 @@ RSpec.describe 'Member autocomplete', :js, feature_category: :groups_and_project
include_examples "open suggestions when typing @", 'commit'
end
-
- private
-
- def find_autocomplete_menu
- find('.atwho-view ul', visible: true)
- end
end
diff --git a/spec/features/projects/milestones/gfm_autocomplete_spec.rb b/spec/features/projects/milestones/gfm_autocomplete_spec.rb
index d4ce10b5cb5..0705cdd0d9e 100644
--- a/spec/features/projects/milestones/gfm_autocomplete_spec.rb
+++ b/spec/features/projects/milestones/gfm_autocomplete_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'GFM autocomplete', :js, feature_category: :team_planning do
+ include Features::AutocompleteHelpers
+
let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
let_it_be(:group) { create(:group, name: 'Ancestor') }
let_it_be(:project) { create(:project, :repository, group: group) }
@@ -68,10 +70,6 @@ RSpec.describe 'GFM autocomplete', :js, feature_category: :team_planning do
private
- def find_autocomplete_menu
- find('.atwho-view ul', visible: true)
- end
-
def expect_autocomplete_entry(entry)
page.within('.atwho-container') do
expect(page).to have_content(entry)
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index c9238c4b636..6ef34504da7 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -6,6 +6,9 @@ import {
GlFormInput,
GlAlert,
GlSprintf,
+ GlDisclosureDropdown,
+ GlDisclosureDropdownItem,
+ GlDisclosureDropdownGroup,
} from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
@@ -46,7 +49,13 @@ describe('ErrorDetails', () => {
function mountComponent({ integratedErrorTrackingEnabled = false } = {}) {
wrapper = shallowMount(ErrorDetails, {
- stubs: { GlButton, GlSprintf },
+ stubs: {
+ GlButton,
+ GlSprintf,
+ GlDisclosureDropdown,
+ GlDisclosureDropdownItem,
+ GlDisclosureDropdownGroup,
+ },
store,
mocks,
propsData: {
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
index c8d972b19a3..9f2b91cb7fd 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
@@ -90,9 +90,11 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] =
</div>
<div
- class="js-vue-md-preview md md-preview-holder gl-px-5"
+ class="js-vue-md-preview md-preview-holder gl-px-5 md"
style="display: none;"
- />
+ >
+ <div />
+ </div>
<!---->
diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js b/spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js
index 21d085dc0fb..9714093e001 100644
--- a/spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js
+++ b/spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js
@@ -6,18 +6,21 @@ import CommandPaletteItems from '~/super_sidebar/components/global_search/comman
import {
COMMAND_HANDLE,
USERS_GROUP_TITLE,
+ PATH_GROUP_TITLE,
USER_HANDLE,
+ PATH_HANDLE,
SEARCH_SCOPE,
} from '~/super_sidebar/components/global_search/command_palette/constants';
import {
commandMapper,
linksReducer,
+ fileMapper,
} from '~/super_sidebar/components/global_search/command_palette/utils';
import { getFormattedItem } from '~/super_sidebar/components/global_search/utils';
import axios from '~/lib/utils/axios_utils';
import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import waitForPromises from 'helpers/wait_for_promises';
-import { COMMANDS, LINKS, USERS } from './mock_data';
+import { COMMANDS, LINKS, USERS, FILES } from './mock_data';
const links = LINKS.reduce(linksReducer, []);
@@ -25,6 +28,8 @@ describe('CommandPaletteItems', () => {
let wrapper;
const autocompletePath = '/autocomplete';
const searchContext = { project: { id: 1 }, group: { id: 2 } };
+ const projectFilesPath = 'project/files/path';
+ const projectBlobPath = '/blob/main';
const createComponent = (props) => {
wrapper = shallowMount(CommandPaletteItems, {
@@ -42,6 +47,8 @@ describe('CommandPaletteItems', () => {
commandPaletteLinks: LINKS,
autocompletePath,
searchContext,
+ projectFilesPath,
+ projectBlobPath,
},
});
};
@@ -50,7 +57,7 @@ describe('CommandPaletteItems', () => {
const findGroups = () => wrapper.findAllComponents(GlDisclosureDropdownGroup);
const findLoader = () => wrapper.findComponent(GlLoadingIcon);
- describe('COMMANDS & LINKS', () => {
+ describe('Commands and links', () => {
it('renders all commands initially', () => {
createComponent();
const commandGroup = COMMANDS.map(commandMapper)[0];
@@ -90,7 +97,7 @@ describe('CommandPaletteItems', () => {
});
});
- describe('USERS, ISSUES, PROJECTS', () => {
+ describe('Users, issues, and projects', () => {
let mockAxios;
beforeEach(() => {
@@ -140,4 +147,64 @@ describe('CommandPaletteItems', () => {
expect(wrapper.text()).toBe('No results found');
});
});
+
+ describe('Project files', () => {
+ let mockAxios;
+
+ beforeEach(() => {
+ mockAxios = new MockAdapter(axios);
+ });
+
+ it('should request project files on first search', () => {
+ jest.spyOn(axios, 'get');
+ const searchQuery = 'gitlab-ci.yml';
+ createComponent({ handle: PATH_HANDLE, searchQuery });
+
+ expect(axios.get).toHaveBeenCalledWith(projectFilesPath);
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('should render returned items', async () => {
+ const items = FILES.map(fileMapper.bind(null, projectBlobPath));
+ mockAxios.onGet().replyOnce(HTTP_STATUS_OK, FILES);
+ jest.spyOn(fuzzaldrinPlus, 'filter').mockReturnValue(items);
+
+ const searchQuery = 'gitlab-ci.yml';
+ createComponent({ handle: PATH_HANDLE, searchQuery });
+
+ await waitForPromises();
+
+ expect(findItems()).toHaveLength(items.length);
+ expect(findGroups().at(0).props('group')).toMatchObject({
+ name: PATH_GROUP_TITLE,
+ items,
+ });
+ });
+
+ it('should display no results message when no files matched the search query', async () => {
+ mockAxios.onGet().replyOnce(HTTP_STATUS_OK, []);
+ const searchQuery = 'gitlab-ci.yml';
+ createComponent({ handle: PATH_HANDLE, searchQuery });
+ await waitForPromises();
+ expect(wrapper.text()).toBe('No results found');
+ });
+
+ it('should not make additional server call on the search query change', async () => {
+ const searchQuery = 'gitlab-ci.yml';
+ const newSearchQuery = 'package.json';
+
+ jest.spyOn(axios, 'get');
+
+ createComponent({ handle: PATH_HANDLE, searchQuery });
+
+ mockAxios.onGet().replyOnce(HTTP_STATUS_OK, FILES);
+ await waitForPromises();
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+
+ await wrapper.setProps({ searchQuery: newSearchQuery });
+
+ expect(axios.get).toHaveBeenCalledTimes(1);
+ });
+ });
});
diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js b/spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js
index ec65a43d549..26a6501c338 100644
--- a/spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js
+++ b/spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js
@@ -131,3 +131,15 @@ export const ISSUE = {
project_name: 'Flight',
url: '/flightjs/Flight/-/issues/37',
};
+
+export const FILES = [
+ '.codeclimate.yml',
+ '.gitignore',
+ '.gitlab-ci.yml',
+ '.gitlab/CODEOWNERS',
+ '.ruby-version',
+ '.tool-versions',
+ 'CHANGELOG',
+ 'CONTRIBUTING.md',
+ 'Dangerfile',
+];
diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js b/spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js
index 0b75787723e..ebc52e2d910 100644
--- a/spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js
+++ b/spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js
@@ -1,6 +1,7 @@
import {
commandMapper,
linksReducer,
+ fileMapper,
} from '~/super_sidebar/components/global_search/command_palette/utils';
import { COMMANDS, LINKS, TRANSFORMED_LINKS } from './mock_data';
@@ -16,3 +17,15 @@ describe('commandMapper', () => {
expect(COMMANDS.map(commandMapper)[0].items).toHaveLength(initialCommandsLength - 1);
});
});
+
+describe('fileMapper', () => {
+ it('should transform files', () => {
+ const file = 'file';
+ const projectBlobPath = 'project/blob/path';
+ expect(fileMapper(projectBlobPath, file)).toEqual({
+ icon: 'doc-code',
+ text: file,
+ href: `${projectBlobPath}/${file}`,
+ });
+ });
+});
diff --git a/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js b/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js
index 9b7b9e288df..cfbe508f3d0 100644
--- a/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js
+++ b/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js
@@ -12,6 +12,7 @@ import CommandPaletteItems from '~/super_sidebar/components/global_search/comman
import {
SEARCH_OR_COMMAND_MODE_PLACEHOLDER,
COMMON_HANDLES,
+ PATH_HANDLE,
} from '~/super_sidebar/components/global_search/command_palette/constants';
import {
SEARCH_INPUT_DESCRIPTION,
@@ -319,7 +320,7 @@ describe('GlobalSearchModal', () => {
});
});
- describe.each(COMMON_HANDLES)(
+ describe.each([...COMMON_HANDLES, PATH_HANDLE])(
'when FF `command_palette` is enabled and search handle is %s',
(handle) => {
beforeEach(() => {
@@ -415,7 +416,7 @@ describe('GlobalSearchModal', () => {
describe('Modal events', () => {
beforeEach(() => {
- createComponent();
+ createComponent({ search: 'searchQuery' });
});
it('should emit `shown` event when modal shown`', () => {
@@ -423,9 +424,10 @@ describe('GlobalSearchModal', () => {
expect(wrapper.emitted('shown')).toHaveLength(1);
});
- it('should emit `hidden` event when modal hidden`', () => {
- findGlobalSearchModal().vm.$emit('hidden');
+ it('should emit `hidden` event when modal hidden and clear the search input', () => {
+ findGlobalSearchModal().vm.$emit('hide');
expect(wrapper.emitted('hidden')).toHaveLength(1);
+ expect(actionSpies.setSearch).toHaveBeenCalledWith(expect.any(Object), '');
});
});
});
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index bdcf0ef57ee..9df044c8a66 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -421,6 +421,20 @@ RSpec.describe GroupsHelper do
end
end
+ describe '#can_admin_service_accounts?', feature_category: :user_management do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ before do
+ allow(helper).to receive(:current_user) { user }
+ group.add_owner(user)
+ end
+
+ it 'returns false when current_user can not admin members' do
+ expect(helper.can_admin_service_accounts?(group)).to be(false)
+ end
+ end
+
describe '#localized_jobs_to_be_done_choices' do
it 'has a translation for all `jobs_to_be_done` values' do
expect(localized_jobs_to_be_done_choices.keys).to match_array(NamespaceSetting.jobs_to_be_dones.keys)
diff --git a/spec/helpers/sidebars_helper_spec.rb b/spec/helpers/sidebars_helper_spec.rb
index 6648663b634..8f0bf156d1d 100644
--- a/spec/helpers/sidebars_helper_spec.rb
+++ b/spec/helpers/sidebars_helper_spec.rb
@@ -528,4 +528,31 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do
expect(helper.super_sidebar_nav_panel(user: user)).to be_a(Sidebars::YourWork::Panel)
end
end
+
+ describe '#command_palette_data' do
+ it 'returns data for project files search' do
+ project = create(:project, :repository) # rubocop:disable RSpec/FactoryBot/AvoidCreate
+
+ expect(helper.command_palette_data(project: project)).to eq(
+ project_files_url: project_files_path(
+ project, project.default_branch, format: :json),
+ project_blob_url: project_blob_path(
+ project, project.default_branch)
+ )
+ end
+
+ it 'returns empty object when project is nil' do
+ expect(helper.command_palette_data(project: nil)).to eq({})
+ end
+
+ it 'returns empty object when project does not have repo' do
+ project = build(:project)
+ expect(helper.command_palette_data(project: project)).to eq({})
+ end
+
+ it 'returns empty object when project has repo but it is empty' do
+ project = build(:project, :empty_repo)
+ expect(helper.command_palette_data(project: project)).to eq({})
+ end
+ end
end
diff --git a/spec/lib/api/entities/plan_limit_spec.rb b/spec/lib/api/entities/plan_limit_spec.rb
index a2d183fd631..b0ad13995d7 100644
--- a/spec/lib/api/entities/plan_limit_spec.rb
+++ b/spec/lib/api/entities/plan_limit_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe API::Entities::PlanLimit do
:enforcement_limit,
:generic_packages_max_file_size,
:helm_max_file_size,
+ :limits_history,
:maven_max_file_size,
:notification_limit,
:npm_max_file_size,
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 527ee96ca86..6a970b9939d 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -1848,22 +1848,29 @@ RSpec.describe Group, feature_category: :groups_and_projects do
end
context 'user-related methods' do
- let(:user_a) { create(:user) }
- let(:user_b) { create(:user) }
- let(:user_c) { create(:user) }
- let(:user_d) { create(:user) }
+ let_it_be(:user_a) { create(:user) }
+ let_it_be(:user_b) { create(:user) }
+ let_it_be(:user_c) { create(:user) }
+ let_it_be(:user_d) { create(:user) }
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let(:deep_nested_group) { create(:group, parent: nested_group) }
- let(:project) { create(:project, namespace: group) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:nested_group) { create(:group, parent: group) }
+ let_it_be(:deep_nested_group) { create(:group, parent: nested_group) }
+ let_it_be(:project) { create(:project, namespace: group) }
- before do
+ let_it_be(:another_group) { create(:group) }
+ let_it_be(:another_user) { create(:user) }
+
+ before_all do
group.add_developer(user_a)
group.add_developer(user_c)
nested_group.add_developer(user_b)
deep_nested_group.add_developer(user_a)
project.add_developer(user_d)
+
+ another_group.add_developer(another_user)
+
+ create(:group_group_link, shared_group: group, shared_with_group: another_group)
end
describe '#direct_and_indirect_users' do
@@ -1876,6 +1883,13 @@ RSpec.describe Group, feature_category: :groups_and_projects do
it 'does not return members of projects belonging to ancestor groups' do
expect(nested_group.direct_and_indirect_users).not_to include(user_d)
end
+
+ context 'when share_with_groups is true' do
+ it 'also returns members of groups invited to this group' do
+ expect(group.direct_and_indirect_users(share_with_groups: true))
+ .to contain_exactly(user_a, user_b, user_c, user_d, another_user)
+ end
+ end
end
describe '#direct_and_indirect_users_with_inactive' do
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index ed49009d6d9..19419db979a 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -246,6 +246,16 @@ RSpec.describe Integration, feature_category: :integrations do
end
end
+ describe '#ci?' do
+ it 'is true when integration is a CI integration' do
+ expect(build(:jenkins_integration).ci?).to eq(true)
+ end
+
+ it 'is false when integration is not a ci integration' do
+ expect(build(:integration).ci?).to eq(false)
+ end
+ end
+
describe '.find_or_initialize_non_project_specific_integration' do
let!(:integration_1) { create(:jira_integration, project_id: nil, group_id: group.id) }
let!(:integration_2) { create(:jira_integration, project: project) }
diff --git a/spec/models/plan_limits_spec.rb b/spec/models/plan_limits_spec.rb
index 265f781d61d..bee1c4f47b0 100644
--- a/spec/models/plan_limits_spec.rb
+++ b/spec/models/plan_limits_spec.rb
@@ -302,62 +302,132 @@ RSpec.describe PlanLimits do
end
end
- describe '#log_limits_changes', :freeze_time do
+ describe '#format_limits_history', :freeze_time do
let(:user) { create(:user) }
let(:plan_limits) { create(:plan_limits) }
let(:current_timestamp) { Time.current.utc.to_i }
- let(:history) { plan_limits.limits_history }
- it 'logs a single attribute change' do
- plan_limits.log_limits_changes(user, enforcement_limit: 5_000)
-
- expect(history).to eq(
- { 'enforcement_limit' => [{ 'user_id' => user.id, 'username' => user.username,
- 'timestamp' => current_timestamp, 'value' => 5_000 }] }
+ it 'formats a single attribute change' do
+ formatted_limits_history = plan_limits.format_limits_history(user, enforcement_limit: 5_000)
+
+ expect(formatted_limits_history).to eq(
+ {
+ "enforcement_limit" => [
+ {
+ "user_id" => user.id,
+ "username" => user.username,
+ "timestamp" => current_timestamp,
+ "value" => 5000
+ }
+ ]
+ }
)
end
- it 'logs multiple attribute changes' do
- plan_limits.log_limits_changes(user, enforcement_limit: 10_000, notification_limit: 20_000)
+ it 'does not format limits_history for non-allowed attributes' do
+ formatted_limits_history = plan_limits.format_limits_history(user,
+ { enforcement_limit: 20_000, pipeline_hierarchy_size: 10_000 })
- expect(history).to eq(
- { 'enforcement_limit' => [{ 'user_id' => user.id, 'username' => user.username,
- 'timestamp' => current_timestamp, 'value' => 10_000 }],
- 'notification_limit' => [{ 'user_id' => user.id, 'username' => user.username,
- 'timestamp' => current_timestamp,
- 'value' => 20_000 }] }
- )
+ expect(formatted_limits_history).to eq({
+ "enforcement_limit" => [
+ {
+ "user_id" => user.id,
+ "username" => user.username,
+ "timestamp" => current_timestamp,
+ "value" => 20_000
+ }
+ ]
+ })
end
- it 'allows logging dashboard_limit_enabled_at from console (without user)' do
- plan_limits.log_limits_changes(nil, dashboard_limit_enabled_at: current_timestamp)
+ it 'does not format attributes for values that do not change' do
+ plan_limits.update!(enforcement_limit: 20_000)
+ formatted_limits_history = plan_limits.format_limits_history(user, enforcement_limit: 20_000)
+
+ expect(formatted_limits_history).to eq({})
+ end
- expect(history).to eq(
- { 'dashboard_limit_enabled_at' => [{ 'user_id' => nil, 'username' => nil, 'timestamp' => current_timestamp,
- 'value' => current_timestamp }] }
+ it 'formats multiple attribute changes' do
+ formatted_limits_history = plan_limits.format_limits_history(user, enforcement_limit: 10_000,
+ notification_limit: 20_000, dashboard_limit_enabled_at: current_timestamp)
+
+ expect(formatted_limits_history).to eq(
+ {
+ "notification_limit" => [
+ {
+ "user_id" => user.id,
+ "username" => user.username,
+ "timestamp" => current_timestamp,
+ "value" => 20000
+ }
+ ],
+ "enforcement_limit" => [
+ {
+ "user_id" => user.id,
+ "username" => user.username,
+ "timestamp" => current_timestamp,
+ "value" => 10000
+ }
+ ],
+ "dashboard_limit_enabled_at" => [
+ {
+ "user_id" => user.id,
+ "username" => user.username,
+ "timestamp" => current_timestamp,
+ "value" => current_timestamp
+ }
+ ]
+ }
)
end
- context 'with previous history avilable' do
+ context 'with previous history available' do
let(:plan_limits) do
- create(:plan_limits,
- limits_history: { 'enforcement_limit' => [{ user_id: user.id, username: user.username,
- timestamp: current_timestamp,
- value: 20_000 },
- { user_id: user.id, username: user.username, timestamp: current_timestamp,
- value: 50_000 }] })
+ create(
+ :plan_limits,
+ limits_history: {
+ 'enforcement_limit' => [
+ {
+ user_id: user.id,
+ username: user.username,
+ timestamp: current_timestamp,
+ value: 20_000
+ },
+ {
+ user_id: user.id,
+ username: user.username,
+ timestamp: current_timestamp,
+ value: 50_000
+ }
+ ]
+ }
+ )
end
it 'appends to it' do
- plan_limits.log_limits_changes(user, enforcement_limit: 60_000)
- expect(history).to eq(
+ formatted_limits_history = plan_limits.format_limits_history(user, enforcement_limit: 60_000)
+
+ expect(formatted_limits_history).to eq(
{
- 'enforcement_limit' => [
- { 'user_id' => user.id, 'username' => user.username, 'timestamp' => current_timestamp,
- 'value' => 20_000 },
- { 'user_id' => user.id, 'username' => user.username, 'timestamp' => current_timestamp,
- 'value' => 50_000 },
- { 'user_id' => user.id, 'username' => user.username, 'timestamp' => current_timestamp, 'value' => 60_000 }
+ "enforcement_limit" => [
+ {
+ "user_id" => user.id,
+ "username" => user.username,
+ "timestamp" => current_timestamp,
+ "value" => 20000
+ },
+ {
+ "user_id" => user.id,
+ "username" => user.username,
+ "timestamp" => current_timestamp,
+ "value" => 50000
+ },
+ {
+ "user_id" => user.id,
+ "username" => user.username,
+ "timestamp" => current_timestamp,
+ "value" => 60000
+ }
]
}
)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index b5c47d9fc40..73489e6b35e 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -6311,6 +6311,36 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
expect(recorder.count).to be_zero
end
+
+ context 'with a CI integration' do
+ let!(:ci_integration) do
+ create(:jenkins_integration, push_events: true, active: true, project: integration.project)
+ end
+
+ it 'executes the integrations' do
+ [Integrations::Jenkins, Integrations::Slack].each do |integration_type|
+ expect_next_found_instance_of(integration_type) do |instance|
+ expect(instance).to receive(:async_execute).with('data').once
+ end
+ end
+
+ integration.project.execute_integrations('data', :push_hooks)
+ end
+
+ context 'and skipping ci' do
+ it 'does not execute ci integrations' do
+ expect_next_found_instance_of(Integrations::Jenkins) do |instance|
+ expect(instance).not_to receive(:async_execute)
+ end
+
+ expect_next_found_instance_of(Integrations::Slack) do |instance|
+ expect(instance).to receive(:async_execute).with('data').once
+ end
+
+ integration.project.execute_integrations('data', :push_hooks, skip_ci: true)
+ end
+ end
+ end
end
describe '#has_active_hooks?' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 4fc4341673c..9709684f44b 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -6182,6 +6182,29 @@ RSpec.describe User, feature_category: :user_profile do
expect { user.delete_async(deleted_by: deleted_by) }.not_to change { user.note }
end
end
+
+ describe '#allow_possible_spam?' do
+ context 'when no custom attribute is set' do
+ it 'is false' do
+ expect(user.allow_possible_spam?).to be_falsey
+ end
+ end
+
+ context 'when the custom attribute is set' do
+ before do
+ user.custom_attributes.upsert_custom_attributes(
+ [{
+ user_id: user.id,
+ key: UserCustomAttribute::ALLOW_POSSIBLE_SPAM,
+ value: "test"
+ }])
+ end
+
+ it '#allow_possible_spam? is true' do
+ expect(user.allow_possible_spam?).to be_truthy
+ end
+ end
+ end
end
end
diff --git a/spec/requests/api/admin/plan_limits_spec.rb b/spec/requests/api/admin/plan_limits_spec.rb
index cad1111b76b..97eb8a2b13f 100644
--- a/spec/requests/api/admin/plan_limits_spec.rb
+++ b/spec/requests/api/admin/plan_limits_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :shared d
expect(json_response['conan_max_file_size']).to eq(Plan.default.actual_limits.conan_max_file_size)
expect(json_response['generic_packages_max_file_size']).to eq(Plan.default.actual_limits.generic_packages_max_file_size)
expect(json_response['helm_max_file_size']).to eq(Plan.default.actual_limits.helm_max_file_size)
+ expect(json_response['limits_history']).to eq(Plan.default.actual_limits.limits_history)
expect(json_response['maven_max_file_size']).to eq(Plan.default.actual_limits.maven_max_file_size)
expect(json_response['npm_max_file_size']).to eq(Plan.default.actual_limits.npm_max_file_size)
expect(json_response['nuget_max_file_size']).to eq(Plan.default.actual_limits.nuget_max_file_size)
@@ -86,7 +87,9 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :shared d
let(:params) { { 'plan_name': 'default' } }
end
- context 'as an admin user' do
+ context 'as an admin user', :freeze_time do
+ let(:current_timestamp) { Time.current.utc.to_i }
+
context 'correct params' do
it 'updates multiple plan limits', :aggregate_failures do
put api(path, admin, admin_mode: true), params: {
@@ -124,6 +127,11 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits', feature_category: :shared d
expect(json_response['enforcement_limit']).to eq(15)
expect(json_response['generic_packages_max_file_size']).to eq(20)
expect(json_response['helm_max_file_size']).to eq(25)
+ expect(json_response['limits_history']).to eq(
+ { "enforcement_limit" => [{ "user_id" => admin.id, "username" => admin.username, "timestamp" => current_timestamp, "value" => 15 }],
+ "notification_limit" => [{ "user_id" => admin.id, "username" => admin.username, "timestamp" => current_timestamp, "value" => 90 }],
+ "storage_size_limit" => [{ "user_id" => admin.id, "username" => admin.username, "timestamp" => current_timestamp, "value" => 80 }] }
+ )
expect(json_response['maven_max_file_size']).to eq(30)
expect(json_response['notification_limit']).to eq(90)
expect(json_response['npm_max_file_size']).to eq(40)
diff --git a/spec/serializers/diff_viewer_entity_spec.rb b/spec/serializers/diff_viewer_entity_spec.rb
index 84d2bdceb78..7ee2f8ec12f 100644
--- a/spec/serializers/diff_viewer_entity_spec.rb
+++ b/spec/serializers/diff_viewer_entity_spec.rb
@@ -16,47 +16,27 @@ RSpec.describe DiffViewerEntity do
subject { described_class.new(viewer).as_json(options) }
- context 'when add_ignore_all_white_spaces is enabled' do
- before do
- stub_feature_flags(add_ignore_all_white_spaces: true)
- end
-
- it 'serializes diff file viewer' do
- expect(subject.with_indifferent_access).to match_schema('entities/diff_viewer')
- end
-
- it 'contains whitespace_only attribute' do
- expect(subject.with_indifferent_access).to include(:whitespace_only)
- end
-
- context 'when whitespace_only option is true' do
- let(:options) { { whitespace_only: true } }
+ it 'serializes diff file viewer' do
+ expect(subject.with_indifferent_access).to match_schema('entities/diff_viewer')
+ end
- it 'returns the whitespace_only attribute true' do
- expect(subject.with_indifferent_access[:whitespace_only]).to eq true
- end
- end
+ it 'contains whitespace_only attribute' do
+ expect(subject.with_indifferent_access).to include(:whitespace_only)
+ end
- context 'when whitespace_only option is false' do
- let(:options) { { whitespace_only: false } }
+ context 'when whitespace_only option is true' do
+ let(:options) { { whitespace_only: true } }
- it 'returns the whitespace_only attribute false' do
- expect(subject.with_indifferent_access[:whitespace_only]).to eq false
- end
+ it 'returns the whitespace_only attribute true' do
+ expect(subject.with_indifferent_access[:whitespace_only]).to eq true
end
end
- context 'when add_ignore_all_white_spaces is disabled ' do
- before do
- stub_feature_flags(add_ignore_all_white_spaces: false)
- end
-
- it 'serializes diff file viewer' do
- expect(subject.with_indifferent_access).to match_schema('entities/diff_viewer')
- end
+ context 'when whitespace_only option is false' do
+ let(:options) { { whitespace_only: false } }
- it 'does not contain whitespace_only attribute' do
- expect(subject.with_indifferent_access).not_to include(:whitespace_only)
+ it 'returns the whitespace_only attribute false' do
+ expect(subject.with_indifferent_access[:whitespace_only]).to eq false
end
end
end
diff --git a/spec/services/admin/plan_limits/update_service_spec.rb b/spec/services/admin/plan_limits/update_service_spec.rb
index 4a384b98299..718367fadc2 100644
--- a/spec/services/admin/plan_limits/update_service_spec.rb
+++ b/spec/services/admin/plan_limits/update_service_spec.rb
@@ -33,12 +33,10 @@ RSpec.describe Admin::PlanLimits::UpdateService, feature_category: :shared do
subject(:update_plan_limits) { described_class.new(params, current_user: user, plan: plan).execute }
context 'when current_user is an admin', :enable_admin_mode do
- context 'when the update is successful' do
- it 'updates all attributes' do
- expect_next_instance_of(described_class) do |instance|
- expect(instance).to receive(:parsed_params).and_call_original
- end
+ context 'when the update is successful', :freeze_time do
+ let(:current_timestamp) { Time.current.utc.to_i }
+ it 'updates all attributes' do
update_plan_limits
params.each do |key, value|
@@ -46,6 +44,22 @@ RSpec.describe Admin::PlanLimits::UpdateService, feature_category: :shared do
end
end
+ it 'logs the allowed attributes only' do
+ update_plan_limits
+
+ expect(limits.limits_history).to eq(
+ { "enforcement_limit" =>
+ [{ "user_id" => user.id, "username" => user.username,
+ "timestamp" => current_timestamp, "value" => 15 }],
+ "notification_limit" =>
+ [{ "user_id" => user.id, "username" => user.username,
+ "timestamp" => current_timestamp, "value" => 30 }],
+ "storage_size_limit" =>
+ [{ "user_id" => user.id, "username" => user.username,
+ "timestamp" => current_timestamp, "value" => 90 }] }
+ )
+ end
+
it 'returns success' do
response = update_plan_limits
diff --git a/spec/services/git/base_hooks_service_spec.rb b/spec/services/git/base_hooks_service_spec.rb
index 8a686a19c4c..60883db0cd5 100644
--- a/spec/services/git/base_hooks_service_spec.rb
+++ b/spec/services/git/base_hooks_service_spec.rb
@@ -102,10 +102,25 @@ RSpec.describe Git::BaseHooksService, feature_category: :source_code_management
it 'executes the services' do
expect(subject).to receive(:push_data).at_least(:once).and_call_original
- expect(project).to receive(:execute_integrations)
+ expect(project).to receive(:execute_integrations).with(kind_of(Hash), subject.hook_name, skip_ci: false)
subject.execute
end
+
+ context 'with integrations.skip_ci push option' do
+ before do
+ params[:push_options] = {
+ integrations: { skip_ci: true }
+ }
+ end
+
+ it 'executes the services' do
+ expect(subject).to receive(:push_data).at_least(:once).and_call_original
+ expect(project).to receive(:execute_integrations).with(kind_of(Hash), subject.hook_name, skip_ci: true)
+
+ subject.execute
+ end
+ end
end
context 'with inactive integrations' do
diff --git a/spec/services/groups/participants_service_spec.rb b/spec/services/groups/participants_service_spec.rb
index 749b3e9e3fd..d30ac5ac1a1 100644
--- a/spec/services/groups/participants_service_spec.rb
+++ b/spec/services/groups/participants_service_spec.rb
@@ -4,19 +4,21 @@ require 'spec_helper'
RSpec.describe Groups::ParticipantsService, feature_category: :groups_and_projects do
describe '#execute' do
- let(:user) { create(:user) }
- let(:parent_group) { create(:group) }
- let(:group) { create(:group, parent: parent_group) }
- let(:subgroup) { create(:group, parent: group) }
- let(:subproject) { create(:project, group: subgroup) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:parent_group) { create(:group) }
+ let_it_be(:group) { create(:group, parent: parent_group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:subproject) { create(:project, group: subgroup) }
- subject(:service_result) { described_class.new(group, user).execute(nil) }
+ let(:service) { described_class.new(group, developer) }
- before do
- parent_group.add_developer(create(:user))
- subgroup.add_developer(create(:user))
- subproject.add_developer(create(:user))
+ subject(:service_result) { service.execute(nil) }
+ before_all do
+ parent_group.add_developer(developer)
+ end
+
+ before do
stub_feature_flags(disable_all_mention: false)
end
@@ -24,21 +26,48 @@ RSpec.describe Groups::ParticipantsService, feature_category: :groups_and_projec
expect(service_result).to include(a_hash_including({ username: "all", name: "All Group Members" }))
end
+ context 'when `disable_all_mention` FF is enabled' do
+ before do
+ stub_feature_flags(disable_all_mention: true)
+ end
+
+ it 'does not include `All Group Members`' do
+ expect(service_result).not_to include(a_hash_including({ username: "all", name: "All Group Members" }))
+ end
+ end
+
it 'returns all members in parent groups, sub-groups, and sub-projects' do
+ parent_group.add_developer(create(:user))
+ subgroup.add_developer(create(:user))
+ subproject.add_developer(create(:user))
+
expected_users = (group.self_and_hierarchy.flat_map(&:users) + subproject.users)
.map { |user| user_to_autocompletable(user) }
- expect(expected_users.count).to eq(3)
+ expect(expected_users.count).to eq(4)
expect(service_result).to include(*expected_users)
end
- context 'when `disable_all_mention` FF is enabled' do
- before do
- stub_feature_flags(disable_all_mention: true)
+ context 'when shared with a private group' do
+ let_it_be(:private_group_member) { create(:user) }
+ let_it_be(:private_group) { create(:group, :private, :nested) }
+
+ before_all do
+ private_group.add_owner(private_group_member)
+
+ create(:group_group_link, shared_group: parent_group, shared_with_group: private_group)
end
- it 'does not include `All Group Members`' do
- expect(service_result).not_to include(a_hash_including({ username: "all", name: "All Group Members" }))
+ subject(:usernames) { service_result.pluck(:username) }
+
+ context 'when current_user is not a member' do
+ let(:service) { described_class.new(group, create(:user)) }
+
+ it { is_expected.not_to include(private_group_member.username) }
+ end
+
+ context 'when current_user is a member' do
+ it { is_expected.to include(private_group_member.username) }
end
end
end
diff --git a/spec/services/spam/spam_verdict_service_spec.rb b/spec/services/spam/spam_verdict_service_spec.rb
index 5baa476a23e..bf627304807 100644
--- a/spec/services/spam/spam_verdict_service_spec.rb
+++ b/spec/services/spam/spam_verdict_service_spec.rb
@@ -136,6 +136,38 @@ RSpec.describe Spam::SpamVerdictService, feature_category: :instance_resiliency
end
end
+ context 'if allow_possible_spam user custom attribute is set' do
+ before do
+ UserCustomAttribute.upsert_custom_attributes(
+ [{
+ user_id: user.id,
+ key: 'allow_possible_spam',
+ value: 'does not matter'
+ }]
+ )
+ end
+
+ context 'and a service returns a verdict that should be overridden' do
+ before do
+ allow(service).to receive(:get_spamcheck_verdict).and_return(BLOCK_USER)
+ end
+
+ it 'overrides and renders the override verdict' do
+ is_expected.to eq OVERRIDE_VIA_ALLOW_POSSIBLE_SPAM
+ end
+ end
+
+ context 'and a service returns a verdict that does not need to be overridden' do
+ before do
+ allow(service).to receive(:get_spamcheck_verdict).and_return(ALLOW)
+ end
+
+ it 'does not override and renders the original verdict' do
+ is_expected.to eq ALLOW
+ end
+ end
+ end
+
context 'records metrics' do
let(:histogram) { instance_double(Prometheus::Client::Histogram) }
diff --git a/spec/services/users/allow_possible_spam_service_spec.rb b/spec/services/users/allow_possible_spam_service_spec.rb
new file mode 100644
index 00000000000..53618f0c8e9
--- /dev/null
+++ b/spec/services/users/allow_possible_spam_service_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::AllowPossibleSpamService, feature_category: :user_management do
+ let_it_be(:current_user) { create(:admin) }
+
+ subject(:service) { described_class.new(current_user) }
+
+ describe '#execute' do
+ let(:user) { create(:user) }
+
+ subject(:operation) { service.execute(user) }
+
+ it 'updates the custom attributes', :aggregate_failures do
+ expect(user.custom_attributes).to be_empty
+
+ operation
+ user.reload
+
+ expect(user.custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM)).to be_present
+ end
+ end
+end
diff --git a/spec/services/users/disallow_possible_spam_service_spec.rb b/spec/services/users/disallow_possible_spam_service_spec.rb
new file mode 100644
index 00000000000..32a47e05525
--- /dev/null
+++ b/spec/services/users/disallow_possible_spam_service_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::DisallowPossibleSpamService, feature_category: :user_management do
+ let_it_be(:current_user) { create(:admin) }
+
+ subject(:service) { described_class.new(current_user) }
+
+ describe '#execute' do
+ let(:user) { create(:user) }
+
+ subject(:operation) { service.execute(user) }
+
+ before do
+ UserCustomAttribute.upsert_custom_attributes(
+ [{
+ user_id: user.id,
+ key: :allow_possible_spam,
+ value: 'not important'
+ }]
+ )
+ end
+
+ it 'updates the custom attributes', :aggregate_failures do
+ expect(user.custom_attributes.by_key(UserCustomAttribute::ALLOW_POSSIBLE_SPAM)).to be_present
+
+ operation
+ user.reload
+
+ expect(user.custom_attributes).to be_empty
+ end
+ end
+end
diff --git a/spec/support/helpers/features/autocomplete_helpers.rb b/spec/support/helpers/features/autocomplete_helpers.rb
new file mode 100644
index 00000000000..106e823afef
--- /dev/null
+++ b/spec/support/helpers/features/autocomplete_helpers.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Features
+ module AutocompleteHelpers
+ def find_autocomplete_menu
+ find('.atwho-view ul', visible: true)
+ end
+
+ def find_highlighted_autocomplete_item
+ find('.atwho-view li.cur', visible: true)
+ end
+ end
+end