]> git.openstreetmap.org Git - rails.git/blob - test/controllers/api/changeset_comments_controller_test.rb
Add changeset comment search api with filtering by author and time
[rails.git] / test / controllers / api / changeset_comments_controller_test.rb
1 require "test_helper"
2
3 module Api
4   class ChangesetCommentsControllerTest < ActionDispatch::IntegrationTest
5     ##
6     # test all routes which lead to this controller
7     def test_routes
8       assert_routing(
9         { :path => "/api/0.6/changeset_comments", :method => :get },
10         { :controller => "api/changeset_comments", :action => "index" }
11       )
12       assert_routing(
13         { :path => "/api/0.6/changeset/1/comment", :method => :post },
14         { :controller => "api/changeset_comments", :action => "create", :id => "1" }
15       )
16       assert_routing(
17         { :path => "/api/0.6/changeset/1/comment.json", :method => :post },
18         { :controller => "api/changeset_comments", :action => "create", :id => "1", :format => "json" }
19       )
20       assert_routing(
21         { :path => "/api/0.6/changeset/comment/1/hide", :method => :post },
22         { :controller => "api/changeset_comments", :action => "destroy", :id => "1" }
23       )
24       assert_routing(
25         { :path => "/api/0.6/changeset/comment/1/hide.json", :method => :post },
26         { :controller => "api/changeset_comments", :action => "destroy", :id => "1", :format => "json" }
27       )
28       assert_routing(
29         { :path => "/api/0.6/changeset/comment/1/unhide", :method => :post },
30         { :controller => "api/changeset_comments", :action => "restore", :id => "1" }
31       )
32       assert_routing(
33         { :path => "/api/0.6/changeset/comment/1/unhide.json", :method => :post },
34         { :controller => "api/changeset_comments", :action => "restore", :id => "1", :format => "json" }
35       )
36     end
37
38     def test_index
39       user1 = create(:user)
40       user2 = create(:user)
41       changeset1 = create(:changeset, :closed, :user => user2)
42       comment11 = create(:changeset_comment, :changeset => changeset1, :author => user1, :created_at => "2023-01-01", :body => "changeset 1 question")
43       comment12 = create(:changeset_comment, :changeset => changeset1, :author => user2, :created_at => "2023-02-01", :body => "changeset 1 answer")
44       changeset2 = create(:changeset, :closed, :user => user1)
45       comment21 = create(:changeset_comment, :changeset => changeset2, :author => user1, :created_at => "2023-03-01", :body => "changeset 2 note")
46       comment22 = create(:changeset_comment, :changeset => changeset2, :author => user1, :created_at => "2023-04-01", :body => "changeset 2 extra note")
47       comment23 = create(:changeset_comment, :changeset => changeset2, :author => user2, :created_at => "2023-05-01", :body => "changeset 2 review")
48
49       get api_changeset_comments_path
50       assert_response :success
51       assert_comments_in_order [comment23, comment22, comment21, comment12, comment11]
52
53       get api_changeset_comments_path(:limit => 3)
54       assert_response :success
55       assert_comments_in_order [comment23, comment22, comment21]
56
57       get api_changeset_comments_path(:from => "2023-03-15T00:00:00Z")
58       assert_response :success
59       assert_comments_in_order [comment23, comment22]
60
61       get api_changeset_comments_path(:from => "2023-01-15T00:00:00Z", :to => "2023-04-15T00:00:00Z")
62       assert_response :success
63       assert_comments_in_order [comment22, comment21, comment12]
64
65       get api_changeset_comments_path(:user => user1.id)
66       assert_response :success
67       assert_comments_in_order [comment22, comment21, comment11]
68     end
69
70     def test_create_by_unauthorized
71       assert_no_difference "ChangesetComment.count" do
72         post changeset_comment_path(create(:changeset, :closed), :text => "This is a comment")
73         assert_response :unauthorized
74       end
75     end
76
77     def test_create_on_missing_changeset
78       assert_no_difference "ChangesetComment.count" do
79         post changeset_comment_path(999111, :text => "This is a comment"), :headers => bearer_authorization_header
80         assert_response :not_found
81       end
82     end
83
84     def test_create_on_open_changeset
85       assert_no_difference "ChangesetComment.count" do
86         post changeset_comment_path(create(:changeset), :text => "This is a comment"), :headers => bearer_authorization_header
87         assert_response :conflict
88       end
89     end
90
91     def test_create_without_text
92       assert_no_difference "ChangesetComment.count" do
93         post changeset_comment_path(create(:changeset, :closed)), :headers => bearer_authorization_header
94         assert_response :bad_request
95       end
96     end
97
98     def test_create_with_empty_text
99       assert_no_difference "ChangesetComment.count" do
100         post changeset_comment_path(create(:changeset, :closed), :text => ""), :headers => bearer_authorization_header
101         assert_response :bad_request
102       end
103     end
104
105     def test_create_when_not_agreed_to_terms
106       user = create(:user, :terms_agreed => nil)
107       auth_header = bearer_authorization_header user
108       changeset = create(:changeset, :closed)
109
110       assert_difference "ChangesetComment.count", 0 do
111         post changeset_comment_path(changeset), :params => { :text => "This is a comment" }, :headers => auth_header
112         assert_response :forbidden
113       end
114     end
115
116     def test_create_without_required_scope
117       user = create(:user)
118       auth_header = bearer_authorization_header user, :scopes => %w[read_prefs]
119       changeset = create(:changeset, :closed)
120
121       assert_difference "ChangesetComment.count", 0 do
122         post changeset_comment_path(changeset), :params => { :text => "This is a comment" }, :headers => auth_header
123         assert_response :forbidden
124       end
125     end
126
127     def test_create_with_write_changeset_comments_scope
128       user = create(:user)
129       auth_header = bearer_authorization_header user, :scopes => %w[write_changeset_comments]
130       changeset = create(:changeset, :closed)
131
132       assert_difference "ChangesetComment.count", 1 do
133         post changeset_comment_path(changeset), :params => { :text => "This is a comment" }, :headers => auth_header
134         assert_response :success
135       end
136
137       comment = ChangesetComment.last
138       assert_equal changeset.id, comment.changeset_id
139       assert_equal user.id, comment.author_id
140       assert_equal "This is a comment", comment.body
141       assert comment.visible
142     end
143
144     def test_create_with_write_api_scope
145       user = create(:user)
146       auth_header = bearer_authorization_header user, :scopes => %w[write_api]
147       changeset = create(:changeset, :closed)
148
149       assert_difference "ChangesetComment.count", 1 do
150         post changeset_comment_path(changeset), :params => { :text => "This is a comment" }, :headers => auth_header
151         assert_response :success
152       end
153
154       comment = ChangesetComment.last
155       assert_equal changeset.id, comment.changeset_id
156       assert_equal user.id, comment.author_id
157       assert_equal "This is a comment", comment.body
158       assert comment.visible
159     end
160
161     def test_create_on_changeset_with_no_subscribers
162       changeset = create(:changeset, :closed)
163       auth_header = bearer_authorization_header
164
165       assert_difference "ChangesetComment.count", 1 do
166         assert_no_difference "ActionMailer::Base.deliveries.size" do
167           perform_enqueued_jobs do
168             post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
169             assert_response :success
170           end
171         end
172       end
173     end
174
175     def test_create_on_changeset_with_commenter_subscriber
176       user = create(:user)
177       changeset = create(:changeset, :closed, :user => user)
178       changeset.subscribers << user
179       auth_header = bearer_authorization_header user
180
181       assert_difference "ChangesetComment.count", 1 do
182         assert_no_difference "ActionMailer::Base.deliveries.size" do
183           perform_enqueued_jobs do
184             post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
185             assert_response :success
186           end
187         end
188       end
189     end
190
191     def test_create_on_changeset_with_invisible_subscribers
192       changeset = create(:changeset, :closed)
193       changeset.subscribers << create(:user, :suspended)
194       changeset.subscribers << create(:user, :deleted)
195       auth_header = bearer_authorization_header
196
197       assert_difference "ChangesetComment.count", 1 do
198         assert_no_difference "ActionMailer::Base.deliveries.size" do
199           perform_enqueued_jobs do
200             post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
201             assert_response :success
202           end
203         end
204       end
205     end
206
207     def test_create_on_changeset_with_changeset_creator_subscriber
208       creator_user = create(:user)
209       changeset = create(:changeset, :closed, :user => creator_user)
210       changeset.subscribers << creator_user
211       commenter_user = create(:user)
212       auth_header = bearer_authorization_header commenter_user
213
214       assert_difference "ChangesetComment.count", 1 do
215         assert_difference "ActionMailer::Base.deliveries.size", 1 do
216           perform_enqueued_jobs do
217             post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
218             assert_response :success
219           end
220         end
221       end
222
223       email = ActionMailer::Base.deliveries.first
224       assert_equal 1, email.to.length
225       assert_equal "[OpenStreetMap] #{commenter_user.display_name} has commented on one of your changesets", email.subject
226       assert_equal creator_user.email, email.to.first
227
228       ActionMailer::Base.deliveries.clear
229     end
230
231     def test_create_on_changeset_with_changeset_creator_and_other_user_subscribers
232       creator_user = create(:user)
233       changeset = create(:changeset, :closed, :user => creator_user)
234       changeset.subscribers << creator_user
235       other_user = create(:user)
236       changeset.subscribers << other_user
237       commenter_user = create(:user)
238       auth_header = bearer_authorization_header commenter_user
239
240       assert_difference "ChangesetComment.count", 1 do
241         assert_difference "ActionMailer::Base.deliveries.size", 2 do
242           perform_enqueued_jobs do
243             post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
244             assert_response :success
245           end
246         end
247       end
248
249       email = ActionMailer::Base.deliveries.find { |e| e.to.first == creator_user.email }
250       assert_not_nil email
251       assert_equal 1, email.to.length
252       assert_equal "[OpenStreetMap] #{commenter_user.display_name} has commented on one of your changesets", email.subject
253
254       email = ActionMailer::Base.deliveries.find { |e| e.to.first == other_user.email }
255       assert_not_nil email
256       assert_equal 1, email.to.length
257       assert_equal "[OpenStreetMap] #{commenter_user.display_name} has commented on a changeset you are interested in", email.subject
258
259       ActionMailer::Base.deliveries.clear
260     end
261
262     ##
263     # create comment rate limit for new users
264     def test_create_by_new_user_with_rate_limit
265       changeset = create(:changeset, :closed)
266       user = create(:user)
267
268       auth_header = bearer_authorization_header user
269
270       assert_difference "ChangesetComment.count", Settings.initial_changeset_comments_per_hour do
271         1.upto(Settings.initial_changeset_comments_per_hour) do |count|
272           post changeset_comment_path(changeset, :text => "Comment #{count}"), :headers => auth_header
273           assert_response :success
274         end
275       end
276
277       assert_no_difference "ChangesetComment.count" do
278         post changeset_comment_path(changeset, :text => "One comment too many"), :headers => auth_header
279         assert_response :too_many_requests
280       end
281     end
282
283     ##
284     # create comment rate limit for experienced users
285     def test_create_by_experienced_user_with_rate_limit
286       changeset = create(:changeset, :closed)
287       user = create(:user)
288       create_list(:changeset_comment, Settings.comments_to_max_changeset_comments, :author_id => user.id, :created_at => Time.now.utc - 1.day)
289
290       auth_header = bearer_authorization_header user
291
292       assert_difference "ChangesetComment.count", Settings.max_changeset_comments_per_hour do
293         1.upto(Settings.max_changeset_comments_per_hour) do |count|
294           post changeset_comment_path(changeset, :text => "Comment #{count}"), :headers => auth_header
295           assert_response :success
296         end
297       end
298
299       assert_no_difference "ChangesetComment.count" do
300         post changeset_comment_path(changeset, :text => "One comment too many"), :headers => auth_header
301         assert_response :too_many_requests
302       end
303     end
304
305     ##
306     # create comment rate limit for reported users
307     def test_create_by_reported_user_with_rate_limit
308       changeset = create(:changeset, :closed)
309       user = create(:user)
310       create(:issue_with_reports, :reportable => user, :reported_user => user)
311
312       auth_header = bearer_authorization_header user
313
314       assert_difference "ChangesetComment.count", Settings.initial_changeset_comments_per_hour / 2 do
315         1.upto(Settings.initial_changeset_comments_per_hour / 2) do |count|
316           post changeset_comment_path(changeset, :text => "Comment #{count}"), :headers => auth_header
317           assert_response :success
318         end
319       end
320
321       assert_no_difference "ChangesetComment.count" do
322         post changeset_comment_path(changeset, :text => "One comment too many"), :headers => auth_header
323         assert_response :too_many_requests
324       end
325     end
326
327     ##
328     # create comment rate limit for moderator users
329     def test_create_by_moderator_user_with_rate_limit
330       changeset = create(:changeset, :closed)
331       user = create(:moderator_user)
332
333       auth_header = bearer_authorization_header user
334
335       assert_difference "ChangesetComment.count", Settings.moderator_changeset_comments_per_hour do
336         1.upto(Settings.moderator_changeset_comments_per_hour) do |count|
337           post changeset_comment_path(changeset, :text => "Comment #{count}"), :headers => auth_header
338           assert_response :success
339         end
340       end
341
342       assert_no_difference "ChangesetComment.count" do
343         post changeset_comment_path(changeset, :text => "One comment too many"), :headers => auth_header
344         assert_response :too_many_requests
345       end
346     end
347
348     def test_hide_by_unauthorized
349       comment = create(:changeset_comment)
350
351       post changeset_comment_hide_path(comment)
352
353       assert_response :unauthorized
354       assert comment.reload.visible
355     end
356
357     def test_hide_by_normal_user
358       comment = create(:changeset_comment)
359       auth_header = bearer_authorization_header
360
361       post changeset_comment_hide_path(comment), :headers => auth_header
362
363       assert_response :forbidden
364       assert comment.reload.visible
365     end
366
367     def test_hide_missing_comment
368       auth_header = bearer_authorization_header create(:moderator_user)
369
370       post changeset_comment_hide_path(999111), :headers => auth_header
371
372       assert_response :not_found
373     end
374
375     def test_hide_without_required_scope
376       comment = create(:changeset_comment)
377       auth_header = bearer_authorization_header create(:moderator_user), :scopes => %w[read_prefs]
378
379       post changeset_comment_hide_path(comment), :headers => auth_header
380
381       assert_response :forbidden
382       assert comment.reload.visible
383     end
384
385     def test_hide_with_write_changeset_comments_scope
386       comment = create(:changeset_comment)
387       auth_header = bearer_authorization_header create(:moderator_user), :scopes => %w[write_changeset_comments]
388
389       post changeset_comment_hide_path(comment), :headers => auth_header
390
391       assert_response :success
392       assert_not comment.reload.visible
393     end
394
395     def test_hide_with_write_api_scope
396       comment = create(:changeset_comment)
397       auth_header = bearer_authorization_header create(:moderator_user), :scopes => %w[write_api]
398
399       post changeset_comment_hide_path(comment), :headers => auth_header
400
401       assert_response :success
402       assert_not comment.reload.visible
403     end
404
405     def test_unhide_by_unauthorized
406       comment = create(:changeset_comment, :visible => false)
407
408       post changeset_comment_unhide_path(comment)
409
410       assert_response :unauthorized
411       assert_not comment.reload.visible
412     end
413
414     def test_unhide_by_normal_user
415       comment = create(:changeset_comment, :visible => false)
416       auth_header = bearer_authorization_header
417
418       post changeset_comment_unhide_path(comment), :headers => auth_header
419
420       assert_response :forbidden
421       assert_not comment.reload.visible
422     end
423
424     def test_unhide_missing_comment
425       auth_header = bearer_authorization_header create(:moderator_user)
426
427       post changeset_comment_unhide_path(999111), :headers => auth_header
428
429       assert_response :not_found
430     end
431
432     def test_unhide_without_required_scope
433       comment = create(:changeset_comment, :visible => false)
434       auth_header = bearer_authorization_header create(:moderator_user), :scopes => %w[read_prefs]
435
436       post changeset_comment_unhide_path(comment), :headers => auth_header
437
438       assert_response :forbidden
439       assert_not comment.reload.visible
440     end
441
442     def test_unhide_with_write_changeset_comments_scope
443       comment = create(:changeset_comment, :visible => false)
444       auth_header = bearer_authorization_header create(:moderator_user), :scopes => %w[write_changeset_comments]
445
446       post changeset_comment_unhide_path(comment), :headers => auth_header
447
448       assert_response :success
449       assert comment.reload.visible
450     end
451
452     def test_unhide_with_write_api_scope
453       comment = create(:changeset_comment, :visible => false)
454       auth_header = bearer_authorization_header create(:moderator_user), :scopes => %w[write_api]
455
456       post changeset_comment_unhide_path(comment), :headers => auth_header
457
458       assert_response :success
459       assert comment.reload.visible
460     end
461
462     private
463
464     ##
465     # check that certain comments exist in the output in the specified order
466     def assert_comments_in_order(comments)
467       assert_dom "osm > comment", comments.size do |dom_comments|
468         comments.zip(dom_comments).each do |comment, dom_comment|
469           assert_dom dom_comment, "> @id", comment.id.to_s
470           assert_dom dom_comment, "> @uid", comment.author.id.to_s
471           assert_dom dom_comment, "> @user", comment.author.display_name
472           assert_dom dom_comment, "> text", comment.body
473         end
474       end
475     end
476   end
477 end