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