Commit 629998e741fee1c5748c43833a458be38122063e

Authored by Joenio Costa
Committed by Daniela Feitosa
1 parent cc6d42c3

Fixing crash on visualizing forum with comments from unauthenticated users

(ActionItem1822)
app/helpers/forum_helper.rb
... ... @@ -40,8 +40,12 @@ module ForumHelper
40 40 end
41 41  
42 42 def last_topic_update(article)
43   - last_update_at, last_update_by = (article.comments.count.zero? ? [article.updated_at, article.author] : [article.comments.last.created_at, article.comments.last.author])
44   - time_ago_as_sentence(last_update_at) + ' ' + _('ago') + ' ' + _('by') + ' ' + link_to(last_update_by.name, last_update_by.url)
  43 + info = article.info_from_last_update
  44 + if info[:author_url]
  45 + time_ago_as_sentence(info[:date]) + ' ' + _('ago') + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url])
  46 + else
  47 + time_ago_as_sentence(info[:date]) + ' ' + _('ago') + ' ' + _('by') + ' ' + info[:author_name]
  48 + end
45 49 end
46 50  
47 51 end
... ...
app/models/article.rb
... ... @@ -232,6 +232,15 @@ class Article < ActiveRecord::Base
232 232 self.parent and self.parent.blog?
233 233 end
234 234  
  235 + def info_from_last_update
  236 + last_comment = comments.last
  237 + if last_comment
  238 + {:date => last_comment.created_at, :author_name => last_comment.author_name, :author_url => last_comment.author_url}
  239 + else
  240 + {:date => updated_at, :author_name => author.name, :author_url => author.url}
  241 + end
  242 + end
  243 +
235 244 def url
236 245 @url ||= self.profile.url.merge(:page => path.split('/'))
237 246 end
... ...
app/models/comment.rb
... ... @@ -43,6 +43,10 @@ class Comment < ActiveRecord::Base
43 43 author ? author.url : email
44 44 end
45 45  
  46 + def author_url
  47 + author ? author.url : nil
  48 + end
  49 +
46 50 def url
47 51 article.view_url.merge(:anchor => anchor)
48 52 end
... ...
features/forum.feature
... ... @@ -67,3 +67,29 @@ Feature: forum
67 67 And I go to /joaosilva/forum-one
68 68 When I follow "Configure forum"
69 69 Then I should be on edit "Forum One" by joaosilva
  70 +
  71 + Scenario: last topic update by unautenticated user should not link
  72 + Given the following forums
  73 + | owner | name |
  74 + | joaosilva | Forum |
  75 + And the following articles
  76 + | owner | name | parent |
  77 + | joaosilva | Post one | Forum |
  78 + And the following comments
  79 + | article | name | email | title | body |
  80 + | Post one | Joao | joao@example.com | Hi all | Hi all |
  81 + When I go to /joaosilva/forum
  82 + Then I should not see "Joao" link
  83 +
  84 + Scenario: last topic update by autenticated user should link to profile url
  85 + Given the following forums
  86 + | owner | name |
  87 + | joaosilva | Forum |
  88 + And the following articles
  89 + | owner | name | parent |
  90 + | joaosilva | Post one | Forum |
  91 + And the following comments
  92 + | article | author | title | body |
  93 + | Post one | joaosilva | Hi all | Hi all |
  94 + When I go to /joaosilva/forum
  95 + Then I should see "Joao" linking to "http:///joaosilva"
... ...
features/step_definitions/custom_webrat_steps.rb
... ... @@ -6,6 +6,11 @@ When /^I should not see "([^\"]+)" link$/ do |text|
6 6 response.should_not have_selector("a:contains('#{text}')")
7 7 end
8 8  
  9 +When /^I should see "([^\"]+)" linking to "([^\"]+)"$/ do |text, href|
  10 + response.should have_selector("a:contains('#{text}')")
  11 + response.should have_selector("a[href='#{href}']")
  12 +end
  13 +
