]> git.openstreetmap.org Git - rails.git/blob - test/controllers/traces_controller_test.rb
Switch traces to use ActiveStorage
[rails.git] / test / controllers / traces_controller_test.rb
1 require "test_helper"
2
3 class TracesControllerTest < ActionDispatch::IntegrationTest
4   # Use temporary directories with unique names for each test
5   # This allows the tests to be run in parallel.
6   def setup
7     @gpx_trace_dir_orig = Settings.gpx_trace_dir
8     @gpx_image_dir_orig = Settings.gpx_image_dir
9     Settings.gpx_trace_dir = Dir.mktmpdir("trace", Rails.root.join("test/gpx"))
10     Settings.gpx_image_dir = Dir.mktmpdir("image", Rails.root.join("test/gpx"))
11   end
12
13   def teardown
14     FileUtils.remove_dir(Settings.gpx_trace_dir)
15     FileUtils.remove_dir(Settings.gpx_image_dir)
16     Settings.gpx_trace_dir = @gpx_trace_dir_orig
17     Settings.gpx_image_dir = @gpx_image_dir_orig
18   end
19
20   ##
21   # test all routes which lead to this controller
22   def test_routes
23     assert_routing(
24       { :path => "/traces", :method => :get },
25       { :controller => "traces", :action => "index" }
26     )
27     assert_routing(
28       { :path => "/traces/page/1", :method => :get },
29       { :controller => "traces", :action => "index", :page => "1" }
30     )
31     assert_routing(
32       { :path => "/traces/tag/tagname", :method => :get },
33       { :controller => "traces", :action => "index", :tag => "tagname" }
34     )
35     assert_routing(
36       { :path => "/traces/tag/tagname/page/1", :method => :get },
37       { :controller => "traces", :action => "index", :tag => "tagname", :page => "1" }
38     )
39     assert_routing(
40       { :path => "/user/username/traces", :method => :get },
41       { :controller => "traces", :action => "index", :display_name => "username" }
42     )
43     assert_routing(
44       { :path => "/user/username/traces/page/1", :method => :get },
45       { :controller => "traces", :action => "index", :display_name => "username", :page => "1" }
46     )
47     assert_routing(
48       { :path => "/user/username/traces/tag/tagname", :method => :get },
49       { :controller => "traces", :action => "index", :display_name => "username", :tag => "tagname" }
50     )
51     assert_routing(
52       { :path => "/user/username/traces/tag/tagname/page/1", :method => :get },
53       { :controller => "traces", :action => "index", :display_name => "username", :tag => "tagname", :page => "1" }
54     )
55
56     assert_routing(
57       { :path => "/traces/mine", :method => :get },
58       { :controller => "traces", :action => "mine" }
59     )
60     assert_routing(
61       { :path => "/traces/mine/page/1", :method => :get },
62       { :controller => "traces", :action => "mine", :page => "1" }
63     )
64     assert_routing(
65       { :path => "/traces/mine/tag/tagname", :method => :get },
66       { :controller => "traces", :action => "mine", :tag => "tagname" }
67     )
68     assert_routing(
69       { :path => "/traces/mine/tag/tagname/page/1", :method => :get },
70       { :controller => "traces", :action => "mine", :tag => "tagname", :page => "1" }
71     )
72
73     assert_routing(
74       { :path => "/traces/rss", :method => :get },
75       { :controller => "traces", :action => "georss", :format => :rss }
76     )
77     assert_routing(
78       { :path => "/traces/tag/tagname/rss", :method => :get },
79       { :controller => "traces", :action => "georss", :tag => "tagname", :format => :rss }
80     )
81     assert_routing(
82       { :path => "/user/username/traces/rss", :method => :get },
83       { :controller => "traces", :action => "georss", :display_name => "username", :format => :rss }
84     )
85     assert_routing(
86       { :path => "/user/username/traces/tag/tagname/rss", :method => :get },
87       { :controller => "traces", :action => "georss", :display_name => "username", :tag => "tagname", :format => :rss }
88     )
89
90     assert_routing(
91       { :path => "/user/username/traces/1", :method => :get },
92       { :controller => "traces", :action => "show", :display_name => "username", :id => "1" }
93     )
94     assert_routing(
95       { :path => "/user/username/traces/1/picture", :method => :get },
96       { :controller => "traces", :action => "picture", :display_name => "username", :id => "1" }
97     )
98     assert_routing(
99       { :path => "/user/username/traces/1/icon", :method => :get },
100       { :controller => "traces", :action => "icon", :display_name => "username", :id => "1" }
101     )
102
103     assert_routing(
104       { :path => "/traces/new", :method => :get },
105       { :controller => "traces", :action => "new" }
106     )
107     assert_routing(
108       { :path => "/traces", :method => :post },
109       { :controller => "traces", :action => "create" }
110     )
111     assert_routing(
112       { :path => "/trace/1/data", :method => :get },
113       { :controller => "traces", :action => "data", :id => "1" }
114     )
115     assert_routing(
116       { :path => "/trace/1/data.xml", :method => :get },
117       { :controller => "traces", :action => "data", :id => "1", :format => "xml" }
118     )
119     assert_routing(
120       { :path => "/traces/1/edit", :method => :get },
121       { :controller => "traces", :action => "edit", :id => "1" }
122     )
123     assert_routing(
124       { :path => "/traces/1", :method => :put },
125       { :controller => "traces", :action => "update", :id => "1" }
126     )
127     assert_routing(
128       { :path => "/traces/1", :method => :delete },
129       { :controller => "traces", :action => "destroy", :id => "1" }
130     )
131   end
132
133   # Check that the index of traces is displayed
134   def test_index
135     user = create(:user)
136     # The fourth test below is surprisingly sensitive to timestamp ordering when the timestamps are equal.
137     trace_a = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago) do |trace|
138       create(:tracetag, :trace => trace, :tag => "London")
139     end
140     trace_b = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago) do |trace|
141       create(:tracetag, :trace => trace, :tag => "Birmingham")
142     end
143     trace_c = create(:trace, :visibility => "private", :user => user, :timestamp => 2.seconds.ago) do |trace|
144       create(:tracetag, :trace => trace, :tag => "London")
145     end
146     trace_d = create(:trace, :visibility => "private", :user => user, :timestamp => 1.second.ago) do |trace|
147       create(:tracetag, :trace => trace, :tag => "Birmingham")
148     end
149
150     # First with the public index
151     get traces_path
152     check_trace_index [trace_b, trace_a]
153
154     # Restrict traces to those with a given tag
155     get traces_path(:tag => "London")
156     check_trace_index [trace_a]
157
158     session_for(user)
159
160     # Should see more when we are logged in
161     get traces_path
162     check_trace_index [trace_d, trace_c, trace_b, trace_a]
163
164     # Again, we should see more when we are logged in
165     get traces_path(:tag => "London")
166     check_trace_index [trace_c, trace_a]
167   end
168
169   # Check that I can get mine
170   def test_index_mine
171     user = create(:user)
172     create(:trace, :visibility => "public") do |trace|
173       create(:tracetag, :trace => trace, :tag => "Birmingham")
174     end
175     trace_b = create(:trace, :visibility => "private", :user => user) do |trace|
176       create(:tracetag, :trace => trace, :tag => "London")
177     end
178
179     # First try to get it when not logged in
180     get traces_mine_path
181     assert_redirected_to login_path(:referer => "/traces/mine")
182
183     session_for(user)
184
185     # Now try when logged in
186     get traces_mine_path
187     assert_redirected_to :action => "index", :display_name => user.display_name
188
189     # Fetch the actual index
190     get traces_path(:display_name => user.display_name)
191     check_trace_index [trace_b]
192   end
193
194   # Check the index of traces for a specific user
195   def test_index_user
196     user = create(:user)
197     second_user = create(:user)
198     third_user = create(:user)
199     create(:trace)
200     trace_b = create(:trace, :visibility => "public", :user => user)
201     trace_c = create(:trace, :visibility => "private", :user => user) do |trace|
202       create(:tracetag, :trace => trace, :tag => "London")
203     end
204
205     # Test a user with no traces
206     get traces_path(:display_name => second_user.display_name)
207     check_trace_index []
208
209     # Test the user with the traces - should see only public ones
210     get traces_path(:display_name => user.display_name)
211     check_trace_index [trace_b]
212
213     session_for(third_user)
214
215     # Should still see only public ones when authenticated as another user
216     get traces_path(:display_name => user.display_name)
217     check_trace_index [trace_b]
218
219     session_for(user)
220
221     # Should see all traces when authenticated as the target user
222     get traces_path(:display_name => user.display_name)
223     check_trace_index [trace_c, trace_b]
224
225     # Should only see traces with the correct tag when a tag is specified
226     get traces_path(:display_name => user.display_name, :tag => "London")
227     check_trace_index [trace_c]
228
229     # Should get an error if the user does not exist
230     get traces_path(:display_name => "UnknownUser")
231     assert_response :not_found
232     assert_template "users/no_such_user"
233   end
234
235   # Check a multi-page index
236   def test_index_paged
237     # Create several pages worth of traces
238     create_list(:trace, 50)
239
240     # Try and get the index
241     get traces_path
242     assert_response :success
243     assert_select "table#trace_list tbody", :count => 1 do
244       assert_select "tr", :count => 20
245     end
246
247     # Try and get the second page
248     get traces_path(:page => 2)
249     assert_response :success
250     assert_select "table#trace_list tbody", :count => 1 do
251       assert_select "tr", :count => 20
252     end
253   end
254
255   # Check the RSS feed
256   def test_rss
257     user = create(:user)
258     # The fourth test below is surprisingly sensitive to timestamp ordering when the timestamps are equal.
259     trace_a = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago) do |trace|
260       create(:tracetag, :trace => trace, :tag => "London")
261     end
262     trace_b = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago) do |trace|
263       create(:tracetag, :trace => trace, :tag => "Birmingham")
264     end
265     create(:trace, :visibility => "private", :user => user, :timestamp => 2.seconds.ago) do |trace|
266       create(:tracetag, :trace => trace, :tag => "London")
267     end
268     create(:trace, :visibility => "private", :user => user, :timestamp => 1.second.ago) do |trace|
269       create(:tracetag, :trace => trace, :tag => "Birmingham")
270     end
271
272     # First with the public feed
273     get traces_rss_path
274     check_trace_feed [trace_b, trace_a]
275
276     # Restrict traces to those with a given tag
277     get traces_rss_path(:tag => "London")
278     check_trace_feed [trace_a]
279   end
280
281   # Check the RSS feed for a specific user
282   def test_rss_user
283     user = create(:user)
284     second_user = create(:user)
285     create(:user)
286     create(:trace)
287     trace_b = create(:trace, :visibility => "public", :timestamp => 4.seconds.ago, :user => user)
288     trace_c = create(:trace, :visibility => "public", :timestamp => 3.seconds.ago, :user => user) do |trace|
289       create(:tracetag, :trace => trace, :tag => "London")
290     end
291     create(:trace, :visibility => "private")
292
293     # Test a user with no traces
294     get traces_rss_path(:display_name => second_user.display_name)
295     check_trace_feed []
296
297     # Test the user with the traces - should see only public ones
298     get traces_rss_path(:display_name => user.display_name)
299     check_trace_feed [trace_c, trace_b]
300
301     # Should only see traces with the correct tag when a tag is specified
302     get traces_rss_path(:display_name => user.display_name, :tag => "London")
303     check_trace_feed [trace_c]
304
305     # Should no traces if the user does not exist
306     get traces_rss_path(:display_name => "UnknownUser")
307     check_trace_feed []
308   end
309
310   # Test showing a trace
311   def test_show
312     public_trace_file = create(:trace, :visibility => "public")
313
314     # First with no auth, which should work since the trace is public
315     get show_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
316     check_trace_show public_trace_file
317
318     # Now with some other user, which should work since the trace is public
319     session_for(create(:user))
320     get show_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
321     check_trace_show public_trace_file
322
323     # And finally we should be able to do it with the owner of the trace
324     session_for(public_trace_file.user)
325     get show_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
326     check_trace_show public_trace_file
327   end
328
329   # Check an anonymous trace can't be viewed by another user
330   def test_show_anon
331     anon_trace_file = create(:trace, :visibility => "private")
332
333     # First with no auth
334     get show_trace_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
335     assert_response :redirect
336     assert_redirected_to :action => :index
337
338     # Now with some other user, which should not work since the trace is anon
339     session_for(create(:user))
340     get show_trace_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
341     assert_response :redirect
342     assert_redirected_to :action => :index
343
344     # And finally we should be able to do it with the owner of the trace
345     session_for(anon_trace_file.user)
346     get show_trace_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
347     check_trace_show anon_trace_file
348   end
349
350   # Test showing a trace that doesn't exist
351   def test_show_not_found
352     deleted_trace_file = create(:trace, :deleted)
353
354     # First with a trace that has never existed
355     get show_trace_path(:display_name => create(:user).display_name, :id => 0)
356     assert_response :redirect
357     assert_redirected_to :action => :index
358
359     # Now with a trace that has been deleted
360     session_for(deleted_trace_file.user)
361     get show_trace_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
362     assert_response :redirect
363     assert_redirected_to :action => :index
364   end
365
366   # Test downloading a trace
367   def test_data
368     public_trace_file = create(:trace, :visibility => "public", :fixture => "a")
369
370     # First with no auth, which should work since the trace is public
371     get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
372     follow_redirect!
373     follow_redirect!
374     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
375
376     # Now with some other user, which should work since the trace is public
377     session_for(create(:user))
378     get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
379     follow_redirect!
380     follow_redirect!
381     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
382
383     # And finally we should be able to do it with the owner of the trace
384     session_for(public_trace_file.user)
385     get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
386     follow_redirect!
387     follow_redirect!
388     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
389   end
390
391   # Test downloading a compressed trace
392   def test_data_compressed
393     identifiable_trace_file = create(:trace, :visibility => "identifiable", :fixture => "d")
394
395     # First get the data as is
396     get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file)
397     follow_redirect!
398     follow_redirect!
399     check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/gzip", "gpx.gz"
400
401     # Now ask explicitly for XML format
402     get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file.id, :format => "xml")
403     check_trace_data identifiable_trace_file, "abd6675fdf3024a84fc0a1deac147c0d", "application/xml", "xml"
404
405     # Now ask explicitly for GPX format
406     get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file.id, :format => "gpx")
407     check_trace_data identifiable_trace_file, "abd6675fdf3024a84fc0a1deac147c0d"
408   end
409
410   # Check an anonymous trace can't be downloaded by another user
411   def test_data_anon
412     anon_trace_file = create(:trace, :visibility => "private", :fixture => "b")
413
414     # First with no auth
415     get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
416     assert_response :not_found
417
418     # Now with some other user, which shouldn't work since the trace is anon
419     session_for(create(:user))
420     get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
421     assert_response :not_found
422
423     # And finally we should be able to do it with the owner of the trace
424     session_for(anon_trace_file.user)
425     get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
426     follow_redirect!
427     follow_redirect!
428     check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701"
429   end
430
431   # Test downloading a trace that doesn't exist
432   def test_data_not_found
433     deleted_trace_file = create(:trace, :deleted)
434
435     # First with a trace that has never existed
436     get trace_data_path(:display_name => create(:user).display_name, :id => 0)
437     assert_response :not_found
438
439     # Now with a trace that has been deleted
440     session_for(deleted_trace_file.user)
441     get trace_data_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
442     assert_response :not_found
443   end
444
445   # Test downloading the picture for a trace
446   def test_picture
447     public_trace_file = create(:trace, :visibility => "public", :fixture => "a")
448
449     # First with no auth, which should work since the trace is public
450     get trace_picture_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
451     check_trace_picture public_trace_file
452
453     # Now with some other user, which should work since the trace is public
454     session_for(create(:user))
455     get trace_picture_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
456     check_trace_picture public_trace_file
457
458     # And finally we should be able to do it with the owner of the trace
459     session_for(public_trace_file.user)
460     get trace_picture_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
461     check_trace_picture public_trace_file
462   end
463
464   # Check the picture for an anonymous trace can't be downloaded by another user
465   def test_picture_anon
466     anon_trace_file = create(:trace, :visibility => "private", :fixture => "b")
467
468     # First with no auth
469     get trace_picture_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
470     assert_response :forbidden
471
472     # Now with some other user, which shouldn't work since the trace is anon
473     session_for(create(:user))
474     get trace_picture_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
475     assert_response :forbidden
476
477     # And finally we should be able to do it with the owner of the trace
478     session_for(anon_trace_file.user)
479     get trace_picture_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
480     check_trace_picture anon_trace_file
481   end
482
483   # Test downloading the picture for a trace that doesn't exist
484   def test_picture_not_found
485     deleted_trace_file = create(:trace, :deleted)
486
487     # First with a trace that has never existed
488     get trace_picture_path(:display_name => create(:user).display_name, :id => 0)
489     assert_response :not_found
490
491     # Now with a trace that has been deleted
492     session_for(deleted_trace_file.user)
493     get trace_picture_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
494     assert_response :not_found
495   end
496
497   # Test downloading the icon for a trace
498   def test_icon
499     public_trace_file = create(:trace, :visibility => "public", :fixture => "a")
500
501     # First with no auth, which should work since the trace is public
502     get trace_icon_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
503     check_trace_icon public_trace_file
504
505     # Now with some other user, which should work since the trace is public
506     session_for(create(:user))
507     get trace_icon_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
508     check_trace_icon public_trace_file
509
510     # And finally we should be able to do it with the owner of the trace
511     session_for(public_trace_file.user)
512     get trace_icon_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
513     check_trace_icon public_trace_file
514   end
515
516   # Check the icon for an anonymous trace can't be downloaded by another user
517   def test_icon_anon
518     anon_trace_file = create(:trace, :visibility => "private", :fixture => "b")
519
520     # First with no auth
521     get trace_icon_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
522     assert_response :forbidden
523
524     # Now with some other user, which shouldn't work since the trace is anon
525     session_for(create(:user))
526     get trace_icon_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
527     assert_response :forbidden
528
529     # And finally we should be able to do it with the owner of the trace
530     session_for(anon_trace_file.user)
531     get trace_icon_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
532     check_trace_icon anon_trace_file
533   end
534
535   # Test downloading the icon for a trace that doesn't exist
536   def test_icon_not_found
537     deleted_trace_file = create(:trace, :deleted)
538
539     # First with a trace that has never existed
540     get trace_icon_path(:display_name => create(:user).display_name, :id => 0)
541     assert_response :not_found
542
543     # Now with a trace that has been deleted
544     session_for(deleted_trace_file.user)
545     get trace_icon_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
546     assert_response :not_found
547   end
548
549   # Test fetching the new trace page
550   def test_new_get
551     # First with no auth
552     get new_trace_path
553     assert_response :redirect
554     assert_redirected_to login_path(:referer => new_trace_path)
555
556     # Now authenticated as a user with gps.trace.visibility set
557     user = create(:user)
558     create(:user_preference, :user => user, :k => "gps.trace.visibility", :v => "identifiable")
559     session_for(user)
560     get new_trace_path
561     assert_response :success
562     assert_template :new
563     assert_select "select#trace_visibility option[value=identifiable][selected]", 1
564
565     # Now authenticated as a user with gps.trace.public set
566     second_user = create(:user)
567     create(:user_preference, :user => second_user, :k => "gps.trace.public", :v => "default")
568     session_for(second_user)
569     get new_trace_path
570     assert_response :success
571     assert_template :new
572     assert_select "select#trace_visibility option[value=public][selected]", 1
573
574     # Now authenticated as a user with no preferences
575     third_user = create(:user)
576     session_for(third_user)
577     get new_trace_path
578     assert_response :success
579     assert_template :new
580     assert_select "select#trace_visibility option[value=private][selected]", 1
581   end
582
583   # Test creating a trace
584   def test_create_post
585     # Get file to use
586     fixture = Rails.root.join("test/gpx/fixtures/a.gpx")
587     file = Rack::Test::UploadedFile.new(fixture, "application/gpx+xml")
588     user = create(:user)
589
590     # First with no auth
591     post traces_path(:trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" })
592     assert_response :forbidden
593
594     # Rewind the file
595     file.rewind
596
597     # Now authenticated
598     create(:user_preference, :user => user, :k => "gps.trace.visibility", :v => "identifiable")
599     assert_not_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
600     session_for(user)
601     post traces_path, :params => { :trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" } }
602     assert_response :redirect
603     assert_redirected_to :action => :index, :display_name => user.display_name
604     assert_match(/file has been uploaded/, flash[:notice])
605     trace = Trace.order(:id => :desc).first
606     assert_equal "a.gpx", trace.name
607     assert_equal "New Trace", trace.description
608     assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
609     assert_equal "trackable", trace.visibility
610     assert_not trace.inserted
611     assert_equal File.new(fixture).read, trace.file.blob.download
612     trace.destroy
613     assert_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
614   end
615
616   # Test creating a trace with validation errors
617   def test_create_post_with_validation_errors
618     # Get file to use
619     fixture = Rails.root.join("test/gpx/fixtures/a.gpx")
620     file = Rack::Test::UploadedFile.new(fixture, "application/gpx+xml")
621     user = create(:user)
622
623     # Now authenticated
624     create(:user_preference, :user => user, :k => "gps.trace.visibility", :v => "identifiable")
625     assert_not_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
626     session_for(user)
627     post traces_path, :params => { :trace => { :gpx_file => file, :description => "", :tagstring => "new,trace", :visibility => "trackable" } }
628     assert_template :new
629     assert_match "is too short (minimum is 1 character)", response.body
630   end
631
632   # Test fetching the edit page for a trace using GET
633   def test_edit_get
634     public_trace_file = create(:trace, :visibility => "public")
635     deleted_trace_file = create(:trace, :deleted)
636
637     # First with no auth
638     get edit_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
639     assert_response :redirect
640     assert_redirected_to login_path(:referer => edit_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file.id))
641
642     # Now with some other user, which should fail
643     session_for(create(:user))
644     get edit_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
645     assert_response :forbidden
646
647     # Now with a trace which doesn't exist
648     session_for(create(:user))
649     get edit_trace_path(:display_name => create(:user).display_name, :id => 0)
650     assert_response :not_found
651
652     # Now with a trace which has been deleted
653     session_for(deleted_trace_file.user)
654     get edit_trace_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
655     assert_response :not_found
656
657     # Finally with a trace that we are allowed to edit
658     session_for(public_trace_file.user)
659     get edit_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
660     assert_response :success
661   end
662
663   # Test saving edits to a trace
664   def test_update
665     public_trace_file = create(:trace, :visibility => "public")
666     deleted_trace_file = create(:trace, :deleted)
667
668     # New details
669     new_details = { :description => "Changed description", :tagstring => "new_tag", :visibility => "private" }
670
671     # First with no auth
672     put trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file, :trace => new_details)
673     assert_response :forbidden
674
675     # Now with some other user, which should fail
676     session_for(create(:user))
677     put trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file, :trace => new_details)
678     assert_response :forbidden
679
680     # Now with a trace which doesn't exist
681     session_for(create(:user))
682     put trace_path(:display_name => create(:user).display_name, :id => 0, :trace => new_details)
683     assert_response :not_found
684
685     # Now with a trace which has been deleted
686     session_for(deleted_trace_file.user)
687     put trace_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file, :trace => new_details)
688     assert_response :not_found
689
690     # Finally with a trace that we are allowed to edit
691     session_for(public_trace_file.user)
692     put trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file, :trace => new_details)
693     assert_response :redirect
694     assert_redirected_to :action => :show, :display_name => public_trace_file.user.display_name
695     trace = Trace.find(public_trace_file.id)
696     assert_equal new_details[:description], trace.description
697     assert_equal new_details[:tagstring], trace.tagstring
698     assert_equal new_details[:visibility], trace.visibility
699   end
700
701   # Test destroying a trace
702   def test_destroy
703     public_trace_file = create(:trace, :visibility => "public")
704     deleted_trace_file = create(:trace, :deleted)
705
706     # First with no auth
707     delete trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
708     assert_response :forbidden
709
710     # Now with some other user, which should fail
711     session_for(create(:user))
712     delete trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
713     assert_response :forbidden
714
715     # Now with a trace which doesn't exist
716     session_for(create(:user))
717     delete trace_path(:display_name => create(:user).display_name, :id => 0)
718     assert_response :not_found
719
720     # Now with a trace has already been deleted
721     session_for(deleted_trace_file.user)
722     delete trace_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
723     assert_response :not_found
724
725     # Now with a trace that we are allowed to delete
726     session_for(public_trace_file.user)
727     delete trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
728     assert_response :redirect
729     assert_redirected_to :action => :index, :display_name => public_trace_file.user.display_name
730     trace = Trace.find(public_trace_file.id)
731     assert_not trace.visible
732
733     # Finally with a trace that is destroyed by an admin
734     public_trace_file = create(:trace, :visibility => "public")
735     admin = create(:administrator_user)
736     session_for(admin)
737     delete trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
738     assert_response :redirect
739     assert_redirected_to :action => :index, :display_name => public_trace_file.user.display_name
740     trace = Trace.find(public_trace_file.id)
741     assert_not trace.visible
742   end
743
744   private
745
746   def check_trace_feed(traces)
747     assert_response :success
748     assert_template "georss"
749     assert_equal "application/rss+xml", @response.media_type
750     assert_select "rss", :count => 1 do
751       assert_select "channel", :count => 1 do
752         assert_select "title"
753         assert_select "description"
754         assert_select "link"
755         assert_select "image"
756         assert_select "item", :count => traces.length do |items|
757           traces.zip(items).each do |trace, item|
758             assert_select item, "title", trace.name
759             assert_select item, "link", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
760             assert_select item, "guid", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
761             assert_select item, "description"
762             # assert_select item, "dc:creator", trace.user.display_name
763             assert_select item, "pubDate", trace.timestamp.rfc822
764           end
765         end
766       end
767     end
768   end
769
770   def check_trace_index(traces)
771     assert_response :success
772     assert_template "index"
773
774     if traces.empty?
775       assert_select "h4", /Nothing here yet/
776     else
777       assert_select "table#trace_list tbody", :count => 1 do
778         assert_select "tr", :count => traces.length do |rows|
779           traces.zip(rows).each do |trace, row|
780             assert_select row, "a", Regexp.new(Regexp.escape(trace.name))
781             assert_select row, "li", Regexp.new(Regexp.escape("#{trace.size} points")) if trace.inserted?
782             assert_select row, "td", Regexp.new(Regexp.escape(trace.description))
783             assert_select row, "td", Regexp.new(Regexp.escape("by #{trace.user.display_name}"))
784           end
785         end
786       end
787     end
788   end
789
790   def check_trace_show(trace)
791     assert_response :success
792     assert_template "show"
793
794     assert_select "table", :count => 1 do
795       assert_select "td", /^#{Regexp.quote(trace.name)} /
796       assert_select "td", trace.user.display_name
797       assert_select "td", trace.description
798     end
799   end
800
801   def check_trace_data(trace, digest, content_type = "application/gpx+xml", extension = "gpx")
802     assert_equal digest, Digest::MD5.hexdigest(response.body)
803     assert_equal content_type, response.media_type
804     assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"; filename*=UTF-8''#{trace.id}.#{extension}", @response.header["Content-Disposition"]
805   end
806
807   def check_trace_picture(trace)
808     follow_redirect!
809     follow_redirect!
810     assert_response :success
811     assert_equal "image/gif", response.media_type
812     assert_equal trace.large_picture, response.body
813   end
814
815   def check_trace_icon(trace)
816     follow_redirect!
817     follow_redirect!
818     assert_response :success
819     assert_equal "image/gif", response.media_type
820     assert_equal trace.icon_picture, response.body
821   end
822 end