radiant-comments-extension 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +40 -0
  3. data/HELP_admin.markdown +52 -0
  4. data/HELP_designer.markdown +36 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +53 -0
  7. data/Rakefile +133 -0
  8. data/TODO +6 -0
  9. data/VERSION +1 -0
  10. data/app/controllers/admin/comments_controller.rb +130 -0
  11. data/app/controllers/comments_controller.rb +59 -0
  12. data/app/helpers/admin/comments_helper.rb +7 -0
  13. data/app/models/akismet_spam_filter.rb +37 -0
  14. data/app/models/comment.rb +121 -0
  15. data/app/models/comment_mailer.rb +24 -0
  16. data/app/models/mollom_spam_filter.rb +52 -0
  17. data/app/models/simple_spam_filter.rb +38 -0
  18. data/app/models/spam_filter.rb +43 -0
  19. data/app/views/admin/comments/_comment.rhtml +34 -0
  20. data/app/views/admin/comments/_form.rhtml +36 -0
  21. data/app/views/admin/comments/edit.rhtml +5 -0
  22. data/app/views/admin/comments/index.rhtml +55 -0
  23. data/app/views/admin/pages/_comments.rhtml +0 -0
  24. data/app/views/admin/pages/_edit_comments_enabled.rhtml +8 -0
  25. data/app/views/admin/pages/_index_head_view_comments.rhtml +1 -0
  26. data/app/views/admin/pages/_index_view_comments.rhtml +11 -0
  27. data/app/views/comment_mailer/comment_notification.rhtml +21 -0
  28. data/app/views/comments/_comment.rhtml +1 -0
  29. data/app/views/comments/_form.rhtml +23 -0
  30. data/app/views/comments/_new.rhtml +5 -0
  31. data/autotest/discover.rb +3 -0
  32. data/comments_extension.rb +81 -0
  33. data/cucumber.yml +1 -0
  34. data/db/migrate/001_create_comments.rb +29 -0
  35. data/db/migrate/002_create_snippets.rb +115 -0
  36. data/db/migrate/003_change_filter_id_from_integer_to_string.rb +10 -0
  37. data/db/migrate/004_add_approval_columns.rb +13 -0
  38. data/db/migrate/005_add_mollomid_column.rb +11 -0
  39. data/db/migrate/006_move_config_to_migrations.rb +22 -0
  40. data/db/migrate/007_add_preference_for_simple_spamcheck.rb +12 -0
  41. data/features/support/env.rb +16 -0
  42. data/features/support/paths.rb +16 -0
  43. data/lib/akismet.rb +134 -0
  44. data/lib/comment_page_extensions.rb +41 -0
  45. data/lib/comment_tags.rb +338 -0
  46. data/lib/mollom.rb +246 -0
  47. data/lib/radiant-comments-extension.rb +0 -0
  48. data/lib/tasks/comments_extension_tasks.rake +68 -0
  49. data/public/images/admin/accept.png +0 -0
  50. data/public/images/admin/comment_edit.png +0 -0
  51. data/public/images/admin/comments.png +0 -0
  52. data/public/images/admin/comments_delete.png +0 -0
  53. data/public/images/admin/delete.png +0 -0
  54. data/public/images/admin/email.png +0 -0
  55. data/public/images/admin/error.png +0 -0
  56. data/public/images/admin/link.png +0 -0
  57. data/public/images/admin/page_white_edit.png +0 -0
  58. data/public/images/admin/table_save.png +0 -0
  59. data/public/images/admin/tick.png +0 -0
  60. data/public/stylesheets/admin/comments.css +41 -0
  61. data/radiant-comments-extension.gemspec +133 -0
  62. data/spec/controllers/admin/comments_controller_spec.rb +57 -0
  63. data/spec/controllers/admin/comments_routing_spec.rb +43 -0
  64. data/spec/controllers/page_postback_spec.rb +51 -0
  65. data/spec/datasets/comments_dataset.rb +7 -0
  66. data/spec/models/akismet_spam_filter_spec.rb +61 -0
  67. data/spec/models/comment_spec.rb +148 -0
  68. data/spec/models/comment_tags_spec.rb +55 -0
  69. data/spec/models/mollom_spam_filter_spec.rb +103 -0
  70. data/spec/models/simple_spam_filter_spec.rb +44 -0
  71. data/spec/models/spam_filter_spec.rb +38 -0
  72. data/spec/spec.opts +6 -0
  73. data/spec/spec_helper.rb +36 -0
  74. data/test/fixtures/users.yml +6 -0
  75. data/test/integration/comment_enabling_test.rb +18 -0
  76. data/test/test_helper.rb +24 -0
  77. data/test/unit/comment_test.rb +52 -0
  78. metadata +177 -0
