diff options
Diffstat (limited to 'spec/helpers/nav')
-rw-r--r-- | spec/helpers/nav/new_dropdown_helper_spec.rb | 320 | ||||
-rw-r--r-- | spec/helpers/nav/top_nav_helper_spec.rb | 235 |
2 files changed, 524 insertions, 31 deletions
diff --git a/spec/helpers/nav/new_dropdown_helper_spec.rb b/spec/helpers/nav/new_dropdown_helper_spec.rb new file mode 100644 index 00000000000..dd860ce3180 --- /dev/null +++ b/spec/helpers/nav/new_dropdown_helper_spec.rb @@ -0,0 +1,320 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Nav::NewDropdownHelper do + describe '#new_dropdown_view_model' do + let_it_be(:user) { build_stubbed(:user) } + + let(:current_user) { user } + let(:current_project) { nil } + let(:current_group) { nil } + + let(:with_can_create_project) { false } + let(:with_can_create_group) { false } + let(:with_can_create_snippet) { false } + let(:with_new_repo_experiment) { :control } + let(:with_invite_members_experiment) { false } + let(:with_invite_members_experiment_enabled) { false } + + let(:subject) { helper.new_dropdown_view_model(project: current_project, group: current_group) } + + def expected_menu_section(title:, menu_item:) + [ + { + title: title, + menu_items: [menu_item] + } + ] + end + + before do + stub_experiments(new_repo: with_new_repo_experiment) + allow(::Gitlab::Experimentation).to receive(:active?).with(:invite_members_new_dropdown) { with_invite_members_experiment } + allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { with_invite_members_experiment_enabled } + allow(helper).to receive(:tracking_label) { 'test_tracking_label' } + allow(helper).to receive(:experiment_tracking_category_and_group) { |x| x } + + allow(helper).to receive(:current_user) { current_user } + allow(helper).to receive(:can?) { false } + + allow(user).to receive(:can_create_project?) { with_can_create_project } + allow(user).to receive(:can_create_group?) { with_can_create_group } + allow(user).to receive(:can?).with(:create_snippet) { with_can_create_snippet } + end + + shared_examples 'new repo experiment shared example' do |title| + let(:with_new_repo_experiment) { :candidate } + + it 'has experiment project title' do + expect(subject[:menu_sections]).to match( + expected_menu_section( + title: title, + menu_item: a_hash_including(title: 'New project/repository') + ) + ) + end + end + + shared_examples 'invite member link shared example' do + it 'shows invite member link' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: expected_title, + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'invite', + title: 'Invite members', + href: expected_href, + data: { + track_event: 'click_link', + track_label: 'test_tracking_label', + track_property: :invite_members_new_dropdown + } + ) + ) + ) + end + + context 'with experiment enabled' do + let(:with_invite_members_experiment_enabled) { true } + + it 'shows emoji with invite member link' do + expect(subject[:menu_sections]).to match( + expected_menu_section( + title: expected_title, + menu_item: a_hash_including( + emoji: 'shaking_hands' + ) + ) + ) + end + end + end + + it 'has title' do + expect(subject[:title]).to eq('New...') + end + + context 'when current_user is nil (anonymous)' do + let(:current_user) { nil } + + it 'is nil' do + expect(subject).to be_nil + end + end + + context 'when group and project are nil' do + it 'has no menu sections' do + expect(subject[:menu_sections]).to eq([]) + end + + context 'when can create project' do + let(:with_can_create_project) { true } + + it 'has project menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'GitLab', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_project', + title: 'New project', + href: '/projects/new', + data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' } + ) + ) + ) + end + + it_behaves_like 'new repo experiment shared example', 'GitLab' + end + + context 'when can create group' do + let(:with_can_create_group) { true } + + it 'has group menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'GitLab', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_group', + title: 'New group', + href: '/groups/new', + data: { track_event: 'click_link_new_group', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + end + + context 'when can create snippet' do + let(:with_can_create_snippet) { true } + + it 'has new snippet menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'GitLab', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'general_new_snippet', + title: 'New snippet', + href: '/-/snippets/new', + data: { track_event: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_snippet_link' } + ) + ) + ) + end + end + end + + context 'with persisted group' do + let_it_be(:group) { build_stubbed(:group) } + + let(:current_group) { group } + let(:with_can_create_projects_in_group) { false } + let(:with_can_create_subgroup_in_group) { false } + let(:with_can_admin_in_group) { false } + + before do + allow(group).to receive(:persisted?) { true } + allow(helper).to receive(:can?).with(current_user, :create_projects, group) { with_can_create_projects_in_group } + allow(helper).to receive(:can?).with(current_user, :create_subgroup, group) { with_can_create_subgroup_in_group } + allow(helper).to receive(:can?).with(current_user, :admin_group_member, group) { with_can_admin_in_group } + end + + it 'has no menu sections' do + expect(subject[:menu_sections]).to eq([]) + end + + context 'when can create projects in group' do + let(:with_can_create_projects_in_group) { true } + + it 'has new project menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This group', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_project', + title: 'New project', + href: "/projects/new?namespace_id=#{group.id}", + data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + + it_behaves_like 'new repo experiment shared example', 'This group' + end + + context 'when can create subgroup' do + let(:with_can_create_subgroup_in_group) { true } + + it 'has new subgroup menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This group', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_subgroup', + title: 'New subgroup', + href: "/groups/new?parent_id=#{group.id}", + data: { track_event: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + end + + context 'when can invite members' do + let(:with_can_admin_in_group) { true } + let(:with_invite_members_experiment) { true } + let(:expected_title) { 'This group' } + let(:expected_href) { "/groups/#{group.full_path}/-/group_members" } + + it_behaves_like 'invite member link shared example' + end + end + + context 'with persisted project' do + let_it_be(:project) { build_stubbed(:project) } + let_it_be(:merge_project) { build_stubbed(:project) } + + let(:current_project) { project } + let(:with_show_new_issue_link) { false } + let(:with_merge_project) { nil } + let(:with_can_create_snippet_in_project) { false } + let(:with_can_import_members) { false } + + before do + allow(helper).to receive(:show_new_issue_link?).with(project) { with_show_new_issue_link } + allow(helper).to receive(:merge_request_source_project_for_project).with(project) { with_merge_project } + allow(helper).to receive(:can?).with(user, :create_snippet, project) { with_can_create_snippet_in_project } + allow(helper).to receive(:can_import_members?) { with_can_import_members } + end + + it 'has no menu sections' do + expect(subject[:menu_sections]).to eq([]) + end + + context 'with show_new_issue_link?' do + let(:with_show_new_issue_link) { true } + + it 'shows new issue menu item' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This project', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_issue', + title: 'New issue', + href: "/#{project.path_with_namespace}/-/issues/new", + data: { track_event: 'click_link_new_issue', track_label: 'plus_menu_dropdown', qa_selector: 'new_issue_link' } + ) + ) + ) + end + end + + context 'with merge project' do + let(:with_merge_project) { merge_project } + + it 'shows merge project' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This project', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_mr', + title: 'New merge request', + href: "/#{merge_project.path_with_namespace}/-/merge_requests/new", + data: { track_event: 'click_link_new_mr', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + end + + context 'when can create snippet' do + let(:with_can_create_snippet_in_project) { true } + + it 'shows new snippet' do + expect(subject[:menu_sections]).to eq( + expected_menu_section( + title: 'This project', + menu_item: ::Gitlab::Nav::TopNavMenuItem.build( + id: 'new_snippet', + title: 'New snippet', + href: "/#{project.path_with_namespace}/-/snippets/new", + data: { track_event: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' } + ) + ) + ) + end + end + + context 'when invite members experiment' do + let(:with_invite_members_experiment) { true } + let(:with_can_import_members) { true } + let(:expected_title) { 'This project' } + let(:expected_href) { "/#{project.path_with_namespace}/-/project_members" } + + it_behaves_like 'invite member link shared example' + end + end + end +end diff --git a/spec/helpers/nav/top_nav_helper_spec.rb b/spec/helpers/nav/top_nav_helper_spec.rb index 5c9e1e82b01..d87c751c62f 100644 --- a/spec/helpers/nav/top_nav_helper_spec.rb +++ b/spec/helpers/nav/top_nav_helper_spec.rb @@ -5,11 +5,17 @@ require 'spec_helper' RSpec.describe Nav::TopNavHelper do include ActionView::Helpers::UrlHelper - describe '#top_nav_view_model' do - let_it_be(:user) { build_stubbed(:user) } - let_it_be(:admin) { build_stubbed(:user, :admin) } + let_it_be(:user) { build_stubbed(:user) } + let_it_be(:admin) { build_stubbed(:user, :admin) } + let_it_be(:external_user) { build_stubbed(:user, :external, can_create_group: false) } + + let(:current_user) { nil } + + before do + allow(helper).to receive(:current_user) { current_user } + end - let(:current_user) { nil } + describe '#top_nav_view_model' do let(:current_project) { nil } let(:current_group) { nil } let(:with_current_settings_admin_mode) { false } @@ -26,7 +32,6 @@ RSpec.describe Nav::TopNavHelper do let(:active_title) { 'Menu' } before do - allow(helper).to receive(:current_user) { current_user } allow(Gitlab::CurrentSettings).to receive(:admin_mode) { with_current_settings_admin_mode } allow(helper).to receive(:header_link?).with(:admin_mode) { with_header_link_admin_mode } allow(Gitlab::Sherlock).to receive(:enabled?) { with_sherlock_enabled } @@ -48,30 +53,73 @@ RSpec.describe Nav::TopNavHelper do context 'when current_user is nil (anonymous)' do it 'has expected :primary' do - expected_projects_item = ::Gitlab::Nav::TopNavMenuItem.build( - href: '/explore', - icon: 'project', - id: 'project', - title: 'Projects' - ) - expected_groups_item = ::Gitlab::Nav::TopNavMenuItem.build( - href: '/explore/groups', - icon: 'group', - id: 'groups', - title: 'Groups' - ) - expected_snippets_item = ::Gitlab::Nav::TopNavMenuItem.build( - href: '/explore/snippets', - icon: 'snippet', - id: 'snippets', - title: 'Snippets' - ) - expect(subject[:primary]) - .to eq([ - expected_projects_item, - expected_groups_item, - expected_snippets_item - ]) + expected_primary = [ + ::Gitlab::Nav::TopNavMenuItem.build( + href: '/explore', + icon: 'project', + id: 'project', + title: 'Projects' + ), + ::Gitlab::Nav::TopNavMenuItem.build( + href: '/explore/groups', + icon: 'group', + id: 'groups', + title: 'Groups' + ), + ::Gitlab::Nav::TopNavMenuItem.build( + href: '/explore/snippets', + icon: 'snippet', + id: 'snippets', + title: 'Snippets' + ) + ] + expect(subject[:primary]).to eq(expected_primary) + end + + it 'has expected :shortcuts' do + expected_shortcuts = [ + ::Gitlab::Nav::TopNavMenuItem.build( + href: '/explore', + id: 'project-shortcut', + title: 'Projects', + css_class: 'dashboard-shortcuts-projects' + ), + ::Gitlab::Nav::TopNavMenuItem.build( + href: '/explore/groups', + id: 'groups-shortcut', + title: 'Groups', + css_class: 'dashboard-shortcuts-groups' + ), + ::Gitlab::Nav::TopNavMenuItem.build( + href: '/explore/snippets', + id: 'snippets-shortcut', + title: 'Snippets', + css_class: 'dashboard-shortcuts-snippets' + ) + ] + expect(subject[:shortcuts]).to eq(expected_shortcuts) + end + + it 'has expected :secondary' do + expected_secondary = [ + ::Gitlab::Nav::TopNavMenuItem.build( + href: '/help', + id: 'help', + title: 'Help', + icon: 'question-o' + ) + ] + expect(subject[:secondary]).to eq(expected_secondary) + end + + context 'with current nav as project' do + before do + helper.nav('project') + end + + it 'has expected :active' do + expect(subject[:primary].detect { |entry| entry[:id] == 'project' }[:active]).to eq(true) + end end end @@ -82,6 +130,7 @@ RSpec.describe Nav::TopNavHelper do expect(subject).to eq({ activeTitle: active_title, primary: [], secondary: [], + shortcuts: [], views: {} }) end @@ -105,6 +154,16 @@ RSpec.describe Nav::TopNavHelper do expect(subject[:primary]).to eq([expected_primary]) end + it 'has expected :shortcuts' do + expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build( + id: 'project-shortcut', + title: 'Projects', + href: '/dashboard/projects', + css_class: 'dashboard-shortcuts-projects' + ) + expect(subject[:shortcuts]).to eq([expected_shortcuts]) + end + context 'projects' do it 'has expected :currentUserName' do expect(projects_view[:currentUserName]).to eq(current_user.username) @@ -146,6 +205,16 @@ RSpec.describe Nav::TopNavHelper do expect(projects_view[:linksSecondary]).to eq(expected_links_secondary) end + context 'with current nav as project' do + before do + helper.nav('project') + end + + it 'has expected :active' do + expect(subject[:primary].detect { |entry| entry[:id] == 'project' }[:active]).to eq(true) + end + end + context 'with persisted project' do let_it_be(:project) { build_stubbed(:project) } @@ -191,6 +260,16 @@ RSpec.describe Nav::TopNavHelper do expect(subject[:primary]).to eq([expected_primary]) end + it 'has expected :shortcuts' do + expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build( + id: 'groups-shortcut', + title: 'Groups', + href: '/dashboard/groups', + css_class: 'dashboard-shortcuts-groups' + ) + expect(subject[:shortcuts]).to eq([expected_shortcuts]) + end + context 'groups' do it 'has expected :currentUserName' do expect(groups_view[:currentUserName]).to eq(current_user.username) @@ -219,7 +298,7 @@ RSpec.describe Nav::TopNavHelper do it 'has expected :linksSecondary' do expected_links_secondary = [ ::Gitlab::Nav::TopNavMenuItem.build( - href: '/groups/new#create-group-pane', + href: '/groups/new', id: 'create', title: 'Create group' ) @@ -227,6 +306,24 @@ RSpec.describe Nav::TopNavHelper do expect(groups_view[:linksSecondary]).to eq(expected_links_secondary) end + context 'with external user' do + let(:current_user) { external_user } + + it 'does not have create group link' do + expect(groups_view[:linksSecondary]).to eq([]) + end + end + + context 'with current nav as group' do + before do + helper.nav('group') + end + + it 'has expected :active' do + expect(subject[:primary].detect { |entry| entry[:id] == 'groups' }[:active]).to eq(true) + end + end + context 'with persisted group' do let_it_be(:group) { build_stubbed(:group) } @@ -268,6 +365,16 @@ RSpec.describe Nav::TopNavHelper do ) expect(subject[:primary]).to eq([expected_primary]) end + + it 'has expected :shortcuts' do + expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build( + id: 'milestones-shortcut', + title: 'Milestones', + href: '/dashboard/milestones', + css_class: 'dashboard-shortcuts-milestones' + ) + expect(subject[:shortcuts]).to eq([expected_shortcuts]) + end end context 'with snippets' do @@ -285,6 +392,16 @@ RSpec.describe Nav::TopNavHelper do ) expect(subject[:primary]).to eq([expected_primary]) end + + it 'has expected :shortcuts' do + expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build( + id: 'snippets-shortcut', + title: 'Snippets', + href: '/dashboard/snippets', + css_class: 'dashboard-shortcuts-snippets' + ) + expect(subject[:shortcuts]).to eq([expected_shortcuts]) + end end context 'with activity' do @@ -302,6 +419,16 @@ RSpec.describe Nav::TopNavHelper do ) expect(subject[:primary]).to eq([expected_primary]) end + + it 'has expected :shortcuts' do + expected_shortcuts = ::Gitlab::Nav::TopNavMenuItem.build( + id: 'activity-shortcut', + title: 'Activity', + href: '/dashboard/activity', + css_class: 'dashboard-shortcuts-activity' + ) + expect(subject[:shortcuts]).to eq([expected_shortcuts]) + end end context 'when sherlock is enabled' do @@ -352,7 +479,7 @@ RSpec.describe Nav::TopNavHelper do title: 'Leave Admin Mode', icon: 'lock-open', href: '/admin/session/destroy', - method: :post + data: { method: 'post' } ) expect(subject[:secondary].last).to eq(expected_leave_admin_mode_item) end @@ -373,4 +500,50 @@ RSpec.describe Nav::TopNavHelper do end end end + + describe '#top_nav_responsive_view_model' do + let_it_be(:project) { create(:project) } + let_it_be(:group) { create(:group) } + + let(:with_search) { false } + let(:with_new_view_model) { nil } + + let(:subject) { helper.top_nav_responsive_view_model(project: project, group: group) } + + before do + allow(helper).to receive(:header_link?).with(:search) { with_search } + allow(helper).to receive(:new_dropdown_view_model).with(project: project, group: group) { with_new_view_model } + end + + it 'has nil new subview' do + expect(subject[:views][:new]).to be_nil + end + + it 'has nil search subview' do + expect(subject[:views][:search]).to be_nil + end + + context 'with search' do + let(:with_search) { true } + + it 'has search subview' do + expect(subject[:views][:search]).to eq( + ::Gitlab::Nav::TopNavMenuItem.build( + id: 'search', + title: 'Search', + icon: 'search', + href: search_path + ) + ) + end + end + + context 'with new' do + let(:with_new_view_model) { { id: 'test-new-view-model' } } + + it 'has new subview' do + expect(subject[:views][:new]).to eq({ id: 'test-new-view-model' }) + end + end + end end |