9 14 Then /^I should be exactly on (.+)$/ do |page_name|
10 15 URI.parse(current_url).request_uri.should == path_to(page_name)
11 16 end
... ...
features/step_definitions/noosfero_steps.rb
... ... @@ -52,9 +52,14 @@ Given /^the following (articles|events|blogs|folders|forums|galleries)$/ do |con
52 52 }[content] || raise("Don't know how to build %s" % content)
53 53 table.hashes.map{|item| item.dup}.each do |item|
54 54 owner_identifier = item.delete("owner")
  55 + parent = item.delete("parent")
55 56 owner = Profile[owner_identifier]
56 57 home = item.delete("homepage")
57   - result = klass.create!(item.merge(:profile => owner))
  58 + result = klass.new(item.merge(:profile => owner))
  59 + if parent
  60 + result.parent = Article.find_by_name(parent)
  61 + end
  62 + result.save!
58 63 if home
59 64 owner.home_page = result
60 65 owner.save!
... ... @@ -318,8 +323,11 @@ Given /^the following comments?$/ do |table|
318 323 table.hashes.each do |item|
319 324 data = item.dup
320 325 article = Article.find_by_name(data.delete("article"))
321   - author = Profile[data.delete("author")]
322   - comment = article.comments.build(:author => author, :title => data.delete("title"), :body => data.delete("body"))
  326 + author = data.delete("author")
  327 + comment = article.comments.build(data)
  328 + if author
  329 + comment.author = Profile[author]
  330 + end
323 331 comment.save!
324 332 end
325 333 end
... ...
test/test_helper.rb
... ... @@ -193,7 +193,8 @@ module NoosferoTestHelper
193 193 end
194 194  
195 195 def content_tag(tag, content, options = {})
196   - "<#{tag}>#{content}</#{tag}>"
  196 + tag_attr = options.blank? ? '' : ' ' + options.collect{ |o| "#{o[0]}=\"#{o[1]}\"" }.join(' ')
  197 + "<#{tag}#{tag_attr}>#{content}</#{tag}>"
197 198 end
198 199  
199 200 def submit_tag(content, options = {})
... ... @@ -228,6 +229,8 @@ module NoosferoTestHelper
228 229 icon
229 230 end
230 231  
  232 + def will_paginate(arg1, arg2)
  233 + end
231 234 end
232 235  
233 236 class ActionController::IntegrationTest
... ...
test/unit/article_block_test.rb
... ... @@ -89,7 +89,7 @@ class ArticleBlockTest &lt; Test::Unit::TestCase
89 89 block.expects(:title).returns('')
90 90 block.stubs(:article).returns(article)
91 91  
92   - assert_equal "<h3><span></span></h3>Article content", instance_eval(&block.content)
  92 + assert_equal "<h3 class=\"block-title empty\"><span></span></h3>Article content", instance_eval(&block.content)
93 93 end
94 94  
95 95 should "display title if defined" do
... ... @@ -99,7 +99,7 @@ class ArticleBlockTest &lt; Test::Unit::TestCase
99 99 block.expects(:title).returns('Article title')
100 100 block.stubs(:article).returns(article)
101 101  
102   - assert_equal "<h3><span>Article title</span></h3>Article content", instance_eval(&block.content)
  102 + assert_equal "<h3 class=\"block-title\"><span>Article title</span></h3>Article content", instance_eval(&block.content)
103 103 end
104 104  
105 105 should 'display image if article is an image' do
... ...
test/unit/article_test.rb
... ... @@ -1423,4 +1423,21 @@ class ArticleTest &lt; Test::Unit::TestCase
1423 1423 assert_equal 'some name', a.author_name
1424 1424 end
1425 1425  
  1426 + should 'retrieve latest info from topic when has no comments' do
  1427 + forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id)
  1428 + post = fast_create(TextileArticle, :name => 'First post', :profile_id => profile.id, :parent_id => forum.id, :updated_at => Time.now)
  1429 + assert_equal post.updated_at, post.info_from_last_update[:date]
  1430 + assert_equal profile.name, post.info_from_last_update[:author_name]
  1431 + assert_equal profile.url, post.info_from_last_update[:author_url]
  1432 + end
  1433 +
  1434 + should 'retrieve latest info from comment when has comments' do
  1435 + forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id)
  1436 + post = fast_create(TextileArticle, :name => 'First post', :profile_id => profile.id, :parent_id => forum.id, :updated_at => Time.now)
  1437 + post.comments << Comment.new(:name => 'Guest', :email => 'guest@example.com', :title => 'test comment', :body => 'hello!')
  1438 + assert_equal post.comments.last.created_at, post.info_from_last_update[:date]
  1439 + assert_equal "Guest", post.info_from_last_update[:author_name]
  1440 + assert_nil post.info_from_last_update[:author_url]
  1441 + end
  1442 +
