##// END OF EJS Templates
Removes routes for time entries nested under project/issues....
Jean-Philippe Lang -
r13060:2e9b28906db6
parent child
Show More
@@ -0,0 +1,45
1 # encoding: utf-8
2 #
3 # Redmine - project management software
4 # Copyright (C) 2006-2014 Jean-Philippe Lang
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
20 require File.expand_path('../../../test_helper', __FILE__)
21
22 class RoutesHelperTest < ActionView::TestCase
23 include Rails.application.routes.url_helpers
24
25 def test_time_entries_path
26 assert_equal '/projects/ecookbook/time_entries', _time_entries_path(Project.find(1), nil)
27 assert_equal '/issues/1/time_entries', _time_entries_path(Project.find(1), Issue.find(1))
28 assert_equal '/issues/1/time_entries', _time_entries_path(nil, Issue.find(1))
29 assert_equal '/time_entries', _time_entries_path(nil, nil)
30 end
31
32 def test_report_time_entries_path
33 assert_equal '/projects/ecookbook/time_entries/report', _report_time_entries_path(Project.find(1), nil)
34 assert_equal '/issues/1/time_entries/report', _report_time_entries_path(Project.find(1), Issue.find(1))
35 assert_equal '/issues/1/time_entries/report', _report_time_entries_path(nil, Issue.find(1))
36 assert_equal '/time_entries/report', _report_time_entries_path(nil, nil)
37 end
38
39 def test_new_time_entry_path
40 assert_equal '/projects/ecookbook/time_entries/new', _new_time_entry_path(Project.find(1), nil)
41 assert_equal '/issues/1/time_entries/new', _new_time_entry_path(Project.find(1), Issue.find(1))
42 assert_equal '/issues/1/time_entries/new', _new_time_entry_path(nil, Issue.find(1))
43 assert_equal '/time_entries/new', _new_time_entry_path(nil, nil)
44 end
45 end
@@ -1,39 +1,69
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2014 Jean-Philippe Lang
4 # Copyright (C) 2006-2014 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 module RoutesHelper
20 module RoutesHelper
21
21
22 # Returns the path to project issues or to the cross-project
22 # Returns the path to project issues or to the cross-project
23 # issue list if project is nil
23 # issue list if project is nil
24 def _project_issues_path(project, *args)
24 def _project_issues_path(project, *args)
25 if project
25 if project
26 project_issues_path(project, *args)
26 project_issues_path(project, *args)
27 else
27 else
28 issues_path(*args)
28 issues_path(*args)
29 end
29 end
30 end
30 end
31
31
32 def _project_calendar_path(project, *args)
32 def _project_calendar_path(project, *args)
33 project ? project_calendar_path(project, *args) : issues_calendar_path(*args)
33 project ? project_calendar_path(project, *args) : issues_calendar_path(*args)
34 end
34 end
35
35
36 def _project_gantt_path(project, *args)
36 def _project_gantt_path(project, *args)
37 project ? project_gantt_path(project, *args) : issues_gantt_path(*args)
37 project ? project_gantt_path(project, *args) : issues_gantt_path(*args)
38 end
38 end
39
40 def _time_entries_path(project, issue, *args)
41 if issue
42 issue_time_entries_path(issue, *args)
43 elsif project
44 project_time_entries_path(project, *args)
45 else
46 time_entries_path(*args)
47 end
48 end
49
50 def _report_time_entries_path(project, issue, *args)
51 if issue
52 report_issue_time_entries_path(issue, *args)
53 elsif project
54 report_project_time_entries_path(project, *args)
55 else
56 report_time_entries_path(*args)
57 end
58 end
59
60 def _new_time_entry_path(project, issue, *args)
61 if issue
62 new_issue_time_entry_path(issue, *args)
63 elsif project
64 new_project_time_entry_path(project, *args)
65 else
66 new_time_entry_path(*args)
67 end
68 end
39 end
69 end
@@ -1,36 +1,36
1 <div id="query_form_with_buttons" class="hide-when-print">
1 <div id="query_form_with_buttons" class="hide-when-print">
2 <div id="query_form_content">
2 <div id="query_form_content">
3 <fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
3 <fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
4 <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
4 <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
5 <div style="<%= @query.new_record? ? "" : "display: none;" %>">
5 <div style="<%= @query.new_record? ? "" : "display: none;" %>">
6 <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
6 <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
7 </div>
7 </div>
8 </fieldset>
8 </fieldset>
9 <fieldset class="collapsible collapsed">
9 <fieldset class="collapsible collapsed">
10 <legend onclick="toggleFieldset(this);"><%= l(:label_options) %></legend>
10 <legend onclick="toggleFieldset(this);"><%= l(:label_options) %></legend>
11 <div style="display: none;">
11 <div style="display: none;">
12 <table>
12 <table>
13 <tr>
13 <tr>
14 <td><%= l(:field_column_names) %></td>
14 <td><%= l(:field_column_names) %></td>
15 <td><%= render_query_columns_selection(@query) %></td>
15 <td><%= render_query_columns_selection(@query) %></td>
16 </tr>
16 </tr>
17 </table>
17 </table>
18 </div>
18 </div>
19 </fieldset>
19 </fieldset>
20 </div>
20 </div>
21
21
22 <p class="buttons">
22 <p class="buttons">
23 <%= link_to_function l(:button_apply), 'submit_query_form("query_form")', :class => 'icon icon-checked' %>
23 <%= link_to_function l(:button_apply), 'submit_query_form("query_form")', :class => 'icon icon-checked' %>
24 <%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %>
24 <%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %>
25 </p>
25 </p>
26 </div>
26 </div>
27
27
28 <div class="tabs hide-when-print">
28 <div class="tabs hide-when-print">
29 <% query_params = params.slice(:f, :op, :v, :sort) %>
29 <% query_params = params.slice(:f, :op, :v, :sort) %>
30 <ul>
30 <ul>
31 <li><%= link_to(l(:label_details), query_params.merge({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue }),
31 <li><%= link_to(l(:label_details), _time_entries_path(@project, @issue, query_params),
32 :class => (action_name == 'index' ? 'selected' : nil)) %></li>
32 :class => (action_name == 'index' ? 'selected' : nil)) %></li>
33 <li><%= link_to(l(:label_report), query_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project, :issue_id => @issue}),
33 <li><%= link_to(l(:label_report), _report_time_entries_path(@project, @issue, query_params),
34 :class => (action_name == 'report' ? 'selected' : nil)) %></li>
34 :class => (action_name == 'report' ? 'selected' : nil)) %></li>
35 </ul>
35 </ul>
36 </div>
36 </div>
@@ -1,48 +1,48
1 <div class="contextual">
1 <div class="contextual">
2 <%= link_to l(:button_log_time),
2 <%= link_to l(:button_log_time),
3 {:controller => 'timelog', :action => 'new', :project_id => @project, :issue_id => @issue},
3 _new_time_entry_path(@project, @issue),
4 :class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project, :global => true) %>
4 :class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project, :global => true) %>
5 </div>
5 </div>
6
6
7 <%= render_timelog_breadcrumb %>
7 <%= render_timelog_breadcrumb %>
8
8
9 <h2><%= l(:label_spent_time) %></h2>
9 <h2><%= l(:label_spent_time) %></h2>
10
10
11 <%= form_tag({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue}, :method => :get, :id => 'query_form') do %>
11 <%= form_tag(params.slice(:project_id, :issue_id), :method => :get, :id => 'query_form') do %>
12 <%= render :partial => 'date_range' %>
12 <%= render :partial => 'date_range' %>
13 <% end %>
13 <% end %>
14
14
15 <div class="total-hours">
15 <div class="total-hours">
16 <p><%= l(:label_total_time) %>: <%= html_hours(l_hours(@total_hours)) %></p>
16 <p><%= l(:label_total_time) %>: <%= html_hours(l_hours(@total_hours)) %></p>
17 </div>
17 </div>
18
18
19 <% unless @entries.empty? %>
19 <% unless @entries.empty? %>
20 <%= render :partial => 'list', :locals => { :entries => @entries }%>
20 <%= render :partial => 'list', :locals => { :entries => @entries }%>
21 <p class="pagination"><%= pagination_links_full @entry_pages, @entry_count %></p>
21 <p class="pagination"><%= pagination_links_full @entry_pages, @entry_count %></p>
22
22
23 <% other_formats_links do |f| %>
23 <% other_formats_links do |f| %>
24 <%= f.link_to 'Atom', :url => params.merge({:issue_id => @issue, :key => User.current.rss_key}) %>
24 <%= f.link_to 'Atom', :url => params.merge({:issue_id => @issue, :key => User.current.rss_key}) %>
25 <%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '330px'); return false;" %>
25 <%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '330px'); return false;" %>
26 <% end %>
26 <% end %>
27
27
28 <div id="csv-export-options" style="display:none;">
28 <div id="csv-export-options" style="display:none;">
29 <h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
29 <h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
30 <%= form_tag(params.slice(:project_id, :issue_id).merge(:format => 'csv', :page=>nil), :method => :get, :id => 'csv-export-form') do %>
30 <%= form_tag(params.slice(:project_id, :issue_id).merge(:format => 'csv', :page=>nil), :method => :get, :id => 'csv-export-form') do %>
31 <%= query_hidden_tags @query %>
31 <%= query_hidden_tags @query %>
32 <p>
32 <p>
33 <label><%= radio_button_tag 'columns', '', true %> <%= l(:description_selected_columns) %></label><br />
33 <label><%= radio_button_tag 'columns', '', true %> <%= l(:description_selected_columns) %></label><br />
34 <label><%= radio_button_tag 'columns', 'all' %> <%= l(:description_all_columns) %></label>
34 <label><%= radio_button_tag 'columns', 'all' %> <%= l(:description_all_columns) %></label>
35 </p>
35 </p>
36 <p class="buttons">
36 <p class="buttons">
37 <%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);" %>
37 <%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);" %>
38 <%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %>
38 <%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %>
39 </p>
39 </p>
40 <% end %>
40 <% end %>
41 </div>
41 </div>
42 <% end %>
42 <% end %>
43
43
44 <% html_title l(:label_spent_time), l(:label_details) %>
44 <% html_title l(:label_spent_time), l(:label_details) %>
45
45
46 <% content_for :header_tags do %>
46 <% content_for :header_tags do %>
47 <%= auto_discovery_link_tag(:atom, {:issue_id => @issue, :format => 'atom', :key => User.current.rss_key}, :title => l(:label_spent_time)) %>
47 <%= auto_discovery_link_tag(:atom, {:issue_id => @issue, :format => 'atom', :key => User.current.rss_key}, :title => l(:label_spent_time)) %>
48 <% end %>
48 <% end %>
@@ -1,74 +1,74
1 <div class="contextual">
1 <div class="contextual">
2 <%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'new', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time-add' %>
2 <%= link_to l(:button_log_time),
3 _new_time_entry_path(@project, @issue),
4 :class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project, :global => true) %>
3 </div>
5 </div>
4
6
5 <%= render_timelog_breadcrumb %>
7 <%= render_timelog_breadcrumb %>
6
8
7 <h2><%= l(:label_spent_time) %></h2>
9 <h2><%= l(:label_spent_time) %></h2>
8
10
9 <%= form_tag({:controller => 'timelog', :action => 'report',
11 <%= form_tag(params.slice(:project_id, :issue_id), :method => :get, :id => 'query_form') do %>
10 :project_id => @project, :issue_id => @issue},
11 :method => :get, :id => 'query_form') do %>
12 <% @report.criteria.each do |criterion| %>
12 <% @report.criteria.each do |criterion| %>
13 <%= hidden_field_tag 'criteria[]', criterion, :id => nil %>
13 <%= hidden_field_tag 'criteria[]', criterion, :id => nil %>
14 <% end %>
14 <% end %>
15 <%= render :partial => 'timelog/date_range' %>
15 <%= render :partial => 'timelog/date_range' %>
16
16
17 <p><label for='columns'><%= l(:label_details) %></label>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'],
17 <p><label for='columns'><%= l(:label_details) %></label>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'],
18 [l(:label_month), 'month'],
18 [l(:label_month), 'month'],
19 [l(:label_week), 'week'],
19 [l(:label_week), 'week'],
20 [l(:label_day_plural).titleize, 'day']], @report.columns),
20 [l(:label_day_plural).titleize, 'day']], @report.columns),
21 :onchange => "this.form.submit();" %>
21 :onchange => "this.form.submit();" %>
22
22
23 <label for='criterias'><%= l(:button_add) %></label>: <%= select_tag('criteria[]', options_for_select([[]] + (@report.available_criteria.keys - @report.criteria).collect{|k| [l_or_humanize(@report.available_criteria[k][:label]), k]}),
23 <label for='criterias'><%= l(:button_add) %></label>: <%= select_tag('criteria[]', options_for_select([[]] + (@report.available_criteria.keys - @report.criteria).collect{|k| [l_or_humanize(@report.available_criteria[k][:label]), k]}),
24 :onchange => "this.form.submit();",
24 :onchange => "this.form.submit();",
25 :style => 'width: 200px',
25 :style => 'width: 200px',
26 :id => nil,
26 :id => nil,
27 :disabled => (@report.criteria.length >= 3), :id => "criterias") %>
27 :disabled => (@report.criteria.length >= 3), :id => "criterias") %>
28 <%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue, :period_type => params[:period_type], :period => params[:period], :from => @from, :to => @to, :columns => @report.columns}, :class => 'icon icon-reload' %></p>
28 <%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue, :period_type => params[:period_type], :period => params[:period], :from => @from, :to => @to, :columns => @report.columns}, :class => 'icon icon-reload' %></p>
29 <% end %>
29 <% end %>
30
30
31 <% unless @report.criteria.empty? %>
31 <% unless @report.criteria.empty? %>
32 <div class="total-hours">
32 <div class="total-hours">
33 <p><%= l(:label_total_time) %>: <%= html_hours(l_hours(@report.total_hours)) %></p>
33 <p><%= l(:label_total_time) %>: <%= html_hours(l_hours(@report.total_hours)) %></p>
34 </div>
34 </div>
35
35
36 <% unless @report.hours.empty? %>
36 <% unless @report.hours.empty? %>
37 <div class="autoscroll">
37 <div class="autoscroll">
38 <table class="list" id="time-report">
38 <table class="list" id="time-report">
39 <thead>
39 <thead>
40 <tr>
40 <tr>
41 <% @report.criteria.each do |criteria| %>
41 <% @report.criteria.each do |criteria| %>
42 <th><%= l_or_humanize(@report.available_criteria[criteria][:label]) %></th>
42 <th><%= l_or_humanize(@report.available_criteria[criteria][:label]) %></th>
43 <% end %>
43 <% end %>
44 <% columns_width = (40 / (@report.periods.length+1)).to_i %>
44 <% columns_width = (40 / (@report.periods.length+1)).to_i %>
45 <% @report.periods.each do |period| %>
45 <% @report.periods.each do |period| %>
46 <th class="period" style="width:<%= columns_width %>%;"><%= period %></th>
46 <th class="period" style="width:<%= columns_width %>%;"><%= period %></th>
47 <% end %>
47 <% end %>
48 <th class="total" style="width:<%= columns_width %>%;"><%= l(:label_total_time) %></th>
48 <th class="total" style="width:<%= columns_width %>%;"><%= l(:label_total_time) %></th>
49 </tr>
49 </tr>
50 </thead>
50 </thead>
51 <tbody>
51 <tbody>
52 <%= render :partial => 'report_criteria', :locals => {:criterias => @report.criteria, :hours => @report.hours, :level => 0} %>
52 <%= render :partial => 'report_criteria', :locals => {:criterias => @report.criteria, :hours => @report.hours, :level => 0} %>
53 <tr class="total">
53 <tr class="total">
54 <td><%= l(:label_total_time) %></td>
54 <td><%= l(:label_total_time) %></td>
55 <%= ('<td></td>' * (@report.criteria.size - 1)).html_safe %>
55 <%= ('<td></td>' * (@report.criteria.size - 1)).html_safe %>
56 <% total = 0 -%>
56 <% total = 0 -%>
57 <% @report.periods.each do |period| -%>
57 <% @report.periods.each do |period| -%>
58 <% sum = sum_hours(select_hours(@report.hours, @report.columns, period.to_s)); total += sum -%>
58 <% sum = sum_hours(select_hours(@report.hours, @report.columns, period.to_s)); total += sum -%>
59 <td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
59 <td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
60 <% end -%>
60 <% end -%>
61 <td class="hours"><%= html_hours("%.2f" % total) if total > 0 %></td>
61 <td class="hours"><%= html_hours("%.2f" % total) if total > 0 %></td>
62 </tr>
62 </tr>
63 </tbody>
63 </tbody>
64 </table>
64 </table>
65 </div>
65 </div>
66
66
67 <% other_formats_links do |f| %>
67 <% other_formats_links do |f| %>
68 <%= f.link_to 'CSV', :url => params %>
68 <%= f.link_to 'CSV', :url => params %>
69 <% end %>
69 <% end %>
70 <% end %>
70 <% end %>
71 <% end %>
71 <% end %>
72
72
73 <% html_title l(:label_spent_time), l(:label_report) %>
73 <% html_title l(:label_spent_time), l(:label_report) %>
74
74
@@ -1,356 +1,350
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 RedmineApp::Application.routes.draw do
18 RedmineApp::Application.routes.draw do
19 root :to => 'welcome#index', :as => 'home'
19 root :to => 'welcome#index', :as => 'home'
20
20
21 match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post]
21 match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post]
22 match 'logout', :to => 'account#logout', :as => 'signout', :via => [:get, :post]
22 match 'logout', :to => 'account#logout', :as => 'signout', :via => [:get, :post]
23 match 'account/register', :to => 'account#register', :via => [:get, :post], :as => 'register'
23 match 'account/register', :to => 'account#register', :via => [:get, :post], :as => 'register'
24 match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post], :as => 'lost_password'
24 match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post], :as => 'lost_password'
25 match 'account/activate', :to => 'account#activate', :via => :get
25 match 'account/activate', :to => 'account#activate', :via => :get
26 get 'account/activation_email', :to => 'account#activation_email', :as => 'activation_email'
26 get 'account/activation_email', :to => 'account#activation_email', :as => 'activation_email'
27
27
28 match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put]
28 match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put]
29 match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put]
29 match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put]
30 match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put]
30 match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put]
31 match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put]
31 match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put]
32
32
33 match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
33 match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post
34 match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
34 match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post]
35
35
36 match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post], :as => 'new_board_message'
36 match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post], :as => 'new_board_message'
37 get 'boards/:board_id/topics/:id', :to => 'messages#show', :as => 'board_message'
37 get 'boards/:board_id/topics/:id', :to => 'messages#show', :as => 'board_message'
38 match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post]
38 match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post]
39 get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
39 get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
40
40
41 post 'boards/:board_id/topics/preview', :to => 'messages#preview', :as => 'preview_board_message'
41 post 'boards/:board_id/topics/preview', :to => 'messages#preview', :as => 'preview_board_message'
42 post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply'
42 post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply'
43 post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
43 post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit'
44 post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy'
44 post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy'
45
45
46 # Misc issue routes. TODO: move into resources
46 # Misc issue routes. TODO: move into resources
47 match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues'
47 match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues'
48 match '/issues/context_menu', :to => 'context_menus#issues', :as => 'issues_context_menu', :via => [:get, :post]
48 match '/issues/context_menu', :to => 'context_menus#issues', :as => 'issues_context_menu', :via => [:get, :post]
49 match '/issues/changes', :to => 'journals#index', :as => 'issue_changes', :via => :get
49 match '/issues/changes', :to => 'journals#index', :as => 'issue_changes', :via => :get
50 match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'
50 match '/issues/:id/quoted', :to => 'journals#new', :id => /\d+/, :via => :post, :as => 'quoted_issue'
51
51
52 match '/journals/diff/:id', :to => 'journals#diff', :id => /\d+/, :via => :get
52 match '/journals/diff/:id', :to => 'journals#diff', :id => /\d+/, :via => :get
53 match '/journals/edit/:id', :to => 'journals#edit', :id => /\d+/, :via => [:get, :post]
53 match '/journals/edit/:id', :to => 'journals#edit', :id => /\d+/, :via => [:get, :post]
54
54
55 get '/projects/:project_id/issues/gantt', :to => 'gantts#show', :as => 'project_gantt'
55 get '/projects/:project_id/issues/gantt', :to => 'gantts#show', :as => 'project_gantt'
56 get '/issues/gantt', :to => 'gantts#show'
56 get '/issues/gantt', :to => 'gantts#show'
57
57
58 get '/projects/:project_id/issues/calendar', :to => 'calendars#show', :as => 'project_calendar'
58 get '/projects/:project_id/issues/calendar', :to => 'calendars#show', :as => 'project_calendar'
59 get '/issues/calendar', :to => 'calendars#show'
59 get '/issues/calendar', :to => 'calendars#show'
60
60
61 get 'projects/:id/issues/report', :to => 'reports#issue_report', :as => 'project_issues_report'
61 get 'projects/:id/issues/report', :to => 'reports#issue_report', :as => 'project_issues_report'
62 get 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :as => 'project_issues_report_details'
62 get 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :as => 'project_issues_report_details'
63
63
64 match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
64 match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
65 match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
65 match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
66 match 'my/page', :controller => 'my', :action => 'page', :via => :get
66 match 'my/page', :controller => 'my', :action => 'page', :via => :get
67 match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
67 match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
68 match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post
68 match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post
69 match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post
69 match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post
70 match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post]
70 match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post]
71 match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get
71 match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get
72 match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
72 match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post
73 match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
73 match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post
74 match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
74 match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post
75
75
76 resources :users
76 resources :users
77 match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership'
77 match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership'
78 match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete
78 match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete
79 match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships'
79 match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships'
80
80
81 post 'watchers/watch', :to => 'watchers#watch', :as => 'watch'
81 post 'watchers/watch', :to => 'watchers#watch', :as => 'watch'
82 delete 'watchers/watch', :to => 'watchers#unwatch'
82 delete 'watchers/watch', :to => 'watchers#unwatch'
83 get 'watchers/new', :to => 'watchers#new'
83 get 'watchers/new', :to => 'watchers#new'
84 post 'watchers', :to => 'watchers#create'
84 post 'watchers', :to => 'watchers#create'
85 post 'watchers/append', :to => 'watchers#append'
85 post 'watchers/append', :to => 'watchers#append'
86 delete 'watchers', :to => 'watchers#destroy'
86 delete 'watchers', :to => 'watchers#destroy'
87 get 'watchers/autocomplete_for_user', :to => 'watchers#autocomplete_for_user'
87 get 'watchers/autocomplete_for_user', :to => 'watchers#autocomplete_for_user'
88 # Specific routes for issue watchers API
88 # Specific routes for issue watchers API
89 post 'issues/:object_id/watchers', :to => 'watchers#create', :object_type => 'issue'
89 post 'issues/:object_id/watchers', :to => 'watchers#create', :object_type => 'issue'
90 delete 'issues/:object_id/watchers/:user_id' => 'watchers#destroy', :object_type => 'issue'
90 delete 'issues/:object_id/watchers/:user_id' => 'watchers#destroy', :object_type => 'issue'
91
91
92 resources :projects do
92 resources :projects do
93 member do
93 member do
94 get 'settings(/:tab)', :action => 'settings', :as => 'settings'
94 get 'settings(/:tab)', :action => 'settings', :as => 'settings'
95 post 'modules'
95 post 'modules'
96 post 'archive'
96 post 'archive'
97 post 'unarchive'
97 post 'unarchive'
98 post 'close'
98 post 'close'
99 post 'reopen'
99 post 'reopen'
100 match 'copy', :via => [:get, :post]
100 match 'copy', :via => [:get, :post]
101 end
101 end
102
102
103 shallow do
103 shallow do
104 resources :memberships, :controller => 'members', :only => [:index, :show, :new, :create, :update, :destroy] do
104 resources :memberships, :controller => 'members', :only => [:index, :show, :new, :create, :update, :destroy] do
105 collection do
105 collection do
106 get 'autocomplete'
106 get 'autocomplete'
107 end
107 end
108 end
108 end
109 end
109 end
110
110
111 resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy]
111 resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy]
112
112
113 get 'issues/:copy_from/copy', :to => 'issues#new', :as => 'copy_issue'
113 get 'issues/:copy_from/copy', :to => 'issues#new', :as => 'copy_issue'
114 resources :issues, :only => [:index, :new, :create] do
114 resources :issues, :only => [:index, :new, :create]
115 resources :time_entries, :controller => 'timelog' do
116 collection do
117 get 'report'
118 end
119 end
120 end
121 # issue form update
115 # issue form update
122 match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :post], :as => 'issue_form'
116 match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :post], :as => 'issue_form'
123
117
124 resources :files, :only => [:index, :new, :create]
118 resources :files, :only => [:index, :new, :create]
125
119
126 resources :versions, :except => [:index, :show, :edit, :update, :destroy] do
120 resources :versions, :except => [:index, :show, :edit, :update, :destroy] do
127 collection do
121 collection do
128 put 'close_completed'
122 put 'close_completed'
129 end
123 end
130 end
124 end
131 get 'versions.:format', :to => 'versions#index'
125 get 'versions.:format', :to => 'versions#index'
132 get 'roadmap', :to => 'versions#index', :format => false
126 get 'roadmap', :to => 'versions#index', :format => false
133 get 'versions', :to => 'versions#index'
127 get 'versions', :to => 'versions#index'
134
128
135 resources :news, :except => [:show, :edit, :update, :destroy]
129 resources :news, :except => [:show, :edit, :update, :destroy]
136 resources :time_entries, :controller => 'timelog' do
130 resources :time_entries, :controller => 'timelog' do
137 get 'report', :on => :collection
131 get 'report', :on => :collection
138 end
132 end
139 resources :queries, :only => [:new, :create]
133 resources :queries, :only => [:new, :create]
140 shallow do
134 shallow do
141 resources :issue_categories
135 resources :issue_categories
142 end
136 end
143 resources :documents, :except => [:show, :edit, :update, :destroy]
137 resources :documents, :except => [:show, :edit, :update, :destroy]
144 resources :boards
138 resources :boards
145 shallow do
139 shallow do
146 resources :repositories, :except => [:index, :show] do
140 resources :repositories, :except => [:index, :show] do
147 member do
141 member do
148 match 'committers', :via => [:get, :post]
142 match 'committers', :via => [:get, :post]
149 end
143 end
150 end
144 end
151 end
145 end
152
146
153 match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
147 match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
154 resources :wiki, :except => [:index, :new, :create], :as => 'wiki_page' do
148 resources :wiki, :except => [:index, :new, :create], :as => 'wiki_page' do
155 member do
149 member do
156 get 'rename'
150 get 'rename'
157 post 'rename'
151 post 'rename'
158 get 'history'
152 get 'history'
159 get 'diff'
153 get 'diff'
160 match 'preview', :via => [:post, :put]
154 match 'preview', :via => [:post, :put]
161 post 'protect'
155 post 'protect'
162 post 'add_attachment'
156 post 'add_attachment'
163 end
157 end
164 collection do
158 collection do
165 get 'export'
159 get 'export'
166 get 'date_index'
160 get 'date_index'
167 end
161 end
168 end
162 end
169 match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
163 match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
170 get 'wiki/:id/:version', :to => 'wiki#show', :constraints => {:version => /\d+/}
164 get 'wiki/:id/:version', :to => 'wiki#show', :constraints => {:version => /\d+/}
171 delete 'wiki/:id/:version', :to => 'wiki#destroy_version'
165 delete 'wiki/:id/:version', :to => 'wiki#destroy_version'
172 get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
166 get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
173 get 'wiki/:id/:version/diff', :to => 'wiki#diff'
167 get 'wiki/:id/:version/diff', :to => 'wiki#diff'
174 end
168 end
175
169
176 resources :issues do
170 resources :issues do
177 collection do
171 collection do
178 match 'bulk_edit', :via => [:get, :post]
172 match 'bulk_edit', :via => [:get, :post]
179 post 'bulk_update'
173 post 'bulk_update'
180 end
174 end
181 resources :time_entries, :controller => 'timelog' do
175 resources :time_entries, :controller => 'timelog' do
182 collection do
176 collection do
183 get 'report'
177 get 'report'
184 end
178 end
185 end
179 end
186 shallow do
180 shallow do
187 resources :relations, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
181 resources :relations, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy]
188 end
182 end
189 end
183 end
190 match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
184 match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete
191
185
192 resources :queries, :except => [:show]
186 resources :queries, :except => [:show]
193
187
194 resources :news, :only => [:index, :show, :edit, :update, :destroy]
188 resources :news, :only => [:index, :show, :edit, :update, :destroy]
195 match '/news/:id/comments', :to => 'comments#create', :via => :post
189 match '/news/:id/comments', :to => 'comments#create', :via => :post
196 match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete
190 match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete
197
191
198 resources :versions, :only => [:show, :edit, :update, :destroy] do
192 resources :versions, :only => [:show, :edit, :update, :destroy] do
199 post 'status_by', :on => :member
193 post 'status_by', :on => :member
200 end
194 end
201
195
202 resources :documents, :only => [:show, :edit, :update, :destroy] do
196 resources :documents, :only => [:show, :edit, :update, :destroy] do
203 post 'add_attachment', :on => :member
197 post 'add_attachment', :on => :member
204 end
198 end
205
199
206 match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu, :via => [:get, :post]
200 match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu, :via => [:get, :post]
207
201
208 resources :time_entries, :controller => 'timelog', :except => :destroy do
202 resources :time_entries, :controller => 'timelog', :except => :destroy do
209 collection do
203 collection do
210 get 'report'
204 get 'report'
211 get 'bulk_edit'
205 get 'bulk_edit'
212 post 'bulk_update'
206 post 'bulk_update'
213 end
207 end
214 end
208 end
215 match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/
209 match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/
216 # TODO: delete /time_entries for bulk deletion
210 # TODO: delete /time_entries for bulk deletion
217 match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete
211 match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete
218
212
219 get 'projects/:id/activity', :to => 'activities#index'
213 get 'projects/:id/activity', :to => 'activities#index'
220 get 'projects/:id/activity.:format', :to => 'activities#index'
214 get 'projects/:id/activity.:format', :to => 'activities#index'
221 get 'activity', :to => 'activities#index'
215 get 'activity', :to => 'activities#index'
222
216
223 # repositories routes
217 # repositories routes
224 get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats'
218 get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats'
225 get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
219 get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph'
226
220
227 get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))',
221 get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))',
228 :to => 'repositories#changes'
222 :to => 'repositories#changes'
229
223
230 get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision'
224 get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision'
231 get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision'
225 get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision'
232 post 'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue'
226 post 'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue'
233 delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
227 delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
234 get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
228 get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions'
235 get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))',
229 get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))',
236 :controller => 'repositories',
230 :controller => 'repositories',
237 :format => false,
231 :format => false,
238 :constraints => {
232 :constraints => {
239 :action => /(browse|show|entry|raw|annotate|diff)/,
233 :action => /(browse|show|entry|raw|annotate|diff)/,
240 :rev => /[a-z0-9\.\-_]+/
234 :rev => /[a-z0-9\.\-_]+/
241 }
235 }
242
236
243 get 'projects/:id/repository/statistics', :to => 'repositories#stats'
237 get 'projects/:id/repository/statistics', :to => 'repositories#stats'
244 get 'projects/:id/repository/graph', :to => 'repositories#graph'
238 get 'projects/:id/repository/graph', :to => 'repositories#graph'
245
239
246 get 'projects/:id/repository/changes(/*path(.:ext))',
240 get 'projects/:id/repository/changes(/*path(.:ext))',
247 :to => 'repositories#changes'
241 :to => 'repositories#changes'
248
242
249 get 'projects/:id/repository/revisions', :to => 'repositories#revisions'
243 get 'projects/:id/repository/revisions', :to => 'repositories#revisions'
250 get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision'
244 get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision'
251 get 'projects/:id/repository/revision', :to => 'repositories#revision'
245 get 'projects/:id/repository/revision', :to => 'repositories#revision'
252 post 'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue'
246 post 'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue'
253 delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
247 delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue'
254 get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))',
248 get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))',
255 :controller => 'repositories',
249 :controller => 'repositories',
256 :format => false,
250 :format => false,
257 :constraints => {
251 :constraints => {
258 :action => /(browse|show|entry|raw|annotate|diff)/,
252 :action => /(browse|show|entry|raw|annotate|diff)/,
259 :rev => /[a-z0-9\.\-_]+/
253 :rev => /[a-z0-9\.\-_]+/
260 }
254 }
261 get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))',
255 get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))',
262 :controller => 'repositories',
256 :controller => 'repositories',
263 :action => /(browse|show|entry|raw|changes|annotate|diff)/
257 :action => /(browse|show|entry|raw|changes|annotate|diff)/
264 get 'projects/:id/repository/:action(/*path(.:ext))',
258 get 'projects/:id/repository/:action(/*path(.:ext))',
265 :controller => 'repositories',
259 :controller => 'repositories',
266 :action => /(browse|show|entry|raw|changes|annotate|diff)/
260 :action => /(browse|show|entry|raw|changes|annotate|diff)/
267
261
268 get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil
262 get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil
269 get 'projects/:id/repository', :to => 'repositories#show', :path => nil
263 get 'projects/:id/repository', :to => 'repositories#show', :path => nil
270
264
271 # additional routes for having the file name at the end of url
265 # additional routes for having the file name at the end of url
272 get 'attachments/:id/:filename', :to => 'attachments#show', :id => /\d+/, :filename => /.*/, :as => 'named_attachment'
266 get 'attachments/:id/:filename', :to => 'attachments#show', :id => /\d+/, :filename => /.*/, :as => 'named_attachment'
273 get 'attachments/download/:id/:filename', :to => 'attachments#download', :id => /\d+/, :filename => /.*/, :as => 'download_named_attachment'
267 get 'attachments/download/:id/:filename', :to => 'attachments#download', :id => /\d+/, :filename => /.*/, :as => 'download_named_attachment'
274 get 'attachments/download/:id', :to => 'attachments#download', :id => /\d+/
268 get 'attachments/download/:id', :to => 'attachments#download', :id => /\d+/
275 get 'attachments/thumbnail/:id(/:size)', :to => 'attachments#thumbnail', :id => /\d+/, :size => /\d+/, :as => 'thumbnail'
269 get 'attachments/thumbnail/:id(/:size)', :to => 'attachments#thumbnail', :id => /\d+/, :size => /\d+/, :as => 'thumbnail'
276 resources :attachments, :only => [:show, :destroy]
270 resources :attachments, :only => [:show, :destroy]
277
271
278 resources :groups do
272 resources :groups do
279 member do
273 member do
280 get 'autocomplete_for_user'
274 get 'autocomplete_for_user'
281 end
275 end
282 end
276 end
283
277
284 match 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :via => :post, :as => 'group_users'
278 match 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :via => :post, :as => 'group_users'
285 match 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :via => :delete, :as => 'group_user'
279 match 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :via => :delete, :as => 'group_user'
286 match 'groups/destroy_membership/:id', :controller => 'groups', :action => 'destroy_membership', :id => /\d+/, :via => :post
280 match 'groups/destroy_membership/:id', :controller => 'groups', :action => 'destroy_membership', :id => /\d+/, :via => :post
287 match 'groups/edit_membership/:id', :controller => 'groups', :action => 'edit_membership', :id => /\d+/, :via => :post
281 match 'groups/edit_membership/:id', :controller => 'groups', :action => 'edit_membership', :id => /\d+/, :via => :post
288
282
289 resources :trackers, :except => :show do
283 resources :trackers, :except => :show do
290 collection do
284 collection do
291 match 'fields', :via => [:get, :post]
285 match 'fields', :via => [:get, :post]
292 end
286 end
293 end
287 end
294 resources :issue_statuses, :except => :show do
288 resources :issue_statuses, :except => :show do
295 collection do
289 collection do
296 post 'update_issue_done_ratio'
290 post 'update_issue_done_ratio'
297 end
291 end
298 end
292 end
299 resources :custom_fields, :except => :show
293 resources :custom_fields, :except => :show
300 resources :roles do
294 resources :roles do
301 collection do
295 collection do
302 match 'permissions', :via => [:get, :post]
296 match 'permissions', :via => [:get, :post]
303 end
297 end
304 end
298 end
305 resources :enumerations, :except => :show
299 resources :enumerations, :except => :show
306 match 'enumerations/:type', :to => 'enumerations#index', :via => :get
300 match 'enumerations/:type', :to => 'enumerations#index', :via => :get
307
301
308 get 'projects/:id/search', :controller => 'search', :action => 'index'
302 get 'projects/:id/search', :controller => 'search', :action => 'index'
309 get 'search', :controller => 'search', :action => 'index'
303 get 'search', :controller => 'search', :action => 'index'
310
304
311 match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post
305 match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post
312
306
313 match 'admin', :controller => 'admin', :action => 'index', :via => :get
307 match 'admin', :controller => 'admin', :action => 'index', :via => :get
314 match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get
308 match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get
315 match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get
309 match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get
316 match 'admin/info', :controller => 'admin', :action => 'info', :via => :get
310 match 'admin/info', :controller => 'admin', :action => 'info', :via => :get
317 match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get
311 match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get
318 match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post
312 match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post
319
313
320 resources :auth_sources do
314 resources :auth_sources do
321 member do
315 member do
322 get 'test_connection', :as => 'try_connection'
316 get 'test_connection', :as => 'try_connection'
323 end
317 end
324 collection do
318 collection do
325 get 'autocomplete_for_new_user'
319 get 'autocomplete_for_new_user'
326 end
320 end
327 end
321 end
328
322
329 match 'workflows', :controller => 'workflows', :action => 'index', :via => :get
323 match 'workflows', :controller => 'workflows', :action => 'index', :via => :get
330 match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post]
324 match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post]
331 match 'workflows/permissions', :controller => 'workflows', :action => 'permissions', :via => [:get, :post]
325 match 'workflows/permissions', :controller => 'workflows', :action => 'permissions', :via => [:get, :post]
332 match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post]
326 match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post]
333 match 'settings', :controller => 'settings', :action => 'index', :via => :get
327 match 'settings', :controller => 'settings', :action => 'index', :via => :get
334 match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post]
328 match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post]
335 match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post], :as => 'plugin_settings'
329 match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post], :as => 'plugin_settings'
336
330
337 match 'sys/projects', :to => 'sys#projects', :via => :get
331 match 'sys/projects', :to => 'sys#projects', :via => :get
338 match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post
332 match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post
339 match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => [:get, :post]
333 match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => [:get, :post]
340
334
341 match 'uploads', :to => 'attachments#upload', :via => :post
335 match 'uploads', :to => 'attachments#upload', :via => :post
342
336
343 get 'robots.txt', :to => 'welcome#robots'
337 get 'robots.txt', :to => 'welcome#robots'
344
338
345 Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|
339 Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|
346 file = File.join(plugin_dir, "config/routes.rb")
340 file = File.join(plugin_dir, "config/routes.rb")
347 if File.exists?(file)
341 if File.exists?(file)
348 begin
342 begin
349 instance_eval File.read(file)
343 instance_eval File.read(file)
350 rescue Exception => e
344 rescue Exception => e
351 puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}."
345 puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}."
352 exit 1
346 exit 1
353 end
347 end
354 end
348 end
355 end
349 end
356 end
350 end
@@ -1,386 +1,386
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # Redmine - project management software
2 # Redmine - project management software
3 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 # Copyright (C) 2006-2014 Jean-Philippe Lang
4 #
4 #
5 # This program is free software; you can redistribute it and/or
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
8 # of the License, or (at your option) any later version.
9 #
9 #
10 # This program is distributed in the hope that it will be useful,
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
13 # GNU General Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
18
19 require File.expand_path('../../test_helper', __FILE__)
19 require File.expand_path('../../test_helper', __FILE__)
20
20
21 class TimeEntryReportsControllerTest < ActionController::TestCase
21 class TimeEntryReportsControllerTest < ActionController::TestCase
22 tests TimelogController
22 tests TimelogController
23
23
24 fixtures :projects, :enabled_modules, :roles, :members, :member_roles,
24 fixtures :projects, :enabled_modules, :roles, :members, :member_roles,
25 :issues, :time_entries, :users, :trackers, :enumerations,
25 :issues, :time_entries, :users, :trackers, :enumerations,
26 :issue_statuses, :custom_fields, :custom_values,
26 :issue_statuses, :custom_fields, :custom_values,
27 :projects_trackers, :custom_fields_trackers,
27 :projects_trackers, :custom_fields_trackers,
28 :custom_fields_projects
28 :custom_fields_projects
29
29
30 include Redmine::I18n
30 include Redmine::I18n
31
31
32 def setup
32 def setup
33 Setting.default_language = "en"
33 Setting.default_language = "en"
34 end
34 end
35
35
36 def test_report_at_project_level
36 def test_report_at_project_level
37 get :report, :project_id => 'ecookbook'
37 get :report, :project_id => 'ecookbook'
38 assert_response :success
38 assert_response :success
39 assert_template 'report'
39 assert_template 'report'
40 assert_tag :form,
40 assert_tag :form,
41 :attributes => {:action => "/projects/ecookbook/time_entries/report", :id => 'query_form'}
41 :attributes => {:action => "/projects/ecookbook/time_entries/report", :id => 'query_form'}
42 end
42 end
43
43
44 def test_report_all_projects
44 def test_report_all_projects
45 get :report
45 get :report
46 assert_response :success
46 assert_response :success
47 assert_template 'report'
47 assert_template 'report'
48 assert_tag :form,
48 assert_tag :form,
49 :attributes => {:action => "/time_entries/report", :id => 'query_form'}
49 :attributes => {:action => "/time_entries/report", :id => 'query_form'}
50 end
50 end
51
51
52 def test_report_all_projects_denied
52 def test_report_all_projects_denied
53 r = Role.anonymous
53 r = Role.anonymous
54 r.permissions.delete(:view_time_entries)
54 r.permissions.delete(:view_time_entries)
55 r.permissions_will_change!
55 r.permissions_will_change!
56 r.save
56 r.save
57 get :report
57 get :report
58 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Ftime_entries%2Freport'
58 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Ftime_entries%2Freport'
59 end
59 end
60
60
61 def test_report_all_projects_one_criteria
61 def test_report_all_projects_one_criteria
62 get :report, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']
62 get :report, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']
63 assert_response :success
63 assert_response :success
64 assert_template 'report'
64 assert_template 'report'
65 assert_not_nil assigns(:report)
65 assert_not_nil assigns(:report)
66 assert_equal "8.65", "%.2f" % assigns(:report).total_hours
66 assert_equal "8.65", "%.2f" % assigns(:report).total_hours
67 end
67 end
68
68
69 def test_report_all_time
69 def test_report_all_time
70 get :report, :project_id => 1, :criteria => ['project', 'issue']
70 get :report, :project_id => 1, :criteria => ['project', 'issue']
71 assert_response :success
71 assert_response :success
72 assert_template 'report'
72 assert_template 'report'
73 assert_not_nil assigns(:report)
73 assert_not_nil assigns(:report)
74 assert_equal "162.90", "%.2f" % assigns(:report).total_hours
74 assert_equal "162.90", "%.2f" % assigns(:report).total_hours
75 end
75 end
76
76
77 def test_report_all_time_by_day
77 def test_report_all_time_by_day
78 get :report, :project_id => 1, :criteria => ['project', 'issue'], :columns => 'day'
78 get :report, :project_id => 1, :criteria => ['project', 'issue'], :columns => 'day'
79 assert_response :success
79 assert_response :success
80 assert_template 'report'
80 assert_template 'report'
81 assert_not_nil assigns(:report)
81 assert_not_nil assigns(:report)
82 assert_equal "162.90", "%.2f" % assigns(:report).total_hours
82 assert_equal "162.90", "%.2f" % assigns(:report).total_hours
83 assert_tag :tag => 'th', :content => '2007-03-12'
83 assert_tag :tag => 'th', :content => '2007-03-12'
84 end
84 end
85
85
86 def test_report_one_criteria
86 def test_report_one_criteria
87 get :report, :project_id => 1, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']
87 get :report, :project_id => 1, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']
88 assert_response :success
88 assert_response :success
89 assert_template 'report'
89 assert_template 'report'
90 assert_not_nil assigns(:report)
90 assert_not_nil assigns(:report)
91 assert_equal "8.65", "%.2f" % assigns(:report).total_hours
91 assert_equal "8.65", "%.2f" % assigns(:report).total_hours
92 end
92 end
93
93
94 def test_report_two_criteria
94 def test_report_two_criteria
95 get :report, :project_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]
95 get :report, :project_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]
96 assert_response :success
96 assert_response :success
97 assert_template 'report'
97 assert_template 'report'
98 assert_not_nil assigns(:report)
98 assert_not_nil assigns(:report)
99 assert_equal "162.90", "%.2f" % assigns(:report).total_hours
99 assert_equal "162.90", "%.2f" % assigns(:report).total_hours
100 end
100 end
101
101
102 def test_report_custom_field_criteria_with_multiple_values_on_single_value_custom_field_should_not_fail
102 def test_report_custom_field_criteria_with_multiple_values_on_single_value_custom_field_should_not_fail
103 field = TimeEntryCustomField.create!(:name => 'multi', :field_format => 'list', :possible_values => ['value1', 'value2'])
103 field = TimeEntryCustomField.create!(:name => 'multi', :field_format => 'list', :possible_values => ['value1', 'value2'])
104 entry = TimeEntry.create!(:project => Project.find(1), :hours => 1, :activity_id => 10, :user => User.find(2), :spent_on => Date.today)
104 entry = TimeEntry.create!(:project => Project.find(1), :hours => 1, :activity_id => 10, :user => User.find(2), :spent_on => Date.today)
105 CustomValue.create!(:customized => entry, :custom_field => field, :value => 'value1')
105 CustomValue.create!(:customized => entry, :custom_field => field, :value => 'value1')
106 CustomValue.create!(:customized => entry, :custom_field => field, :value => 'value2')
106 CustomValue.create!(:customized => entry, :custom_field => field, :value => 'value2')
107
107
108 get :report, :project_id => 1, :columns => 'day', :criteria => ["cf_#{field.id}"]
108 get :report, :project_id => 1, :columns => 'day', :criteria => ["cf_#{field.id}"]
109 assert_response :success
109 assert_response :success
110 end
110 end
111
111
112 def test_report_multiple_values_custom_fields_should_not_be_proposed
112 def test_report_multiple_values_custom_fields_should_not_be_proposed
113 TimeEntryCustomField.create!(:name => 'Single', :field_format => 'list', :possible_values => ['value1', 'value2'])
113 TimeEntryCustomField.create!(:name => 'Single', :field_format => 'list', :possible_values => ['value1', 'value2'])
114 TimeEntryCustomField.create!(:name => 'Multi', :field_format => 'list', :multiple => true, :possible_values => ['value1', 'value2'])
114 TimeEntryCustomField.create!(:name => 'Multi', :field_format => 'list', :multiple => true, :possible_values => ['value1', 'value2'])
115
115
116 get :report, :project_id => 1
116 get :report, :project_id => 1
117 assert_response :success
117 assert_response :success
118 assert_select 'select[name=?]', 'criteria[]' do
118 assert_select 'select[name=?]', 'criteria[]' do
119 assert_select 'option', :text => 'Single'
119 assert_select 'option', :text => 'Single'
120 assert_select 'option', :text => 'Multi', :count => 0
120 assert_select 'option', :text => 'Multi', :count => 0
121 end
121 end
122 end
122 end
123
123
124 def test_report_one_day
124 def test_report_one_day
125 get :report, :project_id => 1, :columns => 'day', :from => "2007-03-23", :to => "2007-03-23", :criteria => ["user", "activity"]
125 get :report, :project_id => 1, :columns => 'day', :from => "2007-03-23", :to => "2007-03-23", :criteria => ["user", "activity"]
126 assert_response :success
126 assert_response :success
127 assert_template 'report'
127 assert_template 'report'
128 assert_not_nil assigns(:report)
128 assert_not_nil assigns(:report)
129 assert_equal "4.25", "%.2f" % assigns(:report).total_hours
129 assert_equal "4.25", "%.2f" % assigns(:report).total_hours
130 end
130 end
131
131
132 def test_report_at_issue_level
132 def test_report_at_issue_level
133 get :report, :project_id => 1, :issue_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]
133 get :report, :issue_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]
134 assert_response :success
134 assert_response :success
135 assert_template 'report'
135 assert_template 'report'
136 assert_not_nil assigns(:report)
136 assert_not_nil assigns(:report)
137 assert_equal "154.25", "%.2f" % assigns(:report).total_hours
137 assert_equal "154.25", "%.2f" % assigns(:report).total_hours
138 assert_tag :form,
138 assert_tag :form,
139 :attributes => {:action => "/projects/ecookbook/issues/1/time_entries/report", :id => 'query_form'}
139 :attributes => {:action => "/issues/1/time_entries/report", :id => 'query_form'}
140 end
140 end
141
141
142 def test_report_by_week_should_use_commercial_year
142 def test_report_by_week_should_use_commercial_year
143 TimeEntry.delete_all
143 TimeEntry.delete_all
144 TimeEntry.generate!(:hours => '2', :spent_on => '2009-12-25') # 2009-52
144 TimeEntry.generate!(:hours => '2', :spent_on => '2009-12-25') # 2009-52
145 TimeEntry.generate!(:hours => '4', :spent_on => '2009-12-31') # 2009-53
145 TimeEntry.generate!(:hours => '4', :spent_on => '2009-12-31') # 2009-53
146 TimeEntry.generate!(:hours => '8', :spent_on => '2010-01-01') # 2009-53
146 TimeEntry.generate!(:hours => '8', :spent_on => '2010-01-01') # 2009-53
147 TimeEntry.generate!(:hours => '16', :spent_on => '2010-01-05') # 2010-1
147 TimeEntry.generate!(:hours => '16', :spent_on => '2010-01-05') # 2010-1
148
148
149 get :report, :columns => 'week', :from => "2009-12-25", :to => "2010-01-05", :criteria => ["project"]
149 get :report, :columns => 'week', :from => "2009-12-25", :to => "2010-01-05", :criteria => ["project"]
150 assert_response :success
150 assert_response :success
151
151
152 assert_select '#time-report thead tr' do
152 assert_select '#time-report thead tr' do
153 assert_select 'th:nth-child(1)', :text => 'Project'
153 assert_select 'th:nth-child(1)', :text => 'Project'
154 assert_select 'th:nth-child(2)', :text => '2009-52'
154 assert_select 'th:nth-child(2)', :text => '2009-52'
155 assert_select 'th:nth-child(3)', :text => '2009-53'
155 assert_select 'th:nth-child(3)', :text => '2009-53'
156 assert_select 'th:nth-child(4)', :text => '2010-1'
156 assert_select 'th:nth-child(4)', :text => '2010-1'
157 assert_select 'th:nth-child(5)', :text => 'Total time'
157 assert_select 'th:nth-child(5)', :text => 'Total time'
158 end
158 end
159 assert_select '#time-report tbody tr' do
159 assert_select '#time-report tbody tr' do
160 assert_select 'td:nth-child(1)', :text => 'eCookbook'
160 assert_select 'td:nth-child(1)', :text => 'eCookbook'
161 assert_select 'td:nth-child(2)', :text => '2.00'
161 assert_select 'td:nth-child(2)', :text => '2.00'
162 assert_select 'td:nth-child(3)', :text => '12.00'
162 assert_select 'td:nth-child(3)', :text => '12.00'
163 assert_select 'td:nth-child(4)', :text => '16.00'
163 assert_select 'td:nth-child(4)', :text => '16.00'
164 assert_select 'td:nth-child(5)', :text => '30.00' # Total
164 assert_select 'td:nth-child(5)', :text => '30.00' # Total
165 end
165 end
166 end
166 end
167
167
168 def test_report_should_propose_association_custom_fields
168 def test_report_should_propose_association_custom_fields
169 get :report
169 get :report
170 assert_response :success
170 assert_response :success
171 assert_template 'report'
171 assert_template 'report'
172
172
173 assert_select 'select[name=?]', 'criteria[]' do
173 assert_select 'select[name=?]', 'criteria[]' do
174 assert_select 'option[value=cf_1]', {:text => 'Database'}, 'Issue custom field not found'
174 assert_select 'option[value=cf_1]', {:text => 'Database'}, 'Issue custom field not found'
175 assert_select 'option[value=cf_3]', {:text => 'Development status'}, 'Project custom field not found'
175 assert_select 'option[value=cf_3]', {:text => 'Development status'}, 'Project custom field not found'
176 assert_select 'option[value=cf_7]', {:text => 'Billable'}, 'TimeEntryActivity custom field not found'
176 assert_select 'option[value=cf_7]', {:text => 'Billable'}, 'TimeEntryActivity custom field not found'
177 end
177 end
178 end
178 end
179
179
180 def test_report_with_association_custom_fields
180 def test_report_with_association_custom_fields
181 get :report, :criteria => ['cf_1', 'cf_3', 'cf_7']
181 get :report, :criteria => ['cf_1', 'cf_3', 'cf_7']
182 assert_response :success
182 assert_response :success
183 assert_template 'report'
183 assert_template 'report'
184 assert_not_nil assigns(:report)
184 assert_not_nil assigns(:report)
185 assert_equal 3, assigns(:report).criteria.size
185 assert_equal 3, assigns(:report).criteria.size
186 assert_equal "162.90", "%.2f" % assigns(:report).total_hours
186 assert_equal "162.90", "%.2f" % assigns(:report).total_hours
187
187
188 # Custom fields columns
188 # Custom fields columns
189 assert_select 'th', :text => 'Database'
189 assert_select 'th', :text => 'Database'
190 assert_select 'th', :text => 'Development status'
190 assert_select 'th', :text => 'Development status'
191 assert_select 'th', :text => 'Billable'
191 assert_select 'th', :text => 'Billable'
192
192
193 # Custom field row
193 # Custom field row
194 assert_select 'tr' do
194 assert_select 'tr' do
195 assert_select 'td', :text => 'MySQL'
195 assert_select 'td', :text => 'MySQL'
196 assert_select 'td.hours', :text => '1.00'
196 assert_select 'td.hours', :text => '1.00'
197 end
197 end
198 end
198 end
199
199
200 def test_report_one_criteria_no_result
200 def test_report_one_criteria_no_result
201 get :report, :project_id => 1, :columns => 'week', :from => "1998-04-01", :to => "1998-04-30", :criteria => ['project']
201 get :report, :project_id => 1, :columns => 'week', :from => "1998-04-01", :to => "1998-04-30", :criteria => ['project']
202 assert_response :success
202 assert_response :success
203 assert_template 'report'
203 assert_template 'report'
204 assert_not_nil assigns(:report)
204 assert_not_nil assigns(:report)
205 assert_equal "0.00", "%.2f" % assigns(:report).total_hours
205 assert_equal "0.00", "%.2f" % assigns(:report).total_hours
206 end
206 end
207
207
208 def test_report_status_criterion
208 def test_report_status_criterion
209 get :report, :project_id => 1, :criteria => ['status']
209 get :report, :project_id => 1, :criteria => ['status']
210 assert_response :success
210 assert_response :success
211 assert_template 'report'
211 assert_template 'report'
212 assert_tag :tag => 'th', :content => 'Status'
212 assert_tag :tag => 'th', :content => 'Status'
213 assert_tag :tag => 'td', :content => 'New'
213 assert_tag :tag => 'td', :content => 'New'
214 end
214 end
215
215
216 def test_report_all_projects_csv_export
216 def test_report_all_projects_csv_export
217 get :report, :columns => 'month', :from => "2007-01-01", :to => "2007-06-30",
217 get :report, :columns => 'month', :from => "2007-01-01", :to => "2007-06-30",
218 :criteria => ["project", "user", "activity"], :format => "csv"
218 :criteria => ["project", "user", "activity"], :format => "csv"
219 assert_response :success
219 assert_response :success
220 assert_equal 'text/csv; header=present', @response.content_type
220 assert_equal 'text/csv; header=present', @response.content_type
221 lines = @response.body.chomp.split("\n")
221 lines = @response.body.chomp.split("\n")
222 # Headers
222 # Headers
223 assert_equal 'Project,User,Activity,2007-3,2007-4,Total time', lines.first
223 assert_equal 'Project,User,Activity,2007-3,2007-4,Total time', lines.first
224 # Total row
224 # Total row
225 assert_equal 'Total time,"","",154.25,8.65,162.90', lines.last
225 assert_equal 'Total time,"","",154.25,8.65,162.90', lines.last
226 end
226 end
227
227
228 def test_report_csv_export
228 def test_report_csv_export
229 get :report, :project_id => 1, :columns => 'month',
229 get :report, :project_id => 1, :columns => 'month',
230 :from => "2007-01-01", :to => "2007-06-30",
230 :from => "2007-01-01", :to => "2007-06-30",
231 :criteria => ["project", "user", "activity"], :format => "csv"
231 :criteria => ["project", "user", "activity"], :format => "csv"
232 assert_response :success
232 assert_response :success
233 assert_equal 'text/csv; header=present', @response.content_type
233 assert_equal 'text/csv; header=present', @response.content_type
234 lines = @response.body.chomp.split("\n")
234 lines = @response.body.chomp.split("\n")
235 # Headers
235 # Headers
236 assert_equal 'Project,User,Activity,2007-3,2007-4,Total time', lines.first
236 assert_equal 'Project,User,Activity,2007-3,2007-4,Total time', lines.first
237 # Total row
237 # Total row
238 assert_equal 'Total time,"","",154.25,8.65,162.90', lines.last
238 assert_equal 'Total time,"","",154.25,8.65,162.90', lines.last
239 end
239 end
240
240
241 def test_csv_big_5
241 def test_csv_big_5
242 Setting.default_language = "zh-TW"
242 Setting.default_language = "zh-TW"
243 str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88"
243 str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88"
244 str_big5 = "\xa4@\xa4\xeb"
244 str_big5 = "\xa4@\xa4\xeb"
245 if str_utf8.respond_to?(:force_encoding)
245 if str_utf8.respond_to?(:force_encoding)
246 str_utf8.force_encoding('UTF-8')
246 str_utf8.force_encoding('UTF-8')
247 str_big5.force_encoding('Big5')
247 str_big5.force_encoding('Big5')
248 end
248 end
249 user = User.find_by_id(3)
249 user = User.find_by_id(3)
250 user.firstname = str_utf8
250 user.firstname = str_utf8
251 user.lastname = "test-lastname"
251 user.lastname = "test-lastname"
252 assert user.save
252 assert user.save
253 comments = "test_csv_big_5"
253 comments = "test_csv_big_5"
254 te1 = TimeEntry.create(:spent_on => '2011-11-11',
254 te1 = TimeEntry.create(:spent_on => '2011-11-11',
255 :hours => 7.3,
255 :hours => 7.3,
256 :project => Project.find(1),
256 :project => Project.find(1),
257 :user => user,
257 :user => user,
258 :activity => TimeEntryActivity.find_by_name('Design'),
258 :activity => TimeEntryActivity.find_by_name('Design'),
259 :comments => comments)
259 :comments => comments)
260
260
261 te2 = TimeEntry.find_by_comments(comments)
261 te2 = TimeEntry.find_by_comments(comments)
262 assert_not_nil te2
262 assert_not_nil te2
263 assert_equal 7.3, te2.hours
263 assert_equal 7.3, te2.hours
264 assert_equal 3, te2.user_id
264 assert_equal 3, te2.user_id
265
265
266 get :report, :project_id => 1, :columns => 'day',
266 get :report, :project_id => 1, :columns => 'day',
267 :from => "2011-11-11", :to => "2011-11-11",
267 :from => "2011-11-11", :to => "2011-11-11",
268 :criteria => ["user"], :format => "csv"
268 :criteria => ["user"], :format => "csv"
269 assert_response :success
269 assert_response :success
270 assert_equal 'text/csv; header=present', @response.content_type
270 assert_equal 'text/csv; header=present', @response.content_type
271 lines = @response.body.chomp.split("\n")
271 lines = @response.body.chomp.split("\n")
272 # Headers
272 # Headers
273 s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp"
273 s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp"
274 s2 = "\xa4u\xae\xc9\xc1`\xadp"
274 s2 = "\xa4u\xae\xc9\xc1`\xadp"
275 if s1.respond_to?(:force_encoding)
275 if s1.respond_to?(:force_encoding)
276 s1.force_encoding('Big5')
276 s1.force_encoding('Big5')
277 s2.force_encoding('Big5')
277 s2.force_encoding('Big5')
278 end
278 end
279 assert_equal s1, lines.first
279 assert_equal s1, lines.first
280 # Total row
280 # Total row
281 assert_equal "#{str_big5} #{user.lastname},7.30,7.30", lines[1]
281 assert_equal "#{str_big5} #{user.lastname},7.30,7.30", lines[1]
282 assert_equal "#{s2},7.30,7.30", lines[2]
282 assert_equal "#{s2},7.30,7.30", lines[2]
283
283
284 str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
284 str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
285 if str_tw.respond_to?(:force_encoding)
285 if str_tw.respond_to?(:force_encoding)
286 str_tw.force_encoding('UTF-8')
286 str_tw.force_encoding('UTF-8')
287 end
287 end
288 assert_equal str_tw, l(:general_lang_name)
288 assert_equal str_tw, l(:general_lang_name)
289 assert_equal 'Big5', l(:general_csv_encoding)
289 assert_equal 'Big5', l(:general_csv_encoding)
290 assert_equal ',', l(:general_csv_separator)
290 assert_equal ',', l(:general_csv_separator)
291 assert_equal '.', l(:general_csv_decimal_separator)
291 assert_equal '.', l(:general_csv_decimal_separator)
292 end
292 end
293
293
294 def test_csv_cannot_convert_should_be_replaced_big_5
294 def test_csv_cannot_convert_should_be_replaced_big_5
295 Setting.default_language = "zh-TW"
295 Setting.default_language = "zh-TW"
296 str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85"
296 str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85"
297 if str_utf8.respond_to?(:force_encoding)
297 if str_utf8.respond_to?(:force_encoding)
298 str_utf8.force_encoding('UTF-8')
298 str_utf8.force_encoding('UTF-8')
299 end
299 end
300 user = User.find_by_id(3)
300 user = User.find_by_id(3)
301 user.firstname = str_utf8
301 user.firstname = str_utf8
302 user.lastname = "test-lastname"
302 user.lastname = "test-lastname"
303 assert user.save
303 assert user.save
304 comments = "test_replaced"
304 comments = "test_replaced"
305 te1 = TimeEntry.create(:spent_on => '2011-11-11',
305 te1 = TimeEntry.create(:spent_on => '2011-11-11',
306 :hours => 7.3,
306 :hours => 7.3,
307 :project => Project.find(1),
307 :project => Project.find(1),
308 :user => user,
308 :user => user,
309 :activity => TimeEntryActivity.find_by_name('Design'),
309 :activity => TimeEntryActivity.find_by_name('Design'),
310 :comments => comments)
310 :comments => comments)
311
311
312 te2 = TimeEntry.find_by_comments(comments)
312 te2 = TimeEntry.find_by_comments(comments)
313 assert_not_nil te2
313 assert_not_nil te2
314 assert_equal 7.3, te2.hours
314 assert_equal 7.3, te2.hours
315 assert_equal 3, te2.user_id
315 assert_equal 3, te2.user_id
316
316
317 get :report, :project_id => 1, :columns => 'day',
317 get :report, :project_id => 1, :columns => 'day',
318 :from => "2011-11-11", :to => "2011-11-11",
318 :from => "2011-11-11", :to => "2011-11-11",
319 :criteria => ["user"], :format => "csv"
319 :criteria => ["user"], :format => "csv"
320 assert_response :success
320 assert_response :success
321 assert_equal 'text/csv; header=present', @response.content_type
321 assert_equal 'text/csv; header=present', @response.content_type
322 lines = @response.body.chomp.split("\n")
322 lines = @response.body.chomp.split("\n")
323 # Headers
323 # Headers
324 s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp"
324 s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp"
325 if s1.respond_to?(:force_encoding)
325 if s1.respond_to?(:force_encoding)
326 s1.force_encoding('Big5')
326 s1.force_encoding('Big5')
327 end
327 end
328 assert_equal s1, lines.first
328 assert_equal s1, lines.first
329 # Total row
329 # Total row
330 s2 = ""
330 s2 = ""
331 if s2.respond_to?(:force_encoding)
331 if s2.respond_to?(:force_encoding)
332 s2 = "\xa5H?"
332 s2 = "\xa5H?"
333 s2.force_encoding('Big5')
333 s2.force_encoding('Big5')
334 elsif RUBY_PLATFORM == 'java'
334 elsif RUBY_PLATFORM == 'java'
335 s2 = "??"
335 s2 = "??"
336 else
336 else
337 s2 = "\xa5H???"
337 s2 = "\xa5H???"
338 end
338 end
339 assert_equal "#{s2} #{user.lastname},7.30,7.30", lines[1]
339 assert_equal "#{s2} #{user.lastname},7.30,7.30", lines[1]
340 end
340 end
341
341
342 def test_csv_fr
342 def test_csv_fr
343 with_settings :default_language => "fr" do
343 with_settings :default_language => "fr" do
344 str1 = "test_csv_fr"
344 str1 = "test_csv_fr"
345 user = User.find_by_id(3)
345 user = User.find_by_id(3)
346 te1 = TimeEntry.create(:spent_on => '2011-11-11',
346 te1 = TimeEntry.create(:spent_on => '2011-11-11',
347 :hours => 7.3,
347 :hours => 7.3,
348 :project => Project.find(1),
348 :project => Project.find(1),
349 :user => user,
349 :user => user,
350 :activity => TimeEntryActivity.find_by_name('Design'),
350 :activity => TimeEntryActivity.find_by_name('Design'),
351 :comments => str1)
351 :comments => str1)
352
352
353 te2 = TimeEntry.find_by_comments(str1)
353 te2 = TimeEntry.find_by_comments(str1)
354 assert_not_nil te2
354 assert_not_nil te2
355 assert_equal 7.3, te2.hours
355 assert_equal 7.3, te2.hours
356 assert_equal 3, te2.user_id
356 assert_equal 3, te2.user_id
357
357
358 get :report, :project_id => 1, :columns => 'day',
358 get :report, :project_id => 1, :columns => 'day',
359 :from => "2011-11-11", :to => "2011-11-11",
359 :from => "2011-11-11", :to => "2011-11-11",
360 :criteria => ["user"], :format => "csv"
360 :criteria => ["user"], :format => "csv"
361 assert_response :success
361 assert_response :success
362 assert_equal 'text/csv; header=present', @response.content_type
362 assert_equal 'text/csv; header=present', @response.content_type
363 lines = @response.body.chomp.split("\n")
363 lines = @response.body.chomp.split("\n")
364 # Headers
364 # Headers
365 s1 = "Utilisateur;2011-11-11;Temps total"
365 s1 = "Utilisateur;2011-11-11;Temps total"
366 s2 = "Temps total"
366 s2 = "Temps total"
367 if s1.respond_to?(:force_encoding)
367 if s1.respond_to?(:force_encoding)
368 s1.force_encoding('ISO-8859-1')
368 s1.force_encoding('ISO-8859-1')
369 s2.force_encoding('ISO-8859-1')
369 s2.force_encoding('ISO-8859-1')
370 end
370 end
371 assert_equal s1, lines.first
371 assert_equal s1, lines.first
372 # Total row
372 # Total row
373 assert_equal "#{user.firstname} #{user.lastname};7,30;7,30", lines[1]
373 assert_equal "#{user.firstname} #{user.lastname};7,30;7,30", lines[1]
374 assert_equal "#{s2};7,30;7,30", lines[2]
374 assert_equal "#{s2};7,30;7,30", lines[2]
375
375
376 str_fr = "Fran\xc3\xa7ais"
376 str_fr = "Fran\xc3\xa7ais"
377 if str_fr.respond_to?(:force_encoding)
377 if str_fr.respond_to?(:force_encoding)
378 str_fr.force_encoding('UTF-8')
378 str_fr.force_encoding('UTF-8')
379 end
379 end
380 assert_equal str_fr, l(:general_lang_name)
380 assert_equal str_fr, l(:general_lang_name)
381 assert_equal 'ISO-8859-1', l(:general_csv_encoding)
381 assert_equal 'ISO-8859-1', l(:general_csv_encoding)
382 assert_equal ';', l(:general_csv_separator)
382 assert_equal ';', l(:general_csv_separator)
383 assert_equal ',', l(:general_csv_decimal_separator)
383 assert_equal ',', l(:general_csv_decimal_separator)
384 end
384 end
385 end
385 end
386 end
386 end
@@ -1,717 +1,717
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # Redmine - project management software
2 # Redmine - project management software
3 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 # Copyright (C) 2006-2014 Jean-Philippe Lang
4 #
4 #
5 # This program is free software; you can redistribute it and/or
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
8 # of the License, or (at your option) any later version.
9 #
9 #
10 # This program is distributed in the hope that it will be useful,
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
13 # GNU General Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
18
19 require File.expand_path('../../test_helper', __FILE__)
19 require File.expand_path('../../test_helper', __FILE__)
20
20
21 class TimelogControllerTest < ActionController::TestCase
21 class TimelogControllerTest < ActionController::TestCase
22 fixtures :projects, :enabled_modules, :roles, :members,
22 fixtures :projects, :enabled_modules, :roles, :members,
23 :member_roles, :issues, :time_entries, :users,
23 :member_roles, :issues, :time_entries, :users,
24 :trackers, :enumerations, :issue_statuses,
24 :trackers, :enumerations, :issue_statuses,
25 :custom_fields, :custom_values,
25 :custom_fields, :custom_values,
26 :projects_trackers, :custom_fields_trackers,
26 :projects_trackers, :custom_fields_trackers,
27 :custom_fields_projects
27 :custom_fields_projects
28
28
29 include Redmine::I18n
29 include Redmine::I18n
30
30
31 def test_new
31 def test_new
32 @request.session[:user_id] = 3
32 @request.session[:user_id] = 3
33 get :new
33 get :new
34 assert_response :success
34 assert_response :success
35 assert_template 'new'
35 assert_template 'new'
36 assert_select 'input[name=?][type=hidden]', 'project_id', 0
36 assert_select 'input[name=?][type=hidden]', 'project_id', 0
37 assert_select 'input[name=?][type=hidden]', 'issue_id', 0
37 assert_select 'input[name=?][type=hidden]', 'issue_id', 0
38 assert_select 'select[name=?]', 'time_entry[project_id]' do
38 assert_select 'select[name=?]', 'time_entry[project_id]' do
39 # blank option for project
39 # blank option for project
40 assert_select 'option[value=]'
40 assert_select 'option[value=]'
41 end
41 end
42 end
42 end
43
43
44 def test_new_with_project_id
44 def test_new_with_project_id
45 @request.session[:user_id] = 3
45 @request.session[:user_id] = 3
46 get :new, :project_id => 1
46 get :new, :project_id => 1
47 assert_response :success
47 assert_response :success
48 assert_template 'new'
48 assert_template 'new'
49 assert_select 'input[name=?][type=hidden]', 'project_id'
49 assert_select 'input[name=?][type=hidden]', 'project_id'
50 assert_select 'input[name=?][type=hidden]', 'issue_id', 0
50 assert_select 'input[name=?][type=hidden]', 'issue_id', 0
51 assert_select 'select[name=?]', 'time_entry[project_id]', 0
51 assert_select 'select[name=?]', 'time_entry[project_id]', 0
52 end
52 end
53
53
54 def test_new_with_issue_id
54 def test_new_with_issue_id
55 @request.session[:user_id] = 3
55 @request.session[:user_id] = 3
56 get :new, :issue_id => 2
56 get :new, :issue_id => 2
57 assert_response :success
57 assert_response :success
58 assert_template 'new'
58 assert_template 'new'
59 assert_select 'input[name=?][type=hidden]', 'project_id', 0
59 assert_select 'input[name=?][type=hidden]', 'project_id', 0
60 assert_select 'input[name=?][type=hidden]', 'issue_id'
60 assert_select 'input[name=?][type=hidden]', 'issue_id'
61 assert_select 'select[name=?]', 'time_entry[project_id]', 0
61 assert_select 'select[name=?]', 'time_entry[project_id]', 0
62 end
62 end
63
63
64 def test_new_without_project_should_prefill_the_form
64 def test_new_without_project_should_prefill_the_form
65 @request.session[:user_id] = 3
65 @request.session[:user_id] = 3
66 get :new, :time_entry => {:project_id => '1'}
66 get :new, :time_entry => {:project_id => '1'}
67 assert_response :success
67 assert_response :success
68 assert_template 'new'
68 assert_template 'new'
69 assert_select 'select[name=?]', 'time_entry[project_id]' do
69 assert_select 'select[name=?]', 'time_entry[project_id]' do
70 assert_select 'option[value=1][selected=selected]'
70 assert_select 'option[value=1][selected=selected]'
71 end
71 end
72 end
72 end
73
73
74 def test_new_without_project_should_deny_without_permission
74 def test_new_without_project_should_deny_without_permission
75 Role.all.each {|role| role.remove_permission! :log_time}
75 Role.all.each {|role| role.remove_permission! :log_time}
76 @request.session[:user_id] = 3
76 @request.session[:user_id] = 3
77
77
78 get :new
78 get :new
79 assert_response 403
79 assert_response 403
80 end
80 end
81
81
82 def test_new_should_select_default_activity
82 def test_new_should_select_default_activity
83 @request.session[:user_id] = 3
83 @request.session[:user_id] = 3
84 get :new, :project_id => 1
84 get :new, :project_id => 1
85 assert_response :success
85 assert_response :success
86 assert_select 'select[name=?]', 'time_entry[activity_id]' do
86 assert_select 'select[name=?]', 'time_entry[activity_id]' do
87 assert_select 'option[selected=selected]', :text => 'Development'
87 assert_select 'option[selected=selected]', :text => 'Development'
88 end
88 end
89 end
89 end
90
90
91 def test_new_should_only_show_active_time_entry_activities
91 def test_new_should_only_show_active_time_entry_activities
92 @request.session[:user_id] = 3
92 @request.session[:user_id] = 3
93 get :new, :project_id => 1
93 get :new, :project_id => 1
94 assert_response :success
94 assert_response :success
95 assert_no_tag 'option', :content => 'Inactive Activity'
95 assert_no_tag 'option', :content => 'Inactive Activity'
96 end
96 end
97
97
98 def test_get_edit_existing_time
98 def test_get_edit_existing_time
99 @request.session[:user_id] = 2
99 @request.session[:user_id] = 2
100 get :edit, :id => 2, :project_id => nil
100 get :edit, :id => 2, :project_id => nil
101 assert_response :success
101 assert_response :success
102 assert_template 'edit'
102 assert_template 'edit'
103 # Default activity selected
103 # Default activity selected
104 assert_tag :tag => 'form', :attributes => { :action => '/projects/ecookbook/time_entries/2' }
104 assert_tag :tag => 'form', :attributes => { :action => '/projects/ecookbook/time_entries/2' }
105 end
105 end
106
106
107 def test_get_edit_with_an_existing_time_entry_with_inactive_activity
107 def test_get_edit_with_an_existing_time_entry_with_inactive_activity
108 te = TimeEntry.find(1)
108 te = TimeEntry.find(1)
109 te.activity = TimeEntryActivity.find_by_name("Inactive Activity")
109 te.activity = TimeEntryActivity.find_by_name("Inactive Activity")
110 te.save!
110 te.save!
111
111
112 @request.session[:user_id] = 1
112 @request.session[:user_id] = 1
113 get :edit, :project_id => 1, :id => 1
113 get :edit, :project_id => 1, :id => 1
114 assert_response :success
114 assert_response :success
115 assert_template 'edit'
115 assert_template 'edit'
116 # Blank option since nothing is pre-selected
116 # Blank option since nothing is pre-selected
117 assert_tag :tag => 'option', :content => '--- Please select ---'
117 assert_tag :tag => 'option', :content => '--- Please select ---'
118 end
118 end
119
119
120 def test_post_create
120 def test_post_create
121 @request.session[:user_id] = 3
121 @request.session[:user_id] = 3
122 assert_difference 'TimeEntry.count' do
122 assert_difference 'TimeEntry.count' do
123 post :create, :project_id => 1,
123 post :create, :project_id => 1,
124 :time_entry => {:comments => 'Some work on TimelogControllerTest',
124 :time_entry => {:comments => 'Some work on TimelogControllerTest',
125 # Not the default activity
125 # Not the default activity
126 :activity_id => '11',
126 :activity_id => '11',
127 :spent_on => '2008-03-14',
127 :spent_on => '2008-03-14',
128 :issue_id => '1',
128 :issue_id => '1',
129 :hours => '7.3'}
129 :hours => '7.3'}
130 assert_redirected_to '/projects/ecookbook/time_entries'
130 assert_redirected_to '/projects/ecookbook/time_entries'
131 end
131 end
132
132
133 t = TimeEntry.order('id DESC').first
133 t = TimeEntry.order('id DESC').first
134 assert_not_nil t
134 assert_not_nil t
135 assert_equal 'Some work on TimelogControllerTest', t.comments
135 assert_equal 'Some work on TimelogControllerTest', t.comments
136 assert_equal 1, t.project_id
136 assert_equal 1, t.project_id
137 assert_equal 1, t.issue_id
137 assert_equal 1, t.issue_id
138 assert_equal 11, t.activity_id
138 assert_equal 11, t.activity_id
139 assert_equal 7.3, t.hours
139 assert_equal 7.3, t.hours
140 assert_equal 3, t.user_id
140 assert_equal 3, t.user_id
141 end
141 end
142
142
143 def test_post_create_with_blank_issue
143 def test_post_create_with_blank_issue
144 @request.session[:user_id] = 3
144 @request.session[:user_id] = 3
145 assert_difference 'TimeEntry.count' do
145 assert_difference 'TimeEntry.count' do
146 post :create, :project_id => 1,
146 post :create, :project_id => 1,
147 :time_entry => {:comments => 'Some work on TimelogControllerTest',
147 :time_entry => {:comments => 'Some work on TimelogControllerTest',
148 # Not the default activity
148 # Not the default activity
149 :activity_id => '11',
149 :activity_id => '11',
150 :issue_id => '',
150 :issue_id => '',
151 :spent_on => '2008-03-14',
151 :spent_on => '2008-03-14',
152 :hours => '7.3'}
152 :hours => '7.3'}
153 assert_redirected_to '/projects/ecookbook/time_entries'
153 assert_redirected_to '/projects/ecookbook/time_entries'
154 end
154 end
155
155
156 t = TimeEntry.order('id DESC').first
156 t = TimeEntry.order('id DESC').first
157 assert_not_nil t
157 assert_not_nil t
158 assert_equal 'Some work on TimelogControllerTest', t.comments
158 assert_equal 'Some work on TimelogControllerTest', t.comments
159 assert_equal 1, t.project_id
159 assert_equal 1, t.project_id
160 assert_nil t.issue_id
160 assert_nil t.issue_id
161 assert_equal 11, t.activity_id
161 assert_equal 11, t.activity_id
162 assert_equal 7.3, t.hours
162 assert_equal 7.3, t.hours
163 assert_equal 3, t.user_id
163 assert_equal 3, t.user_id
164 end
164 end
165
165
166 def test_create_and_continue_at_project_level
166 def test_create_and_continue_at_project_level
167 @request.session[:user_id] = 2
167 @request.session[:user_id] = 2
168 assert_difference 'TimeEntry.count' do
168 assert_difference 'TimeEntry.count' do
169 post :create, :time_entry => {:project_id => '1',
169 post :create, :time_entry => {:project_id => '1',
170 :activity_id => '11',
170 :activity_id => '11',
171 :issue_id => '',
171 :issue_id => '',
172 :spent_on => '2008-03-14',
172 :spent_on => '2008-03-14',
173 :hours => '7.3'},
173 :hours => '7.3'},
174 :continue => '1'
174 :continue => '1'
175 assert_redirected_to '/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=&time_entry%5Bproject_id%5D=1'
175 assert_redirected_to '/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=&time_entry%5Bproject_id%5D=1'
176 end
176 end
177 end
177 end
178
178
179 def test_create_and_continue_at_issue_level
179 def test_create_and_continue_at_issue_level
180 @request.session[:user_id] = 2
180 @request.session[:user_id] = 2
181 assert_difference 'TimeEntry.count' do
181 assert_difference 'TimeEntry.count' do
182 post :create, :time_entry => {:project_id => '',
182 post :create, :time_entry => {:project_id => '',
183 :activity_id => '11',
183 :activity_id => '11',
184 :issue_id => '1',
184 :issue_id => '1',
185 :spent_on => '2008-03-14',
185 :spent_on => '2008-03-14',
186 :hours => '7.3'},
186 :hours => '7.3'},
187 :continue => '1'
187 :continue => '1'
188 assert_redirected_to '/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=1&time_entry%5Bproject_id%5D='
188 assert_redirected_to '/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=1&time_entry%5Bproject_id%5D='
189 end
189 end
190 end
190 end
191
191
192 def test_create_and_continue_with_project_id
192 def test_create_and_continue_with_project_id
193 @request.session[:user_id] = 2
193 @request.session[:user_id] = 2
194 assert_difference 'TimeEntry.count' do
194 assert_difference 'TimeEntry.count' do
195 post :create, :project_id => 1,
195 post :create, :project_id => 1,
196 :time_entry => {:activity_id => '11',
196 :time_entry => {:activity_id => '11',
197 :issue_id => '',
197 :issue_id => '',
198 :spent_on => '2008-03-14',
198 :spent_on => '2008-03-14',
199 :hours => '7.3'},
199 :hours => '7.3'},
200 :continue => '1'
200 :continue => '1'
201 assert_redirected_to '/projects/ecookbook/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=&time_entry%5Bproject_id%5D='
201 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 end
202 end
203 end
203 end
204
204
205 def test_create_and_continue_with_issue_id
205 def test_create_and_continue_with_issue_id
206 @request.session[:user_id] = 2
206 @request.session[:user_id] = 2
207 assert_difference 'TimeEntry.count' do
207 assert_difference 'TimeEntry.count' do
208 post :create, :issue_id => 1,
208 post :create, :issue_id => 1,
209 :time_entry => {:activity_id => '11',
209 :time_entry => {:activity_id => '11',
210 :issue_id => '1',
210 :issue_id => '1',
211 :spent_on => '2008-03-14',
211 :spent_on => '2008-03-14',
212 :hours => '7.3'},
212 :hours => '7.3'},
213 :continue => '1'
213 :continue => '1'
214 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='
214 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 end
215 end
216 end
216 end
217
217
218 def test_create_without_log_time_permission_should_be_denied
218 def test_create_without_log_time_permission_should_be_denied
219 @request.session[:user_id] = 2
219 @request.session[:user_id] = 2
220 Role.find_by_name('Manager').remove_permission! :log_time
220 Role.find_by_name('Manager').remove_permission! :log_time
221 post :create, :project_id => 1,
221 post :create, :project_id => 1,
222 :time_entry => {:activity_id => '11',
222 :time_entry => {:activity_id => '11',
223 :issue_id => '',
223 :issue_id => '',
224 :spent_on => '2008-03-14',
224 :spent_on => '2008-03-14',
225 :hours => '7.3'}
225 :hours => '7.3'}
226
226
227 assert_response 403
227 assert_response 403
228 end
228 end
229
229
230 def test_create_without_project_and_issue_should_fail
230 def test_create_without_project_and_issue_should_fail
231 @request.session[:user_id] = 2
231 @request.session[:user_id] = 2
232 post :create, :time_entry => {:issue_id => ''}
232 post :create, :time_entry => {:issue_id => ''}
233
233
234 assert_response :success
234 assert_response :success
235 assert_template 'new'
235 assert_template 'new'
236 end
236 end
237
237
238 def test_create_with_failure
238 def test_create_with_failure
239 @request.session[:user_id] = 2
239 @request.session[:user_id] = 2
240 post :create, :project_id => 1,
240 post :create, :project_id => 1,
241 :time_entry => {:activity_id => '',
241 :time_entry => {:activity_id => '',
242 :issue_id => '',
242 :issue_id => '',
243 :spent_on => '2008-03-14',
243 :spent_on => '2008-03-14',
244 :hours => '7.3'}
244 :hours => '7.3'}
245
245
246 assert_response :success
246 assert_response :success
247 assert_template 'new'
247 assert_template 'new'
248 end
248 end
249
249
250 def test_create_without_project
250 def test_create_without_project
251 @request.session[:user_id] = 2
251 @request.session[:user_id] = 2
252 assert_difference 'TimeEntry.count' do
252 assert_difference 'TimeEntry.count' do
253 post :create, :time_entry => {:project_id => '1',
253 post :create, :time_entry => {:project_id => '1',
254 :activity_id => '11',
254 :activity_id => '11',
255 :issue_id => '',
255 :issue_id => '',
256 :spent_on => '2008-03-14',
256 :spent_on => '2008-03-14',
257 :hours => '7.3'}
257 :hours => '7.3'}
258 end
258 end
259
259
260 assert_redirected_to '/projects/ecookbook/time_entries'
260 assert_redirected_to '/projects/ecookbook/time_entries'
261 time_entry = TimeEntry.order('id DESC').first
261 time_entry = TimeEntry.order('id DESC').first
262 assert_equal 1, time_entry.project_id
262 assert_equal 1, time_entry.project_id
263 end
263 end
264
264
265 def test_create_without_project_should_fail_with_issue_not_inside_project
265 def test_create_without_project_should_fail_with_issue_not_inside_project
266 @request.session[:user_id] = 2
266 @request.session[:user_id] = 2
267 assert_no_difference 'TimeEntry.count' do
267 assert_no_difference 'TimeEntry.count' do
268 post :create, :time_entry => {:project_id => '1',
268 post :create, :time_entry => {:project_id => '1',
269 :activity_id => '11',
269 :activity_id => '11',
270 :issue_id => '5',
270 :issue_id => '5',
271 :spent_on => '2008-03-14',
271 :spent_on => '2008-03-14',
272 :hours => '7.3'}
272 :hours => '7.3'}
273 end
273 end
274
274
275 assert_response :success
275 assert_response :success
276 assert assigns(:time_entry).errors[:issue_id].present?
276 assert assigns(:time_entry).errors[:issue_id].present?
277 end
277 end
278
278
279 def test_create_without_project_should_deny_without_permission
279 def test_create_without_project_should_deny_without_permission
280 @request.session[:user_id] = 2
280 @request.session[:user_id] = 2
281 Project.find(3).disable_module!(:time_tracking)
281 Project.find(3).disable_module!(:time_tracking)
282
282
283 assert_no_difference 'TimeEntry.count' do
283 assert_no_difference 'TimeEntry.count' do
284 post :create, :time_entry => {:project_id => '3',
284 post :create, :time_entry => {:project_id => '3',
285 :activity_id => '11',
285 :activity_id => '11',
286 :issue_id => '',
286 :issue_id => '',
287 :spent_on => '2008-03-14',
287 :spent_on => '2008-03-14',
288 :hours => '7.3'}
288 :hours => '7.3'}
289 end
289 end
290
290
291 assert_response 403
291 assert_response 403
292 end
292 end
293
293
294 def test_create_without_project_with_failure
294 def test_create_without_project_with_failure
295 @request.session[:user_id] = 2
295 @request.session[:user_id] = 2
296 assert_no_difference 'TimeEntry.count' do
296 assert_no_difference 'TimeEntry.count' do
297 post :create, :time_entry => {:project_id => '1',
297 post :create, :time_entry => {:project_id => '1',
298 :activity_id => '11',
298 :activity_id => '11',
299 :issue_id => '',
299 :issue_id => '',
300 :spent_on => '2008-03-14',
300 :spent_on => '2008-03-14',
301 :hours => ''}
301 :hours => ''}
302 end
302 end
303
303
304 assert_response :success
304 assert_response :success
305 assert_tag 'select', :attributes => {:name => 'time_entry[project_id]'},
305 assert_tag 'select', :attributes => {:name => 'time_entry[project_id]'},
306 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
306 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
307 end
307 end
308
308
309 def test_update
309 def test_update
310 entry = TimeEntry.find(1)
310 entry = TimeEntry.find(1)
311 assert_equal 1, entry.issue_id
311 assert_equal 1, entry.issue_id
312 assert_equal 2, entry.user_id
312 assert_equal 2, entry.user_id
313
313
314 @request.session[:user_id] = 1
314 @request.session[:user_id] = 1
315 put :update, :id => 1,
315 put :update, :id => 1,
316 :time_entry => {:issue_id => '2',
316 :time_entry => {:issue_id => '2',
317 :hours => '8'}
317 :hours => '8'}
318 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
318 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
319 entry.reload
319 entry.reload
320
320
321 assert_equal 8, entry.hours
321 assert_equal 8, entry.hours
322 assert_equal 2, entry.issue_id
322 assert_equal 2, entry.issue_id
323 assert_equal 2, entry.user_id
323 assert_equal 2, entry.user_id
324 end
324 end
325
325
326 def test_update_should_allow_to_change_issue_to_another_project
326 def test_update_should_allow_to_change_issue_to_another_project
327 entry = TimeEntry.generate!(:issue_id => 1)
327 entry = TimeEntry.generate!(:issue_id => 1)
328
328
329 @request.session[:user_id] = 1
329 @request.session[:user_id] = 1
330 put :update, :id => entry.id, :time_entry => {:issue_id => '5'}
330 put :update, :id => entry.id, :time_entry => {:issue_id => '5'}
331 assert_response 302
331 assert_response 302
332 entry.reload
332 entry.reload
333
333
334 assert_equal 5, entry.issue_id
334 assert_equal 5, entry.issue_id
335 assert_equal 3, entry.project_id
335 assert_equal 3, entry.project_id
336 end
336 end
337
337
338 def test_update_should_not_allow_to_change_issue_to_an_invalid_project
338 def test_update_should_not_allow_to_change_issue_to_an_invalid_project
339 entry = TimeEntry.generate!(:issue_id => 1)
339 entry = TimeEntry.generate!(:issue_id => 1)
340 Project.find(3).disable_module!(:time_tracking)
340 Project.find(3).disable_module!(:time_tracking)
341
341
342 @request.session[:user_id] = 1
342 @request.session[:user_id] = 1
343 put :update, :id => entry.id, :time_entry => {:issue_id => '5'}
343 put :update, :id => entry.id, :time_entry => {:issue_id => '5'}
344 assert_response 200
344 assert_response 200
345 assert_include "Issue is invalid", assigns(:time_entry).errors.full_messages
345 assert_include "Issue is invalid", assigns(:time_entry).errors.full_messages
346 end
346 end
347
347
348 def test_get_bulk_edit
348 def test_get_bulk_edit
349 @request.session[:user_id] = 2
349 @request.session[:user_id] = 2
350 get :bulk_edit, :ids => [1, 2]
350 get :bulk_edit, :ids => [1, 2]
351 assert_response :success
351 assert_response :success
352 assert_template 'bulk_edit'
352 assert_template 'bulk_edit'
353
353
354 assert_select 'ul#bulk-selection' do
354 assert_select 'ul#bulk-selection' do
355 assert_select 'li', 2
355 assert_select 'li', 2
356 assert_select 'li a', :text => '03/23/2007 - eCookbook: 4.25 hours'
356 assert_select 'li a', :text => '03/23/2007 - eCookbook: 4.25 hours'
357 end
357 end
358
358
359 assert_select 'form#bulk_edit_form[action=?]', '/time_entries/bulk_update' do
359 assert_select 'form#bulk_edit_form[action=?]', '/time_entries/bulk_update' do
360 # System wide custom field
360 # System wide custom field
361 assert_select 'select[name=?]', 'time_entry[custom_field_values][10]'
361 assert_select 'select[name=?]', 'time_entry[custom_field_values][10]'
362
362
363 # Activities
363 # Activities
364 assert_select 'select[name=?]', 'time_entry[activity_id]' do
364 assert_select 'select[name=?]', 'time_entry[activity_id]' do
365 assert_select 'option[value=]', :text => '(No change)'
365 assert_select 'option[value=]', :text => '(No change)'
366 assert_select 'option[value=9]', :text => 'Design'
366 assert_select 'option[value=9]', :text => 'Design'
367 end
367 end
368 end
368 end
369 end
369 end
370
370
371 def test_get_bulk_edit_on_different_projects
371 def test_get_bulk_edit_on_different_projects
372 @request.session[:user_id] = 2
372 @request.session[:user_id] = 2
373 get :bulk_edit, :ids => [1, 2, 6]
373 get :bulk_edit, :ids => [1, 2, 6]
374 assert_response :success
374 assert_response :success
375 assert_template 'bulk_edit'
375 assert_template 'bulk_edit'
376 end
376 end
377
377
378 def test_bulk_update
378 def test_bulk_update
379 @request.session[:user_id] = 2
379 @request.session[:user_id] = 2
380 # update time entry activity
380 # update time entry activity
381 post :bulk_update, :ids => [1, 2], :time_entry => { :activity_id => 9}
381 post :bulk_update, :ids => [1, 2], :time_entry => { :activity_id => 9}
382
382
383 assert_response 302
383 assert_response 302
384 # check that the issues were updated
384 # check that the issues were updated
385 assert_equal [9, 9], TimeEntry.where(:id => [1, 2]).collect {|i| i.activity_id}
385 assert_equal [9, 9], TimeEntry.where(:id => [1, 2]).collect {|i| i.activity_id}
386 end
386 end
387
387
388 def test_bulk_update_with_failure
388 def test_bulk_update_with_failure
389 @request.session[:user_id] = 2
389 @request.session[:user_id] = 2
390 post :bulk_update, :ids => [1, 2], :time_entry => { :hours => 'A'}
390 post :bulk_update, :ids => [1, 2], :time_entry => { :hours => 'A'}
391
391
392 assert_response 302
392 assert_response 302
393 assert_match /Failed to save 2 time entrie/, flash[:error]
393 assert_match /Failed to save 2 time entrie/, flash[:error]
394 end
394 end
395
395
396 def test_bulk_update_on_different_projects
396 def test_bulk_update_on_different_projects
397 @request.session[:user_id] = 2
397 @request.session[:user_id] = 2
398 # makes user a manager on the other project
398 # makes user a manager on the other project
399 Member.create!(:user_id => 2, :project_id => 3, :role_ids => [1])
399 Member.create!(:user_id => 2, :project_id => 3, :role_ids => [1])
400
400
401 # update time entry activity
401 # update time entry activity
402 post :bulk_update, :ids => [1, 2, 4], :time_entry => { :activity_id => 9 }
402 post :bulk_update, :ids => [1, 2, 4], :time_entry => { :activity_id => 9 }
403
403
404 assert_response 302
404 assert_response 302
405 # check that the issues were updated
405 # check that the issues were updated
406 assert_equal [9, 9, 9], TimeEntry.where(:id => [1, 2, 4]).collect {|i| i.activity_id}
406 assert_equal [9, 9, 9], TimeEntry.where(:id => [1, 2, 4]).collect {|i| i.activity_id}
407 end
407 end
408
408
409 def test_bulk_update_on_different_projects_without_rights
409 def test_bulk_update_on_different_projects_without_rights
410 @request.session[:user_id] = 3
410 @request.session[:user_id] = 3
411 user = User.find(3)
411 user = User.find(3)
412 action = { :controller => "timelog", :action => "bulk_update" }
412 action = { :controller => "timelog", :action => "bulk_update" }
413 assert user.allowed_to?(action, TimeEntry.find(1).project)
413 assert user.allowed_to?(action, TimeEntry.find(1).project)
414 assert ! user.allowed_to?(action, TimeEntry.find(5).project)
414 assert ! user.allowed_to?(action, TimeEntry.find(5).project)
415 post :bulk_update, :ids => [1, 5], :time_entry => { :activity_id => 9 }
415 post :bulk_update, :ids => [1, 5], :time_entry => { :activity_id => 9 }
416 assert_response 403
416 assert_response 403
417 end
417 end
418
418
419 def test_bulk_update_custom_field
419 def test_bulk_update_custom_field
420 @request.session[:user_id] = 2
420 @request.session[:user_id] = 2
421 post :bulk_update, :ids => [1, 2], :time_entry => { :custom_field_values => {'10' => '0'} }
421 post :bulk_update, :ids => [1, 2], :time_entry => { :custom_field_values => {'10' => '0'} }
422
422
423 assert_response 302
423 assert_response 302
424 assert_equal ["0", "0"], TimeEntry.where(:id => [1, 2]).collect {|i| i.custom_value_for(10).value}
424 assert_equal ["0", "0"], TimeEntry.where(:id => [1, 2]).collect {|i| i.custom_value_for(10).value}
425 end
425 end
426
426
427 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
427 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
428 @request.session[:user_id] = 2
428 @request.session[:user_id] = 2
429 post :bulk_update, :ids => [1,2], :back_url => '/time_entries'
429 post :bulk_update, :ids => [1,2], :back_url => '/time_entries'
430
430
431 assert_response :redirect
431 assert_response :redirect
432 assert_redirected_to '/time_entries'
432 assert_redirected_to '/time_entries'
433 end
433 end
434
434
435 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
435 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
436 @request.session[:user_id] = 2
436 @request.session[:user_id] = 2
437 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
437 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
438
438
439 assert_response :redirect
439 assert_response :redirect
440 assert_redirected_to :controller => 'timelog', :action => 'index', :project_id => Project.find(1).identifier
440 assert_redirected_to :controller => 'timelog', :action => 'index', :project_id => Project.find(1).identifier
441 end
441 end
442
442
443 def test_post_bulk_update_without_edit_permission_should_be_denied
443 def test_post_bulk_update_without_edit_permission_should_be_denied
444 @request.session[:user_id] = 2
444 @request.session[:user_id] = 2
445 Role.find_by_name('Manager').remove_permission! :edit_time_entries
445 Role.find_by_name('Manager').remove_permission! :edit_time_entries
446 post :bulk_update, :ids => [1,2]
446 post :bulk_update, :ids => [1,2]
447
447
448 assert_response 403
448 assert_response 403
449 end
449 end
450
450
451 def test_destroy
451 def test_destroy
452 @request.session[:user_id] = 2
452 @request.session[:user_id] = 2
453 delete :destroy, :id => 1
453 delete :destroy, :id => 1
454 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
454 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
455 assert_equal I18n.t(:notice_successful_delete), flash[:notice]
455 assert_equal I18n.t(:notice_successful_delete), flash[:notice]
456 assert_nil TimeEntry.find_by_id(1)
456 assert_nil TimeEntry.find_by_id(1)
457 end
457 end
458
458
459 def test_destroy_should_fail
459 def test_destroy_should_fail
460 # simulate that this fails (e.g. due to a plugin), see #5700
460 # simulate that this fails (e.g. due to a plugin), see #5700
461 TimeEntry.any_instance.expects(:destroy).returns(false)
461 TimeEntry.any_instance.expects(:destroy).returns(false)
462
462
463 @request.session[:user_id] = 2
463 @request.session[:user_id] = 2
464 delete :destroy, :id => 1
464 delete :destroy, :id => 1
465 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
465 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
466 assert_equal I18n.t(:notice_unable_delete_time_entry), flash[:error]
466 assert_equal I18n.t(:notice_unable_delete_time_entry), flash[:error]
467 assert_not_nil TimeEntry.find_by_id(1)
467 assert_not_nil TimeEntry.find_by_id(1)
468 end
468 end
469
469
470 def test_index_all_projects
470 def test_index_all_projects
471 get :index
471 get :index
472 assert_response :success
472 assert_response :success
473 assert_template 'index'
473 assert_template 'index'
474 assert_not_nil assigns(:total_hours)
474 assert_not_nil assigns(:total_hours)
475 assert_equal "162.90", "%.2f" % assigns(:total_hours)
475 assert_equal "162.90", "%.2f" % assigns(:total_hours)
476 assert_tag :form,
476 assert_tag :form,
477 :attributes => {:action => "/time_entries", :id => 'query_form'}
477 :attributes => {:action => "/time_entries", :id => 'query_form'}
478 end
478 end
479
479
480 def test_index_all_projects_should_show_log_time_link
480 def test_index_all_projects_should_show_log_time_link
481 @request.session[:user_id] = 2
481 @request.session[:user_id] = 2
482 get :index
482 get :index
483 assert_response :success
483 assert_response :success
484 assert_template 'index'
484 assert_template 'index'
485 assert_tag 'a', :attributes => {:href => '/time_entries/new'}, :content => /Log time/
485 assert_tag 'a', :attributes => {:href => '/time_entries/new'}, :content => /Log time/
486 end
486 end
487
487
488 def test_index_my_spent_time
488 def test_index_my_spent_time
489 @request.session[:user_id] = 2
489 @request.session[:user_id] = 2
490 get :index, :user_id => 'me'
490 get :index, :user_id => 'me'
491 assert_response :success
491 assert_response :success
492 assert_template 'index'
492 assert_template 'index'
493 assert assigns(:entries).all? {|entry| entry.user_id == 2}
493 assert assigns(:entries).all? {|entry| entry.user_id == 2}
494 end
494 end
495
495
496 def test_index_at_project_level
496 def test_index_at_project_level
497 get :index, :project_id => 'ecookbook'
497 get :index, :project_id => 'ecookbook'
498 assert_response :success
498 assert_response :success
499 assert_template 'index'
499 assert_template 'index'
500 assert_not_nil assigns(:entries)
500 assert_not_nil assigns(:entries)
501 assert_equal 4, assigns(:entries).size
501 assert_equal 4, assigns(:entries).size
502 # project and subproject
502 # project and subproject
503 assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
503 assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
504 assert_not_nil assigns(:total_hours)
504 assert_not_nil assigns(:total_hours)
505 assert_equal "162.90", "%.2f" % assigns(:total_hours)
505 assert_equal "162.90", "%.2f" % assigns(:total_hours)
506 assert_tag :form,
506 assert_tag :form,
507 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
507 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
508 end
508 end
509
509
510 def test_index_with_display_subprojects_issues_to_false_should_not_include_subproject_entries
510 def test_index_with_display_subprojects_issues_to_false_should_not_include_subproject_entries
511 entry = TimeEntry.generate!(:project => Project.find(3))
511 entry = TimeEntry.generate!(:project => Project.find(3))
512
512
513 with_settings :display_subprojects_issues => '0' do
513 with_settings :display_subprojects_issues => '0' do
514 get :index, :project_id => 'ecookbook'
514 get :index, :project_id => 'ecookbook'
515 assert_response :success
515 assert_response :success
516 assert_template 'index'
516 assert_template 'index'
517 assert_not_include entry, assigns(:entries)
517 assert_not_include entry, assigns(:entries)
518 end
518 end
519 end
519 end
520
520
521 def test_index_with_display_subprojects_issues_to_false_and_subproject_filter_should_include_subproject_entries
521 def test_index_with_display_subprojects_issues_to_false_and_subproject_filter_should_include_subproject_entries
522 entry = TimeEntry.generate!(:project => Project.find(3))
522 entry = TimeEntry.generate!(:project => Project.find(3))
523
523
524 with_settings :display_subprojects_issues => '0' do
524 with_settings :display_subprojects_issues => '0' do
525 get :index, :project_id => 'ecookbook', :subproject_id => 3
525 get :index, :project_id => 'ecookbook', :subproject_id => 3
526 assert_response :success
526 assert_response :success
527 assert_template 'index'
527 assert_template 'index'
528 assert_include entry, assigns(:entries)
528 assert_include entry, assigns(:entries)
529 end
529 end
530 end
530 end
531
531
532 def test_index_at_project_level_with_date_range
532 def test_index_at_project_level_with_date_range
533 get :index, :project_id => 'ecookbook',
533 get :index, :project_id => 'ecookbook',
534 :f => ['spent_on'],
534 :f => ['spent_on'],
535 :op => {'spent_on' => '><'},
535 :op => {'spent_on' => '><'},
536 :v => {'spent_on' => ['2007-03-20', '2007-04-30']}
536 :v => {'spent_on' => ['2007-03-20', '2007-04-30']}
537 assert_response :success
537 assert_response :success
538 assert_template 'index'
538 assert_template 'index'
539 assert_not_nil assigns(:entries)
539 assert_not_nil assigns(:entries)
540 assert_equal 3, assigns(:entries).size
540 assert_equal 3, assigns(:entries).size
541 assert_not_nil assigns(:total_hours)
541 assert_not_nil assigns(:total_hours)
542 assert_equal "12.90", "%.2f" % assigns(:total_hours)
542 assert_equal "12.90", "%.2f" % assigns(:total_hours)
543 assert_tag :form,
543 assert_tag :form,
544 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
544 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
545 end
545 end
546
546
547 def test_index_at_project_level_with_date_range_using_from_and_to_params
547 def test_index_at_project_level_with_date_range_using_from_and_to_params
548 get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
548 get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
549 assert_response :success
549 assert_response :success
550 assert_template 'index'
550 assert_template 'index'
551 assert_not_nil assigns(:entries)
551 assert_not_nil assigns(:entries)
552 assert_equal 3, assigns(:entries).size
552 assert_equal 3, assigns(:entries).size
553 assert_not_nil assigns(:total_hours)
553 assert_not_nil assigns(:total_hours)
554 assert_equal "12.90", "%.2f" % assigns(:total_hours)
554 assert_equal "12.90", "%.2f" % assigns(:total_hours)
555 assert_tag :form,
555 assert_tag :form,
556 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
556 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
557 end
557 end
558
558
559 def test_index_at_project_level_with_period
559 def test_index_at_project_level_with_period
560 get :index, :project_id => 'ecookbook',
560 get :index, :project_id => 'ecookbook',
561 :f => ['spent_on'],
561 :f => ['spent_on'],
562 :op => {'spent_on' => '>t-'},
562 :op => {'spent_on' => '>t-'},
563 :v => {'spent_on' => ['7']}
563 :v => {'spent_on' => ['7']}
564 assert_response :success
564 assert_response :success
565 assert_template 'index'
565 assert_template 'index'
566 assert_not_nil assigns(:entries)
566 assert_not_nil assigns(:entries)
567 assert_not_nil assigns(:total_hours)
567 assert_not_nil assigns(:total_hours)
568 assert_tag :form,
568 assert_tag :form,
569 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
569 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
570 end
570 end
571
571
572 def test_index_at_issue_level
572 def test_index_at_issue_level
573 get :index, :issue_id => 1
573 get :index, :issue_id => 1
574 assert_response :success
574 assert_response :success
575 assert_template 'index'
575 assert_template 'index'
576 assert_not_nil assigns(:entries)
576 assert_not_nil assigns(:entries)
577 assert_equal 2, assigns(:entries).size
577 assert_equal 2, assigns(:entries).size
578 assert_not_nil assigns(:total_hours)
578 assert_not_nil assigns(:total_hours)
579 assert_equal 154.25, assigns(:total_hours)
579 assert_equal 154.25, assigns(:total_hours)
580 # display all time
580 # display all time
581 assert_nil assigns(:from)
581 assert_nil assigns(:from)
582 assert_nil assigns(:to)
582 assert_nil assigns(:to)
583 assert_tag :form,
583 assert_tag :form,
584 :attributes => {:action => "/projects/ecookbook/issues/1/time_entries", :id => 'query_form'}
584 :attributes => {:action => "/issues/1/time_entries", :id => 'query_form'}
585 end
585 end
586
586
587 def test_index_should_sort_by_spent_on_and_created_on
587 def test_index_should_sort_by_spent_on_and_created_on
588 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)
588 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 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)
589 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 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)
590 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
591
592 get :index, :project_id => 1,
592 get :index, :project_id => 1,
593 :f => ['spent_on'],
593 :f => ['spent_on'],
594 :op => {'spent_on' => '><'},
594 :op => {'spent_on' => '><'},
595 :v => {'spent_on' => ['2012-06-15', '2012-06-16']}
595 :v => {'spent_on' => ['2012-06-15', '2012-06-16']}
596 assert_response :success
596 assert_response :success
597 assert_equal [t2, t1, t3], assigns(:entries)
597 assert_equal [t2, t1, t3], assigns(:entries)
598
598
599 get :index, :project_id => 1,
599 get :index, :project_id => 1,
600 :f => ['spent_on'],
600 :f => ['spent_on'],
601 :op => {'spent_on' => '><'},
601 :op => {'spent_on' => '><'},
602 :v => {'spent_on' => ['2012-06-15', '2012-06-16']},
602 :v => {'spent_on' => ['2012-06-15', '2012-06-16']},
603 :sort => 'spent_on'
603 :sort => 'spent_on'
604 assert_response :success
604 assert_response :success
605 assert_equal [t3, t1, t2], assigns(:entries)
605 assert_equal [t3, t1, t2], assigns(:entries)
606 end
606 end
607
607
608 def test_index_with_filter_on_issue_custom_field
608 def test_index_with_filter_on_issue_custom_field
609 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
609 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
610 entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
610 entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
611
611
612 get :index, :f => ['issue.cf_2'], :op => {'issue.cf_2' => '='}, :v => {'issue.cf_2' => ['filter_on_issue_custom_field']}
612 get :index, :f => ['issue.cf_2'], :op => {'issue.cf_2' => '='}, :v => {'issue.cf_2' => ['filter_on_issue_custom_field']}
613 assert_response :success
613 assert_response :success
614 assert_equal [entry], assigns(:entries)
614 assert_equal [entry], assigns(:entries)
615 end
615 end
616
616
617 def test_index_with_issue_custom_field_column
617 def test_index_with_issue_custom_field_column
618 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
618 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
619 entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
619 entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
620
620
621 get :index, :c => %w(project spent_on issue comments hours issue.cf_2)
621 get :index, :c => %w(project spent_on issue comments hours issue.cf_2)
622 assert_response :success
622 assert_response :success
623 assert_include :'issue.cf_2', assigns(:query).column_names
623 assert_include :'issue.cf_2', assigns(:query).column_names
624 assert_select 'td.issue_cf_2', :text => 'filter_on_issue_custom_field'
624 assert_select 'td.issue_cf_2', :text => 'filter_on_issue_custom_field'
625 end
625 end
626
626
627 def test_index_with_time_entry_custom_field_column
627 def test_index_with_time_entry_custom_field_column
628 field = TimeEntryCustomField.generate!(:field_format => 'string')
628 field = TimeEntryCustomField.generate!(:field_format => 'string')
629 entry = TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value'})
629 entry = TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value'})
630 field_name = "cf_#{field.id}"
630 field_name = "cf_#{field.id}"
631
631
632 get :index, :c => ["hours", field_name]
632 get :index, :c => ["hours", field_name]
633 assert_response :success
633 assert_response :success
634 assert_include field_name.to_sym, assigns(:query).column_names
634 assert_include field_name.to_sym, assigns(:query).column_names
635 assert_select "td.#{field_name}", :text => 'CF Value'
635 assert_select "td.#{field_name}", :text => 'CF Value'
636 end
636 end
637
637
638 def test_index_with_time_entry_custom_field_sorting
638 def test_index_with_time_entry_custom_field_sorting
639 field = TimeEntryCustomField.generate!(:field_format => 'string', :name => 'String Field')
639 field = TimeEntryCustomField.generate!(:field_format => 'string', :name => 'String Field')
640 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 1'})
640 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 1'})
641 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 3'})
641 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 3'})
642 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 2'})
642 TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 2'})
643 field_name = "cf_#{field.id}"
643 field_name = "cf_#{field.id}"
644
644
645 get :index, :c => ["hours", field_name], :sort => field_name
645 get :index, :c => ["hours", field_name], :sort => field_name
646 assert_response :success
646 assert_response :success
647 assert_include field_name.to_sym, assigns(:query).column_names
647 assert_include field_name.to_sym, assigns(:query).column_names
648 assert_select "th a.sort", :text => 'String Field'
648 assert_select "th a.sort", :text => 'String Field'
649
649
650 # Make sure that values are properly sorted
650 # Make sure that values are properly sorted
651 values = assigns(:entries).map {|e| e.custom_field_value(field)}.compact
651 values = assigns(:entries).map {|e| e.custom_field_value(field)}.compact
652 assert_equal 3, values.size
652 assert_equal 3, values.size
653 assert_equal values.sort, values
653 assert_equal values.sort, values
654 end
654 end
655
655
656 def test_index_atom_feed
656 def test_index_atom_feed
657 get :index, :project_id => 1, :format => 'atom'
657 get :index, :project_id => 1, :format => 'atom'
658 assert_response :success
658 assert_response :success
659 assert_equal 'application/atom+xml', @response.content_type
659 assert_equal 'application/atom+xml', @response.content_type
660 assert_not_nil assigns(:items)
660 assert_not_nil assigns(:items)
661 assert assigns(:items).first.is_a?(TimeEntry)
661 assert assigns(:items).first.is_a?(TimeEntry)
662 end
662 end
663
663
664 def test_index_at_project_level_should_include_csv_export_dialog
664 def test_index_at_project_level_should_include_csv_export_dialog
665 get :index, :project_id => 'ecookbook',
665 get :index, :project_id => 'ecookbook',
666 :f => ['spent_on'],
666 :f => ['spent_on'],
667 :op => {'spent_on' => '>='},
667 :op => {'spent_on' => '>='},
668 :v => {'spent_on' => ['2007-04-01']},
668 :v => {'spent_on' => ['2007-04-01']},
669 :c => ['spent_on', 'user']
669 :c => ['spent_on', 'user']
670 assert_response :success
670 assert_response :success
671
671
672 assert_select '#csv-export-options' do
672 assert_select '#csv-export-options' do
673 assert_select 'form[action=?][method=get]', '/projects/ecookbook/time_entries.csv' do
673 assert_select 'form[action=?][method=get]', '/projects/ecookbook/time_entries.csv' do
674 # filter
674 # filter
675 assert_select 'input[name=?][value=?]', 'f[]', 'spent_on'
675 assert_select 'input[name=?][value=?]', 'f[]', 'spent_on'
676 assert_select 'input[name=?][value=?]', 'op[spent_on]', '&gt;='
676 assert_select 'input[name=?][value=?]', 'op[spent_on]', '&gt;='
677 assert_select 'input[name=?][value=?]', 'v[spent_on][]', '2007-04-01'
677 assert_select 'input[name=?][value=?]', 'v[spent_on][]', '2007-04-01'
678 # columns
678 # columns
679 assert_select 'input[name=?][value=?]', 'c[]', 'spent_on'
679 assert_select 'input[name=?][value=?]', 'c[]', 'spent_on'
680 assert_select 'input[name=?][value=?]', 'c[]', 'user'
680 assert_select 'input[name=?][value=?]', 'c[]', 'user'
681 assert_select 'input[name=?]', 'c[]', 2
681 assert_select 'input[name=?]', 'c[]', 2
682 end
682 end
683 end
683 end
684 end
684 end
685
685
686 def test_index_cross_project_should_include_csv_export_dialog
686 def test_index_cross_project_should_include_csv_export_dialog
687 get :index
687 get :index
688 assert_response :success
688 assert_response :success
689
689
690 assert_select '#csv-export-options' do
690 assert_select '#csv-export-options' do
691 assert_select 'form[action=?][method=get]', '/time_entries.csv'
691 assert_select 'form[action=?][method=get]', '/time_entries.csv'
692 end
692 end
693 end
693 end
694
694
695 def test_index_at_issue_level_should_include_csv_export_dialog
695 def test_index_at_issue_level_should_include_csv_export_dialog
696 get :index, :project_id => 'ecookbook', :issue_id => 3
696 get :index, :issue_id => 3
697 assert_response :success
697 assert_response :success
698
698
699 assert_select '#csv-export-options' do
699 assert_select '#csv-export-options' do
700 assert_select 'form[action=?][method=get]', '/projects/ecookbook/issues/3/time_entries.csv'
700 assert_select 'form[action=?][method=get]', '/issues/3/time_entries.csv'
701 end
701 end
702 end
702 end
703
703
704 def test_index_csv_all_projects
704 def test_index_csv_all_projects
705 Setting.date_format = '%m/%d/%Y'
705 Setting.date_format = '%m/%d/%Y'
706 get :index, :format => 'csv'
706 get :index, :format => 'csv'
707 assert_response :success
707 assert_response :success
708 assert_equal 'text/csv; header=present', response.content_type
708 assert_equal 'text/csv; header=present', response.content_type
709 end
709 end
710
710
711 def test_index_csv
711 def test_index_csv
712 Setting.date_format = '%m/%d/%Y'
712 Setting.date_format = '%m/%d/%Y'
713 get :index, :project_id => 1, :format => 'csv'
713 get :index, :project_id => 1, :format => 'csv'
714 assert_response :success
714 assert_response :success
715 assert_equal 'text/csv; header=present', response.content_type
715 assert_equal 'text/csv; header=present', response.content_type
716 end
716 end
717 end
717 end
@@ -1,240 +1,189
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../../test_helper', __FILE__)
18 require File.expand_path('../../../test_helper', __FILE__)
19
19
20 class RoutingTimelogsTest < ActionController::IntegrationTest
20 class RoutingTimelogsTest < ActionController::IntegrationTest
21 def test_timelogs_global
21 def test_timelogs_global
22 assert_routing(
22 assert_routing(
23 { :method => 'get', :path => "/time_entries" },
23 { :method => 'get', :path => "/time_entries" },
24 { :controller => 'timelog', :action => 'index' }
24 { :controller => 'timelog', :action => 'index' }
25 )
25 )
26 assert_routing(
26 assert_routing(
27 { :method => 'get', :path => "/time_entries.csv" },
27 { :method => 'get', :path => "/time_entries.csv" },
28 { :controller => 'timelog', :action => 'index', :format => 'csv' }
28 { :controller => 'timelog', :action => 'index', :format => 'csv' }
29 )
29 )
30 assert_routing(
30 assert_routing(
31 { :method => 'get', :path => "/time_entries.atom" },
31 { :method => 'get', :path => "/time_entries.atom" },
32 { :controller => 'timelog', :action => 'index', :format => 'atom' }
32 { :controller => 'timelog', :action => 'index', :format => 'atom' }
33 )
33 )
34 assert_routing(
34 assert_routing(
35 { :method => 'get', :path => "/time_entries/new" },
35 { :method => 'get', :path => "/time_entries/new" },
36 { :controller => 'timelog', :action => 'new' }
36 { :controller => 'timelog', :action => 'new' }
37 )
37 )
38 assert_routing(
38 assert_routing(
39 { :method => 'get', :path => "/time_entries/22/edit" },
39 { :method => 'get', :path => "/time_entries/22/edit" },
40 { :controller => 'timelog', :action => 'edit', :id => '22' }
40 { :controller => 'timelog', :action => 'edit', :id => '22' }
41 )
41 )
42 assert_routing(
42 assert_routing(
43 { :method => 'post', :path => "/time_entries" },
43 { :method => 'post', :path => "/time_entries" },
44 { :controller => 'timelog', :action => 'create' }
44 { :controller => 'timelog', :action => 'create' }
45 )
45 )
46 assert_routing(
46 assert_routing(
47 { :method => 'put', :path => "/time_entries/22" },
47 { :method => 'put', :path => "/time_entries/22" },
48 { :controller => 'timelog', :action => 'update', :id => '22' }
48 { :controller => 'timelog', :action => 'update', :id => '22' }
49 )
49 )
50 assert_routing(
50 assert_routing(
51 { :method => 'delete', :path => "/time_entries/55" },
51 { :method => 'delete', :path => "/time_entries/55" },
52 { :controller => 'timelog', :action => 'destroy', :id => '55' }
52 { :controller => 'timelog', :action => 'destroy', :id => '55' }
53 )
53 )
54 end
54 end
55
55
56 def test_timelogs_scoped_under_project
56 def test_timelogs_scoped_under_project
57 assert_routing(
57 assert_routing(
58 { :method => 'get', :path => "/projects/567/time_entries" },
58 { :method => 'get', :path => "/projects/567/time_entries" },
59 { :controller => 'timelog', :action => 'index', :project_id => '567' }
59 { :controller => 'timelog', :action => 'index', :project_id => '567' }
60 )
60 )
61 assert_routing(
61 assert_routing(
62 { :method => 'get', :path => "/projects/567/time_entries.csv" },
62 { :method => 'get', :path => "/projects/567/time_entries.csv" },
63 { :controller => 'timelog', :action => 'index', :project_id => '567',
63 { :controller => 'timelog', :action => 'index', :project_id => '567',
64 :format => 'csv' }
64 :format => 'csv' }
65 )
65 )
66 assert_routing(
66 assert_routing(
67 { :method => 'get', :path => "/projects/567/time_entries.atom" },
67 { :method => 'get', :path => "/projects/567/time_entries.atom" },
68 { :controller => 'timelog', :action => 'index', :project_id => '567',
68 { :controller => 'timelog', :action => 'index', :project_id => '567',
69 :format => 'atom' }
69 :format => 'atom' }
70 )
70 )
71 assert_routing(
71 assert_routing(
72 { :method => 'get', :path => "/projects/567/time_entries/new" },
72 { :method => 'get', :path => "/projects/567/time_entries/new" },
73 { :controller => 'timelog', :action => 'new', :project_id => '567' }
73 { :controller => 'timelog', :action => 'new', :project_id => '567' }
74 )
74 )
75 assert_routing(
75 assert_routing(
76 { :method => 'get', :path => "/projects/567/time_entries/22/edit" },
76 { :method => 'get', :path => "/projects/567/time_entries/22/edit" },
77 { :controller => 'timelog', :action => 'edit',
77 { :controller => 'timelog', :action => 'edit',
78 :id => '22', :project_id => '567' }
78 :id => '22', :project_id => '567' }
79 )
79 )
80 assert_routing(
80 assert_routing(
81 { :method => 'post', :path => "/projects/567/time_entries" },
81 { :method => 'post', :path => "/projects/567/time_entries" },
82 { :controller => 'timelog', :action => 'create',
82 { :controller => 'timelog', :action => 'create',
83 :project_id => '567' }
83 :project_id => '567' }
84 )
84 )
85 assert_routing(
85 assert_routing(
86 { :method => 'put', :path => "/projects/567/time_entries/22" },
86 { :method => 'put', :path => "/projects/567/time_entries/22" },
87 { :controller => 'timelog', :action => 'update',
87 { :controller => 'timelog', :action => 'update',
88 :id => '22', :project_id => '567' }
88 :id => '22', :project_id => '567' }
89 )
89 )
90 assert_routing(
90 assert_routing(
91 { :method => 'delete', :path => "/projects/567/time_entries/55" },
91 { :method => 'delete', :path => "/projects/567/time_entries/55" },
92 { :controller => 'timelog', :action => 'destroy',
92 { :controller => 'timelog', :action => 'destroy',
93 :id => '55', :project_id => '567' }
93 :id => '55', :project_id => '567' }
94 )
94 )
95 end
95 end
96
96
97 def test_timelogs_scoped_under_issues
97 def test_timelogs_scoped_under_issues
98 assert_routing(
98 assert_routing(
99 { :method => 'get', :path => "/issues/234/time_entries" },
99 { :method => 'get', :path => "/issues/234/time_entries" },
100 { :controller => 'timelog', :action => 'index', :issue_id => '234' }
100 { :controller => 'timelog', :action => 'index', :issue_id => '234' }
101 )
101 )
102 assert_routing(
102 assert_routing(
103 { :method => 'get', :path => "/issues/234/time_entries.csv" },
103 { :method => 'get', :path => "/issues/234/time_entries.csv" },
104 { :controller => 'timelog', :action => 'index', :issue_id => '234',
104 { :controller => 'timelog', :action => 'index', :issue_id => '234',
105 :format => 'csv' }
105 :format => 'csv' }
106 )
106 )
107 assert_routing(
107 assert_routing(
108 { :method => 'get', :path => "/issues/234/time_entries.atom" },
108 { :method => 'get', :path => "/issues/234/time_entries.atom" },
109 { :controller => 'timelog', :action => 'index', :issue_id => '234',
109 { :controller => 'timelog', :action => 'index', :issue_id => '234',
110 :format => 'atom' }
110 :format => 'atom' }
111 )
111 )
112 assert_routing(
112 assert_routing(
113 { :method => 'get', :path => "/issues/234/time_entries/new" },
113 { :method => 'get', :path => "/issues/234/time_entries/new" },
114 { :controller => 'timelog', :action => 'new', :issue_id => '234' }
114 { :controller => 'timelog', :action => 'new', :issue_id => '234' }
115 )
115 )
116 assert_routing(
116 assert_routing(
117 { :method => 'get', :path => "/issues/234/time_entries/22/edit" },
117 { :method => 'get', :path => "/issues/234/time_entries/22/edit" },
118 { :controller => 'timelog', :action => 'edit', :id => '22',
118 { :controller => 'timelog', :action => 'edit', :id => '22',
119 :issue_id => '234' }
119 :issue_id => '234' }
120 )
120 )
121 assert_routing(
121 assert_routing(
122 { :method => 'post', :path => "/issues/234/time_entries" },
122 { :method => 'post', :path => "/issues/234/time_entries" },
123 { :controller => 'timelog', :action => 'create', :issue_id => '234' }
123 { :controller => 'timelog', :action => 'create', :issue_id => '234' }
124 )
124 )
125 assert_routing(
125 assert_routing(
126 { :method => 'put', :path => "/issues/234/time_entries/22" },
126 { :method => 'put', :path => "/issues/234/time_entries/22" },
127 { :controller => 'timelog', :action => 'update', :id => '22',
127 { :controller => 'timelog', :action => 'update', :id => '22',
128 :issue_id => '234' }
128 :issue_id => '234' }
129 )
129 )
130 assert_routing(
130 assert_routing(
131 { :method => 'delete', :path => "/issues/234/time_entries/55" },
131 { :method => 'delete', :path => "/issues/234/time_entries/55" },
132 { :controller => 'timelog', :action => 'destroy', :id => '55',
132 { :controller => 'timelog', :action => 'destroy', :id => '55',
133 :issue_id => '234' }
133 :issue_id => '234' }
134 )
134 )
135 end
135 end
136
136
137 def test_timelogs_scoped_under_project_and_issues
138 assert_routing(
139 { :method => 'get',
140 :path => "/projects/ecookbook/issues/234/time_entries" },
141 { :controller => 'timelog', :action => 'index',
142 :issue_id => '234', :project_id => 'ecookbook' }
143 )
144 assert_routing(
145 { :method => 'get',
146 :path => "/projects/ecookbook/issues/234/time_entries.csv" },
147 { :controller => 'timelog', :action => 'index',
148 :issue_id => '234', :project_id => 'ecookbook', :format => 'csv' }
149 )
150 assert_routing(
151 { :method => 'get',
152 :path => "/projects/ecookbook/issues/234/time_entries.atom" },
153 { :controller => 'timelog', :action => 'index',
154 :issue_id => '234', :project_id => 'ecookbook', :format => 'atom' }
155 )
156 assert_routing(
157 { :method => 'get',
158 :path => "/projects/ecookbook/issues/234/time_entries/new" },
159 { :controller => 'timelog', :action => 'new',
160 :issue_id => '234', :project_id => 'ecookbook' }
161 )
162 assert_routing(
163 { :method => 'get',
164 :path => "/projects/ecookbook/issues/234/time_entries/22/edit" },
165 { :controller => 'timelog', :action => 'edit', :id => '22',
166 :issue_id => '234', :project_id => 'ecookbook' }
167 )
168 assert_routing(
169 { :method => 'post',
170 :path => "/projects/ecookbook/issues/234/time_entries" },
171 { :controller => 'timelog', :action => 'create',
172 :issue_id => '234', :project_id => 'ecookbook' }
173 )
174 assert_routing(
175 { :method => 'put',
176 :path => "/projects/ecookbook/issues/234/time_entries/22" },
177 { :controller => 'timelog', :action => 'update', :id => '22',
178 :issue_id => '234', :project_id => 'ecookbook' }
179 )
180 assert_routing(
181 { :method => 'delete',
182 :path => "/projects/ecookbook/issues/234/time_entries/55" },
183 { :controller => 'timelog', :action => 'destroy', :id => '55',
184 :issue_id => '234', :project_id => 'ecookbook' }
185 )
186 end
187
188 def test_timelogs_report
137 def test_timelogs_report
189 assert_routing(
138 assert_routing(
190 { :method => 'get',
139 { :method => 'get',
191 :path => "/time_entries/report" },
140 :path => "/time_entries/report" },
192 { :controller => 'timelog', :action => 'report' }
141 { :controller => 'timelog', :action => 'report' }
193 )
142 )
194 assert_routing(
143 assert_routing(
195 { :method => 'get',
144 { :method => 'get',
196 :path => "/time_entries/report.csv" },
145 :path => "/time_entries/report.csv" },
197 { :controller => 'timelog', :action => 'report', :format => 'csv' }
146 { :controller => 'timelog', :action => 'report', :format => 'csv' }
198 )
147 )
199 assert_routing(
148 assert_routing(
200 { :method => 'get',
149 { :method => 'get',
201 :path => "/issues/234/time_entries/report" },
150 :path => "/issues/234/time_entries/report" },
202 { :controller => 'timelog', :action => 'report', :issue_id => '234' }
151 { :controller => 'timelog', :action => 'report', :issue_id => '234' }
203 )
152 )
204 assert_routing(
153 assert_routing(
205 { :method => 'get',
154 { :method => 'get',
206 :path => "/issues/234/time_entries/report.csv" },
155 :path => "/issues/234/time_entries/report.csv" },
207 { :controller => 'timelog', :action => 'report', :issue_id => '234',
156 { :controller => 'timelog', :action => 'report', :issue_id => '234',
208 :format => 'csv' }
157 :format => 'csv' }
209 )
158 )
210 assert_routing(
159 assert_routing(
211 { :method => 'get',
160 { :method => 'get',
212 :path => "/projects/567/time_entries/report" },
161 :path => "/projects/567/time_entries/report" },
213 { :controller => 'timelog', :action => 'report', :project_id => '567' }
162 { :controller => 'timelog', :action => 'report', :project_id => '567' }
214 )
163 )
215 assert_routing(
164 assert_routing(
216 { :method => 'get',
165 { :method => 'get',
217 :path => "/projects/567/time_entries/report.csv" },
166 :path => "/projects/567/time_entries/report.csv" },
218 { :controller => 'timelog', :action => 'report', :project_id => '567',
167 { :controller => 'timelog', :action => 'report', :project_id => '567',
219 :format => 'csv' }
168 :format => 'csv' }
220 )
169 )
221 end
170 end
222
171
223 def test_timelogs_bulk_edit
172 def test_timelogs_bulk_edit
224 assert_routing(
173 assert_routing(
225 { :method => 'delete',
174 { :method => 'delete',
226 :path => "/time_entries/destroy" },
175 :path => "/time_entries/destroy" },
227 { :controller => 'timelog', :action => 'destroy' }
176 { :controller => 'timelog', :action => 'destroy' }
228 )
177 )
229 assert_routing(
178 assert_routing(
230 { :method => 'post',
179 { :method => 'post',
231 :path => "/time_entries/bulk_update" },
180 :path => "/time_entries/bulk_update" },
232 { :controller => 'timelog', :action => 'bulk_update' }
181 { :controller => 'timelog', :action => 'bulk_update' }
233 )
182 )
234 assert_routing(
183 assert_routing(
235 { :method => 'get',
184 { :method => 'get',
236 :path => "/time_entries/bulk_edit" },
185 :path => "/time_entries/bulk_edit" },
237 { :controller => 'timelog', :action => 'bulk_edit' }
186 { :controller => 'timelog', :action => 'bulk_edit' }
238 )
187 )
239 end
188 end
240 end
189 end
General Comments 0
You need to be logged in to leave comments. Login now