Custom updates to the project sidebar refactor

After several discussions, we decided to make some changes to the
existing project sidebar refactor:

- Removing inheritance in menu items refactor
- Renaming the menus and moving them outside of folder
parent ced9a272
......@@ -22,6 +22,6 @@
%span.badge.badge-pill.count.fly-out-badge{ **sidebar_menu.pill_html_options }
= number_with_delimiter(sidebar_menu.pill_count)
- if sidebar_menu.has_renderable_items?
- if sidebar_menu.has_items?
%li.divider.fly-out-top-item
= render partial: 'shared/nav/sidebar_menu_item', collection: sidebar_menu.renderable_items
= render partial: 'shared/nav/sidebar_menu_item', collection: sidebar_menu.items
# frozen_string_literal: true
module EE
module Sidebars
module Projects
module Menus
module Repository
module Menu
extend ::Gitlab::Utils::Override
override :configure_menu_items
def configure_menu_items
super
add_item(::Sidebars::Projects::Menus::Repository::MenuItems::FileLocks.new(context))
end
end
end
end
end
end
end
# frozen_string_literal: true
module EE
module Sidebars
module Projects
module Menus
module RepositoryMenu
extend ::Gitlab::Utils::Override
override :configure_menu_items
def configure_menu_items
return false unless super
add_item(file_locks_menu_item)
true
end
private
def file_locks_menu_item
return unless context.project.licensed_feature_available?(:file_locks)
::Sidebars::MenuItem.new(
title: _('Locked Files'),
link: project_path_locks_path(context.project),
active_routes: { controller: :path_locks },
item_id: :file_locks
)
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
module MenuItems
class FileLocks < ::Sidebars::MenuItem
override :link
def link
project_path_locks_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
data: { qa_selector: 'path_locks_link' }
}
end
override :active_routes
def active_routes
{ controller: :path_locks }
end
override :title
def title
_('Locked Files')
end
override :render?
def render?
context.project.licensed_feature_available?(:file_locks)
end
end
end
end
end
end
end
# 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') }
describe 'File Locks' do
subject { described_class.new(context).items.index { |e| e.item_id == :file_locks} }
context 'when licensed feature file locks is not enabled' do
it 'does not include file locks menu item' do
stub_licensed_features(file_locks: false)
is_expected.to be_nil
end
end
context 'when licensed feature file locks is enabled' do
it 'includes file locks menu item' do
stub_licensed_features(file_locks: true)
is_expected.to be_present
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::Repository::MenuItems::FileLocks do
let(:project) { build(:project) }
let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project) }
subject { described_class.new(context) }
describe '#render?' do
before do
stub_licensed_features(file_locks: license_feature_status)
end
context 'when project has the licensed feature' do
let(:license_feature_status) { true }
it 'returns true' do
expect(subject.render?).to eq true
end
end
context 'when project does not have the licensed feature' do
let(:license_feature_status) { false }
it 'returns false' do
expect(subject.render?).to eq false
end
end
end
end
# frozen_string_literal: true
# This module handles elements in a list. All elements
# must have a different class
# This module handles element positions in a list.
module Sidebars
module Concerns
module PositionableList
def add_element(list, element)
return unless element
list << element
end
def insert_element_before(list, before_element, new_element)
return unless new_element
index = index_of(list, before_element)
if index
......@@ -20,6 +23,8 @@ module Sidebars
end
def insert_element_after(list, after_element, new_element)
return unless new_element
index = index_of(list, after_element)
if index
......@@ -31,8 +36,10 @@ module Sidebars
private
# Classes including this method will have to define
# the way to identify elements through this method
def index_of(list, element)
list.index { |e| e.is_a?(element) }
raise NotImplementedError
end
end
end
......
......@@ -13,7 +13,7 @@ module Sidebars
include ::Sidebars::Concerns::ContainerWithHtmlOptions
include ::Sidebars::Concerns::HasActiveRoutes
attr_reader :context
attr_reader :context, :items
delegate :current_user, :container, to: :@context
def initialize(context)
......@@ -24,12 +24,12 @@ module Sidebars
end
def configure_menu_items
# No-op
true
end
override :render?
def render?
@items.empty? || renderable_items.any?
has_items?
end
# Menus might have or not a link
......@@ -43,7 +43,7 @@ module Sidebars
# This method filters the information and returns: { path: ['foo', 'bar'], controller: :foo }
def all_active_routes
@all_active_routes ||= begin
([active_routes] + renderable_items.map(&:active_routes)).flatten.each_with_object({}) do |pairs, hash|
([active_routes] + items.map(&:active_routes)).flatten.each_with_object({}) do |pairs, hash|
pairs.each do |k, v|
hash[k] ||= []
hash[k] += Array(v)
......@@ -71,12 +71,11 @@ module Sidebars
insert_element_after(@items, after_item, new_item)
end
def has_renderable_items?
renderable_items.any?
end
private
def renderable_items
@renderable_items ||= @items.select(&:render?)
override :index_of
def index_of(list, element)
list.index { |e| e.item_id == element }
end
end
end
......@@ -2,20 +2,21 @@
module Sidebars
class MenuItem
extend ::Gitlab::Utils::Override
include ::Gitlab::Routing
include GitlabRoutingHelper
include Gitlab::Allowable
include ::Sidebars::Concerns::HasIcon
include ::Sidebars::Concerns::HasHint
include ::Sidebars::Concerns::Renderable
include ::Sidebars::Concerns::ContainerWithHtmlOptions
include ::Sidebars::Concerns::HasActiveRoutes
attr_reader :title, :link, :active_routes, :item_id, :container_html_options, :sprite_icon, :sprite_icon_html_options, :hint_html_options
attr_reader :context
def initialize(title:, link:, active_routes:, item_id: nil, container_html_options: {}, sprite_icon: nil, sprite_icon_html_options: {}, hint_html_options: {})
@title = title
@link = link
@active_routes = active_routes
@item_id = item_id
@container_html_options = container_html_options
@sprite_icon = sprite_icon
@sprite_icon_html_options = sprite_icon_html_options
@hint_html_options = hint_html_options
end
def initialize(context)
@context = context
def show_hint?
hint_html_options.present?
end
end
end
......@@ -71,5 +71,12 @@ module Sidebars
def render_raw_menus_partial
# No-op
end
private
override :index_of
def index_of(list, element)
list.index { |e| e.is_a?(element) }
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module LearnGitlab
class Menu < ::Sidebars::Menu
override :link
def link
project_learn_gitlab_path(context.project)
end
override :active_routes
def active_routes
{ controller: :learn_gitlab }
end
override :title
def title
_('Learn GitLab')
end
override :extra_container_html_options
def nav_link_html_options
{ class: 'home' }
end
override :sprite_icon
def sprite_icon
'home'
end
override :render?
def render?
context.learn_gitlab_experiment_enabled
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class LearnGitlabMenu < ::Sidebars::Menu
override :link
def link
project_learn_gitlab_path(context.project)
end
override :active_routes
def active_routes
{ controller: :learn_gitlab }
end
override :title
def title
_('Learn GitLab')
end
override :extra_container_html_options
def nav_link_html_options
{ class: 'home' }
end
override :sprite_icon
def sprite_icon
'home'
end
override :render?
def render?
context.learn_gitlab_experiment_enabled
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module ProjectOverview
class Menu < ::Sidebars::Menu
override :configure_menu_items
def configure_menu_items
add_item(MenuItems::Details.new(context))
add_item(MenuItems::Activity.new(context))
add_item(MenuItems::Releases.new(context))
end
override :link
def link
project_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-project rspec-project-link'
}
end
override :extra_container_html_options
def nav_link_html_options
{ class: 'home' }
end
override :title
def title
_('Project overview')
end
override :sprite_icon
def sprite_icon
'home'
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module ProjectOverview
module MenuItems
class Activity < ::Sidebars::MenuItem
override :link
def link
activity_project_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-project-activity'
}
end
override :active_routes
def active_routes
{ path: 'projects#activity' }
end
override :title
def title
_('Activity')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module ProjectOverview
module MenuItems
class Details < ::Sidebars::MenuItem
override :link
def link
project_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
aria: { label: _('Project details') },
class: 'shortcuts-project'
}
end
override :active_routes
def active_routes
{ path: 'projects#show' }
end
override :title
def title
_('Details')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module ProjectOverview
module MenuItems
class Releases < ::Sidebars::MenuItem
override :link
def link
project_releases_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-project-releases'
}
end
override :render?
def render?
can?(context.current_user, :read_release, context.project) && !context.project.empty_repo?
end
override :active_routes
def active_routes
{ controller: :releases }
end
override :title
def title
_('Releases')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class ProjectOverviewMenu < ::Sidebars::Menu
override :configure_menu_items
def configure_menu_items
add_item(details_menu_item)
add_item(activity_menu_item)
add_item(releases_menu_item)
true
end
override :link
def link
project_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-project rspec-project-link'
}
end
override :nav_link_html_options
def nav_link_html_options
{ class: 'home' }
end
override :title
def title
_('Project overview')
end
override :sprite_icon
def sprite_icon
'home'
end
private
def details_menu_item
::Sidebars::MenuItem.new(
title: _('Details'),
link: project_path(context.project),
active_routes: { path: 'projects#show' },
item_id: :project_overview,
container_html_options: {
aria: { label: _('Project details') },
class: 'shortcuts-project'
}
)
end
def activity_menu_item
::Sidebars::MenuItem.new(
title: _('Activity'),
link: activity_project_path(context.project),
active_routes: { path: 'projects#activity' },
item_id: :activity,
container_html_options: { class: 'shortcuts-project-activity' }
)
end
def releases_menu_item
return unless can?(context.current_user, :read_release, context.project)
return if context.project.empty_repo?
::Sidebars::MenuItem.new(
title: _('Releases'),
link: project_releases_path(context.project),
item_id: :releases,
active_routes: { controller: :releases },
container_html_options: { class: 'shortcuts-project-releases' }
)
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
class Menu < ::Sidebars::Menu
override :configure_menu_items
def configure_menu_items
add_item(MenuItems::Files.new(context))
add_item(MenuItems::Commits.new(context))
add_item(MenuItems::Branches.new(context))
add_item(MenuItems::Tags.new(context))
add_item(MenuItems::Contributors.new(context))
add_item(MenuItems::Graphs.new(context))
add_item(MenuItems::Compare.new(context))
end
override :link
def link
project_tree_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-tree'
}
end
override :title
def title
_('Repository')
end
override :title_html_options
def title_html_options
{
id: 'js-onboarding-repo-link'
}
end
override :sprite_icon
def sprite_icon
'doc-text'
end
override :render?
def render?
can?(context.current_user, :download_code, context.project) &&
!context.project.empty_repo?
end
end
end
end
end
end
Sidebars::Projects::Menus::Repository::Menu.prepend_if_ee('EE::Sidebars::Projects::Menus::Repository::Menu')
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
module MenuItems
class Branches < ::Sidebars::MenuItem
override :link
def link
project_branches_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
id: 'js-onboarding-branches-link'
}
end
override :active_routes
def active_routes
{ controller: :branches }
end
override :title
def title
_('Branches')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
module MenuItems
class Commits < ::Sidebars::MenuItem
override :link
def link
project_commits_path(context.project, context.current_ref)
end
override :extra_container_html_options
def extra_container_html_options
{
id: 'js-onboarding-commits-link'
}
end
override :active_routes
def active_routes
{ controller: %w(commit commits) }
end
override :title
def title
_('Commits')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
module MenuItems
class Compare < ::Sidebars::MenuItem
override :link
def link
project_compare_index_path(context.project, from: context.project.repository.root_ref, to: context.current_ref)
end
override :active_routes
def active_routes
{ controller: :compare }
end
override :title
def title
_('Compare')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
module MenuItems
class Contributors < ::Sidebars::MenuItem
override :link
def link
project_graph_path(context.project, context.current_ref)
end
override :active_routes
def active_routes
{ path: 'graphs#show' }
end
override :title
def title
_('Contributors')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
module MenuItems
class Files < ::Sidebars::MenuItem
override :link
def link
project_tree_path(context.project, context.current_ref)
end
override :active_routes
def active_routes
{ controller: %w[tree blob blame edit_tree new_tree find_file] }
end
override :title
def title
_('Files')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
module MenuItems
class Graphs < ::Sidebars::MenuItem
override :link
def link
project_network_path(context.project, context.current_ref)
end
override :active_routes
def active_routes
{ controller: :network }
end
override :title
def title
_('Graph')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module Repository
module MenuItems
class Tags < ::Sidebars::MenuItem
override :link
def link
project_tags_path(context.project)
end
override :active_routes
def active_routes
{ controller: :tags }
end
override :title
def title
_('Tags')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class RepositoryMenu < ::Sidebars::Menu
override :configure_menu_items
def configure_menu_items
return false unless can?(context.current_user, :download_code, context.project)
return false if context.project.empty_repo?
add_item(files_menu_item)
add_item(commits_menu_item)
add_item(branches_menu_item)
add_item(tags_menu_item)
add_item(contributors_menu_item)
add_item(graphs_menu_item)
add_item(compare_menu_item)
true
end
override :link
def link
project_tree_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-tree'
}
end
override :title
def title
_('Repository')
end
override :title_html_options
def title_html_options
{
id: 'js-onboarding-repo-link'
}
end
override :sprite_icon
def sprite_icon
'doc-text'
end
private
def files_menu_item
::Sidebars::MenuItem.new(
title: _('Files'),
link: project_tree_path(context.project, context.current_ref),
active_routes: { controller: %w[tree blob blame edit_tree new_tree find_file] },
item_id: :files
)
end
def commits_menu_item
::Sidebars::MenuItem.new(
title: _('Commits'),
link: project_commits_path(context.project, context.current_ref),
active_routes: { controller: %w(commit commits) },
item_id: :commits,
container_html_options: { id: 'js-onboarding-commits-link' }
)
end
def branches_menu_item
::Sidebars::MenuItem.new(
title: _('Branches'),
link: project_branches_path(context.project),
active_routes: { controller: :branches },
item_id: :branches,
container_html_options: { id: 'js-onboarding-branches-link' }
)
end
def tags_menu_item
::Sidebars::MenuItem.new(
title: _('Tags'),
link: project_tags_path(context.project),
item_id: :tags,
active_routes: { controller: :tags }
)
end
def contributors_menu_item
::Sidebars::MenuItem.new(
title: _('Contributors'),
link: project_graph_path(context.project, context.current_ref),
active_routes: { path: 'graphs#show' },
item_id: :contributors
)
end
def graphs_menu_item
::Sidebars::MenuItem.new(
title: _('Graph'),
link: project_network_path(context.project, context.current_ref),
active_routes: { controller: :network },
item_id: :graphs
)
end
def compare_menu_item
::Sidebars::MenuItem.new(
title: _('Compare'),
link: project_compare_index_path(context.project, from: context.project.repository.root_ref, to: context.current_ref),
active_routes: { controller: :compare },
item_id: :compare
)
end
end
end
end
end
Sidebars::Projects::Menus::RepositoryMenu.prepend_if_ee('EE::Sidebars::Projects::Menus::RepositoryMenu')
......@@ -3,17 +3,15 @@
module Sidebars
module Projects
module Menus
module Scope
class Menu < ::Sidebars::Menu
override :link
def link
project_path(context.project)
end
class ScopeMenu < ::Sidebars::Menu
override :link
def link
project_path(context.project)
end
override :title
def title
context.project.name
end
override :title
def title
context.project.name
end
end
end
......
......@@ -5,11 +5,11 @@ module Sidebars
class Panel < ::Sidebars::Panel
override :configure_menus
def configure_menus
set_scope_menu(Sidebars::Projects::Menus::Scope::Menu.new(context))
set_scope_menu(Sidebars::Projects::Menus::ScopeMenu.new(context))
add_menu(Sidebars::Projects::Menus::ProjectOverview::Menu.new(context))
add_menu(Sidebars::Projects::Menus::LearnGitlab::Menu.new(context))
add_menu(Sidebars::Projects::Menus::Repository::Menu.new(context))
add_menu(Sidebars::Projects::Menus::ProjectOverviewMenu.new(context))
add_menu(Sidebars::Projects::Menus::LearnGitlabMenu.new(context))
add_menu(Sidebars::Projects::Menus::RepositoryMenu.new(context))
end
override :render_raw_menus_partial
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Concerns::PositionableList do
subject do
Class.new do
include Sidebars::Concerns::PositionableList
end.new
end
describe '#add_element' do
it 'adds the element to the last position of the list' do
list = [1, 2]
subject.add_element(list, 3)
expect(list).to eq([1, 2, 3])
end
end
describe '#insert_element_before' do
let(:user) { build(:user) }
let(:list) { [1, user] }
it 'adds element before the specific element class' do
subject.insert_element_before(list, User, 2)
expect(list).to eq [1, 2, user]
end
context 'when reference element does not exist' do
it 'adds the element to the top of the list' do
subject.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
subject.insert_element_after(list, Integer, 2)
expect(list).to eq [1, 2, user]
end
context 'when reference element does not exist' do
it 'adds the element to the end of the list' do
subject.insert_element_after(list, Project, 2)
expect(list).to eq [1, user, 2]
end
end
end
end
......@@ -8,59 +8,82 @@ RSpec.describe Sidebars::Menu do
describe '#all_active_routes' do
it 'gathers all active routes of items and the current menu' do
menu_item1 = Sidebars::MenuItem.new(context)
menu_item2 = Sidebars::MenuItem.new(context)
menu_item3 = Sidebars::MenuItem.new(context)
menu.add_item(menu_item1)
menu.add_item(menu_item2)
menu.add_item(menu_item3)
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' }))
allow(menu).to receive(:active_routes).and_return({ path: 'foo' })
allow(menu_item1).to receive(:active_routes).and_return({ path: %w(bar test) })
allow(menu_item2).to receive(:active_routes).and_return({ controller: 'fooc' })
allow(menu_item3).to receive(:active_routes).and_return({ controller: 'barc' })
expect(menu.all_active_routes).to eq({ path: %w(foo bar test), controller: %w(fooc barc) })
end
it 'does not include routes for non renderable items' do
menu_item = Sidebars::MenuItem.new(context)
menu.add_item(menu_item)
allow(menu).to receive(:active_routes).and_return({ path: 'foo' })
allow(menu_item).to receive(:render?).and_return(false)
allow(menu_item).to receive(:active_routes).and_return({ controller: 'bar' })
expect(menu.all_active_routes).to eq({ path: ['foo'] })
end
end
describe '#render?' do
context 'when the menus has no items' do
it 'returns true' do
expect(menu.render?).to be true
it 'returns false' do
expect(menu.render?).to be false
end
end
context 'when the menu has items' do
let(:menu_item) { Sidebars::MenuItem.new(context) }
it 'returns true' do
menu.add_item(Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}))
before do
menu.add_item(menu_item)
expect(menu.render?).to be true
end
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 items are not renderable' do
it 'returns false' do
allow(menu_item).to receive(:render?).and_return(false)
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(menu.render?).to be false
end
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)
context 'when there are renderable items' do
it 'returns true' do
expect(menu.render?).to be true
end
expect(list).to eq [item1, item2, item3]
end
end
end
......
......@@ -26,9 +26,79 @@ RSpec.describe Sidebars::Panel do
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
end
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::LearnGitlab::Menu do
RSpec.describe Sidebars::Projects::Menus::LearnGitlabMenu do
let(:project) { build(:project) }
let(:experiment_enabled) { true }
let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project, learn_gitlab_experiment_enabled: experiment_enabled) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ProjectOverview::Menu do
let(:project) { build(:project) }
let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project) }
subject { described_class.new(context) }
it 'has the required items' do
items = subject.instance_variable_get(:@items)
expect(items[0]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Details)
expect(items[1]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Activity)
expect(items[2]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Releases)
end
end
......@@ -2,35 +2,35 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ProjectOverview::MenuItems::Releases do
RSpec.describe Sidebars::Projects::Menus::ProjectOverviewMenu 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 'Releases' do
subject { described_class.new(context).items.index { |e| e.item_id == :releases } }
describe '#render?' do
context 'when project repository is empty' do
it 'returns false' do
it 'does not include releases menu item' do
allow(project).to receive(:empty_repo?).and_return(true)
expect(subject.render?).to eq false
is_expected.to be_nil
end
end
context 'when project repository is not empty' do
context 'when user can read releases' do
it 'returns true' do
expect(subject.render?).to eq true
context 'when user can download code' do
it 'includes releases menu item' do
is_expected.to be_present
end
end
context 'when user cannot read releases' do
context 'when user cannot download code' do
let(:user) { nil }
it 'returns false' do
expect(subject.render?).to eq false
it 'does not include releases menu item' do
is_expected.to be_nil
end
end
end
......
......@@ -2,11 +2,11 @@
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::Repository::Menu do
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) }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: 'master') }
subject { described_class.new(context) }
......
......@@ -9,6 +9,6 @@ RSpec.describe Sidebars::Projects::Panel do
subject { described_class.new(context) }
it 'has a scope menu' do
expect(subject.scope_menu).to be_a(Sidebars::Projects::Menus::Scope::Menu)
expect(subject.scope_menu).to be_a(Sidebars::Projects::Menus::ScopeMenu)
end
end
......@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'shared/nav/_sidebar.html.haml' do
let(:project) { build(:project, id: non_existing_record_id) }
let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project)}
let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project) }
let(:sidebar) { Sidebars::Projects::Panel.new(context) }
before do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment