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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-05-19 18:44:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-05-19 18:44:42 +0300
commit4555e1b21c365ed8303ffb7a3325d773c9b8bf31 (patch)
tree5423a1c7516cffe36384133ade12572cf709398d /spec/lib/sidebars
parente570267f2f6b326480d284e0164a6464ba4081bc (diff)
Add latest changes from gitlab-org/gitlab@13-12-stable-eev13.12.0-rc42
Diffstat (limited to 'spec/lib/sidebars')
-rw-r--r--spec/lib/sidebars/concerns/container_with_html_options_spec.rb27
-rw-r--r--spec/lib/sidebars/menu_item_spec.rb21
-rw-r--r--spec/lib/sidebars/menu_spec.rb147
-rw-r--r--spec/lib/sidebars/panel_spec.rb127
-rw-r--r--spec/lib/sidebars/projects/context_spec.rb13
-rw-r--r--spec/lib/sidebars/projects/menus/analytics_menu_spec.rb120
-rw-r--r--spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb70
-rw-r--r--spec/lib/sidebars/projects/menus/confluence_menu_spec.rb44
-rw-r--r--spec/lib/sidebars/projects/menus/deployments_menu_spec.rb71
-rw-r--r--spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb40
-rw-r--r--spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb39
-rw-r--r--spec/lib/sidebars/projects/menus/hidden_menu_spec.rb102
-rw-r--r--spec/lib/sidebars/projects/menus/issues_menu_spec.rb86
-rw-r--r--spec/lib/sidebars/projects/menus/labels_menu_spec.rb61
-rw-r--r--spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb85
-rw-r--r--spec/lib/sidebars/projects/menus/members_menu_spec.rb35
-rw-r--r--spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb63
-rw-r--r--spec/lib/sidebars/projects/menus/monitor_menu_spec.rb217
-rw-r--r--spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb143
-rw-r--r--spec/lib/sidebars/projects/menus/project_information_menu_spec.rb74
-rw-r--r--spec/lib/sidebars/projects/menus/repository_menu_spec.rb38
-rw-r--r--spec/lib/sidebars/projects/menus/settings_menu_spec.rb177
-rw-r--r--spec/lib/sidebars/projects/menus/snippets_menu_spec.rb27
-rw-r--r--spec/lib/sidebars/projects/menus/wiki_menu_spec.rb31
-rw-r--r--spec/lib/sidebars/projects/panel_spec.rb42
25 files changed, 1900 insertions, 0 deletions
diff --git a/spec/lib/sidebars/concerns/container_with_html_options_spec.rb b/spec/lib/sidebars/concerns/container_with_html_options_spec.rb
new file mode 100644
index 00000000000..7f834419866
--- /dev/null
+++ b/spec/lib/sidebars/concerns/container_with_html_options_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Concerns::ContainerWithHtmlOptions do
+ subject do
+ Class.new do
+ include Sidebars::Concerns::ContainerWithHtmlOptions
+
+ def title
+ 'Foo'
+ end
+ end.new
+ end
+
+ describe '#container_html_options' do
+ it 'includes by default aria-label attribute' do
+ expect(subject.container_html_options).to eq(aria: { label: 'Foo' })
+ end
+ end
+
+ describe '#collapsed_container_html_options' do
+ it 'includes by default aria-label attribute' do
+ expect(subject.collapsed_container_html_options).to eq(aria: { label: 'Foo' })
+ end
+ end
+end
diff --git a/spec/lib/sidebars/menu_item_spec.rb b/spec/lib/sidebars/menu_item_spec.rb
new file mode 100644
index 00000000000..3adde64f550
--- /dev/null
+++ b/spec/lib/sidebars/menu_item_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::MenuItem do
+ let(:title) { 'foo' }
+ let(:html_options) { {} }
+ let(:menu_item) { described_class.new(title: title, active_routes: {}, link: '', container_html_options: html_options) }
+
+ it 'includes by default aria-label attribute set to the title' do
+ expect(menu_item.container_html_options).to eq({ aria: { label: title } })
+ end
+
+ context 'when aria-label is overridde during initialization' do
+ let(:html_options) { { aria: { label: 'bar' } } }
+
+ it 'sets the aria-label to the new attribute' do
+ expect(menu_item.container_html_options).to eq html_options
+ end
+ end
+end
diff --git a/spec/lib/sidebars/menu_spec.rb b/spec/lib/sidebars/menu_spec.rb
new file mode 100644
index 00000000000..7dcf1940442
--- /dev/null
+++ b/spec/lib/sidebars/menu_spec.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Menu do
+ let(:menu) { described_class.new(context) }
+ let(:context) { Sidebars::Context.new(current_user: nil, container: nil) }
+ let(:nil_menu_item) { Sidebars::NilMenuItem.new(item_id: :foo) }
+
+ describe '#all_active_routes' do
+ it 'gathers all active routes of items and the current menu' do
+ menu.add_item(Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: { path: %w(bar test) }))
+ menu.add_item(Sidebars::MenuItem.new(title: 'foo2', link: 'foo2', active_routes: { controller: 'fooc' }))
+ menu.add_item(Sidebars::MenuItem.new(title: 'foo3', link: 'foo3', active_routes: { controller: 'barc' }))
+ menu.add_item(nil_menu_item)
+
+ allow(menu).to receive(:active_routes).and_return({ path: 'foo' })
+
+ expect(menu).to receive(:renderable_items).and_call_original
+ expect(menu.all_active_routes).to eq({ path: %w(foo bar test), controller: %w(fooc barc) })
+ end
+ end
+
+ describe '#render?' do
+ context 'when the menus has no items' do
+ it 'returns false' do
+ expect(menu.render?).to be false
+ end
+ end
+
+ context 'when the menu has items' do
+ it 'returns true' do
+ menu.add_item(Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}))
+
+ expect(menu.render?).to be true
+ end
+
+ context 'when menu items are NilMenuItem' do
+ it 'returns false' do
+ menu.add_item(nil_menu_item)
+
+ expect(menu.render?).to be false
+ end
+ end
+ end
+ end
+
+ describe '#has_items?' do
+ it 'returns true when there are regular menu items' do
+ menu.add_item(Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}))
+
+ expect(menu.has_items?).to be true
+ end
+
+ it 'returns true when there are nil menu items' do
+ menu.add_item(nil_menu_item)
+
+ expect(menu.has_items?).to be true
+ end
+ end
+
+ describe '#has_renderable_items?' do
+ it 'returns true when there are regular menu items' do
+ menu.add_item(Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}))
+
+ expect(menu.has_renderable_items?).to be true
+ end
+
+ it 'returns false when there are nil menu items' do
+ menu.add_item(nil_menu_item)
+
+ expect(menu.has_renderable_items?).to be false
+ end
+
+ it 'returns true when there are both regular and nil menu items' do
+ menu.add_item(Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}))
+ menu.add_item(nil_menu_item)
+
+ expect(menu.has_renderable_items?).to be true
+ end
+ end
+
+ describe '#renderable_items' do
+ it 'returns only regular menu items' do
+ item = Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {})
+ menu.add_item(item)
+ menu.add_item(nil_menu_item)
+
+ expect(menu.renderable_items.size).to eq 1
+ expect(menu.renderable_items.first).to eq item
+ end
+ end
+
+ describe '#insert_element_before' do
+ let(:item1) { Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}, item_id: :foo1) }
+ let(:item2) { Sidebars::MenuItem.new(title: 'foo2', link: 'foo2', active_routes: {}, item_id: :foo2) }
+ let(:item3) { Sidebars::MenuItem.new(title: 'foo3', link: 'foo3', active_routes: {}, item_id: :foo3) }
+ let(:list) { [item1, item2] }
+
+ it 'adds element before the specific element class' do
+ menu.insert_element_before(list, :foo2, item3)
+
+ expect(list).to eq [item1, item3, item2]
+ end
+
+ it 'does not add nil elements' do
+ menu.insert_element_before(list, :foo2, nil)
+
+ expect(list).to eq [item1, item2]
+ end
+
+ context 'when reference element does not exist' do
+ it 'adds the element to the top of the list' do
+ menu.insert_element_before(list, :non_existent, item3)
+
+ expect(list).to eq [item3, item1, item2]
+ end
+ end
+ end
+
+ describe '#insert_element_after' do
+ let(:item1) { Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}, item_id: :foo1) }
+ let(:item2) { Sidebars::MenuItem.new(title: 'foo2', link: 'foo2', active_routes: {}, item_id: :foo2) }
+ let(:item3) { Sidebars::MenuItem.new(title: 'foo3', link: 'foo3', active_routes: {}, item_id: :foo3) }
+ let(:list) { [item1, item2] }
+
+ it 'adds element after the specific element class' do
+ menu.insert_element_after(list, :foo1, item3)
+
+ expect(list).to eq [item1, item3, item2]
+ end
+
+ it 'does not add nil elements' do
+ menu.insert_element_after(list, :foo1, nil)
+
+ expect(list).to eq [item1, item2]
+ end
+
+ context 'when reference element does not exist' do
+ it 'adds the element to the end of the list' do
+ menu.insert_element_after(list, :non_existent, item3)
+
+ expect(list).to eq [item1, item2, item3]
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/panel_spec.rb b/spec/lib/sidebars/panel_spec.rb
new file mode 100644
index 00000000000..b70a79361d0
--- /dev/null
+++ b/spec/lib/sidebars/panel_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Panel do
+ let(:context) { Sidebars::Context.new(current_user: nil, container: nil) }
+ let(:panel) { Sidebars::Panel.new(context) }
+ let(:menu1) { Sidebars::Menu.new(context) }
+ let(:menu2) { Sidebars::Menu.new(context) }
+
+ describe '#renderable_menus' do
+ it 'returns only renderable menus' do
+ panel.add_menu(menu1)
+ panel.add_menu(menu2)
+
+ allow(menu1).to receive(:render?).and_return(true)
+ allow(menu2).to receive(:render?).and_return(false)
+
+ expect(panel.renderable_menus).to eq([menu1])
+ end
+ end
+
+ describe '#has_renderable_menus?' do
+ it 'returns false when no renderable menus' do
+ expect(panel.has_renderable_menus?).to be false
+ end
+
+ it 'returns true when no renderable menus' do
+ allow(menu1).to receive(:render?).and_return(true)
+
+ panel.add_menu(menu1)
+
+ expect(panel.has_renderable_menus?).to be true
+ end
+ end
+
+ describe '#add_element' do
+ it 'adds the element to the last position of the list' do
+ list = [1, 2]
+
+ panel.add_element(list, 3)
+
+ expect(list).to eq([1, 2, 3])
+ end
+
+ it 'does not add nil elements' do
+ list = []
+
+ panel.add_element(list, nil)
+
+ expect(list).to be_empty
+ end
+ end
+
+ describe '#insert_element_before' do
+ let(:user) { build(:user) }
+ let(:list) { [1, user] }
+
+ it 'adds element before the specific element class' do
+ panel.insert_element_before(list, User, 2)
+
+ expect(list).to eq [1, 2, user]
+ end
+
+ it 'does not add nil elements' do
+ panel.insert_element_before(list, User, nil)
+
+ expect(list).to eq [1, user]
+ end
+
+ context 'when reference element does not exist' do
+ it 'adds the element to the top of the list' do
+ panel.insert_element_before(list, Project, 2)
+
+ expect(list).to eq [2, 1, user]
+ end
+ end
+ end
+
+ describe '#insert_element_after' do
+ let(:user) { build(:user) }
+ let(:list) { [1, user] }
+
+ it 'adds element after the specific element class' do
+ panel.insert_element_after(list, Integer, 2)
+
+ expect(list).to eq [1, 2, user]
+ end
+
+ it 'does not add nil elements' do
+ panel.insert_element_after(list, Integer, nil)
+
+ expect(list).to eq [1, user]
+ end
+
+ context 'when reference element does not exist' do
+ it 'adds the element to the end of the list' do
+ panel.insert_element_after(list, Project, 2)
+
+ expect(list).to eq [1, user, 2]
+ end
+ end
+ end
+
+ describe '#replace_element' do
+ let(:user) { build(:user) }
+ let(:list) { [1, user] }
+
+ it 'replace existing element in the list' do
+ panel.replace_element(list, Integer, 2)
+
+ expect(list).to eq [2, user]
+ end
+
+ it 'does not add nil elements' do
+ panel.replace_element(list, Integer, nil)
+
+ expect(list).to eq [1, user]
+ end
+
+ it 'does not add the element if the other element is not found' do
+ panel.replace_element(list, Project, 2)
+
+ expect(list).to eq [1, user]
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/context_spec.rb b/spec/lib/sidebars/projects/context_spec.rb
new file mode 100644
index 00000000000..44578ae1583
--- /dev/null
+++ b/spec/lib/sidebars/projects/context_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Context do
+ let(:project) { build(:project) }
+
+ subject { described_class.new(current_user: nil, container: project) }
+
+ it 'sets project attribute reader' do
+ expect(subject.project).to eq(project)
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb b/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb
new file mode 100644
index 00000000000..ed94b81520e
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/analytics_menu_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::AnalyticsMenu do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: project.repository.root_ref) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'whe user cannot read analytics' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to be false
+ end
+ end
+
+ context 'whe user can read analytics' do
+ it 'returns true' do
+ expect(subject.render?).to be true
+ end
+
+ context 'when menu does not have any menu items' do
+ it 'returns false' do
+ allow(subject).to receive(:has_renderable_items?).and_return(false)
+
+ expect(subject.render?).to be false
+ end
+ end
+
+ context 'when menu has menu items' do
+ it 'returns true' do
+ expect(subject.render?).to be true
+ end
+ end
+ end
+ end
+
+ describe '#link' do
+ it 'returns link to the value stream page' do
+ expect(subject.link).to include('/-/value_stream_analytics')
+ end
+
+ context 'when Value Stream is not visible' do
+ it 'returns link to the the first visible menu item' do
+ allow(subject).to receive(:cycle_analytics_menu_item).and_return(double(render?: false))
+
+ expect(subject.link).to eq subject.renderable_items.first.link
+ end
+ end
+ end
+
+ describe 'Menu items' do
+ subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ describe 'CI/CD' do
+ let(:item_id) { :ci_cd_analytics }
+
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the project repository is empty' do
+ before do
+ allow(project).to receive(:empty_repo?).and_return(true)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ describe 'when builds access level is DISABLED' do
+ before do
+ project.project_feature.update!(builds_access_level: Featurable::DISABLED)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ describe 'Repository' do
+ let(:item_id) { :repository_analytics }
+
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the project repository is empty' do
+ before do
+ allow(project).to receive(:empty_repo?).and_return(true)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ describe 'Value Stream' do
+ let(:item_id) { :cycle_analytics }
+
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb b/spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb
new file mode 100644
index 00000000000..dee2716e4c2
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/ci_cd_menu_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::CiCdMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:can_view_pipeline_editor) { true }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: 'master', can_view_pipeline_editor: can_view_pipeline_editor) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when user cannot read builds' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when user can read builds' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+ end
+
+ describe 'Menu items' do
+ subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ describe 'Pipelines Editor' do
+ let(:item_id) { :pipelines_editor }
+
+ context 'when user cannot view pipeline editor' do
+ let(:can_view_pipeline_editor) { false }
+
+ it 'does not include pipeline editor menu item' do
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when user can view pipeline editor' do
+ it 'includes pipeline editor menu item' do
+ is_expected.not_to be_nil
+ end
+ end
+ end
+
+ describe 'Artifacts' do
+ let(:item_id) { :artifacts }
+
+ context 'when feature flag :artifacts_management_page is disabled' do
+ it 'does not include artifacts menu item' do
+ stub_feature_flags(artifacts_management_page: false)
+
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when feature flag :artifacts_management_page is enabled' do
+ it 'includes artifacts menu item' do
+ stub_feature_flags(artifacts_management_page: true)
+
+ is_expected.not_to be_nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb b/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb
new file mode 100644
index 00000000000..0ecb328efd1
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/confluence_menu_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ConfluenceMenu do
+ let_it_be_with_refind(:project) { create(:project, has_external_wiki: true) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ describe 'render?' do
+ context 'when Confluence integration is not present' do
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when Confluence integration is present' do
+ let!(:confluence) { create(:confluence_service, project: project, active: active) }
+
+ context 'when integration is disabled' do
+ let(:active) { false }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when issues integration is enabled' do
+ let(:active) { true }
+
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+
+ it 'does not contain any sub menu' do
+ expect(subject.has_items?).to be false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb b/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb
new file mode 100644
index 00000000000..4a60dfde674
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::DeploymentsMenu do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ describe '#render?' do
+ subject { described_class.new(context) }
+
+ context 'when menu does not have any menu items' do
+ it 'returns false' do
+ allow(subject).to receive(:has_renderable_items?).and_return(false)
+
+ expect(subject.render?).to be false
+ end
+ end
+
+ context 'when menu has menu items' do
+ it 'returns true' do
+ expect(subject.render?).to be true
+ end
+ end
+ end
+
+ describe 'Menu Items' do
+ subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ shared_examples 'access rights checks' do
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ shared_examples 'feature flag :sidebar_refactor disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ describe 'Feature Flags' do
+ let(:item_id) { :feature_flags }
+
+ it_behaves_like 'access rights checks'
+ it_behaves_like 'feature flag :sidebar_refactor disabled'
+ end
+
+ describe 'Environments' do
+ let(:item_id) { :environments }
+
+ it_behaves_like 'access rights checks'
+ it_behaves_like 'feature flag :sidebar_refactor disabled'
+ end
+
+ describe 'Releases' do
+ let(:item_id) { :releases }
+
+ it_behaves_like 'access rights checks'
+ it_behaves_like 'feature flag :sidebar_refactor disabled'
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb b/spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb
new file mode 100644
index 00000000000..5d62eebca1c
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ExternalIssueTrackerMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:jira_issues_integration_active) { false }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, jira_issues_integration: jira_issues_integration_active) }
+
+ subject { described_class.new(context) }
+
+ it 'does not contain any sub menu' do
+ expect(subject.has_items?).to be false
+ end
+
+ describe '#render?' do
+ before do
+ expect(subject).to receive(:external_issue_tracker).and_return(external_issue_tracker).at_least(1)
+ end
+
+ context 'when active external issue tracker' do
+ let(:external_issue_tracker) { build(:custom_issue_tracker_service, project: project) }
+
+ context 'is present' do
+ it 'returns true' do
+ expect(subject.render?).to be_truthy
+ end
+ end
+
+ context 'is not present' do
+ let(:external_issue_tracker) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to be_falsey
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb b/spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb
new file mode 100644
index 00000000000..19efd2bbd6b
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ExternalWikiMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ it 'does not contain any sub menu' do
+ expect(subject.has_items?).to be false
+ end
+
+ describe '#render?' do
+ before do
+ expect(subject).to receive(:external_wiki).and_return(external_wiki).at_least(1)
+ end
+
+ context 'when active external issue tracker' do
+ let(:external_wiki) { build(:external_wiki_service, project: project) }
+
+ context 'is present' do
+ it 'returns true' do
+ expect(subject.render?).to be_truthy
+ end
+ end
+
+ context 'is not present' do
+ let(:external_wiki) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to be_falsey
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb b/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb
new file mode 100644
index 00000000000..44013898721
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::HiddenMenu do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: project.repository.root_ref) }
+
+ describe '#render?' do
+ subject { described_class.new(context) }
+
+ context 'when menu does not have any menu items' do
+ it 'returns false' do
+ allow(subject).to receive(:has_renderable_items?).and_return(false)
+
+ expect(subject.render?).to be false
+ end
+ end
+
+ context 'when menu has menu items' do
+ it 'returns true' do
+ expect(subject.render?).to be true
+ end
+ end
+ end
+
+ describe 'Menu items' do
+ subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ shared_examples 'access rights checks' do
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ describe 'Activity' do
+ let(:item_id) { :activity }
+
+ context 'when user has access to the project' do
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the user is not present' do
+ let(:user) { nil }
+
+ specify { is_expected.not_to be_nil }
+ end
+ end
+ end
+
+ describe 'Graph' do
+ let(:item_id) { :graph }
+
+ context 'when project repository is empty' do
+ before do
+ allow(project).to receive(:empty_repo?).and_return(true)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'New Issue' do
+ let(:item_id) { :new_issue }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Jobs' do
+ let(:item_id) { :jobs }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Commits' do
+ let(:item_id) { :commits }
+
+ context 'when project repository is empty' do
+ before do
+ allow(project).to receive(:empty_repo?).and_return(true)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Issue Boards' do
+ let(:item_id) { :issue_boards }
+
+ it_behaves_like 'access rights checks'
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/issues_menu_spec.rb b/spec/lib/sidebars/projects/menus/issues_menu_spec.rb
new file mode 100644
index 00000000000..ac62cd7594a
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/issues_menu_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::IssuesMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when user can read issues' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+
+ context 'when user cannot read issues' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+ end
+
+ describe '#has_pill?' do
+ context 'when issues feature is enabled' do
+ it 'returns true' do
+ expect(subject.has_pill?).to eq true
+ end
+ end
+
+ context 'when issue feature is disabled' do
+ it 'returns false' do
+ allow(project).to receive(:issues_enabled?).and_return(false)
+
+ expect(subject.has_pill?).to eq false
+ end
+ end
+ end
+
+ describe '#pill_count' do
+ it 'returns zero when there are no open issues' do
+ expect(subject.pill_count).to eq 0
+ end
+
+ it 'memoizes the query' do
+ subject.pill_count
+
+ control = ActiveRecord::QueryRecorder.new do
+ subject.pill_count
+ end
+
+ expect(control.count).to eq 0
+ end
+
+ context 'when there are open issues' do
+ it 'returns the number of open issues' do
+ create_list(:issue, 2, :opened, project: project)
+ create(:issue, :closed, project: project)
+
+ expect(subject.pill_count).to eq 2
+ end
+ end
+ end
+
+ describe 'Menu Items' do
+ subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ describe 'Labels' do
+ let(:item_id) { :labels }
+
+ specify { is_expected.to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ specify { is_expected.not_to be_nil }
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/labels_menu_spec.rb b/spec/lib/sidebars/projects/menus/labels_menu_spec.rb
new file mode 100644
index 00000000000..e1420f9e61b
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/labels_menu_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::LabelsMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ it 'does not contain any sub menu' do
+ expect(subject.has_items?).to eq false
+ end
+
+ describe '#render?' do
+ let(:issues_enabled) { true }
+
+ before do
+ allow(project).to receive(:issues_enabled?).and_return(issues_enabled)
+ end
+
+ context 'when feature flag :sidebar_refactor is enabled' do
+ let(:issues_enabled) { false }
+
+ it 'returns false' do
+ expect(subject.render?).to be_falsey
+ end
+ end
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ context 'when user can read labels' do
+ context 'when issues feature is enabled' do
+ it 'returns false' do
+ expect(subject.render?).to be_falsey
+ end
+ end
+
+ context 'when issues feature is disabled' do
+ let(:issues_enabled) { false }
+
+ it 'returns true' do
+ expect(subject.render?).to be_truthy
+ end
+ end
+ end
+
+ context 'when user cannot read labels' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to be_falsey
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb b/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb
new file mode 100644
index 00000000000..ef5ae550551
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::LearnGitlabMenu do
+ let_it_be(:project) { build(:project) }
+ let_it_be(:experiment_enabled) { true }
+ let_it_be(:tracking_category) { 'Growth::Activation::Experiment::LearnGitLabB' }
+
+ let(:context) do
+ Sidebars::Projects::Context.new(
+ current_user: nil,
+ container: project,
+ learn_gitlab_experiment_enabled: experiment_enabled,
+ learn_gitlab_experiment_tracking_category: tracking_category
+ )
+ end
+
+ subject { described_class.new(context) }
+
+ it 'does not contain any sub menu' do
+ expect(subject.has_items?).to be false
+ end
+
+ describe '#nav_link_html_options' do
+ let_it_be(:data_tracking) do
+ {
+ class: 'home',
+ data: {
+ track_action: 'click_menu',
+ track_property: tracking_category,
+ track_label: 'learn_gitlab'
+ }
+ }
+ end
+
+ specify do
+ expect(subject.nav_link_html_options).to eq(data_tracking)
+ end
+ end
+
+ describe '#render?' do
+ context 'when learn gitlab experiment is enabled' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+
+ context 'when learn gitlab experiment is disabled' do
+ let(:experiment_enabled) { false }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+ end
+
+ describe '#has_pill?' do
+ context 'when learn gitlab experiment is enabled' do
+ it 'returns true' do
+ expect(subject.has_pill?).to eq true
+ end
+ end
+
+ context 'when learn gitlab experiment is disabled' do
+ let(:experiment_enabled) { false }
+
+ it 'returns false' do
+ expect(subject.has_pill?).to eq false
+ end
+ end
+ end
+
+ describe '#pill_count' do
+ before do
+ expect_next_instance_of(LearnGitlab::Onboarding) do |onboarding|
+ expect(onboarding).to receive(:completed_percentage).and_return(20)
+ end
+ end
+
+ it 'returns pill count' do
+ expect(subject.pill_count).to eq '20%'
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/members_menu_spec.rb b/spec/lib/sidebars/projects/menus/members_menu_spec.rb
new file mode 100644
index 00000000000..dcc085c2957
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/members_menu_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::MembersMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+
+ context 'when user cannot access members' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb b/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb
new file mode 100644
index 00000000000..cef303fb068
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::MergeRequestsMenu do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when repository is not present' do
+ let(:project) { build(:project) }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when repository is present' do
+ context 'when user can read merge requests' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+
+ context 'when user cannot read merge requests' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+ end
+ end
+
+ describe '#pill_count' do
+ it 'returns zero when there are no open merge requests' do
+ expect(subject.pill_count).to eq 0
+ end
+
+ it 'memoizes the query' do
+ subject.pill_count
+
+ control = ActiveRecord::QueryRecorder.new do
+ subject.pill_count
+ end
+
+ expect(control.count).to eq 0
+ end
+
+ context 'when there are open merge requests' do
+ it 'returns the number of open merge requests' do
+ create_list(:merge_request, 2, :unique_branches, source_project: project, author: user, state: :opened)
+ create(:merge_request, source_project: project, state: :merged)
+
+ expect(subject.pill_count).to eq 2
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb b/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb
new file mode 100644
index 00000000000..93618fa3321
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb
@@ -0,0 +1,217 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::MonitorMenu do
+ let_it_be_with_refind(:project) { create(:project) }
+
+ let(:user) { project.owner }
+ let(:show_cluster_hint) { true }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, show_cluster_hint: show_cluster_hint) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when operations feature is disabled' do
+ it 'returns false' do
+ project.project_feature.update!(operations_access_level: Featurable::DISABLED)
+
+ expect(subject.render?).to be false
+ end
+ end
+
+ context 'when operation feature is enabled' do
+ context 'when menu does not have any renderable menu items' do
+ it 'returns false' do
+ allow(subject).to receive(:has_renderable_items?).and_return(false)
+
+ expect(subject.render?).to be false
+ end
+ end
+
+ context 'when menu has menu items' do
+ it 'returns true' do
+ expect(subject.render?).to be true
+ end
+ end
+ end
+ end
+
+ describe '#title' do
+ it 'returns "Monitor"' do
+ expect(subject.title).to eq 'Monitor'
+ end
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ it 'returns "Operations"' do
+ stub_feature_flags(sidebar_refactor: false)
+
+ expect(subject.title).to eq 'Operations'
+ end
+ end
+ end
+
+ describe '#extra_container_html_options' do
+ it 'returns "shortcuts-monitor"' do
+ expect(subject.extra_container_html_options).to eq(class: 'shortcuts-monitor')
+ end
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ it 'returns "shortcuts-operations"' do
+ stub_feature_flags(sidebar_refactor: false)
+
+ expect(subject.extra_container_html_options).to eq(class: 'shortcuts-operations')
+ end
+ end
+ end
+
+ describe '#link' do
+ context 'when metrics dashboard is visible' do
+ it 'returns link to the metrics dashboard page' do
+ expect(subject.link).to include('/-/environments/metrics')
+ end
+ end
+
+ context 'when metrics dashboard is not visible' do
+ it 'returns link to the feature flags page' do
+ project.project_feature.update!(operations_access_level: Featurable::DISABLED)
+
+ expect(subject.link).to include('/-/feature_flags')
+ end
+ end
+ end
+
+ context 'Menu items' do
+ subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ shared_examples 'access rights checks' do
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ describe 'Metrics Dashboard' do
+ let(:item_id) { :metrics }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Logs' do
+ let(:item_id) { :logs }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Tracing' do
+ let(:item_id) { :tracing }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Error Tracking' do
+ let(:item_id) { :error_tracking }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Alert Management' do
+ let(:item_id) { :alert_management }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Incidents' do
+ let(:item_id) { :incidents }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Serverless' do
+ let(:item_id) { :serverless }
+
+ specify { is_expected.to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ it_behaves_like 'access rights checks'
+ end
+ end
+
+ describe 'Terraform' do
+ let(:item_id) { :terraform }
+
+ specify { is_expected.to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ it_behaves_like 'access rights checks'
+ end
+ end
+
+ describe 'Kubernetes' do
+ let(:item_id) { :kubernetes }
+
+ specify { is_expected.to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ it_behaves_like 'access rights checks'
+ end
+ end
+
+ describe 'Environments' do
+ let(:item_id) { :environments }
+
+ specify { is_expected.to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ it_behaves_like 'access rights checks'
+ end
+ end
+
+ describe 'Feature Flags' do
+ let(:item_id) { :feature_flags }
+
+ specify { is_expected.to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ it_behaves_like 'access rights checks'
+ end
+ end
+
+ describe 'Product Analytics' do
+ let(:item_id) { :product_analytics }
+
+ specify { is_expected.not_to be_nil }
+
+ describe 'when feature flag :product_analytics is disabled' do
+ specify do
+ stub_feature_flags(product_analytics: false)
+
+ is_expected.to be_nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
new file mode 100644
index 00000000000..731dd5eca23
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
@@ -0,0 +1,143 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when menu does not have any menu item to show' do
+ it 'returns false' do
+ allow(subject).to receive(:has_renderable_items?).and_return(false)
+
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when menu has menu items to show' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+ end
+
+ describe '#link' do
+ let(:registry_enabled) { true }
+ let(:packages_enabled) { true }
+
+ before do
+ stub_container_registry_config(enabled: registry_enabled)
+ stub_config(packages: { enabled: packages_enabled })
+ end
+
+ context 'when Packages Registry is visible' do
+ it 'menu link points to Packages Registry page' do
+ expect(subject.link).to eq described_class.new(context).renderable_items.find { |i| i.item_id == :packages_registry }.link
+ end
+ end
+
+ context 'when Packages Registry is not visible' do
+ let(:packages_enabled) { false }
+
+ it 'menu link points to Container Registry page' do
+ expect(subject.link).to eq described_class.new(context).renderable_items.find { |i| i.item_id == :container_registry }.link
+ end
+
+ context 'when Container Registry is not visible' do
+ let(:registry_enabled) { false }
+
+ it 'menu link points to Infrastructure Registry page' do
+ expect(subject.link).to eq described_class.new(context).renderable_items.find { |i| i.item_id == :infrastructure_registry }.link
+ end
+ end
+ end
+ end
+
+ describe 'Menu items' do
+ subject { described_class.new(context).renderable_items.find { |i| i.item_id == item_id } }
+
+ describe 'Packages Registry' do
+ let(:item_id) { :packages_registry }
+
+ context 'when user can read packages' do
+ context 'when config package setting is disabled' do
+ it 'the menu item is not added to list of menu items' do
+ stub_config(packages: { enabled: false })
+
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when config package setting is enabled' do
+ it 'the menu item is added to list of menu items' do
+ stub_config(packages: { enabled: true })
+
+ is_expected.not_to be_nil
+ end
+ end
+ end
+
+ context 'when user cannot read packages' do
+ let(:user) { nil }
+
+ it 'the menu item is not added to list of menu items' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ describe 'Container Registry' do
+ let(:item_id) { :container_registry }
+
+ context 'when user can read container images' do
+ context 'when config registry setting is disabled' do
+ it 'the menu item is not added to list of menu items' do
+ stub_container_registry_config(enabled: false)
+
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when config registry setting is enabled' do
+ it 'the menu item is added to list of menu items' do
+ stub_container_registry_config(enabled: true)
+
+ is_expected.not_to be_nil
+ end
+ end
+ end
+
+ context 'when user cannot read container images' do
+ let(:user) { nil }
+
+ it 'the menu item is not added to list of menu items' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ describe 'Infrastructure Registry' do
+ let(:item_id) { :infrastructure_registry }
+
+ context 'when feature flag :infrastructure_registry_page is enabled' do
+ it 'the menu item is added to list of menu items' do
+ stub_feature_flags(infrastructure_registry_page: true)
+
+ is_expected.not_to be_nil
+ end
+ end
+
+ context 'when feature flag :infrastructure_registry_page is disabled' do
+ it 'the menu item is not added to list of menu items' do
+ stub_feature_flags(infrastructure_registry_page: false)
+
+ is_expected.to be_nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb b/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb
new file mode 100644
index 00000000000..b50bf0f4bf1
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ProjectInformationMenu do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ describe 'Menu Items' do
+ subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } }
+
+ describe 'Releases' do
+ let(:item_id) { :releases }
+
+ specify { is_expected.to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ context 'when project repository is empty' do
+ it 'does not include releases menu item' do
+ allow(project).to receive(:empty_repo?).and_return(true)
+
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when project repository is not empty' do
+ context 'when user can download code' do
+ specify { is_expected.not_to be_nil }
+ end
+
+ context 'when user cannot download code' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+ end
+ end
+
+ describe 'Labels' do
+ let(:item_id) { :labels }
+
+ specify { is_expected.not_to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ describe 'Members' do
+ let(:item_id) { :members }
+
+ specify { is_expected.not_to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb
new file mode 100644
index 00000000000..554a4e3f532
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::RepositoryMenu do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: 'master') }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when project repository is empty' do
+ it 'returns false' do
+ allow(project).to receive(:empty_repo?).and_return(true)
+
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when project repository is not empty' do
+ context 'when user can download code' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+
+ context 'when user cannot download code' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/settings_menu_spec.rb b/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
new file mode 100644
index 00000000000..88f2df6cd84
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/settings_menu_spec.rb
@@ -0,0 +1,177 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::SettingsMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ it 'returns false when menu does not have any menu items' do
+ allow(subject).to receive(:has_renderable_items?).and_return(false)
+
+ expect(subject.render?).to be false
+ end
+ end
+
+ describe 'Menu items' do
+ subject { described_class.new(context).renderable_items.find { |e| e.item_id == item_id } }
+
+ shared_examples 'access rights checks' do
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ describe 'General' do
+ let(:item_id) { :general }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Integrations' do
+ let(:item_id) { :integrations }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Webhooks' do
+ let(:item_id) { :webhooks }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Access Tokens' do
+ let(:item_id) { :access_tokens }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'Repository' do
+ let(:item_id) { :repository }
+
+ it_behaves_like 'access rights checks'
+ end
+
+ describe 'CI/CD' do
+ let(:item_id) { :ci_cd }
+
+ describe 'when project is archived' do
+ before do
+ allow(project).to receive(:archived?).and_return(true)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ describe 'when project is not archived' do
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+ end
+
+ describe 'Monitor' do
+ let(:item_id) { :monitor }
+
+ describe 'when project is archived' do
+ before do
+ allow(project).to receive(:archived?).and_return(true)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ describe 'when project is not archived' do
+ specify { is_expected.not_to be_nil }
+
+ specify { expect(subject.title).to eq 'Monitor' }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ specify { expect(subject.title).to eq 'Operations' }
+ end
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+ end
+
+ describe 'Pages' do
+ let(:item_id) { :pages }
+
+ before do
+ allow(project).to receive(:pages_available?).and_return(pages_enabled)
+ end
+
+ describe 'when pages are enabled' do
+ let(:pages_enabled) { true }
+
+ specify { is_expected.not_to be_nil }
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ describe 'when pages are not enabled' do
+ let(:pages_enabled) { false }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+
+ describe 'Packages & Registries' do
+ let(:item_id) { :packages_and_registries }
+
+ before do
+ stub_container_registry_config(enabled: container_enabled)
+ end
+
+ describe 'when config registry setting is disabled' do
+ let(:container_enabled) { false }
+
+ specify { is_expected.to be_nil }
+ end
+
+ describe 'when config registry setting is enabled' do
+ let(:container_enabled) { true }
+
+ specify { is_expected.not_to be_nil }
+
+ context 'when feature flag :sidebar_refactor is disabled' do
+ before do
+ stub_feature_flags(sidebar_refactor: false)
+ end
+
+ specify { is_expected.to be_nil }
+ end
+
+ describe 'when the user does not have access' do
+ let(:user) { nil }
+
+ specify { is_expected.to be_nil }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb b/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb
new file mode 100644
index 00000000000..af219e4a742
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::SnippetsMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when user cannot access snippets' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when user can access snippets' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb b/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb
new file mode 100644
index 00000000000..41447ee24a9
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::WikiMenu do
+ let(:project) { build(:project) }
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ it 'does not contain any sub menu' do
+ expect(subject.has_items?).to be false
+ end
+
+ describe '#render?' do
+ context 'when user can access project wiki' do
+ it 'returns true' do
+ expect(subject.render?).to be true
+ end
+
+ context 'when user cannot access project wiki' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to be false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/projects/panel_spec.rb b/spec/lib/sidebars/projects/panel_spec.rb
new file mode 100644
index 00000000000..51d37bf69ea
--- /dev/null
+++ b/spec/lib/sidebars/projects/panel_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Panel do
+ let(:project) { build(:project) }
+ let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project) }
+
+ subject { described_class.new(context) }
+
+ it 'has a scope menu' do
+ expect(subject.scope_menu).to be_a(Sidebars::Projects::Menus::ScopeMenu)
+ end
+
+ context 'Confluence menu item' do
+ subject { described_class.new(context).instance_variable_get(:@menus) }
+
+ context 'when integration is present and active' do
+ let_it_be(:confluence) { create(:confluence_service, active: true) }
+
+ let(:project) { confluence.project }
+
+ it 'contains Confluence menu item' do
+ expect(subject.index { |i| i.is_a?(Sidebars::Projects::Menus::ConfluenceMenu) }).not_to be_nil
+ end
+
+ it 'does not contain Wiki menu item' do
+ expect(subject.index { |i| i.is_a?(Sidebars::Projects::Menus::WikiMenu) }).to be_nil
+ end
+ end
+
+ context 'when integration is not present' do
+ it 'does not contain Confluence menu item' do
+ expect(subject.index { |i| i.is_a?(Sidebars::Projects::Menus::ConfluenceMenu) }).to be_nil
+ end
+
+ it 'contains Wiki menu item' do
+ expect(subject.index { |i| i.is_a?(Sidebars::Projects::Menus::WikiMenu) }).not_to be_nil
+ end
+ end
+ end
+end