@@ -1,81 +1,82 | |||
|
1 | 1 | # redMine - project management software |
|
2 | 2 | # Copyright (C) 2006-2007 Jean-Philippe Lang |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
|
6 | 6 | # as published by the Free Software Foundation; either version 2 |
|
7 | 7 | # of the License, or (at your option) any later version. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU General Public License |
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | class BoardsController < ApplicationController |
|
19 | 19 | before_filter :find_project, :authorize |
|
20 | 20 | |
|
21 | 21 | helper :messages |
|
22 | 22 | include MessagesHelper |
|
23 | 23 | helper :sort |
|
24 | 24 | include SortHelper |
|
25 | 25 | helper :watchers |
|
26 | 26 | include WatchersHelper |
|
27 | 27 | |
|
28 | 28 | def index |
|
29 | 29 | @boards = @project.boards |
|
30 | 30 | # show the board if there is only one |
|
31 | 31 | if @boards.size == 1 |
|
32 | 32 | @board = @boards.first |
|
33 | 33 | show |
|
34 | 34 | end |
|
35 | 35 | end |
|
36 | 36 | |
|
37 | 37 | def show |
|
38 | 38 | sort_init 'updated_on', 'desc' |
|
39 | 39 | sort_update 'created_on' => "#{Message.table_name}.created_on", |
|
40 | 40 | 'replies' => "#{Message.table_name}.replies_count", |
|
41 | 41 | 'updated_on' => "#{Message.table_name}.updated_on" |
|
42 | 42 | |
|
43 | 43 | @topic_count = @board.topics.count |
|
44 | 44 | @topic_pages = Paginator.new self, @topic_count, per_page_option, params['page'] |
|
45 | 45 | @topics = @board.topics.find :all, :order => ["#{Message.table_name}.sticky DESC", sort_clause].compact.join(', '), |
|
46 | 46 | :include => [:author, {:last_reply => :author}], |
|
47 | 47 | :limit => @topic_pages.items_per_page, |
|
48 | 48 | :offset => @topic_pages.current.offset |
|
49 | @message = Message.new | |
|
49 | 50 | render :action => 'show', :layout => !request.xhr? |
|
50 | 51 | end |
|
51 | 52 | |
|
52 | 53 | verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index } |
|
53 | 54 | |
|
54 | 55 | def new |
|
55 | 56 | @board = Board.new(params[:board]) |
|
56 | 57 | @board.project = @project |
|
57 | 58 | if request.post? && @board.save |
|
58 | 59 | flash[:notice] = l(:notice_successful_create) |
|
59 | 60 | redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards' |
|
60 | 61 | end |
|
61 | 62 | end |
|
62 | 63 | |
|
63 | 64 | def edit |
|
64 | 65 | if request.post? && @board.update_attributes(params[:board]) |
|
65 | 66 | redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards' |
|
66 | 67 | end |
|
67 | 68 | end |
|
68 | 69 | |
|
69 | 70 | def destroy |
|
70 | 71 | @board.destroy |
|
71 | 72 | redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'boards' |
|
72 | 73 | end |
|
73 | 74 | |
|
74 | 75 | private |
|
75 | 76 | def find_project |
|
76 | 77 | @project = Project.find(params[:project_id]) |
|
77 | 78 | @board = @project.boards.find(params[:id]) if params[:id] |
|
78 | 79 | rescue ActiveRecord::RecordNotFound |
|
79 | 80 | render_404 |
|
80 | 81 | end |
|
81 | 82 | end |
@@ -1,125 +1,126 | |||
|
1 | 1 | # redMine - project management software |
|
2 | 2 | # Copyright (C) 2006-2007 Jean-Philippe Lang |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
|
6 | 6 | # as published by the Free Software Foundation; either version 2 |
|
7 | 7 | # of the License, or (at your option) any later version. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU General Public License |
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | class MessagesController < ApplicationController |
|
19 | 19 | menu_item :boards |
|
20 | 20 | before_filter :find_board, :only => [:new, :preview] |
|
21 | 21 | before_filter :find_message, :except => [:new, :preview] |
|
22 | 22 | before_filter :authorize, :except => [:preview, :edit, :destroy] |
|
23 | 23 | |
|
24 | 24 | verify :method => :post, :only => [ :reply, :destroy ], :redirect_to => { :action => :show } |
|
25 | 25 | verify :xhr => true, :only => :quote |
|
26 | 26 | |
|
27 | 27 | helper :watchers |
|
28 | 28 | helper :attachments |
|
29 | 29 | include AttachmentsHelper |
|
30 | 30 | |
|
31 | 31 | # Show a topic and its replies |
|
32 | 32 | def show |
|
33 | 33 | @replies = @topic.children.find(:all, :include => [:author, :attachments, {:board => :project}]) |
|
34 | 34 | @replies.reverse! if User.current.wants_comments_in_reverse_order? |
|
35 | 35 | @reply = Message.new(:subject => "RE: #{@message.subject}") |
|
36 | 36 | render :action => "show", :layout => false if request.xhr? |
|
37 | 37 | end |
|
38 | 38 | |
|
39 | 39 | # Create a new topic |
|
40 | 40 | def new |
|
41 | 41 | @message = Message.new(params[:message]) |
|
42 | 42 | @message.author = User.current |
|
43 | 43 | @message.board = @board |
|
44 | 44 | if params[:message] && User.current.allowed_to?(:edit_messages, @project) |
|
45 | 45 | @message.locked = params[:message]['locked'] |
|
46 | 46 | @message.sticky = params[:message]['sticky'] |
|
47 | 47 | end |
|
48 | 48 | if request.post? && @message.save |
|
49 | 49 | attach_files(@message, params[:attachments]) |
|
50 | 50 | redirect_to :action => 'show', :id => @message |
|
51 | 51 | end |
|
52 | 52 | end |
|
53 | 53 | |
|
54 | 54 | # Reply to a topic |
|
55 | 55 | def reply |
|
56 | 56 | @reply = Message.new(params[:reply]) |
|
57 | 57 | @reply.author = User.current |
|
58 | 58 | @reply.board = @board |
|
59 | 59 | @topic.children << @reply |
|
60 | 60 | if !@reply.new_record? |
|
61 | 61 | attach_files(@reply, params[:attachments]) |
|
62 | 62 | end |
|
63 | 63 | redirect_to :action => 'show', :id => @topic |
|
64 | 64 | end |
|
65 | 65 | |
|
66 | 66 | # Edit a message |
|
67 | 67 | def edit |
|
68 | 68 | render_403 and return false unless @message.editable_by?(User.current) |
|
69 | 69 | if params[:message] |
|
70 | 70 | @message.locked = params[:message]['locked'] |
|
71 | 71 | @message.sticky = params[:message]['sticky'] |
|
72 | 72 | end |
|
73 | 73 | if request.post? && @message.update_attributes(params[:message]) |
|
74 | 74 | attach_files(@message, params[:attachments]) |
|
75 | 75 | flash[:notice] = l(:notice_successful_update) |
|
76 | redirect_to :action => 'show', :id => @topic | |
|
76 | @message.reload | |
|
77 | redirect_to :action => 'show', :board_id => @message.board, :id => @message.root | |
|
77 | 78 | end |
|
78 | 79 | end |
|
79 | 80 | |
|
80 | 81 | # Delete a messages |
|
81 | 82 | def destroy |
|
82 | 83 | render_403 and return false unless @message.destroyable_by?(User.current) |
|
83 | 84 | @message.destroy |
|
84 | 85 | redirect_to @message.parent.nil? ? |
|
85 | 86 | { :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } : |
|
86 | 87 | { :action => 'show', :id => @message.parent } |
|
87 | 88 | end |
|
88 | 89 | |
|
89 | 90 | def quote |
|
90 | 91 | user = @message.author |
|
91 | 92 | text = @message.content |
|
92 | 93 | content = "#{ll(Setting.default_language, :text_user_wrote, user)}\\n> " |
|
93 | 94 | content << text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub('"', '\"').gsub(/(\r?\n|\r\n?)/, "\\n> ") + "\\n\\n" |
|
94 | 95 | render(:update) { |page| |
|
95 | 96 | page.<< "$('message_content').value = \"#{content}\";" |
|
96 | 97 | page.show 'reply' |
|
97 | 98 | page << "Form.Element.focus('message_content');" |
|
98 | 99 | page << "Element.scrollTo('reply');" |
|
99 | 100 | page << "$('message_content').scrollTop = $('message_content').scrollHeight - $('message_content').clientHeight;" |
|
100 | 101 | } |
|
101 | 102 | end |
|
102 | 103 | |
|
103 | 104 | def preview |
|
104 | 105 | message = @board.messages.find_by_id(params[:id]) |
|
105 | 106 | @attachements = message.attachments if message |
|
106 | 107 | @text = (params[:message] || params[:reply])[:content] |
|
107 | 108 | render :partial => 'common/preview' |
|
108 | 109 | end |
|
109 | 110 | |
|
110 | 111 | private |
|
111 | 112 | def find_message |
|
112 | 113 | find_board |
|
113 | 114 | @message = @board.messages.find(params[:id], :include => :parent) |
|
114 | 115 | @topic = @message.root |
|
115 | 116 | rescue ActiveRecord::RecordNotFound |
|
116 | 117 | render_404 |
|
117 | 118 | end |
|
118 | 119 | |
|
119 | 120 | def find_board |
|
120 | 121 | @board = Board.find(params[:board_id], :include => :project) |
|
121 | 122 | @project = @board.project |
|
122 | 123 | rescue ActiveRecord::RecordNotFound |
|
123 | 124 | render_404 |
|
124 | 125 | end |
|
125 | 126 | end |
@@ -1,29 +1,42 | |||
|
1 | 1 | # redMine - project management software |
|
2 | 2 | # Copyright (C) 2006-2007 Jean-Philippe Lang |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
|
6 | 6 | # as published by the Free Software Foundation; either version 2 |
|
7 | 7 | # of the License, or (at your option) any later version. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU General Public License |
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | class Board < ActiveRecord::Base |
|
19 | 19 | belongs_to :project |
|
20 | 20 | has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC" |
|
21 | 21 | has_many :messages, :dependent => :delete_all, :order => "#{Message.table_name}.created_on DESC" |
|
22 | 22 | belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id |
|
23 | 23 | acts_as_list :scope => :project_id |
|
24 | 24 | acts_as_watchable |
|
25 | 25 | |
|
26 | 26 | validates_presence_of :name, :description |
|
27 | 27 | validates_length_of :name, :maximum => 30 |
|
28 | 28 | validates_length_of :description, :maximum => 255 |
|
29 | ||
|
30 | def reset_counters! | |
|
31 | self.class.reset_counters!(id) | |
|
32 | end | |
|
33 | ||
|
34 | # Updates topics_count, messages_count and last_message_id attributes for +board_id+ | |
|
35 | def self.reset_counters!(board_id) | |
|
36 | board_id = board_id.to_i | |
|
37 | update_all("topics_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id} AND parent_id IS NULL)," + | |
|
38 | " messages_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id})," + | |
|
39 | " last_message_id = (SELECT MAX(id) FROM #{Message.table_name} WHERE board_id=#{board_id})", | |
|
40 | ["id = ?", board_id]) | |
|
41 | end | |
|
29 | 42 | end |
@@ -1,89 +1,90 | |||
|
1 | 1 | # redMine - project management software |
|
2 | 2 | # Copyright (C) 2006-2007 Jean-Philippe Lang |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
|
6 | 6 | # as published by the Free Software Foundation; either version 2 |
|
7 | 7 | # of the License, or (at your option) any later version. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU General Public License |
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | class Message < ActiveRecord::Base |
|
19 | 19 | belongs_to :board |
|
20 | 20 | belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' |
|
21 | 21 | acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC" |
|
22 | 22 | acts_as_attachable |
|
23 | 23 | belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id' |
|
24 | 24 | |
|
25 | 25 | acts_as_searchable :columns => ['subject', 'content'], |
|
26 | 26 | :include => {:board => :project}, |
|
27 | 27 | :project_key => 'project_id', |
|
28 | 28 | :date_column => "#{table_name}.created_on" |
|
29 | 29 | acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"}, |
|
30 | 30 | :description => :content, |
|
31 | 31 | :type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'}, |
|
32 | 32 | :url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} : |
|
33 | 33 | {:id => o.parent_id, :anchor => "message-#{o.id}"})} |
|
34 | 34 | |
|
35 | 35 | acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]}, |
|
36 | 36 | :author_key => :author_id |
|
37 | 37 | acts_as_watchable |
|
38 | 38 | |
|
39 | 39 | attr_protected :locked, :sticky |
|
40 | validates_presence_of :subject, :content | |
|
40 | validates_presence_of :board, :subject, :content | |
|
41 | 41 | validates_length_of :subject, :maximum => 255 |
|
42 | 42 | |
|
43 | 43 | after_create :add_author_as_watcher |
|
44 | 44 | |
|
45 | 45 | def validate_on_create |
|
46 | 46 | # Can not reply to a locked topic |
|
47 | 47 | errors.add_to_base 'Topic is locked' if root.locked? && self != root |
|
48 | 48 | end |
|
49 | 49 | |
|
50 | 50 | def after_create |
|
51 | board.update_attribute(:last_message_id, self.id) | |
|
52 | board.increment! :messages_count | |
|
53 | 51 | if parent |
|
54 | 52 | parent.reload.update_attribute(:last_reply_id, self.id) |
|
55 |
e |
|
|
56 |
|
|
|
53 | end | |
|
54 | board.reset_counters! | |
|
55 | end | |
|
56 | ||
|
57 | def after_update | |
|
58 | if board_id_changed? | |
|
59 | Message.update_all("board_id = #{board_id}", ["id = ? OR parent_id = ?", root.id, root.id]) | |
|
60 | Board.reset_counters!(board_id_was) | |
|
61 | Board.reset_counters!(board_id) | |
|
57 | 62 | end |
|
58 | 63 | end |
|
59 | 64 | |
|
60 | 65 | def after_destroy |
|
61 | # The following line is required so that the previous counter | |
|
62 | # updates (due to children removal) are not overwritten | |
|
63 | board.reload | |
|
64 | board.decrement! :messages_count | |
|
65 | board.decrement! :topics_count unless parent | |
|
66 | board.reset_counters! | |
|
66 | 67 | end |
|
67 | 68 | |
|
68 | 69 | def sticky? |
|
69 | 70 | sticky == 1 |
|
70 | 71 | end |
|
71 | 72 | |
|
72 | 73 | def project |
|
73 | 74 | board.project |
|
74 | 75 | end |
|
75 | 76 | |
|
76 | 77 | def editable_by?(usr) |
|
77 | 78 | usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))) |
|
78 | 79 | end |
|
79 | 80 | |
|
80 | 81 | def destroyable_by?(usr) |
|
81 | 82 | usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project))) |
|
82 | 83 | end |
|
83 | 84 | |
|
84 | 85 | private |
|
85 | 86 | |
|
86 | 87 | def add_author_as_watcher |
|
87 | 88 | Watcher.create(:watchable => self.root, :user => author) |
|
88 | 89 | end |
|
89 | 90 | end |
@@ -1,21 +1,26 | |||
|
1 | 1 | <%= error_messages_for 'message' %> |
|
2 | 2 | <% replying ||= false %> |
|
3 | 3 | |
|
4 | 4 | <div class="box"> |
|
5 | 5 | <!--[form:message]--> |
|
6 | 6 | <p><label><%= l(:field_subject) %></label><br /> |
|
7 | 7 | <%= f.text_field :subject, :size => 120 %> |
|
8 | 8 | |
|
9 | 9 | <% if !replying && User.current.allowed_to?(:edit_messages, @project) %> |
|
10 | 10 | <label><%= f.check_box :sticky %> Sticky</label> |
|
11 | 11 | <label><%= f.check_box :locked %> Locked</label> |
|
12 | 12 | <% end %> |
|
13 | 13 | </p> |
|
14 | 14 | |
|
15 | <% if !replying && !@message.new_record? && User.current.allowed_to?(:edit_messages, @project) %> | |
|
16 | <p><label><%= l(:label_board) %></label><br /> | |
|
17 | <%= f.select :board_id, @project.boards.collect {|b| [b.name, b.id]} %></p> | |
|
18 | <% end %> | |
|
19 | ||
|
15 | 20 | <p><%= f.text_area :content, :cols => 80, :rows => 15, :class => 'wiki-edit', :id => 'message_content' %></p> |
|
16 | 21 | <%= wikitoolbar_for 'message_content' %> |
|
17 | 22 | <!--[eoform:message]--> |
|
18 | 23 | |
|
19 | 24 | <p><%= l(:label_attachment_plural) %><br /> |
|
20 | 25 | <%= render :partial => 'attachments/form' %></p> |
|
21 | 26 | </div> |
@@ -1,19 +1,19 | |||
|
1 | 1 | --- |
|
2 | 2 | boards_001: |
|
3 | 3 | name: Help |
|
4 | 4 | project_id: 1 |
|
5 | 5 | topics_count: 2 |
|
6 | 6 | id: 1 |
|
7 | 7 | description: Help board |
|
8 | 8 | position: 1 |
|
9 |
last_message_id: |
|
|
10 |
messages_count: |
|
|
9 | last_message_id: 6 | |
|
10 | messages_count: 6 | |
|
11 | 11 | boards_002: |
|
12 | 12 | name: Discussion |
|
13 | 13 | project_id: 1 |
|
14 | 14 | topics_count: 0 |
|
15 | 15 | id: 2 |
|
16 | 16 | description: Discussion board |
|
17 | 17 | position: 2 |
|
18 | 18 | last_message_id: |
|
19 | 19 | messages_count: 0 |
@@ -1,97 +1,131 | |||
|
1 | # Redmine - project management software | |
|
2 | # Copyright (C) 2006-2009 Jean-Philippe Lang | |
|
3 | # | |
|
4 | # This program is free software; you can redistribute it and/or | |
|
5 | # modify it under the terms of the GNU General Public License | |
|
6 | # as published by the Free Software Foundation; either version 2 | |
|
7 | # of the License, or (at your option) any later version. | |
|
8 | # | |
|
9 | # This program is distributed in the hope that it will be useful, | |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
12 | # GNU General Public License for more details. | |
|
13 | # | |
|
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 | |
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
|
17 | ||
|
1 | 18 | require File.dirname(__FILE__) + '/../test_helper' |
|
2 | 19 | |
|
3 | 20 | class MessageTest < Test::Unit::TestCase |
|
4 | 21 | fixtures :projects, :roles, :members, :boards, :messages, :users, :watchers |
|
5 | 22 | |
|
6 | 23 | def setup |
|
7 | 24 | @board = Board.find(1) |
|
8 | 25 | @user = User.find(1) |
|
9 | 26 | end |
|
10 | 27 | |
|
11 | 28 | def test_create |
|
12 | 29 | topics_count = @board.topics_count |
|
13 | 30 | messages_count = @board.messages_count |
|
14 | 31 | |
|
15 | 32 | message = Message.new(:board => @board, :subject => 'Test message', :content => 'Test message content', :author => @user) |
|
16 | 33 | assert message.save |
|
17 | 34 | @board.reload |
|
18 | 35 | # topics count incremented |
|
19 | 36 | assert_equal topics_count+1, @board[:topics_count] |
|
20 | 37 | # messages count incremented |
|
21 | 38 | assert_equal messages_count+1, @board[:messages_count] |
|
22 | 39 | assert_equal message, @board.last_message |
|
23 | 40 | # author should be watching the message |
|
24 | 41 | assert message.watched_by?(@user) |
|
25 | 42 | end |
|
26 | 43 | |
|
27 | 44 | def test_reply |
|
28 | 45 | topics_count = @board.topics_count |
|
29 | 46 | messages_count = @board.messages_count |
|
30 | 47 | @message = Message.find(1) |
|
31 | 48 | replies_count = @message.replies_count |
|
32 | 49 | |
|
33 | 50 | reply_author = User.find(2) |
|
34 | 51 | reply = Message.new(:board => @board, :subject => 'Test reply', :content => 'Test reply content', :parent => @message, :author => reply_author) |
|
35 | 52 | assert reply.save |
|
36 | 53 | @board.reload |
|
37 | 54 | # same topics count |
|
38 | 55 | assert_equal topics_count, @board[:topics_count] |
|
39 | 56 | # messages count incremented |
|
40 | 57 | assert_equal messages_count+1, @board[:messages_count] |
|
41 | 58 | assert_equal reply, @board.last_message |
|
42 | 59 | @message.reload |
|
43 | 60 | # replies count incremented |
|
44 | 61 | assert_equal replies_count+1, @message[:replies_count] |
|
45 | 62 | assert_equal reply, @message.last_reply |
|
46 | 63 | # author should be watching the message |
|
47 | 64 | assert @message.watched_by?(reply_author) |
|
48 | 65 | end |
|
49 | 66 | |
|
67 | def test_moving_message_should_update_counters | |
|
68 | @message = Message.find(1) | |
|
69 | assert_no_difference 'Message.count' do | |
|
70 | # Previous board | |
|
71 | assert_difference 'Board.find(1).topics_count', -1 do | |
|
72 | assert_difference 'Board.find(1).messages_count', -(1 + @message.replies_count) do | |
|
73 | # New board | |
|
74 | assert_difference 'Board.find(2).topics_count' do | |
|
75 | assert_difference 'Board.find(2).messages_count', (1 + @message.replies_count) do | |
|
76 | @message.update_attributes(:board_id => 2) | |
|
77 | end | |
|
78 | end | |
|
79 | end | |
|
80 | end | |
|
81 | end | |
|
82 | end | |
|
83 | ||
|
50 | 84 | def test_destroy_topic |
|
51 | 85 | message = Message.find(1) |
|
52 | 86 | board = message.board |
|
53 | 87 | topics_count, messages_count = board.topics_count, board.messages_count |
|
54 | 88 | |
|
55 | 89 | assert_difference('Watcher.count', -1) do |
|
56 | 90 | assert message.destroy |
|
57 | 91 | end |
|
58 | 92 | board.reload |
|
59 | 93 | |
|
60 | 94 | # Replies deleted |
|
61 | 95 | assert Message.find_all_by_parent_id(1).empty? |
|
62 | 96 | # Checks counters |
|
63 | 97 | assert_equal topics_count - 1, board.topics_count |
|
64 | 98 | assert_equal messages_count - 3, board.messages_count |
|
65 | 99 | # Watchers removed |
|
66 | 100 | end |
|
67 | 101 | |
|
68 | 102 | def test_destroy_reply |
|
69 | 103 | message = Message.find(5) |
|
70 | 104 | board = message.board |
|
71 | 105 | topics_count, messages_count = board.topics_count, board.messages_count |
|
72 | 106 | assert message.destroy |
|
73 | 107 | board.reload |
|
74 | 108 | |
|
75 | 109 | # Checks counters |
|
76 | 110 | assert_equal topics_count, board.topics_count |
|
77 | 111 | assert_equal messages_count - 1, board.messages_count |
|
78 | 112 | end |
|
79 | 113 | |
|
80 | 114 | def test_editable_by |
|
81 | 115 | message = Message.find(6) |
|
82 | 116 | author = message.author |
|
83 | 117 | assert message.editable_by?(author) |
|
84 | 118 | |
|
85 | 119 | author.role_for_project(message.project).remove_permission!(:edit_own_messages) |
|
86 | 120 | assert !message.reload.editable_by?(author.reload) |
|
87 | 121 | end |
|
88 | 122 | |
|
89 | 123 | def test_destroyable_by |
|
90 | 124 | message = Message.find(6) |
|
91 | 125 | author = message.author |
|
92 | 126 | assert message.destroyable_by?(author) |
|
93 | 127 | |
|
94 | 128 | author.role_for_project(message.project).remove_permission!(:delete_own_messages) |
|
95 | 129 | assert !message.reload.destroyable_by?(author.reload) |
|
96 | 130 | end |
|
97 | 131 | end |
General Comments 0
You need to be logged in to leave comments.
Login now