@@ -0,0 +1,57 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Admin::CommentsController do
4
+ dataset :users_and_pages, :comments
5
+ before(:each) do
6
+ login_as :admin
7
+ end
8
+
9
+ describe "requesting 'show' with GET" do
10
+ it "should redirect to the comment edit screen" do
11
+ id = comments(:first).id
12
+ get :show, :id => id
13
+ response.should redirect_to("http://test.host/admin/comments/#{id}/edit")
14
+ end
15
+ end
16
+ describe "requesting 'edit' with GET" do
17
+ describe "for an invalid id" do
18
+ it "should redirect to the comments index" do
19
+ get :edit, :id => 999
20
+ response.should redirect_to('http://test.host/admin/comments')
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "requesting 'destroy' with DELETE" do
26
+ describe "for an invalid id" do
27
+ it "should redirect to the comments index" do
28
+ delete :destroy, :id => 999
29
+ response.should redirect_to('http://test.host/admin/comments')
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "requesting 'destroy_unapproved' with DELETE" do
35
+ before(:each) do
36
+ request.env['HTTP_REFERER'] = 'http://test.host/admin/comments'
37
+ Comment.count.should > 0
38
+ end
39
+ it "should destroy all of the unapproved comments" do
40
+ Comment.should_receive(:unapproved).and_return(Comment)
41
+ Comment.should_receive(:destroy_all).and_return(true)
42
+ delete :destroy_unapproved
43
+ end
44
+ it "should leave no unapproved comments in the database" do
45
+ delete :destroy_unapproved
46
+ Comment.count.should == 0
47
+ end
48
+ it "should display the message 'You have removed all unapproved comments.'" do
49
+ delete :destroy_unapproved
50
+ flash[:notice].should == 'You have removed all unapproved comments.'
51
+ end
52
+ it "should redirect to the requesting page" do
53
+ delete :destroy_unapproved
54
+ response.should redirect_to('http://test.host/admin/comments')
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Admin::CommentsController do
4
+ dataset :users_and_pages, :comments
5
+ before(:each) do
6
+ login_as :admin
7
+ end
8
+
9
+ describe "routing" do
10
+ it "should route to unapproved comments by default" do
11
+ params_from(:get, "/admin/comments").should == { :controller => "admin/comments", :action => "index", :status => 'unapproved' }
12
+ end
13
+
14
+ %w(all approved unapproved).each do |status|
15
+ it "should route to the index action for #{status} comments" do
16
+ params_from(:get, "/admin/comments/#{status}").should == { :controller => "admin/comments", :action => "index", :status => status }
17
+ end
18
+ it "should route to the index action for #{status} comments on the page" do
19
+ params_from(:get, "/admin/pages/1/comments/#{status}").should == { :controller => "admin/comments", :action => "index", :page_id => "1", :status => status }
20
+ end
21
+ it "should route to the index action for #{status} comments with the csv format" do
22
+ params_from(:get, "/admin/comments/#{status}.csv").should == { :controller => "admin/comments", :action => "index", :status => status, :format => 'csv' }
23
+ end
24
+ it "should route to the index action for #{status} comments on the page with the csv format" do
25
+ params_from(:get, "/admin/pages/1/comments/#{status}.csv").should == { :controller => "admin/comments", :action => "index", :status => status, :page_id => "1", :format => 'csv' }
26
+ end
27
+ end
28
+
29
+ it "should route to the destroy_unapproved action" do
30
+ params_from(:delete, "/admin/comments/destroy_unapproved").should == { :controller => "admin/comments", :action => "destroy_unapproved" }
31
+ end
32
+
33
+ it "should route to the enable action for the page" do
34
+ params_from(:put, "/admin/pages/1/comments/enable").should == { :controller => "admin/comments", :action => "enable", :page_id => "1" }
35
+ end
36
+
37
+ %w(approve unapprove).each do |action|
38
+ it "should route to the #{action} action" do
39
+ params_from(:put, "/admin/comments/1/#{action}").should == { :controller => "admin/comments", :action => action, :id => "1" }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe SiteController, "Comments form posting to page" do
4
+ dataset :pages
5
+
6
+ before :each do
7
+ Radiant::Config['comments.post_to_page?'] = true
8
+ end
9
+
10
+ def do_post(comment_params={})
11
+ post :show_page, :url => "/", :comment => {
12
+ :author => "Jim Gay",
13
+ :author_email => "test@test.com",
14
+ :content => "That's all I have to say about that."
15
+ }.merge(comment_params)
16
+ end
17
+
18
+ describe "when the comment succeeds in saving" do
19
+ it "should create the comment" do
20
+ lambda { do_post }.should change(Comment, :count).by(1)
21
+ end
22
+
23
+ it "should redirect back to the page, with the comment anchor" do
24
+ do_post
25
+ response.should be_redirect
26
+ response.redirect_url.should =~ /#comment-\d+$/
27
+ end
28
+ end
29
+
30
+ describe "when the comment fails to save" do
31
+ before :each do
32
+ @comment_mock = mock_model(Comment)
33
+ Comment.should_receive(:new).and_return(@comment_mock)
34
+ @comment_mock.stub!(:[]=)
35
+ @comment_mock.stub!(:request=)
36
+ @comment_mock.errors.stub!(:full_messages).and_return([])
37
+ @comment_mock.should_receive(:save!).and_raise(ActiveRecord::RecordInvalid.new(@comment_mock))
38
+ end
39
+
40
+ it "should re-render the page and not cache the result" do
41
+ do_post
42
+ response.should be_success
43
+ response.headers['Cache-Control'].should =~ /private/
44
+ end
45
+
46
+ it "should assign the failed comment to loaded page" do
47
+ do_post
48
+ assigns[:page].last_comment.should == @comment_mock
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ class CommentsDataset < Dataset::Base
2
+ uses :pages
3
+
4
+ def load
5
+ create_record Comment, :first, :page_id => pages(:home).id, :author => 'Jim Gay', :author_email => 'test@spec.com', :content => "That's all I have to say about that."
6
+ end
7
+ end
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe AkismetSpamFilter do
4
+ dataset :comments
5
+
6
+ before :each do
7
+ @akismet = mock("akismet", :valid? => true, :commentCheck => false)
8
+ end
9
+
10
+ it "should always allow comments to save" do
11
+ @comment = comments(:first)
12
+ AkismetSpamFilter.valid?(@comment).should be_true
13
+ end
14
+
15
+ it "should be configured if the api key and blog url are set" do
16
+ Radiant::Config['comments.akismet_key'] = 'foo'
17
+ Radiant::Config['comments.akismet_url'] = 'bar'
18
+ AkismetSpamFilter.should be_configured
19
+ end
20
+
21
+ it "should not be configured if either the public or private key are empty" do
22
+ Radiant::Config['comments.akismet_key'] = ''
23
+ Radiant::Config['comments.akismet_url'] = 'bar'
24
+ AkismetSpamFilter.should_not be_configured
25
+
26
+ Radiant::Config['comments.akismet_key'] = 'foo'
27
+ Radiant::Config['comments.akismet_url'] = ''
28
+ AkismetSpamFilter.should_not be_configured
29
+ end
30
+
31
+
32
+ it "should initialize an Akismet API object" do
33
+ AkismetSpamFilter.akismet.should be_kind_of(Akismet)
34
+ end
35
+
36
+ describe "when approving a comment" do
37
+ before :each do
38
+ @comment = comments(:first)
39
+ AkismetSpamFilter.instance.stub!(:akismet).and_return(@akismet)
40
+ end
41
+
42
+ it "should be approved when the Akismet API is valid and returns false (message is not spam)" do
43
+ AkismetSpamFilter.should be_approved(@comment)
44
+ end
45
+
46
+ it "should not be approved when the API is invalid" do
47
+ @akismet.stub!(:valid?).and_return(false)
48
+ AkismetSpamFilter.should_not be_approved(@comment)
49
+ end
50
+
51
+ it "should not be approved when the API call returns true (message is spam)" do
52
+ @akismet.stub!(:commentCheck).and_return(true)
53
+ AkismetSpamFilter.should_not be_approved(@comment)
54
+ end
55
+
56
+ it "should not be approved when the API is unreachable" do
57
+ @akismet.stub!(:commentCheck).and_raise(TimeoutError)
58
+ AkismetSpamFilter.should_not be_approved(@comment)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,148 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "Comment" do
4
+ dataset :comments
5
+
6
+ before do
7
+ @page = pages(:home)
8
+ Radiant::Config['comments.auto_approve'] = 'true'
9
+ end
10
+
11
+ describe "self.per_page" do
12
+ it "should be 50 when Radiant::Config['comments.per_page'] is not set" do
13
+ Comment.per_page.should == 50
14
+ end
15
+ it "should be 50 when Radiant::Config['comments.per_page'] is 0" do
16
+ Radiant::Config['comments.per_page'] = 0
17
+ Comment.per_page.should == 50
18
+ end
19
+ it "should be the integer value when Radiant::Config['comments.per_page'] is an integer" do
20
+ Radiant::Config['comments.per_page'] = 123
21
+ Comment.per_page.should == 123
22
+ end
23
+ it "should be the absolute value when Radiant::Config['comments.per_page'] is a negative number" do
24
+ Radiant::Config['comments.per_page'] = -99
25
+ Comment.per_page.should == 99
26
+ end
27
+
28
+ end
29
+
30
+ describe "when creating" do
31
+ before do
32
+ @comment = comments(:first)
33
+ @comment.stub!(:using_logic_spam_filter?).and_return(false)
34
+ Radiant::Config['comments.filters_enabled'] = "true"
35
+ end
36
+
37
+ it "should escape html for content_html when a filter is not selected" do
38
+ @comment.content = %{<script type="text/javascript">alert('hello')</script>}
39
+ @comment.save!
40
+ @comment.content_html.should == %{<p>alert(&#39;hello&#39;)</p>}
41
+ end
42
+ it "should sanitize the content" do
43
+ @comment.content = %{*hello* <script type="text/javascript">alert('hello')</script>}
44
+ @comment.save!
45
+ @comment.content_html.should_not include_text('script')
46
+ end
47
+ it "should filter the content for content_html when a filter is selected" do
48
+ @comment.filter_id = 'Textile'
49
+ @comment.content = %{*hello* <script type="text/javascript">alert('hello')</script>}
50
+ @comment.save!
51
+ @comment.content_html.should match(/<strong>hello<\/strong>/)
52
+ end
53
+ it "should escape the content for content_html when a filter is not selected" do
54
+ Radiant::Config['comments.filters_enabled'] = 'true'
55
+ @comment.filter_id = ''
56
+ @comment.content = %{*hello* <script type="text/javascript">alert('hello')</script>}
57
+ @comment.save!
58
+ @comment.content_html.should_not include_text('script')
59
+ end
60
+
61
+ it "should successfully create comment" do
62
+ @comment.valid?.should be_true
63
+ lambda{@comment.save!}.should_not raise_error
64
+ end
65
+
66
+ it "should set content_html with filter when saving" do
67
+ @comment.save
68
+ @comment.content_html.should eql("<p>That&#39;s all I have to say about that.</p>")
69
+ end
70
+
71
+ it "should validate that author is supplied" do
72
+ comment = create_comment(:author => nil)
73
+ comment.valid?.should be_false
74
+ end
75
+
76
+ it "should validate that author_email is supplied" do
77
+ comment = create_comment(:author_email => nil)
78
+ comment.valid?.should be_false
79
+ end
80
+
81
+ it "should validate that content is supplied" do
82
+ comment = create_comment(:content => nil)
83
+ comment.valid?.should be_false
84
+ end
85
+
86
+ it "should add a http:// prefix when author_url does not include a protocol" do
87
+ url = 'www.example.com'
88
+ @comment.author_url = url
89
+ @comment.save!
90
+ @comment.author_url.should == "http://#{url}"
91
+ end
92
+
93
+ it "should not alter author_url with a http:// prefix" do
94
+ url = 'http://www.example.com'
95
+ @comment.author_url = url
96
+ @comment.save!
97
+ @comment.author_url.should == url
98
+ end
99
+
100
+ it "should not alter author_url with a https:// prefix" do
101
+ url = 'https://www.example.com'
102
+ @comment.author_url = url
103
+ @comment.save!
104
+ @comment.author_url.should == url
105
+ end
106
+
107
+ it "should encode special characters in author_url" do
108
+ url = 'http://example.com/~foo/q?a=1&b=2'
109
+ @comment.author_url = url
110
+ @comment.save!
111
+ @comment.author_url.should == CGI.escapeHTML(url)
112
+ end
113
+
114
+ it "should not alter author_url with a HTTP:// prefix" do
115
+ url = 'HTTP://Www.Example.Com'
116
+ @comment.author_url = url
117
+ @comment.save!
118
+ @comment.author_url.should == url
119
+ end
120
+ end
121
+
122
+ def create_comment(opts={})
123
+ Comment.new({ :page => @page, :author => "Test", :author_email => "test@test.com", :author_ip => "10.1.10.1",
124
+ :content => "Test..." }.merge(opts))
125
+ end
126
+
127
+ def page_params(attributes={})
128
+ title = attributes[:title] || unique_page_title
129
+
130
+ attributes = {
131
+ :title => title,
132
+ :breadcrumb => title,
133
+ :slug => title.symbolize.to_s.gsub("_", "-"),
134
+ :class_name => nil,
135
+ :status_id => Status[:published].id,
136
+ :published_at => Time.now.to_s(:db)
137
+ }.update(attributes)
138
+ attributes[:parent_id] = 10
139
+ attributes
140
+ end
141
+
142
+ @@unique_page_title_call_count = 0
143
+ def unique_page_title
144
+ @@unique_page_title_call_count += 1
145
+ "Page #{@@unique_page_title_call_count}"
146
+ end
147
+
148
+ end
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Page do
4
+ dataset :users_and_pages, :comments
5
+
6
+ describe "r:comments:field:spam_answer_tag" do
7
+ it "should render the spam_answer input and the valid_spam_answer hidden input" do
8
+ answer_as_set = 'no spam'
9
+ correct_answer = Digest::MD5.hexdigest(answer_as_set.to_slug)
10
+ pages(:home).should render("<r:comments:field:spam_answer_tag answer='#{answer_as_set}' />").as(%{<input type="text" id="comment_spam_answer" name="comment[spam_answer]" value="" /><input type="hidden" name="comment[valid_spam_answer]" value="#{correct_answer}" />})
11
+ end
12
+ end
13
+ describe "r:if_comments_simple_spam_filter_enabled" do
14
+ it "should render the content when required in Radiant::Config" do
15
+ Radiant::Config['comments.simple_spam_filter_required?'] = true
16
+ tag = %{<r:if_comments_simple_spam_filter_enabled>foo</r:if_comments_simple_spam_filter_enabled>}
17
+ expected = 'foo'
18
+ pages(:home).should render(tag).as(expected)
19
+ end
20
+ it "should not render the content when not required in Radiant::Config" do
21
+ Radiant::Config['comments.simple_spam_filter_required?'] = false
22
+ tag = %{<r:if_comments_simple_spam_filter_enabled>foo</r:if_comments_simple_spam_filter_enabled>}
23
+ expected = ''
24
+ pages(:home).should render(tag).as(expected)
25
+ end
26
+ end
27
+ describe "r:unless_comments_use_simple_spam_filter" do
28
+ it "should not render the content when required in Radiant::Config" do
29
+ Radiant::Config['comments.simple_spam_filter_required?'] = true
30
+ tag = %{<r:unless_comments_simple_spam_filter_enabled>foo</r:unless_comments_simple_spam_filter_enabled>}
31
+ expected = ''
32
+ pages(:home).should render(tag).as(expected)
33
+ end
34
+ it "should render the content when not required in Radiant::Config" do
35
+ Radiant::Config['comments.simple_spam_filter_required?'] = false
36
+ tag = %{<r:unless_comments_simple_spam_filter_enabled>foo</r:unless_comments_simple_spam_filter_enabled>}
37
+ expected = 'foo'
38
+ pages(:home).should render(tag).as(expected)
39
+ end
40
+ end
41
+ describe "<r:comments:form>" do
42
+ before :each do
43
+ @page = pages(:first)
44
+ end
45
+ it "should postback to the comments controller by default" do
46
+ Radiant::Config['comments.post_to_page?'] = false
47
+ @page.should render('<r:comments:form></r:comments:form>').matching(%r[#{@page.url}comments])
48
+ end
49
+
50
+ it "should postback to the page when comments.post_to_page? is set to true" do
51
+ Radiant::Config['comments.post_to_page?'] = true
52
+ @page.should render('<r:comments:form></r:comments:form>').matching(%r[#{@page.url}"])
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,103 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe MollomSpamFilter do
4
+ dataset :comments
5
+
6
+ before :each do
7
+ @mollom_response = mock("response", :ham? => true, :session_id => '00011001')
8
+ @mollom = mock("mollom", :key_ok? => true, :check_content => @mollom_response, :server_list= => '', :server_list => [])
9
+ MollomSpamFilter.instance.instance_variable_set(:@mollom, nil)
10
+ end
11
+
12
+ it "should always allow comments to save" do
13
+ @comment = comments(:first)
14
+ MollomSpamFilter.valid?(@comment).should be_true
15
+ end
16
+
17
+ it "should be configured if the public and private key are set" do
18
+ Radiant::Config['comments.mollom_publickey'] = 'foo'
19
+ Radiant::Config['comments.mollom_privatekey'] = 'bar'
20
+ MollomSpamFilter.should be_configured
21
+ end
22
+
23
+ it "should not be configured if either the public or private key are empty" do
24
+ Radiant::Config['comments.mollom_publickey'] = ''
25
+ Radiant::Config['comments.mollom_privatekey'] = 'bar'
26
+ MollomSpamFilter.should_not be_configured
27
+
28
+ Radiant::Config['comments.mollom_publickey'] = 'foo'
29
+ Radiant::Config['comments.mollom_privatekey'] = ''
30
+ MollomSpamFilter.should_not be_configured
31
+ end
32
+
33
+
34
+ it "should initialize a Mollom API object" do
35
+ MollomSpamFilter.mollom.should be_kind_of(Mollom)
36
+ end
37
+
38
+ it "should load the server list from the cache when possible" do
39
+ Rails.cache.write('MOLLOM_SERVER_CACHE', [{:proto=>"http", :host=>"88.151.243.81"}].to_yaml)
40
+ MollomSpamFilter.mollom.server_list.should == [{:proto=>"http", :host=>"88.151.243.81"}]
41
+ end
42
+
43
+ describe "when approving a comment" do
44
+ before :each do
45
+ @comment = comments(:first)
46
+ MollomSpamFilter.instance.stub!(:mollom).and_return(@mollom)
47
+ end
48
+
49
+ it "should not be approved when the Mollom key is invalid" do
50
+ @mollom.stub!(:key_ok?).and_return(false)
51
+ MollomSpamFilter.should_not be_approved(@comment)
52
+ end
53
+
54
+ it "should not be approved when the response is not ham" do
55
+ @mollom_response.stub!(:ham?).and_return(false)
56
+ MollomSpamFilter.should_not be_approved(@comment)
57
+ end
58
+
59
+ it "should not be approved when the API is unreachable" do
60
+ @mollom.stub!(:key_ok?).and_raise(Mollom::Error)
61
+ MollomSpamFilter.should_not be_approved(@comment)
62
+ end
63
+
64
+ it "should be approved when the key is valid and response is ham" do
65
+ MollomSpamFilter.should be_approved(@comment)
66
+ end
67
+
68
+ it "should cache the Mollom server list after a successful response" do
69
+ Rails.cache.should_receive(:write).with('MOLLOM_SERVER_CACHE', anything())
70
+ MollomSpamFilter.should be_approved(@comment)
71
+ end
72
+ end
73
+
74
+ describe "when submitting a comment as spam" do
75
+ before :each do
76
+ @comment = comments(:first)
77
+ @comment.mollom_id = '1010101010001'
78
+ MollomSpamFilter.instance.stub!(:mollom).and_return(@mollom)
79
+ end
80
+
81
+ it "should send the feedback to mollom" do
82
+ @mollom.should_receive(:send_feedback).with(hash_including(:feedback => 'spam')).and_return(true)
83
+ MollomSpamFilter.spam!(@comment)
84
+ end
85
+
86
+ it "should not submit the spam if the comment has no Mollom response id" do
87
+ @comment.mollom_id = ''
88
+ @mollom.should_not_receive(:send_feedback)
89
+ MollomSpamFilter.spam!(@comment)
90
+ end
91
+
92
+ it "should not submit the spam if the Mollom key is invalid" do
93
+ @mollom.stub(:key_ok?).and_return(false)
94
+ @mollom.should_not_receive(:send_feedback)
95
+ MollomSpamFilter.spam!(@comment)
96
+ end
97
+
98
+ it "should raise a antispam error if Mollom raised an error" do
99
+ @mollom.should_receive(:send_feedback).and_raise(Mollom::Error)
100
+ lambda { MollomSpamFilter.spam!(@comment) }.should raise_error(Comment::AntispamWarning)
101
+ end
102
+ end
103
+ end