##// END OF EJS Templates
Removed deep nested time entries routes....
Jean-Philippe Lang -
r13227:043c2c92da7d
parent child
Show More
@@ -1,6 +1,6
1 1 <h2><%= l(:label_spent_time) %></h2>
2 2
3 <%= labelled_form_for @time_entry, :url => project_time_entry_path(@time_entry.project, @time_entry) do |f| %>
3 <%= labelled_form_for @time_entry, :url => time_entry_path(@time_entry) do |f| %>
4 4 <%= render :partial => 'form', :locals => {:f => f} %>
5 5 <%= submit_tag l(:button_save) %>
6 6 <% end %>
@@ -1,348 +1,348
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2014 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 Rails.application.routes.draw do
19 19 root :to => 'welcome#index', :as => 'home'
20 20
21 21 match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post]
22 22 match 'logout', :to => 'account#logout', :as => 'signout', :via => [:get, :post]
23 23 match 'account/register', :to => 'account#register', :via => [:get, :post], :as => 'register'
24 24 match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post], :as => 'lost_password'
25 25 match 'account/activate', :to => 'account#activate', :via => :get
26 26 get 'account/activation_email', :to => 'account#activation_email', :as => 'activation_email'
27 27
28 28 match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put, :patch]
29 29 match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put, :patch]
30 30 match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put, :patch]
31 31 match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put, :patch]
32 32
33 33 match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
34 34 match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
35 35
36 36 match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post], :as => 'new_board_message'
37 37 get 'boards/:board_id/topics/:id', :to => 'messages#show', :as => 'board_message'
38 38 match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post]
39 39 get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
40 40
41 41 post 'boards/:board_id/topics/preview', :to => 'messages#preview', :as => 'preview_board_message'
42 42 post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply'
43 43 post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
44 44 post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy'
45 45
46 46 # Misc issue routes. TODO: move into resources
47 47 match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues'
48 48 match '/issues/context_menu', :to => 'context_menus#issues', :as => 'issues_context_menu', :via => [:get, :post]
49 49 match '/issues/changes', :to => 'journals#index', :as => 'issue_changes', :via => :get
50 50 match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'
51 51
52 52 match '/journals/diff/:id', :to => 'journals#diff', :id => /\d+/, :via => :get
53 53 match '/journals/edit/:id', :to => 'journals#edit', :id => /\d+/, :via => [:get, :post]
54 54
55 55 get '/projects/:project_id/issues/gantt', :to => 'gantts#show', :as => 'project_gantt'
56 56 get '/issues/gantt', :to => 'gantts#show'
57 57
58 58 get '/projects/:project_id/issues/calendar', :to => 'calendars#show', :as => 'project_calendar'
59 59 get '/issues/calendar', :to => 'calendars#show'
60 60
61 61 get 'projects/:id/issues/report', :to => 'reports#issue_report', :as => 'project_issues_report'
62 62 get 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :as => 'project_issues_report_details'
63 63
64 64 match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
65 65 match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
66 66 match 'my/page', :controller => 'my', :action => 'page', :via => :get
67 67 match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
68 68 match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post
69 69 match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post
70 70 match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post]
71 71 match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get
72 72 match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
73 73 match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
74 74 match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
75 75
76 76 resources :users do
77 77 resources :memberships, :controller => 'principal_memberships'
78 78 end
79 79
80 80 post 'watchers/watch', :to => 'watchers#watch', :as => 'watch'
81 81 delete 'watchers/watch', :to => 'watchers#unwatch'
82 82 get 'watchers/new', :to => 'watchers#new'
83 83 post 'watchers', :to => 'watchers#create'
84 84 post 'watchers/append', :to => 'watchers#append'
85 85 delete 'watchers', :to => 'watchers#destroy'
86 86 get 'watchers/autocomplete_for_user', :to => 'watchers#autocomplete_for_user'
87 87 # Specific routes for issue watchers API
88 88 post 'issues/:object_id/watchers', :to => 'watchers#create', :object_type => 'issue'
89 89 delete 'issues/:object_id/watchers/:user_id' => 'watchers#destroy', :object_type => 'issue'
90 90
91 91 resources :projects do
92 92 member do
93 93 get 'settings(/:tab)', :action => 'settings', :as => 'settings'
94 94 post 'modules'
95 95 post 'archive'
96 96 post 'unarchive'
97 97 post 'close'
98 98 post 'reopen'
99 99 match 'copy', :via => [:get, :post]
100 100 end
101 101
102 102 shallow do
103 103 resources :memberships, :controller => 'members', :only => [:index, :show, :new, :create, :update, :destroy] do
104 104 collection do
105 105 get 'autocomplete'
106 106 end
107 107 end
108 108 end
109 109
110 110 resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy]
111 111
112 112 get 'issues/:copy_from/copy', :to => 'issues#new', :as => 'copy_issue'
113 113 resources :issues, :only => [:index, :new, :create]
114 114 # issue form update
115 115 match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :patch, :post], :as => 'issue_form'
116 116
117 117 resources :files, :only => [:index, :new, :create]
118 118
119 119 resources :versions, :except => [:index, :show, :edit, :update, :destroy] do
120 120 collection do
121 121 put 'close_completed'
122 122 end
123 123 end
124 124 get 'versions.:format', :to => 'versions#index'
125 125 get 'roadmap', :to => 'versions#index', :format => false
126 126 get 'versions', :to => 'versions#index'
127 127
128 128 resources :news, :except => [:show, :edit, :update, :destroy]
129 resources :time_entries, :controller => 'timelog' do
129 resources :time_entries, :controller => 'timelog', :except => [:show, :edit, :update, :destroy] do
130 130 get 'report', :on => :collection
131 131 end
132 132 resources :queries, :only => [:new, :create]
133 133 shallow do
134 134 resources :issue_categories
135 135 end
136 136 resources :documents, :except => [:show, :edit, :update, :destroy]
137 137 resources :boards
138 138 shallow do
139 139 resources :repositories, :except => [:index, :show] do
140 140 member do
141 141 match 'committers', :via => [:get, :post]
142 142 end
143 143 end
144 144 end
145 145
146 146 match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
147 147 resources :wiki, :except => [:index, :new, :create], :as => 'wiki_page' do
148 148 member do
149 149 get 'rename'
150 150 post 'rename'
151 151 get 'history'
152 152 get 'diff'
153 153 match 'preview', :via => [:post, :put, :patch]
154 154 post 'protect'
155 155 post 'add_attachment'
156 156 end
157 157 collection do
158 158 get 'export'
159 159 get 'date_index'
160 160 end
161 161 end
162 162 match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
163 163 get 'wiki/:id/:version', :to => 'wiki#show', :constraints => {:version => /\d+/}
164 164 delete 'wiki/:id/:version', :to => 'wiki#destroy_version'
165 165 get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
166 166 get 'wiki/:id/:version/diff', :to => 'wiki#diff'
167 167 end
168 168
169 169 resources :issues do
170 170 collection do
171 171 match 'bulk_edit', :via => [:get, :post]
172 172 post 'bulk_update'
173 173 end
174 resources :time_entries, :controller => 'timelog' do
174 resources :time_entries, :controller => 'timelog', :except => [:show, :edit, :update, :destroy] do
175 175 collection do
176 176 get 'report'
177 177 end
178 178 end
179 179 shallow do
180 180 resources :relations, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
181 181 end
182 182 end
183 183 match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
184 184
185 185 resources :queries, :except => [:show]
186 186
187 187 resources :news, :only => [:index, :show, :edit, :update, :destroy]
188 188 match '/news/:id/comments', :to => 'comments#create', :via => :post
189 189 match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete
190 190
191 191 resources :versions, :only => [:show, :edit, :update, :destroy] do
192 192 post 'status_by', :on => :member
193 193 end
194 194
195 195 resources :documents, :only => [:show, :edit, :update, :destroy] do
196 196 post 'add_attachment', :on => :member
197 197 end
198 198
199 199 match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu, :via => [:get, :post]
200 200
201 201 resources :time_entries, :controller => 'timelog', :except => :destroy do
202 202 collection do
203 203 get 'report'
204 204 get 'bulk_edit'
205 205 post 'bulk_update'
206 206 end
207 207 end
208 208 match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/
209 209 # TODO: delete /time_entries for bulk deletion
210 210 match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete
211 211
212 212 get 'projects/:id/activity', :to => 'activities#index', :as => :project_activity
213 213 get 'activity', :to => 'activities#index'
214 214
215 215 # repositories routes
216 216 get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats'
217 217 get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
218 218
219 219 get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))',
220 220 :to => 'repositories#changes'
221 221
222 222 get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision'
223 223 get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision'
224 224 post 'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue'
225 225 delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
226 226 get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
227 227 get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))',
228 228 :controller => 'repositories',
229 229 :format => false,
230 230 :constraints => {
231 231 :action => /(browse|show|entry|raw|annotate|diff)/,
232 232 :rev => /[a-z0-9\.\-_]+/
233 233 }
234 234
235 235 get 'projects/:id/repository/statistics', :to => 'repositories#stats'
236 236 get 'projects/:id/repository/graph', :to => 'repositories#graph'
237 237
238 238 get 'projects/:id/repository/changes(/*path(.:ext))',
239 239 :to => 'repositories#changes'
240 240
241 241 get 'projects/:id/repository/revisions', :to => 'repositories#revisions'
242 242 get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision'
243 243 get 'projects/:id/repository/revision', :to => 'repositories#revision'
244 244 post 'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue'
245 245 delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
246 246 get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))',
247 247 :controller => 'repositories',
248 248 :format => false,
249 249 :constraints => {
250 250 :action => /(browse|show|entry|raw|annotate|diff)/,
251 251 :rev => /[a-z0-9\.\-_]+/
252 252 }
253 253 get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))',
254 254 :controller => 'repositories',
255 255 :action => /(browse|show|entry|raw|changes|annotate|diff)/
256 256 get 'projects/:id/repository/:action(/*path(.:ext))',
257 257 :controller => 'repositories',
258 258 :action => /(browse|show|entry|raw|changes|annotate|diff)/
259 259
260 260 get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil
261 261 get 'projects/:id/repository', :to => 'repositories#show', :path => nil
262 262
263 263 # additional routes for having the file name at the end of url
264 264 get 'attachments/:id/:filename', :to => 'attachments#show', :id => /\d+/, :filename => /.*/, :as => 'named_attachment'
265 265 get 'attachments/download/:id/:filename', :to => 'attachments#download', :id => /\d+/, :filename => /.*/, :as => 'download_named_attachment'
266 266 get 'attachments/download/:id', :to => 'attachments#download', :id => /\d+/
267 267 get 'attachments/thumbnail/:id(/:size)', :to => 'attachments#thumbnail', :id => /\d+/, :size => /\d+/, :as => 'thumbnail'
268 268 resources :attachments, :only => [:show, :destroy]
269 269
270 270 resources :groups do
271 271 resources :memberships, :controller => 'principal_memberships'
272 272 member do
273 273 get 'autocomplete_for_user'
274 274 end
275 275 end
276 276
277 277 get 'groups/:id/users/new', :to => 'groups#new_users', :id => /\d+/, :as => 'new_group_users'
278 278 post 'groups/:id/users', :to => 'groups#add_users', :id => /\d+/, :as => 'group_users'
279 279 delete 'groups/:id/users/:user_id', :to => 'groups#remove_user', :id => /\d+/, :as => 'group_user'
280 280
281 281 resources :trackers, :except => :show do
282 282 collection do
283 283 match 'fields', :via => [:get, :post]
284 284 end
285 285 end
286 286 resources :issue_statuses, :except => :show do
287 287 collection do
288 288 post 'update_issue_done_ratio'
289 289 end
290 290 end
291 291 resources :custom_fields, :except => :show
292 292 resources :roles do
293 293 collection do
294 294 match 'permissions', :via => [:get, :post]
295 295 end
296 296 end
297 297 resources :enumerations, :except => :show
298 298 match 'enumerations/:type', :to => 'enumerations#index', :via => :get
299 299
300 300 get 'projects/:id/search', :controller => 'search', :action => 'index'
301 301 get 'search', :controller => 'search', :action => 'index'
302 302
303 303 match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post
304 304
305 305 match 'admin', :controller => 'admin', :action => 'index', :via => :get
306 306 match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get
307 307 match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get
308 308 match 'admin/info', :controller => 'admin', :action => 'info', :via => :get
309 309 match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get
310 310 match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post
311 311
312 312 resources :auth_sources do
313 313 member do
314 314 get 'test_connection', :as => 'try_connection'
315 315 end
316 316 collection do
317 317 get 'autocomplete_for_new_user'
318 318 end
319 319 end
320 320
321 321 match 'workflows', :controller => 'workflows', :action => 'index', :via => :get
322 322 match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post]
323 323 match 'workflows/permissions', :controller => 'workflows', :action => 'permissions', :via => [:get, :post]
324 324 match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post]
325 325 match 'settings', :controller => 'settings', :action => 'index', :via => :get
326 326 match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post]
327 327 match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post], :as => 'plugin_settings'
328 328
329 329 match 'sys/projects', :to => 'sys#projects', :via => :get
330 330 match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post
331 331 match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => [:get, :post]
332 332
333 333 match 'uploads', :to => 'attachments#upload', :via => :post
334 334
335 335 get 'robots.txt', :to => 'welcome#robots'
336 336
337 337 Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|
338 338 file = File.join(plugin_dir, "config/routes.rb")
339 339 if File.exists?(file)
340 340 begin
341 341 instance_eval File.read(file)
342 342 rescue Exception => e
343 343 puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}."
344 344 exit 1
345 345 end
346 346 end
347 347 end
348 348 end
@@ -1,729 +1,728
1 1 # -*- coding: utf-8 -*-
2 2 # Redmine - project management software
3 3 # Copyright (C) 2006-2014 Jean-Philippe Lang
4 4 #
5 5 # This program is free software; you can redistribute it and/or
6 6 # modify it under the terms of the GNU General Public License
7 7 # as published by the Free Software Foundation; either version 2
8 8 # of the License, or (at your option) any later version.
9 9 #
10 10 # This program is distributed in the hope that it will be useful,
11 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 # GNU General Public License for more details.
14 14 #
15 15 # You should have received a copy of the GNU General Public License
16 16 # along with this program; if not, write to the Free Software
17 17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 18
19 19 require File.expand_path('../../test_helper', __FILE__)
20 20
21 21 class TimelogControllerTest < ActionController::TestCase
22 22 fixtures :projects, :enabled_modules, :roles, :members,
23 23 :member_roles, :issues, :time_entries, :users,
24 24 :trackers, :enumerations, :issue_statuses,
25 25 :custom_fields, :custom_values,
26 26 :projects_trackers, :custom_fields_trackers,
27 27 :custom_fields_projects
28 28
29 29 include Redmine::I18n
30 30
31 31 def test_new
32 32 @request.session[:user_id] = 3
33 33 get :new
34 34 assert_response :success
35 35 assert_template 'new'
36 36 assert_select 'input[name=?][type=hidden]', 'project_id', 0
37 37 assert_select 'input[name=?][type=hidden]', 'issue_id', 0
38 38 assert_select 'select[name=?]', 'time_entry[project_id]' do
39 39 # blank option for project
40 40 assert_select 'option[value=]'
41 41 end
42 42 end
43 43
44 44 def test_new_with_project_id
45 45 @request.session[:user_id] = 3
46 46 get :new, :project_id => 1
47 47 assert_response :success
48 48 assert_template 'new'
49 49 assert_select 'input[name=?][type=hidden]', 'project_id'
50 50 assert_select 'input[name=?][type=hidden]', 'issue_id', 0
51 51 assert_select 'select[name=?]', 'time_entry[project_id]', 0
52 52 end
53 53
54 54 def test_new_with_issue_id
55 55 @request.session[:user_id] = 3
56 56 get :new, :issue_id => 2
57 57 assert_response :success
58 58 assert_template 'new'
59 59 assert_select 'input[name=?][type=hidden]', 'project_id', 0
60 60 assert_select 'input[name=?][type=hidden]', 'issue_id'
61 61 assert_select 'select[name=?]', 'time_entry[project_id]', 0
62 62 end
63 63
64 64 def test_new_without_project_should_prefill_the_form
65 65 @request.session[:user_id] = 3
66 66 get :new, :time_entry => {:project_id => '1'}
67 67 assert_response :success
68 68 assert_template 'new'
69 69 assert_select 'select[name=?]', 'time_entry[project_id]' do
70 70 assert_select 'option[value=1][selected=selected]'
71 71 end
72 72 end
73 73
74 74 def test_new_without_project_should_deny_without_permission
75 75 Role.all.each {|role| role.remove_permission! :log_time}
76 76 @request.session[:user_id] = 3
77 77
78 78 get :new
79 79 assert_response 403
80 80 end
81 81
82 82 def test_new_should_select_default_activity
83 83 @request.session[:user_id] = 3
84 84 get :new, :project_id => 1
85 85 assert_response :success
86 86 assert_select 'select[name=?]', 'time_entry[activity_id]' do
87 87 assert_select 'option[selected=selected]', :text => 'Development'
88 88 end
89 89 end
90 90
91 91 def test_new_should_only_show_active_time_entry_activities
92 92 @request.session[:user_id] = 3
93 93 get :new, :project_id => 1
94 94 assert_response :success
95 95 assert_no_tag 'option', :content => 'Inactive Activity'
96 96 end
97 97
98 98 def test_get_edit_existing_time
99 99 @request.session[:user_id] = 2
100 100 get :edit, :id => 2, :project_id => nil
101 101 assert_response :success
102 102 assert_template 'edit'
103 # Default activity selected
104 assert_tag :tag => 'form', :attributes => { :action => '/projects/ecookbook/time_entries/2' }
103 assert_tag :tag => 'form', :attributes => { :action => '/time_entries/2' }
105 104 end
106 105
107 106 def test_get_edit_with_an_existing_time_entry_with_inactive_activity
108 107 te = TimeEntry.find(1)
109 108 te.activity = TimeEntryActivity.find_by_name("Inactive Activity")
110 109 te.save!
111 110
112 111 @request.session[:user_id] = 1
113 112 get :edit, :project_id => 1, :id => 1
114 113 assert_response :success
115 114 assert_template 'edit'
116 115 # Blank option since nothing is pre-selected
117 116 assert_tag :tag => 'option', :content => '--- Please select ---'
118 117 end
119 118
120 119 def test_post_create
121 120 @request.session[:user_id] = 3
122 121 assert_difference 'TimeEntry.count' do
123 122 post :create, :project_id => 1,
124 123 :time_entry => {:comments => 'Some work on TimelogControllerTest',
125 124 # Not the default activity
126 125 :activity_id => '11',
127 126 :spent_on => '2008-03-14',
128 127 :issue_id => '1',
129 128 :hours => '7.3'}
130 129 assert_redirected_to '/projects/ecookbook/time_entries'
131 130 end
132 131
133 132 t = TimeEntry.order('id DESC').first
134 133 assert_not_nil t
135 134 assert_equal 'Some work on TimelogControllerTest', t.comments
136 135 assert_equal 1, t.project_id
137 136 assert_equal 1, t.issue_id
138 137 assert_equal 11, t.activity_id
139 138 assert_equal 7.3, t.hours
140 139 assert_equal 3, t.user_id
141 140 end
142 141
143 142 def test_post_create_with_blank_issue
144 143 @request.session[:user_id] = 3
145 144 assert_difference 'TimeEntry.count' do
146 145 post :create, :project_id => 1,
147 146 :time_entry => {:comments => 'Some work on TimelogControllerTest',
148 147 # Not the default activity
149 148 :activity_id => '11',
150 149 :issue_id => '',
151 150 :spent_on => '2008-03-14',
152 151 :hours => '7.3'}
153 152 assert_redirected_to '/projects/ecookbook/time_entries'
154 153 end
155 154
156 155 t = TimeEntry.order('id DESC').first
157 156 assert_not_nil t
158 157 assert_equal 'Some work on TimelogControllerTest', t.comments
159 158 assert_equal 1, t.project_id
160 159 assert_nil t.issue_id
161 160 assert_equal 11, t.activity_id
162 161 assert_equal 7.3, t.hours
163 162 assert_equal 3, t.user_id
164 163 end
165 164
166 165 def test_create_and_continue_at_project_level
167 166 @request.session[:user_id] = 2
168 167 assert_difference 'TimeEntry.count' do
169 168 post :create, :time_entry => {:project_id => '1',
170 169 :activity_id => '11',
171 170 :issue_id => '',
172 171 :spent_on => '2008-03-14',
173 172 :hours => '7.3'},
174 173 :continue => '1'
175 174 assert_redirected_to '/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=&time_entry%5Bproject_id%5D=1'
176 175 end
177 176 end
178 177
179 178 def test_create_and_continue_at_issue_level
180 179 @request.session[:user_id] = 2
181 180 assert_difference 'TimeEntry.count' do
182 181 post :create, :time_entry => {:project_id => '',
183 182 :activity_id => '11',
184 183 :issue_id => '1',
185 184 :spent_on => '2008-03-14',
186 185 :hours => '7.3'},
187 186 :continue => '1'
188 187 assert_redirected_to '/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=1&time_entry%5Bproject_id%5D='
189 188 end
190 189 end
191 190
192 191 def test_create_and_continue_with_project_id
193 192 @request.session[:user_id] = 2
194 193 assert_difference 'TimeEntry.count' do
195 194 post :create, :project_id => 1,
196 195 :time_entry => {:activity_id => '11',
197 196 :issue_id => '',
198 197 :spent_on => '2008-03-14',
199 198 :hours => '7.3'},
200 199 :continue => '1'
201 200 assert_redirected_to '/projects/ecookbook/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=&time_entry%5Bproject_id%5D='
202 201 end
203 202 end
204 203
205 204 def test_create_and_continue_with_issue_id
206 205 @request.session[:user_id] = 2
207 206 assert_difference 'TimeEntry.count' do
208 207 post :create, :issue_id => 1,
209 208 :time_entry => {:activity_id => '11',
210 209 :issue_id => '1',
211 210 :spent_on => '2008-03-14',
212 211 :hours => '7.3'},
213 212 :continue => '1'
214 213 assert_redirected_to '/issues/1/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=1&time_entry%5Bproject_id%5D='
215 214 end
216 215 end
217 216
218 217 def test_create_without_log_time_permission_should_be_denied
219 218 @request.session[:user_id] = 2
220 219 Role.find_by_name('Manager').remove_permission! :log_time
221 220 post :create, :project_id => 1,
222 221 :time_entry => {:activity_id => '11',
223 222 :issue_id => '',
224 223 :spent_on => '2008-03-14',
225 224 :hours => '7.3'}
226 225
227 226 assert_response 403
228 227 end
229 228
230 229 def test_create_without_project_and_issue_should_fail
231 230 @request.session[:user_id] = 2
232 231 post :create, :time_entry => {:issue_id => ''}
233 232
234 233 assert_response :success
235 234 assert_template 'new'
236 235 end
237 236
238 237 def test_create_with_failure
239 238 @request.session[:user_id] = 2
240 239 post :create, :project_id => 1,
241 240 :time_entry => {:activity_id => '',
242 241 :issue_id => '',
243 242 :spent_on => '2008-03-14',
244 243 :hours => '7.3'}
245 244
246 245 assert_response :success
247 246 assert_template 'new'
248 247 end
249 248
250 249 def test_create_without_project
251 250 @request.session[:user_id] = 2
252 251 assert_difference 'TimeEntry.count' do
253 252 post :create, :time_entry => {:project_id => '1',
254 253 :activity_id => '11',
255 254 :issue_id => '',
256 255 :spent_on => '2008-03-14',
257 256 :hours => '7.3'}
258 257 end
259 258
260 259 assert_redirected_to '/projects/ecookbook/time_entries'
261 260 time_entry = TimeEntry.order('id DESC').first
262 261 assert_equal 1, time_entry.project_id
263 262 end
264 263
265 264 def test_create_without_project_should_fail_with_issue_not_inside_project
266 265 @request.session[:user_id] = 2
267 266 assert_no_difference 'TimeEntry.count' do
268 267 post :create, :time_entry => {:project_id => '1',
269 268 :activity_id => '11',
270 269 :issue_id => '5',
271 270 :spent_on => '2008-03-14',
272 271 :hours => '7.3'}
273 272 end
274 273
275 274 assert_response :success
276 275 assert assigns(:time_entry).errors[:issue_id].present?
277 276 end
278 277
279 278 def test_create_without_project_should_deny_without_permission
280 279 @request.session[:user_id] = 2
281 280 Project.find(3).disable_module!(:time_tracking)
282 281
283 282 assert_no_difference 'TimeEntry.count' do
284 283 post :create, :time_entry => {:project_id => '3',
285 284 :activity_id => '11',
286 285 :issue_id => '',
287 286 :spent_on => '2008-03-14',
288 287 :hours => '7.3'}
289 288 end
290 289
291 290 assert_response 403
292 291 end
293 292
294 293 def test_create_without_project_with_failure
295 294 @request.session[:user_id] = 2
296 295 assert_no_difference 'TimeEntry.count' do
297 296 post :create, :time_entry => {:project_id => '1',
298 297 :activity_id => '11',
299 298 :issue_id => '',
300 299 :spent_on => '2008-03-14',
301 300 :hours => ''}
302 301 end
303 302
304 303 assert_response :success
305 304 assert_tag 'select', :attributes => {:name => 'time_entry[project_id]'},
306 305 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
307 306 end
308 307
309 308 def test_update
310 309 entry = TimeEntry.find(1)
311 310 assert_equal 1, entry.issue_id
312 311 assert_equal 2, entry.user_id
313 312
314 313 @request.session[:user_id] = 1
315 314 put :update, :id => 1,
316 315 :time_entry => {:issue_id => '2',
317 316 :hours => '8'}
318 317 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
319 318 entry.reload
320 319
321 320 assert_equal 8, entry.hours
322 321 assert_equal 2, entry.issue_id
323 322 assert_equal 2, entry.user_id
324 323 end
325 324
326 325 def test_update_should_allow_to_change_issue_to_another_project
327 326 entry = TimeEntry.generate!(:issue_id => 1)
328 327
329 328 @request.session[:user_id] = 1
330 329 put :update, :id => entry.id, :time_entry => {:issue_id => '5'}
331 330 assert_response 302
332 331 entry.reload
333 332
334 333 assert_equal 5, entry.issue_id
335 334 assert_equal 3, entry.project_id
336 335 end
337 336
338 337 def test_update_should_not_allow_to_change_issue_to_an_invalid_project
339 338 entry = TimeEntry.generate!(:issue_id => 1)
340 339 Project.find(3).disable_module!(:time_tracking)
341 340
342 341 @request.session[:user_id] = 1
343 342 put :update, :id => entry.id, :time_entry => {:issue_id => '5'}
344 343 assert_response 200
345 344 assert_include "Issue is invalid", assigns(:time_entry).errors.full_messages
346 345 end
347 346
348 347 def test_get_bulk_edit
349 348 @request.session[:user_id] = 2
350 349 get :bulk_edit, :ids => [1, 2]
351 350 assert_response :success
352 351 assert_template 'bulk_edit'
353 352
354 353 assert_select 'ul#bulk-selection' do
355 354 assert_select 'li', 2
356 355 assert_select 'li a', :text => '03/23/2007 - eCookbook: 4.25 hours'
357 356 end
358 357
359 358 assert_select 'form#bulk_edit_form[action=?]', '/time_entries/bulk_update' do
360 359 # System wide custom field
361 360 assert_select 'select[name=?]', 'time_entry[custom_field_values][10]'
362 361
363 362 # Activities
364 363 assert_select 'select[name=?]', 'time_entry[activity_id]' do
365 364 assert_select 'option[value=]', :text => '(No change)'
366 365 assert_select 'option[value=9]', :text => 'Design'
367 366 end
368 367 end
369 368 end
370 369
371 370 def test_get_bulk_edit_on_different_projects
372 371 @request.session[:user_id] = 2
373 372 get :bulk_edit, :ids => [1, 2, 6]
374 373 assert_response :success
375 374 assert_template 'bulk_edit'
376 375 end
377 376
378 377 def test_bulk_update
379 378 @request.session[:user_id] = 2
380 379 # update time entry activity
381 380 post :bulk_update, :ids => [1, 2], :time_entry => { :activity_id => 9}
382 381
383 382 assert_response 302
384 383 # check that the issues were updated
385 384 assert_equal [9, 9], TimeEntry.where(:id => [1, 2]).collect {|i| i.activity_id}
386 385 end
387 386
388 387 def test_bulk_update_with_failure
389 388 @request.session[:user_id] = 2
390 389 post :bulk_update, :ids => [1, 2], :time_entry => { :hours => 'A'}
391 390
392 391 assert_response 302
393 392 assert_match /Failed to save 2 time entrie/, flash[:error]
394 393 end
395 394
396 395 def test_bulk_update_on_different_projects
397 396 @request.session[:user_id] = 2
398 397 # makes user a manager on the other project
399 398 Member.create!(:user_id => 2, :project_id => 3, :role_ids => [1])
400 399
401 400 # update time entry activity
402 401 post :bulk_update, :ids => [1, 2, 4], :time_entry => { :activity_id => 9 }
403 402
404 403 assert_response 302
405 404 # check that the issues were updated
406 405 assert_equal [9, 9, 9], TimeEntry.where(:id => [1, 2, 4]).collect {|i| i.activity_id}
407 406 end
408 407
409 408 def test_bulk_update_on_different_projects_without_rights
410 409 @request.session[:user_id] = 3
411 410 user = User.find(3)
412 411 action = { :controller => "timelog", :action => "bulk_update" }
413 412 assert user.allowed_to?(action, TimeEntry.find(1).project)
414 413 assert ! user.allowed_to?(action, TimeEntry.find(5).project)
415 414 post :bulk_update, :ids => [1, 5], :time_entry => { :activity_id => 9 }
416 415 assert_response 403
417 416 end
418 417
419 418 def test_bulk_update_custom_field
420 419 @request.session[:user_id] = 2
421 420 post :bulk_update, :ids => [1, 2], :time_entry => { :custom_field_values => {'10' => '0'} }
422 421
423 422 assert_response 302
424 423 assert_equal ["0", "0"], TimeEntry.where(:id => [1, 2]).collect {|i| i.custom_value_for(10).value}
425 424 end
426 425
427 426 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
428 427 @request.session[:user_id] = 2
429 428 post :bulk_update, :ids => [1,2], :back_url => '/time_entries'
430 429
431 430 assert_response :redirect
432 431 assert_redirected_to '/time_entries'
433 432 end
434 433
435 434 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
436 435 @request.session[:user_id] = 2
437 436 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
438 437
439 438 assert_response :redirect
440 439 assert_redirected_to :controller => 'timelog', :action => 'index', :project_id => Project.find(1).identifier
441 440 end
442 441
443 442 def test_post_bulk_update_without_edit_permission_should_be_denied
444 443 @request.session[:user_id] = 2
445 444 Role.find_by_name('Manager').remove_permission! :edit_time_entries
446 445 post :bulk_update, :ids => [1,2]
447 446
448 447 assert_response 403
449 448 end
450 449
451 450 def test_destroy
452 451 @request.session[:user_id] = 2
453 452 delete :destroy, :id => 1
454 453 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
455 454 assert_equal I18n.t(:notice_successful_delete), flash[:notice]
456 455 assert_nil TimeEntry.find_by_id(1)
457 456 end
458 457
459 458 def test_destroy_should_fail
460 459 # simulate that this fails (e.g. due to a plugin), see #5700
461 460 TimeEntry.any_instance.expects(:destroy).returns(false)
462 461
463 462 @request.session[:user_id] = 2
464 463 delete :destroy, :id => 1
465 464 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
466 465 assert_equal I18n.t(:notice_unable_delete_time_entry), flash[:error]
467 466 assert_not_nil TimeEntry.find_by_id(1)
468 467 end
469 468
470 469 def test_index_all_projects
471 470 get :index
472 471 assert_response :success
473 472 assert_template 'index'
474 473 assert_not_nil assigns(:total_hours)
475 474 assert_equal "162.90", "%.2f" % assigns(:total_hours)
476 475 assert_tag :form,
477 476 :attributes => {:action => "/time_entries", :id => 'query_form'}
478 477 end
479 478
480 479 def test_index_all_projects_should_show_log_time_link
481 480 @request.session[:user_id] = 2
482 481 get :index
483 482 assert_response :success
484 483 assert_template 'index'
485 484 assert_tag 'a', :attributes => {:href => '/time_entries/new'}, :content => /Log time/
486 485 end
487 486
488 487 def test_index_my_spent_time
489 488 @request.session[:user_id] = 2
490 489 get :index, :user_id => 'me'
491 490 assert_response :success
492 491 assert_template 'index'
493 492 assert assigns(:entries).all? {|entry| entry.user_id == 2}
494 493 end
495 494
496 495 def test_index_at_project_level
497 496 get :index, :project_id => 'ecookbook'
498 497 assert_response :success
499 498 assert_template 'index'
500 499 assert_not_nil assigns(:entries)
501 500 assert_equal 4, assigns(:entries).size
502 501 # project and subproject
503 502 assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
504 503 assert_not_nil assigns(:total_hours)
505 504 assert_equal "162.90", "%.2f" % assigns(:total_hours)
506 505 assert_tag :form,
507 506 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
508 507 end
509 508
510 509 def test_index_with_display_subprojects_issues_to_false_should_not_include_subproject_entries
511 510 entry = TimeEntry.generate!(:project => Project.find(3))
512 511
513 512 with_settings :display_subprojects_issues => '0' do
514 513 get :index, :project_id => 'ecookbook'
515 514 assert_response :success
516 515 assert_template 'index'
517 516 assert_not_include entry, assigns(:entries)
518 517 end
519 518 end
520 519
521 520 def test_index_with_display_subprojects_issues_to_false_and_subproject_filter_should_include_subproject_entries
522 521 entry = TimeEntry.generate!(:project => Project.find(3))
523 522
524 523 with_settings :display_subprojects_issues => '0' do
525 524 get :index, :project_id => 'ecookbook', :subproject_id => 3
526 525 assert_response :success
527 526 assert_template 'index'
528 527 assert_include entry, assigns(:entries)
529 528 end
530 529 end
531 530
532 531 def test_index_at_project_level_with_date_range
533 532 get :index, :project_id => 'ecookbook',
534 533 :f => ['spent_on'],
535 534 :op => {'spent_on' => '><'},
536 535 :v => {'spent_on' => ['2007-03-20', '2007-04-30']}
537 536 assert_response :success
538 537 assert_template 'index'
539 538 assert_not_nil assigns(:entries)
540 539 assert_equal 3, assigns(:entries).size
541 540 assert_not_nil assigns(:total_hours)
542 541 assert_equal "12.90", "%.2f" % assigns(:total_hours)
543 542 assert_tag :form,
544 543 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
545 544 end
546 545
547 546 def test_index_at_project_level_with_date_range_using_from_and_to_params
548 547 get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
549 548 assert_response :success
550 549 assert_template 'index'
551 550 assert_not_nil assigns(:entries)
552 551 assert_equal 3, assigns(:entries).size
553 552 assert_not_nil assigns(:total_hours)
554 553 assert_equal "12.90", "%.2f" % assigns(:total_hours)
555 554 assert_tag :form,
556 555 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
557 556 end
558 557
559 558 def test_index_at_project_level_with_period
560 559 get :index, :project_id => 'ecookbook',
561 560 :f => ['spent_on'],
562 561 :op => {'spent_on' => '>t-'},
563 562 :v => {'spent_on' => ['7']}
564 563 assert_response :success
565 564 assert_template 'index'
566 565 assert_not_nil assigns(:entries)
567 566 assert_not_nil assigns(:total_hours)
568 567 assert_tag :form,
569 568 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
570 569 end
571 570
572 571 def test_index_at_issue_level
573 572 get :index, :issue_id => 1
574 573 assert_response :success
575 574 assert_template 'index'
576 575 assert_not_nil assigns(:entries)
577 576 assert_equal 2, assigns(:entries).size
578 577 assert_not_nil assigns(:total_hours)
579 578 assert_equal 154.25, assigns(:total_hours)
580 579 # display all time
581 580 assert_nil assigns(:from)
582 581 assert_nil assigns(:to)
583 582 assert_tag :form,
584 583 :attributes => {:action => "/issues/1/time_entries", :id => 'query_form'}
585 584 end
586 585
587 586 def test_index_should_sort_by_spent_on_and_created_on
588 587 t1 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-16', :created_on => '2012-06-16 20:00:00', :activity_id => 10)
589 588 t2 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-16', :created_on => '2012-06-16 20:05:00', :activity_id => 10)
590 589 t3 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-15', :created_on => '2012-06-16 20:10:00', :activity_id => 10)
591 590
592 591 get :index, :project_id => 1,
593 592 :f => ['spent_on'],
594 593 :op => {'spent_on' => '><'},
595 594 :v => {'spent_on' => ['2012-06-15', '2012-06-16']}
596 595 assert_response :success
597 596 assert_equal [t2, t1, t3], assigns(:entries)
598 597
599 598 get :index, :project_id => 1,
600 599 :f => ['spent_on'],
601 600 :op => {'spent_on' => '><'},
602 601 :v => {'spent_on' => ['2012-06-15', '2012-06-16']},
603 602 :sort => 'spent_on'
604 603 assert_response :success
605 604 assert_equal [t3, t1, t2], assigns(:entries)
606 605 end
607 606
608 607 def test_index_with_filter_on_issue_custom_field
609 608 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
610 609 entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
611 610
612 611 get :index, :f => ['issue.cf_2'], :op => {'issue.cf_2' => '='}, :v => {'issue.cf_2' => ['filter_on_issue_custom_field']}
613 612 assert_response :success
614 613 assert_equal [entry], assigns(:entries)
615 614 end
616 615
617 616 def test_index_with_issue_custom_field_column
618 617 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
619 618 entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
620 619
621 620 get :index, :c => %w(project spent_on issue comments hours issue.cf_2)
622 621 assert_response :success
623 622 assert_include :'issue.cf_2', assigns(:query).column_names
624 623 assert_select 'td.issue_cf_2', :text => 'filter_on_issue_custom_field'
625 624 end
626 625
627 626 def test_index_with_time_entry_custom_field_column
628 627 field = TimeEntryCustomField.generate!(:field_format => 'string')
629 628 entry = TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value'})
630 629 field_name = "cf_#{field.id}"
631 630
632 631 get :index, :c => ["hours", field_name]
633 632 assert_response :success
634 633 assert_include field_name.to_sym, assigns(:query).column_names
635 634 assert_select "td.#{field_name}", :text => 'CF Value'
636 635 end
637 636
638 637 def test_index_with_time_entry_custom_field_sorting
639 638 field = TimeEntryCustomField.generate!(:field_format => 'string', :name => 'String Field')
640 639 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 1'})
641 640 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 3'})
642 641 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 2'})
643 642 field_name = "cf_#{field.id}"
644 643
645 644 get :index, :c => ["hours", field_name], :sort => field_name
646 645 assert_response :success
647 646 assert_include field_name.to_sym, assigns(:query).column_names
648 647 assert_select "th a.sort", :text => 'String Field'
649 648
650 649 # Make sure that values are properly sorted
651 650 values = assigns(:entries).map {|e| e.custom_field_value(field)}.compact
652 651 assert_equal 3, values.size
653 652 assert_equal values.sort, values
654 653 end
655 654
656 655 def test_index_atom_feed
657 656 get :index, :project_id => 1, :format => 'atom'
658 657 assert_response :success
659 658 assert_equal 'application/atom+xml', @response.content_type
660 659 assert_not_nil assigns(:items)
661 660 assert assigns(:items).first.is_a?(TimeEntry)
662 661 end
663 662
664 663 def test_index_at_project_level_should_include_csv_export_dialog
665 664 get :index, :project_id => 'ecookbook',
666 665 :f => ['spent_on'],
667 666 :op => {'spent_on' => '>='},
668 667 :v => {'spent_on' => ['2007-04-01']},
669 668 :c => ['spent_on', 'user']
670 669 assert_response :success
671 670
672 671 assert_select '#csv-export-options' do
673 672 assert_select 'form[action=?][method=get]', '/projects/ecookbook/time_entries.csv' do
674 673 # filter
675 674 assert_select 'input[name=?][value=?]', 'f[]', 'spent_on'
676 675 assert_select 'input[name=?][value=?]', 'op[spent_on]', '&gt;='
677 676 assert_select 'input[name=?][value=?]', 'v[spent_on][]', '2007-04-01'
678 677 # columns
679 678 assert_select 'input[name=?][value=?]', 'c[]', 'spent_on'
680 679 assert_select 'input[name=?][value=?]', 'c[]', 'user'
681 680 assert_select 'input[name=?]', 'c[]', 2
682 681 end
683 682 end
684 683 end
685 684
686 685 def test_index_cross_project_should_include_csv_export_dialog
687 686 get :index
688 687 assert_response :success
689 688
690 689 assert_select '#csv-export-options' do
691 690 assert_select 'form[action=?][method=get]', '/time_entries.csv'
692 691 end
693 692 end
694 693
695 694 def test_index_at_issue_level_should_include_csv_export_dialog
696 695 get :index, :issue_id => 3
697 696 assert_response :success
698 697
699 698 assert_select '#csv-export-options' do
700 699 assert_select 'form[action=?][method=get]', '/issues/3/time_entries.csv'
701 700 end
702 701 end
703 702
704 703 def test_index_csv_all_projects
705 704 with_settings :date_format => '%m/%d/%Y' do
706 705 get :index, :format => 'csv'
707 706 assert_response :success
708 707 assert_equal 'text/csv; header=present', response.content_type
709 708 end
710 709 end
711 710
712 711 def test_index_csv
713 712 with_settings :date_format => '%m/%d/%Y' do
714 713 get :index, :project_id => 1, :format => 'csv'
715 714 assert_response :success
716 715 assert_equal 'text/csv; header=present', response.content_type
717 716 end
718 717 end
719 718
720 719 def test_index_csv_should_fill_issue_column_with_tracker_id_and_subject
721 720 issue = Issue.find(1)
722 721 entry = TimeEntry.generate!(:issue => issue, :comments => "Issue column content test")
723 722
724 723 get :index, :format => 'csv'
725 724 line = response.body.split("\n").detect {|l| l.include?(entry.comments)}
726 725 assert_not_nil line
727 726 assert_include "#{issue.tracker} #1: #{issue.subject}", line
728 727 end
729 728 end
@@ -1,75 +1,65
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2014 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.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class RoutingTimelogsTest < Redmine::RoutingTest
21 21 def test_timelogs_global
22 22 should_route 'GET /time_entries' => 'timelog#index'
23 23 should_route 'GET /time_entries.csv' => 'timelog#index', :format => 'csv'
24 24 should_route 'GET /time_entries.atom' => 'timelog#index', :format => 'atom'
25 25 should_route 'GET /time_entries/new' => 'timelog#new'
26 26 should_route 'POST /time_entries' => 'timelog#create'
27 27
28 28 should_route 'GET /time_entries/22/edit' => 'timelog#edit', :id => '22'
29 29 should_route 'PUT /time_entries/22' => 'timelog#update', :id => '22'
30 30 should_route 'DELETE /time_entries/22' => 'timelog#destroy', :id => '22'
31 31 end
32 32
33 33 def test_timelogs_scoped_under_project
34 34 should_route 'GET /projects/foo/time_entries' => 'timelog#index', :project_id => 'foo'
35 35 should_route 'GET /projects/foo/time_entries.csv' => 'timelog#index', :project_id => 'foo', :format => 'csv'
36 36 should_route 'GET /projects/foo/time_entries.atom' => 'timelog#index', :project_id => 'foo', :format => 'atom'
37 37 should_route 'GET /projects/foo/time_entries/new' => 'timelog#new', :project_id => 'foo'
38 38 should_route 'POST /projects/foo/time_entries' => 'timelog#create', :project_id => 'foo'
39
40 # TODO: unused?
41 should_route 'GET /projects/foo/time_entries/22/edit' => 'timelog#edit', :project_id => 'foo', :id => '22'
42 should_route 'PUT /projects/foo/time_entries/22' => 'timelog#update', :project_id => 'foo', :id => '22'
43 should_route 'DELETE /projects/foo/time_entries/22' => 'timelog#destroy', :project_id => 'foo', :id => '22'
44 39 end
45 40
46 41 def test_timelogs_scoped_under_issues
47 42 should_route 'GET /issues/234/time_entries' => 'timelog#index', :issue_id => '234'
48 43 should_route 'GET /issues/234/time_entries.csv' => 'timelog#index', :issue_id => '234', :format => 'csv'
49 44 should_route 'GET /issues/234/time_entries.atom' => 'timelog#index', :issue_id => '234', :format => 'atom'
50 45 should_route 'GET /issues/234/time_entries/new' => 'timelog#new', :issue_id => '234'
51 46 should_route 'POST /issues/234/time_entries' => 'timelog#create', :issue_id => '234'
52
53 # TODO: unused?
54 should_route 'GET /issues/234/time_entries/22/edit' => 'timelog#edit', :issue_id => '234', :id => '22'
55 should_route 'PUT /issues/234/time_entries/22' => 'timelog#update', :issue_id => '234', :id => '22'
56 should_route 'DELETE /issues/234/time_entries/22' => 'timelog#destroy', :issue_id => '234', :id => '22'
57 47 end
58 48
59 49 def test_timelogs_report
60 50 should_route 'GET /time_entries/report' => 'timelog#report'
61 51 should_route 'GET /time_entries/report.csv' => 'timelog#report', :format => 'csv'
62 52
63 53 should_route 'GET /projects/foo/time_entries/report' => 'timelog#report', :project_id => 'foo'
64 54 should_route 'GET /projects/foo/time_entries/report.csv' => 'timelog#report', :project_id => 'foo', :format => 'csv'
65 55
66 56 should_route 'GET /issues/234/time_entries/report' => 'timelog#report', :issue_id => '234'
67 57 should_route 'GET /issues/234/time_entries/report.csv' => 'timelog#report', :issue_id => '234', :format => 'csv'
68 58 end
69 59
70 60 def test_timelogs_bulk_edit
71 61 should_route 'GET /time_entries/bulk_edit' => 'timelog#bulk_edit'
72 62 should_route 'POST /time_entries/bulk_update' => 'timelog#bulk_update'
73 63 should_route 'DELETE /time_entries/destroy' => 'timelog#destroy'
74 64 end
75 65 end
General Comments 0
You need to be logged in to leave comments. Login now