[DRE-commits] r4193 - trunk/redmine/debian/patches

Jérémy Lal kapouer-guest at alioth.debian.org
Tue Sep 22 22:56:39 UTC 2009


Author: kapouer-guest
Date: 2009-09-22 22:56:39 +0000 (Tue, 22 Sep 2009)
New Revision: 4193

Added:
   trunk/redmine/debian/patches/changeset_r2891.diff
   trunk/redmine/debian/patches/changeset_r2892.diff
   trunk/redmine/debian/patches/changeset_r2893.diff
   trunk/redmine/debian/patches/changeset_r2894.diff
Modified:
   trunk/redmine/debian/patches/series
Log:
Latest patches from upstream.

Added: trunk/redmine/debian/patches/changeset_r2891.diff
===================================================================
--- trunk/redmine/debian/patches/changeset_r2891.diff	                        (rev 0)
+++ trunk/redmine/debian/patches/changeset_r2891.diff	2009-09-22 22:56:39 UTC (rev 4193)
@@ -0,0 +1,238 @@
+Index: trunk/app/views/timelog/report.rhtml
+===================================================================
+--- trunk/app/views/timelog/report.rhtml	(revision 2890)
++++ trunk/app/views/timelog/report.rhtml	(revision 2891)
+@@ -6,7 +6,7 @@
+ 
+ <h2><%= l(:label_spent_time) %></h2>
+ 
+-<% form_remote_tag(:url => {}, :html => {:method => :get}, :method => :get, :update => 'content') do %>
++<% form_remote_tag(:url => {}, :html => {:method => :get, :id => 'query_form'}, :method => :get, :update => 'content') do %>
+   <% @criterias.each do |criteria| %>
+     <%= hidden_field_tag 'criterias[]', criteria, :id => nil %>
+   <% end %>
+Index: trunk/app/views/timelog/details.rhtml
+===================================================================
+--- trunk/app/views/timelog/details.rhtml	(revision 2890)
++++ trunk/app/views/timelog/details.rhtml	(revision 2891)
+@@ -6,7 +6,7 @@
+ 
+ <h2><%= l(:label_spent_time) %></h2>
+ 
+-<% form_remote_tag( :url => {}, :html => {:method => :get}, :method => :get, :update => 'content' ) do %>
++<% form_remote_tag( :url => {}, :html => {:method => :get, :id => 'query_form'}, :method => :get, :update => 'content' ) do %>
+ <%# TOOD: remove the project_id and issue_id hidden fields, that information is
+ already in the URI %>
+ <%= hidden_field_tag('project_id', params[:project_id]) if @project %>
+Index: trunk/app/views/timelog/_date_range.rhtml
+===================================================================
+--- trunk/app/views/timelog/_date_range.rhtml	(revision 2890)
++++ trunk/app/views/timelog/_date_range.rhtml	(revision 2891)
+@@ -1,4 +1,6 @@
+-<fieldset id="filters"><legend><%= l(:label_date_range) %></legend>
++<fieldset id="date-range" class="collapsible">
++<legend onclick="toggleFieldset(this);"><%= l(:label_date_range) %></legend>
++<div>
+ <p>
+ <%= radio_button_tag 'period_type', '1', !@free_period %>
+ <%= select_tag 'period', options_for_period_select(params[:period]),
+@@ -11,9 +13,16 @@
+ <%= l(:label_date_from_to, :start => (text_field_tag('from', @from, :size => 10) + calendar_for('from')),
+ 													 :end => (text_field_tag('to', @to, :size => 10) + calendar_for('to'))) %>
+ </span>
+-<%= submit_tag l(:button_apply), :name => nil %>
+ </p>
++</div>
+ </fieldset>
++<p class="buttons">
++	<%= link_to_remote l(:button_apply), 
++	                   { :url => { },
++	                     :update => "content",
++	                     :with => "Form.serialize('query_form')"
++	                   }, :class => 'icon icon-checked' %>
++</p>
+ 
+ <div class="tabs">
+ <% url_params = @free_period ? { :from => @from, :to => @to } : { :period => params[:period] } %>
+Index: trunk/app/views/issues/index.rhtml
+===================================================================
+--- trunk/app/views/issues/index.rhtml	(revision 2890)
++++ trunk/app/views/issues/index.rhtml	(revision 2891)
+@@ -5,11 +5,19 @@
+     <% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %>
+     <%= hidden_field_tag('project_id', @project.to_param) if @project %>
+ 		<div id="query_form_content">
+-    <fieldset id="filters"><legend><%= l(:label_filter_plural) %></legend>
+-    <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
++    <fieldset id="filters" class="collapsible">
++    	<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
++    	<div>
++    		<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
++    	</div>
+     </fieldset>
+-		<p><%= l(:field_group_by) %>
+-		<%= select_tag('group_by', options_for_select([[]] + @query.groupable_columns.collect {|c| [c.caption, c.name.to_s]}, @query.group_by)) %></p>
++    <fieldset class="collapsible collapsed">
++    	<legend onclick="toggleFieldset(this);">Options</legend>
++    	<div style="display: none;">
++				<%= l(:field_group_by) %>
++				<%= select_tag('group_by', options_for_select([[]] + @query.groupable_columns.collect {|c| [c.caption, c.name.to_s]}, @query.group_by)) %></p>
++			</div>
++		</fieldset>
+ 		</div>
+     <p class="buttons">
+ 
+Index: trunk/app/views/issues/calendar.rhtml
+===================================================================
+--- trunk/app/views/issues/calendar.rhtml	(revision 2890)
++++ trunk/app/views/issues/calendar.rhtml	(revision 2891)
+@@ -1,20 +1,18 @@
+ <% form_tag({}, :id => 'query_form') do %>
+ <% if @query.new_record? %>
+-    <h2><%= l(:label_calendar) %></h2>
+-    <fieldset id="filters"><legend><%= l(:label_filter_plural) %></legend>
++<h2><%= l(:label_calendar) %></h2>
++<fieldset id="filters" class="collapsible">
++  <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
++  <div>
+     <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
+-    </fieldset>
++  </div>
++</fieldset>
+ <% else %>
+     <h2><%=h @query.name %></h2>
+     <% html_title @query.name %>
+ <% end %>
+ 
+-<fieldset id="date-range"><legend><%= l(:label_date_range) %></legend>
+-    <%= select_month(@month, :prefix => "month", :discard_type => true) %>
+-    <%= select_year(@year, :prefix => "year", :discard_type => true) %>
+-</fieldset>
+-
+-<p style="float:right; margin:0px;">
++<p style="float:right;">
+ <%= link_to_remote ('&#171; ' + (@month==1 ? "#{month_name(12)} #{@year-1}" : "#{month_name(@month-1)}")), 
+                         {:update => "content", :url => { :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1) }},
+                         {:href => url_for(:action => 'calendar', :year => (@month==1 ? @year-1 : @year), :month =>(@month==1 ? 12 : @month-1))}
+@@ -26,6 +24,9 @@
+ </p>
+ 
+ <p class="buttons">
++<%= select_month(@month, :prefix => "month", :discard_type => true) %>
++<%= select_year(@year, :prefix => "year", :discard_type => true) %>
++
+ <%= link_to_remote l(:button_apply), 
+                    { :url => { :set_filter => (@query.new_record? ? 1 : nil) },
+                      :update => "content",
+Index: trunk/app/views/issues/gantt.rhtml
+===================================================================
+--- trunk/app/views/issues/gantt.rhtml	(revision 2890)
++++ trunk/app/views/issues/gantt.rhtml	(revision 2891)
+@@ -1,23 +1,18 @@
+ <% form_tag(params.merge(:month => nil, :year => nil, :months => nil), :id => 'query_form') do %>
+ <% if @query.new_record? %>
+-    <h2><%=l(:label_gantt)%></h2>
+-    <fieldset id="filters"><legend><%= l(:label_filter_plural) %></legend>
++<h2><%=l(:label_gantt)%></h2>
++<fieldset id="filters" class="collapsible">
++  <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
++	<div>
+     <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
+-    </fieldset>
++  </div>
++</fieldset>
+ <% else %>
+     <h2><%=h @query.name %></h2>
+     <% html_title @query.name %>
+ <% end %>
+ 
+-<fieldset id="date-range"><legend><%= l(:label_date_range) %></legend>
+-    <%= text_field_tag 'months', @gantt.months, :size => 2 %>
+-    <%= l(:label_months_from) %>
+-    <%= select_month(@gantt.month_from, :prefix => "month", :discard_type => true) %>
+-    <%= select_year(@gantt.year_from, :prefix => "year", :discard_type => true) %>
+-    <%= hidden_field_tag 'zoom', @gantt.zoom %>
+-</fieldset>
+-
+-<p style="float:right; margin:0px;">
++<p style="float:right;">
+ <%= if @gantt.zoom < 4
+     link_to_remote image_tag('zoom_in.png'), {:url => @gantt.params.merge(:zoom => (@gantt.zoom+1)), :update => 'content'}, {:href => url_for(@gantt.params.merge(:zoom => (@gantt.zoom+1)))}
+   else
+@@ -31,6 +26,12 @@
+ </p>
+ 
+ <p class="buttons">
++<%= text_field_tag 'months', @gantt.months, :size => 2 %>
++<%= l(:label_months_from) %>
++<%= select_month(@gantt.month_from, :prefix => "month", :discard_type => true) %>
++<%= select_year(@gantt.year_from, :prefix => "year", :discard_type => true) %>
++<%= hidden_field_tag 'zoom', @gantt.zoom %>
++
+ <%= link_to_remote l(:button_apply), 
+                    { :url => { :set_filter => (@query.new_record? ? 1 : nil) },
+                      :update => "content",
+Index: trunk/public/images/arrow_expanded.png
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: trunk/public/images/arrow_expanded.png
+___________________________________________________________________
+Name: svn:mime-type
+   + application/octet-stream
+
+Index: trunk/public/images/arrow_collapsed.png
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: trunk/public/images/arrow_collapsed.png
+___________________________________________________________________
+Name: svn:mime-type
+   + application/octet-stream
+
+Index: trunk/public/javascripts/application.js
+===================================================================
+--- trunk/public/javascripts/application.js	(revision 2890)
++++ trunk/public/javascripts/application.js	(revision 2891)
+@@ -33,6 +33,12 @@
+ 	}
+ }
+ 
++function toggleFieldset(el) {
++	var fieldset = Element.up(el, 'fieldset');
++	fieldset.toggleClassName('collapsed');
++	Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2});
++}
++
+ var fileFieldCount = 1;
+ 
+ function addFileField() {
+Index: trunk/public/stylesheets/application.css
+===================================================================
+--- trunk/public/stylesheets/application.css	(revision 2890)
++++ trunk/public/stylesheets/application.css	(revision 2891)
+@@ -200,17 +200,16 @@
+ p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; } 
+ p.footnote { font-size: 0.9em; margin-top: 0px; margin-bottom: 0px; }
+ 
+-#query_form_content { font-size: 0.9em; padding: 4px; background: #f6f6f6; border: 1px solid #e4e4e4; }
+-#query_form_content fieldset#filters { border-left: 0; border-right: 0; }
+-#query_form_content p { margin-top: 0.5em; margin-bottom: 0.5em; }
++fieldset.collapsible { border-width: 1px 0 0 0; font-size: 0.9em; }
++fieldset.collapsible legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; }
++fieldset.collapsible.collapsed legend { background-image: url(../images/arrow_collapsed.png); }
+ 
+-fieldset#filters, fieldset#date-range { padding: 0.7em; margin-bottom: 8px; }
+-fieldset#filters p { margin: 1.2em 0 0.8em 2px; }
++fieldset#date-range p { margin: 2px 0 2px 0; }
+ fieldset#filters table { border-collapse: collapse; }
+ fieldset#filters table td { padding: 0; vertical-align: middle; }
+ fieldset#filters tr.filter { height: 2em; }
+ fieldset#filters td.add-filter { text-align: right; vertical-align: top; }
+-.buttons { font-size: 0.9em; margin-bottom: 1.4em; }
++.buttons { font-size: 0.9em; margin-bottom: 1.4em; margin-top: 1em; }
+ 
+ div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;}
+ div#issue-changesets .changeset { padding: 4px;}

