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