1 # frozen_string_literal: true
6 class NotesControllerTest < ActionDispatch::IntegrationTest
9 # Stub nominatim response for note locations
10 stub_request(:get, %r{^https://nominatim\.openstreetmap\.org/reverse\?})
11 .to_return(:status => 404)
15 # test all routes which lead to this controller
18 { :path => "/api/0.6/notes", :method => :post },
19 { :controller => "api/notes", :action => "create" }
22 { :path => "/api/0.6/notes/1", :method => :get },
23 { :controller => "api/notes", :action => "show", :id => "1" }
26 { :controller => "api/notes", :action => "show", :id => "1", :format => "xml" },
27 { :path => "/api/0.6/notes/1.xml", :method => :get }
30 { :path => "/api/0.6/notes/1.rss", :method => :get },
31 { :controller => "api/notes", :action => "show", :id => "1", :format => "rss" }
34 { :path => "/api/0.6/notes/1.json", :method => :get },
35 { :controller => "api/notes", :action => "show", :id => "1", :format => "json" }
38 { :path => "/api/0.6/notes/1.gpx", :method => :get },
39 { :controller => "api/notes", :action => "show", :id => "1", :format => "gpx" }
42 { :path => "/api/0.6/notes/1/comment", :method => :post },
43 { :controller => "api/notes", :action => "comment", :id => "1" }
46 { :path => "/api/0.6/notes/1/close", :method => :post },
47 { :controller => "api/notes", :action => "close", :id => "1" }
50 { :path => "/api/0.6/notes/1/reopen", :method => :post },
51 { :controller => "api/notes", :action => "reopen", :id => "1" }
54 { :path => "/api/0.6/notes/1", :method => :delete },
55 { :controller => "api/notes", :action => "destroy", :id => "1" }
59 { :path => "/api/0.6/notes", :method => :get },
60 { :controller => "api/notes", :action => "index" }
63 { :controller => "api/notes", :action => "index", :format => "xml" },
64 { :path => "/api/0.6/notes.xml", :method => :get }
67 { :path => "/api/0.6/notes.rss", :method => :get },
68 { :controller => "api/notes", :action => "index", :format => "rss" }
71 { :path => "/api/0.6/notes.json", :method => :get },
72 { :controller => "api/notes", :action => "index", :format => "json" }
75 { :path => "/api/0.6/notes.gpx", :method => :get },
76 { :controller => "api/notes", :action => "index", :format => "gpx" }
80 { :path => "/api/0.6/notes/search", :method => :get },
81 { :controller => "api/notes", :action => "search" }
84 { :controller => "api/notes", :action => "search", :format => "xml" },
85 { :path => "/api/0.6/notes/search.xml", :method => :get }
88 { :path => "/api/0.6/notes/search.rss", :method => :get },
89 { :controller => "api/notes", :action => "search", :format => "rss" }
92 { :path => "/api/0.6/notes/search.json", :method => :get },
93 { :controller => "api/notes", :action => "search", :format => "json" }
96 { :path => "/api/0.6/notes/search.gpx", :method => :get },
97 { :controller => "api/notes", :action => "search", :format => "gpx" }
101 { :path => "/api/0.6/notes/feed", :method => :get },
102 { :controller => "api/notes", :action => "feed", :format => "rss" }
106 def test_create_anonymous_success
107 assert_difference "Note.count", 1 do
108 assert_difference "NoteComment.count", 1 do
109 assert_no_difference "NoteSubscription.count" do
110 post api_notes_path(:lat => -1.0, :lon => -1.0, :text => "This is a comment", :format => "json")
114 assert_response :success
115 js = ActiveSupport::JSON.decode(@response.body)
117 assert_equal "Feature", js["type"]
118 assert_equal "Point", js["geometry"]["type"]
119 assert_equal [-1.0, -1.0], js["geometry"]["coordinates"]
120 assert_equal "open", js["properties"]["status"]
121 assert_equal 1, js["properties"]["comments"].count
122 assert_equal "opened", js["properties"]["comments"].last["action"]
123 assert_equal "This is a comment", js["properties"]["comments"].last["text"]
124 assert_nil js["properties"]["comments"].last["user"]
125 id = js["properties"]["id"]
127 get api_note_path(id, :format => "json")
128 assert_response :success
129 js = ActiveSupport::JSON.decode(@response.body)
131 assert_equal "Feature", js["type"]
132 assert_equal "Point", js["geometry"]["type"]
133 assert_equal [-1.0, -1.0], js["geometry"]["coordinates"]
134 assert_equal id, js["properties"]["id"]
135 assert_equal "open", js["properties"]["status"]
136 assert_equal 1, js["properties"]["comments"].count
137 assert_equal "opened", js["properties"]["comments"].last["action"]
138 assert_equal "This is a comment", js["properties"]["comments"].last["text"]
139 assert_nil js["properties"]["comments"].last["user"]
142 def test_create_anonymous_fail
143 assert_no_difference "Note.count" do
144 assert_no_difference "NoteComment.count" do
145 post api_notes_path(:lon => -1.0, :text => "This is a comment")
148 assert_response :bad_request
150 assert_no_difference "Note.count" do
151 assert_no_difference "NoteComment.count" do
152 post api_notes_path(:lat => -1.0, :text => "This is a comment")
155 assert_response :bad_request
157 assert_no_difference "Note.count" do
158 assert_no_difference "NoteComment.count" do
159 post api_notes_path(:lat => -1.0, :lon => -1.0)
162 assert_response :bad_request
164 assert_no_difference "Note.count" do
165 assert_no_difference "NoteComment.count" do
166 post api_notes_path(:lat => -1.0, :lon => -1.0, :text => "")
169 assert_response :bad_request
171 assert_no_difference "Note.count" do
172 assert_no_difference "NoteComment.count" do
173 post api_notes_path(:lat => -100.0, :lon => -1.0, :text => "This is a comment")
176 assert_response :bad_request
178 assert_no_difference "Note.count" do
179 assert_no_difference "NoteComment.count" do
180 post api_notes_path(:lat => -1.0, :lon => -200.0, :text => "This is a comment")
183 assert_response :bad_request
185 assert_no_difference "Note.count" do
186 assert_no_difference "NoteComment.count" do
187 post api_notes_path(:lat => "abc", :lon => -1.0, :text => "This is a comment")
190 assert_response :bad_request
192 assert_no_difference "Note.count" do
193 assert_no_difference "NoteComment.count" do
194 post api_notes_path(:lat => -1.0, :lon => "abc", :text => "This is a comment")
197 assert_response :bad_request
199 assert_no_difference "Note.count" do
200 assert_no_difference "NoteComment.count" do
201 post api_notes_path(:lat => -1.0, :lon => -1.0, :text => "x\u0000y")
204 assert_response :bad_request
207 def test_create_anonymous_in_moderation_zone
208 point = coordinates_inside_seville_cathedral
209 create(:moderation_zone, :seville_cathedral)
210 assert_no_difference "Note.count" do
211 assert_no_difference "NoteComment.count" do
212 post api_notes_path(:lat => point.lat, :lon => point.lon, :text => "Down with this sort of thing")
215 assert_response :forbidden
216 assert_equal "You don't have permissions to make changes in this zone, as it is currently protected by moderators", response.headers["Error"]
219 def test_create_success
221 auth_header = bearer_authorization_header user
222 assert_difference "Note.count", 1 do
223 assert_difference "NoteComment.count", 1 do
224 assert_difference "NoteSubscription.count", 1 do
225 post api_notes_path(:lat => -1.0, :lon => -1.0, :text => "This is a comment", :format => "json"), :headers => auth_header
229 assert_response :success
230 js = ActiveSupport::JSON.decode(@response.body)
232 assert_equal "Feature", js["type"]
233 assert_equal "Point", js["geometry"]["type"]
234 assert_equal [-1.0, -1.0], js["geometry"]["coordinates"]
235 assert_equal "open", js["properties"]["status"]
236 assert_equal 1, js["properties"]["comments"].count
237 assert_equal "opened", js["properties"]["comments"].last["action"]
238 assert_equal "This is a comment", js["properties"]["comments"].last["text"]
239 assert_equal user.display_name, js["properties"]["comments"].last["user"]
242 subscription = NoteSubscription.last
243 assert_equal user, subscription.user
244 assert_equal note, subscription.note
247 def test_create_success_in_moderation_zone
248 point = coordinates_inside_seville_cathedral
249 create(:moderation_zone, :seville_cathedral)
251 auth_header = bearer_authorization_header user
252 assert_difference "Note.count", 1 do
253 assert_difference "NoteComment.count", 1 do
254 assert_difference "NoteSubscription.count", 1 do
255 post api_notes_path(:lat => point.lat, :lon => point.lon, :text => "This is a comment", :format => "json"), :headers => auth_header
259 assert_response :success
262 def test_create_no_scope_fail
264 auth_header = bearer_authorization_header user, :scopes => %w[read_prefs]
266 assert_no_difference "Note.count" do
267 post api_notes_path(:lat => -1.0, :lon => -1.0, :text => "This is a description", :format => "json"), :headers => auth_header
269 assert_response :forbidden
273 def test_comment_success
274 open_note_with_comment = create(:note_with_comments)
276 auth_header = bearer_authorization_header user
277 assert_difference "NoteComment.count", 1 do
278 assert_difference "NoteSubscription.count", 1 do
279 assert_no_difference "ActionMailer::Base.deliveries.size" do
280 perform_enqueued_jobs do
281 post comment_api_note_path(open_note_with_comment, :text => "This is an additional comment", :format => "json"), :headers => auth_header
286 assert_response :success
287 js = ActiveSupport::JSON.decode(@response.body)
289 assert_equal "Feature", js["type"]
290 assert_equal open_note_with_comment.id, js["properties"]["id"]
291 assert_equal "open", js["properties"]["status"]
292 assert_equal 2, js["properties"]["comments"].count
293 assert_equal "commented", js["properties"]["comments"].last["action"]
294 assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
295 assert_equal user.display_name, js["properties"]["comments"].last["user"]
297 subscription = NoteSubscription.last
298 assert_equal user, subscription.user
299 assert_equal open_note_with_comment, subscription.note
301 get api_note_path(open_note_with_comment, :format => "json")
302 assert_response :success
303 js = ActiveSupport::JSON.decode(@response.body)
305 assert_equal "Feature", js["type"]
306 assert_equal open_note_with_comment.id, js["properties"]["id"]
307 assert_equal "open", js["properties"]["status"]
308 assert_equal 2, js["properties"]["comments"].count
309 assert_equal "commented", js["properties"]["comments"].last["action"]
310 assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
311 assert_equal user.display_name, js["properties"]["comments"].last["user"]
314 def test_comment_without_notifications_success
315 # Ensure that emails are sent to users
316 first_user = create(:user)
317 second_user = create(:user)
318 third_user = create(:user)
320 note_with_comments_by_users = create(:note) do |note|
321 create(:note_comment, :note => note, :author => first_user)
322 create(:note_comment, :note => note, :author => second_user)
325 auth_header = bearer_authorization_header third_user
327 assert_difference "NoteComment.count", 1 do
328 assert_difference "NoteSubscription.count", 1 do
329 assert_no_difference "ActionMailer::Base.deliveries.size" do
330 perform_enqueued_jobs do
331 post comment_api_note_path(note_with_comments_by_users, :text => "This is an additional comment", :format => "json"), :headers => auth_header
336 assert_response :success
337 js = ActiveSupport::JSON.decode(@response.body)
339 assert_equal "Feature", js["type"]
340 assert_equal note_with_comments_by_users.id, js["properties"]["id"]
341 assert_equal "open", js["properties"]["status"]
342 assert_equal 3, js["properties"]["comments"].count
343 assert_equal "commented", js["properties"]["comments"].last["action"]
344 assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
345 assert_equal third_user.display_name, js["properties"]["comments"].last["user"]
347 subscription = NoteSubscription.last
348 assert_equal third_user, subscription.user
349 assert_equal note_with_comments_by_users, subscription.note
351 get api_note_path(note_with_comments_by_users, :format => "json")
352 assert_response :success
353 js = ActiveSupport::JSON.decode(@response.body)
355 assert_equal "Feature", js["type"]
356 assert_equal note_with_comments_by_users.id, js["properties"]["id"]
357 assert_equal "open", js["properties"]["status"]
358 assert_equal 3, js["properties"]["comments"].count
359 assert_equal "commented", js["properties"]["comments"].last["action"]
360 assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
361 assert_equal third_user.display_name, js["properties"]["comments"].last["user"]
364 def test_comment_with_notifications_success
365 # Ensure that emails are sent to users
366 first_user = create(:user)
367 second_user = create(:user)
368 third_user = create(:user)
370 note_with_comments_by_users = create(:note, :author => first_user) do |note|
371 create(:note_comment, :note => note, :author => first_user)
372 create(:note_comment, :note => note, :author => second_user)
374 create(:note_subscription, :note => note_with_comments_by_users, :user => first_user)
375 create(:note_subscription, :note => note_with_comments_by_users, :user => second_user)
377 auth_header = bearer_authorization_header third_user
379 assert_difference "NoteComment.count", 1 do
380 assert_difference "NoteSubscription.count", 1 do
381 assert_difference "ActionMailer::Base.deliveries.size", 2 do
382 perform_enqueued_jobs do
383 post comment_api_note_path(note_with_comments_by_users, :text => "This is an additional comment", :format => "json"), :headers => auth_header
388 assert_response :success
389 js = ActiveSupport::JSON.decode(@response.body)
391 assert_equal "Feature", js["type"]
392 assert_equal note_with_comments_by_users.id, js["properties"]["id"]
393 assert_equal "open", js["properties"]["status"]
394 assert_equal 3, js["properties"]["comments"].count
395 assert_equal "commented", js["properties"]["comments"].last["action"]
396 assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
397 assert_equal third_user.display_name, js["properties"]["comments"].last["user"]
399 subscription = NoteSubscription.last
400 assert_equal third_user, subscription.user
401 assert_equal note_with_comments_by_users, subscription.note
403 assert_email_received first_user.email, "[OpenStreetMap] #{third_user.display_name} has commented on one of your notes"
404 assert_email_received second_user.email, "[OpenStreetMap] #{third_user.display_name} has commented on a note you are interested in"
406 get api_note_path(note_with_comments_by_users, :format => "json")
407 assert_response :success
408 js = ActiveSupport::JSON.decode(@response.body)
410 assert_equal "Feature", js["type"]
411 assert_equal note_with_comments_by_users.id, js["properties"]["id"]
412 assert_equal "open", js["properties"]["status"]
413 assert_equal 3, js["properties"]["comments"].count
414 assert_equal "commented", js["properties"]["comments"].last["action"]
415 assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
416 assert_equal third_user.display_name, js["properties"]["comments"].last["user"]
419 def test_comment_twice_success
420 open_note_with_comment = create(:note_with_comments)
422 auth_header = bearer_authorization_header user
423 assert_difference "NoteComment.count", 1 do
424 assert_difference "NoteSubscription.count", 1 do
425 assert_no_difference "ActionMailer::Base.deliveries.size" do
426 perform_enqueued_jobs do
427 post comment_api_note_path(open_note_with_comment, :text => "This is an additional comment", :format => "json"), :headers => auth_header
432 assert_response :success
433 js = ActiveSupport::JSON.decode(@response.body)
435 assert_equal 2, js["properties"]["comments"].count
437 subscription = NoteSubscription.last
438 assert_equal user, subscription.user
439 assert_equal open_note_with_comment, subscription.note
441 assert_difference "NoteComment.count", 1 do
442 assert_no_difference "NoteSubscription.count" do
443 assert_no_difference "ActionMailer::Base.deliveries.size" do
444 perform_enqueued_jobs do
445 post comment_api_note_path(open_note_with_comment, :text => "This is a second additional comment", :format => "json"), :headers => auth_header
450 assert_response :success
451 js = ActiveSupport::JSON.decode(@response.body)
453 assert_equal 3, js["properties"]["comments"].count
456 def test_comment_fail
457 open_note_with_comment = create(:note_with_comments)
461 assert_no_difference "NoteComment.count" do
462 post comment_api_note_path(open_note_with_comment)
463 assert_response :unauthorized
466 auth_header = bearer_authorization_header user
468 assert_no_difference "NoteComment.count" do
469 post comment_api_note_path(open_note_with_comment), :headers => auth_header
471 assert_response :bad_request
473 assert_no_difference "NoteComment.count" do
474 post comment_api_note_path(open_note_with_comment, :text => ""), :headers => auth_header
476 assert_response :bad_request
478 assert_no_difference "NoteComment.count" do
479 post comment_api_note_path(12345, :text => "This is an additional comment"), :headers => auth_header
481 assert_response :not_found
483 hidden_note_with_comment = create(:note_with_comments, :status => "hidden")
485 assert_no_difference "NoteComment.count" do
486 post comment_api_note_path(hidden_note_with_comment, :text => "This is an additional comment"), :headers => auth_header
488 assert_response :gone
490 closed_note_with_comment = create(:note_with_comments, :closed)
492 assert_no_difference "NoteComment.count" do
493 post comment_api_note_path(closed_note_with_comment, :text => "This is an additional comment"), :headers => auth_header
495 assert_response :conflict
497 assert_no_difference "NoteComment.count" do
498 post comment_api_note_path(open_note_with_comment, :text => "x\u0000y"), :headers => auth_header
500 assert_response :bad_request
503 def test_close_success
504 open_note_with_comment = create(:note_with_comments)
507 post close_api_note_path(open_note_with_comment, :text => "This is a close comment", :format => "json")
508 assert_response :unauthorized
510 auth_header = bearer_authorization_header user
512 assert_difference "NoteSubscription.count", 1 do
513 post close_api_note_path(open_note_with_comment, :text => "This is a close comment", :format => "json"), :headers => auth_header
515 assert_response :success
516 js = ActiveSupport::JSON.decode(@response.body)
518 assert_equal "Feature", js["type"]
519 assert_equal open_note_with_comment.id, js["properties"]["id"]
520 assert_equal "closed", js["properties"]["status"]
521 assert_equal 2, js["properties"]["comments"].count
522 assert_equal "closed", js["properties"]["comments"].last["action"]
523 assert_equal "This is a close comment", js["properties"]["comments"].last["text"]
524 assert_equal user.display_name, js["properties"]["comments"].last["user"]
526 subscription = NoteSubscription.last
527 assert_equal user, subscription.user
528 assert_equal open_note_with_comment, subscription.note
530 get api_note_path(open_note_with_comment.id, :format => "json")
531 assert_response :success
532 js = ActiveSupport::JSON.decode(@response.body)
534 assert_equal "Feature", js["type"]
535 assert_equal open_note_with_comment.id, js["properties"]["id"]
536 assert_equal "closed", js["properties"]["status"]
537 assert_equal 2, js["properties"]["comments"].count
538 assert_equal "closed", js["properties"]["comments"].last["action"]
539 assert_equal "This is a close comment", js["properties"]["comments"].last["text"]
540 assert_equal user.display_name, js["properties"]["comments"].last["user"]
544 post close_api_note_path(12345)
545 assert_response :unauthorized
547 auth_header = bearer_authorization_header
549 post close_api_note_path(12345), :headers => auth_header
550 assert_response :not_found
552 hidden_note_with_comment = create(:note_with_comments, :status => "hidden")
554 post close_api_note_path(hidden_note_with_comment), :headers => auth_header
555 assert_response :gone
557 closed_note_with_comment = create(:note_with_comments, :closed)
559 post close_api_note_path(closed_note_with_comment), :headers => auth_header
560 assert_response :conflict
563 def test_reopen_success
564 closed_note_with_comment = create(:note_with_comments, :closed)
567 post reopen_api_note_path(closed_note_with_comment, :text => "This is a reopen comment", :format => "json")
568 assert_response :unauthorized
570 auth_header = bearer_authorization_header user
572 assert_difference "NoteSubscription.count", 1 do
573 post reopen_api_note_path(closed_note_with_comment, :text => "This is a reopen comment", :format => "json"), :headers => auth_header
575 assert_response :success
576 js = ActiveSupport::JSON.decode(@response.body)
578 assert_equal "Feature", js["type"]
579 assert_equal closed_note_with_comment.id, js["properties"]["id"]
580 assert_equal "open", js["properties"]["status"]
581 assert_equal 3, js["properties"]["comments"].count
582 assert_equal "reopened", js["properties"]["comments"].last["action"]
583 assert_equal "This is a reopen comment", js["properties"]["comments"].last["text"]
584 assert_equal user.display_name, js["properties"]["comments"].last["user"]
586 subscription = NoteSubscription.last
587 assert_equal user, subscription.user
588 assert_equal closed_note_with_comment, subscription.note
590 get api_note_path(closed_note_with_comment, :format => "json")
591 assert_response :success
592 js = ActiveSupport::JSON.decode(@response.body)
594 assert_equal "Feature", js["type"]
595 assert_equal closed_note_with_comment.id, js["properties"]["id"]
596 assert_equal "open", js["properties"]["status"]
597 assert_equal 3, js["properties"]["comments"].count
598 assert_equal "reopened", js["properties"]["comments"].last["action"]
599 assert_equal "This is a reopen comment", js["properties"]["comments"].last["text"]
600 assert_equal user.display_name, js["properties"]["comments"].last["user"]
604 hidden_note_with_comment = create(:note_with_comments, :status => "hidden")
606 post reopen_api_note_path(hidden_note_with_comment)
607 assert_response :unauthorized
609 auth_header = bearer_authorization_header
611 post reopen_api_note_path(12345), :headers => auth_header
612 assert_response :not_found
614 post reopen_api_note_path(hidden_note_with_comment), :headers => auth_header
615 assert_response :gone
617 open_note_with_comment = create(:note_with_comments)
619 post reopen_api_note_path(open_note_with_comment), :headers => auth_header
620 assert_response :conflict
623 def test_show_success
624 open_note = create(:note_with_comments)
626 get api_note_path(open_note, :format => "xml")
627 assert_response :success
628 assert_equal "application/xml", @response.media_type
629 assert_select "osm", :count => 1 do
630 assert_select "note[lat='#{open_note.lat}'][lon='#{open_note.lon}']", :count => 1 do
631 assert_select "id", open_note.id.to_s
632 assert_select "url", api_note_url(open_note, :format => "xml")
633 assert_select "comment_url", comment_api_note_url(open_note, :format => "xml")
634 assert_select "close_url", close_api_note_url(open_note, :format => "xml")
635 assert_select "date_created", open_note.created_at.to_s
636 assert_select "status", open_note.status
637 assert_select "comments", :count => 1 do
638 assert_select "comment", :count => 1
643 get api_note_path(open_note, :format => "rss")
644 assert_response :success
645 assert_equal "application/rss+xml", @response.media_type
646 assert_select "rss", :count => 1 do
647 assert_select "channel", :count => 1 do
648 assert_select "item", :count => 1 do
649 assert_select "link", note_url(open_note)
650 assert_select "guid", api_note_url(open_note)
651 assert_select "pubDate", open_note.created_at.to_fs(:rfc822)
652 assert_select "geo|lat", open_note.lat.to_s
653 assert_select "geo|long", open_note.lon.to_s
654 assert_select "georss|point", "#{open_note.lon} #{open_note.lon}"
659 get api_note_path(open_note, :format => "json")
660 assert_response :success
661 assert_equal "application/json", @response.media_type
662 js = ActiveSupport::JSON.decode(@response.body)
664 assert_equal "Feature", js["type"]
665 assert_equal "Point", js["geometry"]["type"]
666 assert_equal open_note.lat, js["geometry"]["coordinates"][0]
667 assert_equal open_note.lon, js["geometry"]["coordinates"][1]
668 assert_equal open_note.id, js["properties"]["id"]
669 assert_equal api_note_url(open_note, :format => "json"), js["properties"]["url"]
670 assert_equal comment_api_note_url(open_note, :format => "json"), js["properties"]["comment_url"]
671 assert_equal close_api_note_url(open_note, :format => "json"), js["properties"]["close_url"]
672 assert_equal open_note.created_at.to_s, js["properties"]["date_created"]
673 assert_equal open_note.status, js["properties"]["status"]
675 get api_note_path(open_note, :format => "gpx")
676 assert_response :success
677 assert_equal "application/gpx+xml", @response.media_type
678 assert_select "gpx", :count => 1 do
679 assert_select "wpt[lat='#{open_note.lat}'][lon='#{open_note.lon}']", :count => 1 do
680 assert_select "time", :count => 1
681 assert_select "name", "Note: #{open_note.id}"
682 assert_select "desc", :count => 1
683 assert_select "link[href='http://www.example.com/note/#{open_note.id}']", :count => 1
684 assert_select "extensions", :count => 1 do
685 assert_select "id", open_note.id.to_s
686 assert_select "url", api_note_url(open_note, :format => "gpx")
687 assert_select "comment_url", comment_api_note_url(open_note, :format => "gpx")
688 assert_select "close_url", close_api_note_url(open_note, :format => "gpx")
694 def test_show_hidden_comment
695 note_with_hidden_comment = create(:note) do |note|
696 create(:note_comment, :note => note, :body => "Valid comment for hidden note")
697 create(:note_comment, :note => note, :visible => false)
698 create(:note_comment, :note => note, :body => "Another valid comment for hidden note")
701 get api_note_path(note_with_hidden_comment, :format => "json")
702 assert_response :success
703 js = ActiveSupport::JSON.decode(@response.body)
705 assert_equal "Feature", js["type"]
706 assert_equal note_with_hidden_comment.id, js["properties"]["id"]
707 assert_equal 2, js["properties"]["comments"].count
708 assert_equal "Valid comment for hidden note", js["properties"]["comments"][0]["text"]
709 assert_equal "Another valid comment for hidden note", js["properties"]["comments"][1]["text"]
713 get api_note_path(12345)
714 assert_response :not_found
716 get api_note_path(create(:note, :status => "hidden"))
717 assert_response :gone
720 def test_destroy_success
721 open_note_with_comment = create(:note_with_comments)
723 moderator_user = create(:moderator_user)
725 delete api_note_path(open_note_with_comment, :text => "This is a hide comment", :format => "json")
726 assert_response :unauthorized
728 auth_header = bearer_authorization_header user
730 delete api_note_path(open_note_with_comment, :text => "This is a hide comment", :format => "json"), :headers => auth_header
731 assert_response :forbidden
733 auth_header = bearer_authorization_header moderator_user
735 delete api_note_path(open_note_with_comment, :text => "This is a hide comment", :format => "json"), :headers => auth_header
736 assert_response :success
737 js = ActiveSupport::JSON.decode(@response.body)
739 assert_equal "Feature", js["type"]
740 assert_equal open_note_with_comment.id, js["properties"]["id"]
741 assert_equal "hidden", js["properties"]["status"]
742 assert_equal 2, js["properties"]["comments"].count
743 assert_equal "hidden", js["properties"]["comments"].last["action"]
744 assert_equal "This is a hide comment", js["properties"]["comments"].last["text"]
745 assert_equal moderator_user.display_name, js["properties"]["comments"].last["user"]
747 get api_note_path(open_note_with_comment, :format => "json"), :headers => auth_header
748 assert_response :success
750 auth_header = bearer_authorization_header user
752 get api_note_path(open_note_with_comment, :format => "json"), :headers => auth_header
753 assert_response :gone
756 def test_destroy_fail
758 moderator_user = create(:moderator_user)
760 delete api_note_path(12345, :format => "json")
761 assert_response :unauthorized
763 auth_header = bearer_authorization_header user
765 delete api_note_path(12345, :format => "json"), :headers => auth_header
766 assert_response :forbidden
768 auth_header = bearer_authorization_header moderator_user
770 delete api_note_path(12345, :format => "json"), :headers => auth_header
771 assert_response :not_found
773 hidden_note_with_comment = create(:note_with_comments, :status => "hidden")
775 delete api_note_path(hidden_note_with_comment, :format => "json"), :headers => auth_header
776 assert_response :gone
779 def test_index_success
780 position = (1.1 * GeoRecord::SCALE).to_i
781 create(:note_with_comments, :latitude => position, :longitude => position)
782 create(:note_with_comments, :latitude => position, :longitude => position)
784 get api_notes_path(:bbox => "1,1,1.2,1.2", :format => "rss")
785 assert_response :success
786 assert_equal "application/rss+xml", @response.media_type
787 assert_select "rss", :count => 1 do
788 assert_select "channel", :count => 1 do
789 assert_select "description", :text => /1\.2/, :count => 1
790 assert_select "item", :count => 2
794 get api_notes_path(:bbox => "1,1,1.2,1.2", :format => "json")
795 assert_response :success
796 assert_equal "application/json", @response.media_type
797 js = ActiveSupport::JSON.decode(@response.body)
799 assert_equal "FeatureCollection", js["type"]
800 assert_equal 2, js["features"].count
802 get api_notes_path(:bbox => "1,1,1.2,1.2", :format => "xml")
803 assert_response :success
804 assert_equal "application/xml", @response.media_type
805 assert_select "osm", :count => 1 do
806 assert_select "note", :count => 2
809 get api_notes_path(:bbox => "1,1,1.2,1.2", :format => "gpx")
810 assert_response :success
811 assert_equal "application/gpx+xml", @response.media_type
812 assert_select "gpx", :count => 1 do
813 assert_select "wpt", :count => 2
818 position = (1.1 * GeoRecord::SCALE).to_i
819 create(:note_with_comments, :latitude => position, :longitude => position)
820 create(:note_with_comments, :latitude => position, :longitude => position)
822 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => 1, :format => "rss")
823 assert_response :success
824 assert_equal "application/rss+xml", @response.media_type
825 assert_select "rss", :count => 1 do
826 assert_select "channel", :count => 1 do
827 assert_select "item", :count => 1
831 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => 1, :format => "json")
832 assert_response :success
833 assert_equal "application/json", @response.media_type
834 js = ActiveSupport::JSON.decode(@response.body)
836 assert_equal "FeatureCollection", js["type"]
837 assert_equal 1, js["features"].count
839 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => 1, :format => "xml")
840 assert_response :success
841 assert_equal "application/xml", @response.media_type
842 assert_select "osm", :count => 1 do
843 assert_select "note", :count => 1
846 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => 1, :format => "gpx")
847 assert_response :success
848 assert_equal "application/gpx+xml", @response.media_type
849 assert_select "gpx", :count => 1 do
850 assert_select "wpt", :count => 1
853 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => Settings.max_note_query_limit, :format => "rss")
854 assert_response :success
857 def test_index_empty_area
858 get api_notes_path(:bbox => "5,5,5.1,5.1", :format => "rss")
859 assert_response :success
860 assert_equal "application/rss+xml", @response.media_type
861 assert_select "rss", :count => 1 do
862 assert_select "channel", :count => 1 do
863 assert_select "item", :count => 0
867 get api_notes_path(:bbox => "5,5,5.1,5.1", :format => "json")
868 assert_response :success
869 assert_equal "application/json", @response.media_type
870 js = ActiveSupport::JSON.decode(@response.body)
872 assert_equal "FeatureCollection", js["type"]
873 assert_equal 0, js["features"].count
875 get api_notes_path(:bbox => "5,5,5.1,5.1", :format => "xml")
876 assert_response :success
877 assert_equal "application/xml", @response.media_type
878 assert_select "osm", :count => 1 do
879 assert_select "note", :count => 0
882 get api_notes_path(:bbox => "5,5,5.1,5.1", :format => "gpx")
883 assert_response :success
884 assert_equal "application/gpx+xml", @response.media_type
885 assert_select "gpx", :count => 1 do
886 assert_select "wpt", :count => 0
890 def test_index_large_area
891 get api_notes_path(:bbox => "-2.5,-2.5,2.5,2.5", :format => :json)
892 assert_response :success
893 assert_equal "application/json", @response.media_type
895 get api_notes_path(:l => "-2.5", :b => "-2.5", :r => "2.5", :t => "2.5", :format => :json)
896 assert_response :success
897 assert_equal "application/json", @response.media_type
899 get api_notes_path(:bbox => "-10,-10,12,12", :format => :json)
900 assert_response :bad_request
901 assert_equal "text/plain", @response.media_type
903 get api_notes_path(:l => "-10", :b => "-10", :r => "12", :t => "12", :format => :json)
904 assert_response :bad_request
905 assert_equal "text/plain", @response.media_type
908 def test_index_closed
909 create(:note_with_comments, :closed, :closed_at => Time.now.utc - 5.days)
910 create(:note_with_comments, :closed, :closed_at => Time.now.utc - 100.days)
911 create(:note_with_comments, :status => "hidden")
912 create(:note_with_comments)
914 # Open notes + closed in last 7 days
915 get api_notes_path(:bbox => "1,1,1.7,1.7", :closed => "7", :format => "json")
916 assert_response :success
917 assert_equal "application/json", @response.media_type
918 js = ActiveSupport::JSON.decode(@response.body)
920 assert_equal "FeatureCollection", js["type"]
921 assert_equal 2, js["features"].count
924 get api_notes_path(:bbox => "1,1,1.7,1.7", :closed => "0", :format => "json")
925 assert_response :success
926 assert_equal "application/json", @response.media_type
927 js = ActiveSupport::JSON.decode(@response.body)
929 assert_equal "FeatureCollection", js["type"]
930 assert_equal 1, js["features"].count
932 # Open notes + all closed notes
933 get api_notes_path(:bbox => "1,1,1.7,1.7", :closed => "-1", :format => "json")
934 assert_response :success
935 assert_equal "application/json", @response.media_type
936 js = ActiveSupport::JSON.decode(@response.body)
938 assert_equal "FeatureCollection", js["type"]
939 assert_equal 3, js["features"].count
942 def test_index_bad_params
944 assert_response :bad_request
945 assert_equal "The parameter bbox is required", @response.body
947 get api_notes_path(:bbox => "-2.5,-2.5,2.5")
948 assert_response :bad_request
950 get api_notes_path(:bbox => "-2.5,-2.5,2.5,2.5,2.5")
951 assert_response :bad_request
953 get api_notes_path(:b => "-2.5", :r => "2.5", :t => "2.5")
954 assert_response :bad_request
956 get api_notes_path(:l => "-2.5", :r => "2.5", :t => "2.5")
957 assert_response :bad_request
959 get api_notes_path(:l => "-2.5", :b => "-2.5", :t => "2.5")
960 assert_response :bad_request
962 get api_notes_path(:l => "-2.5", :b => "-2.5", :r => "2.5")
963 assert_response :bad_request
965 get api_notes_path(:bbox => "1,1,1.7,1.7", :limit => "0", :format => "json")
966 assert_response :bad_request
968 get api_notes_path(:bbox => "1,1,1.7,1.7", :limit => Settings.max_note_query_limit + 1, :format => "json")
969 assert_response :bad_request
972 def test_search_success
973 create(:note_with_comments)
975 get search_api_notes_path(:q => "note comment", :format => "xml")
976 assert_response :success
977 assert_equal "application/xml", @response.media_type
978 assert_select "osm", :count => 1 do
979 assert_select "note", :count => 1
982 get search_api_notes_path(:q => "note comment", :format => "json")
983 assert_response :success
984 assert_equal "application/json", @response.media_type
985 js = ActiveSupport::JSON.decode(@response.body)
987 assert_equal "FeatureCollection", js["type"]
988 assert_equal 1, js["features"].count
990 get search_api_notes_path(:q => "note comment", :format => "rss")
991 assert_response :success
992 assert_equal "application/rss+xml", @response.media_type
993 assert_select "rss", :count => 1 do
994 assert_select "channel", :count => 1 do
995 assert_select "item", :count => 1
999 get search_api_notes_path(:q => "note comment", :format => "gpx")
1000 assert_response :success
1001 assert_equal "application/gpx+xml", @response.media_type
1002 assert_select "gpx", :count => 1 do
1003 assert_select "wpt", :count => 1
1006 get search_api_notes_path(:q => "note comment", :limit => Settings.max_note_query_limit, :format => "xml")
1007 assert_response :success
1010 def test_search_by_display_name_success
1011 user = create(:user)
1013 create(:note) do |note|
1014 create(:note_comment, :note => note, :author => user)
1017 get search_api_notes_path(:display_name => user.display_name, :format => "xml")
1018 assert_response :success
1019 assert_equal "application/xml", @response.media_type
1020 assert_select "osm", :count => 1 do
1021 assert_select "note", :count => 1
1024 get search_api_notes_path(:display_name => user.display_name, :format => "json")
1025 assert_response :success
1026 assert_equal "application/json", @response.media_type
1027 js = ActiveSupport::JSON.decode(@response.body)
1029 assert_equal "FeatureCollection", js["type"]
1030 assert_equal 1, js["features"].count
1032 get search_api_notes_path(:display_name => user.display_name, :format => "rss")
1033 assert_response :success
1034 assert_equal "application/rss+xml", @response.media_type
1035 assert_select "rss", :count => 1 do
1036 assert_select "channel", :count => 1 do
1037 assert_select "item", :count => 1
1041 get search_api_notes_path(:display_name => user.display_name, :format => "gpx")
1042 assert_response :success
1043 assert_equal "application/gpx+xml", @response.media_type
1044 assert_select "gpx", :count => 1 do
1045 assert_select "wpt", :count => 1
1049 def test_search_by_user_success
1050 user = create(:user)
1052 create(:note) do |note|
1053 create(:note_comment, :note => note, :author => user)
1056 get search_api_notes_path(:user => user.id, :format => "xml")
1057 assert_response :success
1058 assert_equal "application/xml", @response.media_type
1059 assert_select "osm", :count => 1 do
1060 assert_select "note", :count => 1
1063 get search_api_notes_path(:user => user.id, :format => "json")
1064 assert_response :success
1065 assert_equal "application/json", @response.media_type
1066 js = ActiveSupport::JSON.decode(@response.body)
1068 assert_equal "FeatureCollection", js["type"]
1069 assert_equal 1, js["features"].count
1071 get search_api_notes_path(:user => user.id, :format => "rss")
1072 assert_response :success
1073 assert_equal "application/rss+xml", @response.media_type
1074 assert_select "rss", :count => 1 do
1075 assert_select "channel", :count => 1 do
1076 assert_select "item", :count => 1
1080 get search_api_notes_path(:user => user.id, :format => "gpx")
1081 assert_response :success
1082 assert_equal "application/gpx+xml", @response.media_type
1083 assert_select "gpx", :count => 1 do
1084 assert_select "wpt", :count => 1
1087 user2 = create(:user)
1088 get search_api_notes_path(:user => user2.id, :format => "xml")
1089 assert_response :success
1090 assert_equal "application/xml", @response.media_type
1091 assert_select "osm", :count => 1 do
1092 assert_select "note", :count => 0
1096 def test_search_by_time_success
1097 note1 = create(:note, :created_at => "2020-02-01T00:00:00Z", :updated_at => "2020-04-01T00:00:00Z")
1098 note2 = create(:note, :created_at => "2020-03-01T00:00:00Z", :updated_at => "2020-05-01T00:00:00Z")
1100 get search_api_notes_path(:from => "2020-02-15T00:00:00Z", :to => "2020-04-15T00:00:00Z", :format => "xml")
1101 assert_response :success
1102 assert_equal "application/xml", @response.media_type
1103 assert_select "osm", :count => 1 do
1104 assert_select "note", :count => 1 do
1105 assert_select "id", note2.id.to_s
1109 get search_api_notes_path(:from => "2020-02-15T00:00:00Z", :to => "2020-04-15T00:00:00Z", :sort => "updated_at", :format => "xml")
1110 assert_response :success
1111 assert_equal "application/xml", @response.media_type
1112 assert_select "osm", :count => 1 do
1113 assert_select "note", :count => 1 do
1114 assert_select "id", note1.id.to_s
1119 def test_search_by_bbox_success
1120 notes = Array.new(5) do |i|
1121 position = ((1.0 + (i * 0.1)) * GeoRecord::SCALE).to_i
1122 create(:note_with_comments, :created_at => Time.parse("2020-01-01T00:00:00Z") + i.day, :latitude => position, :longitude => position)
1125 get search_api_notes_path(:bbox => "1.0,1.0,1.6,1.6", :sort => "created_at", :order => "oldest", :format => "xml")
1126 assert_response :success
1127 assert_equal "application/xml", @response.media_type
1128 assert_notes_in_order notes
1130 get search_api_notes_path(:bbox => "1.25,1.25,1.45,1.45", :sort => "created_at", :order => "oldest", :format => "xml")
1131 assert_response :success
1132 assert_equal "application/xml", @response.media_type
1133 assert_notes_in_order [notes[3], notes[4]]
1135 get search_api_notes_path(:bbox => "2.0,2.0,2.5,2.5", :sort => "created_at", :order => "oldest", :format => "xml")
1136 assert_response :success
1137 assert_equal "application/xml", @response.media_type
1138 assert_notes_in_order []
1141 def test_search_no_match
1142 create(:note_with_comments)
1144 get search_api_notes_path(:q => "no match", :format => "xml")
1145 assert_response :success
1146 assert_equal "application/xml", @response.media_type
1147 assert_select "osm", :count => 1 do
1148 assert_select "note", :count => 0
1151 get search_api_notes_path(:q => "no match", :format => "json")
1152 assert_response :success
1153 assert_equal "application/json", @response.media_type
1154 js = ActiveSupport::JSON.decode(@response.body)
1156 assert_equal "FeatureCollection", js["type"]
1157 assert_equal 0, js["features"].count
1159 get search_api_notes_path(:q => "no match", :format => "rss")
1160 assert_response :success
1161 assert_equal "application/rss+xml", @response.media_type
1162 assert_select "rss", :count => 1 do
1163 assert_select "channel", :count => 1 do
1164 assert_select "item", :count => 0
1168 get search_api_notes_path(:q => "no match", :format => "gpx")
1169 assert_response :success
1170 assert_equal "application/gpx+xml", @response.media_type
1171 assert_select "gpx", :count => 1 do
1172 assert_select "wpt", :count => 0
1176 def test_search_by_time_no_match
1177 create(:note_with_comments)
1179 get search_api_notes_path(:from => "01.01.2010", :to => "01.10.2010", :format => "xml")
1180 assert_response :success
1181 assert_equal "application/xml", @response.media_type
1182 assert_select "osm", :count => 1 do
1183 assert_select "note", :count => 0
1186 get search_api_notes_path(:from => "01.01.2010", :to => "01.10.2010", :format => "json")
1187 assert_response :success
1188 assert_equal "application/json", @response.media_type
1189 js = ActiveSupport::JSON.decode(@response.body)
1191 assert_equal "FeatureCollection", js["type"]
1192 assert_equal 0, js["features"].count
1194 get search_api_notes_path(:from => "01.01.2010", :to => "01.10.2010", :format => "rss")
1195 assert_response :success
1196 assert_equal "application/rss+xml", @response.media_type
1197 assert_select "rss", :count => 1 do
1198 assert_select "channel", :count => 1 do
1199 assert_select "item", :count => 0
1203 get search_api_notes_path(:from => "01.01.2010", :to => "01.10.2010", :format => "gpx")
1204 assert_response :success
1205 assert_equal "application/gpx+xml", @response.media_type
1206 assert_select "gpx", :count => 1 do
1207 assert_select "wpt", :count => 0
1211 def test_search_bad_params
1212 get search_api_notes_path(:q => "no match", :limit => "0", :format => "json")
1213 assert_response :bad_request
1215 get search_api_notes_path(:q => "no match", :limit => Settings.max_note_query_limit + 1, :format => "json")
1216 assert_response :bad_request
1218 get search_api_notes_path(:display_name => "non-existent")
1219 assert_response :bad_request
1221 get search_api_notes_path(:user => "-1")
1222 assert_response :bad_request
1224 get search_api_notes_path(:from => "wrong-date", :to => "wrong-date")
1225 assert_response :bad_request
1227 get search_api_notes_path(:from => "01.01.2010", :to => "2010.01.2010")
1228 assert_response :bad_request
1231 def test_feed_success
1232 position = (1.1 * GeoRecord::SCALE).to_i
1233 create(:note_with_comments, :latitude => position, :longitude => position)
1234 create(:note_with_comments, :latitude => position, :longitude => position)
1235 position = (1.5 * GeoRecord::SCALE).to_i
1236 create(:note_with_comments, :latitude => position, :longitude => position)
1237 create(:note_with_comments, :latitude => position, :longitude => position)
1239 get feed_api_notes_path(:format => "rss")
1240 assert_response :success
1241 assert_equal "application/rss+xml", @response.media_type
1242 assert_select "rss", :count => 1 do
1243 assert_select "channel", :count => 1 do
1244 assert_select "item", :count => 4
1248 get feed_api_notes_path(:bbox => "1,1,1.2,1.2", :format => "rss")
1249 assert_response :success
1250 assert_equal "application/rss+xml", @response.media_type
1251 assert_select "rss", :count => 1 do
1252 assert_select "channel", :count => 1 do
1253 assert_select "description", :text => /1\.2/, :count => 1
1254 assert_select "item", :count => 2
1258 get feed_api_notes_path(:bbox => "1,1,1.2,1.2", :limit => Settings.max_note_query_limit, :format => "rss")
1259 assert_response :success
1263 get feed_api_notes_path(:bbox => "1,1,1.2", :format => "rss")
1264 assert_response :bad_request
1266 get feed_api_notes_path(:bbox => "1,1,1.2,1.2,1.2", :format => "rss")
1267 assert_response :bad_request
1269 get feed_api_notes_path(:bbox => "1,1,1.2,1.2", :limit => "0", :format => "rss")
1270 assert_response :bad_request
1272 get feed_api_notes_path(:bbox => "1,1,1.2,1.2", :limit => Settings.max_note_query_limit + 1, :format => "rss")
1273 assert_response :bad_request
1278 def assert_notes_in_order(notes)
1279 assert_select "osm>note", notes.size
1280 notes.each_with_index do |note, index|
1281 assert_select "osm>note:nth-child(#{index + 1})>id", :text => note.id.to_s, :count => 1
1285 def coordinates_inside_seville_cathedral
1286 Struct.new(:lat, :lon).new(37.385972, -5.993149)