adva_comments 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +2 -0
  7. data/adva_comments.gemspec +20 -0
  8. data/app/assets/javascripts/adva_comments/jquery.comments.js +41 -0
  9. data/app/assets/stylesheets/adva_comments/admin/comments.scss +34 -0
  10. data/app/assets/stylesheets/adva_comments/comments.scss +50 -0
  11. data/app/controllers/admin/comments_controller.rb +86 -0
  12. data/app/controllers/comments_controller.rb +109 -0
  13. data/app/helpers/admin/comments_helper.rb +32 -0
  14. data/app/helpers/comments_helper.rb +71 -0
  15. data/app/mailers/comment_mailer.rb +8 -0
  16. data/app/models/comment.rb +94 -0
  17. data/app/views/admin/articles/_comments_settings.html.erb +1 -0
  18. data/app/views/admin/comments/_form.html.erb +12 -0
  19. data/app/views/admin/comments/edit.html.erb +9 -0
  20. data/app/views/admin/comments/index.html.erb +43 -0
  21. data/app/views/admin/sections/_comments_settings.html.erb +7 -0
  22. data/app/views/admin/sites/_comments_settings.html.erb +7 -0
  23. data/app/views/comment_mailer/comment_notification.html.erb +12 -0
  24. data/app/views/comments/_comment.html.erb +13 -0
  25. data/app/views/comments/_form.html.erb +44 -0
  26. data/app/views/comments/_list.html.erb +8 -0
  27. data/app/views/comments/comments.atom.builder +16 -0
  28. data/app/views/comments/preview.html.erb +3 -0
  29. data/app/views/comments/show.html.erb +12 -0
  30. data/config/initializers/article.rb +13 -0
  31. data/config/initializers/content.rb +17 -0
  32. data/config/initializers/controllers.rb +25 -0
  33. data/config/initializers/menus.rb +24 -0
  34. data/config/initializers/section.rb +15 -0
  35. data/config/initializers/site.rb +11 -0
  36. data/config/routes.rb +9 -0
  37. data/db/migrate/20080401000007_create_comments_table.rb +22 -0
  38. data/db/migrate/20080721141112_add_comment_board_id.rb +9 -0
  39. data/lib/action_controller/acts_as_commentable.rb +43 -0
  40. data/lib/active_record/has_many_comments.rb +49 -0
  41. data/lib/adva_comments/version.rb +3 -0
  42. data/lib/adva_comments.rb +19 -0
  43. data/lib/format.rb +3 -0
  44. data/test/contexts.rb +29 -0
  45. data/test/functional/admin/comments_controller_test.rb +200 -0
  46. data/test/functional/comments_controller_test.rb +133 -0
  47. data/test/functional/comments_routes_test.rb +17 -0
  48. data/test/test_helper.rb +4 -0
  49. data/test/unit/helpers/admin/comments_helper_test.rb +23 -0
  50. data/test/unit/helpers/comments_helper_test.rb +147 -0
  51. data/test/unit/models/comment_test.rb +150 -0
  52. data/test/unit/models/commentable_test.rb +30 -0
  53. data/test/unit/observers/activities_comment_observer_test.rb +45 -0
  54. metadata +132 -0
