summaryrefslogtreecommitdiff
path: root/spec/helpers
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-07-20 15:40:28 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-07-20 15:40:28 +0000
commitb595cb0c1dec83de5bdee18284abe86614bed33b (patch)
tree8c3d4540f193c5ff98019352f554e921b3a41a72 /spec/helpers
parent2f9104a328fc8a4bddeaa4627b595166d24671d0 (diff)
downloadgitlab-ce-b595cb0c1dec83de5bdee18284abe86614bed33b.tar.gz
Add latest changes from gitlab-org/gitlab@15-2-stable-eev15.2.0-rc42
Diffstat (limited to 'spec/helpers')
-rw-r--r--spec/helpers/avatars_helper_spec.rb70
-rw-r--r--spec/helpers/ci/pipeline_editor_helper_spec.rb4
-rw-r--r--spec/helpers/commits_helper_spec.rb4
-rw-r--r--spec/helpers/diff_helper_spec.rb61
-rw-r--r--spec/helpers/emails_helper_spec.rb2
-rw-r--r--spec/helpers/environments_helper_spec.rb1
-rw-r--r--spec/helpers/groups/group_members_helper_spec.rb2
-rw-r--r--spec/helpers/groups_helper_spec.rb4
-rw-r--r--spec/helpers/learn_gitlab_helper_spec.rb85
-rw-r--r--spec/helpers/namespace_storage_limit_alert_helper_spec.rb11
-rw-r--r--spec/helpers/nav/new_dropdown_helper_spec.rb2
-rw-r--r--spec/helpers/projects/pipeline_helper_spec.rb6
-rw-r--r--spec/helpers/projects/project_members_helper_spec.rb70
-rw-r--r--spec/helpers/projects_helper_spec.rb6
-rw-r--r--spec/helpers/releases_helper_spec.rb6
-rw-r--r--spec/helpers/search_helper_spec.rb2
-rw-r--r--spec/helpers/sessions_helper_spec.rb47
-rw-r--r--spec/helpers/storage_helper_spec.rb14
-rw-r--r--spec/helpers/todos_helper_spec.rb65
-rw-r--r--spec/helpers/tree_helper_spec.rb54
-rw-r--r--spec/helpers/users/callouts_helper_spec.rb56
-rw-r--r--spec/helpers/web_hooks/web_hooks_helper_spec.rb120
22 files changed, 531 insertions, 161 deletions
diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb
index 192e48f43e5..9c0f8b77d45 100644
--- a/spec/helpers/avatars_helper_spec.rb
+++ b/spec/helpers/avatars_helper_spec.rb
@@ -221,48 +221,56 @@ RSpec.describe AvatarsHelper do
stub_application_setting(gravatar_enabled?: true)
end
- it 'returns a generic avatar when email is blank' do
- expect(helper.gravatar_icon('')).to match_asset_path(described_class::DEFAULT_AVATAR_PATH)
- end
+ context 'with FIPS not enabled', fips_mode: false do
+ it 'returns a generic avatar when email is blank' do
+ expect(helper.gravatar_icon('')).to match_asset_path(described_class::DEFAULT_AVATAR_PATH)
+ end
- it 'returns a valid Gravatar URL' do
- stub_config_setting(https: false)
+ it 'returns a valid Gravatar URL' do
+ stub_config_setting(https: false)
- expect(helper.gravatar_icon(user_email))
- .to match('https://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118')
- end
+ expect(helper.gravatar_icon(user_email))
+ .to match('https://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118')
+ end
- it 'uses HTTPs when configured' do
- stub_config_setting(https: true)
+ it 'uses HTTPs when configured' do
+ stub_config_setting(https: true)
- expect(helper.gravatar_icon(user_email))
- .to match('https://secure.gravatar.com')
- end
+ expect(helper.gravatar_icon(user_email))
+ .to match('https://secure.gravatar.com')
+ end
- it 'returns custom gravatar path when gravatar_url is set' do
- stub_gravatar_setting(plain_url: 'http://example.local/?s=%{size}&hash=%{hash}')
+ it 'returns custom gravatar path when gravatar_url is set' do
+ stub_gravatar_setting(plain_url: 'http://example.local/?s=%{size}&hash=%{hash}')
- expect(gravatar_icon(user_email, 20))
- .to eq('http://example.local/?s=40&hash=b58c6f14d292556214bd64909bcdb118')
- end
+ expect(gravatar_icon(user_email, 20))
+ .to eq('http://example.local/?s=40&hash=b58c6f14d292556214bd64909bcdb118')
+ end
- it 'accepts a custom size argument' do
- expect(helper.gravatar_icon(user_email, 64)).to include '?s=128'
- end
+ it 'accepts a custom size argument' do
+ expect(helper.gravatar_icon(user_email, 64)).to include '?s=128'
+ end
- it 'defaults size to 40@2x when given an invalid size' do
- expect(helper.gravatar_icon(user_email, nil)).to include '?s=80'
- end
+ it 'defaults size to 40@2x when given an invalid size' do
+ expect(helper.gravatar_icon(user_email, nil)).to include '?s=80'
+ end
- it 'accepts a scaling factor' do
- expect(helper.gravatar_icon(user_email, 40, 3)).to include '?s=120'
- end
+ it 'accepts a scaling factor' do
+ expect(helper.gravatar_icon(user_email, 40, 3)).to include '?s=120'
+ end
- it 'ignores case and surrounding whitespace' do
- normal = helper.gravatar_icon('foo@example.com')
- upcase = helper.gravatar_icon(' FOO@EXAMPLE.COM ')
+ it 'ignores case and surrounding whitespace' do
+ normal = helper.gravatar_icon('foo@example.com')
+ upcase = helper.gravatar_icon(' FOO@EXAMPLE.COM ')
- expect(normal).to eq upcase
+ expect(normal).to eq upcase
+ end
+ end
+
+ context 'with FIPS enabled', :fips_mode do
+ it 'returns a generic avatar' do
+ expect(helper.gravatar_icon(user_email)).to match_asset_path(described_class::DEFAULT_AVATAR_PATH)
+ end
end
end
end
diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb
index 8366506aa45..bc9e47a4ca1 100644
--- a/spec/helpers/ci/pipeline_editor_helper_spec.rb
+++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb
@@ -48,6 +48,7 @@ RSpec.describe Ci::PipelineEditorHelper do
"ci-config-path": project.ci_config_path_or_default,
"ci-examples-help-page-path" => help_page_path('ci/examples/index'),
"ci-help-page-path" => help_page_path('ci/index'),
+ "ci-lint-path" => project_ci_lint_path(project),
"default-branch" => project.default_branch_or_main,
"empty-state-illustration-path" => 'illustrations/empty.svg',
"initial-branch-name" => nil,
@@ -62,6 +63,7 @@ RSpec.describe Ci::PipelineEditorHelper do
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
"runner-help-page-path" => help_page_path('ci/runners/index'),
+ "simulate-pipeline-help-page-path" => help_page_path('ci/lint', anchor: 'simulate-a-pipeline'),
"total-branches" => project.repository.branches.length,
"validate-tab-illustration-path" => 'illustrations/validate.svg',
"yml-help-page-path" => help_page_path('ci/yaml/index')
@@ -77,6 +79,7 @@ RSpec.describe Ci::PipelineEditorHelper do
"ci-config-path": project.ci_config_path_or_default,
"ci-examples-help-page-path" => help_page_path('ci/examples/index'),
"ci-help-page-path" => help_page_path('ci/index'),
+ "ci-lint-path" => project_ci_lint_path(project),
"default-branch" => project.default_branch_or_main,
"empty-state-illustration-path" => 'illustrations/empty.svg',
"initial-branch-name" => nil,
@@ -91,6 +94,7 @@ RSpec.describe Ci::PipelineEditorHelper do
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
"runner-help-page-path" => help_page_path('ci/runners/index'),
+ "simulate-pipeline-help-page-path" => help_page_path('ci/lint', anchor: 'simulate-a-pipeline'),
"total-branches" => 0,
"validate-tab-illustration-path" => 'illustrations/validate.svg',
"yml-help-page-path" => help_page_path('ci/yaml/index')
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 961e7688202..b5b572e9719 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -94,7 +94,7 @@ RSpec.describe CommitsHelper do
it 'renders the correct select-rendered button' do
expect(node[:title]).to eq('Display rendered diff')
expect(node['data-file-hash']).to eq('abc')
- expect(node['data-diff-toggle-entity']).to eq('toShowBtn')
+ expect(node['data-diff-toggle-entity']).to eq('renderedButton')
expect(node.xpath("//a/svg")[0]["data-testid"]).to eq('doc-text-icon')
end
end
@@ -105,7 +105,7 @@ RSpec.describe CommitsHelper do
it 'renders the correct select-raw button' do
expect(node[:title]).to eq('Display raw diff')
expect(node['data-file-hash']).to eq('abc')
- expect(node['data-diff-toggle-entity']).to eq('toHideBtn')
+ expect(node['data-diff-toggle-entity']).to eq('rawButton')
expect(node.xpath("//a/svg")[0]["data-testid"]).to eq('doc-code-icon')
end
end
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index cf16807723b..93efce6b58b 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -470,22 +470,69 @@ RSpec.describe DiffHelper do
end
describe '#conflicts' do
- let(:merge_request) { instance_double(MergeRequest) }
+ let(:merge_request) { instance_double(MergeRequest, cannot_be_merged?: true) }
+ let(:merge_ref_head_diff) { true }
+ let(:can_be_resolved_in_ui?) { true }
+ let(:allow_tree_conflicts) { false }
+ let(:files) { [instance_double(Gitlab::Conflict::File, path: 'a')] }
+ let(:exception) { nil }
before do
allow(helper).to receive(:merge_request).and_return(merge_request)
- allow(helper).to receive(:options).and_return(merge_ref_head_diff: true)
+ allow(helper).to receive(:options).and_return(merge_ref_head_diff: merge_ref_head_diff)
+
+ allow_next_instance_of(MergeRequests::Conflicts::ListService, merge_request, allow_tree_conflicts: allow_tree_conflicts) do |svc|
+ allow(svc).to receive(:can_be_resolved_in_ui?).and_return(can_be_resolved_in_ui?)
+
+ if exception.present?
+ allow(svc).to receive_message_chain(:conflicts, :files).and_raise(exception)
+ else
+ allow(svc).to receive_message_chain(:conflicts, :files).and_return(files)
+ end
+ end
end
- context 'when Gitlab::Git::Conflict::Resolver::ConflictSideMissing exception is raised' do
- before do
- allow_next_instance_of(MergeRequests::Conflicts::ListService, merge_request, allow_tree_conflicts: true) do |svc|
- allow(svc).to receive_message_chain(:conflicts, :files).and_raise(Gitlab::Git::Conflict::Resolver::ConflictSideMissing)
+ it 'returns list of conflicts indexed by path' do
+ expect(helper.conflicts).to eq('a' => files.first)
+ end
+
+ context 'when merge_ref_head_diff option is false' do
+ let(:merge_ref_head_diff) { false }
+
+ it 'returns nil' do
+ expect(helper.conflicts).to be_nil
+ end
+ end
+
+ context 'when merge request can be merged' do
+ let(:merge_request) { instance_double(MergeRequest, cannot_be_merged?: false) }
+
+ it 'returns nil' do
+ expect(helper.conflicts).to be_nil
+ end
+ end
+
+ context 'when conflicts cannot be resolved in UI' do
+ let(:can_be_resolved_in_ui?) { false }
+
+ it 'returns nil' do
+ expect(helper.conflicts).to be_nil
+ end
+
+ context 'when allow_tree_conflicts is true' do
+ let(:allow_tree_conflicts) { true }
+
+ it 'returns list of conflicts' do
+ expect(helper.conflicts(allow_tree_conflicts: allow_tree_conflicts)).to eq('a' => files.first)
end
end
+ end
+
+ context 'when Gitlab::Git::Conflict::Resolver::ConflictSideMissing exception is raised' do
+ let(:exception) { Gitlab::Git::Conflict::Resolver::ConflictSideMissing }
it 'returns an empty hash' do
- expect(helper.conflicts(allow_tree_conflicts: true)).to eq({})
+ expect(helper.conflicts).to eq({})
end
end
end
diff --git a/spec/helpers/emails_helper_spec.rb b/spec/helpers/emails_helper_spec.rb
index 220e154aad8..04653d9ff03 100644
--- a/spec/helpers/emails_helper_spec.rb
+++ b/spec/helpers/emails_helper_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe EmailsHelper do
end
describe 'notification_reason_text' do
- subject { helper.notification_reason_text(reason_code) }
+ subject { helper.notification_reason_text(reason: reason_code) }
using RSpec::Parameterized::TableSyntax
diff --git a/spec/helpers/environments_helper_spec.rb b/spec/helpers/environments_helper_spec.rb
index e4d4f18ad68..c1eaf1b1bcd 100644
--- a/spec/helpers/environments_helper_spec.rb
+++ b/spec/helpers/environments_helper_spec.rb
@@ -129,7 +129,6 @@ RSpec.describe EnvironmentsHelper do
"environment_name": environment.name,
"environments_path": api_v4_projects_environments_path(id: project.id),
"environment_id": environment.id,
- "cluster_applications_documentation_path" => help_page_path('user/clusters/integrations.md', anchor: 'elastic-stack-cluster-integration'),
"clusters_path": project_clusters_path(project, format: :json)
}
diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb
index d308df3a017..89c26c21338 100644
--- a/spec/helpers/groups/group_members_helper_spec.rb
+++ b/spec/helpers/groups/group_members_helper_spec.rb
@@ -44,6 +44,7 @@ RSpec.describe Groups::GroupMembersHelper do
members: present_members(members_collection),
invited: present_members(invited),
access_requests: present_members(access_requests),
+ banned: [],
include_relations: [:inherited, :direct],
search: nil
)
@@ -117,6 +118,7 @@ RSpec.describe Groups::GroupMembersHelper do
members: present_members(members_collection),
invited: present_members(invited),
access_requests: present_members(access_requests),
+ banned: [],
include_relations: include_relations,
search: nil
)
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index bcbe571db5e..d00cd8f1d6b 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -355,8 +355,8 @@ RSpec.describe GroupsHelper do
end
end
- describe '#show_thanks_for_purchase_banner?' do
- subject { helper.show_thanks_for_purchase_banner? }
+ describe '#show_thanks_for_purchase_alert?' do
+ subject { helper.show_thanks_for_purchase_alert? }
it 'returns true with purchased_quantity present in params' do
allow(controller).to receive(:params) { { purchased_quantity: '1' } }
diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb
index 9fce7495b5a..7c9dfd6b5be 100644
--- a/spec/helpers/learn_gitlab_helper_spec.rb
+++ b/spec/helpers/learn_gitlab_helper_spec.rb
@@ -92,38 +92,6 @@ RSpec.describe LearnGitlabHelper do
it_behaves_like 'has all data'
- it 'sets correct paths' do
- expect(onboarding_actions_data).to match({
- trial_started: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab/-/issues/2\z})
- ),
- pipeline_created: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab/-/issues/7\z})
- ),
- code_owners_enabled: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab/-/issues/10\z})
- ),
- required_mr_approvals_enabled: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab/-/issues/11\z})
- ),
- issue_created: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab/-/issues\z})
- ),
- git_write: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab\z})
- ),
- user_added: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab/-/project_members\z})
- ),
- merge_request_created: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab/-/merge_requests\z})
- ),
- security_scan_enabled: a_hash_including(
- url: a_string_matching(%r{/learn_gitlab/-/security/configuration\z})
- )
- })
- end
-
it 'sets correct completion statuses' do
expect(onboarding_actions_data).to match({
issue_created: a_hash_including(completed: false),
@@ -137,5 +105,58 @@ RSpec.describe LearnGitlabHelper do
security_scan_enabled: a_hash_including(completed: false)
})
end
+
+ describe 'security_actions_continuous_onboarding experiment' do
+ let(:base_paths) do
+ {
+ trial_started: a_hash_including(url: %r{/learn_gitlab/-/issues/2\z}),
+ pipeline_created: a_hash_including(url: %r{/learn_gitlab/-/issues/7\z}),
+ code_owners_enabled: a_hash_including(url: %r{/learn_gitlab/-/issues/10\z}),
+ required_mr_approvals_enabled: a_hash_including(url: %r{/learn_gitlab/-/issues/11\z}),
+ issue_created: a_hash_including(url: %r{/learn_gitlab/-/issues\z}),
+ git_write: a_hash_including(url: %r{/learn_gitlab\z}),
+ user_added: a_hash_including(url: %r{/learn_gitlab/-/project_members\z}),
+ merge_request_created: a_hash_including(url: %r{/learn_gitlab/-/merge_requests\z})
+ }
+ end
+
+ context 'when control' do
+ before do
+ stub_experiments(security_actions_continuous_onboarding: :control)
+ end
+
+ it 'sets correct paths' do
+ expect(onboarding_actions_data).to match(
+ base_paths.merge(
+ security_scan_enabled: a_hash_including(
+ url: %r{/learn_gitlab/-/security/configuration\z}
+ )
+ )
+ )
+ end
+ end
+
+ context 'when candidate' do
+ before do
+ stub_experiments(security_actions_continuous_onboarding: :candidate)
+ end
+
+ it 'sets correct paths' do
+ expect(onboarding_actions_data).to match(
+ base_paths.merge(
+ license_scanning_run: a_hash_including(
+ url: described_class::LICENSE_SCANNING_RUN_URL
+ ),
+ secure_dependency_scanning_run: a_hash_including(
+ url: project_security_configuration_path(project, anchor: 'dependency-scanning')
+ ),
+ secure_dast_run: a_hash_including(
+ url: project_security_configuration_path(project, anchor: 'dast')
+ )
+ )
+ )
+ end
+ end
+ end
end
end
diff --git a/spec/helpers/namespace_storage_limit_alert_helper_spec.rb b/spec/helpers/namespace_storage_limit_alert_helper_spec.rb
deleted file mode 100644
index ab3cf96edef..00000000000
--- a/spec/helpers/namespace_storage_limit_alert_helper_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe NamespaceStorageLimitAlertHelper do
- describe '#display_namespace_storage_limit_alert!' do
- it 'is defined in CE' do
- expect { helper.display_namespace_storage_limit_alert! }.not_to raise_error
- end
- end
-end
diff --git a/spec/helpers/nav/new_dropdown_helper_spec.rb b/spec/helpers/nav/new_dropdown_helper_spec.rb
index 4f32ac5b5c6..2fe237fb996 100644
--- a/spec/helpers/nav/new_dropdown_helper_spec.rb
+++ b/spec/helpers/nav/new_dropdown_helper_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe Nav::NewDropdownHelper do
end
it 'has title' do
- expect(subject[:title]).to eq('Create new')
+ expect(subject[:title]).to eq('Create new...')
end
context 'when current_user is nil (anonymous)' do
diff --git a/spec/helpers/projects/pipeline_helper_spec.rb b/spec/helpers/projects/pipeline_helper_spec.rb
index d04aa9a9d04..2b2dad286c7 100644
--- a/spec/helpers/projects/pipeline_helper_spec.rb
+++ b/spec/helpers/projects/pipeline_helper_spec.rb
@@ -11,7 +11,11 @@ RSpec.describe Projects::PipelineHelper do
let_it_be(:pipeline) { Ci::PipelinePresenter.new(raw_pipeline, current_user: user)}
describe '#js_pipeline_tabs_data' do
- subject(:pipeline_tabs_data) { helper.js_pipeline_tabs_data(project, pipeline) }
+ before do
+ project.add_developer(user)
+ end
+
+ subject(:pipeline_tabs_data) { helper.js_pipeline_tabs_data(project, pipeline, user) }
it 'returns pipeline tabs data' do
expect(pipeline_tabs_data).to include({
diff --git a/spec/helpers/projects/project_members_helper_spec.rb b/spec/helpers/projects/project_members_helper_spec.rb
index 2414a1782c5..844c33de635 100644
--- a/spec/helpers/projects/project_members_helper_spec.rb
+++ b/spec/helpers/projects/project_members_helper_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe Projects::ProjectMembersHelper do
describe 'project members' do
let_it_be(:members) { create_list(:project_member, 2, project: project) }
- let_it_be(:group_links) { create_list(:project_group_link, 1, project: project) }
let_it_be(:invited) { create_list(:project_member, 2, :invited, project: project) }
let_it_be(:access_requests) { create_list(:project_member, 2, :access_request, project: project) }
@@ -26,9 +25,10 @@ RSpec.describe Projects::ProjectMembersHelper do
helper.project_members_app_data_json(
project,
members: present_members(members_collection),
- group_links: group_links,
invited: present_members(invited),
- access_requests: present_members(access_requests)
+ access_requests: present_members(access_requests),
+ include_relations: [:inherited, :direct],
+ search: nil
)
)
end
@@ -84,6 +84,70 @@ RSpec.describe Projects::ProjectMembersHelper do
expect(subject['user']['pagination']).to match(expected)
end
end
+
+ context 'group links' do
+ let_it_be(:shared_with_group) { create(:group) }
+ let_it_be(:group_link) { create(:project_group_link, project: project, group: shared_with_group) }
+
+ before do
+ allow(helper).to receive(:project_group_link_path).with(project, ':id').and_return('/foo-group/foo-project/-/group_links/:id')
+ end
+
+ it 'sets `group.members` property that matches json schema' do
+ expect(subject['group']['members'].to_json).to match_schema('group_link/project_group_links')
+ end
+
+ it 'sets `member_path` property' do
+ expect(subject['group']['member_path']).to eq('/foo-group/foo-project/-/group_links/:id')
+ end
+
+ context 'inherited' do
+ let_it_be(:shared_with_group_1) { create(:group) }
+ let_it_be(:shared_with_group_2) { create(:group) }
+ let_it_be(:shared_with_group_3) { create(:group) }
+ let_it_be(:shared_with_group_4) { create(:group) }
+ let_it_be(:shared_with_group_5) { create(:group) }
+ let_it_be(:top_group) { create(:group) }
+ let_it_be(:sub_group) { create(:group, parent: top_group) }
+ let_it_be(:project) { create(:project, group: sub_group) }
+ let_it_be(:group_link_1) { create(:group_group_link, shared_group: top_group, shared_with_group: shared_with_group_1, group_access: Gitlab::Access::GUEST) }
+ let_it_be(:group_link_2) { create(:group_group_link, shared_group: top_group, shared_with_group: shared_with_group_4, group_access: Gitlab::Access::GUEST) }
+ let_it_be(:group_link_3) { create(:group_group_link, shared_group: top_group, shared_with_group: shared_with_group_5, group_access: Gitlab::Access::DEVELOPER) }
+ let_it_be(:group_link_4) { create(:group_group_link, shared_group: sub_group, shared_with_group: shared_with_group_2, group_access: Gitlab::Access::DEVELOPER) }
+ let_it_be(:group_link_5) { create(:group_group_link, shared_group: sub_group, shared_with_group: shared_with_group_4, group_access: Gitlab::Access::DEVELOPER) }
+ let_it_be(:group_link_6) { create(:group_group_link, shared_group: sub_group, shared_with_group: shared_with_group_5, group_access: Gitlab::Access::GUEST) }
+ let_it_be(:group_link_7) { create(:project_group_link, project: project, group: shared_with_group_1, group_access: Gitlab::Access::DEVELOPER) }
+ let_it_be(:group_link_8) { create(:project_group_link, project: project, group: shared_with_group_2, group_access: Gitlab::Access::GUEST) }
+ let_it_be(:group_link_9) { create(:project_group_link, project: project, group: shared_with_group_3, group_access: Gitlab::Access::REPORTER) }
+
+ subject do
+ Gitlab::Json.parse(
+ helper.project_members_app_data_json(
+ project,
+ members: present_members(members_collection),
+ invited: present_members(invited),
+ access_requests: present_members(access_requests),
+ include_relations: include_relations,
+ search: nil
+ )
+ )
+ end
+
+ using RSpec::Parameterized::TableSyntax
+
+ where(:include_relations, :result) do
+ [:inherited, :direct] | lazy { [group_link_7, group_link_4, group_link_9, group_link_5, group_link_3].map(&:id) }
+ [:inherited] | lazy { [group_link_1, group_link_4, group_link_5, group_link_3].map(&:id) }
+ [:direct] | lazy { [group_link_7, group_link_8, group_link_9].map(&:id) }
+ end
+
+ with_them do
+ it 'returns correct group links' do
+ expect(subject['group']['members'].map { |link| link['id'] }).to match_array(result)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 4502729866c..b7cc8c217a4 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -698,7 +698,7 @@ RSpec.describe ProjectsHelper do
def grant_user_access(project, user, access)
case access
when :developer, :maintainer
- project.add_user(user, access)
+ project.add_member(user, access)
when :owner
project.namespace.update!(owner: user)
end
@@ -969,6 +969,10 @@ RSpec.describe ProjectsHelper do
containerRegistryAccessLevel: project.project_feature.container_registry_access_level
)
end
+
+ it 'includes membersPagePath' do
+ expect(subject).to include(membersPagePath: project_project_members_path(project))
+ end
end
describe '#project_classes' do
diff --git a/spec/helpers/releases_helper_spec.rb b/spec/helpers/releases_helper_spec.rb
index b7493e84c6a..59a92c067f4 100644
--- a/spec/helpers/releases_helper_spec.rb
+++ b/spec/helpers/releases_helper_spec.rb
@@ -64,7 +64,9 @@ RSpec.describe ReleasesHelper do
release_assets_docs_path
manage_milestones_path
new_milestone_path
- edit_release_docs_path)
+ upcoming_release_docs_path
+ edit_release_docs_path
+ delete_release_docs_path)
expect(helper.data_for_edit_release_page.keys).to match_array(keys)
end
@@ -76,6 +78,7 @@ RSpec.describe ReleasesHelper do
group_id
group_milestones_available
project_path
+ tag_name
releases_page_path
markdown_preview_path
markdown_docs_path
@@ -83,6 +86,7 @@ RSpec.describe ReleasesHelper do
manage_milestones_path
new_milestone_path
default_branch
+ upcoming_release_docs_path
edit_release_docs_path)
expect(helper.data_for_new_release_page.keys).to match_array(keys)
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 4117d577f20..1ead1fc9b8b 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -741,7 +741,7 @@ RSpec.describe SearchHelper do
let(:for_group) { true }
it 'adds the :group and :group_metadata correctly to hash' do
- expect(header_search_context[:group]).to eq({ id: group.id, name: group.name })
+ expect(header_search_context[:group]).to eq({ id: group.id, name: group.name, full_name: group.full_name })
expect(header_search_context[:group_metadata]).to eq(group_metadata)
end
diff --git a/spec/helpers/sessions_helper_spec.rb b/spec/helpers/sessions_helper_spec.rb
index fd3d7100ba1..15424425060 100644
--- a/spec/helpers/sessions_helper_spec.rb
+++ b/spec/helpers/sessions_helper_spec.rb
@@ -50,4 +50,51 @@ RSpec.describe SessionsHelper do
expect(helper.unconfirmed_email?).to be_falsey
end
end
+
+ describe '#send_rate_limited?' do
+ let_it_be(:user) { build(:user) }
+
+ subject { helper.send_rate_limited?(user) }
+
+ before do
+ allow(::Gitlab::ApplicationRateLimiter)
+ .to receive(:peek)
+ .with(:email_verification_code_send, scope: user)
+ .and_return(rate_limited)
+ end
+
+ context 'when rate limited' do
+ let(:rate_limited) { true }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when not rate limited' do
+ let(:rate_limited) { false }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ describe '#obfuscated_email' do
+ subject { helper.obfuscated_email(email) }
+
+ context 'when an email address is normal length' do
+ let(:email) { 'alex@gitlab.com' }
+
+ it { is_expected.to eq('al**@g*****.com') }
+ end
+
+ context 'when an email address contains multiple top level domains' do
+ let(:email) { 'alex@gl.co.uk' }
+
+ it { is_expected.to eq('al**@g****.uk') }
+ end
+
+ context 'when an email address is very short' do
+ let(:email) { 'a@b' }
+
+ it { is_expected.to eq('a@b') }
+ end
+ end
end
diff --git a/spec/helpers/storage_helper_spec.rb b/spec/helpers/storage_helper_spec.rb
index c2c508cf485..4b46bf169e0 100644
--- a/spec/helpers/storage_helper_spec.rb
+++ b/spec/helpers/storage_helper_spec.rb
@@ -51,14 +51,14 @@ RSpec.describe StorageHelper do
end
end
- describe "storage_enforcement_banner", :saas do
+ describe "storage_enforcement_banner" do
let_it_be_with_refind(:current_user) { create(:user) }
let_it_be(:free_group) { create(:group) }
let_it_be(:paid_group) { create(:group) }
before do
- allow(helper).to receive(:can?).with(current_user, :admin_namespace, free_group).and_return(true)
- allow(helper).to receive(:can?).with(current_user, :admin_namespace, paid_group).and_return(true)
+ allow(helper).to receive(:can?).with(current_user, :maintain_namespace, free_group).and_return(true)
+ allow(helper).to receive(:can?).with(current_user, :maintain_namespace, paid_group).and_return(true)
allow(helper).to receive(:current_user) { current_user }
allow(paid_group).to receive(:paid?).and_return(true)
@@ -84,7 +84,13 @@ RSpec.describe StorageHelper do
end
it 'returns nil when current_user do not have access usage quotas page' do
- allow(helper).to receive(:can?).with(current_user, :admin_namespace, free_group).and_return(false)
+ allow(helper).to receive(:can?).with(current_user, :maintain_namespace, free_group).and_return(false)
+
+ expect(helper.storage_enforcement_banner_info(free_group)).to be(nil)
+ end
+
+ it 'returns nil when namespace_storage_limit_show_preenforcement_banner FF is disabled' do
+ stub_feature_flags(namespace_storage_limit_show_preenforcement_banner: false)
expect(helper.storage_enforcement_banner_info(free_group)).to be(nil)
end
diff --git a/spec/helpers/todos_helper_spec.rb b/spec/helpers/todos_helper_spec.rb
index 922fb1d7c92..bbabfedc3ee 100644
--- a/spec/helpers/todos_helper_spec.rb
+++ b/spec/helpers/todos_helper_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe TodosHelper do
let_it_be(:user) { create(:user) }
let_it_be(:author) { create(:user) }
- let_it_be(:issue) { create(:issue, title: 'Issue 1') }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue) { create(:issue, title: 'Issue 1', project: project) }
let_it_be(:design) { create(:design, issue: issue) }
let_it_be(:note) do
create(:note,
@@ -16,7 +17,7 @@ RSpec.describe TodosHelper do
let_it_be(:design_todo) do
create(:todo, :mentioned,
user: user,
- project: issue.project,
+ project: project,
target: design,
author: author,
note: note)
@@ -27,6 +28,15 @@ RSpec.describe TodosHelper do
create(:todo, target: alert)
end
+ let_it_be(:task_todo) do
+ task = create(:work_item, :task, project: project)
+ create(:todo, target: task, target_type: task.class.name, project: project)
+ end
+
+ let_it_be(:issue_todo) do
+ create(:todo, target: issue)
+ end
+
describe '#todos_count_format' do
it 'shows fuzzy count for 100 or more items' do
expect(helper.todos_count_format(100)).to eq '99+'
@@ -113,27 +123,62 @@ RSpec.describe TodosHelper do
)
end
end
+
+ context 'when given a task' do
+ let(:todo) { task_todo }
+
+ it 'responds with an appropriate path' do
+ path = helper.todo_target_path(todo)
+
+ expect(path).to eq("/#{todo.project.full_path}/-/work_items/#{todo.target.id}")
+ end
+ end
+
+ context 'when given an issue with a note anchor' do
+ let(:todo) { create(:todo, project: issue.project, target: issue, note: note) }
+
+ it 'responds with an appropriate path' do
+ path = helper.todo_target_path(todo)
+
+ expect(path).to eq("/#{issue.project.full_path}/-/issues/#{issue.iid}##{dom_id(note)}")
+ end
+ end
end
describe '#todo_target_type_name' do
+ subject { helper.todo_target_type_name(todo) }
+
context 'when given a design todo' do
let(:todo) { design_todo }
- it 'responds with an appropriate target type name' do
- name = helper.todo_target_type_name(todo)
-
- expect(name).to eq('design')
- end
+ it { is_expected.to eq('design') }
end
context 'when given an alert todo' do
let(:todo) { alert_todo }
- it 'responds with an appropriate target type name' do
- name = helper.todo_target_type_name(todo)
+ it { is_expected.to eq('alert') }
+ end
+
+ context 'when given a task todo' do
+ let(:todo) { task_todo }
- expect(name).to eq('alert')
+ it { is_expected.to eq('task') }
+ end
+
+ context 'when given an issue todo' do
+ let(:todo) { issue_todo }
+
+ it { is_expected.to eq('issue') }
+ end
+
+ context 'when given a merge request todo' do
+ let(:todo) do
+ merge_request = create(:merge_request, source_project: project)
+ create(:todo, target: merge_request)
end
+
+ it { is_expected.to eq('merge request') }
end
end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index 026432adf99..c40284ee933 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -3,63 +3,12 @@
require 'spec_helper'
RSpec.describe TreeHelper do
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
let(:repository) { project.repository }
let(:sha) { 'c1c67abbaf91f624347bb3ae96eabe3a1b742478' }
let_it_be(:user) { create(:user) }
- def create_file(filename)
- project.repository.create_file(
- project.creator,
- filename,
- 'test this',
- message: "Automatically created file #{filename}",
- branch_name: 'master'
- )
- end
-
- describe 'flatten_tree' do
- let(:tree) { repository.tree(sha, 'files') }
- let(:root_path) { 'files' }
- let(:tree_item) { tree.entries.find { |entry| entry.path == path } }
-
- subject { flatten_tree(root_path, tree_item) }
-
- context "on a directory containing more than one file/directory" do
- let(:path) { 'files/html' }
-
- it "returns the directory name" do
- expect(subject).to match('html')
- end
- end
-
- context "on a directory containing only one directory" do
- let(:path) { 'files/flat' }
-
- it "returns the flattened path" do
- expect(subject).to match('flat/path/correct')
- end
-
- context "with a nested root path" do
- let(:root_path) { 'files/flat' }
-
- it "returns the flattened path with the root path suffix removed" do
- expect(subject).to match('path/correct')
- end
- end
- end
-
- context 'when the root path contains a plus character' do
- let(:root_path) { 'gtk/C++' }
- let(:tree_item) { double(flat_path: 'gtk/C++/glade') }
-
- it 'returns the flattened path' do
- expect(subject).to eq('glade')
- end
- end
- end
-
describe '#commit_in_single_accessible_branch' do
it 'escapes HTML from the branch name' do
helper.instance_variable_set(:@branch_name, "<script>alert('escape me!');</script>")
@@ -163,6 +112,7 @@ RSpec.describe TreeHelper do
context 'user does not have write access but a personal fork exists' do
include ProjectForksHelper
+ let(:project) { create(:project, :repository) }
let(:forked_project) { create(:project, :repository, namespace: user.namespace) }
before do
diff --git a/spec/helpers/users/callouts_helper_spec.rb b/spec/helpers/users/callouts_helper_spec.rb
index 71a8d340b30..2c148aabead 100644
--- a/spec/helpers/users/callouts_helper_spec.rb
+++ b/spec/helpers/users/callouts_helper_spec.rb
@@ -222,4 +222,60 @@ RSpec.describe Users::CalloutsHelper do
it { is_expected.to be true }
end
end
+
+ describe '#web_hook_disabled_dismissed?' do
+ context 'without a project' do
+ it 'is false' do
+ expect(helper).not_to be_web_hook_disabled_dismissed(nil)
+ end
+ end
+
+ context 'with a project' do
+ let_it_be(:project) { create(:project) }
+
+ context 'the web-hook failure callout has never been dismissed' do
+ it 'is false' do
+ expect(helper).not_to be_web_hook_disabled_dismissed(project)
+ end
+ end
+
+ context 'the web-hook failure callout has been dismissed', :freeze_time do
+ before do
+ create(:namespace_callout,
+ feature_name: described_class::WEB_HOOK_DISABLED,
+ user: user,
+ namespace: project.namespace,
+ dismissed_at: 1.week.ago)
+ end
+
+ it 'is true' do
+ expect(helper).to be_web_hook_disabled_dismissed(project)
+ end
+
+ context 'when there was an older failure', :clean_gitlab_redis_shared_state do
+ let(:key) { "web_hooks:last_failure:project-#{project.id}" }
+
+ before do
+ Gitlab::Redis::SharedState.with { |r| r.set(key, 1.month.ago.iso8601) }
+ end
+
+ it 'is true' do
+ expect(helper).to be_web_hook_disabled_dismissed(project)
+ end
+ end
+
+ context 'when there has been a more recent failure', :clean_gitlab_redis_shared_state do
+ let(:key) { "web_hooks:last_failure:project-#{project.id}" }
+
+ before do
+ Gitlab::Redis::SharedState.with { |r| r.set(key, 1.day.ago.iso8601) }
+ end
+
+ it 'is false' do
+ expect(helper).not_to be_web_hook_disabled_dismissed(project)
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/helpers/web_hooks/web_hooks_helper_spec.rb b/spec/helpers/web_hooks/web_hooks_helper_spec.rb
new file mode 100644
index 00000000000..473f33a982f
--- /dev/null
+++ b/spec/helpers/web_hooks/web_hooks_helper_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WebHooks::WebHooksHelper do
+ let_it_be_with_reload(:project) { create(:project) }
+
+ let(:current_user) { nil }
+ let(:callout_dismissed) { false }
+ let(:web_hooks_disable_failed) { false }
+ let(:webhooks_failed_callout) { false }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(current_user)
+ allow(helper).to receive(:web_hook_disabled_dismissed?).with(project).and_return(callout_dismissed)
+
+ stub_feature_flags(
+ webhooks_failed_callout: webhooks_failed_callout,
+ web_hooks_disable_failed: web_hooks_disable_failed
+ )
+ end
+
+ shared_context 'user is logged in' do
+ let(:current_user) { create(:user) }
+ end
+
+ shared_context 'webhooks_failed_callout is enabled' do
+ let(:webhooks_failed_callout) { true }
+ end
+
+ shared_context 'webhooks_failed_callout is enabled for this project' do
+ let(:webhooks_failed_callout) { project }
+ end
+
+ shared_context 'web_hooks_disable_failed is enabled' do
+ let(:web_hooks_disable_failed) { true }
+ end
+
+ shared_context 'web_hooks_disable_failed is enabled for this project' do
+ let(:web_hooks_disable_failed) { project }
+ end
+
+ shared_context 'the user has permission' do
+ before do
+ project.add_maintainer(current_user)
+ end
+ end
+
+ shared_context 'the user dismissed the callout' do
+ let(:callout_dismissed) { true }
+ end
+
+ shared_context 'a hook has failed' do
+ before do
+ create(:project_hook, :permanently_disabled, project: project)
+ end
+ end
+
+ describe '#show_project_hook_failed_callout?' do
+ context 'all conditions are met' do
+ include_context 'user is logged in'
+ include_context 'webhooks_failed_callout is enabled'
+ include_context 'web_hooks_disable_failed is enabled'
+ include_context 'the user has permission'
+ include_context 'a hook has failed'
+
+ it 'is true' do
+ expect(helper).to be_show_project_hook_failed_callout(project: project)
+ end
+
+ it 'caches the DB calls until the TTL', :use_clean_rails_memory_store_caching, :request_store do
+ helper.show_project_hook_failed_callout?(project: project)
+
+ travel_to((described_class::EXPIRY_TTL - 1.second).from_now) do
+ expect do
+ helper.show_project_hook_failed_callout?(project: project)
+ end.not_to exceed_query_limit(0)
+ end
+
+ travel_to((described_class::EXPIRY_TTL + 1.second).from_now) do
+ expect do
+ helper.show_project_hook_failed_callout?(project: project)
+ end.to exceed_query_limit(0)
+ end
+ end
+ end
+
+ context 'all conditions are met, project scoped flags' do
+ include_context 'user is logged in'
+ include_context 'webhooks_failed_callout is enabled for this project'
+ include_context 'web_hooks_disable_failed is enabled for this project'
+ include_context 'the user has permission'
+ include_context 'a hook has failed'
+
+ it 'is true' do
+ expect(helper).to be_show_project_hook_failed_callout(project: project)
+ end
+ end
+
+ context 'one condition is not met' do
+ contexts = [
+ 'user is logged in',
+ 'webhooks_failed_callout is enabled',
+ 'web_hooks_disable_failed is enabled',
+ 'the user has permission',
+ 'a hook has failed'
+ ]
+
+ contexts.each do |name|
+ context "namely #{name}" do
+ contexts.each { |ctx| include_context(ctx) unless ctx == name }
+
+ it 'is false' do
+ expect(helper).not_to be_show_project_hook_failed_callout(project: project)
+ end
+ end
+ end
+ end
+ end
+end