]> git.openstreetmap.org Git - rails.git/blob - test/controllers/traces_controller_test.rb
36bee9c95135e1e85b9a1282d0dc84a9d2785daa
[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 surpisingly 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 :controller => "users", :action => "login", :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 surpisingly 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     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
373
374     # Now with some other user, which should work since the trace is public
375     session_for(create(:user))
376     get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
377     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
378
379     # And finally we should be able to do it with the owner of the trace
380     session_for(public_trace_file.user)
381     get trace_data_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
382     check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
383   end
384
385   # Test downloading a compressed trace
386   def test_data_compressed
387     identifiable_trace_file = create(:trace, :visibility => "identifiable", :fixture => "d")
388
389     # First get the data as is
390     get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file)
391     check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/x-gzip", "gpx.gz"
392
393     # Now ask explicitly for XML format
394     get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file.id, :format => "xml")
395     check_trace_data identifiable_trace_file, "abd6675fdf3024a84fc0a1deac147c0d", "application/xml", "xml"
396
397     # Now ask explicitly for GPX format
398     get trace_data_path(:display_name => identifiable_trace_file.user.display_name, :id => identifiable_trace_file.id, :format => "gpx")
399     check_trace_data identifiable_trace_file, "abd6675fdf3024a84fc0a1deac147c0d"
400   end
401
402   # Check an anonymous trace can't be downloaded by another user
403   def test_data_anon
404     anon_trace_file = create(:trace, :visibility => "private", :fixture => "b")
405
406     # First with no auth
407     get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
408     assert_response :not_found
409
410     # Now with some other user, which shouldn't work since the trace is anon
411     session_for(create(:user))
412     get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
413     assert_response :not_found
414
415     # And finally we should be able to do it with the owner of the trace
416     session_for(anon_trace_file.user)
417     get trace_data_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
418     check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701"
419   end
420
421   # Test downloading a trace that doesn't exist
422   def test_data_not_found
423     deleted_trace_file = create(:trace, :deleted)
424
425     # First with a trace that has never existed
426     get trace_data_path(:display_name => create(:user).display_name, :id => 0)
427     assert_response :not_found
428
429     # Now with a trace that has been deleted
430     session_for(deleted_trace_file.user)
431     get trace_data_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
432     assert_response :not_found
433   end
434
435   # Test downloading the picture for a trace
436   def test_picture
437     public_trace_file = create(:trace, :visibility => "public", :fixture => "a")
438
439     # First with no auth, which should work since the trace is public
440     get trace_picture_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
441     check_trace_picture public_trace_file
442
443     # Now with some other user, which should work since the trace is public
444     session_for(create(:user))
445     get trace_picture_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
446     check_trace_picture public_trace_file
447
448     # And finally we should be able to do it with the owner of the trace
449     session_for(public_trace_file.user)
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   end
453
454   # Check the picture for an anonymous trace can't be downloaded by another user
455   def test_picture_anon
456     anon_trace_file = create(:trace, :visibility => "private", :fixture => "b")
457
458     # First with no auth
459     get trace_picture_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
460     assert_response :forbidden
461
462     # Now with some other user, which shouldn't work since the trace is anon
463     session_for(create(:user))
464     get trace_picture_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
465     assert_response :forbidden
466
467     # And finally we should be able to do it with the owner of the trace
468     session_for(anon_trace_file.user)
469     get trace_picture_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
470     check_trace_picture anon_trace_file
471   end
472
473   # Test downloading the picture for a trace that doesn't exist
474   def test_picture_not_found
475     deleted_trace_file = create(:trace, :deleted)
476
477     # First with a trace that has never existed
478     get trace_picture_path(:display_name => create(:user).display_name, :id => 0)
479     assert_response :not_found
480
481     # Now with a trace that has been deleted
482     session_for(deleted_trace_file.user)
483     get trace_picture_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
484     assert_response :not_found
485   end
486
487   # Test downloading the icon for a trace
488   def test_icon
489     public_trace_file = create(:trace, :visibility => "public", :fixture => "a")
490
491     # First with no auth, which should work since the trace is public
492     get trace_icon_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
493     check_trace_icon public_trace_file
494
495     # Now with some other user, which should work since the trace is public
496     session_for(create(:user))
497     get trace_icon_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
498     check_trace_icon public_trace_file
499
500     # And finally we should be able to do it with the owner of the trace
501     session_for(public_trace_file.user)
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   end
505
506   # Check the icon for an anonymous trace can't be downloaded by another user
507   def test_icon_anon
508     anon_trace_file = create(:trace, :visibility => "private", :fixture => "b")
509
510     # First with no auth
511     get trace_icon_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
512     assert_response :forbidden
513
514     # Now with some other user, which shouldn't work since the trace is anon
515     session_for(create(:user))
516     get trace_icon_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
517     assert_response :forbidden
518
519     # And finally we should be able to do it with the owner of the trace
520     session_for(anon_trace_file.user)
521     get trace_icon_path(:display_name => anon_trace_file.user.display_name, :id => anon_trace_file)
522     check_trace_icon anon_trace_file
523   end
524
525   # Test downloading the icon for a trace that doesn't exist
526   def test_icon_not_found
527     deleted_trace_file = create(:trace, :deleted)
528
529     # First with a trace that has never existed
530     get trace_icon_path(:display_name => create(:user).display_name, :id => 0)
531     assert_response :not_found
532
533     # Now with a trace that has been deleted
534     session_for(deleted_trace_file.user)
535     get trace_icon_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
536     assert_response :not_found
537   end
538
539   # Test fetching the new trace page
540   def test_new_get
541     # First with no auth
542     get new_trace_path
543     assert_response :redirect
544     assert_redirected_to :controller => :users, :action => :login, :referer => new_trace_path
545
546     # Now authenticated as a user with gps.trace.visibility set
547     user = create(:user)
548     create(:user_preference, :user => user, :k => "gps.trace.visibility", :v => "identifiable")
549     session_for(user)
550     get new_trace_path
551     assert_response :success
552     assert_template :new
553     assert_select "select#trace_visibility option[value=identifiable][selected]", 1
554
555     # Now authenticated as a user with gps.trace.public set
556     second_user = create(:user)
557     create(:user_preference, :user => second_user, :k => "gps.trace.public", :v => "default")
558     session_for(second_user)
559     get new_trace_path
560     assert_response :success
561     assert_template :new
562     assert_select "select#trace_visibility option[value=public][selected]", 1
563
564     # Now authenticated as a user with no preferences
565     third_user = create(:user)
566     session_for(third_user)
567     get new_trace_path
568     assert_response :success
569     assert_template :new
570     assert_select "select#trace_visibility option[value=private][selected]", 1
571   end
572
573   # Test creating a trace
574   def test_create_post
575     # Get file to use
576     fixture = Rails.root.join("test/gpx/fixtures/a.gpx")
577     file = Rack::Test::UploadedFile.new(fixture, "application/gpx+xml")
578     user = create(:user)
579
580     # First with no auth
581     post traces_path(:trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" })
582     assert_response :forbidden
583
584     # Rewind the file
585     file.rewind
586
587     # Now authenticated
588     create(:user_preference, :user => user, :k => "gps.trace.visibility", :v => "identifiable")
589     assert_not_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
590     session_for(user)
591     post traces_path, :params => { :trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" } }
592     assert_response :redirect
593     assert_redirected_to :action => :index, :display_name => user.display_name
594     assert_match(/file has been uploaded/, flash[:notice])
595     trace = Trace.order(:id => :desc).first
596     assert_equal "a.gpx", trace.name
597     assert_equal "New Trace", trace.description
598     assert_equal %w[new trace], trace.tags.order(:tag).collect(&:tag)
599     assert_equal "trackable", trace.visibility
600     assert_not trace.inserted
601     assert_equal File.new(fixture).read, File.new(trace.trace_name).read
602     trace.destroy
603     assert_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
604   end
605
606   # Test creating a trace with validation errors
607   def test_create_post_with_validation_errors
608     # Get file to use
609     fixture = Rails.root.join("test/gpx/fixtures/a.gpx")
610     file = Rack::Test::UploadedFile.new(fixture, "application/gpx+xml")
611     user = create(:user)
612
613     # Now authenticated
614     create(:user_preference, :user => user, :k => "gps.trace.visibility", :v => "identifiable")
615     assert_not_equal "trackable", user.preferences.where(:k => "gps.trace.visibility").first.v
616     session_for(user)
617     post traces_path, :params => { :trace => { :gpx_file => file, :description => "", :tagstring => "new,trace", :visibility => "trackable" } }
618     assert_template :new
619     assert_match "is too short (minimum is 1 character)", response.body
620   end
621
622   # Test fetching the edit page for a trace using GET
623   def test_edit_get
624     public_trace_file = create(:trace, :visibility => "public")
625     deleted_trace_file = create(:trace, :deleted)
626
627     # First with no auth
628     get edit_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
629     assert_response :redirect
630     assert_redirected_to :controller => :users, :action => :login, :referer => edit_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file.id)
631
632     # Now with some other user, which should fail
633     session_for(create(:user))
634     get edit_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
635     assert_response :forbidden
636
637     # Now with a trace which doesn't exist
638     session_for(create(:user))
639     get edit_trace_path(:display_name => create(:user).display_name, :id => 0)
640     assert_response :not_found
641
642     # Now with a trace which has been deleted
643     session_for(deleted_trace_file.user)
644     get edit_trace_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
645     assert_response :not_found
646
647     # Finally with a trace that we are allowed to edit
648     session_for(public_trace_file.user)
649     get edit_trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
650     assert_response :success
651   end
652
653   # Test saving edits to a trace
654   def test_update
655     public_trace_file = create(:trace, :visibility => "public")
656     deleted_trace_file = create(:trace, :deleted)
657
658     # New details
659     new_details = { :description => "Changed description", :tagstring => "new_tag", :visibility => "private" }
660
661     # First with no auth
662     put trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file, :trace => new_details)
663     assert_response :forbidden
664
665     # Now with some other user, which should fail
666     session_for(create(:user))
667     put trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file, :trace => new_details)
668     assert_response :forbidden
669
670     # Now with a trace which doesn't exist
671     session_for(create(:user))
672     put trace_path(:display_name => create(:user).display_name, :id => 0, :trace => new_details)
673     assert_response :not_found
674
675     # Now with a trace which has been deleted
676     session_for(deleted_trace_file.user)
677     put trace_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file, :trace => new_details)
678     assert_response :not_found
679
680     # Finally with a trace that we are allowed to edit
681     session_for(public_trace_file.user)
682     put trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file, :trace => new_details)
683     assert_response :redirect
684     assert_redirected_to :action => :show, :display_name => public_trace_file.user.display_name
685     trace = Trace.find(public_trace_file.id)
686     assert_equal new_details[:description], trace.description
687     assert_equal new_details[:tagstring], trace.tagstring
688     assert_equal new_details[:visibility], trace.visibility
689   end
690
691   # Test destroying a trace
692   def test_destroy
693     public_trace_file = create(:trace, :visibility => "public")
694     deleted_trace_file = create(:trace, :deleted)
695
696     # First with no auth
697     delete trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
698     assert_response :forbidden
699
700     # Now with some other user, which should fail
701     session_for(create(:user))
702     delete trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
703     assert_response :forbidden
704
705     # Now with a trace which doesn't exist
706     session_for(create(:user))
707     delete trace_path(:display_name => create(:user).display_name, :id => 0)
708     assert_response :not_found
709
710     # Now with a trace has already been deleted
711     session_for(deleted_trace_file.user)
712     delete trace_path(:display_name => deleted_trace_file.user.display_name, :id => deleted_trace_file)
713     assert_response :not_found
714
715     # Now with a trace that we are allowed to delete
716     session_for(public_trace_file.user)
717     delete trace_path(:display_name => public_trace_file.user.display_name, :id => public_trace_file)
718     assert_response :redirect
719     assert_redirected_to :action => :index, :display_name => public_trace_file.user.display_name
720     trace = Trace.find(public_trace_file.id)
721     assert_not trace.visible
722
723     # Finally with a trace that is destroyed by an admin
724     public_trace_file = create(:trace, :visibility => "public")
725     admin = create(:administrator_user)
726     session_for(admin)
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   end
733
734   private
735
736   def check_trace_feed(traces)
737     assert_response :success
738     assert_template "georss"
739     assert_equal "application/rss+xml", @response.media_type
740     assert_select "rss", :count => 1 do
741       assert_select "channel", :count => 1 do
742         assert_select "title"
743         assert_select "description"
744         assert_select "link"
745         assert_select "image"
746         assert_select "item", :count => traces.length do |items|
747           traces.zip(items).each do |trace, item|
748             assert_select item, "title", trace.name
749             assert_select item, "link", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
750             assert_select item, "guid", "http://www.example.com/user/#{ERB::Util.u(trace.user.display_name)}/traces/#{trace.id}"
751             assert_select item, "description"
752             # assert_select item, "dc:creator", trace.user.display_name
753             assert_select item, "pubDate", trace.timestamp.rfc822
754           end
755         end
756       end
757     end
758   end
759
760   def check_trace_index(traces)
761     assert_response :success
762     assert_template "index"
763
764     if traces.empty?
765       assert_select "h4", /Nothing here yet/
766     else
767       assert_select "table#trace_list tbody", :count => 1 do
768         assert_select "tr", :count => traces.length do |rows|
769           traces.zip(rows).each do |trace, row|
770             assert_select row, "a", Regexp.new(Regexp.escape(trace.name))
771             assert_select row, "span", Regexp.new(Regexp.escape("(#{trace.size} points)")) if trace.inserted?
772             assert_select row, "td", Regexp.new(Regexp.escape(trace.description))
773             assert_select row, "td", Regexp.new(Regexp.escape("by #{trace.user.display_name}"))
774           end
775         end
776       end
777     end
778   end
779
780   def check_trace_show(trace)
781     assert_response :success
782     assert_template "show"
783
784     assert_select "table", :count => 1 do
785       assert_select "td", /^#{Regexp.quote(trace.name)} /
786       assert_select "td", trace.user.display_name
787       assert_select "td", trace.description
788     end
789   end
790
791   def check_trace_data(trace, digest, content_type = "application/gpx+xml", extension = "gpx")
792     assert_response :success
793     assert_equal digest, Digest::MD5.hexdigest(response.body)
794     assert_equal content_type, response.media_type
795     assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"; filename*=UTF-8''#{trace.id}.#{extension}", @response.header["Content-Disposition"]
796   end
797
798   def check_trace_picture(trace)
799     assert_response :success
800     assert_equal "image/gif", response.media_type
801     assert_equal trace.large_picture, response.body
802   end
803
804   def check_trace_icon(trace)
805     assert_response :success
806     assert_equal "image/gif", response.media_type
807     assert_equal trace.icon_picture, response.body
808   end
809 end