Merge pull request #4764 from HDinger/feature/20504-create-top-level-menu-item-work-packages

[20504] Create top level menu item "Work packages"
pull/4801/head
ulferts 8 years ago committed by GitHub
commit 213caff8a3
  1. 7
      app/assets/stylesheets/layout/_top_menu.sass
  2. 4
      app/assets/stylesheets/specific/accessibility.sass
  3. 38
      app/controllers/work_packages_controller.rb
  4. 2
      app/views/layouts/base.html.erb
  5. 95
      config/initializers/menus.rb
  6. 44
      config/locales/en.yml
  7. 2
      config/routes.rb
  8. 2
      features/projects/archive.feature
  9. 16
      lib/redmine/menu_manager/menu_helper.rb
  10. 13
      lib/redmine/menu_manager/menu_item.rb
  11. 66
      lib/redmine/menu_manager/top_menu_helper.rb
  12. 16
      spec/features/menu_items/top_menu_item_spec.rb
  13. 198
      spec/features/menu_items/work_packages_menu_item_spec.rb
  14. 2
      spec_legacy/unit/lib/redmine_spec.rb

@ -148,7 +148,12 @@
&:nth-last-child(2)
margin-bottom: 6px
.drop-down--help
// Hack: Neccessary because we cannot include a <hr>-tag for the separator
// in the wp-menu. The class is now added to the link element.
.drop-down--work-packages .form--separator
padding-bottom: 2.25rem
.drop-down
.form--separator
margin-bottom: 5px
.drop-down--help-headline

@ -51,10 +51,6 @@ body.accessibility-mode
// Mark currently selected top menu items
#top-menu
li a,
li.drop-down a
border: 1px solid transparent
li a.selected,
li.drop-down.selected a
background: $main-menu-bg-hover-selected-background !important

@ -31,16 +31,6 @@ class WorkPackagesController < ApplicationController
DEFAULT_SORT_ORDER = ['parent', 'desc']
EXPORT_FORMATS = %w[atom rss xls csv pdf]
current_menu_item :index do |controller|
query = controller.instance_variable_get :"@query"
if query && query.persisted? && current = query.query_menu_item.try(:unique_name)
current
else
:work_packages
end
end
include QueriesHelper
include PaginationHelper
include SortHelper
@ -121,8 +111,32 @@ class WorkPackagesController < ApplicationController
render_404
end
current_menu_item :index do
:work_packages
# This takes care that the current position in the top menu is marked.
# Depending on the selected query an entry is highlighted in accessibility mode.
current_menu_item :index do |controller|
url_helper = OpenProject::StaticRouting::StaticUrlHelpers.new
url_helper.extend WorkPackagesFilterHelper
case controller.current_path
when url_helper.index_work_packages_path
:list_work_packages
when url_helper.new_work_packages_path
:new_work_packages
when url_helper.work_packages_assigned_to_me_path
:work_packages_filter_assigned_to_me
when url_helper.work_packages_reported_by_me_path
:work_packages_filter_reported_by_me
when url_helper.work_packages_responsible_for_path
:work_packages_filter_responsible_for
when url_helper.work_packages_watched_path
:work_packages_filter_watched_by_me
else
:work_packages
end
end
def current_path
request.fullpath
end
protected

@ -77,7 +77,7 @@ See doc/COPYRIGHT.rdoc for more details.
<h1 class="hidden-for-sighted">
<%= l(:label_top_menu) %>
</h1>
<%= render_top_menu_left %>
<%= render_top_menu_left(@project)%>
<div class="top-menu-items-right">
<%= render partial: 'search/mini_form' %>
<%= render_top_menu_right %>