@@ -0,0 +1,200 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../test_helper")
2
+
3
+ class AdminCommentsControllerTest < ActionController::TestCase
4
+ include ContentHelper, ResourceHelper, BlogHelper
5
+ tests Admin::CommentsController
6
+ attr_reader :controller
7
+
8
+ with_common [:a_page, :a_blog], :a_published_article, [:an_approved_comment, :an_unapproved_comment], :is_superuser
9
+
10
+ def default_params
11
+ { :site_id => @site.id, :return_to => 'return/to/here' }
12
+ end
13
+
14
+ view :comment do
15
+ has_text @comment.body
16
+
17
+ comment_path = show_path(@article, :anchor => "comment_#{@comment.id}", :namespace => nil)
18
+ has_tag 'a[href=?]', comment_path, 'View' # displays a link to the comment on the frontend view
19
+ has_tag 'a', 'Edit' # displays a link to edit the comment
20
+ has_tag 'a', 'Delete' # displays a link to delete the comment
21
+ has_tag 'a', 'Approve' if within :unapproved_comment # displays a link to approve comment
22
+ has_tag 'a', 'Unapprove' if within :approved_comment # displays a link to unapprove comment
23
+ # has_tag 'a', 'Reply' if with? :approved_comment # displays a link to reply to the comment
24
+ end
25
+
26
+ test "is an Admin::BaseController" do
27
+ @controller.should be_kind_of(Admin::BaseController)
28
+ end
29
+
30
+ # FIXME in theory the admin comments controller should also work with scoping
31
+ # to a content or a section (currently only tested scoping to a site)
32
+
33
+ describe "routing" do
34
+ with_options :path_prefix => '/admin/sites/1/', :site_id => '1' do |r|
35
+ r.it_maps :get, 'comments', :action => 'index'
36
+ # r.it_maps :get, 'comments/new', :action => 'new'
37
+ # r.it_maps :post, 'comments', :action => 'create'
38
+ r.it_maps :get, 'comments/1', :action => 'show', :id => '1'
39
+ r.it_maps :get, 'comments/1/edit', :action => 'edit', :id => '1'
40
+ r.it_maps :put, 'comments/1', :action => 'update', :id => '1'
41
+ r.it_maps :delete, 'comments/1', :action => 'destroy', :id => '1'
42
+ end
43
+ end
44
+
45
+ describe "GET to :index" do
46
+ action { get :index, default_params }
47
+ it_guards_permissions :show, :comment
48
+
49
+ with :access_granted do
50
+ it_assigns :comments
51
+ it_renders :template, :index do
52
+ # has_tag 'select[id=filter_list]' # displays a filter for filtering the comments list
53
+ has_tag 'ul[id=comments_list]' # displays a list of comments
54
+ shows :comment
55
+ end
56
+ end
57
+ end
58
+
59
+ # describe "GET to :show" do
60
+ # action { get :show, default_params.merge(:id => @comment.id) }
61
+ # it_guards_permissions :show, :comment
62
+ #
63
+ # with :access_granted do
64
+ # it_assigns :comment
65
+ # it_renders :template, :show do
66
+ # has_tag 'h3', 'Comment'
67
+ # has_text @comment.body
68
+ # shows :comment
69
+ # # FIXME shows a reply form
70
+ # end
71
+ # end
72
+ # end
73
+
74
+ # FIXME ... implement these
75
+ #
76
+ # describe "GET to :new" do
77
+ # action { get :new, default_params }
78
+ # it_guards_permissions :create, :comment
79
+ # with :access_granted do
80
+ # it_assigns :comment
81
+ # it_renders :template, :new
82
+ # end
83
+ # end
84
+ #
85
+ # describe "POST to :create" do
86
+ # action { post :create, @params }
87
+ # it_guards_permissions :create, :comment
88
+ #
89
+ # with :valid_comment_params do
90
+ # it_changes '@site.reload.comments.count' => 1
91
+ # it_redirects_to admin_comment_url(@site, assigns(:comment))
92
+ # it_assigns_flash_cookie :notice => :not_nil
93
+ # end
94
+ #
95
+ # with :invalid_comment_params do
96
+ # it_does_not_change '@site.reload.comments.count'
97
+ # it_renders :template, :new
98
+ # it_assigns_flash_cookie :error => :not_nil
99
+ # end
100
+ # end
101
+
102
+ describe "GET to :edit" do
103
+ action { get :edit, default_params.merge(:id => @comment.id) }
104
+ it_guards_permissions :update, :comment
105
+
106
+ with :access_granted do
107
+ it_assigns :comment
108
+ it_renders :template, :edit do
109
+ # FIXME assert form rendered
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "PUT to :update" do
115
+ action { put :update, default_params.merge(:id => @comment.id).merge(@params || {}) }
116
+ it_guards_permissions :update, :comment
117
+
118
+ with :access_granted do
119
+ it_assigns :comment
120
+
121
+ with "valid comment params" do
122
+ before { @params = { :comment => { :body => 'updated comment body' } } }
123
+ it_updates :comment
124
+ it_redirects_to 'return/to/here'
125
+ it_assigns_flash_cookie :notice => :not_nil
126
+ it_triggers_event :comment_updated
127
+ end
128
+
129
+ with "invalid comment params" do
130
+ before { @params = { :comment => { :body => '' } } }
131
+ it_does_not_update :comment
132
+ it_assigns_flash_cookie :error => :not_nil
133
+ it_does_not_trigger_any_event
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "DELETE to :destroy" do
139
+ action { delete :destroy, default_params.merge(:id => @comment.id) }
140
+ it_guards_permissions :destroy, :comment
141
+
142
+ with :access_granted do
143
+ it_assigns :comment
144
+ it_destroys :comment
145
+ it_redirects_to 'return/to/here'
146
+ it_assigns_flash_cookie :notice => :not_nil
147
+ it_triggers_event :comment_deleted
148
+ end
149
+ end
150
+
151
+ # def filter_conditions
152
+ # @controller.send(:filter_options)[:conditions]
153
+ # end
154
+ #
155
+ # describe "filter_options" do
156
+ # before { @controller.instance_variable_set :@section, @section }
157
+ #
158
+ # it "sets :order, :per_page and :page parameters defaults" do
159
+ # @controller.params = { :filter => 'all' }
160
+ # @controller.send(:filter_options).should == { :per_page => nil, :page => 1, :order => 'created_at DESC' }
161
+ # assert_nothing_raised { @controller.send :set_comments }
162
+ # end
163
+ #
164
+ # it "fetches approved comments when :filter == state and :state == approved" do
165
+ # @controller.params = { :filter => 'state', :state => 'approved' }
166
+ # filter_conditions.should == "approved = '1'"
167
+ # assert_nothing_raised { @controller.send :set_comments }
168
+ # end
169
+ #
170
+ # it "fetches unapproved comments when :filter == state and :state == unapproved" do
171
+ # @controller.params = { :filter => 'state', :state => 'unapproved' }
172
+ # filter_conditions.should == "approved = '0'"
173
+ # assert_nothing_raised { @controller.send :set_comments }
174
+ # end
175
+ #
176
+ # it "fetches comments by matching the body when :filter == body" do
177
+ # @controller.params = { :filter => 'body', :query => 'foo' }
178
+ # filter_conditions.should == "LOWER(body) LIKE '%foo%'"
179
+ # assert_nothing_raised { @controller.send :set_comments }
180
+ # end
181
+ #
182
+ # it "fetches comments by matching the author name when :filter == author_name" do
183
+ # @controller.params = { :filter => 'author_name', :query => 'foo' }
184
+ # filter_conditions.should == "LOWER(author_name) LIKE '%foo%'"
185
+ # assert_nothing_raised { @controller.send :set_comments }
186
+ # end
187
+ #
188
+ # it "fetches comments by matching the author email when :filter == author_email" do
189
+ # @controller.params = { :filter => 'author_email', :query => 'foo@bar.baz' }
190
+ # filter_conditions.should == "LOWER(author_email) LIKE '%foo@bar.baz%'"
191
+ # assert_nothing_raised { @controller.send :set_comments }
192
+ # end
193
+ #
194
+ # it "fetches comments by matching the author homepage when :filter == author_homepage" do
195
+ # @controller.params = { :filter => 'author_homepage', :query => 'homepage.com' }
196
+ # filter_conditions.should == "LOWER(author_homepage) LIKE '%homepage.com%'"
197
+ # assert_nothing_raised { @controller.send :set_comments }
198
+ # end
199
+ # end
200
+ end
@@ -0,0 +1,133 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+
3
+ # FIXME should also test comments on section articles and wikipages
4
+
5
+ class CommentsControllerTest < ActionController::TestCase
6
+ with_common :a_blog, :a_published_article, :an_approved_comment, :is_superuser
7
+
8
+ def default_params
9
+ { :comment => { :commentable_type => 'Article', :commentable_id => @article.id } }
10
+ end
11
+
12
+ test "is a BaseController" do
13
+ @controller.should be_kind_of(BaseController)
14
+ end
15
+
16
+ describe "routing" do
17
+ it_maps :get, 'comments', :action => 'index'
18
+ it_maps :get, 'comments/new', :action => 'new'
19
+ it_maps :post, 'comments/preview', :action => 'preview'
20
+ it_maps :post, 'comments', :action => 'create'
21
+ it_maps :get, 'comments/1', :action => 'show', :id => '1'
22
+ it_maps :get, 'comments/1/edit', :action => 'edit', :id => '1'
23
+ it_maps :put, 'comments/1', :action => 'update', :id => '1'
24
+ it_maps :delete, 'comments/1', :action => 'destroy', :id => '1'
25
+ end
26
+
27
+ describe "GET to :show" do
28
+ action { get :show, :id => @comment.id }
29
+ # it_guards_permissions :show, :comment do # FIXME
30
+ it_assigns :section, :comment, :commentable
31
+ it_renders :template, :show do
32
+ has_text @comment.body
33
+ end
34
+
35
+ # FIXME displays a message when the comment is not approved yet: /under review/
36
+ # end
37
+ end
38
+
39
+ describe "POST to preview" do
40
+ action { post :preview, default_params.merge(@params || {}) }
41
+ it_guards_permissions :create, :comment do
42
+ with :valid_comment_params do
43
+ it_assigns :comment => :not_nil
44
+ it_renders :template, :preview do
45
+ has_text 'the comment body'
46
+ end
47
+ end
48
+
49
+ # FIXME
50
+ # with "invalid comment params" do
51
+ # end
52
+ end
53
+ end
54
+
55
+ describe "POST to :create" do
56
+ action do
57
+ Comment.with_observers :comment_sweeper do
58
+ post :create, default_params.merge(@params || {})
59
+ end
60
+ end
61
+
62
+ it_guards_permissions :create, :comment do
63
+ with :valid_comment_params do
64
+ it_assigns :commentable => :article, :comment => :not_nil
65
+ it_saves :comment
66
+ it_assigns_flash_cookie :notice => :not_nil
67
+ it_triggers_event :comment_created
68
+ it_sweeps_page_cache :by_reference => :article
69
+ it_redirects_to { comment_url(assigns(:comment)) }
70
+
71
+ # FIXME
72
+ # it "checks the comment's spaminess" do
73
+ # expect do
74
+ # url = "http://test.host/sections/1/articles/an-article"
75
+ # mock(@comment).check_approval(:permalink => url, :authenticated => false)
76
+ # mock(Article).find { @article }
77
+ # mock(@article).comments.build { @comment }
78
+ # end
79
+ # end
80
+ end
81
+
82
+ with :invalid_comment_params do
83
+ it_renders :template, :show
84
+ it_assigns_flash_cookie :error => :not_nil
85
+ it_does_not_trigger_any_event
86
+ end
87
+ end
88
+ end
89
+
90
+ describe "PUT to :update" do
91
+ action do
92
+ Comment.with_observers :comment_sweeper do
93
+ post :update, (@params || {}).merge(:id => @comment.id)
94
+ end
95
+ end
96
+
97
+ it_guards_permissions :update, :comment do
98
+ with "valid comment params" do
99
+ before { @params = { :comment => { :body => 'the updated comment body' } } }
100
+
101
+ it_updates :comment
102
+ it_redirects_to { comment_url(assigns(:comment)) }
103
+ it_assigns_flash_cookie :notice => :not_nil
104
+ it_triggers_event :comment_updated
105
+ it_sweeps_page_cache :by_reference => :article
106
+ end
107
+
108
+ with :invalid_comment_params do
109
+ it_does_not_update :comment
110
+ it_renders_template :show
111
+ it_assigns_flash_cookie :error => :not_nil
112
+ it_does_not_trigger_any_event
113
+ end
114
+ end
115
+ end
116
+
117
+ describe "DELETE to :destroy" do
118
+ action do
119
+ Comment.with_observers :comment_sweeper do
120
+ delete :destroy,:id => @comment.id
121
+ end
122
+ end
123
+
124
+ it_guards_permissions :destroy, :comment do
125
+ it_assigns :comment
126
+ it_destroys :comment
127
+ it_triggers_event :comment_deleted
128
+ it_redirects_to { '/' }
129
+ it_assigns_flash_cookie :notice => :not_nil
130
+ it_sweeps_page_cache :by_reference => :article
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+
3
+ class CommentsRoutesTest < ActionController::TestCase
4
+ tests CommentsController
5
+
6
+ paths = %W( /comments
7
+ /comments/1 )
8
+
9
+ paths.each do |path|
10
+ test "regenerates the original path from the recognized params for #{path}" do
11
+ without_routing_filters do
12
+ params = ActionController::Routing::Routes.recognize_path(path, :method => :get)
13
+ assert_equal path, @controller.url_for(params.merge(:only_path => true))
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../adva_cms/test/test_helper')
2
+
3
+
4
+
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ class AdminCommentsHelperTest < ActionView::TestCase
4
+ include Admin::CommentsHelper
5
+
6
+ test "translates comment_expiration_options" do
7
+ expected = [ ['Are not allowed', -1],
8
+ ['Never expire', 0],
9
+ ['Expire 24 hours after publishing', 1],
10
+ ['Expire 1 week after publishing', 7],
11
+ ['Expire 1 month after publishing', 30],
12
+ ['Expire 3 months after publishing', 90] ]
13
+ comment_expiration_options.should == expected
14
+ end
15
+
16
+ test "translates comments_filter_options" do
17
+ lambda { comments_filter_options }.should_not raise_error
18
+ end
19
+
20
+ test "translates comments_state_options" do
21
+ lambda { comments_state_options }.should_not raise_error
22
+ end
23
+ end
@@ -0,0 +1,147 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ class CommentsHelperTest < ActionView::TestCase
4
+ include CommentsHelper
5
+
6
+ attr_accessor :request
7
+
8
+ def setup
9
+ super
10
+ @section = Section.first
11
+ @article = @section.articles.first
12
+ @site = @section.site
13
+
14
+ stub(self).protect_against_forgery?.returns false
15
+
16
+ TestController.send :include, CommentsHelper
17
+ @controller = TestController.new
18
+ @request = ActionController::TestRequest.new
19
+ end
20
+
21
+ test '#comments_feed_title joins the titles of site, section and commentable' do
22
+ comments_feed_title(@site, @section, @article).should ==
23
+ "Comments: #{@site.title} &raquo; #{@section.title} &raquo; #{@article.title}"
24
+ end
25
+
26
+ # test '#link_to_remote_comment_preview returns a rote link to preview_comments_path' do
27
+ # mock(self).preview_comments_path.returns '/path/to/comments/preview'
28
+ # link_to_remote_comment_preview.should =~ /Ajax.Updater/
29
+ # end
30
+
31
+ # comment_form_hidden_fields
32
+
33
+ test '#comment_form_hidden_fields includes a hidden return_to field' do
34
+ result = comment_form_hidden_fields(@article)
35
+ result.should have_tag('input[type=?][name=?]', 'hidden', 'return_to')
36
+ end
37
+
38
+ test 'including comment[commentable_type]' do
39
+ result = comment_form_hidden_fields(@article)
40
+ result.should have_tag('input[type=?][name=?]', 'hidden', 'comment[commentable_type]')
41
+ end
42
+
43
+ test 'including comment[commentable_id]' do
44
+ result = comment_form_hidden_fields(@article)
45
+ result.should have_tag('input[type=?][name=?]', 'hidden', 'comment[commentable_id]')
46
+ end
47
+
48
+ test "#admin_comment_path with no :section_id param given and with no :content_id param given
49
+ it returns the admin_site_comment_path with no further params" do
50
+ @controller.params = { :site_id => 1 }
51
+ @controller.admin_comments_path(@site).should_not have_url_params
52
+ end
53
+
54
+ test "#admin_comment_path with no :section_id param given and with a :content_id param given
55
+ it returns the admin_site_comment_path with the :content_id param" do
56
+ @controller.params = { :site_id => 1, :content_id => 1 }
57
+ @controller.admin_comments_path(@site).should have_url_params(:content_id)
58
+ end
59
+
60
+ test "#admin_comment_path with a :section_id param given and with no :content_id param given
61
+ it returns the admin_site_comment_path with the :section_id param" do
62
+ @controller.params = { :site_id => 1, :section_id => 1 }
63
+ @controller.admin_comments_path(@site).should have_url_params(:section_id)
64
+ end
65
+
66
+ test "#admin_comment_path with a :section_id param given and with a :content_id param given
67
+ it returns the admin_site_comment_path with the :content_id param" do
68
+ @controller.params = { :site_id => 1, :section_id => 1, :content_id => 1 }
69
+ @controller.admin_comments_path(@site).should have_url_params(:content_id)
70
+ end
71
+ end
72
+
73
+ class LinkToCommentsHelperTest < ActionView::TestCase
74
+ include ContentHelper, ResourceHelper
75
+ tests CommentsHelper
76
+
77
+ def setup
78
+ super
79
+ @section = Section.first
80
+ @article = @section.articles.find_by_title 'a page article'
81
+ @category = @section.categories.first
82
+ @tag = Tag.new :name => 'foo'
83
+
84
+ stub(self).current_controller_namespace.returns(nil) # yuck
85
+ @article_path = show_path(@article)
86
+ end
87
+
88
+ # link_to_content_comments_count
89
+
90
+ test "#link_to_content_comments_count returns a link_to_content_comments" do
91
+ link_to_content_comments_count(@article).should have_tag('a[href=?]', "#{@article_path}#comments")
92
+ end
93
+
94
+ test "#link_to_content_comments_count given the option :total is set
95
+ it returns a link_to_content_comments with the approved and total comments counts as a link text" do
96
+ link_to_content_comments_count(@article, :total => true).should =~ /\d{2} \(\d{2}\)/
97
+ end
98
+
99
+ test "#link_to_content_comments_count given the option :total is not set
100
+ it returns a link_to_content_comments with the total comments count as a link text" do
101
+ link_to_content_comments_count(@article).should =~ /\d{2}/
102
+ end
103
+
104
+ test "#link_to_content_comments_count given the content has no comments
105
+ it returns the option :alt as plain text" do
106
+ stub(@article).approved_comments_count.returns 0
107
+ link_to_content_comments_count(@article, :alt => 'no comments').should == 'no comments'
108
+ end
109
+
110
+ test "#link_to_content_comments_count given the content has no comments and no option :alt was passed
111
+ it returns 'none' as plain text" do
112
+ stub(@article).approved_comments_count.returns 0
113
+ link_to_content_comments_count(@article).should == 'none'
114
+ end
115
+
116
+ # link_to_content_comments
117
+
118
+ test "#link_to_content_comments given a content it returns a link to show_path" do
119
+ link_to_content_comments(@article).should have_tag('a[href=?]', "#{@article_path}#comments", '1 Comment')
120
+ end
121
+
122
+ test "#link_to_content_comments given a content and a comment it returns a link to show_path + comment anchor" do
123
+ comment = @article.comments.first
124
+ anchor = dom_id(comment)
125
+ link_to_content_comments(@article, comment).should == %(<a href="#{@article_path}##{anchor}">1 Comment</a>)
126
+ end
127
+
128
+ test "#link_to_content_comments given the first arg is a String it uses the String as link text" do
129
+ path = show_path(@article)
130
+ link_to_content_comments('link text', @article).should == %(<a href="#{path}#comments">link text</a>)
131
+ end
132
+
133
+ test "#link_to_content_comments given the content has no approved comments and the content does not accept comments
134
+ it returns nil" do
135
+ mock(@article).approved_comments_count.returns 0
136
+ mock(@article).accept_comments?.returns false
137
+ link_to_content_comments(@article).should be_nil
138
+ end
139
+
140
+ # link_to_content_comment
141
+
142
+ test "#link_to_content_comment inserts the comment's commentable to the args and calls link_to_content_comments" do
143
+ comment = @article.comments.first
144
+ anchor = dom_id(comment)
145
+ link_to_content_comment(comment).should == %(<a href="#{@article_path}##{anchor}">1 Comment</a>)
146
+ end
147
+ end
@@ -0,0 +1,150 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ class CommentTest < ActiveSupport::TestCase
4
+ def setup
5
+ super
6
+ @section = Section.first
7
+ @article = @section.articles.first
8
+ @comment = @article.comments.first
9
+ end
10
+
11
+ test 'acts as a role context for the author role' do
12
+ Comment.should act_as_role_context(:roles => :author)
13
+ end
14
+
15
+ test 'sanitizes the body_html attribute' do
16
+ Comment.should filter_attributes(:sanitize => :body_html)
17
+ end
18
+
19
+ test "filters the body column" do
20
+ @comment.should filter_column(:body)
21
+ end
22
+
23
+ # ASSOCIATIONS
24
+
25
+ test "belongs to a site" do
26
+ @comment.should belong_to(:site)
27
+ end
28
+
29
+ test "belongs to a section" do
30
+ @comment.should belong_to(:section)
31
+ end
32
+
33
+ test "belongs to a commentable" do
34
+ @comment.should belong_to(:commentable)
35
+ end
36
+
37
+ # VALIDATIONS
38
+
39
+ test "validates presence of author (through belongs_to_author)" do
40
+ @comment.should validate_presence_of(:author)
41
+ end
42
+
43
+ test "validates presence of body" do
44
+ @comment.should validate_presence_of(:body)
45
+ end
46
+
47
+ test "validates presence of commentable" do
48
+ @comment.should validate_presence_of(:commentable)
49
+ end
50
+
51
+ # CALLBACKS
52
+
53
+ test 'sets owners (site + section) before validation' do
54
+ Comment.before_validation.should include(:set_owners)
55
+ end
56
+
57
+ test 'authorizes commenting before create' do
58
+ Comment.before_create.should include(:authorize_commenting)
59
+ end
60
+
61
+ # INSTANCE METHODS
62
+
63
+ test '#owner returns the commentable' do
64
+ @comment.owner.should == @article
65
+ end
66
+
67
+ test '#filter returns the comment_filter attribute of the commentable' do
68
+ mock(@comment.commentable.target).comment_filter.returns :filter
69
+ @comment.filter.should == :filter
70
+ end
71
+
72
+ # approved?
73
+
74
+ test '#approved? returns true if the approved attribute is not 0' do
75
+ @comment.approved = 1
76
+ @comment.should be_approved
77
+ end
78
+
79
+ test '#approved? returns true if the approved attribute is 0' do
80
+ @comment.approved = 0
81
+ @comment.should_not be_approved
82
+ end
83
+
84
+ # state_changes
85
+
86
+ test "#state_changes returns :updated, :approved when the comment was just approved" do
87
+ @comment.approved = 0
88
+ @comment.clear_changes!
89
+ @comment.approved = 1
90
+ @comment.state_changes.should == [:updated, :approved]
91
+ end
92
+
93
+ test "#state_changes returns :updated, :unapproved when the comment was just unapproved" do
94
+ @comment.approved = 1
95
+ @comment.clear_changes!
96
+ @comment.approved = 0
97
+ @comment.state_changes.should == [:updated, :unapproved]
98
+ end
99
+
100
+ # authorize_commenting
101
+
102
+ test '#authorize_commenting checks if the commentable accepts comments' do
103
+ mock(@comment.commentable.target).accept_comments?.returns(true)
104
+ @comment.send(:authorize_commenting)
105
+ end
106
+
107
+ test '#authorize_commenting raises CommentNotAllowed if the commentable does not accept comments' do
108
+ mock(@comment.commentable.target).accept_comments?.returns(false)
109
+ lambda { @comment.send(:authorize_commenting) }.should raise_error
110
+ end
111
+
112
+ # set_owners
113
+
114
+ test '#set_owners sets site and section from the commentable' do
115
+ @comment.site, @comment.section = nil, nil
116
+ @comment.send(:set_owners)
117
+ @comment.site.should == @comment.commentable.site
118
+ @comment.section.should == @comment.commentable.section
119
+ end
120
+
121
+ # author_link
122
+
123
+ test "#author_link returns a link when author_url is present" do
124
+ stub(@comment).author_homepage.returns 'http://somewhere.com'
125
+ @comment.author_link.should == %(<a href="http://somewhere.com">#{@comment.author.name}</a>)
126
+ end
127
+
128
+ test "#author_link returns author_name when author_url is not present" do
129
+ stub(@comment).author_homepage.returns nil
130
+ @comment.author_link.should == @comment.author.name
131
+ end
132
+
133
+ # comment creation
134
+
135
+ test "raises Comment::CommentNotAllowed when commentable.accept_comments? returns false" do
136
+ mock(@article).accept_comments?.returns(false)
137
+ comment = Comment.new(:body => 'body', :author => User.first, :commentable => @article)
138
+ lambda { comment.save! }.should raise_error(Comment::CommentNotAllowed)
139
+ end
140
+
141
+ # filtering
142
+
143
+ test "it does not allow html in the comment body" do
144
+ @article.site.comment_filter = 'textile_filter'
145
+ html = 'p{position:absolute; top:50px; left:10px; width:150px; height:150px}. secure html'
146
+ @comment = Comment.new(:body => html, :commentable => @article)
147
+ @comment.save(false)
148
+ @comment.body_html.should == %(<p>secure html</p>)
149
+ end
150
+ end