1 # frozen_string_literal: true
 
   6   class ChangesetCommentsControllerTest < ActionDispatch::IntegrationTest
 
   8     # test all routes which lead to this controller
 
  11         { :path => "/api/0.6/changeset_comments", :method => :get },
 
  12         { :controller => "api/changeset_comments", :action => "index" }
 
  15         { :path => "/api/0.6/changeset_comments.json", :method => :get },
 
  16         { :controller => "api/changeset_comments", :action => "index", :format => "json" }
 
  19         { :path => "/api/0.6/changeset/1/comment", :method => :post },
 
  20         { :controller => "api/changeset_comments", :action => "create", :changeset_id => "1" }
 
  23         { :path => "/api/0.6/changeset/1/comment.json", :method => :post },
 
  24         { :controller => "api/changeset_comments", :action => "create", :changeset_id => "1", :format => "json" }
 
  31       changeset1 = create(:changeset, :closed, :user => user2)
 
  32       comment11 = create(:changeset_comment, :changeset => changeset1, :author => user1, :created_at => "2023-01-01", :body => "changeset 1 question")
 
  33       comment12 = create(:changeset_comment, :changeset => changeset1, :author => user2, :created_at => "2023-02-01", :body => "changeset 1 answer")
 
  34       changeset2 = create(:changeset, :closed, :user => user1)
 
  35       comment21 = create(:changeset_comment, :changeset => changeset2, :author => user1, :created_at => "2023-03-01", :body => "changeset 2 note")
 
  36       comment22 = create(:changeset_comment, :changeset => changeset2, :author => user1, :created_at => "2023-04-01", :body => "changeset 2 extra note")
 
  37       comment23 = create(:changeset_comment, :changeset => changeset2, :author => user2, :created_at => "2023-05-01", :body => "changeset 2 review")
 
  39       get api_changeset_comments_path
 
  40       assert_response :success
 
  41       assert_comments_in_order [comment23, comment22, comment21, comment12, comment11]
 
  43       get api_changeset_comments_path(:limit => 3)
 
  44       assert_response :success
 
  45       assert_comments_in_order [comment23, comment22, comment21]
 
  47       get api_changeset_comments_path(:from => "2023-03-15T00:00:00Z")
 
  48       assert_response :success
 
  49       assert_comments_in_order [comment23, comment22]
 
  51       get api_changeset_comments_path(:from => "2023-01-15T00:00:00Z", :to => "2023-04-15T00:00:00Z")
 
  52       assert_response :success
 
  53       assert_comments_in_order [comment22, comment21, comment12]
 
  55       get api_changeset_comments_path(:user => user1.id)
 
  56       assert_response :success
 
  57       assert_comments_in_order [comment22, comment21, comment11]
 
  59       get api_changeset_comments_path(:from => "2023-03-15T00:00:00Z", :format => "json")
 
  60       assert_response :success
 
  61       js = ActiveSupport::JSON.decode(@response.body)
 
  63       assert_equal 2, js["comments"].count
 
  64       assert_equal comment23.id, js["comments"][0]["id"]
 
  65       assert_equal comment22.id, js["comments"][1]["id"]
 
  68     def test_create_by_unauthorized
 
  69       assert_no_difference "ChangesetComment.count" do
 
  70         post api_changeset_changeset_comments_path(create(:changeset, :closed), :text => "This is a comment")
 
  71         assert_response :unauthorized
 
  75     def test_create_on_missing_changeset
 
  76       assert_no_difference "ChangesetComment.count" do
 
  77         post api_changeset_changeset_comments_path(999111, :text => "This is a comment"), :headers => bearer_authorization_header
 
  78         assert_response :not_found
 
  82     def test_create_on_open_changeset
 
  83       assert_no_difference "ChangesetComment.count" do
 
  84         post api_changeset_changeset_comments_path(create(:changeset), :text => "This is a comment"), :headers => bearer_authorization_header
 
  85         assert_response :conflict
 
  89     def test_create_without_text
 
  90       assert_no_difference "ChangesetComment.count" do
 
  91         post api_changeset_changeset_comments_path(create(:changeset, :closed)), :headers => bearer_authorization_header
 
  92         assert_response :bad_request
 
  96     def test_create_with_empty_text
 
  97       assert_no_difference "ChangesetComment.count" do
 
  98         post api_changeset_changeset_comments_path(create(:changeset, :closed), :text => ""), :headers => bearer_authorization_header
 
  99         assert_response :bad_request
 
 103     def test_create_when_not_agreed_to_terms
 
 104       user = create(:user, :terms_agreed => nil)
 
 105       auth_header = bearer_authorization_header user
 
 106       changeset = create(:changeset, :closed)
 
 108       assert_difference "ChangesetComment.count", 0 do
 
 109         post api_changeset_changeset_comments_path(changeset), :params => { :text => "This is a comment" }, :headers => auth_header
 
 110         assert_response :forbidden
 
 114     def test_create_without_required_scope
 
 116       auth_header = bearer_authorization_header user, :scopes => %w[read_prefs]
 
 117       changeset = create(:changeset, :closed)
 
 119       assert_difference "ChangesetComment.count", 0 do
 
 120         post api_changeset_changeset_comments_path(changeset), :params => { :text => "This is a comment" }, :headers => auth_header
 
 121         assert_response :forbidden
 
 125     def test_create_with_write_changeset_comments_scope
 
 127       auth_header = bearer_authorization_header user, :scopes => %w[write_changeset_comments]
 
 128       changeset = create(:changeset, :closed)
 
 130       assert_difference "ChangesetComment.count", 1 do
 
 131         post api_changeset_changeset_comments_path(changeset), :params => { :text => "This is a comment" }, :headers => auth_header
 
 132         assert_response :success
 
 135       comment = ChangesetComment.last
 
 136       assert_equal changeset.id, comment.changeset_id
 
 137       assert_equal user.id, comment.author_id
 
 138       assert_equal "This is a comment", comment.body
 
 139       assert comment.visible
 
 142     def test_create_with_write_api_scope
 
 144       auth_header = bearer_authorization_header user, :scopes => %w[write_api]
 
 145       changeset = create(:changeset, :closed)
 
 147       assert_difference "ChangesetComment.count", 1 do
 
 148         post api_changeset_changeset_comments_path(changeset), :params => { :text => "This is a comment" }, :headers => auth_header
 
 149         assert_response :success
 
 152       comment = ChangesetComment.last
 
 153       assert_equal changeset.id, comment.changeset_id
 
 154       assert_equal user.id, comment.author_id
 
 155       assert_equal "This is a comment", comment.body
 
 156       assert comment.visible
 
 159     def test_create_on_changeset_with_no_subscribers
 
 160       changeset = create(:changeset, :closed)
 
 161       auth_header = bearer_authorization_header
 
 163       assert_difference "ChangesetComment.count", 1 do
 
 164         assert_no_difference "ActionMailer::Base.deliveries.size" do
 
 165           perform_enqueued_jobs do
 
 166             post api_changeset_changeset_comments_path(changeset, :text => "This is a comment"), :headers => auth_header
 
 167             assert_response :success
 
 173     def test_create_on_changeset_with_commenter_subscriber
 
 175       changeset = create(:changeset, :closed, :user => user)
 
 176       changeset.subscribers << user
 
 177       auth_header = bearer_authorization_header user
 
 179       assert_difference "ChangesetComment.count", 1 do
 
 180         assert_no_difference "ActionMailer::Base.deliveries.size" do
 
 181           perform_enqueued_jobs do
 
 182             post api_changeset_changeset_comments_path(changeset, :text => "This is a comment"), :headers => auth_header
 
 183             assert_response :success
 
 189     def test_create_on_changeset_with_invisible_subscribers
 
 190       changeset = create(:changeset, :closed)
 
 191       changeset.subscribers << create(:user, :suspended)
 
 192       changeset.subscribers << create(:user, :deleted)
 
 193       auth_header = bearer_authorization_header
 
 195       assert_difference "ChangesetComment.count", 1 do
 
 196         assert_no_difference "ActionMailer::Base.deliveries.size" do
 
 197           perform_enqueued_jobs do
 
 198             post api_changeset_changeset_comments_path(changeset, :text => "This is a comment"), :headers => auth_header
 
 199             assert_response :success
 
 205     def test_create_on_changeset_with_changeset_creator_subscriber
 
 206       creator_user = create(:user)
 
 207       changeset = create(:changeset, :closed, :user => creator_user)
 
 208       changeset.subscribers << creator_user
 
 209       commenter_user = create(:user)
 
 210       auth_header = bearer_authorization_header commenter_user
 
 212       assert_difference "ChangesetComment.count", 1 do
 
 213         assert_difference "ActionMailer::Base.deliveries.size", 1 do
 
 214           perform_enqueued_jobs do
 
 215             post api_changeset_changeset_comments_path(changeset, :text => "This is a comment"), :headers => auth_header
 
 216             assert_response :success
 
 221       email = ActionMailer::Base.deliveries.first
 
 222       assert_equal 1, email.to.length
 
 223       assert_equal "[OpenStreetMap] #{commenter_user.display_name} has commented on one of your changesets", email.subject
 
 224       assert_equal creator_user.email, email.to.first
 
 227     def test_create_on_changeset_with_changeset_creator_and_other_user_subscribers
 
 228       creator_user = create(:user)
 
 229       changeset = create(:changeset, :closed, :user => creator_user)
 
 230       changeset.subscribers << creator_user
 
 231       other_user = create(:user)
 
 232       changeset.subscribers << other_user
 
 233       commenter_user = create(:user)
 
 234       auth_header = bearer_authorization_header commenter_user
 
 236       assert_difference "ChangesetComment.count", 1 do
 
 237         assert_difference "ActionMailer::Base.deliveries.size", 2 do
 
 238           perform_enqueued_jobs do
 
 239             post api_changeset_changeset_comments_path(changeset, :text => "This is a comment"), :headers => auth_header
 
 240             assert_response :success
 
 245       email = ActionMailer::Base.deliveries.find { |e| e.to.first == creator_user.email }
 
 247       assert_equal 1, email.to.length
 
 248       assert_equal "[OpenStreetMap] #{commenter_user.display_name} has commented on one of your changesets", email.subject
 
 250       email = ActionMailer::Base.deliveries.find { |e| e.to.first == other_user.email }
 
 252       assert_equal 1, email.to.length
 
 253       assert_equal "[OpenStreetMap] #{commenter_user.display_name} has commented on a changeset you are interested in", email.subject
 
 257     # create comment rate limit for new users
 
 258     def test_create_by_new_user_with_rate_limit
 
 259       changeset = create(:changeset, :closed)
 
 262       auth_header = bearer_authorization_header user
 
 264       assert_difference "ChangesetComment.count", Settings.initial_changeset_comments_per_hour do
 
 265         1.upto(Settings.initial_changeset_comments_per_hour) do |count|
 
 266           post api_changeset_changeset_comments_path(changeset, :text => "Comment #{count}"), :headers => auth_header
 
 267           assert_response :success
 
 271       assert_no_difference "ChangesetComment.count" do
 
 272         post api_changeset_changeset_comments_path(changeset, :text => "One comment too many"), :headers => auth_header
 
 273         assert_response :too_many_requests
 
 278     # create comment rate limit for experienced users
 
 279     def test_create_by_experienced_user_with_rate_limit
 
 280       changeset = create(:changeset, :closed)
 
 282       create_list(:changeset_comment, Settings.comments_to_max_changeset_comments, :author_id => user.id, :created_at => Time.now.utc - 1.day)
 
 284       auth_header = bearer_authorization_header user
 
 286       assert_difference "ChangesetComment.count", Settings.max_changeset_comments_per_hour do
 
 287         1.upto(Settings.max_changeset_comments_per_hour) do |count|
 
 288           post api_changeset_changeset_comments_path(changeset, :text => "Comment #{count}"), :headers => auth_header
 
 289           assert_response :success
 
 293       assert_no_difference "ChangesetComment.count" do
 
 294         post api_changeset_changeset_comments_path(changeset, :text => "One comment too many"), :headers => auth_header
 
 295         assert_response :too_many_requests
 
 300     # create comment rate limit for reported users
 
 301     def test_create_by_reported_user_with_rate_limit
 
 302       changeset = create(:changeset, :closed)
 
 304       create(:issue_with_reports, :reportable => user, :reported_user => user)
 
 306       auth_header = bearer_authorization_header user
 
 308       assert_difference "ChangesetComment.count", Settings.initial_changeset_comments_per_hour / 2 do
 
 309         1.upto(Settings.initial_changeset_comments_per_hour / 2) do |count|
 
 310           post api_changeset_changeset_comments_path(changeset, :text => "Comment #{count}"), :headers => auth_header
 
 311           assert_response :success
 
 315       assert_no_difference "ChangesetComment.count" do
 
 316         post api_changeset_changeset_comments_path(changeset, :text => "One comment too many"), :headers => auth_header
 
 317         assert_response :too_many_requests
 
 322     # create comment rate limit for moderator users
 
 323     def test_create_by_moderator_user_with_rate_limit
 
 324       changeset = create(:changeset, :closed)
 
 325       user = create(:moderator_user)
 
 327       auth_header = bearer_authorization_header user
 
 329       assert_difference "ChangesetComment.count", Settings.moderator_changeset_comments_per_hour do
 
 330         1.upto(Settings.moderator_changeset_comments_per_hour) do |count|
 
 331           post api_changeset_changeset_comments_path(changeset, :text => "Comment #{count}"), :headers => auth_header
 
 332           assert_response :success
 
 336       assert_no_difference "ChangesetComment.count" do
 
 337         post api_changeset_changeset_comments_path(changeset, :text => "One comment too many"), :headers => auth_header
 
 338         assert_response :too_many_requests
 
 345     # check that certain comments exist in the output in the specified order
 
 346     def assert_comments_in_order(comments)
 
 347       assert_dom "osm > comment", comments.size do |dom_comments|
 
 348         comments.zip(dom_comments).each do |comment, dom_comment|
 
 349           assert_dom dom_comment, "> @id", comment.id.to_s
 
 350           assert_dom dom_comment, "> @uid", comment.author.id.to_s
 
 351           assert_dom dom_comment, "> @user", comment.author.display_name
 
 352           assert_dom dom_comment, "> text", comment.body