1 require File.dirname(__FILE__) + '/../test_helper'
3 class TraceControllerTest < ActionController::TestCase
4 fixtures :users, :gpx_files
5 set_fixture_class :gpx_files => 'Trace'
8 @gpx_trace_dir = Object.send("remove_const", "GPX_TRACE_DIR")
9 Object.const_set("GPX_TRACE_DIR", File.dirname(__FILE__) + "/../traces")
13 Object.send("remove_const", "GPX_TRACE_DIR")
14 Object.const_set("GPX_TRACE_DIR", @gpx_trace_dir)
18 # test all routes which lead to this controller
21 { :path => "/api/0.6/gpx/create", :method => :post },
22 { :controller => "trace", :action => "api_create" }
25 { :path => "/api/0.6/gpx/1", :method => :get },
26 { :controller => "trace", :action => "api_read", :id => "1" }
29 { :path => "/api/0.6/gpx/1", :method => :put },
30 { :controller => "trace", :action => "api_update", :id => "1" }
33 { :path => "/api/0.6/gpx/1", :method => :delete },
34 { :controller => "trace", :action => "api_delete", :id => "1" }
37 { :controller => "trace", :action => "api_read", :id => "1" },
38 { :path => "/api/0.6/gpx/1/details", :method => :get }
41 { :path => "/api/0.6/gpx/1/data", :method => :get },
42 { :controller => "trace", :action => "api_data", :id => "1" }
45 { :path => "/api/0.6/gpx/1/data.xml", :method => :get },
46 { :controller => "trace", :action => "api_data", :id => "1", :format => "xml" }
50 { :path => "/traces", :method => :get },
51 { :controller => "trace", :action => "list" }
54 { :path => "/traces/page/1", :method => :get },
55 { :controller => "trace", :action => "list", :page => "1" }
58 { :path => "/traces/tag/tagname", :method => :get },
59 { :controller => "trace", :action => "list", :tag => "tagname" }
62 { :path => "/traces/tag/tagname/page/1", :method => :get },
63 { :controller => "trace", :action => "list", :tag => "tagname", :page => "1" }
66 { :path => "/user/username/traces", :method => :get },
67 { :controller => "trace", :action => "list", :display_name => "username" }
70 { :path => "/user/username/traces/page/1", :method => :get },
71 { :controller => "trace", :action => "list", :display_name => "username", :page => "1" }
74 { :path => "/user/username/traces/tag/tagname", :method => :get },
75 { :controller => "trace", :action => "list", :display_name => "username", :tag => "tagname" }
78 { :path => "/user/username/traces/tag/tagname/page/1", :method => :get },
79 { :controller => "trace", :action => "list", :display_name => "username", :tag => "tagname", :page => "1" }
83 { :path => "/traces/mine", :method => :get },
84 { :controller => "trace", :action => "mine" }
87 { :path => "/traces/mine/page/1", :method => :get },
88 { :controller => "trace", :action => "mine", :page => "1" }
91 { :path => "/traces/mine/tag/tagname", :method => :get },
92 { :controller => "trace", :action => "mine", :tag => "tagname" }
95 { :path => "/traces/mine/tag/tagname/page/1", :method => :get },
96 { :controller => "trace", :action => "mine", :tag => "tagname", :page => "1" }
100 { :path => "/traces/rss", :method => :get },
101 { :controller => "trace", :action => "georss", :format => :rss }
104 { :path => "/traces/tag/tagname/rss", :method => :get },
105 { :controller => "trace", :action => "georss", :tag => "tagname", :format => :rss }
108 { :path => "/user/username/traces/rss", :method => :get },
109 { :controller => "trace", :action => "georss", :display_name => "username", :format => :rss }
112 { :path => "/user/username/traces/tag/tagname/rss", :method => :get },
113 { :controller => "trace", :action => "georss", :display_name => "username", :tag => "tagname", :format => :rss }
117 { :path => "/user/username/traces/1", :method => :get },
118 { :controller => "trace", :action => "view", :display_name => "username", :id => "1" }
121 { :path => "/user/username/traces/1/picture", :method => :get },
122 { :controller => "trace", :action => "picture", :display_name => "username", :id => "1" }
125 { :path => "/user/username/traces/1/icon", :method => :get },
126 { :controller => "trace", :action => "icon", :display_name => "username", :id => "1" }
130 { :path => "/trace/create", :method => :get },
131 { :controller => "trace", :action => "create" }
134 { :path => "/trace/create", :method => :post },
135 { :controller => "trace", :action => "create" }
138 { :path => "/trace/1/data", :method => :get },
139 { :controller => "trace", :action => "data", :id => "1" }
142 { :path => "/trace/1/data.xml", :method => :get },
143 { :controller => "trace", :action => "data", :id => "1", :format => "xml" }
146 { :path => "/trace/1/edit", :method => :get },
147 { :controller => "trace", :action => "edit", :id => "1" }
150 { :path => "/trace/1/edit", :method => :post },
151 { :controller => "trace", :action => "edit", :id => "1" }
154 { :path => "/trace/1/edit", :method => :patch },
155 { :controller => "trace", :action => "edit", :id => "1" }
158 { :path => "/trace/1/delete", :method => :post },
159 { :controller => "trace", :action => "delete", :id => "1" }
163 # Check that the list of changesets is displayed
166 check_trace_list Trace.public
168 get :list, :tag => "London"
169 check_trace_list Trace.tagged("London").public
172 # Check that I can get mine
174 # First try to get it when not logged in
176 assert_redirected_to :controller => 'user', :action => 'login', :referer => '/traces/mine'
178 # Now try when logged in
179 get :mine, {}, {:user => users(:public_user).id}
180 assert_redirected_to :controller => 'trace', :action => 'list', :display_name => users(:public_user).display_name
182 # Fetch the actual list
183 get :list, {:display_name => users(:public_user).display_name}, {:user => users(:public_user).id}
184 check_trace_list users(:public_user).traces
187 # Check the list of changesets for a specific user
189 # Test a user with no traces
190 get :list, :display_name => users(:second_public_user).display_name
191 check_trace_list users(:second_public_user).traces.public
193 # Test a user with some traces - should see only public ones
194 get :list, :display_name => users(:public_user).display_name
195 check_trace_list users(:public_user).traces.public
197 # Should still see only public ones when authenticated as another user
198 get :list, {:display_name => users(:public_user).display_name}, {:user => users(:normal_user).id}
199 check_trace_list users(:public_user).traces.public
201 # Should see all traces when authenticated as the target user
202 get :list, {:display_name => users(:public_user).display_name}, {:user => users(:public_user).id}
203 check_trace_list users(:public_user).traces
205 # Should only see traces with the correct tag when a tag is specified
206 get :list, {:display_name => users(:public_user).display_name, :tag => "London"}, {:user => users(:public_user).id}
207 check_trace_list users(:public_user).traces.tagged("London")
210 # Check that the rss loads
212 get :georss, :format => :rss
213 check_trace_feed Trace.public
215 get :georss, :tag => "London", :format => :rss
216 check_trace_feed Trace.tagged("London").public
218 get :georss, :display_name => users(:public_user).display_name, :format => :rss
219 check_trace_feed users(:public_user).traces.public
221 get :georss, :display_name => users(:public_user).display_name, :tag => "Birmingham", :format => :rss
222 check_trace_feed users(:public_user).traces.tagged("Birmingham").public
225 # Test viewing a trace
227 # First with no auth, which should work since the trace is public
228 get :view, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}
229 check_trace_view gpx_files(:public_trace_file)
231 # Now with some other user, which should work since the trace is public
232 get :view, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:public_user).id}
233 check_trace_view gpx_files(:public_trace_file)
235 # And finally we should be able to do it with the owner of the trace
236 get :view, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:normal_user).id}
237 check_trace_view gpx_files(:public_trace_file)
240 # Check an anonymous trace can't be viewed by another user
243 get :view, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}
244 assert_response :redirect
245 assert_redirected_to :action => :list
247 # Now with some other user, which should work since the trace is anon
248 get :view, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}, {:user => users(:normal_user).id}
249 assert_response :redirect
250 assert_redirected_to :action => :list
252 # And finally we should be able to do it with the owner of the trace
253 get :view, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}, {:user => users(:public_user).id}
254 check_trace_view gpx_files(:anon_trace_file)
257 # Test viewing a trace that doesn't exist
258 def test_view_not_found
259 # First with no auth, which should work since the trace is public
260 get :view, {:display_name => users(:public_user).display_name, :id => 0}
261 assert_response :redirect
262 assert_redirected_to :action => :list
264 # Now with some other user, which should work since the trace is public
265 get :view, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id}
266 assert_response :redirect
267 assert_redirected_to :action => :list
269 # And finally we should be able to do it with the owner of the trace
270 get :view, {:display_name => users(:public_user).display_name, :id => 5}, {:user => users(:public_user).id}
271 assert_response :redirect
272 assert_redirected_to :action => :list
275 # Test downloading a trace
277 # First with no auth, which should work since the trace is public
278 get :data, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}
279 check_trace_data gpx_files(:public_trace_file)
281 # Now with some other user, which should work since the trace is public
282 get :data, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:public_user).id}
283 check_trace_data gpx_files(:public_trace_file)
285 # And finally we should be able to do it with the owner of the trace
286 get :data, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:normal_user).id}
287 check_trace_data gpx_files(:public_trace_file)
290 # Test downloading a compressed trace
291 def test_data_compressed
292 # First get the data as is
293 get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id}
294 check_trace_data gpx_files(:identifiable_trace_file), "application/x-gzip", "gpx.gz"
296 # Now ask explicitly for XML format
297 get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id, :format => "xml"}
298 check_trace_data gpx_files(:identifiable_trace_file), "application/xml", "xml"
300 # Now ask explicitly for GPX format
301 get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id, :format => "gpx"}
302 check_trace_data gpx_files(:identifiable_trace_file)
305 # Check an anonymous trace can't be downloaded by another user
308 get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}
309 assert_response :not_found
311 # Now with some other user, which should work since the trace is anon
312 get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}, {:user => users(:normal_user).id}
313 assert_response :not_found
315 # And finally we should be able to do it with the owner of the trace
316 get :data, {:display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id}, {:user => users(:public_user).id}
317 check_trace_data gpx_files(:anon_trace_file)
320 # Test downloading a trace that doesn't exist
321 def test_data_not_found
322 # First with no auth, which should work since the trace is public
323 get :data, {:display_name => users(:public_user).display_name, :id => 0}
324 assert_response :not_found
326 # Now with some other user, which should work since the trace is public
327 get :data, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id}
328 assert_response :not_found
330 # And finally we should be able to do it with the owner of the trace
331 get :data, {:display_name => users(:public_user).display_name, :id => 5}, {:user => users(:public_user).id}
332 assert_response :not_found
335 # Test fetching the edit page for a trace
338 get :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}
339 assert_response :redirect
340 assert_redirected_to :controller => :user, :action => :login, :referer => trace_edit_path(:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id)
342 # Now with some other user, which should fail
343 get :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:public_user).id}
344 assert_response :forbidden
346 # Now with a trace which doesn't exist
347 get :edit, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id}
348 assert_response :not_found
350 # Now with a trace which has been deleted
351 get :edit, {:display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id}, {:user => users(:public_user).id}
352 assert_response :not_found
354 # Finally with a trace that we are allowed to edit
355 get :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:normal_user).id}
356 assert_response :success
359 # Test saving edits to a trace
362 new_details = { :description => "Changed description", :tagstring => "new_tag", :visibility => "private" }
365 post :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details}
366 assert_response :forbidden
368 # Now with some other user, which should fail
369 post :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details}, {:user => users(:public_user).id}
370 assert_response :forbidden
372 # Now with a trace which doesn't exist
373 post :edit, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id, :trace => new_details}
374 assert_response :not_found
376 # Now with a trace which has been deleted
377 post :edit, {:display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id, :trace => new_details}, {:user => users(:public_user).id}
378 assert_response :not_found
380 # Finally with a trace that we are allowed to edit
381 post :edit, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details}, {:user => users(:normal_user).id}
382 assert_response :redirect
383 assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
384 trace = Trace.find(gpx_files(:public_trace_file).id)
385 assert_equal new_details[:description], trace.description
386 assert_equal new_details[:tagstring], trace.tagstring
387 assert_equal new_details[:visibility], trace.visibility
390 # Test deleting a trace
393 post :delete, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id,}
394 assert_response :forbidden
396 # Now with some other user, which should fail
397 post :delete, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:public_user).id}
398 assert_response :forbidden
400 # Now with a trace which doesn't exist
401 post :delete, {:display_name => users(:public_user).display_name, :id => 0}, {:user => users(:public_user).id}
402 assert_response :not_found
404 # Now with a trace has already been deleted
405 post :delete, {:display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id}, {:user => users(:public_user).id}
406 assert_response :not_found
408 # Finally with a trace that we are allowed to delete
409 post :delete, {:display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id}, {:user => users(:normal_user).id}
410 assert_response :redirect
411 assert_redirected_to :action => :list, :display_name => users(:normal_user).display_name
412 trace = Trace.find(gpx_files(:public_trace_file).id)
413 assert_equal false, trace.visible
416 # Check getting a specific trace through the api
419 get :api_read, :id => gpx_files(:public_trace_file).id
420 assert_response :unauthorized
422 # Now with some other user, which should work since the trace is public
423 basic_authorization(users(:public_user).display_name, "test")
424 get :api_read, :id => gpx_files(:public_trace_file).id
425 assert_response :success
427 # And finally we should be able to do it with the owner of the trace
428 basic_authorization(users(:normal_user).display_name, "test")
429 get :api_read, :id => gpx_files(:public_trace_file).id
430 assert_response :success
433 # Check an anoymous trace can't be specifically fetched by another user
434 def test_api_read_anon
436 get :api_read, :id => gpx_files(:anon_trace_file).id
437 assert_response :unauthorized
439 # Now try with another user, which shouldn't work since the trace is anon
440 basic_authorization(users(:normal_user).display_name, "test")
441 get :api_read, :id => gpx_files(:anon_trace_file).id
442 assert_response :forbidden
444 # And finally we should be able to get the trace details with the trace owner
445 basic_authorization(users(:public_user).display_name, "test")
446 get :api_read, :id => gpx_files(:anon_trace_file).id
447 assert_response :success
450 # Check the api details for a trace that doesn't exist
451 def test_api_read_not_found
452 # Try first with no auth, as it should requure it
453 get :api_read, :id => 0
454 assert_response :unauthorized
456 # Login, and try again
457 basic_authorization(users(:public_user).display_name, "test")
458 get :api_read, :id => 0
459 assert_response :not_found
461 # Now try a trace which did exist but has been deleted
462 basic_authorization(users(:public_user).display_name, "test")
463 get :api_read, :id => 5
464 assert_response :not_found
467 # Check updating a trace through the api
470 content gpx_files(:public_trace_file).to_xml
471 put :api_update, :id => gpx_files(:public_trace_file).id
472 assert_response :unauthorized
474 # Now with some other user, which should fail
475 basic_authorization(users(:public_user).display_name, "test")
476 content gpx_files(:public_trace_file).to_xml
477 put :api_update, :id => gpx_files(:public_trace_file).id
478 assert_response :forbidden
480 # Now with a trace which doesn't exist
481 basic_authorization(users(:public_user).display_name, "test")
482 content gpx_files(:public_trace_file).to_xml
483 put :api_update, :id => 0
484 assert_response :not_found
486 # Now with a trace which did exist but has been deleted
487 basic_authorization(users(:public_user).display_name, "test")
488 content gpx_files(:deleted_trace_file).to_xml
489 put :api_update, :id => gpx_files(:deleted_trace_file).id
490 assert_response :not_found
492 # Now try an update with the wrong ID
493 basic_authorization(users(:normal_user).display_name, "test")
494 content gpx_files(:anon_trace_file).to_xml
495 put :api_update, :id => gpx_files(:public_trace_file).id
496 assert_response :bad_request,
497 "should not be able to update a trace with a different ID from the XML"
499 # And finally try an update that should work
500 basic_authorization(users(:normal_user).display_name, "test")
501 t = gpx_files(:public_trace_file)
502 t.description = "Changed description"
503 t.visibility = "private"
505 put :api_update, :id => t.id
506 assert_response :success
507 nt = Trace.find(t.id)
508 assert_equal nt.description, t.description
509 assert_equal nt.visibility, t.visibility
512 # Check deleting a trace through the api
515 delete :api_delete, :id => gpx_files(:public_trace_file).id
516 assert_response :unauthorized
518 # Now with some other user, which should fail
519 basic_authorization(users(:public_user).display_name, "test")
520 delete :api_delete, :id => gpx_files(:public_trace_file).id
521 assert_response :forbidden
523 # Now with a trace which doesn't exist
524 basic_authorization(users(:public_user).display_name, "test")
525 delete :api_delete, :id => 0
526 assert_response :not_found
528 # And finally we should be able to do it with the owner of the trace
529 basic_authorization(users(:normal_user).display_name, "test")
530 delete :api_delete, :id => gpx_files(:public_trace_file).id
531 assert_response :success
533 # Try it a second time, which should fail
534 basic_authorization(users(:normal_user).display_name, "test")
535 delete :api_delete, :id => gpx_files(:public_trace_file).id
536 assert_response :not_found
541 def check_trace_feed(traces)
542 assert_response :success
543 assert_template "georss"
544 assert_equal "application/rss+xml", @response.content_type
545 assert_select "rss", :count => 1 do
546 assert_select "channel", :count => 1 do
547 assert_select "title"
548 assert_select "description"
550 assert_select "image"
551 assert_select "item", :count => traces.visible.count do |items|
552 traces.visible.order("timestamp DESC").zip(items).each do |trace,item|
553 assert_select item, "title", trace.name
554 assert_select item, "link", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
555 assert_select item, "guid", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
556 assert_select item, "description"
557 # assert_select item, "dc:creator", trace.user.display_name
558 assert_select item, "pubDate", trace.timestamp.rfc822
565 def check_trace_list(traces)
566 assert_response :success
567 assert_template "list"
570 assert_select "table#trace_list tbody", :count => 1 do
571 assert_select "tr", :count => traces.visible.count do |rows|
572 traces.visible.order("timestamp DESC").zip(rows).each do |trace,row|
573 assert_select row, "span.trace_summary", Regexp.new(Regexp.escape("(#{trace.size} points)"))
574 assert_select row, "td", Regexp.new(Regexp.escape(trace.description))
575 assert_select row, "td", Regexp.new(Regexp.escape("by #{trace.user.display_name}"))
580 assert_select "h4", /Nothing here yet/
584 def check_trace_view(trace)
585 assert_response :success
586 assert_template "view"
588 assert_select "table", :count => 1 do
589 assert_select "td", /^#{Regexp.quote(trace.name)} /
590 assert_select "td", trace.user.display_name
591 assert_select "td", trace.description
595 def check_trace_data(trace, content_type = "application/gpx+xml", extension = "gpx")
596 assert_response :success
597 assert_equal content_type, @response.content_type
598 assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"", @response.header["Content-Disposition"]