Added: trunk/redmine/debian/patches/changeset_r2892.diff
===================================================================
--- trunk/redmine/debian/patches/changeset_r2892.diff	                        (rev 0)
+++ trunk/redmine/debian/patches/changeset_r2892.diff	2009-09-22 22:56:39 UTC (rev 4193)
@@ -0,0 +1,93 @@
+Index: trunk/app/views/issues/index.rhtml
+===================================================================
+--- trunk/app/views/issues/index.rhtml	(revision 2891)
++++ trunk/app/views/issues/index.rhtml	(revision 2892)
+@@ -1,8 +1,14 @@
+-<% if @query.new_record? %>
+-    <h2><%=l(:label_issue_plural)%></h2>
+-    <% html_title(l(:label_issue_plural)) %>
+-    
+-    <% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %>
++<div class="contextual">
++<% if !@query.new_record? && @query.editable_by?(User.current) %>
++	<%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => @query}, :class => 'icon icon-edit' %>
++	<%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => @query}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
++<% end %>
++</div>
++
++<h2><%= @query.new_record? ? l(:label_issue_plural) : h(@query.name) %></h2>
++<% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %>
++
++<% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %>
+     <%= hidden_field_tag('project_id', @project.to_param) if @project %>
+ 		<div id="query_form_content">
+     <fieldset id="filters" class="collapsible">
+@@ -33,21 +39,10 @@
+                          :update => "content",
+                        }, :class => 'icon icon-reload'  %>
+                        
+-    <% if User.current.allowed_to?(:save_queries, @project, :global => true) %>
++    <% if @query.new_record? && User.current.allowed_to?(:save_queries, @project, :global => true) %>
+     <%= link_to l(:button_save), {}, :onclick => "$('query_form').submit(); return false;", :class => 'icon icon-save' %>
+     <% end %>
+     </p>
+-    <% end %>
+-<% else %>
+-    <div class="contextual">
+-    <% if @query.editable_by?(User.current) %>
+-    <%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => @query}, :class => 'icon icon-edit' %>
+-    <%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => @query}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
+-    <% end %>
+-    </div>
+-    <h2><%=h @query.name %></h2>
+-    <div id="query_form"></div>
+-    <% html_title @query.name %>
+ <% end %>
+ 
+ <%= error_messages_for 'query' %>
+Index: trunk/app/views/issues/calendar.rhtml
+===================================================================
+--- trunk/app/views/issues/calendar.rhtml	(revision 2891)
++++ trunk/app/views/issues/calendar.rhtml	(revision 2892)
+@@ -1,16 +1,12 @@
+-<% form_tag({}, :id => 'query_form') do %>
+-<% if @query.new_record? %>
+ <h2><%= l(:label_calendar) %></h2>
++
++<% form_tag({}, :id => 'query_form') do %>
+ <fieldset id="filters" class="collapsible">
+   <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
+   <div>
+     <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
+   </div>
+ </fieldset>
+-<% else %>
+-    <h2><%=h @query.name %></h2>
+-    <% html_title @query.name %>
+-<% end %>
+ 
+ <p style="float:right;">
+ <%= link_to_remote ('&#171; ' + (@month==1 ? "#{month_name(12)} #{@year-1}" : "#{month_name(@month-1)}")), 
+Index: trunk/app/views/issues/gantt.rhtml
+===================================================================
+--- trunk/app/views/issues/gantt.rhtml	(revision 2891)
++++ trunk/app/views/issues/gantt.rhtml	(revision 2892)
+@@ -1,16 +1,12 @@
++<h2><%= l(:label_gantt) %></h2>
++
+ <% form_tag(params.merge(:month => nil, :year => nil, :months => nil), :id => 'query_form') do %>
+-<% if @query.new_record? %>
+-<h2><%=l(:label_gantt)%></h2>
+ <fieldset id="filters" class="collapsible">
+   <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
+ 	<div>
+     <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
+   </div>
+ </fieldset>
+-<% else %>
+-    <h2><%=h @query.name %></h2>
+-    <% html_title @query.name %>
+-<% end %>
+ 
+ <p style="float:right;">
+ <%= if @gantt.zoom < 4

