diff --git a/LICENSE b/LICENSE index 81bed39..72ca3a1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 maxrossello +Copyright (c) 2018 Massimo Rossello Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/init.rb b/init.rb index fa51c77..662e8fc 100644 --- a/init.rb +++ b/init.rb @@ -1,3 +1,24 @@ +# Redmine plugin for Better Overviews +# Copyright (C) 2018 Massimo Rossello +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + require 'redmine' Rails.logger.info 'Better project overview' diff --git a/test/fixtures/member_roles.yml b/test/fixtures/member_roles.yml new file mode 100644 index 0000000..2c5c82e --- /dev/null +++ b/test/fixtures/member_roles.yml @@ -0,0 +1,53 @@ +--- +member_roles_001: + id: 1 + role_id: 1 + member_id: 1 +member_roles_002: + id: 2 + role_id: 2 + member_id: 2 +member_roles_003: + id: 3 + role_id: 2 + member_id: 3 +member_roles_004: + id: 4 + role_id: 2 + member_id: 4 +member_roles_005: + id: 5 + role_id: 1 + member_id: 5 +member_roles_006: + id: 6 + role_id: 1 + member_id: 6 +member_roles_007: + id: 7 + role_id: 2 + member_id: 6 +member_roles_008: + id: 8 + role_id: 1 + member_id: 7 + inherited_from: 6 +member_roles_009: + id: 9 + role_id: 2 + member_id: 7 + inherited_from: 7 +member_roles_010: + id: 10 + role_id: 2 + member_id: 9 + inherited_from: +member_roles_011: + id: 11 + role_id: 2 + member_id: 10 + inherited_from: 10 +member_roles_012: + id: 12 + role_id: 1 + member_id: 8 diff --git a/test/fixtures/members.yml b/test/fixtures/members.yml new file mode 100644 index 0000000..f4d39fb --- /dev/null +++ b/test/fixtures/members.yml @@ -0,0 +1,62 @@ +--- +members_001: + created_on: 2006-07-19 19:35:33 +02:00 + project_id: 1 + id: 1 + user_id: 2 + mail_notification: true +members_002: + created_on: 2006-07-19 19:35:36 +02:00 + project_id: 1 + id: 2 + user_id: 3 + mail_notification: true +members_003: + created_on: 2006-07-19 19:35:36 +02:00 + project_id: 2 + id: 3 + user_id: 2 + mail_notification: true +members_004: + id: 4 + created_on: 2006-07-19 19:35:36 +02:00 + project_id: 1 + # Locked user + user_id: 5 + mail_notification: true +members_005: + id: 5 + created_on: 2006-07-19 19:35:33 +02:00 + project_id: 5 + user_id: 2 + mail_notification: true +members_006: + id: 6 + created_on: 2006-07-19 19:35:33 +02:00 + project_id: 5 + user_id: 10 + mail_notification: false +members_007: + id: 7 + created_on: 2006-07-19 19:35:33 +02:00 + project_id: 5 + user_id: 8 + mail_notification: false +members_008: + created_on: 2006-07-19 19:35:33 +02:00 + project_id: 5 + id: 8 + user_id: 1 + mail_notification: true +members_009: + id: 9 + created_on: 2006-07-19 19:35:33 +02:00 + project_id: 2 + user_id: 11 + mail_notification: false +members_010: + id: 10 + created_on: 2006-07-19 19:35:33 +02:00 + project_id: 2 + user_id: 8 + mail_notification: false diff --git a/test/fixtures/projects.yml b/test/fixtures/projects.yml new file mode 100644 index 0000000..474a1cf --- /dev/null +++ b/test/fixtures/projects.yml @@ -0,0 +1,73 @@ +--- +projects_001: + created_on: 2006-07-19 19:13:59 +02:00 + name: eCookbook + updated_on: 2006-07-19 22:53:01 +02:00 + id: 1 + description: Recipes management application + homepage: http://ecookbook.somenet.foo/ + is_public: true + identifier: ecookbook + parent_id: + lft: 1 + rgt: 10 +projects_002: + created_on: 2006-07-19 19:14:19 +02:00 + name: OnlineStore + updated_on: 2006-07-19 19:14:19 +02:00 + id: 2 + description: E-commerce web site + homepage: "" + is_public: false + identifier: onlinestore + parent_id: + lft: 11 + rgt: 12 +projects_003: + created_on: 2006-07-19 19:15:21 +02:00 + name: eCookbook Subproject 1 + updated_on: 2006-07-19 19:18:12 +02:00 + id: 3 + description: eCookBook Subproject 1 + homepage: "" + is_public: true + identifier: subproject1 + parent_id: 1 + lft: 6 + rgt: 7 +projects_004: + created_on: 2006-07-19 19:15:51 +02:00 + name: eCookbook Subproject 2 + updated_on: 2006-07-19 19:17:07 +02:00 + id: 4 + description: eCookbook Subproject 2 + homepage: "" + is_public: true + identifier: subproject2 + parent_id: 1 + lft: 8 + rgt: 9 +projects_005: + created_on: 2006-07-19 19:15:51 +02:00 + name: Private child of eCookbook + updated_on: 2006-07-19 19:17:07 +02:00 + id: 5 + description: This is a private subproject of a public project + homepage: "" + is_public: false + identifier: private-child + parent_id: 1 + lft: 2 + rgt: 5 +projects_006: + created_on: 2006-07-19 19:15:51 +02:00 + name: Child of private child + updated_on: 2006-07-19 19:17:07 +02:00 + id: 6 + description: This is a public subproject of a private project + homepage: "" + is_public: true + identifier: project6 + parent_id: 5 + lft: 3 + rgt: 4 diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml new file mode 100644 index 0000000..ce7e1b4 --- /dev/null +++ b/test/fixtures/roles.yml @@ -0,0 +1,217 @@ +--- +roles_001: + name: Manager + id: 1 + builtin: 0 + issues_visibility: all + users_visibility: all + permissions: | + --- + - :add_project + - :edit_project + - :close_project + - :select_project_modules + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :copy_issues + - :manage_issue_relations + - :manage_subtasks + - :add_issue_notes + - :delete_issues + - :view_issue_watchers + - :add_issue_watchers + - :set_issues_private + - :set_notes_private + - :view_private_notes + - :delete_issue_watchers + - :manage_public_queries + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :edit_time_entries + - :delete_time_entries + - :view_news + - :manage_news + - :comment_news + - :view_documents + - :add_documents + - :edit_documents + - :delete_documents + - :view_wiki_pages + - :export_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :delete_wiki_pages_attachments + - :protect_wiki_pages + - :delete_wiki_pages + - :rename_wiki_pages + - :view_messages + - :add_messages + - :edit_messages + - :delete_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :manage_repository + - :view_changesets + - :manage_related_issues + - :manage_project_activities + - :import_issues + + position: 1 +roles_002: + name: Developer + id: 2 + builtin: 0 + issues_visibility: default + users_visibility: all + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :copy_issues + - :manage_issue_relations + - :manage_subtasks + - :add_issue_notes + - :delete_issues + - :view_issue_watchers + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :edit_own_time_entries + - :view_news + - :manage_news + - :comment_news + - :view_documents + - :add_documents + - :edit_documents + - :delete_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :protect_wiki_pages + - :delete_wiki_pages + - :view_messages + - :add_messages + - :edit_own_messages + - :delete_own_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 2 +roles_003: + name: Reporter + id: 3 + builtin: 0 + issues_visibility: default + users_visibility: all + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :view_issue_watchers + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :view_news + - :manage_news + - :comment_news + - :view_documents + - :add_documents + - :edit_documents + - :delete_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :delete_wiki_pages + - :view_messages + - :add_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 3 +roles_004: + name: Non member + id: 4 + builtin: 1 + issues_visibility: default + users_visibility: all + permissions: | + --- + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :view_news + - :comment_news + - :view_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :view_messages + - :add_messages + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 1 +roles_005: + name: Anonymous + id: 5 + builtin: 2 + issues_visibility: default + users_visibility: all + permissions: | + --- + - :view_issues + - :add_issue_notes + - :view_gantt + - :view_calendar + - :view_time_entries + - :view_news + - :view_documents + - :view_wiki_pages + - :view_wiki_edits + - :view_messages + - :view_files + - :browse_repository + - :view_changesets + + position: 1 + diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000..986ed5d --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,171 @@ +--- +users_001: + created_on: 2006-07-19 19:12:21 +02:00 + status: 1 + last_login_on: 2006-07-19 22:57:52 +02:00 + language: en + # password = admin + salt: 82090c953c4a0000a7db253b0691a6b4 + hashed_password: b5b6ff9543bf1387374cdfa27a54c96d236a7150 + updated_on: 2006-07-19 22:57:52 +02:00 + admin: true + lastname: Admin + firstname: Redmine + id: 1 + auth_source_id: + mail_notification: all + login: admin + type: User +users_002: + created_on: 2006-07-19 19:32:09 +02:00 + status: 1 + last_login_on: 2006-07-19 22:42:15 +02:00 + language: en + # password = jsmith + salt: 67eb4732624d5a7753dcea7ce0bb7d7d + hashed_password: bfbe06043353a677d0215b26a5800d128d5413bc + updated_on: 2006-07-19 22:42:15 +02:00 + admin: false + lastname: Smith + firstname: John + id: 2 + auth_source_id: + mail_notification: all + login: jsmith + type: User +users_003: + created_on: 2006-07-19 19:33:19 +02:00 + status: 1 + last_login_on: + language: en + # password = foo + salt: 7599f9963ec07b5a3b55b354407120c0 + hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed + updated_on: 2006-07-19 19:33:19 +02:00 + admin: false + lastname: Lopper + firstname: Dave + id: 3 + auth_source_id: + mail_notification: all + login: dlopper + type: User +users_004: + created_on: 2006-07-19 19:34:07 +02:00 + status: 1 + last_login_on: + language: en + # password = foo + salt: 3126f764c3c5ac61cbfc103f25f934cf + hashed_password: 9e4dd7eeb172c12a0691a6d9d3a269f7e9fe671b + updated_on: 2006-07-19 19:34:07 +02:00 + admin: false + lastname: Hill + firstname: Robert + id: 4 + auth_source_id: + mail_notification: all + login: rhill + type: User +users_005: + id: 5 + created_on: 2006-07-19 19:33:19 +02:00 + # Locked + status: 3 + last_login_on: + language: en + hashed_password: 1 + updated_on: 2006-07-19 19:33:19 +02:00 + admin: false + lastname: Lopper2 + firstname: Dave2 + auth_source_id: + mail_notification: all + login: dlopper2 + type: User +users_006: + id: 6 + created_on: 2006-07-19 19:33:19 +02:00 + status: 0 + last_login_on: + language: '' + hashed_password: 1 + updated_on: 2006-07-19 19:33:19 +02:00 + admin: false + lastname: Anonymous + firstname: '' + auth_source_id: + mail_notification: only_my_events + login: '' + type: AnonymousUser +users_007: + # A user who does not belong to any project + id: 7 + created_on: 2006-07-19 19:33:19 +02:00 + status: 1 + last_login_on: + language: 'en' + # password = foo + salt: 7599f9963ec07b5a3b55b354407120c0 + hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed + updated_on: 2006-07-19 19:33:19 +02:00 + admin: false + lastname: One + firstname: Some + auth_source_id: + mail_notification: only_my_events + login: someone + type: User +users_008: + id: 8 + created_on: 2006-07-19 19:33:19 +02:00 + status: 1 + last_login_on: + language: 'it' + # password = foo + salt: 7599f9963ec07b5a3b55b354407120c0 + hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed + updated_on: 2006-07-19 19:33:19 +02:00 + admin: false + lastname: Misc + firstname: User + auth_source_id: + mail_notification: only_my_events + login: miscuser8 + type: User +users_009: + id: 9 + created_on: 2006-07-19 19:33:19 +02:00 + status: 1 + last_login_on: + language: 'it' + hashed_password: 1 + updated_on: 2006-07-19 19:33:19 +02:00 + admin: false + lastname: Misc + firstname: User + auth_source_id: + mail_notification: only_my_events + login: miscuser9 + type: User +groups_010: + id: 10 + lastname: A Team + type: Group + status: 1 +groups_011: + id: 11 + lastname: B Team + type: Group + status: 1 +groups_non_member: + id: 12 + lastname: Non member users + type: GroupNonMember + status: 1 +groups_anonymous: + id: 13 + lastname: Anonymous users + type: GroupAnonymous + status: 1 + diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb new file mode 100644 index 0000000..145601b --- /dev/null +++ b/test/functional/projects_controller_test.rb @@ -0,0 +1,101 @@ +# Redmine - project management software +# Copyright (C) 2006-2017 Jean-Philippe Lang +# +# Redmine plugin for Better Overviews +# Copyright (C) 2018 Massimo Rossello +# +# 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. + +require File.expand_path('../../test_helper', __FILE__) + +class ProjectsControllerTest < Redmine::ControllerTest + fixtures :projects, :custom_fields, :custom_values, + :users, :roles, :members, :member_roles + + def setup + @request.session[:user_id] = nil + Setting.default_language = 'en' + end + + def test_show_should_display_description_in_a_box + get :show, :params => { + :id => 'ecookbook' + } + assert_response :success + + assert_select '.box p', :text => /Recipes management application/ + end + + def test_show_should_display_homepage_in_a_box + get :show, :params => { + :id => 'ecookbook' + } + assert_response :success + + assert_select '.box h3', :text => /Homepage/ + assert_select '.homepage a' + end + + def test_show_should_display_visible_custom_fields_in_a_box + ProjectCustomField.find_by_name('Development status').update_attribute :visible, true + get :show, :params => { + :id => 'ecookbook' + } + assert_response :success + + assert_select '.box h3', :text => /Development status/ + assert_select '.custom', :text => /Stable/ + end + + def test_show_should_not_display_blank_custom_fields_with_multiple_values + f1 = ProjectCustomField.generate! :field_format => 'list', :possible_values => %w(Foo Bar), :multiple => true + f2 = ProjectCustomField.generate! :field_format => 'list', :possible_values => %w(Baz Qux), :multiple => true + project = Project.generate!(:custom_field_values => {f2.id.to_s => %w(Qux)}) + + get :show, :params => { + :id => project.id + } + assert_response :success + + assert_select 'h3', :text => /#{f1.name}/, :count => 0 + assert_select 'h3', :text => /#{f2.name}/ + end + + def test_show_should_display_visible_child_projects_in_a_box + get :show, :params => { + :id => 'ecookbook' + } + assert_response :success + + assert_select '.box h3', :text => /#{I18n.t(:label_subproject_plural)}/ + assert_select '.projects .list a', :text => /eCookbook Subproject 1/ + assert_select '.projects .list a', :text => /eCookbook Subproject 2/ + assert_select '.projects .list a', :text => /Private child of eCookbook/, :count => 0 + end + + def test_show_should_display_users_private_child_projects_in_a_box + @request.session[:user_id] = 2 # manager who is a member of the private subproject + get :show, :params => { + :id => 'ecookbook' + } + assert_response :success + + assert_select '.box h3', :text => /#{I18n.t(:label_subproject_plural)}/ + assert_select '.projects .list a', :text => /eCookbook Subproject 1/ + assert_select '.projects .list a', :text => /eCookbook Subproject 2/ + assert_select '.projects .list a', :text => /Private child of eCookbook/ + end + +end diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..88217d6 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,23 @@ +# Redmine plugin for Better Overviews +# Copyright (C) 2018 Massimo Rossello +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Load the Redmine helper +require File.expand_path('../../../../test/test_helper', __FILE__)