diff options
Diffstat (limited to 'spec/lib/sidebars')
56 files changed, 1142 insertions, 135 deletions
diff --git a/spec/lib/sidebars/concerns/super_sidebar_panel_spec.rb b/spec/lib/sidebars/concerns/super_sidebar_panel_spec.rb new file mode 100644 index 00000000000..f33cb4ab7f6 --- /dev/null +++ b/spec/lib/sidebars/concerns/super_sidebar_panel_spec.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +RSpec.describe Sidebars::Concerns::SuperSidebarPanel, feature_category: :navigation do + let(:menu_class_foo) { Class.new(Sidebars::Menu) } + let(:menu_foo) { menu_class_foo.new({}) } + + let(:menu_class_bar) do + Class.new(Sidebars::Menu) do + def title + "Bar" + end + + def pick_into_super_sidebar? + true + end + end + end + + let(:menu_bar) { menu_class_bar.new({}) } + + subject do + Class.new(Sidebars::Panel) do + include Sidebars::Concerns::SuperSidebarPanel + end.new({}) + end + + before do + allow(menu_foo).to receive(:render?).and_return(true) + allow(menu_bar).to receive(:render?).and_return(true) + end + + describe '#pick_from_old_menus' do + it 'removes items with #pick_into_super_sidebar? from a list and adds them to the panel menus' do + old_menus = [menu_foo, menu_bar] + + subject.pick_from_old_menus(old_menus) + + expect(old_menus).to include(menu_foo) + expect(subject.renderable_menus).not_to include(menu_foo) + + expect(old_menus).not_to include(menu_bar) + expect(subject.renderable_menus).to include(menu_bar) + end + end + + describe '#transform_old_menus' do + let(:uncategorized_menu) { ::Sidebars::UncategorizedMenu.new({}) } + + let(:menu_item) do + Sidebars::MenuItem.new(title: 'foo3', link: 'foo3', active_routes: { controller: 'barc' }, + super_sidebar_parent: menu_class_foo) + end + + let(:nil_menu_item) { Sidebars::NilMenuItem.new(item_id: :nil_item) } + let(:existing_item) do + Sidebars::MenuItem.new( + item_id: :exists, + title: 'Existing item', + link: 'foo2', + active_routes: { controller: 'foo2' } + ) + end + + let(:current_menus) { [menu_foo, uncategorized_menu] } + + before do + allow(menu_bar).to receive(:serialize_as_menu_item_args).and_return(nil) + menu_foo.add_item(existing_item) + end + + context 'for Menus with Menu Items' do + before do + menu_bar.add_item(menu_item) + menu_bar.add_item(nil_menu_item) + end + + it 'adds Menu Items to defined super_sidebar_parent' do + subject.transform_old_menus(current_menus, menu_bar) + + expect(menu_foo.renderable_items).to eq([existing_item, menu_item]) + expect(uncategorized_menu.renderable_items).to eq([]) + end + + it 'adds Menu Items to defined super_sidebar_parent, before super_sidebar_before' do + allow(menu_item).to receive(:super_sidebar_before).and_return(:exists) + subject.transform_old_menus(current_menus, menu_bar) + + expect(menu_foo.renderable_items).to eq([menu_item, existing_item]) + expect(uncategorized_menu.renderable_items).to eq([]) + end + + it 'considers Menu Items uncategorized if super_sidebar_parent is nil' do + allow(menu_item).to receive(:super_sidebar_parent).and_return(nil) + subject.transform_old_menus(current_menus, menu_bar) + + expect(menu_foo.renderable_items).to eq([existing_item]) + expect(uncategorized_menu.renderable_items).to eq([menu_item]) + end + + it 'considers Menu Items uncategorized if super_sidebar_parent cannot be found' do + allow(menu_item).to receive(:super_sidebar_parent).and_return(menu_class_bar) + subject.transform_old_menus(current_menus, menu_bar) + + expect(menu_foo.renderable_items).to eq([existing_item]) + expect(uncategorized_menu.renderable_items).to eq([menu_item]) + end + + it 'considers Menu Items deleted if super_sidebar_parent is Sidebars::NilMenuItem' do + allow(menu_item).to receive(:super_sidebar_parent).and_return(::Sidebars::NilMenuItem) + subject.transform_old_menus(current_menus, menu_bar) + + expect(menu_foo.renderable_items).to eq([existing_item]) + expect(uncategorized_menu.renderable_items).to eq([]) + end + end + + it 'converts "solo" top-level Menu entry to Menu Item' do + allow(Sidebars::MenuItem).to receive(:new).and_return(menu_item) + allow(menu_bar).to receive(:serialize_as_menu_item_args).and_return({}) + + subject.transform_old_menus(current_menus, menu_bar) + + expect(menu_foo.renderable_items).to eq([existing_item, menu_item]) + expect(uncategorized_menu.renderable_items).to eq([]) + end + + it 'drops "solo" top-level Menu entries, if they serialize to nil' do + allow(Sidebars::MenuItem).to receive(:new).and_return(menu_item) + allow(menu_bar).to receive(:serialize_as_menu_item_args).and_return(nil) + + subject.transform_old_menus(current_menus, menu_bar) + + expect(menu_foo.renderable_items).to eq([existing_item]) + expect(uncategorized_menu.renderable_items).to eq([]) + end + end +end diff --git a/spec/lib/sidebars/groups/menus/group_information_menu_spec.rb b/spec/lib/sidebars/groups/menus/group_information_menu_spec.rb index 1b27db53b6f..4a0301e2f2d 100644 --- a/spec/lib/sidebars/groups/menus/group_information_menu_spec.rb +++ b/spec/lib/sidebars/groups/menus/group_information_menu_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Groups::Menus::GroupInformationMenu do +RSpec.describe Sidebars::Groups::Menus::GroupInformationMenu, feature_category: :navigation do let_it_be(:owner) { create(:user) } let_it_be(:root_group) do build(:group, :private).tap do |g| @@ -14,6 +14,10 @@ RSpec.describe Sidebars::Groups::Menus::GroupInformationMenu do let(:user) { owner } let(:context) { Sidebars::Groups::Context.new(current_user: user, container: group) } + it_behaves_like 'not serializable as super_sidebar_menu_args' do + let(:menu) { described_class.new(context) } + end + describe '#title' do subject { described_class.new(context).title } diff --git a/spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb b/spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb deleted file mode 100644 index a79e5182f45..00000000000 --- a/spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb +++ /dev/null @@ -1,55 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Sidebars::Groups::Menus::InviteTeamMembersMenu do - let_it_be(:owner) { create(:user) } - let_it_be(:guest) { create(:user) } - let_it_be(:group) do - build(:group).tap do |g| - g.add_owner(owner) - end - end - - let(:context) { Sidebars::Groups::Context.new(current_user: owner, container: group) } - - subject(:invite_menu) { described_class.new(context) } - - context 'when the group is viewed by an owner of the group' do - describe '#render?' do - it 'renders the Invite team members link' do - expect(invite_menu.render?).to eq(true) - end - - context 'when the group already has at least 2 members' do - before do - group.add_guest(guest) - end - - it 'does not render the link' do - expect(invite_menu.render?).to eq(false) - end - end - end - - describe '#title' do - it 'displays the correct Invite team members text for the link in the side nav' do - expect(invite_menu.title).to eq('Invite members') - end - end - end - - context 'when the group is viewed by a guest user without admin permissions' do - let(:context) { Sidebars::Groups::Context.new(current_user: guest, container: group) } - - before do - group.add_guest(guest) - end - - describe '#render?' do - it 'does not render the link' do - expect(subject.render?).to eq(false) - end - end - end -end diff --git a/spec/lib/sidebars/groups/menus/issues_menu_spec.rb b/spec/lib/sidebars/groups/menus/issues_menu_spec.rb index 3d55eb3af40..ceeda4a7ac3 100644 --- a/spec/lib/sidebars/groups/menus/issues_menu_spec.rb +++ b/spec/lib/sidebars/groups/menus/issues_menu_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Groups::Menus::IssuesMenu do +RSpec.describe Sidebars::Groups::Menus::IssuesMenu, feature_category: :navigation do let_it_be(:owner) { create(:user) } let_it_be(:group) do build(:group, :private).tap do |g| @@ -51,4 +51,17 @@ RSpec.describe Sidebars::Groups::Menus::IssuesMenu do it_behaves_like 'pill_count formatted results' do let(:count_service) { ::Groups::OpenIssuesCountService } end + + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:extra_attrs) do + { + item_id: :group_issue_list, + active_routes: { path: 'groups#issues' }, + sprite_icon: 'issues', + pill_count: menu.pill_count, + has_pill: menu.has_pill?, + super_sidebar_parent: ::Sidebars::StaticMenu + } + end + end end diff --git a/spec/lib/sidebars/groups/menus/kubernetes_menu_spec.rb b/spec/lib/sidebars/groups/menus/kubernetes_menu_spec.rb index 5bf8be9d6e5..8eb9a22e3e1 100644 --- a/spec/lib/sidebars/groups/menus/kubernetes_menu_spec.rb +++ b/spec/lib/sidebars/groups/menus/kubernetes_menu_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Groups::Menus::KubernetesMenu, :request_store do +RSpec.describe Sidebars::Groups::Menus::KubernetesMenu, :request_store, feature_category: :navigation do let_it_be(:owner) { create(:user) } let_it_be(:group) do build(:group, :private).tap do |g| @@ -14,6 +14,15 @@ RSpec.describe Sidebars::Groups::Menus::KubernetesMenu, :request_store do let(:context) { Sidebars::Groups::Context.new(current_user: user, container: group) } let(:menu) { described_class.new(context) } + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:extra_attrs) do + { + super_sidebar_parent: Sidebars::Groups::SuperSidebarMenus::OperationsMenu, + item_id: :group_kubernetes_clusters + } + end + end + describe '#render?' do context 'when user can read clusters' do it 'returns true' do diff --git a/spec/lib/sidebars/groups/menus/merge_requests_menu_spec.rb b/spec/lib/sidebars/groups/menus/merge_requests_menu_spec.rb index 3aceff29d6d..72f85f7930a 100644 --- a/spec/lib/sidebars/groups/menus/merge_requests_menu_spec.rb +++ b/spec/lib/sidebars/groups/menus/merge_requests_menu_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Groups::Menus::MergeRequestsMenu do +RSpec.describe Sidebars::Groups::Menus::MergeRequestsMenu, feature_category: :navigation do let_it_be(:owner) { create(:user) } let_it_be(:group) do build(:group, :private).tap do |g| @@ -33,4 +33,16 @@ RSpec.describe Sidebars::Groups::Menus::MergeRequestsMenu do it_behaves_like 'pill_count formatted results' do let(:count_service) { ::Groups::MergeRequestsCountService } end + + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:extra_attrs) do + { + item_id: :group_merge_request_list, + sprite_icon: 'git-merge', + pill_count: menu.pill_count, + has_pill: menu.has_pill?, + super_sidebar_parent: ::Sidebars::StaticMenu + } + end + end end diff --git a/spec/lib/sidebars/groups/menus/observability_menu_spec.rb b/spec/lib/sidebars/groups/menus/observability_menu_spec.rb index 5b993cd6f28..20af8ea00be 100644 --- a/spec/lib/sidebars/groups/menus/observability_menu_spec.rb +++ b/spec/lib/sidebars/groups/menus/observability_menu_spec.rb @@ -20,26 +20,74 @@ RSpec.describe Sidebars::Groups::Menus::ObservabilityMenu do allow(menu).to receive(:can?).and_call_original end - context 'when observability is enabled' do + context 'when observability#explore is allowed' do before do - allow(Gitlab::Observability).to receive(:observability_enabled?).and_return(true) + allow(Gitlab::Observability).to receive(:allowed_for_action?).with(user, group, :explore).and_return(true) end it 'returns true' do expect(menu.render?).to eq true - expect(Gitlab::Observability).to have_received(:observability_enabled?).with(user, group) + expect(Gitlab::Observability).to have_received(:allowed_for_action?).with(user, group, :explore) end end - context 'when observability is disabled' do + context 'when observability#explore is not allowed' do before do - allow(Gitlab::Observability).to receive(:observability_enabled?).and_return(false) + allow(Gitlab::Observability).to receive(:allowed_for_action?).with(user, group, :explore).and_return(false) end it 'returns false' do expect(menu.render?).to eq false - expect(Gitlab::Observability).to have_received(:observability_enabled?).with(user, group) + expect(Gitlab::Observability).to have_received(:allowed_for_action?).with(user, group, :explore) end end end + + describe "Menu items" do + before do + allow(Gitlab::Observability).to receive(:allowed_for_action?).and_return(false) + end + + subject { find_menu(menu, item_id) } + + shared_examples 'observability menu entry' do + context 'when action is allowed' do + before do + allow(Gitlab::Observability).to receive(:allowed_for_action?).with(user, group, item_id).and_return(true) + end + + it 'the menu item is added to list of menu items' do + is_expected.not_to be_nil + end + end + + context 'when action is not allowed' do + before do + allow(Gitlab::Observability).to receive(:allowed_for_action?).with(user, group, item_id).and_return(false) + end + + it 'the menu item is added to list of menu items' do + is_expected.to be_nil + end + end + end + + describe 'Explore' do + it_behaves_like 'observability menu entry' do + let(:item_id) { :explore } + end + end + + describe 'Datasources' do + it_behaves_like 'observability menu entry' do + let(:item_id) { :datasources } + end + end + end + + private + + def find_menu(menu, item) + menu.renderable_items.find { |i| i.item_id == item } + end end diff --git a/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb index ce368ad5bd6..382ee07e458 100644 --- a/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb +++ b/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do +RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu, feature_category: :navigation do let_it_be(:owner) { create(:user) } let_it_be_with_reload(:group) do build(:group, :private).tap do |g| @@ -16,6 +16,8 @@ RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do let(:context) { Sidebars::Groups::Context.new(current_user: user, container: group) } let(:menu) { described_class.new(context) } + it_behaves_like 'not serializable as super_sidebar_menu_args' + describe '#render?' do context 'when menu has menu items to show' do it 'returns true' do diff --git a/spec/lib/sidebars/groups/menus/scope_menu_spec.rb b/spec/lib/sidebars/groups/menus/scope_menu_spec.rb index 4b77a09117a..d3aceaf422b 100644 --- a/spec/lib/sidebars/groups/menus/scope_menu_spec.rb +++ b/spec/lib/sidebars/groups/menus/scope_menu_spec.rb @@ -2,14 +2,26 @@ require 'spec_helper' -RSpec.describe Sidebars::Groups::Menus::ScopeMenu do +RSpec.describe Sidebars::Groups::Menus::ScopeMenu, feature_category: :navigation do let(:group) { build(:group) } let(:user) { group.owner } let(:context) { Sidebars::Groups::Context.new(current_user: user, container: group) } + let(:menu) { described_class.new(context) } describe '#extra_nav_link_html_options' do - subject { described_class.new(context).extra_nav_link_html_options } + subject { menu.extra_nav_link_html_options } specify { is_expected.to match(hash_including(class: 'context-header has-tooltip', title: context.group.name)) } end + + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:extra_attrs) do + { + sprite_icon: 'group', + super_sidebar_parent: ::Sidebars::StaticMenu, + title: _('Group overview'), + item_id: :group_overview + } + end + end end diff --git a/spec/lib/sidebars/groups/super_sidebar_panel_spec.rb b/spec/lib/sidebars/groups/super_sidebar_panel_spec.rb new file mode 100644 index 00000000000..beaf3875f1c --- /dev/null +++ b/spec/lib/sidebars/groups/super_sidebar_panel_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::Groups::SuperSidebarPanel, feature_category: :navigation do + let_it_be(:group) { create(:group) } + + let(:user) { group.first_owner } + + let(:context) do + double("Stubbed context", current_user: user, container: group, group: group).as_null_object # rubocop:disable RSpec/VerifiedDoubles + end + + subject { described_class.new(context) } + + it 'implements #super_sidebar_context_header' do + expect(subject.super_sidebar_context_header).to eq( + { + title: group.name, + avatar: group.avatar_url, + id: group.id + }) + end + + describe '#renderable_menus' do + let(:category_menu) do + [ + Sidebars::StaticMenu, + Sidebars::Groups::SuperSidebarMenus::PlanMenu, + Sidebars::Groups::Menus::CiCdMenu, + (Sidebars::Groups::Menus::SecurityComplianceMenu if Gitlab.ee?), + Sidebars::Groups::SuperSidebarMenus::OperationsMenu, + Sidebars::Groups::Menus::ObservabilityMenu, + (Sidebars::Groups::Menus::AnalyticsMenu if Gitlab.ee?), + Sidebars::UncategorizedMenu, + Sidebars::Groups::Menus::SettingsMenu + ].compact + end + + it "is exposed as a renderable menu" do + expect(subject.instance_variable_get(:@menus).map(&:class)).to eq(category_menu) + end + end +end diff --git a/spec/lib/sidebars/menu_spec.rb b/spec/lib/sidebars/menu_spec.rb index 53a889c2db8..641f1c6e7e6 100644 --- a/spec/lib/sidebars/menu_spec.rb +++ b/spec/lib/sidebars/menu_spec.rb @@ -2,9 +2,10 @@ require 'spec_helper' -RSpec.describe Sidebars::Menu do +RSpec.describe Sidebars::Menu, feature_category: :navigation 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 @@ -21,6 +22,82 @@ RSpec.describe Sidebars::Menu do end end + describe '#serialize_for_super_sidebar' do + before do + allow(menu).to receive(:title).and_return('Title') + allow(menu).to receive(:active_routes).and_return({ path: 'foo' }) + end + + it 'returns a tree-like structure of itself and all menu items' do + menu.add_item(Sidebars::MenuItem.new(title: 'Is active', link: 'foo2', active_routes: { controller: 'fooc' })) + menu.add_item(Sidebars::MenuItem.new( + title: 'Not active', + link: 'foo3', + active_routes: { controller: 'barc' }, + has_pill: true, + pill_count: 10 + )) + menu.add_item(nil_menu_item) + + allow(context).to receive(:route_is_active).and_return(->(x) { x[:controller] == 'fooc' }) + + expect(menu.serialize_for_super_sidebar).to eq( + { + title: "Title", + icon: nil, + link: "foo2", + is_active: true, + pill_count: nil, + items: [ + { + title: "Is active", + icon: nil, + link: "foo2", + is_active: true, + pill_count: nil + }, + { + title: "Not active", + icon: nil, + link: "foo3", + is_active: false, + pill_count: 10 + } + ] + }) + end + + it 'returns pill data if defined' do + allow(menu).to receive(:has_pill?).and_return(true) + allow(menu).to receive(:pill_count).and_return('foo') + expect(menu.serialize_for_super_sidebar).to eq( + { + title: "Title", + icon: nil, + link: nil, + is_active: false, + pill_count: 'foo', + items: [] + }) + end + end + + describe '#serialize_as_menu_item_args' do + it 'returns hash of title, link, active_routes, container_html_options' do + allow(menu).to receive(:title).and_return('Title') + allow(menu).to receive(:active_routes).and_return({ path: 'foo' }) + allow(menu).to receive(:container_html_options).and_return({ class: 'foo' }) + allow(menu).to receive(:link).and_return('/link') + + expect(menu.serialize_as_menu_item_args).to eq({ + title: 'Title', + link: '/link', + active_routes: { path: 'foo' }, + container_html_options: { class: 'foo' } + }) + end + end + describe '#render?' do context 'when the menus has no items' do it 'returns false' do diff --git a/spec/lib/sidebars/panel_spec.rb b/spec/lib/sidebars/panel_spec.rb index b70a79361d0..2c1b9c73595 100644 --- a/spec/lib/sidebars/panel_spec.rb +++ b/spec/lib/sidebars/panel_spec.rb @@ -2,11 +2,12 @@ require 'spec_helper' -RSpec.describe Sidebars::Panel do +RSpec.describe Sidebars::Panel, feature_category: :navigation 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) } + let(:menu3) { Sidebars::Menu.new(context) } describe '#renderable_menus' do it 'returns only renderable menus' do @@ -20,6 +21,31 @@ RSpec.describe Sidebars::Panel do end end + describe '#super_sidebar_menu_items' do + it "serializes every renderable menu and returns a flattened result" do + panel.add_menu(menu1) + panel.add_menu(menu2) + panel.add_menu(menu3) + + allow(menu1).to receive(:render?).and_return(true) + allow(menu1).to receive(:serialize_for_super_sidebar).and_return("foo") + + allow(menu2).to receive(:render?).and_return(false) + allow(menu2).to receive(:serialize_for_super_sidebar).and_return("i-should-not-appear-in-results") + + allow(menu3).to receive(:render?).and_return(true) + allow(menu3).to receive(:serialize_for_super_sidebar).and_return(%w[bar baz]) + + expect(panel.super_sidebar_menu_items).to eq(%w[foo bar baz]) + end + end + + describe '#super_sidebar_context_header' do + it 'raises `NotImplementedError`' do + expect { panel.super_sidebar_context_header }.to raise_error(NotImplementedError) + end + end + describe '#has_renderable_menus?' do it 'returns false when no renderable menus' do expect(panel.has_renderable_menus?).to be false diff --git a/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb b/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb index ce971915174..5065c261cf8 100644 --- a/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/deployments_menu_spec.rb @@ -2,12 +2,16 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::DeploymentsMenu do +RSpec.describe Sidebars::Projects::Menus::DeploymentsMenu, feature_category: :navigation do let_it_be(:project, reload: true) { create(:project, :repository) } let(:user) { project.first_owner } let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) } + it_behaves_like 'not serializable as super_sidebar_menu_args' do + let(:menu) { described_class.new(context) } + end + describe '#render?' do subject { described_class.new(context) } diff --git a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb index 116948b7cb0..7f0e02892e4 100644 --- a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb @@ -2,11 +2,15 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu do +RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu, feature_category: :navigation do let(:project) { build(:project) } let(:user) { project.first_owner } let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, show_cluster_hint: false) } + it_behaves_like 'not serializable as super_sidebar_menu_args' do + let(:menu) { described_class.new(context) } + end + describe '#render?' do subject { described_class.new(context) } @@ -103,6 +107,22 @@ RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu do let(:item_id) { :terraform } it_behaves_like 'access rights checks' + + context 'if terraform_state.enabled=true' do + before do + stub_config(terraform_state: { enabled: true }) + end + + it_behaves_like 'access rights checks' + end + + context 'if terraform_state.enabled=false' do + before do + stub_config(terraform_state: { enabled: false }) + end + + it { is_expected.to be_nil } + end end describe 'Google Cloud' do @@ -141,6 +161,56 @@ RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu do it_behaves_like 'access rights checks' end end + + context 'when instance is not configured for Google OAuth2' do + before do + stub_feature_flags(incubation_5mp_google_cloud: true) + unconfigured_google_oauth2 = Struct.new(:app_id, :app_secret).new('', '') + allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for) + .with('google_oauth2') + .and_return(unconfigured_google_oauth2) + end + + it { is_expected.to be_nil } + end + end + + describe 'AWS' do + let(:item_id) { :aws } + + it_behaves_like 'access rights checks' + + context 'when feature flag is turned off globally' do + before do + stub_feature_flags(cloudseed_aws: false) + end + + it { is_expected.to be_nil } + + context 'when feature flag is enabled for specific project' do + before do + stub_feature_flags(cloudseed_aws: project) + end + + it_behaves_like 'access rights checks' + end + + context 'when feature flag is enabled for specific group' do + before do + stub_feature_flags(cloudseed_aws: project.group) + end + + it_behaves_like 'access rights checks' + end + + context 'when feature flag is enabled for specific project' do + before do + stub_feature_flags(cloudseed_aws: user) + end + + it_behaves_like 'access rights checks' + end + end end end end diff --git a/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb b/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb deleted file mode 100644 index 9838aa8c3e3..00000000000 --- a/spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Sidebars::Projects::Menus::InviteTeamMembersMenu do - let_it_be(:project) { create(:project) } - let_it_be(:guest) { create(:user) } - - let(:context) { Sidebars::Projects::Context.new(current_user: owner, container: project) } - - subject(:invite_menu) { described_class.new(context) } - - context 'when the project is viewed by an owner of the group' do - let(:owner) { project.first_owner } - - describe '#render?' do - it 'renders the Invite team members link' do - expect(invite_menu.render?).to eq(true) - end - - context 'when the project already has at least 2 members' do - before do - project.add_guest(guest) - end - - it 'does not render the link' do - expect(invite_menu.render?).to eq(false) - end - end - end - - describe '#title' do - it 'displays the correct Invite team members text for the link in the side nav' do - expect(invite_menu.title).to eq('Invite members') - end - end - end - - context 'when the project is viewed by a guest user without admin permissions' do - let(:context) { Sidebars::Projects::Context.new(current_user: guest, container: project) } - - before do - project.add_guest(guest) - end - - describe '#render?' do - it 'does not render' do - expect(invite_menu.render?).to eq(false) - end - 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 index 4c0016a77a1..c7ff846bc95 100644 --- a/spec/lib/sidebars/projects/menus/issues_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/issues_menu_spec.rb @@ -2,13 +2,26 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::IssuesMenu do +RSpec.describe Sidebars::Projects::Menus::IssuesMenu, feature_category: :navigation do let(:project) { build(:project) } let(:user) { project.first_owner } let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) } subject { described_class.new(context) } + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:menu) { subject } + let(:extra_attrs) do + { + item_id: :project_issue_list, + sprite_icon: 'issues', + pill_count: menu.pill_count, + has_pill: menu.has_pill?, + super_sidebar_parent: ::Sidebars::StaticMenu + } + end + end + describe '#render?' do context 'when user can read issues' do it 'returns true' do diff --git a/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb b/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb index 45c49500e46..a19df559b58 100644 --- a/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::MergeRequestsMenu do +RSpec.describe Sidebars::Projects::Menus::MergeRequestsMenu, feature_category: :navigation do let_it_be(:project) { create(:project, :repository) } let(:user) { project.first_owner } @@ -10,6 +10,19 @@ RSpec.describe Sidebars::Projects::Menus::MergeRequestsMenu do subject { described_class.new(context) } + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:menu) { subject } + let(:extra_attrs) do + { + item_id: :project_merge_request_list, + sprite_icon: 'git-merge', + pill_count: menu.pill_count, + has_pill: menu.has_pill?, + super_sidebar_parent: ::Sidebars::StaticMenu + } + end + end + describe '#render?' do context 'when repository is not present' do let(:project) { build(:project) } diff --git a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb index b03269c424a..554bc763345 100644 --- a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do +RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu, feature_category: :navigation do let_it_be(:project) { create(:project) } let_it_be(:harbor_integration) { create(:harbor_integration, project: project) } @@ -12,6 +12,10 @@ RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do subject { described_class.new(context) } + it_behaves_like 'not serializable as super_sidebar_menu_args' do + let(:menu) { subject } + end + describe '#render?' do context 'when menu does not have any menu item to show' do it 'returns false' do diff --git a/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb b/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb index 7ff06ac229e..7547f152b27 100644 --- a/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/project_information_menu_spec.rb @@ -2,12 +2,16 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::ProjectInformationMenu do +RSpec.describe Sidebars::Projects::Menus::ProjectInformationMenu, feature_category: :navigation do let_it_be_with_reload(:project) { create(:project, :repository) } let(:user) { project.first_owner } let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) } + it_behaves_like 'not serializable as super_sidebar_menu_args' do + let(:menu) { described_class.new(context) } + end + describe '#container_html_options' do subject { described_class.new(context).container_html_options } diff --git a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb index 40ca2107698..b0631aacdb9 100644 --- a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb @@ -85,7 +85,7 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu, feature_category: :sou end end - describe 'Contributors' do + describe 'Contributor statistics' do let_it_be(:item_id) { :contributors } context 'when analytics is disabled' do diff --git a/spec/lib/sidebars/projects/menus/scope_menu_spec.rb b/spec/lib/sidebars/projects/menus/scope_menu_spec.rb index 4e87f3b8ead..45464278880 100644 --- a/spec/lib/sidebars/projects/menus/scope_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/scope_menu_spec.rb @@ -2,11 +2,23 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::ScopeMenu do +RSpec.describe Sidebars::Projects::Menus::ScopeMenu, feature_category: :navigation do let(:project) { build(:project) } let(:user) { project.first_owner } let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) } + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:menu) { described_class.new(context) } + let(:extra_attrs) do + { + title: _('Project overview'), + sprite_icon: 'project', + super_sidebar_parent: ::Sidebars::StaticMenu, + item_id: :project_overview + } + end + end + describe '#container_html_options' do subject { described_class.new(context).container_html_options } diff --git a/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb b/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb index 41158bd58dc..697359b7941 100644 --- a/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/security_compliance_menu_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Sidebars::Projects::Menus::SecurityComplianceMenu do end context 'when user is authenticated' do - context 'when the Security & Compliance is disabled' do + context 'when the Security and Compliance is disabled' do before do allow(Ability).to receive(:allowed?).with(user, :access_security_and_compliance, project).and_return(false) end @@ -28,7 +28,7 @@ RSpec.describe Sidebars::Projects::Menus::SecurityComplianceMenu do it { is_expected.to be_falsey } end - context 'when the Security & Compliance is not disabled' do + context 'when the Security and Compliance is not disabled' do it { is_expected.to be_truthy } end end diff --git a/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb b/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb index 04b8c128e3d..c5fd407dae9 100644 --- a/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/snippets_menu_spec.rb @@ -2,13 +2,24 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::SnippetsMenu do +RSpec.describe Sidebars::Projects::Menus::SnippetsMenu, feature_category: :navigation do let(:project) { build(:project) } let(:user) { project.first_owner } let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) } subject { described_class.new(context) } + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:menu) { subject } + let(:extra_attrs) do + { + super_sidebar_parent: ::Sidebars::Projects::Menus::RepositoryMenu, + super_sidebar_before: :contributors, + item_id: :project_snippets + } + end + end + describe '#render?' do context 'when user cannot access snippets' do let(:user) { nil } diff --git a/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb b/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb index 362da3e7b50..64050e3e488 100644 --- a/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/wiki_menu_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::WikiMenu do +RSpec.describe Sidebars::Projects::Menus::WikiMenu, feature_category: :navigation do let(:project) { build(:project) } let(:user) { project.first_owner } let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) } @@ -28,4 +28,14 @@ RSpec.describe Sidebars::Projects::Menus::WikiMenu do end end end + + it_behaves_like 'serializable as super_sidebar_menu_args' do + let(:menu) { subject } + let(:extra_attrs) do + { + super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::PlanMenu, + item_id: :project_wiki + } + end + end end diff --git a/spec/lib/sidebars/projects/panel_spec.rb b/spec/lib/sidebars/projects/panel_spec.rb index ff253eedd08..ec1df438cf1 100644 --- a/spec/lib/sidebars/projects/panel_spec.rb +++ b/spec/lib/sidebars/projects/panel_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Panel do +RSpec.describe Sidebars::Projects::Panel, feature_category: :navigation do let_it_be(:project) { create(:project) } let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project) } diff --git a/spec/lib/sidebars/projects/super_sidebar_menus/operations_menu_spec.rb b/spec/lib/sidebars/projects/super_sidebar_menus/operations_menu_spec.rb new file mode 100644 index 00000000000..df3f7e6cdab --- /dev/null +++ b/spec/lib/sidebars/projects/super_sidebar_menus/operations_menu_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::Projects::SuperSidebarMenus::OperationsMenu, feature_category: :navigation do + subject { described_class.new({}) } + + it 'has title and sprite_icon' do + expect(subject.title).to eq(_("Operations")) + expect(subject.sprite_icon).to eq("deployments") + end +end diff --git a/spec/lib/sidebars/projects/super_sidebar_menus/plan_menu_spec.rb b/spec/lib/sidebars/projects/super_sidebar_menus/plan_menu_spec.rb new file mode 100644 index 00000000000..3917d26f6f2 --- /dev/null +++ b/spec/lib/sidebars/projects/super_sidebar_menus/plan_menu_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::Projects::SuperSidebarMenus::PlanMenu, feature_category: :navigation do + subject { described_class.new({}) } + + it 'has title and sprite_icon' do + expect(subject.title).to eq(_("Plan")) + expect(subject.sprite_icon).to eq("planning") + end +end diff --git a/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb b/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb new file mode 100644 index 00000000000..d6fc3fd8fe1 --- /dev/null +++ b/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::Projects::SuperSidebarPanel, feature_category: :navigation do + let_it_be(:project) { create(:project, :repository) } + + let(:user) { project.first_owner } + + let(:context) do + double("Stubbed context", current_user: user, container: project, project: project, current_ref: 'master').as_null_object # rubocop:disable RSpec/VerifiedDoubles + end + + subject { described_class.new(context) } + + it 'implements #super_sidebar_context_header' do + expect(subject.super_sidebar_context_header).to eq( + { + title: project.name, + avatar: project.avatar_url, + id: project.id + }) + end + + describe '#renderable_menus' do + let(:category_menu) do + [ + Sidebars::StaticMenu, + Sidebars::Projects::SuperSidebarMenus::PlanMenu, + Sidebars::Projects::Menus::RepositoryMenu, + Sidebars::Projects::Menus::CiCdMenu, + Sidebars::Projects::Menus::SecurityComplianceMenu, + Sidebars::Projects::SuperSidebarMenus::OperationsMenu, + Sidebars::Projects::Menus::MonitorMenu, + Sidebars::Projects::Menus::AnalyticsMenu, + Sidebars::UncategorizedMenu, + Sidebars::Projects::Menus::SettingsMenu + ] + end + + it "is exposed as a renderable menu" do + expect(subject.instance_variable_get(:@menus).map(&:class)).to eq(category_menu) + end + end +end diff --git a/spec/lib/sidebars/static_menu_spec.rb b/spec/lib/sidebars/static_menu_spec.rb new file mode 100644 index 00000000000..086eb332a15 --- /dev/null +++ b/spec/lib/sidebars/static_menu_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::StaticMenu, feature_category: :navigation do + let(:context) { {} } + + subject { described_class.new(context) } + + describe '#serialize_for_super_sidebar' do + it 'returns flat list of all menu items' do + subject.add_item(Sidebars::MenuItem.new(title: 'Is active', link: 'foo2', active_routes: { controller: 'fooc' })) + subject.add_item(Sidebars::MenuItem.new(title: 'Not active', link: 'foo3', active_routes: { controller: 'barc' })) + subject.add_item(Sidebars::NilMenuItem.new(item_id: 'nil_item')) + + allow(context).to receive(:route_is_active).and_return(->(x) { x[:controller] == 'fooc' }) + + expect(subject.serialize_for_super_sidebar).to eq( + [ + { + title: "Is active", + icon: nil, + link: "foo2", + is_active: true, + pill_count: nil + }, + { + title: "Not active", + icon: nil, + link: "foo3", + is_active: false, + pill_count: nil + } + ] + ) + end + end +end diff --git a/spec/lib/sidebars/uncategorized_menu_spec.rb b/spec/lib/sidebars/uncategorized_menu_spec.rb new file mode 100644 index 00000000000..45e7c0c87e2 --- /dev/null +++ b/spec/lib/sidebars/uncategorized_menu_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UncategorizedMenu, feature_category: :navigation do + subject { described_class.new({}) } + + it 'has title and sprite_icon' do + expect(subject.title).to eq(_("Uncategorized")) + expect(subject.sprite_icon).to eq("question") + end +end diff --git a/spec/lib/sidebars/user_profile/menus/activity_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/activity_menu_spec.rb new file mode 100644 index 00000000000..44492380f11 --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/activity_menu_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::ActivityMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Activity'), + active_route: 'users#activity' do + let(:link) { "/users/#{user.username}/activity" } + end +end diff --git a/spec/lib/sidebars/user_profile/menus/contributed_projects_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/contributed_projects_menu_spec.rb new file mode 100644 index 00000000000..a5371c36fd3 --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/contributed_projects_menu_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::ContributedProjectsMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Contributed projects'), + active_route: 'users#contributed' do + let(:link) { "/users/#{user.username}/contributed" } + end +end diff --git a/spec/lib/sidebars/user_profile/menus/followers_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/followers_menu_spec.rb new file mode 100644 index 00000000000..1b3efbf4ceb --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/followers_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::FollowersMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Followers'), + active_route: 'users#followers' do + let(:link) { "/users/#{user.username}/followers" } + end + + it_behaves_like 'Followers/followees counts', :followers +end diff --git a/spec/lib/sidebars/user_profile/menus/following_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/following_menu_spec.rb new file mode 100644 index 00000000000..167961f085e --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/following_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::FollowingMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Following'), + active_route: 'users#following' do + let(:link) { "/users/#{user.username}/following" } + end + + it_behaves_like 'Followers/followees counts', :followees +end diff --git a/spec/lib/sidebars/user_profile/menus/groups_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/groups_menu_spec.rb new file mode 100644 index 00000000000..6c48ad2e8d0 --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/groups_menu_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::GroupsMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Groups'), + active_route: 'users#groups' do + let(:link) { "/users/#{user.username}/groups" } + end +end diff --git a/spec/lib/sidebars/user_profile/menus/overview_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/overview_menu_spec.rb new file mode 100644 index 00000000000..e34f59cddf0 --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/overview_menu_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::OverviewMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Overview'), + active_route: 'users#show' do + let(:link) { "/#{user.username}" } + end +end diff --git a/spec/lib/sidebars/user_profile/menus/personal_projects_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/personal_projects_menu_spec.rb new file mode 100644 index 00000000000..ba2c3d11b88 --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/personal_projects_menu_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::PersonalProjectsMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Personal projects'), + active_route: 'users#projects' do + let(:link) { "/users/#{user.username}/projects" } + end +end diff --git a/spec/lib/sidebars/user_profile/menus/snippets_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/snippets_menu_spec.rb new file mode 100644 index 00000000000..2760d172a51 --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/snippets_menu_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::SnippetsMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Snippets'), + active_route: 'users#snippets' do + let(:link) { "/users/#{user.username}/snippets" } + end +end diff --git a/spec/lib/sidebars/user_profile/menus/starred_projects_menu_spec.rb b/spec/lib/sidebars/user_profile/menus/starred_projects_menu_spec.rb new file mode 100644 index 00000000000..e205d1f5492 --- /dev/null +++ b/spec/lib/sidebars/user_profile/menus/starred_projects_menu_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Menus::StarredProjectsMenu, feature_category: :navigation do + it_behaves_like 'User profile menu', + title: s_('UserProfile|Starred projects'), + active_route: 'users#starred' do + let(:link) { "/users/#{user.username}/starred" } + end +end diff --git a/spec/lib/sidebars/user_profile/panel_spec.rb b/spec/lib/sidebars/user_profile/panel_spec.rb new file mode 100644 index 00000000000..af261dce3f3 --- /dev/null +++ b/spec/lib/sidebars/user_profile/panel_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserProfile::Panel, feature_category: :navigation do + let_it_be(:current_user) { create(:user) } + let_it_be(:user) { create(:user) } + + let(:context) { Sidebars::Context.new(current_user: current_user, container: user) } + + subject { described_class.new(context) } + + it 'implements #aria_label' do + expect(subject.aria_label).to eq(s_('UserProfile|User profile navigation')) + end + + it 'implements #super_sidebar_context_header' do + expect(subject.super_sidebar_context_header).to eq({ + title: user.name, + avatar: user.avatar_url, + avatar_shape: 'circle' + }) + end +end diff --git a/spec/lib/sidebars/user_settings/menus/access_tokens_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/access_tokens_menu_spec.rb new file mode 100644 index 00000000000..fa33e7bedfb --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/access_tokens_menu_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::AccessTokensMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/personal_access_tokens', + title: _('Access Tokens'), + icon: 'token', + active_routes: { controller: :personal_access_tokens } + + describe '#render?' do + subject { described_class.new(context) } + + let_it_be(:user) { build(:user) } + + context 'when personal access tokens are disabled' do + before do + allow(::Gitlab::CurrentSettings).to receive_messages(personal_access_tokens_disabled?: true) + end + + context 'when user is logged in' do + let(:context) { Sidebars::Context.new(current_user: user, container: nil) } + + it 'does not render' do + expect(subject.render?).to be false + end + end + + context 'when user is not logged in' do + let(:context) { Sidebars::Context.new(current_user: nil, container: nil) } + + subject { described_class.new(context) } + + it 'does not render' do + expect(subject.render?).to be false + end + end + end + + context 'when personal access tokens are enabled' do + before do + allow(::Gitlab::CurrentSettings).to receive_messages(personal_access_tokens_disabled?: false) + end + + context 'when user is logged in' do + let(:context) { Sidebars::Context.new(current_user: user, container: nil) } + + it 'renders' do + expect(subject.render?).to be true + end + end + + context 'when user is not logged in' do + let(:context) { Sidebars::Context.new(current_user: nil, container: nil) } + + subject { described_class.new(context) } + + it 'does not render' do + expect(subject.render?).to be false + end + end + end + end +end diff --git a/spec/lib/sidebars/user_settings/menus/account_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/account_menu_spec.rb new file mode 100644 index 00000000000..d5810d9c5ae --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/account_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::AccountMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/account', + title: _('Account'), + icon: 'account', + active_routes: { controller: [:accounts, :two_factor_auths] } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/active_sessions_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/active_sessions_menu_spec.rb new file mode 100644 index 00000000000..be5f826ee58 --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/active_sessions_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::ActiveSessionsMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/active_sessions', + title: _('Active Sessions'), + icon: 'monitor-lines', + active_routes: { controller: :active_sessions } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/applications_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/applications_menu_spec.rb new file mode 100644 index 00000000000..eeda4fb844c --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/applications_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::ApplicationsMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/applications', + title: _('Applications'), + icon: 'applications', + active_routes: { controller: 'oauth/applications' } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/authentication_log_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/authentication_log_menu_spec.rb new file mode 100644 index 00000000000..33be5050c37 --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/authentication_log_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::AuthenticationLogMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/audit_log', + title: _('Authentication Log'), + icon: 'log', + active_routes: { path: 'profiles#audit_log' } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/chat_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/chat_menu_spec.rb new file mode 100644 index 00000000000..2a0587e2504 --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/chat_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::ChatMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/chat', + title: _('Chat'), + icon: 'comment', + active_routes: { controller: :chat_names } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/emails_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/emails_menu_spec.rb new file mode 100644 index 00000000000..2f16c68e601 --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/emails_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::EmailsMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/emails', + title: _('Emails'), + icon: 'mail', + active_routes: { controller: :emails } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/gpg_keys_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/gpg_keys_menu_spec.rb new file mode 100644 index 00000000000..1f4340ad29c --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/gpg_keys_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::GpgKeysMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/gpg_keys', + title: _('GPG Keys'), + icon: 'key', + active_routes: { controller: :gpg_keys } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/notifications_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/notifications_menu_spec.rb new file mode 100644 index 00000000000..282324056d4 --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/notifications_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::NotificationsMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/notifications', + title: _('Notifications'), + icon: 'notifications', + active_routes: { controller: :notifications } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/password_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/password_menu_spec.rb new file mode 100644 index 00000000000..168019fea5d --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/password_menu_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::PasswordMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/password', + title: _('Password'), + icon: 'lock', + active_routes: { controller: :passwords } + + describe '#render?' do + subject { described_class.new(context) } + + let_it_be(:user) { build(:user) } + let(:context) { Sidebars::Context.new(current_user: user, container: nil) } + + context 'when password authentication is enabled' do + before do + allow(user).to receive(:allow_password_authentication?).and_return(true) + end + + it 'renders' do + expect(subject.render?).to be true + end + end + + context 'when password authentication is disabled' do + before do + allow(user).to receive(:allow_password_authentication?).and_return(false) + end + + it 'renders' do + expect(subject.render?).to be false + end + end + end +end diff --git a/spec/lib/sidebars/user_settings/menus/preferences_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/preferences_menu_spec.rb new file mode 100644 index 00000000000..83a67a40081 --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/preferences_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::PreferencesMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/preferences', + title: _('Preferences'), + icon: 'preferences', + active_routes: { controller: :preferences } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/profile_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/profile_menu_spec.rb new file mode 100644 index 00000000000..8410ba7cfcd --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/profile_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::ProfileMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile', + title: _('Profile'), + icon: 'profile', + active_routes: { path: 'profiles#show' } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/menus/saved_replies_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/saved_replies_menu_spec.rb new file mode 100644 index 00000000000..ea1a2a3539f --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/saved_replies_menu_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::SavedRepliesMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/saved_replies', + title: _('Saved Replies'), + icon: 'symlink', + active_routes: { controller: :saved_replies } + + describe '#render?' do + subject { described_class.new(context) } + + let_it_be(:user) { build(:user) } + + context 'when saved replies are enabled' do + before do + allow(subject).to receive(:saved_replies_enabled?).and_return(true) + end + + context 'when user is logged in' do + let(:context) { Sidebars::Context.new(current_user: user, container: nil) } + + it 'does not render' do + expect(subject.render?).to be true + end + end + + context 'when user is not logged in' do + let(:context) { Sidebars::Context.new(current_user: nil, container: nil) } + + subject { described_class.new(context) } + + it 'does not render' do + expect(subject.render?).to be false + end + end + end + + context 'when saved replies are disabled' do + before do + allow(subject).to receive(:saved_replies_enabled?).and_return(false) + end + + context 'when user is logged in' do + let(:context) { Sidebars::Context.new(current_user: user, container: nil) } + + it 'renders' do + expect(subject.render?).to be false + end + end + + context 'when user is not logged in' do + let(:context) { Sidebars::Context.new(current_user: nil, container: nil) } + + subject { described_class.new(context) } + + it 'does not render' do + expect(subject.render?).to be false + end + end + end + end +end diff --git a/spec/lib/sidebars/user_settings/menus/ssh_keys_menu_spec.rb b/spec/lib/sidebars/user_settings/menus/ssh_keys_menu_spec.rb new file mode 100644 index 00000000000..8c781cc743b --- /dev/null +++ b/spec/lib/sidebars/user_settings/menus/ssh_keys_menu_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Menus::SshKeysMenu, feature_category: :navigation do + it_behaves_like 'User settings menu', + link: '/-/profile/keys', + title: _('SSH Keys'), + icon: 'key', + active_routes: { controller: :keys } + + it_behaves_like 'User settings menu #render? method' +end diff --git a/spec/lib/sidebars/user_settings/panel_spec.rb b/spec/lib/sidebars/user_settings/panel_spec.rb new file mode 100644 index 00000000000..aa05d99912a --- /dev/null +++ b/spec/lib/sidebars/user_settings/panel_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::UserSettings::Panel, feature_category: :navigation do + let_it_be(:user) { create(:user) } + + let(:context) { Sidebars::Context.new(current_user: user, container: nil) } + + subject { described_class.new(context) } + + it 'implements #super_sidebar_context_header' do + expect(subject.super_sidebar_context_header).to eq({ title: _('User settings'), avatar: user.avatar_url }) + end +end diff --git a/spec/lib/sidebars/your_work/panel_spec.rb b/spec/lib/sidebars/your_work/panel_spec.rb new file mode 100644 index 00000000000..97da94e4114 --- /dev/null +++ b/spec/lib/sidebars/your_work/panel_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::YourWork::Panel, feature_category: :navigation do + let_it_be(:user) { create(:user) } + + let(:context) { Sidebars::Context.new(current_user: user, container: nil) } + + subject { described_class.new(context) } + + it 'implements #super_sidebar_context_header' do + expect(subject.super_sidebar_context_header).to eq({ title: 'Your work', icon: 'work' }) + end +end |