Added: trunk/redmine/debian/patches/changeset_r2893.diff
===================================================================
--- trunk/redmine/debian/patches/changeset_r2893.diff	                        (rev 0)
+++ trunk/redmine/debian/patches/changeset_r2893.diff	2009-09-22 22:56:39 UTC (rev 4193)
@@ -0,0 +1,76 @@
+Index: trunk/test/functional/timelog_controller_test.rb
+===================================================================
+--- trunk/test/functional/timelog_controller_test.rb	(revision 2892)
++++ trunk/test/functional/timelog_controller_test.rb	(revision 2893)
+@@ -206,6 +206,14 @@
+     assert_equal "162.90", "%.2f" % assigns(:total_hours)
+   end
+   
++  def test_report_at_issue_level
++    get :report, :project_id => 1, :issue_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criterias => ["member", "activity"]
++    assert_response :success
++    assert_template 'report'
++    assert_not_nil assigns(:total_hours)
++    assert_equal "154.25", "%.2f" % assigns(:total_hours)
++  end
++  
+   def test_report_custom_field_criteria
+     get :report, :project_id => 1, :criterias => ['project', 'cf_1']
+     assert_response :success
+Index: trunk/app/controllers/timelog_controller.rb
+===================================================================
+--- trunk/app/controllers/timelog_controller.rb	(revision 2892)
++++ trunk/app/controllers/timelog_controller.rb	(revision 2893)
+@@ -80,14 +80,22 @@
+     unless @criterias.empty?
+       sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
+       sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ')
++      sql_condition = ''
+       
++      if @project.nil?
++        sql_condition = Project.allowed_to_condition(User.current, :view_time_entries)
++      elsif @issue.nil?
++        sql_condition = @project.project_condition(Setting.display_subprojects_issues?)
++      else
++        sql_condition = "#{TimeEntry.table_name}.issue_id = #{@issue.id}"
++      end
++
+       sql = "SELECT #{sql_select}, tyear, tmonth, tweek, spent_on, SUM(hours) AS hours"
+       sql << " FROM #{TimeEntry.table_name}"
+       sql << " LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id"
+       sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id"
+       sql << " WHERE"
+-      sql << " (%s) AND" % @project.project_condition(Setting.display_subprojects_issues?) if @project
+-      sql << " (%s) AND" % Project.allowed_to_condition(User.current, :view_time_entries)
++      sql << " (%s) AND" % sql_condition
+       sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from.to_time), ActiveRecord::Base.connection.quoted_date(@to.to_time)]
+       sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on"
+       
+Index: trunk/app/views/timelog/report.rhtml
+===================================================================
+--- trunk/app/views/timelog/report.rhtml	(revision 2892)
++++ trunk/app/views/timelog/report.rhtml	(revision 2893)
+@@ -12,6 +12,7 @@
+   <% end %>
+   <%# TODO: get rid of the project_id field, that should already be in the URL %>
+   <%= hidden_field_tag('project_id', params[:project_id]) if @project %>
++  <%= hidden_field_tag('issue_id', params[:issue_id]) if @issue %>
+   <%= render :partial => 'date_range' %>
+ 
+   <p><%= l(:label_details) %>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'],
+Index: trunk/app/views/timelog/_date_range.rhtml
+===================================================================
+--- trunk/app/views/timelog/_date_range.rhtml	(revision 2892)
++++ trunk/app/views/timelog/_date_range.rhtml	(revision 2893)
+@@ -27,9 +27,9 @@
+ <div class="tabs">
+ <% url_params = @free_period ? { :from => @from, :to => @to } : { :period => params[:period] } %>
+ <ul>
+-    <li><%= link_to(l(:label_details), url_params.merge({:controller => 'timelog', :action => 'details', :project_id => @project }),
++    <li><%= link_to(l(:label_details), url_params.merge({:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue }),
+                                        :class => (@controller.action_name == 'details' ? 'selected' : nil)) %></li>
+-    <li><%= link_to(l(:label_report), url_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project}),
++    <li><%= link_to(l(:label_report), url_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project, :issue_id => @issue}),
+                                        :class => (@controller.action_name == 'report' ? 'selected' : nil)) %></li>
+ </ul>
+ </div>