1426 1443 end
... ...
test/unit/comment_test.rb
... ... @@ -317,4 +317,14 @@ class CommentTest &lt; Test::Unit::TestCase
317 317 assert result[1].replies.empty?
318 318 end
319 319  
  320 + should 'provide author url for authenticated user' do
  321 + author = Person.new
  322 + author.expects(:url).returns('http://blabla.net/author')
  323 + assert_equal 'http://blabla.net/author', Comment.new(:author => author).author_url
  324 + end
  325 +
  326 + should 'not provide author url for unauthenticated user' do
  327 + assert_nil Comment.new(:email => 'my@email.com').author_url
  328 + end
  329 +
320 330 end
... ...
test/unit/forum_helper_test.rb
... ... @@ -9,7 +9,6 @@ class ForumHelperTest &lt; Test::Unit::TestCase
9 9 include ApplicationHelper
10 10  
11 11 def setup
12   - stubs(:show_date).returns('')
13 12 @environment = Environment.default
14 13 @profile = create_user('forum_helper_test').person
15 14 @forum = fast_create(Forum, :profile_id => profile.id, :name => 'Forum test')
... ... @@ -39,9 +38,9 @@ class ForumHelperTest &lt; Test::Unit::TestCase
39 38 should 'return post update if it has no comments' do
40 39 author = create_user('forum test author').person
41 40 some_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => forum, :published => true)
42   - some_post.expects(:author).returns(author)
  41 + some_post.expects(:author).returns(author).times(2)
43 42 assert some_post.comments.empty?
44   - assert_equal "#{some_post.updated_at.to_s} ago by #{author.name}", last_topic_update(some_post)
  43 + assert_match /#{some_post.updated_at.to_s} ago by <a href='[^']+'>forum test author<\/a>/, last_topic_update(some_post)
45 44 end
46 45  
47 46 should 'return last comment date if it has comments' do
... ... @@ -51,27 +50,19 @@ class ForumHelperTest &lt; Test::Unit::TestCase
51 50 some_post.comments << Comment.new(:title => 'test', :body => 'test', :author => a2)
52 51 c = Comment.last
53 52 assert_equal 2, some_post.comments.count
54   - assert_equal "#{c.created_at.to_s} ago by #{a2.name}", last_topic_update(some_post)
  53 + assert_match /#{c.created_at.to_s} ago by <a href='[^']+'>a2<\/a>/, last_topic_update(some_post)
55 54 end
56 55  
57   - protected
58   -
59   - def will_paginate(arg1, arg2)
60   - end
61   -
62   - def link_to(content, url)
63   - content
  56 + should "return last comment author's name from unauthenticated user" do
  57 + some_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => forum, :published => true)
  58 + some_post.comments << Comment.new(:name => 'John', :email => 'lenon@example.com', :title => 'test', :body => 'test')
  59 + c = Comment.last
  60 + assert_match /#{c.created_at.to_s} ago by John/m, last_topic_update(some_post)
64 61 end
65 62  
66   - def tag(tag, args = {})
67   - attrs = args.map{|k,v| "#{k}='#{v}'"}.join(' ')
68   - "<#{tag} #{attrs} />"
69   - end
  63 + protected
70 64  
71   - def content_tag(tag, content, options = {})
72   - tag_attr = options.blank? ? "" : options.collect{ |o| "#{o[0]}=\"#{o[1]}\"" }.join(' ')
73   - "<#{tag}#{tag_attr}>#{content}</#{tag}>"
74   - end
  65 + include NoosferoTestHelper
75 66  
76 67 def time_ago_as_sentence(t = Time.now)
77 68 t.to_s
... ...