diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-19 15:44:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-19 15:44:42 +0000 |
commit | 4555e1b21c365ed8303ffb7a3325d773c9b8bf31 (patch) | |
tree | 5423a1c7516cffe36384133ade12572cf709398d /spec/lib/sidebars/projects | |
parent | e570267f2f6b326480d284e0164a6464ba4081bc (diff) | |
download | gitlab-ce-4555e1b21c365ed8303ffb7a3325d773c9b8bf31.tar.gz |
Add latest changes from gitlab-org/gitlab@13-12-stable-eev13.12.0-rc42
Diffstat (limited to 'spec/lib/sidebars/projects')
21 files changed, 1578 insertions, 0 deletions
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 |