Added: trunk/redmine/debian/patches/changeset_r2894.diff
===================================================================
--- trunk/redmine/debian/patches/changeset_r2894.diff	                        (rev 0)
+++ trunk/redmine/debian/patches/changeset_r2894.diff	2009-09-22 22:56:39 UTC (rev 4193)
@@ -0,0 +1,1199 @@
+Index: trunk/test/functional/account_controller_test.rb
+===================================================================
+--- trunk/test/functional/account_controller_test.rb	(revision 2893)
++++ trunk/test/functional/account_controller_test.rb	(revision 2894)
+@@ -37,7 +37,19 @@
+     assert_template 'show'
+     assert_not_nil assigns(:user)
+   end
++
++  def test_show_should_not_fail_when_custom_values_are_nil
++    user = User.find(2)
++
++    # Create a custom field to illustrate the issue
++    custom_field = CustomField.create!(:name => 'Testing', :field_format => 'text')
++    custom_value = user.custom_values.build(:custom_field => custom_field).save!
++
++    get :show, :id => 2
++    assert_response :success
++  end
+   
++
+   def test_show_inactive
+     get :show, :id => 5
+     assert_response 404
+Index: trunk/test/functional/projects_controller_test.rb
+===================================================================
+--- trunk/test/functional/projects_controller_test.rb	(revision 2893)
++++ trunk/test/functional/projects_controller_test.rb	(revision 2894)
+@@ -1,567 +1,577 @@
+-# Redmine - project management software
+-# Copyright (C) 2006-2008  Jean-Philippe Lang
+-#
+-# This program is free software; you can redistribute it and/or
+-# modify it under the terms of the GNU General Public License
+-# as published by the Free Software Foundation; either version 2
+-# of the License, or (at your option) any later version.
+-# 
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-# GNU General Public License for more details.
+-# 
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+-
+-require File.dirname(__FILE__) + '/../test_helper'
+-require 'projects_controller'
+-
+-# Re-raise errors caught by the controller.
+-class ProjectsController; def rescue_action(e) raise e end; end
+-
+-class ProjectsControllerTest < ActionController::TestCase
+-  fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
+-           :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
+-           :attachments
+-
+-  def setup
+-    @controller = ProjectsController.new
+-    @request    = ActionController::TestRequest.new
+-    @response   = ActionController::TestResponse.new
+-    @request.session[:user_id] = nil
+-    Setting.default_language = 'en'
+-  end
+-  
+-  def test_index_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects'},
+-      :controller => 'projects', :action => 'index'
+-    )
+-  end
+-  
+-  def test_index
+-    get :index
+-    assert_response :success
+-    assert_template 'index'
+-    assert_not_nil assigns(:projects)
+-    
+-    assert_tag :ul, :child => {:tag => 'li',
+-                               :descendant => {:tag => 'a', :content => 'eCookbook'},
+-                               :child => { :tag => 'ul',
+-                                           :descendant => { :tag => 'a',
+-                                                            :content => 'Child of private child'
+-                                                           }
+-                                          }
+-                               }
+-                               
+-    assert_no_tag :a, :content => /Private child of eCookbook/
+-  end
+-  
+-  def test_index_atom_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects.atom'},
+-      :controller => 'projects', :action => 'index', :format => 'atom'
+-    )
+-  end
+-  
+-  def test_index_atom
+-    get :index, :format => 'atom'
+-    assert_response :success
+-    assert_template 'common/feed.atom.rxml'
+-    assert_select 'feed>title', :text => 'Redmine: Latest projects'
+-    assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_by(User.current))
+-  end
+-  
+-  def test_add_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/new'},
+-      :controller => 'projects', :action => 'add'
+-    )
+-    assert_recognizes(
+-      {:controller => 'projects', :action => 'add'},
+-      {:method => :post, :path => '/projects/new'}
+-    )
+-    assert_recognizes(
+-      {:controller => 'projects', :action => 'add'},
+-      {:method => :post, :path => '/projects'}
+-    )
+-  end
+-  
+-  def test_get_add
+-    @request.session[:user_id] = 1
+-    get :add
+-    assert_response :success
+-    assert_template 'add'
+-  end
+-  
+-  def test_get_add_by_non_admin
+-    @request.session[:user_id] = 2
+-    get :add
+-    assert_response :success
+-    assert_template 'add'
+-  end
+-  
+-  def test_post_add
+-    @request.session[:user_id] = 1
+-    post :add, :project => { :name => "blog", 
+-                             :description => "weblog",
+-                             :identifier => "blog",
+-                             :is_public => 1,
+-                             :custom_field_values => { '3' => 'Beta' }
+-                            }
+-    assert_redirected_to '/projects/blog/settings'
+-    
+-    project = Project.find_by_name('blog')
+-    assert_kind_of Project, project
+-    assert_equal 'weblog', project.description 
+-    assert_equal true, project.is_public?
+-  end
+-  
+-  def test_post_add_by_non_admin
+-    @request.session[:user_id] = 2
+-    post :add, :project => { :name => "blog", 
+-                             :description => "weblog",
+-                             :identifier => "blog",
+-                             :is_public => 1,
+-                             :custom_field_values => { '3' => 'Beta' }
+-                            }
+-    assert_redirected_to '/projects/blog/settings'
+-    
+-    project = Project.find_by_name('blog')
+-    assert_kind_of Project, project
+-    assert_equal 'weblog', project.description 
+-    assert_equal true, project.is_public?
+-    
+-    # User should be added as a project member
+-    assert User.find(2).member_of?(project)
+-    assert_equal 1, project.members.size
+-  end
+-  
+-  def test_show_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/test'},
+-      :controller => 'projects', :action => 'show', :id => 'test'
+-    )
+-  end
+-  
+-  def test_show_by_id
+-    get :show, :id => 1
+-    assert_response :success
+-    assert_template 'show'
+-    assert_not_nil assigns(:project)
+-  end
+-
+-  def test_show_by_identifier
+-    get :show, :id => 'ecookbook'
+-    assert_response :success
+-    assert_template 'show'
+-    assert_not_nil assigns(:project)
+-    assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
+-  end
+-  
+-  def test_private_subprojects_hidden
+-    get :show, :id => 'ecookbook'
+-    assert_response :success
+-    assert_template 'show'
+-    assert_no_tag :tag => 'a', :content => /Private child/
+-  end
+-
+-  def test_private_subprojects_visible
+-    @request.session[:user_id] = 2 # manager who is a member of the private subproject
+-    get :show, :id => 'ecookbook'
+-    assert_response :success
+-    assert_template 'show'
+-    assert_tag :tag => 'a', :content => /Private child/
+-  end
+-  
+-  def test_settings_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/4223/settings'},
+-      :controller => 'projects', :action => 'settings', :id => '4223'
+-    )
+-    assert_routing(
+-      {:method => :get, :path => '/projects/4223/settings/members'},
+-      :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
+-    )
+-  end
+-  
+-  def test_settings
+-    @request.session[:user_id] = 2 # manager
+-    get :settings, :id => 1
+-    assert_response :success
+-    assert_template 'settings'
+-  end
+-  
+-  def test_edit
+-    @request.session[:user_id] = 2 # manager
+-    post :edit, :id => 1, :project => {:name => 'Test changed name',
+-                                       :issue_custom_field_ids => ['']}
+-    assert_redirected_to 'projects/ecookbook/settings'
+-    project = Project.find(1)
+-    assert_equal 'Test changed name', project.name
+-  end
+-  
+-  def test_add_version_routing
+-    assert_routing(
+-      {:method => :get, :path => 'projects/64/versions/new'},
+-      :controller => 'projects', :action => 'add_version', :id => '64'
+-    )
+-    assert_routing(
+-    #TODO: use PUT
+-      {:method => :post, :path => 'projects/64/versions/new'},
+-      :controller => 'projects', :action => 'add_version', :id => '64'
+-    )
+-  end
+-  
+-  def test_add_issue_category_routing
+-    assert_routing(
+-      {:method => :get, :path => 'projects/test/categories/new'},
+-      :controller => 'projects', :action => 'add_issue_category', :id => 'test'
+-    )
+-    assert_routing(
+-    #TODO: use PUT and update form
+-      {:method => :post, :path => 'projects/64/categories/new'},
+-      :controller => 'projects', :action => 'add_issue_category', :id => '64'
+-    )
+-  end
+-  
+-  def test_destroy_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/567/destroy'},
+-      :controller => 'projects', :action => 'destroy', :id => '567'
+-    )
+-    assert_routing(
+-    #TODO: use DELETE and update form
+-      {:method => :post, :path => 'projects/64/destroy'},
+-      :controller => 'projects', :action => 'destroy', :id => '64'
+-    )
+-  end
+-  
+-  def test_get_destroy
+-    @request.session[:user_id] = 1 # admin
+-    get :destroy, :id => 1
+-    assert_response :success
+-    assert_template 'destroy'
+-    assert_not_nil Project.find_by_id(1)
+-  end
+-
+-  def test_post_destroy
+-    @request.session[:user_id] = 1 # admin
+-    post :destroy, :id => 1, :confirm => 1
+-    assert_redirected_to 'admin/projects'
+-    assert_nil Project.find_by_id(1)
+-  end
+-  
+-  def test_add_file
+-    set_tmp_attachments_directory
+-    @request.session[:user_id] = 2
+-    Setting.notified_events = ['file_added']
+-    ActionMailer::Base.deliveries.clear
+-    
+-    assert_difference 'Attachment.count' do
+-      post :add_file, :id => 1, :version_id => '',
+-           :attachments => {'1' => {'file' => test_uploaded_file('testfile.txt', 'text/plain')}}
+-    end
+-    assert_redirected_to 'projects/ecookbook/files'
+-    a = Attachment.find(:first, :order => 'created_on DESC')
+-    assert_equal 'testfile.txt', a.filename
+-    assert_equal Project.find(1), a.container
+-
+-    mail = ActionMailer::Base.deliveries.last
+-    assert_kind_of TMail::Mail, mail
+-    assert_equal "[eCookbook] New file", mail.subject
+-    assert mail.body.include?('testfile.txt')
+-  end
+-  
+-  def test_add_file_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/33/files/new'},
+-      :controller => 'projects', :action => 'add_file', :id => '33'
+-    )
+-    assert_routing(
+-      {:method => :post, :path => '/projects/33/files/new'},
+-      :controller => 'projects', :action => 'add_file', :id => '33'
+-    )
+-  end
+-  
+-  def test_add_version_file
+-    set_tmp_attachments_directory
+-    @request.session[:user_id] = 2
+-    Setting.notified_events = ['file_added']
+-    
+-    assert_difference 'Attachment.count' do
+-      post :add_file, :id => 1, :version_id => '2',
+-           :attachments => {'1' => {'file' => test_uploaded_file('testfile.txt', 'text/plain')}}
+-    end
+-    assert_redirected_to 'projects/ecookbook/files'
+-    a = Attachment.find(:first, :order => 'created_on DESC')
+-    assert_equal 'testfile.txt', a.filename
+-    assert_equal Version.find(2), a.container
+-  end
+-  
+-  def test_list_files
+-    get :list_files, :id => 1
+-    assert_response :success
+-    assert_template 'list_files'
+-    assert_not_nil assigns(:containers)
+-    
+-    # file attached to the project
+-    assert_tag :a, :content => 'project_file.zip',
+-                   :attributes => { :href => '/attachments/download/8/project_file.zip' }
+-    
+-    # file attached to a project's version
+-    assert_tag :a, :content => 'version_file.zip',
+-                   :attributes => { :href => '/attachments/download/9/version_file.zip' }
+-  end
+-
+-  def test_list_files_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/33/files'},
+-      :controller => 'projects', :action => 'list_files', :id => '33'
+-    )
+-  end
+-  
+-  def test_changelog_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/44/changelog'},
+-      :controller => 'projects', :action => 'changelog', :id => '44'
+-    )
+-  end
+-  
+-  def test_changelog
+-    get :changelog, :id => 1
+-    assert_response :success
+-    assert_template 'changelog'
+-    assert_not_nil assigns(:versions)
+-  end
+-  
+-  def test_roadmap_routing
+-    assert_routing(
+-      {:method => :get, :path => 'projects/33/roadmap'},
+-      :controller => 'projects', :action => 'roadmap', :id => '33'
+-    )
+-  end
+-  
+-  def test_roadmap
+-    get :roadmap, :id => 1
+-    assert_response :success
+-    assert_template 'roadmap'
+-    assert_not_nil assigns(:versions)
+-    # Version with no date set appears
+-    assert assigns(:versions).include?(Version.find(3))
+-    # Completed version doesn't appear
+-    assert !assigns(:versions).include?(Version.find(1))
+-  end
+-  
+-  def test_roadmap_with_completed_versions
+-    get :roadmap, :id => 1, :completed => 1
+-    assert_response :success
+-    assert_template 'roadmap'
+-    assert_not_nil assigns(:versions)
+-    # Version with no date set appears
+-    assert assigns(:versions).include?(Version.find(3))
+-    # Completed version appears
+-    assert assigns(:versions).include?(Version.find(1))
+-  end
+-  
+-  def test_project_activity_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/1/activity'},
+-       :controller => 'projects', :action => 'activity', :id => '1'
+-    )
+-  end
+-  
+-  def test_project_activity_atom_routing
+-    assert_routing(
+-      {:method => :get, :path => '/projects/1/activity.atom'},
+-       :controller => 'projects', :action => 'activity', :id => '1', :format => 'atom'
+-    )    
+-  end
+-  
+-  def test_project_activity
+-    get :activity, :id => 1, :with_subprojects => 0
+-    assert_response :success
+-    assert_template 'activity'
+-    assert_not_nil assigns(:events_by_day)
+-    
+-    assert_tag :tag => "h3", 
+-               :content => /#{2.days.ago.to_date.day}/,
+-               :sibling => { :tag => "dl",
+-                 :child => { :tag => "dt",
+-                   :attributes => { :class => /issue-edit/ },
+-                   :child => { :tag => "a",
+-                     :content => /(#{IssueStatus.find(2).name})/,
+-                   }
+-                 }
+-               }
+-  end
+-  
+-  def test_previous_project_activity
+-    get :activity, :id => 1, :from => 3.days.ago.to_date
+-    assert_response :success
+-    assert_template 'activity'
+-    assert_not_nil assigns(:events_by_day)
+-               
+-    assert_tag :tag => "h3", 
+-               :content => /#{3.day.ago.to_date.day}/,
+-               :sibling => { :tag => "dl",
+-                 :child => { :tag => "dt",
+-                   :attributes => { :class => /issue/ },
+-                   :child => { :tag => "a",
+-                     :content => /#{Issue.find(1).subject}/,
+-                   }
+-                 }
+-               }
+-  end
+-  
+-  def test_global_activity_routing
+-    assert_routing({:method => :get, :path => '/activity'}, :controller => 'projects', :action => 'activity', :id => nil)
+-  end
+-  
+-  def test_global_activity
+-    get :activity
+-    assert_response :success
+-    assert_template 'activity'
+-    assert_not_nil assigns(:events_by_day)
+-    
+-    assert_tag :tag => "h3", 
+-               :content => /#{5.day.ago.to_date.day}/,
+-               :sibling => { :tag => "dl",
+-                 :child => { :tag => "dt",
+-                   :attributes => { :class => /issue/ },
+-                   :child => { :tag => "a",
+-                     :content => /#{Issue.find(5).subject}/,
+-                   }
+-                 }
+-               }
+-  end
+-  
+-  def test_user_activity
+-    get :activity, :user_id => 2
+-    assert_response :success
+-    assert_template 'activity'
+-    assert_not_nil assigns(:events_by_day)
+-    
+-    assert_tag :tag => "h3", 
+-               :content => /#{3.day.ago.to_date.day}/,
+-               :sibling => { :tag => "dl",
+-                 :child => { :tag => "dt",
+-                   :attributes => { :class => /issue/ },
+-                   :child => { :tag => "a",
+-                     :content => /#{Issue.find(1).subject}/,
+-                   }
+-                 }
+-               }
+-  end
+-  
+-  def test_global_activity_atom_routing
+-    assert_routing({:method => :get, :path => '/activity.atom'}, :controller => 'projects', :action => 'activity', :id => nil, :format => 'atom')
+-  end
+-  
+-  def test_activity_atom_feed
+-    get :activity, :format => 'atom'
+-    assert_response :success
+-    assert_template 'common/feed.atom.rxml'
+-  end
+-  
+-  def test_archive_routing
+-    assert_routing(
+-    #TODO: use PUT to project path and modify form
+-      {:method => :post, :path => 'projects/64/archive'},
+-      :controller => 'projects', :action => 'archive', :id => '64'
+-    )
+-  end
+-  
+-  def test_archive
+-    @request.session[:user_id] = 1 # admin
+-    post :archive, :id => 1
+-    assert_redirected_to 'admin/projects'
+-    assert !Project.find(1).active?
+-  end
+-  
+-  def test_unarchive_routing
+-    assert_routing(
+-    #TODO: use PUT to project path and modify form
+-      {:method => :post, :path => '/projects/567/unarchive'},
+-      :controller => 'projects', :action => 'unarchive', :id => '567'
+-    )
+-  end
+-  
+-  def test_unarchive
+-    @request.session[:user_id] = 1 # admin
+-    Project.find(1).archive
+-    post :unarchive, :id => 1
+-    assert_redirected_to 'admin/projects'
+-    assert Project.find(1).active?
+-  end
+-  
+-  def test_project_breadcrumbs_should_be_limited_to_3_ancestors
+-    CustomField.delete_all
+-    parent = nil
+-    6.times do |i|
+-      p = Project.create!(:name => "Breadcrumbs #{i}", :identifier => "breadcrumbs-#{i}")
+-      p.set_parent!(parent)
+-      get :show, :id => p
+-      assert_tag :h1, :parent => { :attributes => {:id => 'header'}},
+-                      :children => { :count => [i, 3].min,
+-                                     :only => { :tag => 'a' } }
+-                                     
+-      parent = p
+-    end
+-  end
+-
+-  def test_copy_with_project
+-    @request.session[:user_id] = 1 # admin
+-    get :copy, :id => 1
+-    assert_response :success
+-    assert_template 'copy'
+-    assert assigns(:project)
+-    assert_equal Project.find(1).description, assigns(:project).description
+-    assert_nil assigns(:project).id
+-  end
+-
+-  def test_copy_without_project
+-    @request.session[:user_id] = 1 # admin
+-    get :copy
+-    assert_response :redirect
+-    assert_redirected_to :controller => 'admin', :action => 'projects'
+-  end
+-
+-  def test_jump_should_redirect_to_active_tab
+-    get :show, :id => 1, :jump => 'issues'
+-    assert_redirected_to 'projects/ecookbook/issues'
+-  end
+-  
+-  def test_jump_should_not_redirect_to_inactive_tab
+-    get :show, :id => 3, :jump => 'documents'
+-    assert_response :success
+-    assert_template 'show'
+-  end
+-  
+-  def test_jump_should_not_redirect_to_unknown_tab
+-    get :show, :id => 3, :jump => 'foobar'
+-    assert_response :success
+-    assert_template 'show'
+-  end
+-  
+-  # A hook that is manually registered later
+-  class ProjectBasedTemplate < Redmine::Hook::ViewListener
+-    def view_layouts_base_html_head(context)
+-      # Adds a project stylesheet
+-      stylesheet_link_tag(context[:project].identifier) if context[:project]
+-    end
+-  end
+-  # Don't use this hook now
+-  Redmine::Hook.clear_listeners
+-  
+-  def test_hook_response
+-    Redmine::Hook.add_listener(ProjectBasedTemplate)
+-    get :show, :id => 1
+-    assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
+-                               :parent => {:tag => 'head'}
+-    
+-    Redmine::Hook.clear_listeners
+-  end
+-end
++# Redmine - project management software
++# Copyright (C) 2006-2008  Jean-Philippe Lang
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License
++# as published by the Free Software Foundation; either version 2
++# of the License, or (at your option) any later version.
++# 
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++# 
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++
++require File.dirname(__FILE__) + '/../test_helper'
++require 'projects_controller'
++
++# Re-raise errors caught by the controller.
++class ProjectsController; def rescue_action(e) raise e end; end
++
++class ProjectsControllerTest < ActionController::TestCase
++  fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
++           :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
++           :attachments
++
++  def setup
++    @controller = ProjectsController.new
++    @request    = ActionController::TestRequest.new
++    @response   = ActionController::TestResponse.new
++    @request.session[:user_id] = nil
++    Setting.default_language = 'en'
++  end
++  
++  def test_index_routing
++    assert_routing(
++      {:method => :get, :path => '/projects'},
++      :controller => 'projects', :action => 'index'
++    )
++  end
++  
++  def test_index
++    get :index
++    assert_response :success
++    assert_template 'index'
++    assert_not_nil assigns(:projects)
++    
++    assert_tag :ul, :child => {:tag => 'li',
++                               :descendant => {:tag => 'a', :content => 'eCookbook'},
++                               :child => { :tag => 'ul',
++                                           :descendant => { :tag => 'a',
++                                                            :content => 'Child of private child'
++                                                           }
++                                          }
++                               }
++                               
++    assert_no_tag :a, :content => /Private child of eCookbook/
++  end
++  
++  def test_index_atom_routing
++    assert_routing(
++      {:method => :get, :path => '/projects.atom'},
++      :controller => 'projects', :action => 'index', :format => 'atom'
++    )
++  end
++  
++  def test_index_atom
++    get :index, :format => 'atom'
++    assert_response :success
++    assert_template 'common/feed.atom.rxml'
++    assert_select 'feed>title', :text => 'Redmine: Latest projects'
++    assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_by(User.current))
++  end
++  
++  def test_add_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/new'},
++      :controller => 'projects', :action => 'add'
++    )
++    assert_recognizes(
++      {:controller => 'projects', :action => 'add'},
++      {:method => :post, :path => '/projects/new'}
++    )
++    assert_recognizes(
++      {:controller => 'projects', :action => 'add'},
++      {:method => :post, :path => '/projects'}
++    )
++  end
++  
++  def test_get_add
++    @request.session[:user_id] = 1
++    get :add
++    assert_response :success
++    assert_template 'add'
++  end
++  
++  def test_get_add_by_non_admin
++    @request.session[:user_id] = 2
++    get :add
++    assert_response :success
++    assert_template 'add'
++  end
++  
++  def test_post_add
++    @request.session[:user_id] = 1
++    post :add, :project => { :name => "blog", 
++                             :description => "weblog",
++                             :identifier => "blog",
++                             :is_public => 1,
++                             :custom_field_values => { '3' => 'Beta' }
++                            }
++    assert_redirected_to '/projects/blog/settings'
++    
++    project = Project.find_by_name('blog')
++    assert_kind_of Project, project
++    assert_equal 'weblog', project.description 
++    assert_equal true, project.is_public?
++  end
++  
++  def test_post_add_by_non_admin
++    @request.session[:user_id] = 2
++    post :add, :project => { :name => "blog", 
++                             :description => "weblog",
++                             :identifier => "blog",
++                             :is_public => 1,
++                             :custom_field_values => { '3' => 'Beta' }
++                            }
++    assert_redirected_to '/projects/blog/settings'
++    
++    project = Project.find_by_name('blog')
++    assert_kind_of Project, project
++    assert_equal 'weblog', project.description 
++    assert_equal true, project.is_public?
++    
++    # User should be added as a project member
++    assert User.find(2).member_of?(project)
++    assert_equal 1, project.members.size
++  end
++  
++  def test_show_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/test'},
++      :controller => 'projects', :action => 'show', :id => 'test'
++    )
++  end
++  
++  def test_show_by_id
++    get :show, :id => 1
++    assert_response :success
++    assert_template 'show'
++    assert_not_nil assigns(:project)
++  end
++
++  def test_show_by_identifier
++    get :show, :id => 'ecookbook'
++    assert_response :success
++    assert_template 'show'
++    assert_not_nil assigns(:project)
++    assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
++  end
++  
++  def test_show_should_not_fail_when_custom_values_are_nil
++    project = Project.find_by_identifier('ecookbook')
++    project.custom_values.first.update_attribute(:value, nil)
++    get :show, :id => 'ecookbook'
++    assert_response :success
++    assert_template 'show'
++    assert_not_nil assigns(:project)
++    assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
++  end
++  
++  def test_private_subprojects_hidden
++    get :show, :id => 'ecookbook'
++    assert_response :success
++    assert_template 'show'
++    assert_no_tag :tag => 'a', :content => /Private child/
++  end
++
++  def test_private_subprojects_visible
++    @request.session[:user_id] = 2 # manager who is a member of the private subproject
++    get :show, :id => 'ecookbook'
++    assert_response :success
++    assert_template 'show'
++    assert_tag :tag => 'a', :content => /Private child/
++  end
++  
++  def test_settings_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/4223/settings'},
++      :controller => 'projects', :action => 'settings', :id => '4223'
++    )
++    assert_routing(
++      {:method => :get, :path => '/projects/4223/settings/members'},
++      :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
++    )
++  end
++  
++  def test_settings
++    @request.session[:user_id] = 2 # manager
++    get :settings, :id => 1
++    assert_response :success
++    assert_template 'settings'
++  end
++  
++  def test_edit
++    @request.session[:user_id] = 2 # manager
++    post :edit, :id => 1, :project => {:name => 'Test changed name',
++                                       :issue_custom_field_ids => ['']}
++    assert_redirected_to 'projects/ecookbook/settings'
++    project = Project.find(1)
++    assert_equal 'Test changed name', project.name
++  end
++  
++  def test_add_version_routing
++    assert_routing(
++      {:method => :get, :path => 'projects/64/versions/new'},
++      :controller => 'projects', :action => 'add_version', :id => '64'
++    )
++    assert_routing(
++    #TODO: use PUT
++      {:method => :post, :path => 'projects/64/versions/new'},
++      :controller => 'projects', :action => 'add_version', :id => '64'
++    )
++  end
++  
++  def test_add_issue_category_routing
++    assert_routing(
++      {:method => :get, :path => 'projects/test/categories/new'},
++      :controller => 'projects', :action => 'add_issue_category', :id => 'test'
++    )
++    assert_routing(
++    #TODO: use PUT and update form
++      {:method => :post, :path => 'projects/64/categories/new'},
++      :controller => 'projects', :action => 'add_issue_category', :id => '64'
++    )
++  end
++  
++  def test_destroy_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/567/destroy'},
++      :controller => 'projects', :action => 'destroy', :id => '567'
++    )
++    assert_routing(
++    #TODO: use DELETE and update form
++      {:method => :post, :path => 'projects/64/destroy'},
++      :controller => 'projects', :action => 'destroy', :id => '64'
++    )
++  end
++  
++  def test_get_destroy
++    @request.session[:user_id] = 1 # admin
++    get :destroy, :id => 1
++    assert_response :success
++    assert_template 'destroy'
++    assert_not_nil Project.find_by_id(1)
++  end
++
++  def test_post_destroy
++    @request.session[:user_id] = 1 # admin
++    post :destroy, :id => 1, :confirm => 1
++    assert_redirected_to 'admin/projects'
++    assert_nil Project.find_by_id(1)
++  end
++  
++  def test_add_file
++    set_tmp_attachments_directory
++    @request.session[:user_id] = 2
++    Setting.notified_events = ['file_added']
++    ActionMailer::Base.deliveries.clear
++    
++    assert_difference 'Attachment.count' do
++      post :add_file, :id => 1, :version_id => '',
++           :attachments => {'1' => {'file' => test_uploaded_file('testfile.txt', 'text/plain')}}
++    end
++    assert_redirected_to 'projects/ecookbook/files'
++    a = Attachment.find(:first, :order => 'created_on DESC')
++    assert_equal 'testfile.txt', a.filename
++    assert_equal Project.find(1), a.container
++
++    mail = ActionMailer::Base.deliveries.last
++    assert_kind_of TMail::Mail, mail
++    assert_equal "[eCookbook] New file", mail.subject
++    assert mail.body.include?('testfile.txt')
++  end
++  
++  def test_add_file_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/33/files/new'},
++      :controller => 'projects', :action => 'add_file', :id => '33'
++    )
++    assert_routing(
++      {:method => :post, :path => '/projects/33/files/new'},
++      :controller => 'projects', :action => 'add_file', :id => '33'
++    )
++  end
++  
++  def test_add_version_file
++    set_tmp_attachments_directory
++    @request.session[:user_id] = 2
++    Setting.notified_events = ['file_added']
++    
++    assert_difference 'Attachment.count' do
++      post :add_file, :id => 1, :version_id => '2',
++           :attachments => {'1' => {'file' => test_uploaded_file('testfile.txt', 'text/plain')}}
++    end
++    assert_redirected_to 'projects/ecookbook/files'
++    a = Attachment.find(:first, :order => 'created_on DESC')
++    assert_equal 'testfile.txt', a.filename
++    assert_equal Version.find(2), a.container
++  end
++  
++  def test_list_files
++    get :list_files, :id => 1
++    assert_response :success
++    assert_template 'list_files'
++    assert_not_nil assigns(:containers)
++    
++    # file attached to the project
++    assert_tag :a, :content => 'project_file.zip',
++                   :attributes => { :href => '/attachments/download/8/project_file.zip' }
++    
++    # file attached to a project's version
++    assert_tag :a, :content => 'version_file.zip',
++                   :attributes => { :href => '/attachments/download/9/version_file.zip' }
++  end
++
++  def test_list_files_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/33/files'},
++      :controller => 'projects', :action => 'list_files', :id => '33'
++    )
++  end
++  
++  def test_changelog_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/44/changelog'},
++      :controller => 'projects', :action => 'changelog', :id => '44'
++    )
++  end
++  
++  def test_changelog
++    get :changelog, :id => 1
++    assert_response :success
++    assert_template 'changelog'
++    assert_not_nil assigns(:versions)
++  end
++  
++  def test_roadmap_routing
++    assert_routing(
++      {:method => :get, :path => 'projects/33/roadmap'},
++      :controller => 'projects', :action => 'roadmap', :id => '33'
++    )
++  end
++  
++  def test_roadmap
++    get :roadmap, :id => 1
++    assert_response :success
++    assert_template 'roadmap'
++    assert_not_nil assigns(:versions)
++    # Version with no date set appears
++    assert assigns(:versions).include?(Version.find(3))
++    # Completed version doesn't appear
++    assert !assigns(:versions).include?(Version.find(1))
++  end
++  
++  def test_roadmap_with_completed_versions
++    get :roadmap, :id => 1, :completed => 1
++    assert_response :success
++    assert_template 'roadmap'
++    assert_not_nil assigns(:versions)
++    # Version with no date set appears
++    assert assigns(:versions).include?(Version.find(3))
++    # Completed version appears
++    assert assigns(:versions).include?(Version.find(1))
++  end
++  
++  def test_project_activity_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/1/activity'},
++       :controller => 'projects', :action => 'activity', :id => '1'
++    )
++  end
++  
++  def test_project_activity_atom_routing
++    assert_routing(
++      {:method => :get, :path => '/projects/1/activity.atom'},
++       :controller => 'projects', :action => 'activity', :id => '1', :format => 'atom'
++    )    
++  end
++  
++  def test_project_activity
++    get :activity, :id => 1, :with_subprojects => 0
++    assert_response :success
++    assert_template 'activity'
++    assert_not_nil assigns(:events_by_day)
++    
++    assert_tag :tag => "h3", 
++               :content => /#{2.days.ago.to_date.day}/,
++               :sibling => { :tag => "dl",
++                 :child => { :tag => "dt",
++                   :attributes => { :class => /issue-edit/ },
++                   :child => { :tag => "a",
++                     :content => /(#{IssueStatus.find(2).name})/,
++                   }
++                 }
++               }
++  end
++  
++  def test_previous_project_activity
++    get :activity, :id => 1, :from => 3.days.ago.to_date
++    assert_response :success
++    assert_template 'activity'
++    assert_not_nil assigns(:events_by_day)
++               
++    assert_tag :tag => "h3", 
++               :content => /#{3.day.ago.to_date.day}/,
++               :sibling => { :tag => "dl",
++                 :child => { :tag => "dt",
++                   :attributes => { :class => /issue/ },
++                   :child => { :tag => "a",
++                     :content => /#{Issue.find(1).subject}/,
++                   }
++                 }
++               }
++  end
++  
++  def test_global_activity_routing
++    assert_routing({:method => :get, :path => '/activity'}, :controller => 'projects', :action => 'activity', :id => nil)
++  end
++  
++  def test_global_activity
++    get :activity
++    assert_response :success
++    assert_template 'activity'
++    assert_not_nil assigns(:events_by_day)
++    
++    assert_tag :tag => "h3", 
++               :content => /#{5.day.ago.to_date.day}/,
++               :sibling => { :tag => "dl",
++                 :child => { :tag => "dt",
++                   :attributes => { :class => /issue/ },
++                   :child => { :tag => "a",
++                     :content => /#{Issue.find(5).subject}/,
++                   }
++                 }
++               }
++  end
++  
++  def test_user_activity
++    get :activity, :user_id => 2
++    assert_response :success
++    assert_template 'activity'
++    assert_not_nil assigns(:events_by_day)
++    
++    assert_tag :tag => "h3", 
++               :content => /#{3.day.ago.to_date.day}/,
++               :sibling => { :tag => "dl",
++                 :child => { :tag => "dt",
++                   :attributes => { :class => /issue/ },
++                   :child => { :tag => "a",
++                     :content => /#{Issue.find(1).subject}/,
++                   }
++                 }
++               }
++  end
++  
++  def test_global_activity_atom_routing
++    assert_routing({:method => :get, :path => '/activity.atom'}, :controller => 'projects', :action => 'activity', :id => nil, :format => 'atom')
++  end
++  
++  def test_activity_atom_feed
++    get :activity, :format => 'atom'
++    assert_response :success
++    assert_template 'common/feed.atom.rxml'
++  end
++  
++  def test_archive_routing
++    assert_routing(
++    #TODO: use PUT to project path and modify form
++      {:method => :post, :path => 'projects/64/archive'},
++      :controller => 'projects', :action => 'archive', :id => '64'
++    )
++  end
++  
++  def test_archive
++    @request.session[:user_id] = 1 # admin
++    post :archive, :id => 1
++    assert_redirected_to 'admin/projects'
++    assert !Project.find(1).active?
++  end
++  
++  def test_unarchive_routing
++    assert_routing(
++    #TODO: use PUT to project path and modify form
++      {:method => :post, :path => '/projects/567/unarchive'},
++      :controller => 'projects', :action => 'unarchive', :id => '567'
++    )
++  end
++  
++  def test_unarchive
++    @request.session[:user_id] = 1 # admin
++    Project.find(1).archive
++    post :unarchive, :id => 1
++    assert_redirected_to 'admin/projects'
++    assert Project.find(1).active?
++  end
++  
++  def test_project_breadcrumbs_should_be_limited_to_3_ancestors
++    CustomField.delete_all
++    parent = nil
++    6.times do |i|
++      p = Project.create!(:name => "Breadcrumbs #{i}", :identifier => "breadcrumbs-#{i}")
++      p.set_parent!(parent)
++      get :show, :id => p
++      assert_tag :h1, :parent => { :attributes => {:id => 'header'}},
++                      :children => { :count => [i, 3].min,
++                                     :only => { :tag => 'a' } }
++                                     
++      parent = p
++    end
++  end
++
++  def test_copy_with_project
++    @request.session[:user_id] = 1 # admin
++    get :copy, :id => 1
++    assert_response :success
++    assert_template 'copy'
++    assert assigns(:project)
++    assert_equal Project.find(1).description, assigns(:project).description
++    assert_nil assigns(:project).id
++  end
++
++  def test_copy_without_project
++    @request.session[:user_id] = 1 # admin
++    get :copy
++    assert_response :redirect
++    assert_redirected_to :controller => 'admin', :action => 'projects'
++  end
++
++  def test_jump_should_redirect_to_active_tab
++    get :show, :id => 1, :jump => 'issues'
++    assert_redirected_to 'projects/ecookbook/issues'
++  end
++  
++  def test_jump_should_not_redirect_to_inactive_tab
++    get :show, :id => 3, :jump => 'documents'
++    assert_response :success
++    assert_template 'show'
++  end
++  
++  def test_jump_should_not_redirect_to_unknown_tab
++    get :show, :id => 3, :jump => 'foobar'
++    assert_response :success
++    assert_template 'show'
++  end
++  
++  # A hook that is manually registered later
++  class ProjectBasedTemplate < Redmine::Hook::ViewListener
++    def view_layouts_base_html_head(context)
++      # Adds a project stylesheet
++      stylesheet_link_tag(context[:project].identifier) if context[:project]
++    end
++  end
++  # Don't use this hook now
++  Redmine::Hook.clear_listeners
++  
++  def test_hook_response
++    Redmine::Hook.add_listener(ProjectBasedTemplate)
++    get :show, :id => 1
++    assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
++                               :parent => {:tag => 'head'}
++    
++    Redmine::Hook.clear_listeners
++  end
++end
+Index: trunk/app/views/projects/show.rhtml
+===================================================================
+--- trunk/app/views/projects/show.rhtml	(revision 2893)
++++ trunk/app/views/projects/show.rhtml	(revision 2894)
+@@ -9,7 +9,7 @@
+ 	    <%= @subprojects.collect{|p| link_to(h(p), :action => 'show', :id => p)}.join(", ") %></li>
+   <% end %>
+ 	<% @project.custom_values.each do |custom_value| %>
+-	<% if !custom_value.value.empty? %>
++	<% if !custom_value.value.blank? %>
+ 	   <li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li>
+ 	<% end %>
+ 	<% end %>
+Index: trunk/app/views/account/show.rhtml
+===================================================================
+--- trunk/app/views/account/show.rhtml	(revision 2893)
++++ trunk/app/views/account/show.rhtml	(revision 2894)
+@@ -10,7 +10,7 @@
+ 		<li><%=l(:field_mail)%>: <%= mail_to(h(@user.mail), nil, :encode => 'javascript') %></li>
+ 	<% end %>
+ 	<% for custom_value in @custom_values %>
+-	<% if !custom_value.value.empty? %>
++	<% if !custom_value.value.blank? %>
+     <li><%=h custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li>
+ 	<% end %>
+ 	<% end %>

Modified: trunk/redmine/debian/patches/series
===================================================================
--- trunk/redmine/debian/patches/series	2009-09-22 22:56:35 UTC (rev 4192)
+++ trunk/redmine/debian/patches/series	2009-09-22 22:56:39 UTC (rev 4193)
@@ -1,3 +1,7 @@
 01_paths.patch
 changeset_r2888.diff
 changeset_r2889.diff
+changeset_r2891.diff
+changeset_r2892.diff
+changeset_r2893.diff
+changeset_r2894.diff




More information about the Pkg-ruby-extras-commits mailing list