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 here. Please either sign in or create an OpenStreetMap account", 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, :author => create(:user))
505 create(:note_comment, :note => open_note_with_comment, :author => create(:user))
508 post close_api_note_path(open_note_with_comment, :text => "This is a close comment", :format => "json")
509 assert_response :unauthorized
511 auth_header = bearer_authorization_header user
513 assert_difference "NoteSubscription.count", 1 do
514 post close_api_note_path(open_note_with_comment, :text => "This is a close comment", :format => "json"), :headers => auth_header
516 assert_response :success
517 js = ActiveSupport::JSON.decode(@response.body)
519 assert_equal "Feature", js["type"]
520 assert_equal open_note_with_comment.id, js["properties"]["id"]
521 assert_equal "closed", js["properties"]["status"]
522 assert_equal 3, js["properties"]["comments"].count
523 assert_equal "closed", js["properties"]["comments"].last["action"]
524 assert_equal "This is a close comment", js["properties"]["comments"].last["text"]
525 assert_equal user.display_name, js["properties"]["comments"].last["user"]
527 subscription = NoteSubscription.last
528 assert_equal user, subscription.user
529 assert_equal open_note_with_comment, subscription.note
531 get api_note_path(open_note_with_comment.id, :format => "json")
532 assert_response :success
533 js = ActiveSupport::JSON.decode(@response.body)
535 assert_equal "Feature", js["type"]
536 assert_equal open_note_with_comment.id, js["properties"]["id"]
537 assert_equal "closed", js["properties"]["status"]
538 assert_equal 3, js["properties"]["comments"].count
539 assert_equal "closed", js["properties"]["comments"].last["action"]
540 assert_equal "This is a close comment", js["properties"]["comments"].last["text"]
541 assert_equal user.display_name, js["properties"]["comments"].last["user"]
545 post close_api_note_path(12345)
546 assert_response :unauthorized
548 auth_header = bearer_authorization_header
550 post close_api_note_path(12345), :headers => auth_header
551 assert_response :not_found
553 hidden_note_with_comment = create(:note_with_comments, :status => "hidden")
555 post close_api_note_path(hidden_note_with_comment), :headers => auth_header
556 assert_response :gone
558 closed_note_with_comment = create(:note_with_comments, :closed)
560 post close_api_note_path(closed_note_with_comment), :headers => auth_header
561 assert_response :conflict
564 def test_reopen_success
565 closed_note_with_comment = create(:note_with_comments, :closed, :author => create(:user), :closed_by => create(:user))
568 post reopen_api_note_path(closed_note_with_comment, :text => "This is a reopen comment", :format => "json")
569 assert_response :unauthorized
571 auth_header = bearer_authorization_header user
573 assert_difference "NoteSubscription.count", 1 do
574 post reopen_api_note_path(closed_note_with_comment, :text => "This is a reopen comment", :format => "json"), :headers => auth_header
576 assert_response :success
577 js = ActiveSupport::JSON.decode(@response.body)
579 assert_equal "Feature", js["type"]
580 assert_equal closed_note_with_comment.id, js["properties"]["id"]
581 assert_equal "open", js["properties"]["status"]
582 assert_equal 3, js["properties"]["comments"].count
583 assert_equal "reopened", js["properties"]["comments"].last["action"]
584 assert_equal "This is a reopen comment", js["properties"]["comments"].last["text"]
585 assert_equal user.display_name, js["properties"]["comments"].last["user"]
587 subscription = NoteSubscription.last
588 assert_equal user, subscription.user
589 assert_equal closed_note_with_comment, subscription.note
591 get api_note_path(closed_note_with_comment, :format => "json")
592 assert_response :success
593 js = ActiveSupport::JSON.decode(@response.body)
595 assert_equal "Feature", js["type"]
596 assert_equal closed_note_with_comment.id, js["properties"]["id"]
597 assert_equal "open", js["properties"]["status"]
598 assert_equal 3, js["properties"]["comments"].count
599 assert_equal "reopened", js["properties"]["comments"].last["action"]
600 assert_equal "This is a reopen comment", js["properties"]["comments"].last["text"]
601 assert_equal user.display_name, js["properties"]["comments"].last["user"]
605 hidden_note_with_comment = create(:note_with_comments, :status => "hidden")
607 post reopen_api_note_path(hidden_note_with_comment)
608 assert_response :unauthorized
610 auth_header = bearer_authorization_header
612 post reopen_api_note_path(12345), :headers => auth_header
613 assert_response :not_found
615 post reopen_api_note_path(hidden_note_with_comment), :headers => auth_header
616 assert_response :gone
618 open_note_with_comment = create(:note_with_comments)
620 post reopen_api_note_path(open_note_with_comment), :headers => auth_header
621 assert_response :conflict
624 def test_show_success
625 open_note = create(:note_with_comments, :author => create(:user))
626 create(:note_comment, :note => open_note, :author => create(:user))
627 create(:note_comment, :note => open_note, :author => create(:user))
629 get api_note_path(open_note, :format => "xml")
630 assert_response :success
631 assert_equal "application/xml", @response.media_type
632 assert_select "osm", :count => 1 do
633 assert_select "note[lat='#{open_note.lat}'][lon='#{open_note.lon}']", :count => 1 do
634 assert_select "id", open_note.id.to_s
635 assert_select "url", api_note_url(open_note, :format => "xml")
636 assert_select "comment_url", comment_api_note_url(open_note, :format => "xml")
637 assert_select "close_url", close_api_note_url(open_note, :format => "xml")
638 assert_select "date_created", open_note.created_at.to_s
639 assert_select "status", open_note.status
640 assert_select "comments", :count => 1 do
641 assert_select "comment", :count => 3
646 get api_note_path(open_note, :format => "rss")
647 assert_response :success
648 assert_equal "application/rss+xml", @response.media_type
649 assert_select "rss", :count => 1 do
650 assert_select "channel", :count => 1 do
651 assert_select "item", :count => 1 do
652 assert_select "link", note_url(open_note)
653 assert_select "guid", api_note_url(open_note)
654 assert_select "pubDate", open_note.created_at.to_fs(:rfc822)
655 assert_select "geo|lat", open_note.lat.to_s
656 assert_select "geo|long", open_note.lon.to_s
657 assert_select "georss|point", "#{open_note.lon} #{open_note.lon}"
662 get api_note_path(open_note, :format => "json")
663 assert_response :success
664 assert_equal "application/json", @response.media_type
665 js = ActiveSupport::JSON.decode(@response.body)
667 assert_equal "Feature", js["type"]
668 assert_equal "Point", js["geometry"]["type"]
669 assert_equal open_note.lat, js["geometry"]["coordinates"][0]
670 assert_equal open_note.lon, js["geometry"]["coordinates"][1]
671 assert_equal open_note.id, js["properties"]["id"]
672 assert_equal api_note_url(open_note, :format => "json"), js["properties"]["url"]
673 assert_equal comment_api_note_url(open_note, :format => "json"), js["properties"]["comment_url"]
674 assert_equal close_api_note_url(open_note, :format => "json"), js["properties"]["close_url"]
675 assert_equal open_note.created_at.to_s, js["properties"]["date_created"]
676 assert_equal open_note.status, js["properties"]["status"]
678 get api_note_path(open_note, :format => "gpx")
679 assert_response :success
680 assert_equal "application/gpx+xml", @response.media_type
681 assert_select "gpx", :count => 1 do
682 assert_select "wpt[lat='#{open_note.lat}'][lon='#{open_note.lon}']", :count => 1 do
683 assert_select "time", :count => 1
684 assert_select "name", "Note: #{open_note.id}"
685 assert_select "desc", :count => 1
686 assert_select "link[href='http://www.example.com/note/#{open_note.id}']", :count => 1
687 assert_select "extensions", :count => 1 do
688 assert_select "id", open_note.id.to_s
689 assert_select "url", api_note_url(open_note, :format => "gpx")
690 assert_select "comment_url", comment_api_note_url(open_note, :format => "gpx")
691 assert_select "close_url", close_api_note_url(open_note, :format => "gpx")
697 def test_show_hidden_comment
698 note_with_hidden_comment = create(:note) do |note|
699 create(:note_comment, :note => note, :body => "Valid comment for hidden note")
700 create(:note_comment, :note => note, :visible => false)
701 create(:note_comment, :note => note, :body => "Another valid comment for hidden note")
704 get api_note_path(note_with_hidden_comment, :format => "json")
705 assert_response :success
706 js = ActiveSupport::JSON.decode(@response.body)
708 assert_equal "Feature", js["type"]
709 assert_equal note_with_hidden_comment.id, js["properties"]["id"]
710 assert_equal 2, js["properties"]["comments"].count
711 assert_equal "Valid comment for hidden note", js["properties"]["comments"][0]["text"]
712 assert_equal "Another valid comment for hidden note", js["properties"]["comments"][1]["text"]
716 get api_note_path(12345)
717 assert_response :not_found
719 get api_note_path(create(:note, :status => "hidden"))
720 assert_response :gone
723 def test_destroy_success
724 open_note_with_comment = create(:note_with_comments, :author => create(:user))
725 create(:note_comment, :note => open_note_with_comment, :author => create(:user))
727 moderator_user = create(:moderator_user)
729 delete api_note_path(open_note_with_comment, :text => "This is a hide comment", :format => "json")
730 assert_response :unauthorized
732 auth_header = bearer_authorization_header user
734 delete api_note_path(open_note_with_comment, :text => "This is a hide comment", :format => "json"), :headers => auth_header
735 assert_response :forbidden
737 auth_header = bearer_authorization_header moderator_user
739 delete api_note_path(open_note_with_comment, :text => "This is a hide comment", :format => "json"), :headers => auth_header
740 assert_response :success
741 js = ActiveSupport::JSON.decode(@response.body)
743 assert_equal "Feature", js["type"]
744 assert_equal open_note_with_comment.id, js["properties"]["id"]
745 assert_equal "hidden", js["properties"]["status"]
746 assert_equal 3, js["properties"]["comments"].count
747 assert_equal "hidden", js["properties"]["comments"].last["action"]
748 assert_equal "This is a hide comment", js["properties"]["comments"].last["text"]
749 assert_equal moderator_user.display_name, js["properties"]["comments"].last["user"]
751 get api_note_path(open_note_with_comment, :format => "json"), :headers => auth_header
752 assert_response :success
754 auth_header = bearer_authorization_header user
756 get api_note_path(open_note_with_comment, :format => "json"), :headers => auth_header
757 assert_response :gone
760 def test_destroy_fail
762 moderator_user = create(:moderator_user)
764 delete api_note_path(12345, :format => "json")
765 assert_response :unauthorized
767 auth_header = bearer_authorization_header user
769 delete api_note_path(12345, :format => "json"), :headers => auth_header
770 assert_response :forbidden
772 auth_header = bearer_authorization_header moderator_user
774 delete api_note_path(12345, :format => "json"), :headers => auth_header
775 assert_response :not_found
777 hidden_note_with_comment = create(:note_with_comments, :status => "hidden")
779 delete api_note_path(hidden_note_with_comment, :format => "json"), :headers => auth_header
780 assert_response :gone
783 def test_index_success
784 position = (1.1 * GeoRecord::SCALE).to_i
785 create(:note_with_comments, :author => create(:user), :latitude => position, :longitude => position)
786 create(:note_with_comments, :author => create(:user), :latitude => position, :longitude => position)
787 create(:note_with_comments, :author => create(:user), :latitude => position, :longitude => position)
789 get api_notes_path(:bbox => "1,1,1.2,1.2", :format => "rss")
790 assert_response :success
791 assert_equal "application/rss+xml", @response.media_type
792 assert_select "rss", :count => 1 do
793 assert_select "channel", :count => 1 do
794 assert_select "description", :text => /1\.2/, :count => 1
795 assert_select "item", :count => 3
799 get api_notes_path(:bbox => "1,1,1.2,1.2", :format => "json")
800 assert_response :success
801 assert_equal "application/json", @response.media_type
802 js = ActiveSupport::JSON.decode(@response.body)
804 assert_equal "FeatureCollection", js["type"]
805 assert_equal 3, js["features"].count
807 get api_notes_path(:bbox => "1,1,1.2,1.2", :format => "xml")
808 assert_response :success
809 assert_equal "application/xml", @response.media_type
810 assert_select "osm", :count => 1 do
811 assert_select "note", :count => 3
814 get api_notes_path(:bbox => "1,1,1.2,1.2", :format => "gpx")
815 assert_response :success
816 assert_equal "application/gpx+xml", @response.media_type
817 assert_select "gpx", :count => 1 do
818 assert_select "wpt", :count => 3
823 position = (1.1 * GeoRecord::SCALE).to_i
824 create(:note_with_comments, :latitude => position, :longitude => position)
825 create(:note_with_comments, :latitude => position, :longitude => position)
827 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => 1, :format => "rss")
828 assert_response :success
829 assert_equal "application/rss+xml", @response.media_type
830 assert_select "rss", :count => 1 do
831 assert_select "channel", :count => 1 do
832 assert_select "item", :count => 1
836 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => 1, :format => "json")
837 assert_response :success
838 assert_equal "application/json", @response.media_type
839 js = ActiveSupport::JSON.decode(@response.body)
841 assert_equal "FeatureCollection", js["type"]
842 assert_equal 1, js["features"].count
844 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => 1, :format => "xml")
845 assert_response :success
846 assert_equal "application/xml", @response.media_type
847 assert_select "osm", :count => 1 do
848 assert_select "note", :count => 1
851 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => 1, :format => "gpx")
852 assert_response :success
853 assert_equal "application/gpx+xml", @response.media_type
854 assert_select "gpx", :count => 1 do
855 assert_select "wpt", :count => 1
858 get api_notes_path(:bbox => "1,1,1.2,1.2", :limit => Settings.max_note_query_limit, :format => "rss")
859 assert_response :success
862 def test_index_empty_area
863 get api_notes_path(:bbox => "5,5,5.1,5.1", :format => "rss")
864 assert_response :success
865 assert_equal "application/rss+xml", @response.media_type
866 assert_select "rss", :count => 1 do
867 assert_select "channel", :count => 1 do
868 assert_select "item", :count => 0
872 get api_notes_path(:bbox => "5,5,5.1,5.1", :format => "json")
873 assert_response :success
874 assert_equal "application/json", @response.media_type
875 js = ActiveSupport::JSON.decode(@response.body)
877 assert_equal "FeatureCollection", js["type"]
878 assert_equal 0, js["features"].count
880 get api_notes_path(:bbox => "5,5,5.1,5.1", :format => "xml")
881 assert_response :success
882 assert_equal "application/xml", @response.media_type
883 assert_select "osm", :count => 1 do
884 assert_select "note", :count => 0
887 get api_notes_path(:bbox => "5,5,5.1,5.1", :format => "gpx")
888 assert_response :success
889 assert_equal "application/gpx+xml", @response.media_type
890 assert_select "gpx", :count => 1 do
891 assert_select "wpt", :count => 0
895 def test_index_large_area
896 get api_notes_path(:bbox => "-2.5,-2.5,2.5,2.5", :format => :json)
897 assert_response :success
898 assert_equal "application/json", @response.media_type
900 get api_notes_path(:l => "-2.5", :b => "-2.5", :r => "2.5", :t => "2.5", :format => :json)
901 assert_response :success
902 assert_equal "application/json", @response.media_type
904 get api_notes_path(:bbox => "-10,-10,12,12", :format => :json)
905 assert_response :bad_request
906 assert_equal "text/plain", @response.media_type
908 get api_notes_path(:l => "-10", :b => "-10", :r => "12", :t => "12", :format => :json)
909 assert_response :bad_request
910 assert_equal "text/plain", @response.media_type
913 def test_index_closed
914 create(:note_with_comments, :closed, :closed_at => Time.now.utc - 5.days)
915 create(:note_with_comments, :closed, :closed_at => Time.now.utc - 100.days)
916 create(:note_with_comments, :status => "hidden")
917 create(:note_with_comments)
919 # Open notes + closed in last 7 days
920 get api_notes_path(:bbox => "1,1,1.7,1.7", :closed => "7", :format => "json")
921 assert_response :success
922 assert_equal "application/json", @response.media_type
923 js = ActiveSupport::JSON.decode(@response.body)
925 assert_equal "FeatureCollection", js["type"]
926 assert_equal 2, js["features"].count
929 get api_notes_path(:bbox => "1,1,1.7,1.7", :closed => "0", :format => "json")
930 assert_response :success
931 assert_equal "application/json", @response.media_type
932 js = ActiveSupport::JSON.decode(@response.body)
934 assert_equal "FeatureCollection", js["type"]
935 assert_equal 1, js["features"].count
937 # Open notes + all closed notes
938 get api_notes_path(:bbox => "1,1,1.7,1.7", :closed => "-1", :format => "json")
939 assert_response :success
940 assert_equal "application/json", @response.media_type
941 js = ActiveSupport::JSON.decode(@response.body)
943 assert_equal "FeatureCollection", js["type"]
944 assert_equal 3, js["features"].count
947 def test_index_bad_params
949 assert_response :bad_request
950 assert_equal "The parameter bbox is required", @response.body
952 get api_notes_path(:bbox => "-2.5,-2.5,2.5")
953 assert_response :bad_request
955 get api_notes_path(:bbox => "-2.5,-2.5,2.5,2.5,2.5")
956 assert_response :bad_request
958 get api_notes_path(:b => "-2.5", :r => "2.5", :t => "2.5")
959 assert_response :bad_request
961 get api_notes_path(:l => "-2.5", :r => "2.5", :t => "2.5")
962 assert_response :bad_request
964 get api_notes_path(:l => "-2.5", :b => "-2.5", :t => "2.5")
965 assert_response :bad_request
967 get api_notes_path(:l => "-2.5", :b => "-2.5", :r => "2.5")
968 assert_response :bad_request
970 get api_notes_path(:bbox => "1,1,1.7,1.7", :limit => "0", :format => "json")
971 assert_response :bad_request
973 get api_notes_path(:bbox => "1,1,1.7,1.7", :limit => Settings.max_note_query_limit + 1, :format => "json")
974 assert_response :bad_request
977 def test_search_success
978 create(:note_with_comments, :author => create(:user))
979 create(:note_with_comments, :author => create(:user))
980 create(:note_with_comments, :author => create(:user))
982 get search_api_notes_path(:q => "note comment", :format => "xml")
983 assert_response :success
984 assert_equal "application/xml", @response.media_type
985 assert_select "osm", :count => 1 do
986 assert_select "note", :count => 3
989 get search_api_notes_path(:q => "note comment", :format => "json")
990 assert_response :success
991 assert_equal "application/json", @response.media_type
992 js = ActiveSupport::JSON.decode(@response.body)
994 assert_equal "FeatureCollection", js["type"]
995 assert_equal 3, js["features"].count
997 get search_api_notes_path(:q => "note comment", :format => "rss")
998 assert_response :success
999 assert_equal "application/rss+xml", @response.media_type
1000 assert_select "rss", :count => 1 do
1001 assert_select "channel", :count => 1 do
1002 assert_select "item", :count => 3
1006 get search_api_notes_path(:q => "note comment", :format => "gpx")
1007 assert_response :success
1008 assert_equal "application/gpx+xml", @response.media_type
1009 assert_select "gpx", :count => 1 do
1010 assert_select "wpt", :count => 3
1013 get search_api_notes_path(:q => "note comment", :limit => Settings.max_note_query_limit, :format => "xml")
1014 assert_response :success
1017 def test_search_by_display_name_success
1018 user = create(:user)
1020 create(:note) do |note|
1021 create(:note_comment, :note => note, :author => user)
1024 get search_api_notes_path(:display_name => user.display_name, :format => "xml")
1025 assert_response :success
1026 assert_equal "application/xml", @response.media_type
1027 assert_select "osm", :count => 1 do
1028 assert_select "note", :count => 1
1031 get search_api_notes_path(:display_name => user.display_name, :format => "json")
1032 assert_response :success
1033 assert_equal "application/json", @response.media_type
1034 js = ActiveSupport::JSON.decode(@response.body)
1036 assert_equal "FeatureCollection", js["type"]
1037 assert_equal 1, js["features"].count
1039 get search_api_notes_path(:display_name => user.display_name, :format => "rss")
1040 assert_response :success
1041 assert_equal "application/rss+xml", @response.media_type
1042 assert_select "rss", :count => 1 do
1043 assert_select "channel", :count => 1 do
1044 assert_select "item", :count => 1
1048 get search_api_notes_path(:display_name => user.display_name, :format => "gpx")
1049 assert_response :success
1050 assert_equal "application/gpx+xml", @response.media_type
1051 assert_select "gpx", :count => 1 do
1052 assert_select "wpt", :count => 1
1056 def test_search_by_user_success
1057 user = create(:user)
1059 create(:note) do |note|
1060 create(:note_comment, :note => note, :author => user)
1063 get search_api_notes_path(:user => user.id, :format => "xml")
1064 assert_response :success
1065 assert_equal "application/xml", @response.media_type
1066 assert_select "osm", :count => 1 do
1067 assert_select "note", :count => 1
1070 get search_api_notes_path(:user => user.id, :format => "json")
1071 assert_response :success
1072 assert_equal "application/json", @response.media_type
1073 js = ActiveSupport::JSON.decode(@response.body)
1075 assert_equal "FeatureCollection", js["type"]
1076 assert_equal 1, js["features"].count
1078 get search_api_notes_path(:user => user.id, :format => "rss")
1079 assert_response :success
1080 assert_equal "application/rss+xml", @response.media_type
1081 assert_select "rss", :count => 1 do
1082 assert_select "channel", :count => 1 do
1083 assert_select "item", :count => 1
1087 get search_api_notes_path(:user => user.id, :format => "gpx")
1088 assert_response :success
1089 assert_equal "application/gpx+xml", @response.media_type
1090 assert_select "gpx", :count => 1 do
1091 assert_select "wpt", :count => 1
1094 user2 = create(:user)
1095 get search_api_notes_path(:user => user2.id, :format => "xml")
1096 assert_response :success
1097 assert_equal "application/xml", @response.media_type
1098 assert_select "osm", :count => 1 do
1099 assert_select "note", :count => 0
1103 def test_search_by_time_success
1104 note1 = create(:note, :created_at => "2020-02-01T00:00:00Z", :updated_at => "2020-04-01T00:00:00Z")
1105 note2 = create(:note, :created_at => "2020-03-01T00:00:00Z", :updated_at => "2020-05-01T00:00:00Z")
1107 get search_api_notes_path(:from => "2020-02-15T00:00:00Z", :to => "2020-04-15T00:00:00Z", :format => "xml")
1108 assert_response :success
1109 assert_equal "application/xml", @response.media_type
1110 assert_select "osm", :count => 1 do
1111 assert_select "note", :count => 1 do
1112 assert_select "id", note2.id.to_s
1116 get search_api_notes_path(:from => "2020-02-15T00:00:00Z", :to => "2020-04-15T00:00:00Z", :sort => "updated_at", :format => "xml")
1117 assert_response :success
1118 assert_equal "application/xml", @response.media_type
1119 assert_select "osm", :count => 1 do
1120 assert_select "note", :count => 1 do
1121 assert_select "id", note1.id.to_s
1126 def test_search_by_bbox_success
1127 notes = Array.new(5) do |i|
1128 position = ((1.0 + (i * 0.1)) * GeoRecord::SCALE).to_i
1129 create(:note_with_comments, :created_at => Time.parse("2020-01-01T00:00:00Z") + i.day, :latitude => position, :longitude => position)
1132 get search_api_notes_path(:bbox => "1.0,1.0,1.6,1.6", :sort => "created_at", :order => "oldest", :format => "xml")
1133 assert_response :success
1134 assert_equal "application/xml", @response.media_type
1135 assert_notes_in_order notes
1137 get search_api_notes_path(:bbox => "1.25,1.25,1.45,1.45", :sort => "created_at", :order => "oldest", :format => "xml")
1138 assert_response :success
1139 assert_equal "application/xml", @response.media_type
1140 assert_notes_in_order [notes[3], notes[4]]
1142 get search_api_notes_path(:bbox => "2.0,2.0,2.5,2.5", :sort => "created_at", :order => "oldest", :format => "xml")
1143 assert_response :success
1144 assert_equal "application/xml", @response.media_type
1145 assert_notes_in_order []
1148 def test_search_no_match
1149 create(:note_with_comments)
1151 get search_api_notes_path(:q => "no match", :format => "xml")
1152 assert_response :success
1153 assert_equal "application/xml", @response.media_type
1154 assert_select "osm", :count => 1 do
1155 assert_select "note", :count => 0
1158 get search_api_notes_path(:q => "no match", :format => "json")
1159 assert_response :success
1160 assert_equal "application/json", @response.media_type
1161 js = ActiveSupport::JSON.decode(@response.body)
1163 assert_equal "FeatureCollection", js["type"]
1164 assert_equal 0, js["features"].count
1166 get search_api_notes_path(:q => "no match", :format => "rss")
1167 assert_response :success
1168 assert_equal "application/rss+xml", @response.media_type
1169 assert_select "rss", :count => 1 do
1170 assert_select "channel", :count => 1 do
1171 assert_select "item", :count => 0
1175 get search_api_notes_path(:q => "no match", :format => "gpx")
1176 assert_response :success
1177 assert_equal "application/gpx+xml", @response.media_type
1178 assert_select "gpx", :count => 1 do
1179 assert_select "wpt", :count => 0
1183 def test_search_by_time_no_match
1184 create(:note_with_comments)
1186 get search_api_notes_path(:from => "01.01.2010", :to => "01.10.2010", :format => "xml")
1187 assert_response :success
1188 assert_equal "application/xml", @response.media_type
1189 assert_select "osm", :count => 1 do
1190 assert_select "note", :count => 0
1193 get search_api_notes_path(:from => "01.01.2010", :to => "01.10.2010", :format => "json")
1194 assert_response :success
1195 assert_equal "application/json", @response.media_type
1196 js = ActiveSupport::JSON.decode(@response.body)
1198 assert_equal "FeatureCollection", js["type"]
1199 assert_equal 0, js["features"].count
1201 get search_api_notes_path(:from => "01.01.2010", :to => "01.10.2010", :format => "rss")
1202 assert_response :success
1203 assert_equal "application/rss+xml", @response.media_type
1204 assert_select "rss", :count => 1 do
1205 assert_select "channel", :count => 1 do
1206 assert_select "item", :count => 0
1210 get search_api_notes_path(:from => "01.01.2010", :to => "01.10.2010", :format => "gpx")
1211 assert_response :success
1212 assert_equal "application/gpx+xml", @response.media_type
1213 assert_select "gpx", :count => 1 do
1214 assert_select "wpt", :count => 0
1218 def test_search_bad_params
1219 get search_api_notes_path(:q => "no match", :limit => "0", :format => "json")
1220 assert_response :bad_request
1222 get search_api_notes_path(:q => "no match", :limit => Settings.max_note_query_limit + 1, :format => "json")
1223 assert_response :bad_request
1225 get search_api_notes_path(:display_name => "non-existent")
1226 assert_response :bad_request
1228 get search_api_notes_path(:user => "-1")
1229 assert_response :bad_request
1231 get search_api_notes_path(:from => "wrong-date", :to => "wrong-date")
1232 assert_response :bad_request
1234 get search_api_notes_path(:from => "01.01.2010", :to => "2010.01.2010")
1235 assert_response :bad_request
1238 def test_feed_success
1239 position = (1.1 * GeoRecord::SCALE).to_i
1240 create(:note_with_comments, :latitude => position, :longitude => position)
1241 create(:note_with_comments, :latitude => position, :longitude => position)
1242 position = (1.5 * GeoRecord::SCALE).to_i
1243 create(:note_with_comments, :latitude => position, :longitude => position)
1244 create(:note_with_comments, :latitude => position, :longitude => position)
1246 get feed_api_notes_path(:format => "rss")
1247 assert_response :success
1248 assert_equal "application/rss+xml", @response.media_type
1249 assert_select "rss", :count => 1 do
1250 assert_select "channel", :count => 1 do
1251 assert_select "item", :count => 4
1255 get feed_api_notes_path(:bbox => "1,1,1.2,1.2", :format => "rss")
1256 assert_response :success
1257 assert_equal "application/rss+xml", @response.media_type
1258 assert_select "rss", :count => 1 do
1259 assert_select "channel", :count => 1 do
1260 assert_select "description", :text => /1\.2/, :count => 1
1261 assert_select "item", :count => 2
1265 get feed_api_notes_path(:bbox => "1,1,1.2,1.2", :limit => Settings.max_note_query_limit, :format => "rss")
1266 assert_response :success
1270 get feed_api_notes_path(:bbox => "1,1,1.2", :format => "rss")
1271 assert_response :bad_request
1273 get feed_api_notes_path(:bbox => "1,1,1.2,1.2,1.2", :format => "rss")
1274 assert_response :bad_request
1276 get feed_api_notes_path(:bbox => "1,1,1.2,1.2", :limit => "0", :format => "rss")
1277 assert_response :bad_request
1279 get feed_api_notes_path(:bbox => "1,1,1.2,1.2", :limit => Settings.max_note_query_limit + 1, :format => "rss")
1280 assert_response :bad_request
1285 def assert_notes_in_order(notes)
1286 assert_select "osm>note", notes.size
1287 notes.each_with_index do |note, index|
1288 assert_select "osm>note:nth-child(#{index + 1})>id", :text => note.id.to_s, :count => 1
1292 def coordinates_inside_seville_cathedral
1293 Struct.new(:lat, :lon).new(37.385972, -5.993149)