radiant-comments-extension 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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