diff options
-rw-r--r-- | app/controllers/projects_controller.rb | 1 | ||||
-rw-r--r-- | app/models/journal.rb | 9 | ||||
-rw-r--r-- | app/models/project.rb | 12 | ||||
-rw-r--r-- | app/views/projects/activity.rhtml | 2 | ||||
-rw-r--r-- | test/fixtures/issues.yml | 6 | ||||
-rw-r--r-- | test/fixtures/journals.yml | 2 | ||||
-rw-r--r-- | test/functional/projects_controller_test.rb | 20 | ||||
-rw-r--r-- | test/unit/journal_test.rb | 39 | ||||
-rw-r--r-- | test/unit/project_test.rb | 223 |
9 files changed, 199 insertions, 115 deletions
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index b4ffe57e8..f67a1caa2 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -405,6 +405,7 @@ class ProjectsController < ApplicationController if @scope.include?('issues') @events += @project.issues.find(:all, :include => [:author, :tracker], :conditions => ["#{Issue.table_name}.created_on>=? and #{Issue.table_name}.created_on<=?", @date_from, @date_to] ) + @events += @project.issues_status_changes(@date_from, @date_to) end if @scope.include?('news') diff --git a/app/models/journal.rb b/app/models/journal.rb index 331d7a729..64483d21d 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -29,12 +29,19 @@ class Journal < ActiveRecord::Base :project_key => "#{Issue.table_name}.project_id", :date_column => "#{Issue.table_name}.created_on" - acts_as_event :title => Proc.new {|o| "#{o.issue.tracker.name} ##{o.issue.id}: #{o.issue.subject}"}, + acts_as_event :title => Proc.new {|o| "#{o.issue.tracker.name} ##{o.issue.id}: #{o.issue.subject}" + ((s = o.new_status) ? " (#{s})" : '') }, :description => :notes, + :author => :user, :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id}} def save # Do not save an empty journal (details.empty? && notes.blank?) ? false : super end + + # Returns the new status if the journal contains a status change, otherwise nil + def new_status + c = details.detect {|detail| detail.prop_key == 'status_id'} + (c && c.value) ? IssueStatus.find_by_id(c.value.to_i) : nil + end end diff --git a/app/models/project.rb b/app/models/project.rb index 8f7e03a7c..152808c14 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -75,7 +75,17 @@ class Project < ActiveRecord::Base yield end end - + + # Return all issues status changes for the project between the 2 given dates + def issues_status_changes(from, to) + Journal.find(:all, :include => [:issue, :details, :user], + :conditions => ["#{Journal.table_name}.journalized_type = 'Issue'" + + " AND #{Issue.table_name}.project_id = ?" + + " AND #{JournalDetail.table_name}.prop_key = 'status_id'" + + " AND #{Journal.table_name}.created_on BETWEEN ? AND ?", + id, from, to+1]) + end + # returns latest created projects # non public projects will be returned only if user is a member of those def self.latest(user=nil, count=5) diff --git a/app/views/projects/activity.rhtml b/app/views/projects/activity.rhtml index a2f5296f0..cc54eac95 100644 --- a/app/views/projects/activity.rhtml +++ b/app/views/projects/activity.rhtml @@ -6,7 +6,7 @@ <% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| %> <li><p><%= e.event_datetime.strftime("%H:%M") %> <%= link_to truncate(e.event_title, 100), e.event_url %><br /> <% unless e.event_description.blank? %><em><%= truncate(e.event_description, 500) %></em><br /><% end %> - <span class="author"><%= e.event_author if e.respond_to?(:author) %></span></p></li> + <span class="author"><%= e.event_author if e.respond_to?(:event_author) %></span></p></li> <% end %> </ul> <% end %> diff --git a/test/fixtures/issues.yml b/test/fixtures/issues.yml index ef4ef9de8..6649849d8 100644 --- a/test/fixtures/issues.yml +++ b/test/fixtures/issues.yml @@ -1,8 +1,8 @@ ---
issues_001:
- created_on: 2006-07-19 21:02:17 +02:00
+ created_on: <%= 3.days.ago.to_date.to_s(:db) %>
project_id: 1
- updated_on: 2006-07-19 21:04:30 +02:00
+ updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
priority_id: 4
subject: Can't print recipes
id: 1
@@ -55,4 +55,4 @@ issues_004: assigned_to_id:
author_id: 2
status_id: 1
-
\ No newline at end of file +
diff --git a/test/fixtures/journals.yml b/test/fixtures/journals.yml index 49aab14d7..0de938168 100644 --- a/test/fixtures/journals.yml +++ b/test/fixtures/journals.yml @@ -1,6 +1,6 @@ ---
journals_001:
- created_on: 2007-01-26 19:58:40 +01:00
+ created_on: <%= 2.days.ago.to_date.to_s(:db) %>
notes: "Journal notes"
id: 1
journalized_type: Issue
diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 002dc1e4d..e6c06cf56 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -22,7 +22,7 @@ require 'projects_controller' class ProjectsController; def rescue_action(e) raise e end; end class ProjectsControllerTest < Test::Unit::TestCase - fixtures :projects, :users, :roles, :members, :issues, :enabled_modules, :enumerations + fixtures :projects, :users, :roles, :members, :issues, :journals, :journal_details, :trackers, :issue_statuses, :enabled_modules, :enumerations def setup @controller = ProjectsController.new @@ -93,6 +93,24 @@ class ProjectsControllerTest < Test::Unit::TestCase 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 => "ul", + :child => { :tag => "li", + :child => { :tag => "p", + :content => /(#{IssueStatus.find(2).name})/, + } + } + } + assert_tag :tag => "h3", + :content => /#{3.day.ago.to_date.day}/, + :sibling => { :tag => "ul", :child => { :tag => "li", + :child => { :tag => "p", + :content => /#{Issue.find(1).subject}/, + } + } + } end def test_archive diff --git a/test/unit/journal_test.rb b/test/unit/journal_test.rb new file mode 100644 index 000000000..b177f3198 --- /dev/null +++ b/test/unit/journal_test.rb @@ -0,0 +1,39 @@ +# redMine - project management software +# Copyright (C) 2006-2007 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' + +class JournalTest < Test::Unit::TestCase + fixtures :issues, :issue_statuses, :journals, :journal_details + + def setup + @journal = Journal.find 1 + end + + def test_journalized_is_an_issue + issue = @journal.issue + assert_kind_of Issue, issue + assert_equal 1, issue.id + end + + def test_new_status + status = @journal.new_status + assert_not_nil status + assert_kind_of IssueStatus, status + assert_equal 2, status.id + end +end diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index 14612d306..a8cf46e4f 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -1,107 +1,116 @@ -# redMine - project management software -# Copyright (C) 2006-2007 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' - -class ProjectTest < Test::Unit::TestCase - fixtures :projects - - def setup - @ecookbook = Project.find(1) - @ecookbook_sub1 = Project.find(3) - end - - def test_truth - assert_kind_of Project, @ecookbook - assert_equal "eCookbook", @ecookbook.name - end - - def test_update - assert_equal "eCookbook", @ecookbook.name - @ecookbook.name = "eCook" - assert @ecookbook.save, @ecookbook.errors.full_messages.join("; ") - @ecookbook.reload - assert_equal "eCook", @ecookbook.name - end - - def test_validate - @ecookbook.name = "" - assert !@ecookbook.save - assert_equal 1, @ecookbook.errors.count - assert_equal "activerecord_error_blank", @ecookbook.errors.on(:name) - end - - def test_public_projects - public_projects = Project.find(:all, :conditions => ["is_public=?", true]) - assert_equal 3, public_projects.length - assert_equal true, public_projects[0].is_public? - end - - def test_archive - user = @ecookbook.members.first.user - @ecookbook.archive - @ecookbook.reload - - assert !@ecookbook.active? - assert !user.projects.include?(@ecookbook) - # Subproject are also archived - assert !@ecookbook.children.empty? - assert @ecookbook.active_children.empty? - end - - def test_unarchive - user = @ecookbook.members.first.user - @ecookbook.archive - # A subproject of an archived project can not be unarchived - assert !@ecookbook_sub1.unarchive - - # Unarchive project - assert @ecookbook.unarchive - @ecookbook.reload - assert @ecookbook.active? - assert user.projects.include?(@ecookbook) - # Subproject can now be unarchived - @ecookbook_sub1.reload - assert @ecookbook_sub1.unarchive - end - - def test_destroy - @ecookbook.destroy - assert_raise(ActiveRecord::RecordNotFound) { Project.find(@ecookbook.id) } - end - - def test_subproject_ok - sub = Project.find(2) - sub.parent = @ecookbook - assert sub.save - assert_equal @ecookbook.id, sub.parent.id - @ecookbook.reload - assert_equal 3, @ecookbook.children.size - end - - def test_subproject_invalid - sub = Project.find(2) - sub.parent = @ecookbook_sub1 - assert !sub.save - end - - def test_subproject_invalid_2 - sub = @ecookbook - sub.parent = Project.find(2) - assert !sub.save - end -end +# redMine - project management software
+# Copyright (C) 2006-2007 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'
+
+class ProjectTest < Test::Unit::TestCase
+ fixtures :projects, :issues, :issue_statuses, :journals, :journal_details
+
+ def setup
+ @ecookbook = Project.find(1)
+ @ecookbook_sub1 = Project.find(3)
+ end
+
+ def test_truth
+ assert_kind_of Project, @ecookbook
+ assert_equal "eCookbook", @ecookbook.name
+ end
+
+ def test_update
+ assert_equal "eCookbook", @ecookbook.name
+ @ecookbook.name = "eCook"
+ assert @ecookbook.save, @ecookbook.errors.full_messages.join("; ")
+ @ecookbook.reload
+ assert_equal "eCook", @ecookbook.name
+ end
+
+ def test_validate
+ @ecookbook.name = ""
+ assert !@ecookbook.save
+ assert_equal 1, @ecookbook.errors.count
+ assert_equal "activerecord_error_blank", @ecookbook.errors.on(:name)
+ end
+
+ def test_public_projects
+ public_projects = Project.find(:all, :conditions => ["is_public=?", true])
+ assert_equal 3, public_projects.length
+ assert_equal true, public_projects[0].is_public?
+ end
+
+ def test_archive
+ user = @ecookbook.members.first.user
+ @ecookbook.archive
+ @ecookbook.reload
+
+ assert !@ecookbook.active?
+ assert !user.projects.include?(@ecookbook)
+ # Subproject are also archived
+ assert !@ecookbook.children.empty?
+ assert @ecookbook.active_children.empty?
+ end
+
+ def test_unarchive
+ user = @ecookbook.members.first.user
+ @ecookbook.archive
+ # A subproject of an archived project can not be unarchived
+ assert !@ecookbook_sub1.unarchive
+
+ # Unarchive project
+ assert @ecookbook.unarchive
+ @ecookbook.reload
+ assert @ecookbook.active?
+ assert user.projects.include?(@ecookbook)
+ # Subproject can now be unarchived
+ @ecookbook_sub1.reload
+ assert @ecookbook_sub1.unarchive
+ end
+
+ def test_destroy
+ @ecookbook.destroy
+ assert_raise(ActiveRecord::RecordNotFound) { Project.find(@ecookbook.id) }
+ end
+
+ def test_subproject_ok
+ sub = Project.find(2)
+ sub.parent = @ecookbook
+ assert sub.save
+ assert_equal @ecookbook.id, sub.parent.id
+ @ecookbook.reload
+ assert_equal 3, @ecookbook.children.size
+ end
+
+ def test_subproject_invalid
+ sub = Project.find(2)
+ sub.parent = @ecookbook_sub1
+ assert !sub.save
+ end
+
+ def test_subproject_invalid_2
+ sub = @ecookbook
+ sub.parent = Project.find(2)
+ assert !sub.save
+ end
+
+ def test_issues_status_changes
+ journals = @ecookbook.issues_status_changes 3.days.ago.to_date, Date.today
+ assert_equal 1, journals.size
+ assert_kind_of Journal, journals.first
+
+ journals = @ecookbook.issues_status_changes 30.days.ago.to_date, 10.days.ago.to_date
+ assert_equal 0, journals.size
+ end
+end
|