##// END OF EJS Templates
Fixed: Calendar and Gantt show private subprojects even if current user is not a member of them (#1217)....
Jean-Philippe Lang -
r1416:7ee38a95a005
parent child
Show More
@@ -1,256 +1,257
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Project < ActiveRecord::Base
19 19 # Project statuses
20 20 STATUS_ACTIVE = 1
21 21 STATUS_ARCHIVED = 9
22 22
23 23 has_many :members, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
24 24 has_many :users, :through => :members
25 25 has_many :custom_values, :dependent => :delete_all, :as => :customized
26 26 has_many :enabled_modules, :dependent => :delete_all
27 27 has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
28 28 has_many :issues, :dependent => :destroy, :order => "#{Issue.table_name}.created_on DESC", :include => [:status, :tracker]
29 29 has_many :issue_changes, :through => :issues, :source => :journals
30 30 has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
31 31 has_many :time_entries, :dependent => :delete_all
32 32 has_many :queries, :dependent => :delete_all
33 33 has_many :documents, :dependent => :destroy
34 34 has_many :news, :dependent => :delete_all, :include => :author
35 35 has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
36 36 has_many :boards, :dependent => :destroy, :order => "position ASC"
37 37 has_one :repository, :dependent => :destroy
38 38 has_many :changesets, :through => :repository
39 39 has_one :wiki, :dependent => :destroy
40 40 # Custom field for the project issues
41 41 has_and_belongs_to_many :custom_fields,
42 42 :class_name => 'IssueCustomField',
43 43 :order => "#{CustomField.table_name}.position",
44 44 :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
45 45 :association_foreign_key => 'custom_field_id'
46 46
47 47 acts_as_tree :order => "name", :counter_cache => true
48 48
49 49 acts_as_searchable :columns => ['name', 'description'], :project_key => 'id'
50 50 acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"},
51 51 :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o.id}}
52 52
53 53 attr_protected :status, :enabled_module_names
54 54
55 55 validates_presence_of :name, :identifier
56 56 validates_uniqueness_of :name, :identifier
57 57 validates_associated :custom_values, :on => :update
58 58 validates_associated :repository, :wiki
59 59 validates_length_of :name, :maximum => 30
60 60 validates_length_of :homepage, :maximum => 60
61 61 validates_length_of :identifier, :in => 3..20
62 62 validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
63 63
64 64 before_destroy :delete_all_members
65 65
66 66 def identifier=(identifier)
67 67 super unless identifier_frozen?
68 68 end
69 69
70 70 def identifier_frozen?
71 71 errors[:identifier].nil? && !(new_record? || identifier.blank?)
72 72 end
73 73
74 74 def issues_with_subprojects(include_subprojects=false)
75 75 conditions = nil
76 if include_subprojects && !active_children.empty?
77 ids = [id] + active_children.collect {|c| c.id}
78 conditions = ["#{Project.table_name}.id IN (#{ids.join(',')})"]
76 if include_subprojects
77 ids = [id] + child_ids
78 conditions = ["#{Project.table_name}.id IN (#{ids.join(',')}) AND #{Project.visible_by}"]
79 79 end
80 80 conditions ||= ["#{Project.table_name}.id = ?", id]
81 81 # Quick and dirty fix for Rails 2 compatibility
82 82 Issue.send(:with_scope, :find => { :conditions => conditions }) do
83 83 Version.send(:with_scope, :find => { :conditions => conditions }) do
84 84 yield
85 85 end
86 86 end
87 87 end
88 88
89 89 # returns latest created projects
90 90 # non public projects will be returned only if user is a member of those
91 91 def self.latest(user=nil, count=5)
92 92 find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC")
93 93 end
94 94
95 95 def self.visible_by(user=nil)
96 user ||= User.current
96 97 if user && user.admin?
97 98 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
98 99 elsif user && user.memberships.any?
99 100 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND (#{Project.table_name}.is_public = #{connection.quoted_true} or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')}))"
100 101 else
101 102 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = #{connection.quoted_true}"
102 103 end
103 104 end
104 105
105 106 def self.allowed_to_condition(user, permission, options={})
106 107 statements = []
107 108 base_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
108 109 if options[:project]
109 110 project_statement = "#{Project.table_name}.id = #{options[:project].id}"
110 111 project_statement << " OR #{Project.table_name}.parent_id = #{options[:project].id}" if options[:with_subprojects]
111 112 base_statement = "(#{project_statement}) AND (#{base_statement})"
112 113 end
113 114 if user.admin?
114 115 # no restriction
115 116 elsif user.logged?
116 117 statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if Role.non_member.allowed_to?(permission)
117 118 allowed_project_ids = user.memberships.select {|m| m.role.allowed_to?(permission)}.collect {|m| m.project_id}
118 119 statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any?
119 120 elsif Role.anonymous.allowed_to?(permission)
120 121 # anonymous user allowed on public project
121 122 statements << "#{Project.table_name}.is_public = #{connection.quoted_true}"
122 123 else
123 124 # anonymous user is not authorized
124 125 statements << "1=0"
125 126 end
126 127 statements.empty? ? base_statement : "((#{base_statement}) AND (#{statements.join(' OR ')}))"
127 128 end
128 129
129 130 def project_condition(with_subprojects)
130 131 cond = "#{Project.table_name}.id = #{id}"
131 132 cond = "(#{cond} OR #{Project.table_name}.parent_id = #{id})" if with_subprojects
132 133 cond
133 134 end
134 135
135 136 def self.find(*args)
136 137 if args.first && args.first.is_a?(String) && !args.first.match(/^\d*$/)
137 138 project = find_by_identifier(*args)
138 139 raise ActiveRecord::RecordNotFound, "Couldn't find Project with identifier=#{args.first}" if project.nil?
139 140 project
140 141 else
141 142 super
142 143 end
143 144 end
144 145
145 146 def to_param
146 147 identifier
147 148 end
148 149
149 150 def active?
150 151 self.status == STATUS_ACTIVE
151 152 end
152 153
153 154 def archive
154 155 # Archive subprojects if any
155 156 children.each do |subproject|
156 157 subproject.archive
157 158 end
158 159 update_attribute :status, STATUS_ARCHIVED
159 160 end
160 161
161 162 def unarchive
162 163 return false if parent && !parent.active?
163 164 update_attribute :status, STATUS_ACTIVE
164 165 end
165 166
166 167 def active_children
167 168 children.select {|child| child.active?}
168 169 end
169 170
170 171 # Returns an array of the trackers used by the project and its sub projects
171 172 def rolled_up_trackers
172 173 @rolled_up_trackers ||=
173 174 Tracker.find(:all, :include => :projects,
174 175 :select => "DISTINCT #{Tracker.table_name}.*",
175 176 :conditions => ["#{Project.table_name}.id = ? OR #{Project.table_name}.parent_id = ?", id, id],
176 177 :order => "#{Tracker.table_name}.position")
177 178 end
178 179
179 180 # Deletes all project's members
180 181 def delete_all_members
181 182 Member.delete_all(['project_id = ?', id])
182 183 end
183 184
184 185 # Users issues can be assigned to
185 186 def assignable_users
186 187 members.select {|m| m.role.assignable?}.collect {|m| m.user}.sort
187 188 end
188 189
189 190 # Returns the mail adresses of users that should be always notified on project events
190 191 def recipients
191 192 members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail}
192 193 end
193 194
194 195 # Returns an array of all custom fields enabled for project issues
195 196 # (explictly associated custom fields and custom fields enabled for all projects)
196 197 def custom_fields_for_issues(tracker)
197 198 all_custom_fields.select {|c| tracker.custom_fields.include? c }
198 199 end
199 200
200 201 def all_custom_fields
201 202 @all_custom_fields ||= (IssueCustomField.for_all + custom_fields).uniq
202 203 end
203 204
204 205 def <=>(project)
205 206 name.downcase <=> project.name.downcase
206 207 end
207 208
208 209 def to_s
209 210 name
210 211 end
211 212
212 213 # Returns a short description of the projects (first lines)
213 214 def short_description(length = 255)
214 215 description.gsub(/^(.{#{length}}[^\n]*).*$/m, '\1').strip if description
215 216 end
216 217
217 218 def allows_to?(action)
218 219 if action.is_a? Hash
219 220 allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
220 221 else
221 222 allowed_permissions.include? action
222 223 end
223 224 end
224 225
225 226 def module_enabled?(module_name)
226 227 module_name = module_name.to_s
227 228 enabled_modules.detect {|m| m.name == module_name}
228 229 end
229 230
230 231 def enabled_module_names=(module_names)
231 232 enabled_modules.clear
232 233 module_names = [] unless module_names && module_names.is_a?(Array)
233 234 module_names.each do |name|
234 235 enabled_modules << EnabledModule.new(:name => name.to_s)
235 236 end
236 237 end
237 238
238 239 protected
239 240 def validate
240 241 errors.add(parent_id, " must be a root project") if parent and parent.parent
241 242 errors.add_to_base("A project with subprojects can't be a subproject") if parent and children.size > 0
242 243 errors.add(:identifier, :activerecord_error_invalid) if !identifier.blank? && identifier.match(/^\d*$/)
243 244 end
244 245
245 246 private
246 247 def allowed_permissions
247 248 @allowed_permissions ||= begin
248 249 module_names = enabled_modules.collect {|m| m.name}
249 250 Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name}
250 251 end
251 252 end
252 253
253 254 def allowed_actions
254 255 @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
255 256 end
256 257 end
@@ -1,74 +1,90
1 1 ---
2 2 issues_001:
3 3 created_on: <%= 3.days.ago.to_date.to_s(:db) %>
4 4 project_id: 1
5 5 updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
6 6 priority_id: 4
7 7 subject: Can't print recipes
8 8 id: 1
9 9 fixed_version_id:
10 10 category_id: 1
11 11 description: Unable to print recipes
12 12 tracker_id: 1
13 13 assigned_to_id:
14 14 author_id: 2
15 15 status_id: 1
16 16 issues_002:
17 17 created_on: 2006-07-19 21:04:21 +02:00
18 18 project_id: 1
19 19 updated_on: 2006-07-19 21:09:50 +02:00
20 20 priority_id: 5
21 21 subject: Add ingredients categories
22 22 id: 2
23 23 fixed_version_id:
24 24 category_id:
25 25 description: Ingredients of the recipe should be classified by categories
26 26 tracker_id: 2
27 27 assigned_to_id: 3
28 28 author_id: 2
29 29 status_id: 2
30 30 issues_003:
31 31 created_on: 2006-07-19 21:07:27 +02:00
32 32 project_id: 1
33 33 updated_on: 2006-07-19 21:07:27 +02:00
34 34 priority_id: 4
35 35 subject: Error 281 when updating a recipe
36 36 id: 3
37 37 fixed_version_id:
38 38 category_id:
39 39 description: Error 281 is encountered when saving a recipe
40 40 tracker_id: 1
41 41 assigned_to_id:
42 42 author_id: 2
43 43 status_id: 1
44 44 start_date: <%= 1.day.from_now.to_date.to_s(:db) %>
45 45 due_date: <%= 40.day.ago.to_date.to_s(:db) %>
46 46 issues_004:
47 47 created_on: <%= 5.days.ago.to_date.to_s(:db) %>
48 48 project_id: 2
49 49 updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
50 50 priority_id: 4
51 51 subject: Issue on project 2
52 52 id: 4
53 53 fixed_version_id:
54 54 category_id:
55 55 description: Issue on project 2
56 56 tracker_id: 1
57 57 assigned_to_id:
58 58 author_id: 2
59 59 status_id: 1
60 60 issues_005:
61 61 created_on: <%= 5.days.ago.to_date.to_s(:db) %>
62 62 project_id: 3
63 63 updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
64 64 priority_id: 4
65 65 subject: Subproject issue
66 66 id: 5
67 67 fixed_version_id:
68 68 category_id:
69 69 description: This is an issue on a cookbook subproject
70 70 tracker_id: 1
71 71 assigned_to_id:
72 72 author_id: 2
73 73 status_id: 1
74
74 issues_006:
75 created_on: <%= 1.minute.ago.to_date.to_s(:db) %>
76 project_id: 5
77 updated_on: <%= 1.minute.ago.to_date.to_s(:db) %>
78 priority_id: 4
79 subject: Issue of a private subproject
80 id: 6
81 fixed_version_id:
82 category_id:
83 description: This is an issue of a private subproject of cookbook
84 tracker_id: 1
85 assigned_to_id:
86 author_id: 2
87 status_id: 1
88 start_date: <%= Date.today.to_s(:db) %>
89 due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
90 No newline at end of file
@@ -1,283 +1,304
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.dirname(__FILE__) + '/../test_helper'
19 19 require 'projects_controller'
20 20
21 21 # Re-raise errors caught by the controller.
22 22 class ProjectsController; def rescue_action(e) raise e end; end
23 23
24 24 class ProjectsControllerTest < Test::Unit::TestCase
25 25 fixtures :projects, :versions, :users, :roles, :members, :issues, :journals, :journal_details,
26 26 :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages
27 27
28 28 def setup
29 29 @controller = ProjectsController.new
30 30 @request = ActionController::TestRequest.new
31 31 @response = ActionController::TestResponse.new
32 @request.session[:user_id] = nil
32 33 end
33 34
34 35 def test_index
35 36 get :index
36 37 assert_response :success
37 38 assert_template 'list'
38 39 end
39 40
40 41 def test_list
41 42 get :list
42 43 assert_response :success
43 44 assert_template 'list'
44 45 assert_not_nil assigns(:project_tree)
45 46 # Root project as hash key
46 47 assert assigns(:project_tree).has_key?(Project.find(1))
47 48 # Subproject in corresponding value
48 49 assert assigns(:project_tree)[Project.find(1)].include?(Project.find(3))
49 50 end
50 51
51 52 def test_show_by_id
52 53 get :show, :id => 1
53 54 assert_response :success
54 55 assert_template 'show'
55 56 assert_not_nil assigns(:project)
56 57 end
57 58
58 59 def test_show_by_identifier
59 60 get :show, :id => 'ecookbook'
60 61 assert_response :success
61 62 assert_template 'show'
62 63 assert_not_nil assigns(:project)
63 64 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
64 65 end
65 66
66 67 def test_private_subprojects_hidden
67 68 get :show, :id => 'ecookbook'
68 69 assert_response :success
69 70 assert_template 'show'
70 71 assert_no_tag :tag => 'a', :content => /Private child/
71 72 end
72 73
73 74 def test_private_subprojects_visible
74 75 @request.session[:user_id] = 2 # manager who is a member of the private subproject
75 76 get :show, :id => 'ecookbook'
76 77 assert_response :success
77 78 assert_template 'show'
78 79 assert_tag :tag => 'a', :content => /Private child/
79 80 end
80 81
81 82 def test_settings
82 83 @request.session[:user_id] = 2 # manager
83 84 get :settings, :id => 1
84 85 assert_response :success
85 86 assert_template 'settings'
86 87 end
87 88
88 89 def test_edit
89 90 @request.session[:user_id] = 2 # manager
90 91 post :edit, :id => 1, :project => {:name => 'Test changed name',
91 92 :custom_field_ids => ['']}
92 93 assert_redirected_to 'projects/settings/ecookbook'
93 94 project = Project.find(1)
94 95 assert_equal 'Test changed name', project.name
95 96 end
96 97
97 98 def test_get_destroy
98 99 @request.session[:user_id] = 1 # admin
99 100 get :destroy, :id => 1
100 101 assert_response :success
101 102 assert_template 'destroy'
102 103 assert_not_nil Project.find_by_id(1)
103 104 end
104 105
105 106 def test_post_destroy
106 107 @request.session[:user_id] = 1 # admin
107 108 post :destroy, :id => 1, :confirm => 1
108 109 assert_redirected_to 'admin/projects'
109 110 assert_nil Project.find_by_id(1)
110 111 end
111 112
112 113 def test_list_files
113 114 get :list_files, :id => 1
114 115 assert_response :success
115 116 assert_template 'list_files'
116 117 assert_not_nil assigns(:versions)
117 118 end
118 119
119 120 def test_changelog
120 121 get :changelog, :id => 1
121 122 assert_response :success
122 123 assert_template 'changelog'
123 124 assert_not_nil assigns(:versions)
124 125 end
125 126
126 127 def test_roadmap
127 128 get :roadmap, :id => 1
128 129 assert_response :success
129 130 assert_template 'roadmap'
130 131 assert_not_nil assigns(:versions)
131 132 # Version with no date set appears
132 133 assert assigns(:versions).include?(Version.find(3))
133 134 # Completed version doesn't appear
134 135 assert !assigns(:versions).include?(Version.find(1))
135 136 end
136 137
137 138 def test_roadmap_with_completed_versions
138 139 get :roadmap, :id => 1, :completed => 1
139 140 assert_response :success
140 141 assert_template 'roadmap'
141 142 assert_not_nil assigns(:versions)
142 143 # Version with no date set appears
143 144 assert assigns(:versions).include?(Version.find(3))
144 145 # Completed version appears
145 146 assert assigns(:versions).include?(Version.find(1))
146 147 end
147 148
148 149 def test_project_activity
149 150 get :activity, :id => 1, :with_subprojects => 0
150 151 assert_response :success
151 152 assert_template 'activity'
152 153 assert_not_nil assigns(:events_by_day)
153 154 assert_not_nil assigns(:events)
154 155
155 156 # subproject issue not included by default
156 157 assert !assigns(:events).include?(Issue.find(5))
157 158
158 159 assert_tag :tag => "h3",
159 160 :content => /#{2.days.ago.to_date.day}/,
160 161 :sibling => { :tag => "dl",
161 162 :child => { :tag => "dt",
162 163 :attributes => { :class => 'issue-edit' },
163 164 :child => { :tag => "a",
164 165 :content => /(#{IssueStatus.find(2).name})/,
165 166 }
166 167 }
167 168 }
168 169
169 170 get :activity, :id => 1, :from => 3.days.ago.to_date
170 171 assert_response :success
171 172 assert_template 'activity'
172 173 assert_not_nil assigns(:events_by_day)
173 174
174 175 assert_tag :tag => "h3",
175 176 :content => /#{3.day.ago.to_date.day}/,
176 177 :sibling => { :tag => "dl",
177 178 :child => { :tag => "dt",
178 179 :attributes => { :class => 'issue' },
179 180 :child => { :tag => "a",
180 181 :content => /#{Issue.find(1).subject}/,
181 182 }
182 183 }
183 184 }
184 185 end
185 186
186 187 def test_activity_with_subprojects
187 188 get :activity, :id => 1, :with_subprojects => 1
188 189 assert_response :success
189 190 assert_template 'activity'
190 191 assert_not_nil assigns(:events)
191 192
192 193 assert assigns(:events).include?(Issue.find(1))
193 194 assert !assigns(:events).include?(Issue.find(4))
194 195 # subproject issue
195 196 assert assigns(:events).include?(Issue.find(5))
196 197 end
197 198
198 199 def test_global_activity_anonymous
199 200 get :activity
200 201 assert_response :success
201 202 assert_template 'activity'
202 203 assert_not_nil assigns(:events)
203 204
204 205 assert assigns(:events).include?(Issue.find(1))
205 206 # Issue of a private project
206 207 assert !assigns(:events).include?(Issue.find(4))
207 208 end
208 209
209 210 def test_global_activity_logged_user
210 211 @request.session[:user_id] = 2 # manager
211 212 get :activity
212 213 assert_response :success
213 214 assert_template 'activity'
214 215 assert_not_nil assigns(:events)
215 216
216 217 assert assigns(:events).include?(Issue.find(1))
217 218 # Issue of a private project the user belongs to
218 219 assert assigns(:events).include?(Issue.find(4))
219 220 end
220 221
221 222
222 223 def test_global_activity_with_all_types
223 224 get :activity, :show_issues => 1, :show_news => 1, :show_files => 1, :show_documents => 1, :show_changesets => 1, :show_wiki_pages => 1, :show_messages => 1
224 225 assert_response :success
225 226 assert_template 'activity'
226 227 assert_not_nil assigns(:events)
227 228
228 229 assert assigns(:events).include?(Issue.find(1))
229 230 assert !assigns(:events).include?(Issue.find(4))
230 231 assert assigns(:events).include?(Message.find(5))
231 232 end
232 233
233 234 def test_calendar
234 235 get :calendar, :id => 1
235 236 assert_response :success
236 237 assert_template 'calendar'
237 238 assert_not_nil assigns(:calendar)
238 239 end
239 240
240 def test_calendar_with_subprojects
241 def test_calendar_with_subprojects_should_not_show_private_subprojects
241 242 get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
242 243 assert_response :success
243 244 assert_template 'calendar'
244 245 assert_not_nil assigns(:calendar)
246 assert_no_tag :tag => 'a', :content => /#6/
247 end
248
249 def test_calendar_with_subprojects_should_show_private_subprojects
250 @request.session[:user_id] = 2
251 get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
252 assert_response :success
253 assert_template 'calendar'
254 assert_not_nil assigns(:calendar)
255 assert_tag :tag => 'a', :content => /#6/
245 256 end
246 257
247 258 def test_gantt
248 259 get :gantt, :id => 1
249 260 assert_response :success
250 261 assert_template 'gantt.rhtml'
251 262 assert_not_nil assigns(:events)
252 263 end
253 264
254 def test_gantt_with_subprojects
265 def test_gantt_with_subprojects_should_not_show_private_subprojects
255 266 get :gantt, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
256 267 assert_response :success
257 268 assert_template 'gantt.rhtml'
258 269 assert_not_nil assigns(:events)
270 assert_no_tag :tag => 'a', :content => /#6/
259 271 end
260 272
273 def test_gantt_with_subprojects_should_show_private_subprojects
274 @request.session[:user_id] = 2
275 get :gantt, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
276 assert_response :success
277 assert_template 'gantt.rhtml'
278 assert_not_nil assigns(:events)
279 assert_tag :tag => 'a', :content => /#6/
280 end
281
261 282 def test_gantt_export_to_pdf
262 283 get :gantt, :id => 1, :format => 'pdf'
263 284 assert_response :success
264 285 assert_template 'gantt.rfpdf'
265 286 assert_equal 'application/pdf', @response.content_type
266 287 assert_not_nil assigns(:events)
267 288 end
268 289
269 290 def test_archive
270 291 @request.session[:user_id] = 1 # admin
271 292 post :archive, :id => 1
272 293 assert_redirected_to 'admin/projects'
273 294 assert !Project.find(1).active?
274 295 end
275 296
276 297 def test_unarchive
277 298 @request.session[:user_id] = 1 # admin
278 299 Project.find(1).archive
279 300 post :unarchive, :id => 1
280 301 assert_redirected_to 'admin/projects'
281 302 assert Project.find(1).active?
282 303 end
283 304 end
General Comments 0
You need to be logged in to leave comments. Login now