##// END OF EJS Templates
Project identifier is now used in URLs (instead of project id)....
Jean-Philippe Lang -
r994:524cd689cf87
parent child
Show More
@@ -1,202 +1,216
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, :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, :description, :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 :description, :maximum => 255
61 61 validates_length_of :homepage, :maximum => 60
62 62 validates_length_of :identifier, :in => 3..20
63 63 validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
64 64
65 65 before_destroy :delete_all_members
66 66
67 67 def identifier=(identifier)
68 68 super unless identifier_frozen?
69 69 end
70 70
71 71 def identifier_frozen?
72 72 errors[:identifier].nil? && !(new_record? || identifier.blank?)
73 73 end
74 74
75 75 def issues_with_subprojects(include_subprojects=false)
76 76 conditions = nil
77 77 if include_subprojects && !active_children.empty?
78 78 ids = [id] + active_children.collect {|c| c.id}
79 79 conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"]
80 80 end
81 81 conditions ||= ["#{Issue.table_name}.project_id = ?", id]
82 82 # Quick and dirty fix for Rails 2 compatibility
83 83 Issue.send(:with_scope, :find => { :conditions => conditions }) do
84 84 yield
85 85 end
86 86 end
87 87
88 88 # Return all issues status changes for the project between the 2 given dates
89 89 def issues_status_changes(from, to)
90 90 Journal.find(:all, :include => [:issue, :details, :user],
91 91 :conditions => ["#{Journal.table_name}.journalized_type = 'Issue'" +
92 92 " AND #{Issue.table_name}.project_id = ?" +
93 93 " AND #{JournalDetail.table_name}.prop_key = 'status_id'" +
94 94 " AND #{Journal.table_name}.created_on BETWEEN ? AND ?",
95 95 id, from, to+1])
96 96 end
97 97
98 98 # returns latest created projects
99 99 # non public projects will be returned only if user is a member of those
100 100 def self.latest(user=nil, count=5)
101 101 find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC")
102 102 end
103 103
104 104 def self.visible_by(user=nil)
105 105 if user && user.admin?
106 106 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
107 107 elsif user && user.memberships.any?
108 108 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(',')}))"
109 109 else
110 110 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = #{connection.quoted_true}"
111 111 end
112 112 end
113 113
114 def self.find(*args)
115 if args.first && args.first.is_a?(String) && !args.first.match(/^\d*$/)
116 project = find_by_identifier(*args)
117 raise ActiveRecord::RecordNotFound, "Couldn't find Project with identifier=#{args.first}" if project.nil?
118 project
119 else
120 super
121 end
122 end
123
124 def to_param
125 identifier
126 end
127
114 128 def active?
115 129 self.status == STATUS_ACTIVE
116 130 end
117 131
118 132 def archive
119 133 # Archive subprojects if any
120 134 children.each do |subproject|
121 135 subproject.archive
122 136 end
123 137 update_attribute :status, STATUS_ARCHIVED
124 138 end
125 139
126 140 def unarchive
127 141 return false if parent && !parent.active?
128 142 update_attribute :status, STATUS_ACTIVE
129 143 end
130 144
131 145 def active_children
132 146 children.select {|child| child.active?}
133 147 end
134 148
135 149 # Deletes all project's members
136 150 def delete_all_members
137 151 Member.delete_all(['project_id = ?', id])
138 152 end
139 153
140 154 # Users issues can be assigned to
141 155 def assignable_users
142 156 members.select {|m| m.role.assignable?}.collect {|m| m.user}.sort
143 157 end
144 158
145 159 # Returns the mail adresses of users that should be always notified on project events
146 160 def recipients
147 161 members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail}
148 162 end
149 163
150 164 # Returns an array of all custom fields enabled for project issues
151 165 # (explictly associated custom fields and custom fields enabled for all projects)
152 166 def custom_fields_for_issues(tracker)
153 167 all_custom_fields.select {|c| tracker.custom_fields.include? c }
154 168 end
155 169
156 170 def all_custom_fields
157 171 @all_custom_fields ||= (IssueCustomField.for_all + custom_fields).uniq
158 172 end
159 173
160 174 def <=>(project)
161 175 name.downcase <=> project.name.downcase
162 176 end
163 177
164 178 def allows_to?(action)
165 179 if action.is_a? Hash
166 180 allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
167 181 else
168 182 allowed_permissions.include? action
169 183 end
170 184 end
171 185
172 186 def module_enabled?(module_name)
173 187 module_name = module_name.to_s
174 188 enabled_modules.detect {|m| m.name == module_name}
175 189 end
176 190
177 191 def enabled_module_names=(module_names)
178 192 enabled_modules.clear
179 193 module_names = [] unless module_names && module_names.is_a?(Array)
180 194 module_names.each do |name|
181 195 enabled_modules << EnabledModule.new(:name => name.to_s)
182 196 end
183 197 end
184 198
185 199 protected
186 200 def validate
187 201 errors.add(parent_id, " must be a root project") if parent and parent.parent
188 202 errors.add_to_base("A project with subprojects can't be a subproject") if parent and children.size > 0
189 203 end
190 204
191 205 private
192 206 def allowed_permissions
193 207 @allowed_permissions ||= begin
194 208 module_names = enabled_modules.collect {|m| m.name}
195 209 Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name}
196 210 end
197 211 end
198 212
199 213 def allowed_actions
200 214 @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
201 215 end
202 216 end
@@ -1,45 +1,45
1 1 ---
2 2 projects_001:
3 3 created_on: 2006-07-19 19:13:59 +02:00
4 4 name: eCookbook
5 5 updated_on: 2006-07-19 22:53:01 +02:00
6 6 projects_count: 2
7 7 id: 1
8 8 description: Recipes management application
9 9 homepage: http://ecookbook.somenet.foo/
10 10 is_public: true
11 11 identifier: ecookbook
12 12 parent_id:
13 13 projects_002:
14 14 created_on: 2006-07-19 19:14:19 +02:00
15 15 name: OnlineStore
16 16 updated_on: 2006-07-19 19:14:19 +02:00
17 17 projects_count: 0
18 18 id: 2
19 19 description: E-commerce web site
20 20 homepage: ""
21 21 is_public: false
22 22 identifier: onlinestore
23 23 parent_id:
24 24 projects_003:
25 25 created_on: 2006-07-19 19:15:21 +02:00
26 26 name: eCookbook Subproject 1
27 27 updated_on: 2006-07-19 19:18:12 +02:00
28 28 projects_count: 0
29 29 id: 3
30 30 description: eCookBook Subproject 1
31 31 homepage: ""
32 32 is_public: true
33 33 identifier: subproject1
34 34 parent_id: 1
35 35 projects_004:
36 36 created_on: 2006-07-19 19:15:51 +02:00
37 37 name: eCookbook Subproject 2
38 38 updated_on: 2006-07-19 19:17:07 +02:00
39 39 projects_count: 0
40 40 id: 4
41 41 description: eCookbook Subproject 2
42 42 homepage: ""
43 43 is_public: true
44 identifier: subproject1
44 identifier: subproject2
45 45 parent_id: 1
@@ -1,163 +1,163
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 'issues_controller'
20 20
21 21 # Re-raise errors caught by the controller.
22 22 class IssuesController; def rescue_action(e) raise e end; end
23 23
24 24 class IssuesControllerTest < Test::Unit::TestCase
25 25 fixtures :projects,
26 26 :users,
27 27 :roles,
28 28 :members,
29 29 :issues,
30 30 :issue_statuses,
31 31 :trackers,
32 32 :issue_categories,
33 33 :enabled_modules,
34 34 :enumerations,
35 35 :attachments
36 36
37 37 def setup
38 38 @controller = IssuesController.new
39 39 @request = ActionController::TestRequest.new
40 40 @response = ActionController::TestResponse.new
41 41 User.current = nil
42 42 end
43 43
44 44 def test_index
45 45 get :index
46 46 assert_response :success
47 47 assert_template 'index.rhtml'
48 48 assert_not_nil assigns(:issues)
49 49 assert_nil assigns(:project)
50 50 end
51 51
52 52 def test_index_with_project
53 53 get :index, :project_id => 1
54 54 assert_response :success
55 55 assert_template 'index.rhtml'
56 56 assert_not_nil assigns(:issues)
57 57 end
58 58
59 59 def test_index_with_project_and_filter
60 60 get :index, :project_id => 1, :set_filter => 1
61 61 assert_response :success
62 62 assert_template 'index.rhtml'
63 63 assert_not_nil assigns(:issues)
64 64 end
65 65
66 66 def test_index_csv_with_project
67 67 get :index, :format => 'csv'
68 68 assert_response :success
69 69 assert_not_nil assigns(:issues)
70 70 assert_equal 'text/csv', @response.content_type
71 71
72 72 get :index, :project_id => 1, :format => 'csv'
73 73 assert_response :success
74 74 assert_not_nil assigns(:issues)
75 75 assert_equal 'text/csv', @response.content_type
76 76 end
77 77
78 78 def test_index_pdf
79 79 get :index, :format => 'pdf'
80 80 assert_response :success
81 81 assert_not_nil assigns(:issues)
82 82 assert_equal 'application/pdf', @response.content_type
83 83
84 84 get :index, :project_id => 1, :format => 'pdf'
85 85 assert_response :success
86 86 assert_not_nil assigns(:issues)
87 87 assert_equal 'application/pdf', @response.content_type
88 88 end
89 89
90 90 def test_changes
91 91 get :changes, :project_id => 1
92 92 assert_response :success
93 93 assert_not_nil assigns(:changes)
94 94 assert_equal 'application/atom+xml', @response.content_type
95 95 end
96 96
97 97 def test_show
98 98 get :show, :id => 1
99 99 assert_response :success
100 100 assert_template 'show.rhtml'
101 101 assert_not_nil assigns(:issue)
102 102 end
103 103
104 104 def test_get_edit
105 105 @request.session[:user_id] = 2
106 106 get :edit, :id => 1
107 107 assert_response :success
108 108 assert_template 'edit'
109 109 assert_not_nil assigns(:issue)
110 110 assert_equal Issue.find(1), assigns(:issue)
111 111 end
112 112
113 113 def test_post_edit
114 114 @request.session[:user_id] = 2
115 115 post :edit, :id => 1, :issue => {:subject => 'Modified subject'}
116 116 assert_redirected_to 'issues/show/1'
117 117 assert_equal 'Modified subject', Issue.find(1).subject
118 118 end
119 119
120 120 def test_post_change_status
121 121 issue = Issue.find(1)
122 122 assert_equal 1, issue.status_id
123 123 @request.session[:user_id] = 2
124 124 post :change_status, :id => 1,
125 125 :new_status_id => 2,
126 126 :issue => { :assigned_to_id => 3 },
127 127 :notes => 'Assigned to dlopper',
128 128 :confirm => 1
129 129 assert_redirected_to 'issues/show/1'
130 130 issue.reload
131 131 assert_equal 2, issue.status_id
132 132 j = issue.journals.find(:first, :order => 'created_on DESC')
133 133 assert_equal 'Assigned to dlopper', j.notes
134 134 assert_equal 2, j.details.size
135 135 end
136 136
137 137 def test_context_menu
138 138 @request.session[:user_id] = 2
139 139 get :context_menu, :id => 1
140 140 assert_response :success
141 141 assert_template 'context_menu'
142 142 end
143 143
144 144 def test_destroy
145 145 @request.session[:user_id] = 2
146 146 post :destroy, :id => 1
147 assert_redirected_to 'projects/1/issues'
147 assert_redirected_to 'projects/ecookbook/issues'
148 148 assert_nil Issue.find_by_id(1)
149 149 end
150 150
151 151 def test_destroy_attachment
152 152 issue = Issue.find(3)
153 153 a = issue.attachments.size
154 154 @request.session[:user_id] = 2
155 155 post :destroy_attachment, :id => 3, :attachment_id => 1
156 156 assert_redirected_to 'issues/show/3'
157 157 assert_nil Attachment.find_by_id(1)
158 158 issue.reload
159 159 assert_equal((a-1), issue.attachments.size)
160 160 j = issue.journals.find(:first, :order => 'created_on DESC')
161 161 assert_equal 'attachment', j.details.first.property
162 162 end
163 163 end
@@ -1,257 +1,265
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, :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations
26 26
27 27 def setup
28 28 @controller = ProjectsController.new
29 29 @request = ActionController::TestRequest.new
30 30 @response = ActionController::TestResponse.new
31 31 end
32 32
33 33 def test_index
34 34 get :index
35 35 assert_response :success
36 36 assert_template 'list'
37 37 end
38 38
39 39 def test_list
40 40 get :list
41 41 assert_response :success
42 42 assert_template 'list'
43 43 assert_not_nil assigns(:project_tree)
44 44 # Root project as hash key
45 45 assert assigns(:project_tree).has_key?(Project.find(1))
46 46 # Subproject in corresponding value
47 47 assert assigns(:project_tree)[Project.find(1)].include?(Project.find(3))
48 48 end
49 49
50 def test_show
50 def test_show_by_id
51 51 get :show, :id => 1
52 52 assert_response :success
53 53 assert_template 'show'
54 54 assert_not_nil assigns(:project)
55 55 end
56
57 def test_show_by_identifier
58 get :show, :id => 'ecookbook'
59 assert_response :success
60 assert_template 'show'
61 assert_not_nil assigns(:project)
62 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
63 end
56 64
57 65 def test_settings
58 66 @request.session[:user_id] = 2 # manager
59 67 get :settings, :id => 1
60 68 assert_response :success
61 69 assert_template 'settings'
62 70 end
63 71
64 72 def test_edit
65 73 @request.session[:user_id] = 2 # manager
66 74 post :edit, :id => 1, :project => {:name => 'Test changed name'}
67 assert_redirected_to 'projects/settings/1'
75 assert_redirected_to 'projects/settings/ecookbook'
68 76 project = Project.find(1)
69 77 assert_equal 'Test changed name', project.name
70 78 end
71 79
72 80 def test_get_destroy
73 81 @request.session[:user_id] = 1 # admin
74 82 get :destroy, :id => 1
75 83 assert_response :success
76 84 assert_template 'destroy'
77 85 assert_not_nil Project.find_by_id(1)
78 86 end
79 87
80 88 def test_post_destroy
81 89 @request.session[:user_id] = 1 # admin
82 90 post :destroy, :id => 1, :confirm => 1
83 91 assert_redirected_to 'admin/projects'
84 92 assert_nil Project.find_by_id(1)
85 93 end
86 94
87 95 def test_list_documents
88 96 get :list_documents, :id => 1
89 97 assert_response :success
90 98 assert_template 'list_documents'
91 99 assert_not_nil assigns(:grouped)
92 100 end
93 101
94 102 def test_bulk_edit_issues
95 103 @request.session[:user_id] = 2
96 104 # update issues priority
97 105 post :bulk_edit_issues, :id => 1, :issue_ids => [1, 2], :priority_id => 7, :notes => 'Bulk editing', :assigned_to_id => ''
98 106 assert_response 302
99 107 # check that the issues were updated
100 108 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
101 109 assert_equal 'Bulk editing', Issue.find(1).journals.find(:first, :order => 'created_on DESC').notes
102 110 end
103 111
104 112 def test_move_issues_to_another_project
105 113 @request.session[:user_id] = 1
106 114 post :move_issues, :id => 1, :issue_ids => [1, 2], :new_project_id => 2
107 assert_redirected_to 'projects/1/issues'
115 assert_redirected_to 'projects/ecookbook/issues'
108 116 assert_equal 2, Issue.find(1).project_id
109 117 assert_equal 2, Issue.find(2).project_id
110 118 end
111 119
112 120 def test_move_issues_to_another_tracker
113 121 @request.session[:user_id] = 1
114 122 post :move_issues, :id => 1, :issue_ids => [1, 2], :new_tracker_id => 3
115 assert_redirected_to 'projects/1/issues'
123 assert_redirected_to 'projects/ecookbook/issues'
116 124 assert_equal 3, Issue.find(1).tracker_id
117 125 assert_equal 3, Issue.find(2).tracker_id
118 126 end
119 127
120 128 def test_list_files
121 129 get :list_files, :id => 1
122 130 assert_response :success
123 131 assert_template 'list_files'
124 132 assert_not_nil assigns(:versions)
125 133 end
126 134
127 135 def test_changelog
128 136 get :changelog, :id => 1
129 137 assert_response :success
130 138 assert_template 'changelog'
131 139 assert_not_nil assigns(:versions)
132 140 end
133 141
134 142 def test_roadmap
135 143 get :roadmap, :id => 1
136 144 assert_response :success
137 145 assert_template 'roadmap'
138 146 assert_not_nil assigns(:versions)
139 147 # Version with no date set appears
140 148 assert assigns(:versions).include?(Version.find(3))
141 149 # Completed version doesn't appear
142 150 assert !assigns(:versions).include?(Version.find(1))
143 151 end
144 152
145 153 def test_roadmap_with_completed_versions
146 154 get :roadmap, :id => 1, :completed => 1
147 155 assert_response :success
148 156 assert_template 'roadmap'
149 157 assert_not_nil assigns(:versions)
150 158 # Version with no date set appears
151 159 assert assigns(:versions).include?(Version.find(3))
152 160 # Completed version appears
153 161 assert assigns(:versions).include?(Version.find(1))
154 162 end
155 163
156 164 def test_activity
157 165 get :activity, :id => 1, :year => 2.days.ago.to_date.year, :month => 2.days.ago.to_date.month
158 166 assert_response :success
159 167 assert_template 'activity'
160 168 assert_not_nil assigns(:events_by_day)
161 169
162 170 assert_tag :tag => "h3",
163 171 :content => /#{2.days.ago.to_date.day}/,
164 172 :sibling => { :tag => "ul",
165 173 :child => { :tag => "li",
166 174 :child => { :tag => "p",
167 175 :content => /(#{IssueStatus.find(2).name})/,
168 176 }
169 177 }
170 178 }
171 179
172 180 get :activity, :id => 1, :year => 3.days.ago.to_date.year, :month => 3.days.ago.to_date.month
173 181 assert_response :success
174 182 assert_template 'activity'
175 183 assert_not_nil assigns(:events_by_day)
176 184
177 185 assert_tag :tag => "h3",
178 186 :content => /#{3.day.ago.to_date.day}/,
179 187 :sibling => { :tag => "ul",
180 188 :child => { :tag => "li",
181 189 :child => { :tag => "p",
182 190 :content => /#{Issue.find(1).subject}/,
183 191 }
184 192 }
185 193 }
186 194 end
187 195
188 196 def test_calendar
189 197 get :calendar, :id => 1
190 198 assert_response :success
191 199 assert_template 'calendar'
192 200 assert_not_nil assigns(:calendar)
193 201 end
194 202
195 203 def test_calendar_with_subprojects
196 204 get :calendar, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
197 205 assert_response :success
198 206 assert_template 'calendar'
199 207 assert_not_nil assigns(:calendar)
200 208 end
201 209
202 210 def test_gantt
203 211 get :gantt, :id => 1
204 212 assert_response :success
205 213 assert_template 'gantt.rhtml'
206 214 assert_not_nil assigns(:events)
207 215 end
208 216
209 217 def test_gantt_with_subprojects
210 218 get :gantt, :id => 1, :with_subprojects => 1, :tracker_ids => [1, 2]
211 219 assert_response :success
212 220 assert_template 'gantt.rhtml'
213 221 assert_not_nil assigns(:events)
214 222 end
215 223
216 224 def test_gantt_export_to_pdf
217 225 get :gantt, :id => 1, :format => 'pdf'
218 226 assert_response :success
219 227 assert_template 'gantt.rfpdf'
220 228 assert_equal 'application/pdf', @response.content_type
221 229 assert_not_nil assigns(:events)
222 230 end
223 231
224 232 def test_archive
225 233 @request.session[:user_id] = 1 # admin
226 234 post :archive, :id => 1
227 235 assert_redirected_to 'admin/projects'
228 236 assert !Project.find(1).active?
229 237 end
230 238
231 239 def test_unarchive
232 240 @request.session[:user_id] = 1 # admin
233 241 Project.find(1).archive
234 242 post :unarchive, :id => 1
235 243 assert_redirected_to 'admin/projects'
236 244 assert Project.find(1).active?
237 245 end
238 246
239 247 def test_add_issue
240 248 @request.session[:user_id] = 2
241 249 get :add_issue, :id => 1, :tracker_id => 1
242 250 assert_response :success
243 251 assert_template 'add_issue'
244 252 post :add_issue, :id => 1, :issue => {:tracker_id => 1, :subject => 'This is the test_add_issue issue', :description => 'This is the description', :priority_id => 5}
245 assert_redirected_to 'projects/1/issues'
253 assert_redirected_to 'projects/ecookbook/issues'
246 254 assert Issue.find_by_subject('This is the test_add_issue issue')
247 255 end
248 256
249 257 def test_copy_issue
250 258 @request.session[:user_id] = 2
251 259 get :add_issue, :id => 1, :copy_from => 1
252 260 assert_template 'add_issue'
253 261 assert_not_nil assigns(:issue)
254 262 orig = Issue.find(1)
255 263 assert_equal orig.subject, assigns(:issue).subject
256 264 end
257 265 end
@@ -1,64 +1,64
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 'repositories_controller'
20 20
21 21 # Re-raise errors caught by the controller.
22 22 class RepositoriesController; def rescue_action(e) raise e end; end
23 23
24 24 class RepositoriesControllerTest < Test::Unit::TestCase
25 25 fixtures :projects, :users, :roles, :members, :repositories, :issues, :issue_statuses, :changesets, :changes, :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
26 26
27 27 def setup
28 28 @controller = RepositoriesController.new
29 29 @request = ActionController::TestRequest.new
30 30 @response = ActionController::TestResponse.new
31 31 User.current = nil
32 32 end
33 33
34 34 def test_revisions
35 35 get :revisions, :id => 1
36 36 assert_response :success
37 37 assert_template 'revisions'
38 38 assert_not_nil assigns(:changesets)
39 39 end
40 40
41 41 def test_revision_with_before_nil_and_afer_normal
42 42 get :revision, {:id => 1, :rev => 1}
43 43 assert_response :success
44 44 assert_template 'revision'
45 45 assert_no_tag :tag => "div", :attributes => { :class => "contextual" },
46 :child => { :tag => "a", :attributes => { :href => '/repositories/revision/1?rev=0'}
46 :child => { :tag => "a", :attributes => { :href => '/repositories/revision/ecookbook?rev=0'}
47 47 }
48 48 assert_tag :tag => "div", :attributes => { :class => "contextual" },
49 :child => { :tag => "a", :attributes => { :href => '/repositories/revision/1?rev=2'}
49 :child => { :tag => "a", :attributes => { :href => '/repositories/revision/ecookbook?rev=2'}
50 50 }
51 51 end
52 52
53 53 def test_graph_commits_per_month
54 54 get :graph, :id => 1, :graph => 'commits_per_month'
55 55 assert_response :success
56 56 assert_equal 'image/svg+xml', @response.content_type
57 57 end
58 58
59 59 def test_graph_commits_per_author
60 60 get :graph, :id => 1, :graph => 'commits_per_author'
61 61 assert_response :success
62 62 assert_equal 'image/svg+xml', @response.content_type
63 63 end
64 64 end
@@ -1,73 +1,73
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 'versions_controller'
20 20
21 21 # Re-raise errors caught by the controller.
22 22 class VersionsController; def rescue_action(e) raise e end; end
23 23
24 24 class VersionsControllerTest < Test::Unit::TestCase
25 25 fixtures :projects, :versions, :users, :roles, :members, :enabled_modules
26 26
27 27 def setup
28 28 @controller = VersionsController.new
29 29 @request = ActionController::TestRequest.new
30 30 @response = ActionController::TestResponse.new
31 31 User.current = nil
32 32 end
33 33
34 34 def test_show
35 35 get :show, :id => 2
36 36 assert_response :success
37 37 assert_template 'show'
38 38 assert_not_nil assigns(:version)
39 39
40 40 assert_tag :tag => 'h2', :content => /1.0/
41 41 end
42 42
43 43 def test_get_edit
44 44 @request.session[:user_id] = 2
45 45 get :edit, :id => 2
46 46 assert_response :success
47 47 assert_template 'edit'
48 48 end
49 49
50 50 def test_post_edit
51 51 @request.session[:user_id] = 2
52 52 post :edit, :id => 2,
53 53 :version => { :name => 'New version name',
54 54 :effective_date => Date.today.strftime("%Y-%m-%d")}
55 assert_redirected_to 'projects/settings/1'
55 assert_redirected_to 'projects/settings/ecookbook'
56 56 version = Version.find(2)
57 57 assert_equal 'New version name', version.name
58 58 assert_equal Date.today, version.effective_date
59 59 end
60 60
61 61 def test_destroy
62 62 @request.session[:user_id] = 2
63 63 post :destroy, :id => 2
64 assert_redirected_to 'projects/settings/1'
64 assert_redirected_to 'projects/settings/ecookbook'
65 65 assert_nil Version.find_by_id(2)
66 66 end
67 67
68 68 def test_issue_status_by
69 69 xhr :get, :status_by, :id => 2
70 70 assert_response :success
71 71 assert_template '_issue_counts'
72 72 end
73 73 end
@@ -1,145 +1,145
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 'wiki_controller'
20 20
21 21 # Re-raise errors caught by the controller.
22 22 class WikiController; def rescue_action(e) raise e end; end
23 23
24 24 class WikiControllerTest < Test::Unit::TestCase
25 25 fixtures :projects, :users, :roles, :members, :enabled_modules, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
26 26
27 27 def setup
28 28 @controller = WikiController.new
29 29 @request = ActionController::TestRequest.new
30 30 @response = ActionController::TestResponse.new
31 31 User.current = nil
32 32 end
33 33
34 34 def test_show_start_page
35 35 get :index, :id => 1
36 36 assert_response :success
37 37 assert_template 'show'
38 38 assert_tag :tag => 'h1', :content => /CookBook documentation/
39 39 end
40 40
41 41 def test_show_page_with_name
42 42 get :index, :id => 1, :page => 'Another_page'
43 43 assert_response :success
44 44 assert_template 'show'
45 45 assert_tag :tag => 'h1', :content => /Another page/
46 46 end
47 47
48 48 def test_show_unexistent_page_without_edit_right
49 49 get :index, :id => 1, :page => 'Unexistent page'
50 50 assert_response 404
51 51 end
52 52
53 53 def test_show_unexistent_page_with_edit_right
54 54 @request.session[:user_id] = 2
55 55 get :index, :id => 1, :page => 'Unexistent page'
56 56 assert_response :success
57 57 assert_template 'edit'
58 58 end
59 59
60 60 def test_create_page
61 61 @request.session[:user_id] = 2
62 62 post :edit, :id => 1,
63 63 :page => 'New page',
64 64 :content => {:comments => 'Created the page',
65 65 :text => "h1. New page\n\nThis is a new page",
66 66 :version => 0}
67 assert_redirected_to 'wiki/1/New_page'
67 assert_redirected_to 'wiki/ecookbook/New_page'
68 68 page = Project.find(1).wiki.find_page('New page')
69 69 assert !page.new_record?
70 70 assert_not_nil page.content
71 71 assert_equal 'Created the page', page.content.comments
72 72 end
73 73
74 74 def test_preview
75 75 @request.session[:user_id] = 2
76 76 xhr :post, :preview, :id => 1, :page => 'CookBook_documentation',
77 77 :content => { :comments => '',
78 78 :text => 'this is a *previewed text*',
79 79 :version => 3 }
80 80 assert_response :success
81 81 assert_template 'common/_preview'
82 82 assert_tag :tag => 'strong', :content => /previewed text/
83 83 end
84 84
85 85 def test_history
86 86 get :history, :id => 1, :page => 'CookBook_documentation'
87 87 assert_response :success
88 88 assert_template 'history'
89 89 assert_not_nil assigns(:versions)
90 90 assert_equal 3, assigns(:versions).size
91 91 end
92 92
93 93 def test_diff
94 94 get :diff, :id => 1, :page => 'CookBook_documentation', :version => 2, :version_from => 1
95 95 assert_response :success
96 96 assert_template 'diff'
97 97 assert_tag :tag => 'span', :attributes => { :class => 'diff_in'},
98 98 :content => /updated/
99 99 end
100 100
101 101 def test_rename_with_redirect
102 102 @request.session[:user_id] = 2
103 103 post :rename, :id => 1, :page => 'Another_page',
104 104 :wiki_page => { :title => 'Another renamed page',
105 105 :redirect_existing_links => 1 }
106 assert_redirected_to 'wiki/1/Another_renamed_page'
106 assert_redirected_to 'wiki/ecookbook/Another_renamed_page'
107 107 wiki = Project.find(1).wiki
108 108 # Check redirects
109 109 assert_not_nil wiki.find_page('Another page')
110 110 assert_nil wiki.find_page('Another page', :with_redirect => false)
111 111 end
112 112
113 113 def test_rename_without_redirect
114 114 @request.session[:user_id] = 2
115 115 post :rename, :id => 1, :page => 'Another_page',
116 116 :wiki_page => { :title => 'Another renamed page',
117 117 :redirect_existing_links => "0" }
118 assert_redirected_to 'wiki/1/Another_renamed_page'
118 assert_redirected_to 'wiki/ecookbook/Another_renamed_page'
119 119 wiki = Project.find(1).wiki
120 120 # Check that there's no redirects
121 121 assert_nil wiki.find_page('Another page')
122 122 end
123 123
124 124 def test_destroy
125 125 @request.session[:user_id] = 2
126 126 post :destroy, :id => 1, :page => 'CookBook_documentation'
127 assert_redirected_to 'wiki/1/Page_index/special'
127 assert_redirected_to 'wiki/ecookbook/Page_index/special'
128 128 end
129 129
130 130 def test_page_index
131 get :special, :id => 1, :page => 'Page_index'
131 get :special, :id => 'ecookbook', :page => 'Page_index'
132 132 assert_response :success
133 133 assert_template 'special_page_index'
134 134 pages = assigns(:pages)
135 135 assert_not_nil pages
136 136 assert_equal 2, pages.size
137 assert_tag :tag => 'a', :attributes => { :href => '/wiki/1/CookBook_documentation' },
137 assert_tag :tag => 'a', :attributes => { :href => '/wiki/ecookbook/CookBook_documentation' },
138 138 :content => /CookBook documentation/
139 139 end
140 140
141 141 def test_not_found
142 142 get :index, :id => 999
143 143 assert_response 404
144 144 end
145 145 end
@@ -1,56 +1,56
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 'wikis_controller'
20 20
21 21 # Re-raise errors caught by the controller.
22 22 class WikisController; def rescue_action(e) raise e end; end
23 23
24 24 class WikisControllerTest < Test::Unit::TestCase
25 25 fixtures :projects, :users, :roles, :members, :enabled_modules, :wikis
26 26
27 27 def setup
28 28 @controller = WikisController.new
29 29 @request = ActionController::TestRequest.new
30 30 @response = ActionController::TestResponse.new
31 31 User.current = nil
32 32 end
33 33
34 34 def test_create
35 35 @request.session[:user_id] = 1
36 36 assert_nil Project.find(3).wiki
37 37 post :edit, :id => 3, :wiki => { :start_page => 'Start page' }
38 38 assert_response :success
39 39 wiki = Project.find(3).wiki
40 40 assert_not_nil wiki
41 41 assert_equal 'Start page', wiki.start_page
42 42 end
43 43
44 44 def test_destroy
45 45 @request.session[:user_id] = 1
46 46 post :destroy, :id => 1, :confirm => 1
47 assert_redirected_to 'projects/settings/1'
47 assert_redirected_to 'projects/settings/ecookbook'
48 48 assert_nil Project.find(1).wiki
49 49 end
50 50
51 51 def test_not_found
52 52 @request.session[:user_id] = 1
53 53 post :destroy, :id => 999, :confirm => 1
54 54 assert_response 404
55 55 end
56 56 end
@@ -1,58 +1,58
1 1 require "#{File.dirname(__FILE__)}/../test_helper"
2 2
3 3 class IssuesTest < ActionController::IntegrationTest
4 4 fixtures :projects, :users, :trackers, :issue_statuses, :issues, :enumerations
5 5
6 6 # create an issue
7 7 def test_add_issue
8 8 log_user('jsmith', 'jsmith')
9 9 get "projects/add_issue/1", :tracker_id => "1"
10 10 assert_response :success
11 11 assert_template "projects/add_issue"
12 12
13 13 post "projects/add_issue/1", :tracker_id => "1",
14 14 :issue => { :start_date => "2006-12-26",
15 15 :priority_id => "3",
16 16 :subject => "new test issue",
17 17 :category_id => "",
18 18 :description => "new issue",
19 19 :done_ratio => "0",
20 20 :due_date => "",
21 21 :assigned_to_id => "" }
22 22 # find created issue
23 23 issue = Issue.find_by_subject("new test issue")
24 24 assert_kind_of Issue, issue
25 25
26 26 # check redirection
27 assert_redirected_to "projects/1/issues"
27 assert_redirected_to "projects/ecookbook/issues"
28 28 follow_redirect!
29 29 assert assigns(:issues).include?(issue)
30 30
31 31 # check issue attributes
32 32 assert_equal 'jsmith', issue.author.login
33 33 assert_equal 1, issue.project.id
34 34 assert_equal 1, issue.status.id
35 35 end
36 36
37 37 # add then remove 2 attachments to an issue
38 38 def test_issue_attachements
39 39 log_user('jsmith', 'jsmith')
40 40
41 41 post "issues/add_note/1", { :notes => 'Some notes', 'attachments[]' => ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + '/files/testfile.txt', 'text/plain') }
42 42 assert_redirected_to "issues/show/1"
43 43
44 44 # make sure attachment was saved
45 45 attachment = Issue.find(1).attachments.find_by_filename("testfile.txt")
46 46 assert_kind_of Attachment, attachment
47 47 assert_equal Issue.find(1), attachment.container
48 48 # verify the size of the attachment stored in db
49 49 #assert_equal file_data_1.length, attachment.filesize
50 50 # verify that the attachment was written to disk
51 51 assert File.exist?(attachment.diskfile)
52 52
53 53 # remove the attachments
54 54 Issue.find(1).attachments.each(&:destroy)
55 55 assert_equal 0, Issue.find(1).attachments.length
56 56 end
57 57
58 58 end
General Comments 0
You need to be logged in to leave comments. Login now