@ -34,26 +34,20 @@ Redmine::MenuManager.map :top_menu do |menu|
{ controller: '/my', action: 'page' },
context: :main,
html: { class: 'icon5 icon-star' },
if: Proc.new { User.current.logged? }
if: Proc.new { User.current.logged? },
omit_path_check: true
# projects menu will be added by
# Redmine::MenuManager::TopMenuHelper#render_projects_top_menu_node
menu.push :work_packages,
{ controller: '/work_packages', project_id: nil, action: 'index' },
context: :modules,
caption: I18n.t('label_work_package_plural'),
if: Proc.new {
(User.current.logged? || !Setting.login_required?) &&
User.current.allowed_to?(:view_work_packages, nil, global: true)
}
menu.push :news,
{ controller: '/news', project_id: nil, action: 'index' },
context: :modules,
if: Proc.new {
(User.current.logged? || !Setting.login_required?) &&
User.current.allowed_to?(:view_news, nil, global: true)
}
},
omit_path_check: true
menu.push :time_sheet,
{ controller: '/time_entries', project_id: nil, action: 'index' },
context: :modules,
@ -61,27 +55,96 @@ Redmine::MenuManager.map :top_menu do |menu|
if: Proc.new {
(User.current.logged? || !Setting.login_required?) &&
User.current.allowed_to?(:view_time_entries, nil, global: true)
}
},
omit_path_check: true
menu.push :help, OpenProject::Static::Links.help_link,
last: true,
caption: '',
html: { accesskey: OpenProject::AccessKeys.key_for(:help),
title: I18n.t('label_help'),
class: 'icon5 icon-help1',
target: '_blank' }
target: '_blank' },
omit_path_check: true
# work packages menu will be added by
# Redmine::MenuManager::TopMenuHelper#render_work_packages_top_menu_node
menu.push :new_work_packages,
{ controller: '/work_packages', action: 'index', state: 'new' },
param: :project_id,
context: :work_packages,
caption: I18n.t(:label_work_package_new),
html: {
class: "icon-add icon4 form--separator",
accesskey: OpenProject::AccessKeys.key_for(:new_work_package)
},
if: Proc.new { |project|
User.current.allowed_to?(:add_work_packages, project, global: project.nil?)
}
menu.push :list_work_packages,
{ controller: '/work_packages', action: 'index', project_id: nil },
context: :work_packages,
caption: I18n.t(:label_all),
if: Proc.new {
User.current.allowed_to?(:view_work_packages, nil, global: true)
}
menu.push :work_packages_filter_assigned_to_me,
:work_packages_assigned_to_me_path,
context: :work_packages,
caption: I18n.t(:label_assigned_to_me),
if: Proc.new {
User.current.logged? &&
User.current.allowed_to?(:view_work_packages, nil, global: true)
},
omit_path_check: true
menu.push :work_packages_filter_reported_by_me,
:work_packages_reported_by_me_path,
context: :work_packages,
caption: I18n.t(:label_reported_by_me),
if: Proc.new {
User.current.logged? &&
User.current.allowed_to?(:view_work_packages, nil, global: true)
},
omit_path_check: true
menu.push :work_packages_filter_responsible_for,
:work_packages_responsible_for_path,
context: :work_packages,
caption: I18n.t(:label_responsible_for),
if: Proc.new {
User.current.logged? &&
User.current.allowed_to?(:view_work_packages, nil, global: true)
},
omit_path_check: true
menu.push :work_packages_filter_watched_by_me,
:work_packages_watched_path,
context: :work_packages,
caption: I18n.t(:label_watched_by_me),
if: Proc.new {
User.current.logged? &&
User.current.allowed_to?(:view_work_packages, nil, global: true)
},
omit_path_check: true
end
Redmine::MenuManager.map :account_menu do |menu|
menu.push :administration,
{ controller: '/admin', action: 'projects' },
html: { class: 'hidden-for-mobile' },
if: Proc.new { User.current.admin? }
if: Proc.new { User.current.admin? },
omit_path_check: true
menu.push :my_account,
{ controller: '/my', action: 'account' },
html: { class: 'hidden-for-mobile' },
if: Proc.new { User.current.logged? }
if: Proc.new { User.current.logged? },
omit_path_check: true
menu.push :logout, :signout_path,
if: Proc.new { User.current.logged? }
if: Proc.new { User.current.logged? },
omit_path_check: true
end
Redmine::MenuManager.map :application_menu do |_menu|
@ -218,7 +281,7 @@ Redmine::MenuManager.map :project_menu do |menu|
html: { class: 'icon2 icon-roadmap' }
menu.push :work_packages,
{ controller: '/work_packages', action: 'index' },
{ controller: '/work_packages', action: 'index', state: nil },
param: :project_id,
caption: :label_work_package_plural,
html: {

@ -863,7 +863,7 @@ en:
label_advanced_settings: "Advanced settings"
label_age: "Age"
label_ago: "days ago"
label_all: "all"
label_all: "All"
label_all_time: "all time"
label_all_words: "All words"
label_always_visible: "Always displayed"
@ -874,6 +874,7 @@ en:
label_api_access_key_type: "API"
label_applied_status: "Applied status"
label_ascending: "Ascending"
label_assigned_to_me: "Assigned to me"
label_assigned_to_me_work_packages: "Work packages assigned to me"
label_associated_revisions: "Associated revisions"
label_attachment_delete: "Delete file"
@ -1024,25 +1025,6 @@ en:
label_internal: "Internal"
label_invite_user: "Invite user"
label_show_hide: "Show/hide"
label_work_package_added: "Work package added"
label_work_package_category_new: "New category"
label_work_package_category_plural: "Work package categories"
label_work_package_hierarchy: "Work package hierarchy"
label_work_package_new: "New work package"
label_work_package_note_added: "Work package note added"
label_work_package_edit: "Edit work package %{name}"
label_work_package_plural: "Work packages"
label_work_package_priority_updated: "Work package priority updated"
label_work_package_status_new: "New status"
label_work_package_status_plural: "Work package statuses"
label_work_package_tracking: "Work package tracking"
label_work_package_updated: "Work package updated"
label_work_package_view_all: "View all work packages"
label_work_package_view_all_assigned_to_me: "View all work packages assigned to me"
label_work_package_view_all_reported_by_me: "View all work packages reported by me"
label_work_package_view_all_responsible_for: "View all work packages that I am responsible for"
label_work_package_view_all_watched: "View all watched work packages"
label_work_package_watchers: "Watchers"
label_journal_diff: "Description Comparison"
label_jump_to_a_project: "Jump to a project..."
label_language_based: "Based on user's language"
@ -1180,12 +1162,14 @@ en:
label_report: "Report"
label_report_bug: "Report a bug"
label_report_plural: "Reports"
label_reported_by_me: "Reported by me"
label_reported_work_packages: "Reported work packages"
label_reporting: "Reporting"
label_reporting_plural: "Reportings"
label_repository: "Repository"
label_repository_root: "Repository root"
label_repository_plural: "Repositories"
label_responsible_for: "I am responsible for"
label_responsible_for_work_packages: "Work packages I am responsible for"
label_result_plural: "Results"
label_reverse_chronological_order: "In reverse chronological order"
@ -1279,6 +1263,7 @@ en:
label_view_all_revisions: "View all revisions"
label_view_diff: "View differences"
label_view_revisions: "View revisions"
label_watched_by_me: "Watched by me"
label_watched_work_packages: "Watched work packages"
label_week: "Week"
label_wiki_content_added: "Wiki page added"
@ -1296,10 +1281,27 @@ en:
label_wiki_show_new_page_link: "Show submenu item 'Create new child page'"
label_wiki_show_submenu_item: "Show as submenu item of "
label_work_package: "Work package"
label_work_package_plural: "Work packages"
label_work_package_added: "Work package added"
label_work_package_category_new: "New category"
label_work_package_category_plural: "Work package categories"
label_work_package_hierarchy: "Work package hierarchy"
label_work_package_new: "New work package"
label_work_package_note_added: "Work package note added"
label_work_package_edit: "Edit work package %{name}"
label_work_package_plural: "Work packages"
label_work_package_priority_updated: "Work package priority updated"
label_work_package_status: "Work package status"
label_work_package_status_new: "New status"
label_work_package_status_plural: "Work package statuses"
label_work_package_tracking: "Work package tracking"
label_work_package_types: "Work package types"
label_work_package_updated: "Work package updated"
label_work_package_view_all: "View all work packages"
label_work_package_view_all_assigned_to_me: "View all work packages assigned to me"
label_work_package_view_all_reported_by_me: "View all work packages reported by me"
label_work_package_view_all_responsible_for: "View all work packages that I am responsible for"
label_work_package_view_all_watched: "View all watched work packages"
label_work_package_watchers: "Watchers"
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"

@ -286,7 +286,7 @@ OpenProject::Application.routes.draw do
# states managed by client-side routing on work_package#index
get '(/*state)' => 'work_packages#index', on: :collection, as: ''
get '/create_new' => 'work_packages#index', on: :collection, as: 'new_split'
get '/new' => 'work_packages#index', on: :collection, as: 'new'
get '/new' => 'work_packages#index', on: :collection, as: 'new', state: 'new'
end
resources :activity, :activities, only: :index, controller: 'activities'

@ -51,7 +51,7 @@ Feature: Navigating to reports page
When I go to the page of the project called "SubProject"
Then I should see "403"
When I go to the projects admin page
When I select "all" from "status"
When I select "All" from "status"
And I click on "Unarchive" within "tbody > tr:nth-of-type(1)"
Then I should be on the projects admin page
And I should see "ParentProject"

@ -79,7 +79,10 @@ module Redmine::MenuManager::MenuHelper
Redmine::MenuManager.loose :project_menu do |menu|
query_menu_items.each do |query_menu_item|
# url = project_work_packages_path(project, query_id: query_menu_item.navigatable_id) does not work because the authorization check fails
url = { controller: '/work_packages', action: 'index', params: { query_id: query_menu_item.navigatable_id } }
url = { controller: '/work_packages',
action: 'index',
state: nil,
params: { query_id: query_menu_item.navigatable_id } }
menu.push query_menu_item.unique_name,
url,
param: :project_id,
@ -112,13 +115,13 @@ module Redmine::MenuManager::MenuHelper
# Render a dropdown menu item with the given MenuItem children.
# Caller may add additional items through the optional block.
# Remaining options are passed through to +render_menu_dropdown+.
def render_menu_dropdown_with_items(label:, label_options:, items:, options: {})
def render_menu_dropdown_with_items(label:, label_options:, items:, project: nil, options: {})
selected = any_item_selected?(items)
label_node = render_drop_down_label_node(label, selected, label_options)
render_menu_dropdown(label_node, options) do
items.each do |item|
concat render_menu_node(item)
concat render_menu_node(item, project)
end
concat(yield) if block_given?
@ -238,8 +241,7 @@ module Redmine::MenuManager::MenuHelper
block_given? ? nil : items
end
def extract_node_details(node, project = nil)
item = node
def extract_node_details(item, project = nil)
url = case item.url
when Hash
project.nil? ? item.url : { item.param => project }.merge(item.url)
@ -263,9 +265,7 @@ module Redmine::MenuManager::MenuHelper
if node.condition && !node.condition.call(project)
# Condition that doesn't pass
return false
end
if project
elsif project && !node.omit_path_check
return user && user.allowed_to?(node.url, project)
else
# outside a project, all menu items allowed

@ -29,7 +29,15 @@
class Redmine::MenuManager::MenuItem < Redmine::MenuManager::TreeNode
include Redmine::I18n
attr_reader :name, :url, :param, :context, :condition, :parent, :child_menus, :last
attr_reader :name,
:url,
:param,
:context,
:condition,
:parent,
:child_menus,
:last,
:omit_path_check
def initialize(name, url, options)
raise ArgumentError, "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
@ -50,6 +58,7 @@ class Redmine::MenuManager::MenuItem < Redmine::MenuManager::TreeNode
@parent = options[:parent]
@child_menus = options[:children]
@last = options[:last] || false
@omit_path_check = options[:omit_path_check] || false
super @name.to_sym
end
@ -82,4 +91,6 @@ class Redmine::MenuManager::MenuItem < Redmine::MenuManager::TreeNode
old_condition = @condition
@condition = -> (project) { old_condition.call(project) && new_condition.call(project) }
end
alias :omit_path_check? :omit_path_check
end

@ -32,11 +32,13 @@ module Redmine::MenuManager::TopMenuHelper
include Redmine::MenuManager::TopMenu::HelpMenu
include Redmine::MenuManager::TopMenu::ProjectsMenu
def render_top_menu_left
def render_top_menu_left(project)
items = split_top_menu_into_main_or_more_menus(project)
content_tag :ul, id: 'account-nav-left', class: 'menu_root account-nav hidden-for-mobile' do
[render_main_top_menu_nodes,
[render_main_top_menu_nodes(items[:main]),
render_projects_top_menu_node,
render_module_top_menu_node].join.html_safe
render_work_packages_top_menu_node(project, items[:work_packages]),
render_module_top_menu_node(items[:modules])].join.html_safe
end
end
@ -104,7 +106,23 @@ module Redmine::MenuManager::TopMenuHelper
render partial: partial
end
def render_module_top_menu_node(items = more_top_menu_items)
def render_work_packages_top_menu_node(project, items)
return nil if items.empty?
render_menu_dropdown_with_items(
label: l(:label_work_package_plural),
label_options: { id: 'work-packages-menu', class: 'icon5 icon-work-packages' },
items: items,
project: project,
options: {
drop_down_class: 'drop-down--work-packages'
}
)
end
def render_module_top_menu_node(items)
return nil if items.empty?
render_menu_dropdown_with_items(
label: l(:label_modules),
label_options: { class: 'icon5 icon-modules' },
@ -113,43 +131,29 @@ module Redmine::MenuManager::TopMenuHelper
)
end
def render_main_top_menu_nodes(items = main_top_menu_items)
def render_main_top_menu_nodes(items)
items.map { |item|
render_menu_node(item)
}.join(' ')
end
# Menu items for the main top menu
def main_top_menu_items
split_top_menu_into_main_or_more_menus[:main]
end
# Menu items for the modules top menu
def more_top_menu_items
split_top_menu_into_main_or_more_menus[:modules]
end
def project_menu_items
split_top_menu_into_main_or_more_menus[:projects]
end
def help_menu_item
split_top_menu_into_main_or_more_menus[:help]
end
# Split the :top_menu into separate :main and :modules items
def split_top_menu_into_main_or_more_menus
@top_menu_split ||= begin
items = Hash.new { |h, k| h[k] = [] }
menu_items_for(:top_menu) do |item|
if item.name == :help
items[:help] = item
else
context = item.context || :modules
items[context] << item
end
# Split the :top_menu into separate :main, :work_package and :modules items
def split_top_menu_into_main_or_more_menus(project = nil)
items = Hash.new { |h, k| h[k] = [] }
menu_items_for(:top_menu, project) do |item|
if item.name == :help
items[:help] = item
else
context = item.context || :modules
items[context] << item
end
items
end
items
end
end

@ -33,10 +33,9 @@ feature 'Top menu items', js: true, selenium: true do
let(:modules) { find(:css, "[title=#{I18n.t('label_modules')}]") }
let(:news_item) { I18n.t('label_news_plural') }
let(:work_packages_item) { I18n.t('label_work_package_plural') }
let(:time_entries_item) { I18n.t('label_time_sheet_menu') }
let(:all_items) { [news_item, work_packages_item, time_entries_item] }
let(:all_items) { [news_item, time_entries_item] }
def has_menu_items(*labels)
labels.each do |l|
@ -61,20 +60,17 @@ feature 'Top menu items', js: true, selenium: true do
context 'as an admin' do
let(:user) { FactoryGirl.create :admin }
it 'displays all items' do
has_menu_items(work_packages_item, time_entries_item, news_item)
end
it 'visits the work package page' do
click_link work_packages_item
expect(current_path).to eq(work_packages_path)
has_menu_items(time_entries_item, news_item)
end
it 'visits the time sheet page' do
expect(page).to have_content(time_entries_item)
click_link time_entries_item
expect(current_path).to eq(time_entries_path)
end
it 'visits the work package page' do
it 'visits the news page' do
expect(page).to have_content(news_item)
click_link news_item
expect(current_path).to eq(news_index_path)
end
@ -88,7 +84,7 @@ feature 'Top menu items', js: true, selenium: true do
context 'as a user with permissions', allowed_to: true do
it 'displays all options' do
has_menu_items(work_packages_item, time_entries_item, news_item)
has_menu_items(time_entries_item, news_item)
end
end

@ -0,0 +1,198 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
feature 'Work packages top menu items', js: true, selenium: true do
include WorkPackagesFilterHelper
let(:user) { FactoryGirl.create :user }
let(:project) { FactoryGirl.create(:project, is_public: false) }
let(:new_wp_item) { I18n.t('label_work_package_new') }
let(:all_wp_item) { I18n.t('label_all') }
let(:assigned_wp_item) { I18n.t('label_assigned_to_me') }
let(:reported_wp_item) { I18n.t('label_reported_by_me') }
let(:responsible_wp_item) { I18n.t('label_responsible_for') }
let(:watched_wp_item) { I18n.t('label_watched_by_me') }
let(:all_items) {
[new_wp_item, all_wp_item, assigned_wp_item,
reported_wp_item, responsible_wp_item, watched_wp_item]
}
def has_menu_items(*labels)
labels.each do |l|
expect(page).to have_link(l)
end
(all_items - labels).each do |l|
expect(page).not_to have_link(l)
end
end
before do
allow(User).to receive(:current).and_return user
end
context 'as an admin' do
let(:work_packages) { find(:css, '#work-packages-menu') }
let(:user) { FactoryGirl.create :admin }
before do
visit root_path
work_packages.click
end
it 'displays all items' do
has_menu_items(new_wp_item,
all_wp_item,
assigned_wp_item,
reported_wp_item,
responsible_wp_item,
watched_wp_item)
end
it 'visits the new work package page' do
expect(page).to have_content(new_wp_item)
click_link new_wp_item
expect(page).to have_current_path(new_work_packages_path)
end
it 'visits the all work packages page' do
expect(page).to have_content(all_wp_item)
click_link all_wp_item
expect(page).to have_current_path(index_work_packages_path)
end
it 'visits the work packages assigned to me page' do
expect(page).to have_content(assigned_wp_item)
click_link assigned_wp_item
expect(page).to have_current_path(work_packages_assigned_to_me_path)
end
it 'visits the work packages reported by me page' do
expect(page).to have_content(reported_wp_item)
click_link reported_wp_item
expect(page).to have_current_path(work_packages_reported_by_me_path)
end
it 'visits the work packages I am responsible for page' do
expect(page).to have_content(responsible_wp_item)
click_link responsible_wp_item
expect(page).to have_current_path(work_packages_responsible_for_path)
end
it 'visits the work packages watched by me page' do
expect(page).to have_content(watched_wp_item)
click_link watched_wp_item
expect(page).to have_current_path(work_packages_watched_path)
end
it 'visits the projects new work package page' do
visit project_path(project)
work_packages.click
expect(page).to have_content(new_wp_item)
click_link new_wp_item
expect(page).to have_current_path(new_project_work_packages_path(project))
end
end
context 'as a user with permissions' do
let(:user) { FactoryGirl.create(:user, member_in_project: project, member_through_role: role) }
let(:role) {
FactoryGirl.create(:role, permissions: [:create_work_packages,
:add_work_packages,
:view_work_packages])
}
let(:work_packages) { find(:css, '#work-packages-menu') }
before do
visit root_path
work_packages.click
end
it 'displays all options' do
has_menu_items(new_wp_item,
all_wp_item,
assigned_wp_item,
reported_wp_item,
responsible_wp_item,
watched_wp_item)
end
end
context 'as a user without any permission', allowed_to: false do
before do
visit root_path
end
it 'shows no top menu entry Work packages' do
has_menu_items
expect(page).not_to have_css('#work-packages-menu')
end
end
context 'as a user who is logged in but is not allowed to add work packages' do
let(:user) { FactoryGirl.create(:user, member_in_project: project, member_through_role: role) }
let(:role) { FactoryGirl.create(:role, permissions: [:view_work_packages]) }
let(:work_packages) { find(:css, '#work-packages-menu') }
before do
visit root_path
work_packages.click
end
it 'displays no add new work package option' do
has_menu_items(all_wp_item,
assigned_wp_item,
reported_wp_item,
responsible_wp_item,
watched_wp_item)
end
end
context 'as a user who is not logged in' do
let(:user) { FactoryGirl.create(:anonymous) }
let(:role) {
FactoryGirl.create(:anonymous_role,
permissions: [:create_work_packages,
:add_work_packages,
:view_work_packages])
}
let(:work_packages) { find(:css, '#work-packages-menu') }
before do
role
visit root_path
work_packages.click
end
it 'displays only add new work package' do
has_menu_items(new_wp_item, all_wp_item)
end
end
end

@ -50,7 +50,7 @@ describe Redmine do
it 'should top_menu' do
assert_number_of_items_in_menu :top_menu, 6
assert_menu_contains_item_named :top_menu, :my_page
assert_menu_contains_item_named :top_menu, :work_packages
assert_menu_contains_item_named :top_menu, :list_work_packages
assert_menu_contains_item_named :top_menu, :news
assert_menu_contains_item_named :top_menu, :time_sheet
# do not test :projects here. it does not appear in the top_menu data structure, but will be generated by the TopMenuHelper

Loading…
Cancel
Save