adva_comments 0.1.0

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 (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