Commit 4f91184d39168c2105c77c1ad61fe0c5f2337789
Exists in
master
and in
28 other branches
Merge branch 'merge-requests/282'
Showing
37 changed files
with
1993 additions
and
681 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,164 @@ |
| 1 | +class CommentController < ApplicationController | |
| 2 | + | |
| 3 | + needs_profile | |
| 4 | + | |
| 5 | + before_filter :can_update?, :only => [:edit, :update] | |
| 6 | + | |
| 7 | + def create | |
| 8 | + begin | |
| 9 | + @page = profile.articles.find(params[:id]) | |
| 10 | + rescue | |
| 11 | + @page = nil | |
| 12 | + end | |
| 13 | + | |
| 14 | + # page not found, give error | |
| 15 | + if @page.nil? | |
| 16 | + respond_to do |format| | |
| 17 | + format.js do | |
| 18 | + render :json => { :msg => _('Page not found.')} | |
| 19 | + end | |
| 20 | + end | |
| 21 | + return | |
| 22 | + end | |
| 23 | + | |
| 24 | + unless @page.accept_comments? | |
| 25 | + respond_to do |format| | |
| 26 | + format.js do | |
| 27 | + render :json => { :msg => _('Comment not allowed in this article')} | |
| 28 | + end | |
| 29 | + end | |
| 30 | + return | |
| 31 | + end | |
| 32 | + | |
| 33 | + @comment = Comment.new(params[:comment]) | |
| 34 | + @comment.author = user if logged_in? | |
| 35 | + @comment.article = @page | |
| 36 | + @comment.ip_address = request.remote_ip | |
| 37 | + @comment.user_agent = request.user_agent | |
| 38 | + @comment.referrer = request.referrer | |
| 39 | + @plugins.dispatch(:filter_comment, @comment) | |
| 40 | + | |
| 41 | + if @comment.rejected? | |
| 42 | + respond_to do |format| | |
| 43 | + format.js do | |
| 44 | + render :json => { :msg => _('Comment was rejected')} | |
| 45 | + end | |
| 46 | + end | |
| 47 | + return | |
| 48 | + end | |
| 49 | + | |
| 50 | + if !@comment.valid? || (not pass_without_comment_captcha? and not verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) | |
| 51 | + respond_to do |format| | |
| 52 | + format.js do | |
| 53 | + render :json => { | |
| 54 | + :render_target => 'form', | |
| 55 | + :html => render_to_string(:partial => 'comment_form', :object => @comment, :locals => {:comment => @comment, :display_link => true, :show_form => true}) | |
| 56 | + } | |
| 57 | + end | |
| 58 | + end | |
| 59 | + return | |
| 60 | + end | |
| 61 | + | |
| 62 | + if @comment.need_moderation? | |
| 63 | + @comment.created_at = Time.now | |
| 64 | + ApproveComment.create!(:requestor => @comment.author, :target => profile, :comment_attributes => @comment.attributes.to_json) | |
| 65 | + | |
| 66 | + respond_to do |format| | |
| 67 | + format.js do | |
| 68 | + render :json => { :render_target => nil, :msg => _('Your comment is waiting for approval.') } | |
| 69 | + end | |
| 70 | + end | |
| 71 | + return | |
| 72 | + end | |
| 73 | + | |
| 74 | + @comment.save | |
| 75 | + | |
| 76 | + respond_to do |format| | |
| 77 | + format.js do | |
| 78 | + comment_to_render = @comment.comment_root | |
| 79 | + render :json => { | |
| 80 | + :render_target => comment_to_render.anchor, | |
| 81 | + :html => render_to_string(:partial => 'comment', :locals => {:comment => comment_to_render, :display_link => true}), | |
| 82 | + :msg => _('Comment successfully created.') | |
| 83 | + } | |
| 84 | + end | |
| 85 | + end | |
| 86 | + end | |
| 87 | + | |
| 88 | + def destroy | |
| 89 | + comment = profile.comments_received.find(params[:id]) | |
| 90 | + | |
| 91 | + if comment && comment.can_be_destroyed_by?(user) && comment.destroy | |
| 92 | + render :text => {'ok' => true}.to_json, :content_type => 'application/json' | |
| 93 | + else | |
| 94 | + session[:notice] = _("The comment was not removed.") | |
| 95 | + render :text => {'ok' => false}.to_json, :content_type => 'application/json' | |
| 96 | + end | |
| 97 | + end | |
| 98 | + | |
| 99 | + def mark_as_spam | |
| 100 | + comment = profile.comments_received.find(params[:id]) | |
| 101 | + if comment.can_be_marked_as_spam_by?(user) | |
| 102 | + comment.spam! | |
| 103 | + render :text => {'ok' => true}.to_json, :content_type => 'application/json' | |
| 104 | + else | |
| 105 | + session[:notice] = _("You couldn't mark this comment as spam.") | |
| 106 | + render :text => {'ok' => false}.to_json, :content_type => 'application/json' | |
| 107 | + end | |
| 108 | + end | |
| 109 | + | |
| 110 | + def edit | |
| 111 | + render :partial => "comment_form", :locals => {:comment => @comment, :display_link => params[:reply_of_id].present?, :edition_mode => true, :show_form => true} | |
| 112 | + end | |
| 113 | + | |
| 114 | + def update | |
| 115 | + if @comment.update_attributes(params[:comment]) | |
| 116 | + respond_to do |format| | |
| 117 | + format.js do | |
| 118 | + comment_to_render = @comment.comment_root | |
| 119 | + render :json => { | |
| 120 | + :ok => true, | |
| 121 | + :render_target => comment_to_render.anchor, | |
| 122 | + :html => render_to_string(:partial => 'comment', :locals => {:comment => comment_to_render}) | |
| 123 | + } | |
| 124 | + end | |
| 125 | + end | |
| 126 | + else | |
| 127 | + respond_to do |format| | |
| 128 | + format.js do | |
| 129 | + render :json => { | |
| 130 | + :ok => false, | |
| 131 | + :render_target => 'form', | |
| 132 | + :html => render_to_string(:partial => 'comment_form', :object => @comment, :locals => {:comment => @comment, :display_link => false, :edition_mode => true, :show_form => true}) | |
| 133 | + } | |
| 134 | + end | |
| 135 | + end | |
| 136 | + end | |
| 137 | + end | |
| 138 | + | |
| 139 | + def check_actions | |
| 140 | + comment = profile.comments_received.find(params[:id]) | |
| 141 | + ids = @plugins.dispatch(:check_comment_actions, comment).collect do |action| | |
| 142 | + action.kind_of?(Proc) ? self.instance_eval(&action) : action | |
| 143 | + end.flatten.compact | |
| 144 | + render :json => {:ids => ids} | |
| 145 | + end | |
| 146 | + | |
| 147 | + protected | |
| 148 | + | |
| 149 | + def pass_without_comment_captcha? | |
| 150 | + logged_in? && !environment.enabled?('captcha_for_logged_users') | |
| 151 | + end | |
| 152 | + helper_method :pass_without_comment_captcha? | |
| 153 | + | |
| 154 | + def can_update? | |
| 155 | + begin | |
| 156 | + @comment = profile.comments_received.find(params[:id]) | |
| 157 | + raise ActiveRecord::RecordNotFound unless @comment.can_be_updated_by?(user) # Not reveal that the comment exists | |
| 158 | + rescue ActiveRecord::RecordNotFound | |
| 159 | + render_not_found | |
| 160 | + return | |
| 161 | + end | |
| 162 | + end | |
| 163 | + | |
| 164 | +end | ... | ... |
app/controllers/public/content_viewer_controller.rb
| ... | ... | @@ -2,8 +2,6 @@ class ContentViewerController < ApplicationController |
| 2 | 2 | |
| 3 | 3 | needs_profile |
| 4 | 4 | |
| 5 | - before_filter :comment_author, :only => :edit_comment | |
| 6 | - | |
| 7 | 5 | helper ProfileHelper |
| 8 | 6 | helper TagsHelper |
| 9 | 7 | |
| ... | ... | @@ -70,24 +68,8 @@ class ContentViewerController < ApplicationController |
| 70 | 68 | |
| 71 | 69 | @form_div = params[:form] |
| 72 | 70 | |
| 73 | - if params[:comment] && params[:confirm] == 'true' | |
| 74 | - @comment = Comment.new(params[:comment]) | |
| 75 | - if request.post? && @page.accept_comments? | |
| 76 | - add_comment | |
| 77 | - end | |
| 78 | - else | |
| 79 | - @comment = Comment.new | |
| 80 | - end | |
| 81 | - | |
| 82 | - if request.post? | |
| 83 | - if params[:remove_comment] | |
| 84 | - remove_comment | |
| 85 | - return | |
| 86 | - elsif params[:mark_comment_as_spam] | |
| 87 | - mark_comment_as_spam | |
| 88 | - return | |
| 89 | - end | |
| 90 | - end | |
| 71 | + #FIXME see a better way to do this. It's not need to pass this variable anymore | |
| 72 | + @comment = Comment.new | |
| 91 | 73 | |
| 92 | 74 | if @page.has_posts? |
| 93 | 75 | posts = if params[:year] and params[:month] |
| ... | ... | @@ -125,81 +107,8 @@ class ContentViewerController < ApplicationController |
| 125 | 107 | end |
| 126 | 108 | end |
| 127 | 109 | |
| 128 | - def edit_comment | |
| 129 | - path = params[:page].join('/') | |
| 130 | - @page = profile.articles.find_by_path(path) | |
| 131 | - @form_div = 'opened' | |
| 132 | - @comment = @page.comments.find_by_id(params[:id]) | |
| 133 | - if @comment | |
| 134 | - if request.post? | |
| 135 | - begin | |
| 136 | - @comment.update_attributes(params[:comment]) | |
| 137 | - session[:notice] = _('Comment succesfully updated') | |
| 138 | - redirect_to :action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path | |
| 139 | - rescue | |
| 140 | - session[:notice] = _('Comment could not be updated') | |
| 141 | - end | |
| 142 | - end | |
| 143 | - else | |
| 144 | - redirect_to @page.view_url | |
| 145 | - session[:notice] = _('Could not find the comment in the article') | |
| 146 | - end | |
| 147 | - end | |
| 148 | - | |
| 149 | 110 | protected |
| 150 | 111 | |
| 151 | - def add_comment | |
| 152 | - @comment.author = user if logged_in? | |
| 153 | - @comment.article = @page | |
| 154 | - @comment.ip_address = request.remote_ip | |
| 155 | - @comment.user_agent = request.user_agent | |
| 156 | - @comment.referrer = request.referrer | |
| 157 | - plugins_filter_comment(@comment) | |
| 158 | - return if @comment.rejected? | |
| 159 | - if (pass_without_comment_captcha? || verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) && @comment.save | |
| 160 | - @page.touch | |
| 161 | - @comment = nil # clear the comment form | |
| 162 | - redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] | |
| 163 | - else | |
| 164 | - @form_div = 'opened' if params[:comment][:reply_of_id].blank? | |
| 165 | - end | |
| 166 | - end | |
| 167 | - | |
| 168 | - def plugins_filter_comment(comment) | |
| 169 | - @plugins.each do |plugin| | |
| 170 | - plugin.filter_comment(comment) | |
| 171 | - end | |
| 172 | - end | |
| 173 | - | |
| 174 | - def pass_without_comment_captcha? | |
| 175 | - logged_in? && !environment.enabled?('captcha_for_logged_users') | |
| 176 | - end | |
| 177 | - helper_method :pass_without_comment_captcha? | |
| 178 | - | |
| 179 | - def remove_comment | |
| 180 | - @comment = @page.comments.find(params[:remove_comment]) | |
| 181 | - if (user == @comment.author || user == @page.profile || user.has_permission?(:moderate_comments, @page.profile)) | |
| 182 | - @comment.destroy | |
| 183 | - end | |
| 184 | - finish_comment_handling | |
| 185 | - end | |
| 186 | - | |
| 187 | - def mark_comment_as_spam | |
| 188 | - @comment = @page.comments.find(params[:mark_comment_as_spam]) | |
| 189 | - if logged_in? && (user == @page.profile || user.has_permission?(:moderate_comments, @page.profile)) | |
| 190 | - @comment.spam! | |
| 191 | - end | |
| 192 | - finish_comment_handling | |
| 193 | - end | |
| 194 | - | |
| 195 | - def finish_comment_handling | |
| 196 | - if request.xhr? | |
| 197 | - render :text => {'ok' => true}.to_json, :content_type => 'application/json' | |
| 198 | - else | |
| 199 | - redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view] | |
| 200 | - end | |
| 201 | - end | |
| 202 | - | |
| 203 | 112 | def per_page |
| 204 | 113 | 12 |
| 205 | 114 | end |
| ... | ... | @@ -223,13 +132,9 @@ class ContentViewerController < ApplicationController |
| 223 | 132 | end |
| 224 | 133 | end |
| 225 | 134 | |
| 226 | - def comment_author | |
| 227 | - comment = Comment.find_by_id(params[:id]) | |
| 228 | - if comment | |
| 229 | - render_access_denied if comment.author.blank? || comment.author != user | |
| 230 | - else | |
| 231 | - render_not_found | |
| 232 | - end | |
| 135 | + def pass_without_comment_captcha? | |
| 136 | + logged_in? && !environment.enabled?('captcha_for_logged_users') | |
| 233 | 137 | end |
| 138 | + helper_method :pass_without_comment_captcha? | |
| 234 | 139 | |
| 235 | 140 | end | ... | ... |
app/helpers/application_helper.rb
| ... | ... | @@ -30,6 +30,8 @@ module ApplicationHelper |
| 30 | 30 | |
| 31 | 31 | include AccountHelper |
| 32 | 32 | |
| 33 | + include CommentHelper | |
| 34 | + | |
| 33 | 35 | include BlogHelper |
| 34 | 36 | |
| 35 | 37 | include ContentViewerHelper |
| ... | ... | @@ -1385,12 +1387,12 @@ module ApplicationHelper |
| 1385 | 1387 | end |
| 1386 | 1388 | |
| 1387 | 1389 | def expirable_button(content, action, text, url, options = {}) |
| 1388 | - options[:class] = "button with-text icon-#{action.to_s}" | |
| 1390 | + options[:class] = ["button with-text icon-#{action.to_s}", options[:class]].compact.join(' ') | |
| 1389 | 1391 | expirable_content_reference content, action, text, url, options |
| 1390 | 1392 | end |
| 1391 | 1393 | |
| 1392 | 1394 | def expirable_comment_link(content, action, text, url, options = {}) |
| 1393 | - options[:class] = "comment-footer comment-footer-link comment-footer-hide" | |
| 1395 | + options[:class] = ["comment-footer comment-footer-link comment-footer-hide", options[:class]].compact.join(' ') | |
| 1394 | 1396 | expirable_content_reference content, action, text, url, options |
| 1395 | 1397 | end |
| 1396 | 1398 | ... | ... |
app/helpers/article_helper.rb
| ... | ... | @@ -35,7 +35,13 @@ module ArticleHelper |
| 35 | 35 | 'div', |
| 36 | 36 | check_box(:article, :notify_comments) + |
| 37 | 37 | content_tag('label', _('I want to receive a notification of each comment written by e-mail'), :for => 'article_notify_comments') + |
| 38 | - observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked") | |
| 38 | + observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked;$('article_moderate_comments').disabled = ! $('article_accept_comments').checked") | |
| 39 | + ) + | |
| 40 | + | |
| 41 | + content_tag( | |
| 42 | + 'div', | |
| 43 | + check_box(:article, :moderate_comments) + | |
| 44 | + content_tag('label', _('I want to approve comments on this article'), :for => 'article_moderate_comments') | |
| 39 | 45 | ) + |
| 40 | 46 | |
| 41 | 47 | (article.can_display_hits? ? | ... | ... |
| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | +module CommentHelper | |
| 2 | + | |
| 3 | + def article_title(article, args = {}) | |
| 4 | + title = article.title | |
| 5 | + title = article.display_title if article.kind_of?(UploadedFile) && article.image? | |
| 6 | + title = content_tag('h1', h(title), :class => 'title') | |
| 7 | + if article.belongs_to_blog? | |
| 8 | + unless args[:no_link] | |
| 9 | + title = content_tag('h1', link_to(article.name, article.url), :class => 'title') | |
| 10 | + end | |
| 11 | + comments = '' | |
| 12 | + unless args[:no_comments] || !article.accept_comments | |
| 13 | + comments = (" - %s") % link_to_comments(article) | |
| 14 | + end | |
| 15 | + title << content_tag('span', | |
| 16 | + content_tag('span', show_date(article.published_at), :class => 'date') + | |
| 17 | + content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') + | |
| 18 | + content_tag('span', comments, :class => 'comments'), | |
| 19 | + :class => 'created-at' | |
| 20 | + ) | |
| 21 | + end | |
| 22 | + title | |
| 23 | + end | |
| 24 | + | |
| 25 | + def comment_actions(comment) | |
| 26 | + url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id) | |
| 27 | + links = links_for_comment_actions(comment) | |
| 28 | + content_tag(:li, link_to(content_tag(:span, _('Contents menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger comment-trigger', :url => url), :class=> 'vcard') unless links.empty? | |
| 29 | + end | |
| 30 | + | |
| 31 | + private | |
| 32 | + | |
| 33 | + def links_for_comment_actions(comment) | |
| 34 | + actions = [link_for_report_abuse(comment), link_for_spam(comment), link_for_edit(comment), link_for_remove(comment)] | |
| 35 | + @plugins.dispatch(:comment_actions, comment).collect do |action| | |
| 36 | + actions << (action.kind_of?(Proc) ? self.instance_eval(&action) : action) | |
| 37 | + end | |
| 38 | + actions.flatten.compact | |
| 39 | + end | |
| 40 | + | |
| 41 | + def link_for_report_abuse(comment) | |
| 42 | + if comment.author | |
| 43 | + report_abuse_link = report_abuse(comment.author, :comment_link, comment) | |
| 44 | + {:link => report_abuse_link} if report_abuse_link | |
| 45 | + end | |
| 46 | + end | |
| 47 | + | |
| 48 | + def link_for_spam(comment) | |
| 49 | + if comment.can_be_marked_as_spam_by?(user) | |
| 50 | + if comment.spam? | |
| 51 | + {:link => link_to_function(_('Mark as NOT SPAM'), 'remove_comment(this, %s); return false;' % url_for(:profile => profile.identifier, :mark_comment_as_ham => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide')} | |
| 52 | + else | |
| 53 | + {:link => link_to_function(_('Mark as SPAM'), 'remove_comment(this, %s, %s); return false;' % [url_for(:profile => profile.identifier, :controller => 'comment', :action => :mark_as_spam, :id => comment.id).to_json, _('Are you sure you want to mark this comment as SPAM?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide')} | |
| 54 | + end | |
| 55 | + end | |
| 56 | + end | |
| 57 | + | |
| 58 | + def link_for_edit(comment) | |
| 59 | + if comment.can_be_updated_by?(user) | |
| 60 | + {:link => expirable_comment_link(comment, :edit, _('Edit'), url_for(:profile => profile.identifier, :controller => :comment, :action => :edit, :id => comment.id),:class => 'colorbox')} | |
| 61 | + end | |
| 62 | + end | |
| 63 | + | |
| 64 | + def link_for_remove(comment) | |
| 65 | + if comment.can_be_destroyed_by?(user) | |
| 66 | + {:link => link_to_function(_('Remove'), 'remove_comment(this, %s, %s); return false ;' % [url_for(:profile => profile.identifier, :controller => 'comment', :action => :destroy, :id => comment.id).to_json, _('Are you sure you want to remove this comment and all its replies?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide remove-children')} | |
| 67 | + end | |
| 68 | + end | |
| 69 | + | |
| 70 | +end | ... | ... |
app/helpers/content_viewer_helper.rb
| ... | ... | @@ -5,11 +5,9 @@ module ContentViewerHelper |
| 5 | 5 | |
| 6 | 6 | def number_of_comments(article) |
| 7 | 7 | n = article.comments.without_spam.count |
| 8 | - if n == 0 | |
| 9 | - _('No comments yet') | |
| 10 | - else | |
| 11 | - n_('One comment', '<span class="comment-count">%{comments}</span> comments', n) % { :comments => n } | |
| 12 | - end | |
| 8 | + base_str = "<span class='comment-count hide'>#{n}</span>" | |
| 9 | + amount_str = n == 0 ? _('no comments yet') : (n == 1 ? _('One comment') : _('%s comments') % n) | |
| 10 | + base_str + "<span class='comment-count-write-out'>#{amount_str}</span>" | |
| 13 | 11 | end |
| 14 | 12 | |
| 15 | 13 | def article_title(article, args = {}) | ... | ... |
| ... | ... | @@ -0,0 +1,104 @@ |
| 1 | +class ApproveComment < Task | |
| 2 | + validates_presence_of :target_id | |
| 3 | + | |
| 4 | + settings_items :comment_attributes, :closing_statment | |
| 5 | + | |
| 6 | + validates_presence_of :comment_attributes | |
| 7 | + | |
| 8 | + def comment | |
| 9 | + @comment ||= Comment.new(JSON.parse(self.comment_attributes)) unless self.comment_attributes.nil? | |
| 10 | + end | |
| 11 | + | |
| 12 | + def requestor_name | |
| 13 | + requestor ? requestor.name : (comment.name || _('Anonymous')) | |
| 14 | + end | |
| 15 | + | |
| 16 | + def article | |
| 17 | + Article.find_by_id comment.source_id unless self.comment.nil? | |
| 18 | + end | |
| 19 | + | |
| 20 | + def article_name | |
| 21 | + article ? article.name : _("Article removed.") | |
| 22 | + end | |
| 23 | + | |
| 24 | + def perform | |
| 25 | + comment.save! | |
| 26 | + end | |
| 27 | + | |
| 28 | + def title | |
| 29 | + _("New comment to article") | |
| 30 | + end | |
| 31 | + | |
| 32 | + def icon | |
| 33 | + result = {:type => :defined_image, :src => '/images/icons-app/article-minor.png'} | |
| 34 | + result.merge!({:url => article.url}) if article | |
| 35 | + result | |
| 36 | + end | |
| 37 | + | |
| 38 | + def linked_subject | |
| 39 | + {:text => article_name, :url => article.url} if article | |
| 40 | + end | |
| 41 | + | |
| 42 | + def information | |
| 43 | + if article | |
| 44 | + if requestor | |
| 45 | + {:message => _('%{requestor} commented on the the article: %{linked_subject}.')} | |
| 46 | + else | |
| 47 | + { :message => _('%{requestor} commented on the the article: %{linked_subject}.'), | |
| 48 | + :variables => {:requestor => requestor_name} } | |
| 49 | + end | |
| 50 | + else | |
| 51 | + {:message => _("The article was removed.")} | |
| 52 | + end | |
| 53 | + end | |
| 54 | + | |
| 55 | + def accept_details | |
| 56 | + true | |
| 57 | + end | |
| 58 | + | |
| 59 | + def reject_details | |
| 60 | + true | |
| 61 | + end | |
| 62 | + | |
| 63 | + def default_decision | |
| 64 | + if article | |
| 65 | + 'skip' | |
| 66 | + else | |
| 67 | + 'reject' | |
| 68 | + end | |
| 69 | + end | |
| 70 | + | |
| 71 | + def accept_disabled? | |
| 72 | + article.blank? | |
| 73 | + end | |
| 74 | + | |
| 75 | + def target_notification_description | |
| 76 | + if article | |
| 77 | + _('%{requestor} wants to comment the article: %{article}.') % {:requestor => requestor_name, :article => article.name} | |
| 78 | + else | |
| 79 | + _('%{requestor} wanted to comment the article but it was removed.') % {:requestor => requestor_name} | |
| 80 | + end | |
| 81 | + end | |
| 82 | + | |
| 83 | + def target_notification_message | |
| 84 | + target_notification_description + "\n\n" + | |
| 85 | + _('You need to login on %{system} in order to approve or reject this comment.') % { :system => target.environment.name } | |
| 86 | + end | |
| 87 | + | |
| 88 | + def task_finished_message | |
| 89 | + if !closing_statment.blank? | |
| 90 | + _("Your comment to the article \"%{article}\" was approved. Here is the comment left by the admin who approved your comment:\n\n%{comment} ") % {:article => article_name, :comment => closing_statment} | |
| 91 | + else | |
| 92 | + _('Your request for comment the article "%{article}" was approved.') % {:article => article_name} | |
| 93 | + end | |
| 94 | + end | |
| 95 | + | |
| 96 | + def task_cancelled_message | |
| 97 | + message = _('Your request for commenting the article "%{article}" was rejected.') % {:article => article_name} | |
| 98 | + if !reject_explanation.blank? | |
| 99 | + message += " " + _("Here is the reject explanation left by the administrator who rejected your comment: \n\n%{reject_explanation}") % {:reject_explanation => reject_explanation} | |
| 100 | + end | |
| 101 | + message | |
| 102 | + end | |
| 103 | + | |
| 104 | +end | ... | ... |
app/models/article.rb
| ... | ... | @@ -65,6 +65,7 @@ class Article < ActiveRecord::Base |
| 65 | 65 | settings_items :display_hits, :type => :boolean, :default => true |
| 66 | 66 | settings_items :author_name, :type => :string, :default => "" |
| 67 | 67 | settings_items :allow_members_to_edit, :type => :boolean, :default => false |
| 68 | + settings_items :moderate_comments, :type => :boolean, :default => false | |
| 68 | 69 | settings_items :followers, :type => Array, :default => [] |
| 69 | 70 | |
| 70 | 71 | belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' |
| ... | ... | @@ -327,6 +328,14 @@ class Article < ActiveRecord::Base |
| 327 | 328 | @view_url ||= image? ? url.merge(:view => true) : url |
| 328 | 329 | end |
| 329 | 330 | |
| 331 | + def comment_url_structure(comment, action = :edit) | |
| 332 | + if comment.new_record? | |
| 333 | + profile.url.merge(:page => path.split("/"), :controller => :comment, :action => :create) | |
| 334 | + else | |
| 335 | + profile.url.merge(:page => path.split("/"), :controller => :comment, :action => action || :edit, :id => comment.id) | |
| 336 | + end | |
| 337 | + end | |
| 338 | + | |
| 330 | 339 | def allow_children? |
| 331 | 340 | true |
| 332 | 341 | end |
| ... | ... | @@ -489,6 +498,14 @@ class Article < ActiveRecord::Base |
| 489 | 498 | allow_post_content?(user) || user && allow_members_to_edit && user.is_member_of?(profile) |
| 490 | 499 | end |
| 491 | 500 | |
| 501 | + def moderate_comments? | |
| 502 | + moderate_comments == true | |
| 503 | + end | |
| 504 | + | |
| 505 | + def comments_updated | |
| 506 | + solr_save | |
| 507 | + end | |
| 508 | + | |
| 492 | 509 | def accept_category?(cat) |
| 493 | 510 | !cat.is_a?(ProductCategory) |
| 494 | 511 | end | ... | ... |
app/models/comment.rb
| ... | ... | @@ -34,7 +34,9 @@ class Comment < ActiveRecord::Base |
| 34 | 34 | |
| 35 | 35 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' |
| 36 | 36 | |
| 37 | - delegate :environment, :to => :source | |
| 37 | + def comment_root | |
| 38 | + (reply_of && reply_of.comment_root) || self | |
| 39 | + end | |
| 38 | 40 | |
| 39 | 41 | def action_tracker_target |
| 40 | 42 | self.article.profile |
| ... | ... | @@ -248,4 +250,22 @@ class Comment < ActiveRecord::Base |
| 248 | 250 | plugins.dispatch(:comment_marked_as_ham, self) |
| 249 | 251 | end |
| 250 | 252 | |
| 253 | + def need_moderation? | |
| 254 | + article.moderate_comments? && (author.nil? || article.author != author) | |
| 255 | + end | |
| 256 | + | |
| 257 | + def can_be_destroyed_by?(user) | |
| 258 | + return if user.nil? | |
| 259 | + user == author || user == profile || user.has_permission?(:moderate_comments, profile) | |
| 260 | + end | |
| 261 | + | |
| 262 | + def can_be_marked_as_spam_by?(user) | |
| 263 | + return if user.nil? | |
| 264 | + user == profile || user.has_permission?(:moderate_comments, profile) | |
| 265 | + end | |
| 266 | + | |
| 267 | + def can_be_updated_by?(user) | |
| 268 | + user.present? && user == author | |
| 269 | + end | |
| 270 | + | |
| 251 | 271 | end | ... | ... |
app/models/task.rb
| ... | ... | @@ -74,7 +74,7 @@ class Task < ActiveRecord::Base |
| 74 | 74 | end |
| 75 | 75 | |
| 76 | 76 | def self.all_types |
| 77 | - %w[Invitation EnterpriseActivation AddMember Ticket SuggestArticle AddFriend CreateCommunity AbuseComplaint ApproveArticle CreateEnterprise ChangePassword EmailActivation InviteFriend InviteMember] | |
| 77 | + %w[Invitation EnterpriseActivation AddMember Ticket SuggestArticle AddFriend CreateCommunity AbuseComplaint ApproveComment ApproveArticle CreateEnterprise ChangePassword EmailActivation InviteFriend InviteMember] | |
| 78 | 78 | end |
| 79 | 79 | |
| 80 | 80 | # this method finished the task. It calls #perform, which must be overriden | ... | ... |
| ... | ... | @@ -0,0 +1,84 @@ |
| 1 | +<li id="<%= comment.anchor %>" class="article-comment"> | |
| 2 | + <div class="article-comment-inner"> | |
| 3 | + | |
| 4 | + <div class="comment-content comment-logged-<%= comment.author ? 'in' : 'out' %> <%= 'comment-from-owner' if ( comment.author && (profile == comment.author) ) %>"> | |
| 5 | + | |
| 6 | + <% if comment.author %> | |
| 7 | + <%= link_to image_tag(profile_icon(comment.author, :minor)) + | |
| 8 | + content_tag('span', comment.author_name, :class => 'comment-info'), | |
| 9 | + comment.author.url, | |
| 10 | + :class => 'comment-picture', | |
| 11 | + :title => comment.author_name | |
| 12 | + %> | |
| 13 | + <% else %> | |
| 14 | + <% url_image, status_class = comment.author_id ? | |
| 15 | + [comment.removed_user_image, 'icon-user-removed'] : | |
| 16 | + [str_gravatar_url_for( comment.email, :size => 50, :d=>404 ), 'icon-user-unknown'] %> | |
| 17 | + | |
| 18 | + <%= link_to( | |
| 19 | + image_tag(url_image, :onerror=>'gravatarCommentFailback(this)', | |
| 20 | + 'data-gravatar'=>str_gravatar_url_for(comment.email, :size=>50)) + | |
| 21 | + content_tag('span', comment.author_name, :class => 'comment-info') + | |
| 22 | + content_tag('span', comment.message, | |
| 23 | + :class => 'comment-user-status ' + status_class), | |
| 24 | + gravatar_profile_url(comment.email), | |
| 25 | + :target => '_blank', | |
| 26 | + :class => 'comment-picture', | |
| 27 | + :title => '%s %s' % [comment.author_name, comment.message] | |
| 28 | + )%> | |
| 29 | + <% end %> | |
| 30 | + | |
| 31 | + <% comment_balloon do %> | |
| 32 | + | |
| 33 | + <div class="comment-details"> | |
| 34 | + <div class="comment-header"> | |
| 35 | + <ul> | |
| 36 | + <div class="comment-actions"> | |
| 37 | + <%= comment_actions(comment) %> | |
| 38 | + </div> | |
| 39 | + </ul> | |
| 40 | + <% unless comment.spam? %> | |
| 41 | + <%= link_to_function '', | |
| 42 | + "var f = add_comment_reply_form(this, %s); f.find('comment_title, textarea').val(''); return false" % comment.id, | |
| 43 | + :class => 'comment-footer comment-footer-link comment-footer-hide comment-actions-reply button', | |
| 44 | + :id => 'comment-reply-to-' + comment.id.to_s | |
| 45 | + %> | |
| 46 | + <% end %> | |
| 47 | + </div> | |
| 48 | + | |
| 49 | + <div class="comment-created-at"> | |
| 50 | + <%= show_time(comment.created_at) %> | |
| 51 | + </div> | |
| 52 | + <h4><%= comment.title.blank? && ' ' || comment.title %></h4> | |
| 53 | + <div class="comment-text"> | |
| 54 | + <p/> | |
| 55 | + <%= txt2html comment.body %> | |
| 56 | + </div> | |
| 57 | + </div> | |
| 58 | + | |
| 59 | + <div class="comment_reply post_comment_box closed" id="comment_reply_to_<%= comment.id %>"> | |
| 60 | + <% if @comment && @comment.errors.any? && @comment.reply_of_id.to_i == comment.id %> | |
| 61 | + <%= error_messages_for :comment %> | |
| 62 | + <script type="text/javascript"> | |
| 63 | + jQuery(function() { | |
| 64 | + document.location.href = '#<%= comment.anchor %>'; | |
| 65 | + add_comment_reply_form('#comment-reply-to-<%= comment.id %>', <%= comment.id %>); | |
| 66 | + }); | |
| 67 | + </script> | |
| 68 | + <% end %> | |
| 69 | + </div> | |
| 70 | + | |
| 71 | + <% end %> | |
| 72 | + | |
| 73 | + </div> | |
| 74 | + | |
| 75 | + <% unless comment.replies.blank? || comment.spam? %> | |
| 76 | + <ul class="comment-replies"> | |
| 77 | + <% comment.replies.each do |reply| %> | |
| 78 | + <%= render :partial => 'comment/comment', :locals => { :comment => reply } %> | |
| 79 | + <% end %> | |
| 80 | + </ul> | |
| 81 | + <% end %> | |
| 82 | + | |
| 83 | + </div> | |
| 84 | +</li> | ... | ... |
| ... | ... | @@ -0,0 +1,96 @@ |
| 1 | +<% edition_mode = (defined? edition_mode) ? edition_mode : false %> | |
| 2 | +<div class="<%= edition_mode ? '' : 'page-comment-form' %>"> | |
| 3 | + | |
| 4 | +<% focus_on = logged_in? ? 'title' : 'name' %> | |
| 5 | + | |
| 6 | + | |
| 7 | +<% if !edition_mode && !pass_without_comment_captcha? %> | |
| 8 | + <div id="recaptcha-container" style="display: none"> | |
| 9 | + <h3><%= _('Please type the two words below') %></h3> | |
| 10 | + <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> | |
| 11 | + <% button_bar do %> | |
| 12 | + <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> | |
| 13 | + <%= button_to_function :cancel, _('Cancel'), "jQuery.colorbox.close()" %> | |
| 14 | + <% end %> | |
| 15 | + </div> | |
| 16 | + | |
| 17 | + <script type="text/javascript"> | |
| 18 | + jQuery(document).bind('cbox_cleanup', function() { | |
| 19 | + jQuery('#recaptcha-container').hide(); | |
| 20 | + }); | |
| 21 | + </script> | |
| 22 | +<% end %> | |
| 23 | + | |
| 24 | +<script type="text/javascript"> | |
| 25 | +function check_captcha(button, confirm_action) { | |
| 26 | + <% if edition_mode %> | |
| 27 | + return true; | |
| 28 | + <% elsif pass_without_comment_captcha? %> | |
| 29 | + button.form.confirm.value = 'true'; | |
| 30 | + button.disabled = true; | |
| 31 | + return true; | |
| 32 | + <% else %> | |
| 33 | + jQuery('#recaptcha-container').show(); | |
| 34 | + jQuery.colorbox({ inline : true, href : '#recaptcha-container', maxWidth : '600px', maxHeight : '300px' }); | |
| 35 | + jQuery('#confirm-captcha').unbind('click'); | |
| 36 | + jQuery('#confirm-captcha').bind('click', function() { | |
| 37 | + jQuery.colorbox.close(); | |
| 38 | + button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val(); | |
| 39 | + button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val(); | |
| 40 | + button.form.confirm.value = 'true'; | |
| 41 | + button.disabled = false; | |
| 42 | + confirm_action(button); | |
| 43 | + }); | |
| 44 | + return false; | |
| 45 | + <% end %> | |
| 46 | +} | |
| 47 | +</script> | |
| 48 | + | |
| 49 | +<% if @comment && @comment.errors.any? %> | |
| 50 | + <%= error_messages_for :comment %> | |
| 51 | +<% end %> | |
| 52 | + | |
| 53 | +<div class="post_comment_box <%= ((defined? show_form) && show_form) ? 'opened' : 'closed' %>"> | |
| 54 | + | |
| 55 | + <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form') if display_link && @comment.reply_of_id.blank? %> | |
| 56 | +<% remote_form_for(:comment, comment, :url => {:profile => profile.identifier, :controller => 'comment', :action => (edition_mode ? 'update' : 'create'), :id => (edition_mode ? comment.id : @page.id)}, :html => { :class => 'comment_form' } ) do |f| %> | |
| 57 | + | |
| 58 | + <%= required_fields_message %> | |
| 59 | + | |
| 60 | + <% unless logged_in? %> | |
| 61 | + | |
| 62 | + <%= required labelled_form_field(_('Name'), f.text_field(:name)) %> | |
| 63 | + <%= required labelled_form_field(_('e-mail'), f.text_field(:email)) %> | |
| 64 | + <p> | |
| 65 | + <%= _('If you are a registered user, you can login and be automatically recognized.') %> | |
| 66 | + </p> | |
| 67 | + | |
| 68 | + <% end %> | |
| 69 | + | |
| 70 | + <% if !edition_mode && !pass_without_comment_captcha? %> | |
| 71 | + <%= hidden_field_tag(:recaptcha_response_field, nil, :id => nil) %> | |
| 72 | + <%= hidden_field_tag(:recaptcha_challenge_field, nil, :id => nil) %> | |
| 73 | + <% end %> | |
| 74 | + | |
| 75 | + <%= labelled_form_field(_('Title'), f.text_field(:title)) %> | |
| 76 | + <%= required labelled_form_field(_('Enter your comment'), f.text_area(:body, :rows => 5)) %> | |
| 77 | + | |
| 78 | + <%= hidden_field_tag(:confirm, 'false') %> | |
| 79 | + <%= hidden_field_tag(:view, params[:view])%> | |
| 80 | + <%= f.hidden_field(:reply_of_id) %> | |
| 81 | + | |
| 82 | + <% button_bar do %> | |
| 83 | + <%= submit_button('add', _('Post comment'), :onclick => "if(check_captcha(this)) { save_comment(this) } else { check_captcha(this, save_comment)};return false;") %> | |
| 84 | + <% if !edition_mode %> | |
| 85 | + <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> | |
| 86 | + <% else %> | |
| 87 | + <%= button :cancel, _('Cancel'), '#', :onclick => "jQuery.colorbox.close();" %> | |
| 88 | + <% end %> | |
| 89 | + <% end %> | |
| 90 | +<% end %> | |
| 91 | + | |
| 92 | + | |
| 93 | +</div><!-- end class="post_comment_box" --> | |
| 94 | +</div><!-- end class="page-comment-form" --> | |
| 95 | + | |
| 96 | +<%= javascript_include_tag 'comment_form'%> | ... | ... |
app/views/content_viewer/_comment.rhtml
| ... | ... | @@ -1,99 +0,0 @@ |
| 1 | -<li id="<%= comment.anchor %>" class="article-comment"> | |
| 2 | - <div class="article-comment-inner"> | |
| 3 | - | |
| 4 | - <div class="comment-content comment-logged-<%= comment.author ? 'in' : 'out' %> <%= 'comment-from-owner' if ( comment.author && (profile == comment.author) ) %>"> | |
| 5 | - | |
| 6 | - <% if comment.author %> | |
| 7 | - <%= link_to image_tag(profile_icon(comment.author, :minor)) + | |
| 8 | - content_tag('span', comment.author_name, :class => 'comment-info'), | |
| 9 | - comment.author.url, | |
| 10 | - :class => 'comment-picture', | |
| 11 | - :title => comment.author_name | |
| 12 | - %> | |
| 13 | - <% else %> | |
| 14 | - <% url_image, status_class = comment.author_id ? | |
| 15 | - [comment.removed_user_image, 'icon-user-removed'] : | |
| 16 | - [str_gravatar_url_for( comment.email, :size => 50, :d=>404 ), 'icon-user-unknown'] %> | |
| 17 | - | |
| 18 | - <%= link_to( | |
| 19 | - image_tag(url_image, :onerror=>'gravatarCommentFailback(this)', | |
| 20 | - 'data-gravatar'=>str_gravatar_url_for(comment.email, :size=>50)) + | |
| 21 | - content_tag('span', comment.author_name, :class => 'comment-info') + | |
| 22 | - content_tag('span', comment.message, | |
| 23 | - :class => 'comment-user-status ' + status_class), | |
| 24 | - gravatar_profile_url(comment.email), | |
| 25 | - :target => '_blank', | |
| 26 | - :class => 'comment-picture', | |
| 27 | - :title => '%s %s' % [comment.author_name, comment.message] | |
| 28 | - )%> | |
| 29 | - <% end %> | |
| 30 | - | |
| 31 | - <% comment_balloon do %> | |
| 32 | - | |
| 33 | - <div class="comment-details"> | |
| 34 | - <div class="comment-created-at"> | |
| 35 | - <%= show_time(comment.created_at) %> | |
| 36 | - </div> | |
| 37 | - <h4><%= comment.title.blank? && ' ' || comment.title %></h4> | |
| 38 | - <div class="comment-text"> | |
| 39 | - <p/> | |
| 40 | - <%= txt2html comment.body %> | |
| 41 | - </div> | |
| 42 | - </div> | |
| 43 | - | |
| 44 | - <div class="comment_reply post_comment_box closed"> | |
| 45 | - <% if @comment && @comment.errors.any? && @comment.reply_of_id.to_i == comment.id %> | |
| 46 | - <%= error_messages_for :comment %> | |
| 47 | - <script type="text/javascript"> | |
| 48 | - jQuery(function() { | |
| 49 | - document.location.href = '#<%= comment.anchor %>'; | |
| 50 | - add_comment_reply_form('#comment-reply-to-<%= comment.id %>', <%= comment.id %>); | |
| 51 | - }); | |
| 52 | - </script> | |
| 53 | - <% end %> | |
| 54 | - <%= report_abuse(comment.author, :comment_link, comment) if comment.author %> | |
| 55 | - | |
| 56 | - <% if comment.spam? %> | |
| 57 | - | |
| 58 | - <%= link_to_function(_('Mark as NOT SPAM'), 'remove_comment(this, %s); return false;' % url_for(:mark_comment_as_ham => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide') %> | |
| 59 | - <% else %> | |
| 60 | - <% if (logged_in? && (user == profile || user.has_permission?(:moderate_comments, profile))) %> | |
| 61 | - | |
| 62 | - <%= link_to_function(_('Mark as SPAM'), 'remove_comment(this, %s, %s); return false;' % [url_for(:mark_comment_as_spam => comment.id).to_json, _('Are you sure you want to mark this comment as SPAM?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide') %> | |
| 63 | - <% end %> | |
| 64 | - <% end %> | |
| 65 | - | |
| 66 | - <% if comment.author && comment.author == user %> | |
| 67 | - | |
| 68 | - <%= expirable_comment_link comment, :edit, _('Edit'), {:action => 'edit_comment', :id => comment.id, :profile => profile.identifier} %> | |
| 69 | - <% end %> | |
| 70 | - | |
| 71 | - <% if logged_in? && (user == profile || user == comment.author || user.has_permission?(:moderate_comments, profile)) %> | |
| 72 | - | |
| 73 | - <%= link_to_function(_('Remove'), 'remove_comment(this, %s, %s); return false ;' % [url_for(:profile => params[:profile], :remove_comment => comment.id, :view => params[:view]).to_json, _('Are you sure you want to remove this comment and all its replies?').to_json], :class => 'comment-footer comment-footer-link comment-footer-hide remove-children') %> | |
| 74 | - <% end %> | |
| 75 | - | |
| 76 | - <% unless comment.spam? %> | |
| 77 | - | |
| 78 | - <%= link_to_function _('Reply'), | |
| 79 | - "var f = add_comment_reply_form(this, %s); f.find('comment_title, textarea').val(''); return false" % comment.id, | |
| 80 | - :class => 'comment-footer comment-footer-link comment-footer-hide', | |
| 81 | - :id => 'comment-reply-to-' + comment.id.to_s | |
| 82 | - %> | |
| 83 | - <% end %> | |
| 84 | - </div> | |
| 85 | - | |
| 86 | - <% end %> | |
| 87 | - | |
| 88 | - </div> | |
| 89 | - | |
| 90 | - <% unless comment.replies.blank? || comment.spam? %> | |
| 91 | - <ul class="comment-replies"> | |
| 92 | - <% comment.replies.each do |reply| %> | |
| 93 | - <%= render :partial => 'comment', :locals => { :comment => reply } %> | |
| 94 | - <% end %> | |
| 95 | - </ul> | |
| 96 | - <% end %> | |
| 97 | - | |
| 98 | - </div> | |
| 99 | -</li> |
app/views/content_viewer/_comment_form.rhtml
| ... | ... | @@ -1,88 +0,0 @@ |
| 1 | -<script type="text/javascript"> | |
| 2 | -function submit_comment_form(button) { | |
| 3 | - <% if pass_without_comment_captcha? %> | |
| 4 | - button.form.confirm.value = 'true'; | |
| 5 | - button.disabled = true; | |
| 6 | - button.form.submit(); | |
| 7 | - return true; | |
| 8 | - <% else %> | |
| 9 | - jQuery('#recaptcha-container').show(); | |
| 10 | - jQuery.colorbox({ inline : true, href : '#recaptcha-container', maxWidth : '600px', maxHeight : '300px' }); | |
| 11 | - jQuery('#confirm-captcha').unbind('click'); | |
| 12 | - jQuery('#confirm-captcha').bind('click', function() { | |
| 13 | - jQuery.colorbox.close(); | |
| 14 | - button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val(); | |
| 15 | - button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val(); | |
| 16 | - button.form.confirm.value = 'true'; | |
| 17 | - button.disabled = true; | |
| 18 | - button.form.submit(); | |
| 19 | - }); | |
| 20 | - <% end %> | |
| 21 | -} | |
| 22 | -</script> | |
| 23 | - | |
| 24 | -<% if @comment && @comment.errors.any? && @comment.reply_of_id.blank? %> | |
| 25 | - <%= error_messages_for :comment %> | |
| 26 | - <script type="text/javascript">jQuery(function() { document.location.href = '#page-comment-form'; });</script> | |
| 27 | -<% end %> | |
| 28 | - | |
| 29 | -<% @form_div ||= 'closed' %> | |
| 30 | - | |
| 31 | -<div class="post_comment_box <%= @form_div %>"> | |
| 32 | - | |
| 33 | - <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form') if display_link %> | |
| 34 | - | |
| 35 | -<% unless pass_without_comment_captcha? %> | |
| 36 | - <div id="recaptcha-container" style="display: none"> | |
| 37 | - <h3><%= _('Please type the two words below') %></h3> | |
| 38 | - <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> | |
| 39 | - <% button_bar do %> | |
| 40 | - <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> | |
| 41 | - <%= button_to_function :cancel, _('Cancel'), "jQuery.colorbox.close()" %> | |
| 42 | - <% end %> | |
| 43 | - </div> | |
| 44 | - | |
| 45 | - <script type="text/javascript"> | |
| 46 | - jQuery(document).bind('cbox_cleanup', function() { | |
| 47 | - jQuery('#recaptcha-container').hide(); | |
| 48 | - }); | |
| 49 | - </script> | |
| 50 | -<% end %> | |
| 51 | - | |
| 52 | -<% form_tag( url, { :class => 'comment_form' } ) do %> | |
| 53 | - <%= required_fields_message %> | |
| 54 | - | |
| 55 | - <% unless logged_in? %> | |
| 56 | - | |
| 57 | - <%= required labelled_form_field(_('Name'), text_field(:comment, :name)) %> | |
| 58 | - <%= required labelled_form_field(_('e-mail'), text_field(:comment, :email)) %> | |
| 59 | - <p> | |
| 60 | - <%= _('If you are a registered user, you can login and be automatically recognized.') %> | |
| 61 | - </p> | |
| 62 | - | |
| 63 | - <% end %> | |
| 64 | - | |
| 65 | - <% unless pass_without_comment_captcha? %> | |
| 66 | - <%= hidden_field_tag(:recaptcha_response_field, nil, :id => nil) %> | |
| 67 | - <%= hidden_field_tag(:recaptcha_challenge_field, nil, :id => nil) %> | |
| 68 | - <% end %> | |
| 69 | - | |
| 70 | - <%= labelled_form_field(_('Title'), text_field(:comment, :title)) %> | |
| 71 | - <%= required labelled_form_field(_('Enter your comment'), text_area(:comment, :body, :rows => 5)) %> | |
| 72 | - | |
| 73 | - <%= hidden_field_tag(:confirm, 'false') %> | |
| 74 | - <%= hidden_field_tag(:view, params[:view])%> | |
| 75 | - | |
| 76 | - <% button_bar do %> | |
| 77 | - <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %> | |
| 78 | - <% if cancel_triggers_hide %> | |
| 79 | - <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> | |
| 80 | - <% else %> | |
| 81 | - <%= button('cancel', _('Cancel'), {:action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path})%> | |
| 82 | - <% end %> | |
| 83 | - <% end %> | |
| 84 | -<% end %> | |
| 85 | - | |
| 86 | -</div><!-- end class="post_comment_box" --> | |
| 87 | - | |
| 88 | -<%= javascript_include_tag 'comment_form'%> |
app/views/content_viewer/edit_comment.html.erb
app/views/content_viewer/view_page.rhtml
| ... | ... | @@ -8,6 +8,12 @@ |
| 8 | 8 | |
| 9 | 9 | <%= render :partial => 'confirm_unfollow' %> |
| 10 | 10 | |
| 11 | +<script type="text/javascript"> | |
| 12 | + window.ONE_COMMENT = "<%= _('One comment') %>"; | |
| 13 | + window.COMMENT_PLURAL = "<%= _('comments') %>"; | |
| 14 | + window.NO_COMMENT_YET = "<%= _('No comments yet') %>"; | |
| 15 | +</script> | |
| 16 | + | |
| 11 | 17 | <div id="article-toolbar"></div> |
| 12 | 18 | |
| 13 | 19 | <script type="text/javascript"> |
| ... | ... | @@ -89,15 +95,15 @@ |
| 89 | 95 | <% end %> |
| 90 | 96 | |
| 91 | 97 | <% if @page.accept_comments? && @comments_count > 1 %> |
| 92 | - <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button') %> | |
| 98 | + <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button', :onclick => "jQuery('#page-comment-form .display-comment-form').first().click();") %> | |
| 93 | 99 | <% end %> |
| 94 | 100 | |
| 95 | 101 | <ul class="article-comments-list"> |
| 96 | - <%= render :partial => 'comment', :collection => @comments %> | |
| 102 | + <%= render :partial => 'comment/comment', :collection => @comments %> | |
| 97 | 103 | </ul> |
| 98 | 104 | |
| 99 | 105 | <% if @page.accept_comments? %> |
| 100 | - <div id="page-comment-form"><%= render :partial => 'comment_form', :locals => {:url => url_for(@page.view_url.merge({:only_path => true})), :display_link => true, :cancel_triggers_hide => true}%></div> | |
| 106 | + <div id='page-comment-form' class='page-comment-form'><%= render :partial => 'comment/comment_form', :locals =>{:comment => Comment.new, :url => {:controller => :comment, :action => :create}, :display_link => true, :cancel_triggers_hide => true}%></div> | |
| 101 | 107 | <% end %> |
| 102 | 108 | </div><!-- end class="comments" --> |
| 103 | 109 | ... | ... |
app/views/layouts/application-ng.rhtml
| ... | ... | @@ -17,6 +17,10 @@ |
| 17 | 17 | content.respond_to?(:call) ? content.call : content |
| 18 | 18 | end.join("\n") |
| 19 | 19 | %> |
| 20 | + | |
| 21 | + <script type='text/javascript'> | |
| 22 | + DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>; | |
| 23 | + </script> | |
| 20 | 24 | </head> |
| 21 | 25 | <body class="<%= body_classes %>"> |
| 22 | 26 | <a href="#content" id="link-go-content"><span><%= _("Go to the content") %></span></a> | ... | ... |
app/views/spam/index.rhtml
| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | <div id='article'> |
| 9 | 9 | <div class="comments" id="comments_list"> |
| 10 | 10 | <ul class="article-comments-list"> |
| 11 | - <%= render :partial => 'content_viewer/comment', :collection => @spam %> | |
| 11 | + <%= render :partial => 'comment/comment', :collection => @spam %> | |
| 12 | 12 | </ul> |
| 13 | 13 | </div> |
| 14 | 14 | </div> | ... | ... |
config/routes.rb
| ... | ... | @@ -76,6 +76,9 @@ ActionController::Routing::Routes.draw do |map| |
| 76 | 76 | # profile search |
| 77 | 77 | map.profile_search 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format}/ |
| 78 | 78 | |
| 79 | + # comments | |
| 80 | + map.comment 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format}/ | |
| 81 | + | |
| 79 | 82 | # public profile information |
| 80 | 83 | map.profile 'profile/:profile/:action/:id', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format}/ |
| 81 | 84 | |
| ... | ... | @@ -122,7 +125,6 @@ ActionController::Routing::Routes.draw do |map| |
| 122 | 125 | # cache stuff - hack |
| 123 | 126 | map.cache 'public/:action/:id', :controller => 'public' |
| 124 | 127 | |
| 125 | - map.connect ':profile/edit_comment/:id/*page', :controller => 'content_viewer', :action => 'edit_comment', :profile => /#{Noosfero.identifier_format}/ | |
| 126 | 128 | |
| 127 | 129 | # match requests for profiles that don't have a custom domain |
| 128 | 130 | map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | ... | ... |
lib/noosfero/plugin.rb
| ... | ... | @@ -320,6 +320,30 @@ class Noosfero::Plugin |
| 320 | 320 | def comment_marked_as_ham(comment) |
| 321 | 321 | end |
| 322 | 322 | |
| 323 | + # Adds extra actions for comments | |
| 324 | + # returns = list of hashes or lambda block that creates a list of hashes | |
| 325 | + # example: | |
| 326 | + # | |
| 327 | + # def comment_actions(comment) | |
| 328 | + # [{:link => link_to_function(...)}] | |
| 329 | + # end | |
| 330 | + # | |
| 331 | + def comment_actions(comment) | |
| 332 | + nil | |
| 333 | + end | |
| 334 | + | |
| 335 | + # This method is called when the user click on comment actions menu. | |
| 336 | + # returns = list or lambda block that return ids of enabled menu items for comments | |
| 337 | + # example: | |
| 338 | + # | |
| 339 | + # def check_comment_actions(comment) | |
| 340 | + # ['#action1', '#action2'] | |
| 341 | + # end | |
| 342 | + # | |
| 343 | + def check_comment_actions(comment) | |
| 344 | + [] | |
| 345 | + end | |
| 346 | + | |
| 323 | 347 | # -> Adds fields to the signup form |
| 324 | 348 | # returns = lambda block that creates html code |
| 325 | 349 | def signup_extra_contents | ... | ... |
plugins/require_auth_to_comment/lib/require_auth_to_comment_plugin.rb
plugins/require_auth_to_comment/public/hide_comment_form.js
| 1 | 1 | (function($) { |
| 2 | 2 | $(window).bind('userDataLoaded', function(event, data) { |
| 3 | - if (data.login || $('meta[name="profile.allow_unauthenticated_comments"]').length > 0) { | |
| 4 | - $('.post-comment-button').show(); | |
| 5 | - $('#page-comment-form').show(); | |
| 6 | - $('.comment-footer').show(); | |
| 3 | + if (data.login || $('meta[name=profile.allow_unauthenticated_comments]').length > 0) { | |
| 4 | + $('.post-comment-button').livequery(function() { | |
| 5 | + $(this).show(); | |
| 6 | + }); | |
| 7 | + $('.page-comment-form').livequery(function() { | |
| 8 | + $(this).show(); | |
| 9 | + }); | |
| 10 | + $('.comment-footer').livequery(function() { | |
| 11 | + $(this).show(); | |
| 12 | + }); | |
| 7 | 13 | } |
| 8 | 14 | }); |
| 9 | 15 | })(jQuery); | ... | ... |
plugins/require_auth_to_comment/public/jquery.livequery.min.js
0 → 100644
| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | +/* Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net) | |
| 2 | + * Dual licensed under the MIT (MIT_LICENSE.txt) | |
| 3 | + * and GPL Version 2 (GPL_LICENSE.txt) licenses. | |
| 4 | + * | |
| 5 | + * Version: 1.1.1 | |
| 6 | + * Requires jQuery 1.3+ | |
| 7 | + * Docs: http://docs.jquery.com/Plugins/livequery | |
| 8 | + */ | |
| 9 | +(function(a){a.extend(a.fn,{livequery:function(e,d,c){var b=this,f;if(a.isFunction(e)){c=d,d=e,e=undefined}a.each(a.livequery.queries,function(g,h){if(b.selector==h.selector&&b.context==h.context&&e==h.type&&(!d||d.$lqguid==h.fn.$lqguid)&&(!c||c.$lqguid==h.fn2.$lqguid)){return(f=h)&&false}});f=f||new a.livequery(this.selector,this.context,e,d,c);f.stopped=false;f.run();return this},expire:function(e,d,c){var b=this;if(a.isFunction(e)){c=d,d=e,e=undefined}a.each(a.livequery.queries,function(f,g){if(b.selector==g.selector&&b.context==g.context&&(!e||e==g.type)&&(!d||d.$lqguid==g.fn.$lqguid)&&(!c||c.$lqguid==g.fn2.$lqguid)&&!this.stopped){a.livequery.stop(g.id)}});return this}});a.livequery=function(b,d,f,e,c){this.selector=b;this.context=d;this.type=f;this.fn=e;this.fn2=c;this.elements=[];this.stopped=false;this.id=a.livequery.queries.push(this)-1;e.$lqguid=e.$lqguid||a.livequery.guid++;if(c){c.$lqguid=c.$lqguid||a.livequery.guid++}return this};a.livequery.prototype={stop:function(){var b=this;if(this.type){this.elements.unbind(this.type,this.fn)}else{if(this.fn2){this.elements.each(function(c,d){b.fn2.apply(d)})}}this.elements=[];this.stopped=true},run:function(){if(this.stopped){return}var d=this;var e=this.elements,c=a(this.selector,this.context),b=c.not(e);this.elements=c;if(this.type){b.bind(this.type,this.fn);if(e.length>0){a.each(e,function(f,g){if(a.inArray(g,c)<0){a.event.remove(g,d.type,d.fn)}})}}else{b.each(function(){d.fn.apply(this)});if(this.fn2&&e.length>0){a.each(e,function(f,g){if(a.inArray(g,c)<0){d.fn2.apply(g)}})}}}};a.extend(a.livequery,{guid:0,queries:[],queue:[],running:false,timeout:null,checkQueue:function(){if(a.livequery.running&&a.livequery.queue.length){var b=a.livequery.queue.length;while(b--){a.livequery.queries[a.livequery.queue.shift()].run()}}},pause:function(){a.livequery.running=false},play:function(){a.livequery.running=true;a.livequery.run()},registerPlugin:function(){a.each(arguments,function(c,d){if(!a.fn[d]){return}var b=a.fn[d];a.fn[d]=function(){var e=b.apply(this,arguments);a.livequery.run();return e}})},run:function(b){if(b!=undefined){if(a.inArray(b,a.livequery.queue)<0){a.livequery.queue.push(b)}}else{a.each(a.livequery.queries,function(c){if(a.inArray(c,a.livequery.queue)<0){a.livequery.queue.push(c)}})}if(a.livequery.timeout){clearTimeout(a.livequery.timeout)}a.livequery.timeout=setTimeout(a.livequery.checkQueue,20)},stop:function(b){if(b!=undefined){a.livequery.queries[b].stop()}else{a.each(a.livequery.queries,function(c){a.livequery.queries[c].stop()})}}});a.livequery.registerPlugin("append","prepend","after","before","wrap","attr","removeAttr","addClass","removeClass","toggleClass","empty","remove","html");a(function(){a.livequery.play()})})(jQuery); | |
| 0 | 10 | \ No newline at end of file | ... | ... |
plugins/require_auth_to_comment/public/style.css
public/designs/themes/base/style.css
public/javascripts/add-and-join.js
| ... | ... | @@ -100,4 +100,24 @@ jQuery(function($) { |
| 100 | 100 | clicked.parent().find(".send-an-email").fadeOut(); |
| 101 | 101 | }) |
| 102 | 102 | }) |
| 103 | + | |
| 104 | + $(".comment-trigger").live('click', function(){ | |
| 105 | + clicked = $(this); | |
| 106 | + url = clicked.attr("url"); | |
| 107 | + $.get(url, function(data){ | |
| 108 | + ids = []; | |
| 109 | + if(data && data.ids) { | |
| 110 | + for(var i=0; i<data.ids.length; i++) { | |
| 111 | + clicked.parent().find(data.ids[i]).fadeIn(); | |
| 112 | + ids.push(data.ids[i]); | |
| 113 | + } | |
| 114 | + } | |
| 115 | + clicked.parent().find('.comment-action-extra').each(function() { | |
| 116 | + if($.inArray('#'+$(this).attr('id'), ids)) | |
| 117 | + $(this).fadeOut(); | |
| 118 | + }); | |
| 119 | + }) | |
| 120 | + return false; | |
| 121 | + }) | |
| 122 | + | |
| 103 | 123 | }); | ... | ... |
public/javascripts/application.js
| ... | ... | @@ -79,6 +79,27 @@ function updateUrlField(name_field, id) { |
| 79 | 79 | } |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | + | |
| 83 | + | |
| 84 | +jQuery.fn.centerInForm = function () { | |
| 85 | + var $ = jQuery; | |
| 86 | + var form = $(this).parent('form'); | |
| 87 | + this.css("position", "absolute"); | |
| 88 | + this.css("top", (form.height() - this.height())/ 2 + form.scrollTop() + "px"); | |
| 89 | + this.css("left", (form.width() - this.width()) / 2 + form.scrollLeft() + "px"); | |
| 90 | + this.css("width", form.width() + "px"); | |
| 91 | + this.css("height", form.height() + "px"); | |
| 92 | + return this; | |
| 93 | +} | |
| 94 | + | |
| 95 | +jQuery.fn.center = function () { | |
| 96 | + var $ = jQuery; | |
| 97 | + this.css("position", "absolute"); | |
| 98 | + this.css("top", ($(window).height() - this.height())/ 2 + $(window).scrollTop() + "px"); | |
| 99 | + this.css("left", ($(window).width() - this.width()) / 2 + $(window).scrollLeft() + "px"); | |
| 100 | + return this; | |
| 101 | +} | |
| 102 | + | |
| 82 | 103 | function show_warning(field, message) { |
| 83 | 104 | new Effect.Highlight(field, {duration:3}); |
| 84 | 105 | $(message).show(); |
| ... | ... | @@ -146,8 +167,9 @@ function loading_done(element_id) { |
| 146 | 167 | jQuery(element_id).removeClass('small-loading-dark'); |
| 147 | 168 | } |
| 148 | 169 | function open_loading(message) { |
| 149 | - jQuery('body').append("<div id='overlay_loading' class='ui-widget-overlay' style='display: none'/><div id='overlay_loading_modal' style='display: none'><p>"+message+"</p><img src='/images/loading-dark.gif'/></div>"); | |
| 170 | + jQuery('body').prepend("<div id='overlay_loading' class='ui-widget-overlay' style='display: none'/><div id='overlay_loading_modal' style='display: none'><p>"+message+"</p><img src='/images/loading-dark.gif'/></div>"); | |
| 150 | 171 | jQuery('#overlay_loading').show(); |
| 172 | + jQuery('#overlay_loading_modal').center(); | |
| 151 | 173 | jQuery('#overlay_loading_modal').fadeIn('slow'); |
| 152 | 174 | } |
| 153 | 175 | function close_loading() { |
| ... | ... | @@ -292,11 +314,17 @@ function toggleSubmenu(trigger, title, link_list) { |
| 292 | 314 | content.append('<h4>' + title + '</h4>'); |
| 293 | 315 | jQuery.each(link_list, function(index, link_hash) { |
| 294 | 316 | for (label in link_hash) { |
| 295 | - options = ""; | |
| 296 | - jQuery.each(link_hash[label], function(option, value){ | |
| 297 | - options += option +'="'+ value + '" '; | |
| 298 | - }) | |
| 299 | - list.append('<li><a '+ options +'>' + label + '</a></li>'); | |
| 317 | + if(link_hash[label]!=null) { | |
| 318 | + if(label=='link' && jQuery.type(link_hash[label])=="string") { | |
| 319 | + list.append('<li>' + link_hash[label] + '</li>'); | |
| 320 | + } else { | |
| 321 | + options = ""; | |
| 322 | + jQuery.each(link_hash[label], function(option, value){ | |
| 323 | + options += option +'="'+ value + '" '; | |
| 324 | + }) | |
| 325 | + list.append('<li><a '+ options +'>' + label + '</a></li>'); | |
| 326 | + } | |
| 327 | + } | |
| 300 | 328 | } |
| 301 | 329 | }); |
| 302 | 330 | content.append(list); |
| ... | ... | @@ -320,9 +348,9 @@ function hideAllSubmenus() { |
| 320 | 348 | // Hide visible ballons when clicked outside them |
| 321 | 349 | jQuery(document).ready(function() { |
| 322 | 350 | jQuery('body').live('click', function() { hideAllSubmenus(); }); |
| 323 | - jQuery('.menu-submenu-trigger').click(function(e) { e.stopPropagation(); }); | |
| 324 | - jQuery('.simplemenu-trigger').click(function(e) { e.stopPropagation(); }); | |
| 325 | - jQuery('#chat-online-users').click(function(e) { e.stopPropagation(); }); | |
| 351 | + jQuery('.menu-submenu-trigger').live('click', function(e) { e.stopPropagation(); }); | |
| 352 | + jQuery('.simplemenu-trigger').live('click', function(e) { e.stopPropagation(); }); | |
| 353 | + jQuery('#chat-online-users').live('click', function(e) { e.stopPropagation(); }); | |
| 326 | 354 | }); |
| 327 | 355 | |
| 328 | 356 | function input_javascript_ordering_stuff() { |
| ... | ... | @@ -688,22 +716,51 @@ jQuery(function($) { |
| 688 | 716 | }); |
| 689 | 717 | |
| 690 | 718 | function add_comment_reply_form(button, comment_id) { |
| 691 | - var container = jQuery(button).parents('.comment_reply'); | |
| 719 | + //var container = jQuery(button).parents('.comment_reply'); | |
| 720 | + var container = jQuery('#comment_reply_to_'+comment_id); | |
| 692 | 721 | var f = container.find('.comment_form'); |
| 693 | 722 | if (f.length == 0) { |
| 694 | - f = jQuery('#page-comment-form .comment_form').clone(); | |
| 695 | - f.find('.fieldWithErrors').map(function() { jQuery(this).replaceWith(jQuery(this).contents()); }); | |
| 696 | - f.prepend('<input type="hidden" name="comment[reply_of_id]" value="' + comment_id + '" />'); | |
| 697 | - container.append(f); | |
| 723 | + comments_div = jQuery(button).parents('.comments'); | |
| 724 | + f = comments_div.find('.comment_form').first().clone(); | |
| 725 | + f.find('.errorExplanation').remove(); | |
| 726 | + f.append('<input type="hidden" name="comment[reply_of_id]" value="' + comment_id + '" />'); | |
| 727 | + container.append('<div class="page-comment-form"></div>'); | |
| 728 | + container.find('.page-comment-form').append(f); | |
| 698 | 729 | } |
| 699 | 730 | if (container.hasClass('closed')) { |
| 700 | 731 | container.removeClass('closed'); |
| 701 | 732 | container.addClass('opened'); |
| 702 | 733 | container.find('.comment_form input[type=text]:visible:first').focus(); |
| 703 | 734 | } |
| 735 | + jQuery('.display-comment-form').hide(); | |
| 704 | 736 | return f; |
| 705 | 737 | } |
| 706 | 738 | |
| 739 | +function update_comment_count(element, new_count) { | |
| 740 | + var $ = jQuery; | |
| 741 | + var content = ''; | |
| 742 | + var parent_element = element.parent(); | |
| 743 | + | |
| 744 | + write_out = parent_element.find('.comment-count-write-out'); | |
| 745 | + | |
| 746 | + element.html(new_count); | |
| 747 | + | |
| 748 | + if(new_count == 0) { | |
| 749 | + content = NO_COMMENT_YET; | |
| 750 | + parent_element.addClass("no-comments-yet"); | |
| 751 | + } else if(new_count == 1) { | |
| 752 | + parent_element.removeClass("no-comments-yet"); | |
| 753 | + content = ONE_COMMENT; | |
| 754 | + } else { | |
| 755 | + content = new_count + ' ' + COMMENT_PLURAL; | |
| 756 | + } | |
| 757 | + | |
| 758 | + if(write_out){ | |
| 759 | + write_out.html(content); | |
| 760 | + } | |
| 761 | + | |
| 762 | +} | |
| 763 | + | |
| 707 | 764 | function remove_comment(button, url, msg) { |
| 708 | 765 | var $ = jQuery; |
| 709 | 766 | var $button = $(button); |
| ... | ... | @@ -716,17 +773,27 @@ function remove_comment(button, url, msg) { |
| 716 | 773 | if (data.ok) { |
| 717 | 774 | var $comment = $button.closest('.article-comment'); |
| 718 | 775 | var $replies = $comment.find('.comment-replies .article-comment'); |
| 719 | - $comment.slideUp(); | |
| 776 | + | |
| 777 | + var $comments_div = $button.closest('.comments'); | |
| 778 | + | |
| 720 | 779 | var comments_removed = 1; |
| 721 | - if ($button.hasClass('remove-children')) { | |
| 722 | - comments_removed = 1 + $replies.size(); | |
| 723 | - } else { | |
| 724 | - $replies.appendTo('.article-comments-list'); | |
| 725 | - } | |
| 726 | - $('.comment-count').each(function() { | |
| 727 | - var count = parseInt($(this).html()); | |
| 728 | - $(this).html(count - comments_removed); | |
| 780 | + $comment.slideUp(400, function() { | |
| 781 | + if ($button.hasClass('remove-children')) { | |
| 782 | + comments_removed = 1 + $replies.size(); | |
| 783 | + } else { | |
| 784 | + $replies.appendTo('.article-comments-list'); | |
| 785 | + } | |
| 786 | + | |
| 787 | + $comments_div.find('.comment-count').add('#article-header .comment-count').each(function() { | |
| 788 | + var count = parseInt($(this).html()); | |
| 789 | + update_comment_count($(this), count - comments_removed); | |
| 790 | + }); | |
| 791 | + $(this).remove(); | |
| 729 | 792 | }); |
| 793 | + | |
| 794 | + }else{ | |
| 795 | + $button.removeClass('comment-button-loading'); | |
| 796 | + return; | |
| 730 | 797 | } |
| 731 | 798 | }); |
| 732 | 799 | } | ... | ... |
public/javascripts/comment_form.js
| 1 | +jQuery('.display-comment-form').unbind(); | |
| 1 | 2 | jQuery('.display-comment-form').click(function(){ |
| 2 | - toggleBox('.post_comment_box'); | |
| 3 | + var $button = jQuery(this); | |
| 4 | + toggleBox($button.parents('.post_comment_box')); | |
| 3 | 5 | jQuery('.display-comment-form').hide(); |
| 4 | - jQuery('form.comment_form input').first().focus(); | |
| 6 | + $button.closest('.page-comment-form').find('input').first().focus(); | |
| 5 | 7 | return false; |
| 6 | 8 | }); |
| 7 | 9 | |
| 8 | -jQuery('#cancel-comment').click(function(){ | |
| 9 | - toggleBox('.post_comment_box'); | |
| 10 | - jQuery('.display-comment-form').show(); | |
| 11 | - return false | |
| 12 | -}) | |
| 10 | +jQuery('#cancel-comment').die(); | |
| 11 | +jQuery('#cancel-comment').live("click", function(){ | |
| 12 | + var $button = jQuery(this); | |
| 13 | + toggleBox($button.parents('.post_comment_box')); | |
| 14 | + show_display_comment_button(); | |
| 15 | + var page_comment_form = $button.parents('.page-comment-form'); | |
| 16 | + page_comment_form.find('.errorExplanation').remove(); | |
| 17 | + return false; | |
| 18 | +}); | |
| 13 | 19 | |
| 14 | -function toggleBox(div_selector){ | |
| 15 | - div = jQuery(div_selector); | |
| 20 | +function toggleBox(div){ | |
| 16 | 21 | if(div.hasClass('opened')) { |
| 17 | 22 | div.removeClass('opened'); |
| 18 | 23 | div.addClass('closed'); |
| ... | ... | @@ -21,3 +26,67 @@ function toggleBox(div_selector){ |
| 21 | 26 | div.addClass('opened'); |
| 22 | 27 | } |
| 23 | 28 | } |
| 29 | + | |
| 30 | +function save_comment(button) { | |
| 31 | + var $ = jQuery; | |
| 32 | + open_loading(DEFAULT_LOADING_MESSAGE); | |
| 33 | + var $button = $(button); | |
| 34 | + var form = $button.parents("form"); | |
| 35 | + var post_comment_box = $button.parents('.post_comment_box'); | |
| 36 | + var comment_div = $button.parents('.comments'); | |
| 37 | + var page_comment_form = $button.parents('.page-comment-form'); | |
| 38 | + $button.addClass('comment-button-loading'); | |
| 39 | + $.post(form.attr("action"), form.serialize(), function(data) { | |
| 40 | + | |
| 41 | + if(data.render_target == null) { | |
| 42 | + //Comment for approval | |
| 43 | + form.find("input[type='text']").add('textarea').each(function() { | |
| 44 | + this.value = ''; | |
| 45 | + }); | |
| 46 | + page_comment_form.find('.errorExplanation').remove(); | |
| 47 | + } else if(data.render_target == 'form') { | |
| 48 | + //Comment with errors | |
| 49 | + $.scrollTo(page_comment_form); | |
| 50 | + page_comment_form.html(data.html); | |
| 51 | + $('.display-comment-form').hide(); | |
| 52 | + } else if($('#' + data.render_target).size() > 0) { | |
| 53 | + //Comment of reply | |
| 54 | + $('#'+ data.render_target).replaceWith(data.html); | |
| 55 | + $('#' + data.render_target).effect("highlight", {}, 3000); | |
| 56 | + $.colorbox.close(); | |
| 57 | + } else { | |
| 58 | + //New comment of article | |
| 59 | + comment_div.find('.article-comments-list').append(data.html); | |
| 60 | + | |
| 61 | + form.find("input[type='text']").add('textarea').each(function() { | |
| 62 | + this.value = ''; | |
| 63 | + }); | |
| 64 | + | |
| 65 | + page_comment_form.find('.errorExplanation').remove(); | |
| 66 | + $.colorbox.close(); | |
| 67 | + } | |
| 68 | + | |
| 69 | + comment_div.find('.comment-count').add('#article-header .comment-count').each(function() { | |
| 70 | + var count = parseInt($(this).html()); | |
| 71 | + update_comment_count($(this), count + 1); | |
| 72 | + }); | |
| 73 | + | |
| 74 | + if(jQuery('#recaptcha_response_field').val()){ | |
| 75 | + Recaptcha.reload(); | |
| 76 | + } | |
| 77 | + | |
| 78 | + if(data.msg != null) { | |
| 79 | + display_notice(data.msg); | |
| 80 | + } | |
| 81 | + close_loading(); | |
| 82 | + toggleBox($button.closest('.post_comment_box')); | |
| 83 | + show_display_comment_button(); | |
| 84 | + $button.removeClass('comment-button-loading'); | |
| 85 | + $button.enable(); | |
| 86 | + }, 'json'); | |
| 87 | +} | |
| 88 | + | |
| 89 | +function show_display_comment_button() { | |
| 90 | + if(jQuery('.post_comment_box.opened').length==0) | |
| 91 | + jQuery('.display-comment-form').show(); | |
| 92 | +} | ... | ... |
public/stylesheets/application.css
| ... | ... | @@ -528,11 +528,15 @@ code input { |
| 528 | 528 | background: transparent url(../images/loading-small-dark.gif) no-repeat 10% center; |
| 529 | 529 | } |
| 530 | 530 | #overlay_loading { |
| 531 | - z-index: 100; | |
| 532 | - cursor: progress; | |
| 531 | + z-index: 10000; | |
| 532 | + top: 0; | |
| 533 | + left: 0; | |
| 534 | + position: fixed; | |
| 535 | + width: 100%; | |
| 536 | + height: 100%; | |
| 533 | 537 | } |
| 534 | 538 | #overlay_loading_modal { |
| 535 | - z-index: 101; | |
| 539 | + z-index: 10001; | |
| 536 | 540 | width: 160px; |
| 537 | 541 | height: 120px; |
| 538 | 542 | border: 1px solid #000; |
| ... | ... | @@ -998,6 +1002,9 @@ code input { |
| 998 | 1002 | |
| 999 | 1003 | .comments { |
| 1000 | 1004 | } |
| 1005 | +span.comment-count.hide{ | |
| 1006 | + display: none; | |
| 1007 | +} | |
| 1001 | 1008 | #content .no-comments-yet { |
| 1002 | 1009 | text-align: center; |
| 1003 | 1010 | font-size: 80%; |
| ... | ... | @@ -1018,7 +1025,7 @@ code input { |
| 1018 | 1025 | margin-bottom: 10px; |
| 1019 | 1026 | padding: 4px; |
| 1020 | 1027 | } |
| 1021 | -#article .article-comment h4 { | |
| 1028 | +#article .article-comment .comment-details h4 { | |
| 1022 | 1029 | font-size: 13px; |
| 1023 | 1030 | margin: 0px; |
| 1024 | 1031 | display: inline; |
| ... | ... | @@ -1291,6 +1298,10 @@ a.comment-picture { |
| 1291 | 1298 | -webkit-border-radius: 4px; |
| 1292 | 1299 | border-radius: 4px; |
| 1293 | 1300 | } |
| 1301 | +.post_comment_box.opened h4 { | |
| 1302 | + border: none; | |
| 1303 | + cursor: default; | |
| 1304 | +} | |
| 1294 | 1305 | .post_comment_box.opened { |
| 1295 | 1306 | border: 1px solid #888; |
| 1296 | 1307 | background: #eee; |
| ... | ... | @@ -1341,6 +1352,11 @@ a.comment-picture { |
| 1341 | 1352 | .post_comment_box.comment_reply #comment_title { |
| 1342 | 1353 | width: 100%; |
| 1343 | 1354 | } |
| 1355 | + | |
| 1356 | +#page-comment-form-template { | |
| 1357 | + display:none; | |
| 1358 | +} | |
| 1359 | + | |
| 1344 | 1360 | #page-comment-form .post_comment_box { |
| 1345 | 1361 | text-align: left; |
| 1346 | 1362 | padding-left: 0; |
| ... | ... | @@ -1656,13 +1672,15 @@ a.button.disabled, input.disabled { |
| 1656 | 1672 | * Block options editor floating window * |
| 1657 | 1673 | ****************************************/ |
| 1658 | 1674 | |
| 1675 | +/* FIXME This changes broke colorboxes all over the place. | |
| 1676 | + * Therefore I'm canceling them until they are properly treateda. */ | |
| 1659 | 1677 | #cboxLoadedContent { |
| 1660 | 1678 | background: #FFF; |
| 1661 | - box-shadow: 0 0 15px #888 inset; | |
| 1662 | - border-radius: 5px; | |
| 1663 | - border: 1px solid #777; | |
| 1664 | - border-left: none; | |
| 1665 | - border-right: none; | |
| 1679 | +/* box-shadow: 0 0 15px #888 inset; | |
| 1680 | + border-radius: 5px; | |
| 1681 | + border: 1px solid #777; | |
| 1682 | + border-left: none; | |
| 1683 | + border-right: none; */ | |
| 1666 | 1684 | } |
| 1667 | 1685 | |
| 1668 | 1686 | .block-config-options { |
| ... | ... | @@ -1786,13 +1804,32 @@ a.button.disabled, input.disabled { |
| 1786 | 1804 | #content .profile-list-block ul { |
| 1787 | 1805 | width: 200px; |
| 1788 | 1806 | } |
| 1789 | -#content .common-profile-list-block li { | |
| 1790 | - margin: 0px; | |
| 1807 | +#content .comment-header .comment-actions-reply { | |
| 1808 | + float: right; | |
| 1809 | + background-image: url(/designs/icons/tango/Tango/16x16/actions/go-jump.png); | |
| 1810 | + height: 12px; | |
| 1811 | +} | |
| 1812 | +#content .comment-header ul { | |
| 1813 | + float: right; | |
| 1814 | + margin: 1px 0px 14px 0px; | |
| 1815 | +} | |
| 1816 | +#content .comment-actions .menu-submenu-header, #content .comment-actions .menu-submenu-footer, #content .comment-actions .menu-submenu h4 { | |
| 1817 | + display: none; | |
| 1818 | +} | |
| 1819 | +#content .comment-actions .menu-submenu ul { | |
| 1820 | + border: 1px solid #888a85; | |
| 1821 | + background-color: #efefef; | |
| 1822 | + padding-right: 2px; | |
| 1823 | + height: auto; | |
| 1824 | + display: block; | |
| 1825 | +} | |
| 1826 | +#content .common-profile-list-block li, #content .comment-actions li { | |
| 1827 | + margin: 0px !important; | |
| 1791 | 1828 | padding: 0px; |
| 1792 | 1829 | list-style: none; |
| 1793 | 1830 | position: relative; |
| 1794 | 1831 | } |
| 1795 | -.common-profile-list-block .vcard a { | |
| 1832 | +.common-profile-list-block .vcard a, .comment-actions .vcard a { | |
| 1796 | 1833 | display: block; |
| 1797 | 1834 | height: 112px; |
| 1798 | 1835 | max-height: 112px; |
| ... | ... | @@ -1803,7 +1840,7 @@ a.button.disabled, input.disabled { |
| 1803 | 1840 | text-align: center; |
| 1804 | 1841 | overflow: hidden; |
| 1805 | 1842 | font-size: 11px; |
| 1806 | - text-decoration: none; | |
| 1843 | + text-decoration: none !important; | |
| 1807 | 1844 | color: #000; |
| 1808 | 1845 | position: relative; |
| 1809 | 1846 | cursor: pointer; /* work arround bug for MSIE */ |
| ... | ... | @@ -4559,11 +4596,17 @@ h1#agenda-title { |
| 4559 | 4596 | } |
| 4560 | 4597 | /* Profile balloon */ |
| 4561 | 4598 | |
| 4562 | -.common-profile-list-block .vcard { | |
| 4599 | +.common-profile-list-block .vcard, .comment-actions .vcard { | |
| 4563 | 4600 | position: relative !important; |
| 4564 | 4601 | float: left; |
| 4565 | 4602 | } |
| 4566 | -.common-profile-list-block .vcard .menu-submenu-trigger, .menu-submenu-trigger { | |
| 4603 | +#content .comment-actions .vcard { | |
| 4604 | + padding-right: 20px; | |
| 4605 | +} | |
| 4606 | +#content .comment-actions .vcard .menu-submenu-trigger { | |
| 4607 | + display: block; | |
| 4608 | +} | |
| 4609 | +.common-profile-list-block .vcard .menu-submenu-trigger, .menu-submenu-trigger, .comment-actions .vcard .menu-submenu-trigger { | |
| 4567 | 4610 | display: none; |
| 4568 | 4611 | width: 16px; |
| 4569 | 4612 | height: 16px; |
| ... | ... | @@ -4577,7 +4620,7 @@ h1#agenda-title { |
| 4577 | 4620 | -moz-border-radius: 5px; |
| 4578 | 4621 | -webkit-border-radius: 5px; |
| 4579 | 4622 | } |
| 4580 | -.common-profile-list-block .vcard .menu-submenu-trigger:hover, .menu-submenu-trigger:hover { | |
| 4623 | +.common-profile-list-block .vcard .menu-submenu-trigger:hover, .menu-submenu-trigger:hover, .comment-actions .vcard .menu-submenu-trigger:hover { | |
| 4581 | 4624 | background: #fff url(/images/top-arrow.png) center center no-repeat; |
| 4582 | 4625 | border: 1px solid #ccc; |
| 4583 | 4626 | } |
| ... | ... | @@ -4596,6 +4639,10 @@ h1#agenda-title { |
| 4596 | 4639 | padding: 0; |
| 4597 | 4640 | text-align: left; |
| 4598 | 4641 | } |
| 4642 | +.comment-details .menu-submenu { | |
| 4643 | + bottom: 0px; | |
| 4644 | + right: -134px; | |
| 4645 | +} | |
| 4599 | 4646 | .box-2 .menu-submenu, .box-3 .menu-submenu { |
| 4600 | 4647 | bottom: 78px; |
| 4601 | 4648 | right: -44px; |
| ... | ... | @@ -4630,7 +4677,7 @@ h1#agenda-title { |
| 4630 | 4677 | .msie7 #search-results .menu-submenu-trigger { |
| 4631 | 4678 | width: 20px !important; |
| 4632 | 4679 | } |
| 4633 | -.common-profile-list-block .vcard .menu-submenu a { | |
| 4680 | +.common-profile-list-block .vcard .menu-submenu a, .comment-actions .vcard .menu-submenu a { | |
| 4634 | 4681 | float: none; |
| 4635 | 4682 | display: block; |
| 4636 | 4683 | height: auto; | ... | ... |
| ... | ... | @@ -0,0 +1,562 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | +require 'comment_controller' | |
| 3 | + | |
| 4 | +# Re-raise errors caught by the controller. | |
| 5 | +class CommentController; def rescue_action(e) raise e end; end | |
| 6 | + | |
| 7 | +class CommentControllerTest < ActionController::TestCase | |
| 8 | + | |
| 9 | + def setup | |
| 10 | + @controller = CommentController.new | |
| 11 | + @request = ActionController::TestRequest.new | |
| 12 | + @response = ActionController::TestResponse.new | |
| 13 | + | |
| 14 | + @profile = create_user('testinguser').person | |
| 15 | + @environment = @profile.environment | |
| 16 | + end | |
| 17 | + attr_reader :profile, :environment | |
| 18 | + | |
| 19 | + should "not be able to remove other people's comments if not moderator or admin" do | |
| 20 | + create_user('normaluser') | |
| 21 | + profile = create_user('testuser').person | |
| 22 | + article = profile.articles.build(:name => 'test') | |
| 23 | + article.save! | |
| 24 | + | |
| 25 | + commenter = create_user('otheruser').person | |
| 26 | + comment = fast_create(Comment, :source_id => article, :title => 'a comment', :body => 'lalala') | |
| 27 | + | |
| 28 | + login_as 'normaluser' # normaluser cannot remove other people's comments | |
| 29 | + assert_no_difference Comment, :count do | |
| 30 | + post :destroy, :profile => profile.identifier, :id => comment.id | |
| 31 | + end | |
| 32 | + end | |
| 33 | + | |
| 34 | + should "not be able to remove other people's comments if not moderator or admin and return json if is an ajax request" do | |
| 35 | + create_user('normaluser') | |
| 36 | + profile = create_user('testuser').person | |
| 37 | + article = profile.articles.build(:name => 'test') | |
| 38 | + article.save! | |
| 39 | + | |
| 40 | + commenter = create_user('otheruser').person | |
| 41 | + comment = fast_create(Comment, :source_id => article, :author_id => commenter, :title => 'a comment', :body => 'lalala') | |
| 42 | + | |
| 43 | + login_as 'normaluser' # normaluser cannot remove other people's comments | |
| 44 | + assert_no_difference Comment, :count do | |
| 45 | + xhr :post, :destroy, :profile => profile.identifier, :id => comment.id | |
| 46 | + assert_response :success | |
| 47 | + end | |
| 48 | + assert_match /\{\"ok\":false\}/, @response.body | |
| 49 | + end | |
| 50 | + | |
| 51 | + should 'be able to remove comments on their articles' do | |
| 52 | + profile = create_user('testuser').person | |
| 53 | + article = profile.articles.build(:name => 'test') | |
| 54 | + article.save! | |
| 55 | + | |
| 56 | + commenter = create_user('otheruser').person | |
| 57 | + comment = fast_create(Comment, :source_id => article, :author_id => commenter, :title => 'a comment', :body => 'lalala') | |
| 58 | + | |
| 59 | + login_as 'testuser' # testuser must be able to remove comments in his articles | |
| 60 | + assert_difference Comment, :count, -1 do | |
| 61 | + xhr :post, :destroy, :profile => profile.identifier, :id => comment.id | |
| 62 | + assert_response :success | |
| 63 | + end | |
| 64 | + assert_match /\{\"ok\":true\}/, @response.body | |
| 65 | + end | |
| 66 | + | |
| 67 | + should 'be able to remove comments of their images' do | |
| 68 | + profile = create_user('testuser').person | |
| 69 | + | |
| 70 | + image = UploadedFile.create!(:profile => profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | |
| 71 | + image.save! | |
| 72 | + | |
| 73 | + commenter = create_user('otheruser').person | |
| 74 | + comment = fast_create(Comment, :source_id => image, :author_id => commenter, :title => 'a comment', :body => 'lalala') | |
| 75 | + | |
| 76 | + login_as 'testuser' # testuser must be able to remove comments in his articles | |
| 77 | + assert_difference Comment, :count, -1 do | |
| 78 | + xhr :post, :destroy, :profile => profile.identifier, :id => comment.id | |
| 79 | + assert_response :success | |
| 80 | + end | |
| 81 | + end | |
| 82 | + | |
| 83 | + should 'be able to remove comments if is moderator' do | |
| 84 | + commenter = create_user('commenter_user').person | |
| 85 | + community = Community.create!(:name => 'Community test', :identifier => 'community-test') | |
| 86 | + article = community.articles.create!(:name => 'test', :profile => community) | |
| 87 | + comment = fast_create(Comment, :source_id => article, :author_id => commenter, :title => 'a comment', :body => 'lalala') | |
| 88 | + community.add_moderator(profile) | |
| 89 | + login_as profile.identifier | |
| 90 | + assert_difference Comment, :count, -1 do | |
| 91 | + xhr :post, :destroy, :profile => community.identifier, :id => comment.id | |
| 92 | + assert_response :success | |
| 93 | + end | |
| 94 | + assert_match /\{\"ok\":true\}/, @response.body | |
| 95 | + end | |
| 96 | + | |
| 97 | + should 'be able to remove comment' do | |
| 98 | + profile = create_user('testuser').person | |
| 99 | + article = profile.articles.build(:name => 'test') | |
| 100 | + article.save! | |
| 101 | + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala') | |
| 102 | + | |
| 103 | + login_as 'testuser' | |
| 104 | + assert_difference Comment, :count, -1 do | |
| 105 | + xhr :post, :destroy, :profile => profile.identifier, :id => comment.id | |
| 106 | + assert_response :success | |
| 107 | + end | |
| 108 | + end | |
| 109 | + | |
| 110 | + should 'display not found page if a user should try to make a cross comment' do | |
| 111 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 112 | + | |
| 113 | + other_person = create_user('otheruser').person | |
| 114 | + other_page = other_person.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 115 | + | |
| 116 | + assert_no_difference Comment, :count do | |
| 117 | + xhr :post, :create, :profile => profile.identifier, :id => other_page.id, :comment => { :title => 'crap!', :body => 'I think that this article is crap' } | |
| 118 | + end | |
| 119 | + assert_match /not found/, @response.body | |
| 120 | + end | |
| 121 | + | |
| 122 | + should 'not be able to post comment if article do not accept it' do | |
| 123 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text', :accept_comments => false) | |
| 124 | + | |
| 125 | + assert_no_difference Comment, :count do | |
| 126 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'crap!', :body => 'I think that this article is crap' } | |
| 127 | + end | |
| 128 | + assert_match /Comment not allowed in this article/, @response.body | |
| 129 | + end | |
| 130 | + | |
| 131 | + should "the author's comment be the logged user" do | |
| 132 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 133 | + | |
| 134 | + login_as profile.identifier | |
| 135 | + | |
| 136 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'crap!', :body => 'I think that this article is crap' } | |
| 137 | + assert_equal profile, assigns(:comment).author | |
| 138 | + end | |
| 139 | + | |
| 140 | + should "the articles's comment be the article passed as parameter" do | |
| 141 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 142 | + | |
| 143 | + login_as profile.identifier | |
| 144 | + | |
| 145 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'crap!', :body => 'I think that this article is crap' } | |
| 146 | + assert_equal page, assigns(:comment).article | |
| 147 | + end | |
| 148 | + | |
| 149 | + should 'show comment form opened on error' do | |
| 150 | + login_as profile.identifier | |
| 151 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 152 | + xhr :post, :create, :profile => @profile.identifier, :id => page.id, :comment => { :title => '', :body => '' }, :confirm => 'true' | |
| 153 | + response = JSON.parse @response.body | |
| 154 | + assert_match /<div class=\"post_comment_box opened\"/, response["html"] | |
| 155 | + end | |
| 156 | + | |
| 157 | + should 'show validation error when body comment is missing' do | |
| 158 | + login_as @profile.identifier | |
| 159 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 160 | + xhr :post, :create, :profile => @profile.identifier, :id => page.id, :comment => { :title => '', :body => '' }, :confirm => 'true' | |
| 161 | + response = JSON.parse @response.body | |
| 162 | + assert_match /errorExplanation/, response["html"] | |
| 163 | + end | |
| 164 | + | |
| 165 | + should 'not save a comment if a plugin rejects it' do | |
| 166 | + class TestFilterPlugin < Noosfero::Plugin | |
| 167 | + def filter_comment(c) | |
| 168 | + c.reject! | |
| 169 | + end | |
| 170 | + end | |
| 171 | + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestFilterPlugin.new]) | |
| 172 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 173 | + assert_no_difference Comment, :count do | |
| 174 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'title', :body => 'body', :name => "Spammer", :email => 'damn@spammer.com' }, :confirm => 'true' | |
| 175 | + end | |
| 176 | + end | |
| 177 | + | |
| 178 | + should 'display a message if a plugin reject the comment' do | |
| 179 | + class TestFilterPlugin < Noosfero::Plugin | |
| 180 | + def filter_comment(c) | |
| 181 | + c.reject! | |
| 182 | + end | |
| 183 | + end | |
| 184 | + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestFilterPlugin.new]) | |
| 185 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 186 | + assert_no_difference Comment, :count do | |
| 187 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'title', :body => 'body', :name => "Spammer", :email => 'damn@spammer.com' }, :confirm => 'true' | |
| 188 | + end | |
| 189 | + | |
| 190 | + assert_match /rejected/, @response.body | |
| 191 | + end | |
| 192 | + | |
| 193 | + should 'store IP address, user agent and referrer for comments' do | |
| 194 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 195 | + @request.stubs(:remote_ip).returns('33.44.55.66') | |
| 196 | + @request.stubs(:referrer).returns('http://example.com') | |
| 197 | + @request.stubs(:user_agent).returns('MyBrowser') | |
| 198 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'title', :body => 'body', :name => "Spammer", :email => 'damn@spammer.com' }, :confirm => 'true' | |
| 199 | + comment = Comment.last | |
| 200 | + assert_equal '33.44.55.66', comment.ip_address | |
| 201 | + assert_equal 'MyBrowser', comment.user_agent | |
| 202 | + assert_equal 'http://example.com', comment.referrer | |
| 203 | + end | |
| 204 | + | |
| 205 | + should 'invalid comment display the comment form open' do | |
| 206 | + article = profile.articles.build(:name => 'test') | |
| 207 | + article.save! | |
| 208 | + login_as('testinguser') | |
| 209 | + | |
| 210 | + assert_no_difference Comment, :count do | |
| 211 | + xhr :post, :create, :profile => profile.identifier, :id =>article.id, :comment => {:body => ""}, :confirm => 'true' | |
| 212 | + end | |
| 213 | + assert_match /post_comment_box opened/, @response.body | |
| 214 | + end | |
| 215 | + | |
| 216 | + should 'invalid captcha display the comment form open' do | |
| 217 | + article = profile.articles.build(:name => 'test') | |
| 218 | + article.save! | |
| 219 | + login_as('testinguser') | |
| 220 | + @controller.stubs(:verify_recaptcha).returns(false) | |
| 221 | + | |
| 222 | + environment.enable('captcha_for_logged_users') | |
| 223 | + environment.save! | |
| 224 | + | |
| 225 | + xhr :post, :create, :profile => profile.identifier, :id =>article.id, :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 226 | + assert_match /post_comment_box opened/, @response.body | |
| 227 | + end | |
| 228 | + | |
| 229 | + should 'ask for captcha if environment defines even with logged user' do | |
| 230 | + article = profile.articles.build(:name => 'test') | |
| 231 | + article.save! | |
| 232 | + login_as('testinguser') | |
| 233 | + @controller.stubs(:verify_recaptcha).returns(false) | |
| 234 | + | |
| 235 | + assert_difference Comment, :count, 1 do | |
| 236 | + xhr :post, :create, :profile => profile.identifier, :id => article.id, :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 237 | + end | |
| 238 | + | |
| 239 | + environment.enable('captcha_for_logged_users') | |
| 240 | + environment.save! | |
| 241 | + | |
| 242 | + assert_no_difference Comment, :count do | |
| 243 | + xhr :post, :create, :profile => profile.identifier, :id =>article.id, :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 244 | + end | |
| 245 | + assert_not_nil assigns(:comment) | |
| 246 | + end | |
| 247 | + | |
| 248 | + should 'ask for captcha if user not logged' do | |
| 249 | + article = profile.articles.build(:name => 'test') | |
| 250 | + article.save! | |
| 251 | + | |
| 252 | + @controller.stubs(:verify_recaptcha).returns(false) | |
| 253 | + assert_no_difference Comment, :count do | |
| 254 | + xhr :post, :create, :profile => profile.identifier, :id => article.id, :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 255 | + end | |
| 256 | + | |
| 257 | + @controller.stubs(:verify_recaptcha).returns(true) | |
| 258 | + assert_difference Comment, :count, 1 do | |
| 259 | + xhr :post, :create, :profile => profile.identifier, :id => article.id, :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 260 | + end | |
| 261 | + end | |
| 262 | + | |
| 263 | + should 'create ApproveComment task when adding a comment in a moderated article' do | |
| 264 | + login_as @profile.identifier | |
| 265 | + community = Community.create!(:name => 'testcomm') | |
| 266 | + page = community.articles.create!(:name => 'myarticle', :moderate_comments => true) | |
| 267 | + | |
| 268 | + commenter = create_user('otheruser').person | |
| 269 | + assert_difference ApproveComment, :count, 1 do | |
| 270 | + xhr :post, :create, :profile => community.identifier, :id => page.id, :comment => {:body => 'Some comment...', :author => commenter}, :confirm => 'true' | |
| 271 | + end | |
| 272 | + end | |
| 273 | + | |
| 274 | + should 'not create ApproveComment task when the comment author is the same of article author' do | |
| 275 | + login_as @profile.identifier | |
| 276 | + community = Community.create!(:name => 'testcomm') | |
| 277 | + page = community.articles.create!(:name => 'myarticle', :moderate_comments => true, :last_changed_by => @profile) | |
| 278 | + community.add_moderator(@profile) | |
| 279 | + | |
| 280 | + assert_no_difference ApproveComment, :count do | |
| 281 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:body => 'Some comment...'}, :confirm => 'true' | |
| 282 | + end | |
| 283 | + end | |
| 284 | + | |
| 285 | + should 'create ApproveComment task with the comment author as requestor' do | |
| 286 | + community = Community.create!(:name => 'testcomm') | |
| 287 | + page = community.articles.create!(:name => 'myarticle', :moderate_comments => true) | |
| 288 | + | |
| 289 | + commenter = create_user('otheruser').person | |
| 290 | + assert_difference ApproveComment, :count, 1 do | |
| 291 | + xhr :post, :create, :profile => community.identifier, :id => page.id, :comment => {:body => 'Some comment...', :author => commenter}, :confirm => 'true' | |
| 292 | + end | |
| 293 | + task = Task.last | |
| 294 | + assert_equal commenter, task.requestor | |
| 295 | + | |
| 296 | + end | |
| 297 | + | |
| 298 | + should "create ApproveComment task with the articles's owner profile as the target" do | |
| 299 | + login_as @profile.identifier | |
| 300 | + community = Community.create!(:name => 'testcomm') | |
| 301 | + page = community.articles.create!(:name => 'myarticle', :moderate_comments => true) | |
| 302 | + | |
| 303 | + commenter = create_user('otheruser').person | |
| 304 | + assert_difference ApproveComment, :count, 1 do | |
| 305 | + xhr :post, :create, :profile => community.identifier, :id => page.id, :comment => {:body => 'Some comment...', :author => commenter}, :confirm => 'true' | |
| 306 | + end | |
| 307 | + task = Task.last | |
| 308 | + assert_equal community, task.target | |
| 309 | + end | |
| 310 | + | |
| 311 | + should "create ApproveComment task with the comment created_at attribute defined to now" do | |
| 312 | + login_as @profile.identifier | |
| 313 | + community = Community.create!(:name => 'testcomm') | |
| 314 | + page = community.articles.create!(:name => 'myarticle', :moderate_comments => true) | |
| 315 | + | |
| 316 | + now = Time.now | |
| 317 | + Time.stubs(:now).returns(now) | |
| 318 | + xhr :post, :create, :profile => community.identifier, :id => page.id, :comment => {:body => 'Some comment...'}, :confirm => 'true' | |
| 319 | + task = Task.last | |
| 320 | + assert_equal now.to_s, task.comment.created_at.to_s | |
| 321 | + end | |
| 322 | + | |
| 323 | + should "render_target be nil in article with moderation" do | |
| 324 | + page = profile.articles.create!(:name => 'myarticle', :moderate_comments => true) | |
| 325 | + | |
| 326 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:body => 'Some comment...', :name => 'some name', :email => 'some@test.com.br'}, :confirm => 'true' | |
| 327 | + assert_nil ActiveSupport::JSON.decode(@response.body)['render_target'] | |
| 328 | + end | |
| 329 | + | |
| 330 | + should "display message 'waitting for approval' of comments in article with moderation" do | |
| 331 | + page = profile.articles.create!(:name => 'myarticle', :moderate_comments => true) | |
| 332 | + | |
| 333 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:body => 'Some comment...', :name => 'some name', :email => 'some@test.com.br'}, :confirm => 'true' | |
| 334 | + assert_match /waiting for approval/, @response.body | |
| 335 | + end | |
| 336 | + | |
| 337 | + should "render_target be the comment anchor if everithing is fine" do | |
| 338 | + login_as profile.identifier | |
| 339 | + page = profile.articles.create!(:name => 'myarticle') | |
| 340 | + | |
| 341 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:body => 'Some comment...'}, :confirm => 'true' | |
| 342 | + assert_match /#{Comment.last.id}/, ActiveSupport::JSON.decode(@response.body)['render_target'] | |
| 343 | + end | |
| 344 | + | |
| 345 | + should "display message 'successfully created' if the comment was saved with success" do | |
| 346 | + login_as profile.identifier | |
| 347 | + page = profile.articles.create!(:name => 'myarticle') | |
| 348 | + | |
| 349 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:body => 'Some comment...'}, :confirm => 'true' | |
| 350 | + assert_match /successfully created/, @response.body | |
| 351 | + end | |
| 352 | + | |
| 353 | + should "render partial comment if everithing is fine" do | |
| 354 | + login_as profile.identifier | |
| 355 | + page = profile.articles.create!(:name => 'myarticle') | |
| 356 | + | |
| 357 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:body => 'Some comment...'}, :confirm => 'true' | |
| 358 | + assert_match /id="#{Comment.last.anchor}" class="article-comment"/, ActiveSupport::JSON.decode(@response.body)['html'] | |
| 359 | + end | |
| 360 | + | |
| 361 | + should "render the root comment when a reply is made" do | |
| 362 | + login_as profile.identifier | |
| 363 | + page = profile.articles.create!(:name => 'myarticle') | |
| 364 | + | |
| 365 | + comment = fast_create(Comment, :body => 'some content', :source_id => page.id, :source_type => 'Article') | |
| 366 | + | |
| 367 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => {:body => 'Some comment...', :reply_of_id => comment.id}, :confirm => 'true' | |
| 368 | + assert_match /id="#{comment.anchor}" class="article-comment"/, ActiveSupport::JSON.decode(@response.body)['html'] | |
| 369 | + end | |
| 370 | + | |
| 371 | + should 'filter html content from body' do | |
| 372 | + login_as @profile.identifier | |
| 373 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 374 | + | |
| 375 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'html comment', :body => "this is a <strong id='html_test_comment'>html comment</strong>"} | |
| 376 | + | |
| 377 | + assert Comment.last.body.match(/this is a html comment/) | |
| 378 | + assert_no_tag :tag => 'strong', :attributes => { :id => 'html_test_comment' } | |
| 379 | + end | |
| 380 | + | |
| 381 | + should 'filter html content from title' do | |
| 382 | + login_as @profile.identifier | |
| 383 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 384 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => "html <strong id='html_test_comment'>comment</strong>", :body => "this is a comment"} | |
| 385 | + assert Comment.last.title.match(/html comment/) | |
| 386 | + assert_no_tag :tag => 'strong', :attributes => { :id => 'html_test_comment' } | |
| 387 | + end | |
| 388 | + | |
| 389 | + should 'touch article after adding a comment' do | |
| 390 | + yesterday = Time.now.yesterday | |
| 391 | + Article.record_timestamps = false | |
| 392 | + page = profile.articles.create(:name => 'myarticle', :body => 'the body of the text', :created_at => yesterday, :updated_at => yesterday) | |
| 393 | + Article.record_timestamps = true | |
| 394 | + | |
| 395 | + login_as('ze') | |
| 396 | + xhr :post, :create, :profile => profile.identifier, :id => page.id, :comment => { :title => 'crap!', :body => 'I think that this article is crap' }, :confirm => 'true' | |
| 397 | + assert_not_equal yesterday, page.reload.updated_at | |
| 398 | + end | |
| 399 | + | |
| 400 | + should 'be able to mark comments as spam' do | |
| 401 | + login_as profile.identifier | |
| 402 | + article = fast_create(Article, :profile_id => profile.id) | |
| 403 | + spam = fast_create(Comment, :name => 'foo', :email => 'foo@example.com', :source_id => article.id, :source_type => 'Article') | |
| 404 | + | |
| 405 | + xhr :post, :mark_as_spam, :profile => profile.identifier, :id => spam.id | |
| 406 | + | |
| 407 | + spam.reload | |
| 408 | + assert spam.spam? | |
| 409 | + end | |
| 410 | + | |
| 411 | + should "not be able to mark as spam other people's comments if not moderator or admin" do | |
| 412 | + create_user('normaluser') | |
| 413 | + profile = create_user('testuser').person | |
| 414 | + article = profile.articles.build(:name => 'test') | |
| 415 | + article.save! | |
| 416 | + | |
| 417 | + commenter = create_user('otheruser').person | |
| 418 | + comment = fast_create(Comment, :source_id => article, :title => 'a comment', :body => 'lalala') | |
| 419 | + | |
| 420 | + login_as 'normaluser' # normaluser cannot remove other people's comments | |
| 421 | + xhr :post, :mark_as_spam, :profile => profile.identifier, :id => comment.id | |
| 422 | + comment.reload | |
| 423 | + assert !comment.spam? | |
| 424 | + end | |
| 425 | + | |
| 426 | + should "not be able to mark as spam other people's comments if not moderator or admin and return json if is an ajax request" do | |
| 427 | + create_user('normaluser') | |
| 428 | + profile = create_user('testuser').person | |
| 429 | + article = profile.articles.build(:name => 'test') | |
| 430 | + article.save! | |
| 431 | + | |
| 432 | + commenter = create_user('otheruser').person | |
| 433 | + comment = fast_create(Comment, :source_id => article, :author_id => commenter, :title => 'a comment', :body => 'lalala') | |
| 434 | + | |
| 435 | + login_as 'normaluser' # normaluser cannot remove other people's comments | |
| 436 | + | |
| 437 | + xhr :post, :mark_as_spam, :profile => profile.identifier, :id => comment.id | |
| 438 | + assert_response :success | |
| 439 | + comment.reload | |
| 440 | + assert !comment.spam? | |
| 441 | + assert_match /\{\"ok\":false\}/, @response.body | |
| 442 | + end | |
| 443 | + | |
| 444 | + should 'be able to mark as spam comments on their articles' do | |
| 445 | + profile = create_user('testuser').person | |
| 446 | + article = profile.articles.build(:name => 'test') | |
| 447 | + article.save! | |
| 448 | + | |
| 449 | + commenter = create_user('otheruser').person | |
| 450 | + comment = fast_create(Comment, :source_id => article, :author_id => commenter, :title => 'a comment', :body => 'lalala') | |
| 451 | + | |
| 452 | + login_as 'testuser' # testuser must be able to remove comments in his articles | |
| 453 | + | |
| 454 | + xhr :post, :mark_as_spam, :profile => profile.identifier, :id => comment.id | |
| 455 | + assert_response :success | |
| 456 | + comment.reload | |
| 457 | + assert comment.spam? | |
| 458 | + | |
| 459 | + assert_match /\{\"ok\":true\}/, @response.body | |
| 460 | + end | |
| 461 | + | |
| 462 | + should 'be able to mark comments as spam if is moderator' do | |
| 463 | + commenter = create_user('commenter_user').person | |
| 464 | + community = Community.create!(:name => 'Community test', :identifier => 'community-test') | |
| 465 | + article = community.articles.create!(:name => 'test', :profile => community) | |
| 466 | + comment = fast_create(Comment, :source_id => article, :author_id => commenter, :title => 'a comment', :body => 'lalala') | |
| 467 | + community.add_moderator(profile) | |
| 468 | + login_as profile.identifier | |
| 469 | + | |
| 470 | + xhr :post, :mark_as_spam, :profile => community.identifier, :id => comment.id | |
| 471 | + assert_response :success | |
| 472 | + comment.reload | |
| 473 | + assert comment.spam? | |
| 474 | + assert_match /\{\"ok\":true\}/, @response.body | |
| 475 | + end | |
| 476 | + | |
| 477 | + should 'edit comment from a page' do | |
| 478 | + login_as profile.identifier | |
| 479 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 480 | + comment = fast_create(Comment, :body => 'Original comment', :source_id => page.id, :source_type => 'Article', :author_id => profile.id) | |
| 481 | + | |
| 482 | + get :edit, :id => comment.id, :profile => profile.identifier, :comment => { :body => 'Comment edited' } | |
| 483 | + assert_tag :tag => 'textarea', :attributes => {:id => 'comment_body'}, :content => 'Original comment' | |
| 484 | + end | |
| 485 | + | |
| 486 | + should 'not crash on edit comment if comment does not exist' do | |
| 487 | + login_as profile.identifier | |
| 488 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 489 | + | |
| 490 | + get :edit, :id => 1000, :profile => profile.identifier, :comment => { :body => 'Comment edited' } | |
| 491 | + assert_response 404 | |
| 492 | + end | |
| 493 | + | |
| 494 | + should 'not be able to edit comment not logged' do | |
| 495 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 496 | + comment = fast_create(Comment, :body => 'Original comment', :source_id => page.id, :source_type => 'Article') | |
| 497 | + | |
| 498 | + get :edit, :id => comment.id, :profile => profile.identifier, :comment => { :body => 'Comment edited' } | |
| 499 | + assert_response 404 | |
| 500 | + end | |
| 501 | + | |
| 502 | + should 'not be able to edit comment if does not have the permission to' do | |
| 503 | + user = create_user('any_guy').person | |
| 504 | + login_as user.identifier | |
| 505 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 506 | + comment = fast_create(Comment, :body => 'Original comment', :source_id => page.id, :source_type => 'Article') | |
| 507 | + | |
| 508 | + get :edit, :id => comment.id, :profile => profile.identifier, :comment => { :body => 'Comment edited' } | |
| 509 | + assert_response 404 | |
| 510 | + end | |
| 511 | + | |
| 512 | + should 'be able to update a comment' do | |
| 513 | + login_as profile.identifier | |
| 514 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text', :accept_comments => false) | |
| 515 | + comment = fast_create(Comment, :body => 'Original comment', :source_id => page.id, :source_type => 'Article', :author_id => profile) | |
| 516 | + | |
| 517 | + xhr :post, :update, :id => comment.id, :profile => profile.identifier, :comment => { :body => 'Comment edited' } | |
| 518 | + assert JSON.parse(@response.body)["ok"], "attribute ok expected to be true" | |
| 519 | + assert_equal 'Comment edited', Comment.find(comment.id).body | |
| 520 | + end | |
| 521 | + | |
| 522 | + should 'not crash on update comment if comment does not exist' do | |
| 523 | + login_as profile.identifier | |
| 524 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 525 | + | |
| 526 | + xhr :post, :update, :id => 1000, :profile => profile.identifier, :comment => { :body => 'Comment edited' } | |
| 527 | + assert_response 404 | |
| 528 | + end | |
| 529 | + | |
| 530 | + should 'not be able to update comment not logged' do | |
| 531 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 532 | + comment = fast_create(Comment, :body => 'Original comment', :source_id => page.id, :source_type => 'Article') | |
| 533 | + | |
| 534 | + xhr :post, :update, :id => comment.id, :profile => profile.identifier, :comment => { :body => 'Comment edited' } | |
| 535 | + assert_response 404 | |
| 536 | + end | |
| 537 | + | |
| 538 | + should 'not be able to update comment if does not have the permission to' do | |
| 539 | + user = create_user('any_guy').person | |
| 540 | + login_as user.identifier | |
| 541 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 542 | + comment = fast_create(Comment, :body => 'Original comment', :source_id => page.id, :source_type => 'Article') | |
| 543 | + | |
| 544 | + xhr :post, :update, :id => comment.id, :profile => profile.identifier, :comment => { :body => 'Comment edited' } | |
| 545 | + assert_response 404 | |
| 546 | + end | |
| 547 | + | |
| 548 | + should 'returns ids of menu items that has to be displayed' do | |
| 549 | + class TestActionPlugin < Noosfero::Plugin | |
| 550 | + def check_comment_actions(c) | |
| 551 | + ['action1', 'action2'] | |
| 552 | + end | |
| 553 | + end | |
| 554 | + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestActionPlugin.new]) | |
| 555 | + login_as profile.identifier | |
| 556 | + page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 557 | + comment = fast_create(Comment, :body => 'Original comment', :source_id => page.id, :source_type => 'Article') | |
| 558 | + xhr :post, :check_actions, :profile => profile.identifier, :id => comment.id | |
| 559 | + assert_match /\{\"ids\":\[\"action1\",\"action2\"\]\}/, @response.body | |
| 560 | + end | |
| 561 | + | |
| 562 | +end | ... | ... |
test/functional/content_viewer_controller_test.rb
| ... | ... | @@ -83,149 +83,6 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 83 | 83 | assert_equal feed.data, @response.body |
| 84 | 84 | end |
| 85 | 85 | |
| 86 | - should 'display remove comment button' do | |
| 87 | - profile = create_user('testuser').person | |
| 88 | - article = profile.articles.build(:name => 'test') | |
| 89 | - article.save! | |
| 90 | - comment = article.comments.build(:author => profile, :title => 'a comment', :body => 'lalala') | |
| 91 | - comment.save! | |
| 92 | - | |
| 93 | - login_as 'testuser' | |
| 94 | - get :view_page, :profile => 'testuser', :page => [ 'test' ] | |
| 95 | - assert_tag :tag => 'a', :attributes => { :onclick => %r(/testuser/test\?remove_comment=#{comment.id}.quot) } | |
| 96 | - end | |
| 97 | - | |
| 98 | - should 'display remove comment button with param view when image' do | |
| 99 | - profile = create_user('testuser').person | |
| 100 | - | |
| 101 | - image = UploadedFile.create!(:profile => profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | |
| 102 | - image.save! | |
| 103 | - | |
| 104 | - comment = image.comments.build(:author => profile, :title => 'a comment', :body => 'lalala') | |
| 105 | - comment.save! | |
| 106 | - | |
| 107 | - login_as 'testuser' | |
| 108 | - get :view_page, :profile => 'testuser', :page => [ image.filename ], :view => true | |
| 109 | - assert_tag :tag => 'a', :attributes => { :onclick => %r(/testuser/#{image.filename}\?remove_comment=#{comment.id}.*amp;view=true.quot) } | |
| 110 | -end | |
| 111 | - | |
| 112 | - | |
| 113 | - should 'not add unneeded params for remove comment button' do | |
| 114 | - profile = create_user('testuser').person | |
| 115 | - article = profile.articles.build(:name => 'test') | |
| 116 | - article.save! | |
| 117 | - comment = article.comments.build(:author => profile, :title => 'a comment', :body => 'lalala') | |
| 118 | - comment.save! | |
| 119 | - | |
| 120 | - login_as 'testuser' | |
| 121 | - get :view_page, :profile => 'testuser', :page => [ 'test' ], :random_param => 'bli' | |
| 122 | - assert_tag :tag => 'a', :attributes => { :onclick => %r(/testuser/test\?remove_comment=#{comment.id.to_s}.quot) } | |
| 123 | - end | |
| 124 | - | |
| 125 | - should 'be able to remove comment' do | |
| 126 | - profile = create_user('testuser').person | |
| 127 | - article = profile.articles.build(:name => 'test') | |
| 128 | - article.save! | |
| 129 | - comment = article.comments.build(:author => profile, :title => 'a comment', :body => 'lalala') | |
| 130 | - comment.save! | |
| 131 | - | |
| 132 | - login_as 'testuser' | |
| 133 | - assert_difference Comment, :count, -1 do | |
| 134 | - post :view_page, :profile => profile.identifier, :page => [ 'test' ], :remove_comment => comment.id | |
| 135 | - assert_redirected_to :controller => 'content_viewer', :profile => 'testuser', :action => 'view_page', :page => [ 'test' ] | |
| 136 | - end | |
| 137 | - end | |
| 138 | - | |
| 139 | - should "not be able to remove other people's comments if not moderator or admin" do | |
| 140 | - create_user('normaluser') | |
| 141 | - profile = create_user('testuser').person | |
| 142 | - article = profile.articles.build(:name => 'test') | |
| 143 | - article.save! | |
| 144 | - | |
| 145 | - commenter = create_user('otheruser').person | |
| 146 | - comment = article.comments.build(:author => commenter, :title => 'a comment', :body => 'lalala') | |
| 147 | - comment.save! | |
| 148 | - | |
| 149 | - login_as 'normaluser' # normaluser cannot remove other people's comments | |
| 150 | - assert_no_difference Comment, :count do | |
| 151 | - post :view_page, :profile => profile.identifier, :page => [ 'test' ], :remove_comment => comment.id | |
| 152 | - assert_response :redirect | |
| 153 | - end | |
| 154 | - end | |
| 155 | - | |
| 156 | - should 'be able to remove comments on their articles' do | |
| 157 | - profile = create_user('testuser').person | |
| 158 | - article = profile.articles.build(:name => 'test') | |
| 159 | - article.save! | |
| 160 | - | |
| 161 | - commenter = create_user('otheruser').person | |
| 162 | - comment = article.comments.build(:author => commenter, :title => 'a comment', :body => 'lalala') | |
| 163 | - comment.save! | |
| 164 | - | |
| 165 | - login_as 'testuser' # testuser must be able to remove comments in his articles | |
| 166 | - assert_difference Comment, :count, -1 do | |
| 167 | - post :view_page, :profile => profile.identifier, :page => [ 'test' ], :remove_comment => comment.id | |
| 168 | - assert_response :redirect | |
| 169 | - end | |
| 170 | - end | |
| 171 | - | |
| 172 | - should 'be able to remove comments of their images' do | |
| 173 | - profile = create_user('testuser').person | |
| 174 | - | |
| 175 | - image = UploadedFile.create!(:profile => profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | |
| 176 | - image.save! | |
| 177 | - | |
| 178 | - commenter = create_user('otheruser').person | |
| 179 | - comment = image.comments.build(:author => commenter, :title => 'a comment', :body => 'lalala') | |
| 180 | - comment.save! | |
| 181 | - | |
| 182 | - login_as 'testuser' # testuser must be able to remove comments in his articles | |
| 183 | - assert_difference Comment, :count, -1 do | |
| 184 | - post :view_page, :profile => profile.identifier, :page => [ image.filename ], :remove_comment => comment.id, :view => true | |
| 185 | - | |
| 186 | - assert_response :redirect | |
| 187 | - assert_redirected_to :controller => 'content_viewer', :action => 'view_page', :profile => profile.identifier, :page => image.explode_path, :view => true | |
| 188 | - end | |
| 189 | - end | |
| 190 | - | |
| 191 | - should 'be able to remove comments if is moderator' do | |
| 192 | - commenter = create_user('commenter_user').person | |
| 193 | - community = Community.create!(:name => 'Community test', :identifier => 'community-test') | |
| 194 | - article = community.articles.create!(:name => 'test') | |
| 195 | - comment = article.comments.create!(:author => commenter, :title => 'a comment', :body => 'lalala') | |
| 196 | - community.add_moderator(profile) | |
| 197 | - login_as profile.identifier | |
| 198 | - assert_difference Comment, :count, -1 do | |
| 199 | - post :view_page, :profile => community.identifier, :page => [ 'test' ], :remove_comment => comment.id | |
| 200 | - assert_response :redirect | |
| 201 | - end | |
| 202 | - end | |
| 203 | - | |
| 204 | - should 'filter html content from body' do | |
| 205 | - login_as @profile.identifier | |
| 206 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 207 | - post :view_page, :profile => @profile.identifier, :page => [ 'myarticle' ], | |
| 208 | - :comment => { :title => 'html comment', :body => "this is a <strong id='html_test_comment'>html comment</strong>" } | |
| 209 | - assert_no_tag :tag => 'strong', :attributes => { :id => 'html_test_comment' } | |
| 210 | - end | |
| 211 | - | |
| 212 | - should 'filter html content from title' do | |
| 213 | - login_as @profile.identifier | |
| 214 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 215 | - post :view_page, :profile => @profile.identifier, :page => [ 'myarticle' ], | |
| 216 | - :comment => { :title => "html <strong id='html_test_comment'>comment</strong>", :body => "this is a comment" } | |
| 217 | - assert_no_tag :tag => 'strong', :attributes => { :id => 'html_test_comment' } | |
| 218 | - end | |
| 219 | - | |
| 220 | - should "point to article's url in comment form" do | |
| 221 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 222 | - Article.any_instance.stubs(:url).returns({:host => 'www.mysite.com', :controller => 'content_viewer', :action => 'view_page', :profile => 'person', :page => ['article']}) | |
| 223 | - | |
| 224 | - get :view_page, :profile => profile.identifier, :page => [ 'myarticle' ] | |
| 225 | - | |
| 226 | - assert_tag :tag => 'form', :attributes => { :class => /^comment_form/, :action => '/person/article' } | |
| 227 | - end | |
| 228 | - | |
| 229 | 86 | should "display current article's tags" do |
| 230 | 87 | page = profile.articles.create!(:name => 'myarticle', :body => 'test article', :tag_list => 'tag1, tag2') |
| 231 | 88 | |
| ... | ... | @@ -429,14 +286,6 @@ end |
| 429 | 286 | assert_template 'view_page' |
| 430 | 287 | end |
| 431 | 288 | |
| 432 | - should 'not be able to post comment if article do not accept it' do | |
| 433 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text', :accept_comments => false) | |
| 434 | - | |
| 435 | - assert_no_difference Comment, :count do | |
| 436 | - post :view_page, :profile => profile.identifier, :page => [ 'myarticle' ], :comment => { :title => 'crap!', :body => 'I think that this article is crap', :name => 'Anonymous coward', :email => 'coward@anonymous.com' } | |
| 437 | - end | |
| 438 | - end | |
| 439 | - | |
| 440 | 289 | should 'list comments if article has them, even if new comments are not allowed' do |
| 441 | 290 | page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text', :accept_comments => false) |
| 442 | 291 | page.comments.create!(:author => profile, :title => 'list my comment', :body => 'foo bar baz') |
| ... | ... | @@ -719,15 +568,6 @@ end |
| 719 | 568 | assert_tag :tag => 'a', :content => 'Upload files', :attributes => {:href => /parent_id=#{folder.id}/} |
| 720 | 569 | end |
| 721 | 570 | |
| 722 | - should 'post comment in a image' do | |
| 723 | - login_as(profile.identifier) | |
| 724 | - image = UploadedFile.create!(:profile => profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | |
| 725 | - comment_count = image.comments.count | |
| 726 | - post :view_page, :profile => profile.identifier, :page => image.explode_path, :view => true | |
| 727 | - assert_equal comment_count, image.reload.comments.count | |
| 728 | - assert_template 'view_page' | |
| 729 | - end | |
| 730 | - | |
| 731 | 571 | should 'render slideshow template' do |
| 732 | 572 | f = Folder.create!(:name => 'gallery', :profile => profile) |
| 733 | 573 | get :view_page, :profile => profile.identifier, :page => f.explode_path, :slideshow => true |
| ... | ... | @@ -869,17 +709,6 @@ end |
| 869 | 709 | assert_tag :tag => 'a', :content => 'New article' |
| 870 | 710 | end |
| 871 | 711 | |
| 872 | - should 'touch article after adding a comment' do | |
| 873 | - yesterday = Time.now.yesterday | |
| 874 | - Article.record_timestamps = false | |
| 875 | - page = profile.articles.create(:name => 'myarticle', :body => 'the body of the text', :created_at => yesterday, :updated_at => yesterday) | |
| 876 | - Article.record_timestamps = true | |
| 877 | - | |
| 878 | - login_as('ze') | |
| 879 | - post :view_page, :profile => profile.identifier, :page => [ 'myarticle' ], :comment => { :title => 'crap!', :body => 'I think that this article is crap' } | |
| 880 | - assert_not_equal yesterday, assigns(:page).updated_at | |
| 881 | - end | |
| 882 | - | |
| 883 | 712 | should 'display message if user was removed' do |
| 884 | 713 | article = profile.articles.create(:name => 'comment test') |
| 885 | 714 | to_be_removed = create_user('removed_user').person |
| ... | ... | @@ -891,13 +720,6 @@ end |
| 891 | 720 | assert_tag :tag => 'span', :content => '(removed user)', :attributes => {:class => 'comment-user-status icon-user-removed'} |
| 892 | 721 | end |
| 893 | 722 | |
| 894 | - should 'show comment form opened on error' do | |
| 895 | - login_as @profile.identifier | |
| 896 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 897 | - post :view_page, :profile => @profile.identifier, :page => [ 'myarticle' ], :comment => { :title => '', :body => '' }, :confirm => 'true' | |
| 898 | - assert_tag :tag => 'div', :attributes => { :class => 'post_comment_box opened' } | |
| 899 | - end | |
| 900 | - | |
| 901 | 723 | should 'show only first paragraph of blog posts if visualization_format is short' do |
| 902 | 724 | login_as(profile.identifier) |
| 903 | 725 | |
| ... | ... | @@ -1188,22 +1010,14 @@ end |
| 1188 | 1010 | assert_equal [es_article], assigns(:posts) |
| 1189 | 1011 | end |
| 1190 | 1012 | |
| 1191 | - should 'be redirect after posting a comment' do | |
| 1192 | - login_as @profile.identifier | |
| 1193 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 1194 | - post :view_page, :profile => @profile.identifier, :page => [ 'myarticle' ], :comment => { :title => 'title', :body => 'body' }, :confirm => 'true' | |
| 1195 | - assert_redirected_to :controller => 'content_viewer', :action => 'view_page', :profile => @profile.identifier, :page => page.explode_path | |
| 1196 | - end | |
| 1197 | - | |
| 1198 | 1013 | should 'display reply to comment button if authenticated' do |
| 1199 | 1014 | profile = create_user('testuser').person |
| 1200 | 1015 | article = profile.articles.build(:name => 'test') |
| 1201 | 1016 | article.save! |
| 1202 | - comment = article.comments.build(:author => profile, :title => 'a comment', :body => 'lalala') | |
| 1203 | - comment.save! | |
| 1017 | + comment = Comment.create!(:author => profile, :title => 'a comment', :body => 'lalala', :article => article) | |
| 1204 | 1018 | login_as 'testuser' |
| 1205 | 1019 | get :view_page, :profile => 'testuser', :page => [ 'test' ] |
| 1206 | - assert_tag :tag => 'a', :attributes => { :class => /comment-footer-link/ }, :content => 'Reply' | |
| 1020 | + assert_tag :tag => 'a', :attributes => { :class => /comment-actions-reply/ } | |
| 1207 | 1021 | end |
| 1208 | 1022 | |
| 1209 | 1023 | should 'display reply to comment button if not authenticated' do |
| ... | ... | @@ -1213,7 +1027,7 @@ end |
| 1213 | 1027 | comment = article.comments.build(:author => profile, :title => 'a comment', :body => 'lalala') |
| 1214 | 1028 | comment.save! |
| 1215 | 1029 | get :view_page, :profile => 'testuser', :page => [ 'test' ] |
| 1216 | - assert_tag :tag => 'a', :attributes => { :class => /comment-footer-link/ }, :content => 'Reply' | |
| 1030 | + assert_tag :tag => 'a', :attributes => { :class => /comment-actions-reply/ } | |
| 1217 | 1031 | end |
| 1218 | 1032 | |
| 1219 | 1033 | should 'display replies if comment has replies' do |
| ... | ... | @@ -1238,34 +1052,6 @@ end |
| 1238 | 1052 | assert_no_tag :tag => 'ul', :attributes => { :class => 'comment-replies' } |
| 1239 | 1053 | end |
| 1240 | 1054 | |
| 1241 | - should 'show reply error' do | |
| 1242 | - profile = create_user('testuser').person | |
| 1243 | - article = profile.articles.build(:name => 'test') | |
| 1244 | - article.save! | |
| 1245 | - comment = article.comments.build(:author => profile, :title => 'root', :body => 'root') | |
| 1246 | - comment.save! | |
| 1247 | - login_as 'testuser' | |
| 1248 | - post :view_page, :profile => profile.identifier, :page => ['test'], :comment => { :title => '', :body => '', :reply_of_id => comment.id }, :confirm => 'true' | |
| 1249 | - assert_tag :tag => 'div', :attributes => { :class => /comment_reply/ }, :descendant => {:tag => 'div', :attributes => {:class => 'errorExplanation'} } | |
| 1250 | - assert_no_tag :tag => 'div', :attributes => { :id => 'page-comment-form' }, :descendant => {:tag => 'div', :attributes => {:class => 'errorExplanation'} } | |
| 1251 | - assert_tag :tag => 'div', :attributes => { :id => 'page-comment-form' }, :descendant => { :tag => 'div', :attributes => { :class => /post_comment_box closed/ } } | |
| 1252 | - end | |
| 1253 | - | |
| 1254 | - should 'show comment error' do | |
| 1255 | - profile = create_user('testuser').person | |
| 1256 | - article = profile.articles.build(:name => 'test') | |
| 1257 | - article.save! | |
| 1258 | - comment1 = article.comments.build(:author => profile, :title => 'root', :body => 'root') | |
| 1259 | - comment1.save! | |
| 1260 | - comment2 = article.comments.build(:author => profile, :title => 'root', :body => 'root', :reply_of_id => comment1.id) | |
| 1261 | - comment2.save! | |
| 1262 | - login_as 'testuser' | |
| 1263 | - post :view_page, :profile => profile.identifier, :page => ['test'], :comment => { :title => '', :body => '' }, :confirm => 'true' | |
| 1264 | - assert_no_tag :tag => 'div', :attributes => { :class => /comment_reply/ }, :descendant => {:tag => 'div', :attributes => {:class => 'errorExplanation'} } | |
| 1265 | - assert_tag :tag => 'div', :attributes => { :id => 'page-comment-form' }, :descendant => {:tag => 'div', :attributes => {:class => 'errorExplanation'} } | |
| 1266 | - assert_tag :tag => 'div', :attributes => { :id => 'page-comment-form' }, :descendant => { :tag => 'div', :attributes => { :class => /post_comment_box opened/ } } | |
| 1267 | - end | |
| 1268 | - | |
| 1269 | 1055 | should 'add an zero width space every 4 caracters of comment urls' do |
| 1270 | 1056 | url = 'www.an.url.to.be.splited.com' |
| 1271 | 1057 | a = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'textile', :language => 'en') |
| ... | ... | @@ -1346,60 +1132,6 @@ end |
| 1346 | 1132 | assert_no_tag :tag => 'body', :attributes => { :class => /profile-homepage/ } |
| 1347 | 1133 | end |
| 1348 | 1134 | |
| 1349 | - should 'ask for captcha if user not logged' do | |
| 1350 | - article = profile.articles.build(:name => 'test') | |
| 1351 | - article.save! | |
| 1352 | - | |
| 1353 | - @controller.stubs(:verify_recaptcha).returns(false) | |
| 1354 | - post :view_page, :profile => profile.identifier, :page => ['test'], :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 1355 | - assert_not_nil assigns(:comment) | |
| 1356 | - | |
| 1357 | - @controller.stubs(:verify_recaptcha).returns(true) | |
| 1358 | - post :view_page, :profile => profile.identifier, :page => ['test'], :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 1359 | - assert_nil assigns(:comment) | |
| 1360 | - end | |
| 1361 | - | |
| 1362 | - should 'ask for captcha if environment defines even with logged user' do | |
| 1363 | - article = profile.articles.build(:name => 'test') | |
| 1364 | - article.save! | |
| 1365 | - login_as('testinguser') | |
| 1366 | - @controller.stubs(:verify_recaptcha).returns(false) | |
| 1367 | - | |
| 1368 | - post :view_page, :profile => profile.identifier, :page => ['test'], :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 1369 | - assert_nil assigns(:comment) | |
| 1370 | - | |
| 1371 | - environment.enable('captcha_for_logged_users') | |
| 1372 | - environment.save! | |
| 1373 | - | |
| 1374 | - post :view_page, :profile => profile.identifier, :page => ['test'], :comment => {:body => "Some comment...", :author => profile}, :confirm => 'true' | |
| 1375 | - assert_not_nil assigns(:comment) | |
| 1376 | - end | |
| 1377 | - | |
| 1378 | - should 'store IP address, user agent and referrer for comments' do | |
| 1379 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 1380 | - @request.stubs(:remote_ip).returns('33.44.55.66') | |
| 1381 | - @request.stubs(:referrer).returns('http://example.com') | |
| 1382 | - @request.stubs(:user_agent).returns('MyBrowser') | |
| 1383 | - post :view_page, :profile => profile.identifier, :page => [ 'myarticle' ], :comment => { :title => 'title', :body => 'body', :name => "Spammer", :email => 'damn@spammer.com' }, :confirm => 'true' | |
| 1384 | - comment = Comment.last | |
| 1385 | - assert_equal '33.44.55.66', comment.ip_address | |
| 1386 | - assert_equal 'MyBrowser', comment.user_agent | |
| 1387 | - assert_equal 'http://example.com', comment.referrer | |
| 1388 | - end | |
| 1389 | - | |
| 1390 | - should 'not save a comment if a plugin rejects it' do | |
| 1391 | - class TestFilterPlugin < Noosfero::Plugin | |
| 1392 | - def filter_comment(c) | |
| 1393 | - c.reject! | |
| 1394 | - end | |
| 1395 | - end | |
| 1396 | - Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestFilterPlugin.new]) | |
| 1397 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 1398 | - assert_no_difference Comment, :count do | |
| 1399 | - post :view_page, :profile => profile.identifier, :page => [ 'myarticle' ], :comment => { :title => 'title', :body => 'body', :name => "Spammer", :email => 'damn@spammer.com' }, :confirm => 'true' | |
| 1400 | - end | |
| 1401 | - end | |
| 1402 | - | |
| 1403 | 1135 | should 'not display article actions button if any plugins says so' do |
| 1404 | 1136 | class Plugin1 < Noosfero::Plugin |
| 1405 | 1137 | def content_remove_edit(content); true; end |
| ... | ... | @@ -1453,53 +1185,4 @@ end |
| 1453 | 1185 | assert_equal 1, assigns(:comments_count) |
| 1454 | 1186 | end |
| 1455 | 1187 | |
| 1456 | - should 'be able to mark comments as spam' do | |
| 1457 | - login_as profile.identifier | |
| 1458 | - article = fast_create(Article, :profile_id => profile.id) | |
| 1459 | - spam = fast_create(Comment, :name => 'foo', :email => 'foo@example.com', :source_id => article.id, :source_type => 'Article') | |
| 1460 | - | |
| 1461 | - post 'view_page', :profile => profile.identifier, :page => article.path.split('/'), :mark_comment_as_spam => spam.id | |
| 1462 | - | |
| 1463 | - spam.reload | |
| 1464 | - assert spam.spam? | |
| 1465 | - end | |
| 1466 | - | |
| 1467 | - should 'be able to edit a comment' do | |
| 1468 | - login_as profile.identifier | |
| 1469 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text', :accept_comments => false) | |
| 1470 | - comment = fast_create(Comment, :body => 'Original comment', :author_id => profile.id, :source_id => page.id, :source_type => 'Article') | |
| 1471 | - | |
| 1472 | - post :edit_comment, :id => comment.id, :profile => profile.identifier, :page => [ 'myarticle' ], :comment => { :body => 'Comment edited' } | |
| 1473 | - assert_equal 'Comment edited', Comment.find(comment.id).body | |
| 1474 | - end | |
| 1475 | - | |
| 1476 | - should 'edit comment from a page' do | |
| 1477 | - login_as profile.identifier | |
| 1478 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 1479 | - comment = fast_create(Comment, :body => 'Original comment', :author_id => profile.id, :source_id => page.id, :source_type => 'Article') | |
| 1480 | - | |
| 1481 | - get :edit_comment, :id => comment.id, :profile => profile.identifier, :page => [ 'myarticle' ], :comment => { :body => 'Comment edited' } | |
| 1482 | - assert_tag :tag => 'h1', :content => 'Edit comment' | |
| 1483 | - end | |
| 1484 | - | |
| 1485 | - should 'not edit comment from other page' do | |
| 1486 | - login_as profile.identifier | |
| 1487 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 1488 | - comment = fast_create(Comment, :body => 'Original comment', :author_id => profile.id, :source_id => page.id, :source_type => 'Article') | |
| 1489 | - | |
| 1490 | - other_page = profile.articles.create!(:name => 'my other article', :body => 'the body of the text') | |
| 1491 | - comment_on_other_page = fast_create(Comment, :body => 'Comment on other article', :author_id => profile.id, :source_id => other_page.id, :source_type => 'Article') | |
| 1492 | - | |
| 1493 | - get :edit_comment, :id => comment_on_other_page.id, :profile => profile.identifier, :page => [ 'myarticle' ], :comment => { :body => 'Comment edited' } | |
| 1494 | - assert_redirected_to page.url | |
| 1495 | - end | |
| 1496 | - | |
| 1497 | - should 'not crash on edit comment if comment does not exist' do | |
| 1498 | - login_as profile.identifier | |
| 1499 | - page = profile.articles.create!(:name => 'myarticle', :body => 'the body of the text') | |
| 1500 | - | |
| 1501 | - get :edit_comment, :id => 1000, :profile => profile.identifier, :page => [ 'myarticle' ], :comment => { :body => 'Comment edited' } | |
| 1502 | - assert_response 404 | |
| 1503 | - end | |
| 1504 | - | |
| 1505 | 1188 | end | ... | ... |
| ... | ... | @@ -0,0 +1,217 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | + | |
| 3 | +class ApproveCommentTest < ActiveSupport::TestCase | |
| 4 | + | |
| 5 | + def setup | |
| 6 | + ActionMailer::Base.delivery_method = :test | |
| 7 | + ActionMailer::Base.perform_deliveries = true | |
| 8 | + ActionMailer::Base.deliveries = [] | |
| 9 | + @profile = create_user('test_user', :email => "someone@anyhost.com").person | |
| 10 | + @article = fast_create(TextileArticle, :profile_id => @profile.id, :name => 'test name', :abstract => 'Lead of article', :body => 'This is my article') | |
| 11 | + @community = create(Community, :contact_email => "someone@anyhost.com") | |
| 12 | + @comment = @article.comments.build(:title => 'any comment', :body => "any text", :author => create_user('someperson').person) | |
| 13 | + end | |
| 14 | + | |
| 15 | + attr_reader :profile, :article, :community | |
| 16 | + | |
| 17 | + should 'be a task' do | |
| 18 | + ok { ApproveComment.new.kind_of?(Task) } | |
| 19 | + end | |
| 20 | + | |
| 21 | + should 'comment method deserialize comment attributes' do | |
| 22 | + a = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 23 | + assert_equal @comment.attributes, a.comment.attributes | |
| 24 | + end | |
| 25 | + | |
| 26 | + should 'article method returns comment article' do | |
| 27 | + @comment.article = @article | |
| 28 | + a = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 29 | + assert_equal @article, @comment.article | |
| 30 | + end | |
| 31 | + | |
| 32 | + should 'article method returns nil if comment.article if nil' do | |
| 33 | + @comment.article = nil | |
| 34 | + a = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 35 | + assert_nil @comment.article | |
| 36 | + end | |
| 37 | + | |
| 38 | + should 'not raise in comment action if comment_attributes if nil' do | |
| 39 | + a = ApproveComment.new(:comment_attributes => nil) | |
| 40 | + assert_nothing_raised do | |
| 41 | + a.comment | |
| 42 | + end | |
| 43 | + end | |
| 44 | + | |
| 45 | + should 'have article_name reference comment article' do | |
| 46 | + approve_comment = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 47 | + | |
| 48 | + assert_equal @article.name, approve_comment.article_name | |
| 49 | + end | |
| 50 | + | |
| 51 | + should 'article_name be article removed if there is no article associated to comment' do | |
| 52 | + @comment.article = nil | |
| 53 | + approve_comment = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 54 | + | |
| 55 | + assert_equal "Article removed.", approve_comment.article_name | |
| 56 | + end | |
| 57 | + | |
| 58 | + should 'have linked_subject reference comment article' do | |
| 59 | + approve_comment = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 60 | + | |
| 61 | + expected = {:text => @article.name, :url => @article.url} | |
| 62 | + assert_equal expected, approve_comment.linked_subject | |
| 63 | + end | |
| 64 | + | |
| 65 | + should 'have linked_subject ne nil if there is no article associated to comment' do | |
| 66 | + @comment.article = nil | |
| 67 | + approve_comment = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 68 | + | |
| 69 | + assert_nil approve_comment.linked_subject | |
| 70 | + end | |
| 71 | + | |
| 72 | + should 'create comment when finishing task' do | |
| 73 | + approve_comment = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 74 | + assert_difference @article.comments, :count, 1 do | |
| 75 | + approve_comment.finish | |
| 76 | + end | |
| 77 | + end | |
| 78 | + | |
| 79 | + should 'create comment with the created_at atribute passed as parameter when finishing task' do | |
| 80 | + now = Time.now - 10 | |
| 81 | + @comment.created_at = now | |
| 82 | + approve_comment = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 83 | + assert_difference @article.comments, :count, 1 do | |
| 84 | + approve_comment.finish | |
| 85 | + end | |
| 86 | + comment = Comment.last | |
| 87 | + assert_equal now.to_s, comment.created_at.to_s | |
| 88 | + end | |
| 89 | + | |
| 90 | + should 'require target (profile which the article is going to be commented)' do | |
| 91 | + task = ApproveComment.new | |
| 92 | + task.valid? | |
| 93 | + | |
| 94 | + ok('must not validate with empty target') { task.errors.invalid?(:target_id) } | |
| 95 | + | |
| 96 | + task.target = Person.new | |
| 97 | + task.valid? | |
| 98 | + ok('must validate when target is given') { task.errors.invalid?(:target_id)} | |
| 99 | + end | |
| 100 | + | |
| 101 | + should 'send e-mails' do | |
| 102 | + TaskMailer.expects(:deliver_target_notification).at_least_once | |
| 103 | + | |
| 104 | + task = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 105 | + | |
| 106 | + end | |
| 107 | + | |
| 108 | + should 'override target notification message method from Task' do | |
| 109 | + task = ApproveComment.new(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 110 | + assert_nothing_raised NotImplementedError do | |
| 111 | + task.target_notification_message | |
| 112 | + end | |
| 113 | + end | |
| 114 | + | |
| 115 | + should 'deliver target notification message' do | |
| 116 | + task = ApproveComment.new(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 117 | + | |
| 118 | + email = TaskMailer.deliver_target_notification(task, task.target_notification_message) | |
| 119 | + assert_match(/\[#{task.environment.name}\] #{task.requestor.name} wants to comment the article: #{task.article_name}/, email.subject) | |
| 120 | + end | |
| 121 | + | |
| 122 | + should 'alert when reference article is removed' do | |
| 123 | + a = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 124 | + | |
| 125 | + @article.destroy | |
| 126 | + a.reload | |
| 127 | + assert_equal "The article was removed.", a.information[:message] | |
| 128 | + end | |
| 129 | + | |
| 130 | + should 'display anonymous name if the requestor is nil' do | |
| 131 | + a = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => nil) | |
| 132 | + | |
| 133 | + assert_match /nonymous/, a.information[:message] | |
| 134 | + end | |
| 135 | + | |
| 136 | + should 'accept_details be true' do | |
| 137 | + a = ApproveComment.new | |
| 138 | + assert a.accept_details | |
| 139 | + end | |
| 140 | + | |
| 141 | + should 'reject_details be true' do | |
| 142 | + a = ApproveComment.new | |
| 143 | + assert a.reject_details | |
| 144 | + end | |
| 145 | + | |
| 146 | + should 'default decision be skip if there is an article associated to task' do | |
| 147 | + a = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 148 | + assert 'skip', a.default_decision | |
| 149 | + end | |
| 150 | + | |
| 151 | + should 'default decision be reject if there is no article associated to task' do | |
| 152 | + a = ApproveComment.new() | |
| 153 | + assert 'reject', a.default_decision | |
| 154 | + end | |
| 155 | + | |
| 156 | + should 'accept_disabled be true if there is no article associated to task' do | |
| 157 | + a = ApproveComment.new | |
| 158 | + assert a.accept_disabled? | |
| 159 | + end | |
| 160 | + | |
| 161 | + should 'accept_disabled be false if there is an article associated to task' do | |
| 162 | + a = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 163 | + assert !a.accept_disabled? | |
| 164 | + end | |
| 165 | + | |
| 166 | + should 'have target notification description' do | |
| 167 | + task = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 168 | + | |
| 169 | + assert_match(/#{task.requestor.name} wants to comment the article: #{article.name}/, task.target_notification_description) | |
| 170 | + end | |
| 171 | + | |
| 172 | + should 'have an target notification description for comments on removed articles' do | |
| 173 | + task = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 174 | + | |
| 175 | + @article.destroy | |
| 176 | + assert_match(/#{task.requestor.name} wanted to comment the article but it was removed/, task.target_notification_description) | |
| 177 | + end | |
| 178 | + | |
| 179 | + should 'have a default finished messsage after approval' do | |
| 180 | + task = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 181 | + assert_match(/Your request for comment the article "#{task.article.title}" was approved/, task.task_finished_message) | |
| 182 | + end | |
| 183 | + | |
| 184 | + should 'have a personalized finished messsage after approval' do | |
| 185 | + task = ApproveComment.create!(:target => @community, :comment_attributes => @comment.attributes.to_json, :requestor => @profile) | |
| 186 | + task.stubs(:closing_statment).returns('somenthing') | |
| 187 | + | |
| 188 | + assert_match(/Your .*#{task.article.title}.*Here is the comment.*\n\n#{task.closing_statment}/, task.task_finished_message) | |
| 189 | + end | |
| 190 | + | |
| 191 | + should 'return reject message even without reject explanation' do | |
| 192 | + task = ApproveComment.new | |
| 193 | + assert_not_nil task.task_cancelled_message | |
| 194 | + end | |
| 195 | + | |
| 196 | + should 'show the name of the article in the reject message' do | |
| 197 | + task = ApproveComment.new(:comment_attributes => @comment.attributes.to_json) | |
| 198 | + assert_match /Your request for commenting the article .*#{@article.name}.* was rejected/, task.task_cancelled_message | |
| 199 | + end | |
| 200 | + | |
| 201 | + should 'return reject message with reject explanation' do | |
| 202 | + task = ApproveComment.new | |
| 203 | + task.reject_explanation= "Some reject explanation" | |
| 204 | + assert_match(/Your request for commenting .* Here is the reject explanation .*\n\n#{task.reject_explanation}/, task.task_cancelled_message) | |
| 205 | + end | |
| 206 | + | |
| 207 | + should 'requestor name be the name of the requestor' do | |
| 208 | + a = fast_create(ApproveComment, :target_id => community, :requestor_id => profile) | |
| 209 | + assert_equal profile.name, a.requestor_name | |
| 210 | + end | |
| 211 | + | |
| 212 | + should 'requestor name be Anonymous if there is no requestor' do | |
| 213 | + a = fast_create(ApproveComment, :target_id => community) | |
| 214 | + assert_equal 'Anonymous', a.requestor_name | |
| 215 | + end | |
| 216 | + | |
| 217 | +end | ... | ... |
test/unit/article_test.rb
| ... | ... | @@ -664,6 +664,30 @@ class ArticleTest < ActiveSupport::TestCase |
| 664 | 664 | assert a.notify_comments? |
| 665 | 665 | end |
| 666 | 666 | |
| 667 | + should 'has moderate comments false by default' do | |
| 668 | + a = Article.create!(:name => 'my article', :body => 'my text', :profile_id => profile.id) | |
| 669 | + a.reload | |
| 670 | + assert a.moderate_comments == false | |
| 671 | + end | |
| 672 | + | |
| 673 | + should 'save a article with moderate comments as true' do | |
| 674 | + a = Article.create!(:name => 'my article', :body => 'my text', :profile_id => profile.id, :moderate_comments => true) | |
| 675 | + a.reload | |
| 676 | + assert a.moderate_comments | |
| 677 | + end | |
| 678 | + | |
| 679 | + should 'moderate_comments? return true if moderate_comments variable is true' do | |
| 680 | + a = Article.new | |
| 681 | + a.moderate_comments= true | |
| 682 | + assert a.moderate_comments? | |
| 683 | + end | |
| 684 | + | |
| 685 | + should 'moderate_comments? return false if moderate_comments variable is false' do | |
| 686 | + a = Article.new | |
| 687 | + a.moderate_comments= false | |
| 688 | + assert !a.moderate_comments? | |
| 689 | + end | |
| 690 | + | |
| 667 | 691 | should 'hold hits count' do |
| 668 | 692 | a = fast_create(Article, :name => 'Test article', :profile_id => profile.id) |
| 669 | 693 | a.hits = 10 | ... | ... |
| ... | ... | @@ -0,0 +1,139 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | + | |
| 3 | +class CommentHelperTest < ActiveSupport::TestCase | |
| 4 | + | |
| 5 | + include CommentHelper | |
| 6 | + include ActionView::Helpers::TagHelper | |
| 7 | + include NoosferoTestHelper | |
| 8 | + | |
| 9 | + def setup | |
| 10 | + @user = create_user('usertest').person | |
| 11 | + @profile = @user | |
| 12 | + self.stubs(:logged_in?).returns(true) | |
| 13 | + self.stubs(:report_abuse).returns('<a href="#">link</a>') | |
| 14 | + self.stubs(:expirable_comment_link).returns('<a href="#">link</a>') | |
| 15 | + @plugins.stubs(:dispatch).returns([]) | |
| 16 | + end | |
| 17 | + | |
| 18 | + attr_reader :user, :profile | |
| 19 | + | |
| 20 | + should 'show menu if it has links for actions' do | |
| 21 | + article = Article.new(:profile => profile) | |
| 22 | + comment = Comment.new(:article => article) | |
| 23 | + menu = comment_actions(comment) | |
| 24 | + assert menu | |
| 25 | + end | |
| 26 | + | |
| 27 | + should 'do not show menu if it has no actions' do | |
| 28 | + comment = Comment.new | |
| 29 | + self.stubs(:links_for_comment_actions).returns([]) | |
| 30 | + menu = comment_actions(comment) | |
| 31 | + assert !menu | |
| 32 | + end | |
| 33 | + | |
| 34 | + should 'do not show menu if it has nil actions only' do | |
| 35 | + comment = Comment.new | |
| 36 | + self.stubs(:link_for_report_abuse).returns(nil) | |
| 37 | + self.stubs(:link_for_spam).returns(nil) | |
| 38 | + self.stubs(:link_for_edit).returns(nil) | |
| 39 | + self.stubs(:link_for_remove).returns(nil) | |
| 40 | + menu = comment_actions(comment) | |
| 41 | + assert !menu | |
| 42 | + end | |
| 43 | + | |
| 44 | + should 'include actions of plugins in menu' do | |
| 45 | + article = Article.new(:profile => profile) | |
| 46 | + comment = Comment.new(:article => article) | |
| 47 | + plugin_action = {:link => 'plugin_action'} | |
| 48 | + @plugins.stubs(:dispatch).returns([plugin_action]) | |
| 49 | + links = links_for_comment_actions(comment) | |
| 50 | + assert_includes links, plugin_action | |
| 51 | + end | |
| 52 | + | |
| 53 | + should 'include lambda actions of plugins in menu' do | |
| 54 | + article = Article.new(:profile => profile) | |
| 55 | + comment = Comment.new(:article => article) | |
| 56 | + plugin_action = lambda{[{:link => 'plugin_action'}, {:link => 'plugin_action2'}]} | |
| 57 | + @plugins.stubs(:dispatch).returns([plugin_action]) | |
| 58 | + links = links_for_comment_actions(comment) | |
| 59 | + assert_includes links, {:link => 'plugin_action'} | |
| 60 | + assert_includes links, {:link => 'plugin_action2'} | |
| 61 | + end | |
| 62 | + | |
| 63 | + should 'return link for report abuse action when comment has a author' do | |
| 64 | + comment = Comment.new | |
| 65 | + comment.author = user | |
| 66 | + link = link_for_report_abuse(comment) | |
| 67 | + assert link | |
| 68 | + end | |
| 69 | + | |
| 70 | + should 'do not return link for report abuse action when comment has no author' do | |
| 71 | + comment = Comment.new | |
| 72 | + link = link_for_report_abuse(comment) | |
| 73 | + assert !link | |
| 74 | + end | |
| 75 | + | |
| 76 | + should 'return link for mark comment as spam' do | |
| 77 | + comment = Comment.new | |
| 78 | + comment.stubs(:can_be_marked_as_spam_by?).with(user).returns(true) | |
| 79 | + link = link_for_spam(comment) | |
| 80 | + assert_match /Mark as SPAM/, link[:link] | |
| 81 | + end | |
| 82 | + | |
| 83 | + should 'not return link for mark comment as spam if user does not have the permissions' do | |
| 84 | + comment = Comment.new | |
| 85 | + comment.stubs(:can_be_marked_as_spam_by?).with(user).returns(false) | |
| 86 | + link = link_for_spam(comment) | |
| 87 | + assert_nil link | |
| 88 | + end | |
| 89 | + | |
| 90 | + should 'return link for mark comment as not spam' do | |
| 91 | + comment = Comment.new | |
| 92 | + comment.spam = true | |
| 93 | + comment.stubs(:can_be_marked_as_spam_by?).with(user).returns(true) | |
| 94 | + link = link_for_spam(comment) | |
| 95 | + assert_match /Mark as NOT SPAM/, link[:link] | |
| 96 | + end | |
| 97 | + | |
| 98 | + should 'not return link for mark comment as not spam if user does not have the permissions' do | |
| 99 | + comment = Comment.new | |
| 100 | + comment.spam = true | |
| 101 | + comment.stubs(:can_be_marked_as_spam_by?).with(user).returns(false) | |
| 102 | + link = link_for_spam(comment) | |
| 103 | + assert_nil link | |
| 104 | + end | |
| 105 | + | |
| 106 | + should 'do not return link for edit comment' do | |
| 107 | + comment = Comment.new | |
| 108 | + comment.stubs(:can_be_updated_by?).with(user).returns(false) | |
| 109 | + link = link_for_edit(comment) | |
| 110 | + assert_nil link | |
| 111 | + end | |
| 112 | + | |
| 113 | + should 'return link for edit comment' do | |
| 114 | + comment = Comment.new | |
| 115 | + comment.stubs(:can_be_updated_by?).with(user).returns(true) | |
| 116 | + link = link_for_edit(comment) | |
| 117 | + assert link | |
| 118 | + end | |
| 119 | + | |
| 120 | + should 'do not return link for remove comment' do | |
| 121 | + comment = Comment.new | |
| 122 | + comment.stubs(:can_be_destroyed_by?).with(user).returns(false) | |
| 123 | + link = link_for_remove(comment) | |
| 124 | + assert_nil link | |
| 125 | + end | |
| 126 | + | |
| 127 | + should 'return link for remove comment' do | |
| 128 | + comment = Comment.new | |
| 129 | + comment.stubs(:can_be_destroyed_by?).with(user).returns(true) | |
| 130 | + link = link_for_remove(comment) | |
| 131 | + assert link | |
| 132 | + end | |
| 133 | + | |
| 134 | + def link_to_function(content, url, options = {}) | |
| 135 | + link_to(content, url, options) | |
| 136 | + end | |
| 137 | + | |
| 138 | +end | |
| 139 | + | ... | ... |
test/unit/comment_test.rb
| ... | ... | @@ -550,6 +550,156 @@ class CommentTest < ActiveSupport::TestCase |
| 550 | 550 | SpammerLogger.clean_log |
| 551 | 551 | end |
| 552 | 552 | |
| 553 | + should 'not need moderation if article is not moderated' do | |
| 554 | + article = Article.new | |
| 555 | + comment = Comment.new(:article => article) | |
| 556 | + | |
| 557 | + assert !comment.need_moderation? | |
| 558 | + end | |
| 559 | + | |
| 560 | + should 'not need moderation if the comment author is the article author' do | |
| 561 | + author = Person.new | |
| 562 | + article = Article.new | |
| 563 | + | |
| 564 | + article.stubs(:author).returns(author) | |
| 565 | + article.moderate_comments = true | |
| 566 | + | |
| 567 | + comment = Comment.new(:article => article) | |
| 568 | + comment.stubs(:author).returns(author) | |
| 569 | + | |
| 570 | + assert !comment.need_moderation? | |
| 571 | + end | |
| 572 | + | |
| 573 | + should 'need moderation if article is moderated and the comment has no author' do | |
| 574 | + article = Article.new | |
| 575 | + article.stubs(:moderate_comments?).returns(true) | |
| 576 | + | |
| 577 | + comment = Comment.new(:article => article) | |
| 578 | + | |
| 579 | + assert comment.need_moderation? | |
| 580 | + end | |
| 581 | + | |
| 582 | + should 'need moderation if article is moderated and the comment author is different from article author' do | |
| 583 | + article_author = Person.new | |
| 584 | + comment_author = Person.new | |
| 585 | + | |
| 586 | + article = Article.new | |
| 587 | + article.stubs(:author).returns(article_author) | |
| 588 | + article.stubs(:moderate_comments?).returns(true) | |
| 589 | + | |
| 590 | + comment = Comment.new(:article => article) | |
| 591 | + comment.stubs(:author).returns(comment_author) | |
| 592 | + | |
| 593 | + assert comment.need_moderation? | |
| 594 | + end | |
| 595 | + | |
| 596 | + should 'not be able to destroy comment without user' do | |
| 597 | + comment = Comment.new | |
| 598 | + | |
| 599 | + assert !comment.can_be_destroyed_by?(nil) | |
| 600 | + end | |
| 601 | + | |
| 602 | + should 'not be able to destroy comment' do | |
| 603 | + user = Person.new | |
| 604 | + profile = Profile.new | |
| 605 | + article = Article.new(:profile => profile) | |
| 606 | + comment = Comment.new(:article => article) | |
| 607 | + user.expects(:has_permission?).with(:moderate_comments, profile).returns(false) | |
| 608 | + | |
| 609 | + assert !comment.can_be_destroyed_by?(user) | |
| 610 | + end | |
| 611 | + | |
| 612 | + should 'be able to destroy comment if is the author' do | |
| 613 | + user = Person.new | |
| 614 | + comment = Comment.new(:author => user) | |
| 615 | + | |
| 616 | + assert comment.can_be_destroyed_by?(user) | |
| 617 | + end | |
| 618 | + | |
| 619 | + should 'be able to destroy comment if is the profile' do | |
| 620 | + user = Person.new | |
| 621 | + article = Article.new(:profile => user) | |
| 622 | + comment = Comment.new(:article => article) | |
| 623 | + | |
| 624 | + assert comment.can_be_destroyed_by?(user) | |
| 625 | + end | |
| 626 | + | |
| 627 | + should 'be able to destroy comment if can moderate_comments on the profile' do | |
| 628 | + user = Person.new | |
| 629 | + profile = Profile.new | |
| 630 | + article = Article.new(:profile => profile) | |
| 631 | + comment = Comment.new(:article => article) | |
| 632 | + | |
| 633 | + user.expects(:has_permission?).with(:moderate_comments, profile).returns(true) | |
| 634 | + | |
| 635 | + assert comment.can_be_destroyed_by?(user) | |
| 636 | + end | |
| 637 | + | |
| 638 | + should 'not be able to mark comment as spam without user' do | |
| 639 | + comment = Comment.new | |
| 640 | + | |
| 641 | + assert !comment.can_be_marked_as_spam_by?(nil) | |
| 642 | + end | |
| 643 | + | |
| 644 | + should 'not be able to mark comment as spam' do | |
| 645 | + user = Person.new | |
| 646 | + profile = Profile.new | |
| 647 | + article = Article.new(:profile => profile) | |
| 648 | + comment = Comment.new(:article => article) | |
| 649 | + user.expects(:has_permission?).with(:moderate_comments, profile).returns(false) | |
| 650 | + | |
| 651 | + assert !comment.can_be_marked_as_spam_by?(user) | |
| 652 | + end | |
| 653 | + | |
| 654 | + should 'be able to mark comment as spam if is the profile' do | |
| 655 | + user = Person.new | |
| 656 | + article = Article.new(:profile => user) | |
| 657 | + comment = Comment.new(:article => article) | |
| 658 | + | |
| 659 | + assert comment.can_be_marked_as_spam_by?(user) | |
| 660 | + end | |
| 661 | + | |
| 662 | + should 'be able to mark comment as spam if can moderate_comments on the profile' do | |
| 663 | + user = Person.new | |
| 664 | + profile = Profile.new | |
| 665 | + article = Article.new(:profile => profile) | |
| 666 | + comment = Comment.new(:article => article) | |
| 667 | + | |
| 668 | + user.expects(:has_permission?).with(:moderate_comments, profile).returns(true) | |
| 669 | + | |
| 670 | + assert comment.can_be_marked_as_spam_by?(user) | |
| 671 | + end | |
| 672 | + | |
| 673 | + should 'not be able to update comment without user' do | |
| 674 | + comment = Comment.new | |
| 675 | + | |
| 676 | + assert !comment.can_be_updated_by?(nil) | |
| 677 | + end | |
| 678 | + | |
| 679 | + should 'not be able to update comment' do | |
| 680 | + user = Person.new | |
| 681 | + comment = Comment.new | |
| 682 | + | |
| 683 | + assert !comment.can_be_updated_by?(user) | |
| 684 | + end | |
| 685 | + | |
| 686 | + should 'be able to update comment if is the author' do | |
| 687 | + user = Person.new | |
| 688 | + comment = Comment.new(:author => user) | |
| 689 | + | |
| 690 | + assert comment.can_be_updated_by?(user) | |
| 691 | + end | |
| 692 | + | |
| 693 | + should 'get comment root' do | |
| 694 | + c1 = Comment.new | |
| 695 | + c2 = Comment.new(:reply_of => c1) | |
| 696 | + c3 = Comment.new(:reply_of => c2) | |
| 697 | + | |
| 698 | + assert_equal c1, c3.comment_root | |
| 699 | + assert_equal c1, c2.comment_root | |
| 700 | + assert_equal c1, c1.comment_root | |
| 701 | + end | |
| 702 | + | |
| 553 | 703 | private |
| 554 | 704 | |
| 555 | 705 | def create_comment(args = {}) | ... | ... |