]> git.openstreetmap.org Git - rails.git/blob - test/controllers/trace_controller_test.rb
9170d6e2e70837fbe4633197cbef856c5f33105d
[rails.git] / test / controllers / trace_controller_test.rb
1 require "test_helper"
2 require "minitest/mock"
3
4 class TraceControllerTest < ActionController::TestCase
5   fixtures :users
6
7   def setup
8     @gpx_trace_dir = Object.send("remove_const", "GPX_TRACE_DIR")
9     Object.const_set("GPX_TRACE_DIR", File.dirname(__FILE__) + "/../traces")
10
11     @gpx_image_dir = Object.send("remove_const", "GPX_IMAGE_DIR")
12     Object.const_set("GPX_IMAGE_DIR", File.dirname(__FILE__) + "/../traces")
13   end
14
15   def teardown
16     Object.send("remove_const", "GPX_TRACE_DIR")
17     Object.const_set("GPX_TRACE_DIR", @gpx_trace_dir)
18
19     Object.send("remove_const", "GPX_IMAGE_DIR")
20     Object.const_set("GPX_IMAGE_DIR", @gpx_image_dir)
21   end
22
23   ##
24   # test all routes which lead to this controller
25   def test_routes
26     assert_routing(
27       { :path => "/api/0.6/gpx/create", :method => :post },
28       { :controller => "trace", :action => "api_create" }
29     )
30     assert_routing(
31       { :path => "/api/0.6/gpx/1", :method => :get },
32       { :controller => "trace", :action => "api_read", :id => "1" }
33     )
34     assert_routing(
35       { :path => "/api/0.6/gpx/1", :method => :put },
36       { :controller => "trace", :action => "api_update", :id => "1" }
37     )
38     assert_routing(
39       { :path => "/api/0.6/gpx/1", :method => :delete },
40       { :controller => "trace", :action => "api_delete", :id => "1" }
41     )
42     assert_recognizes(
43       { :controller => "trace", :action => "api_read", :id => "1" },
44       { :path => "/api/0.6/gpx/1/details", :method => :get }
45     )
46     assert_routing(
47       { :path => "/api/0.6/gpx/1/data", :method => :get },
48       { :controller => "trace", :action => "api_data", :id => "1" }
49     )
50     assert_routing(
51       { :path => "/api/0.6/gpx/1/data.xml", :method => :get },
52       { :controller => "trace", :action => "api_data", :id => "1", :format => "xml" }
53     )
54
55     assert_routing(
56       { :path => "/traces", :method => :get },
57       { :controller => "trace", :action => "list" }
58     )
59     assert_routing(
60       { :path => "/traces/page/1", :method => :get },
61       { :controller => "trace", :action => "list", :page => "1" }
62     )
63     assert_routing(
64       { :path => "/traces/tag/tagname", :method => :get },
65       { :controller => "trace", :action => "list", :tag => "tagname" }
66     )
67     assert_routing(
68       { :path => "/traces/tag/tagname/page/1", :method => :get },
69       { :controller => "trace", :action => "list", :tag => "tagname", :page => "1" }
70     )
71     assert_routing(
72       { :path => "/user/username/traces", :method => :get },
73       { :controller => "trace", :action => "list", :display_name => "username" }
74     )
75     assert_routing(
76       { :path => "/user/username/traces/page/1", :method => :get },
77       { :controller => "trace", :action => "list", :display_name => "username", :page => "1" }
78     )
79     assert_routing(
80       { :path => "/user/username/traces/tag/tagname", :method => :get },
81       { :controller => "trace", :action => "list", :display_name => "username", :tag => "tagname" }
82     )
83     assert_routing(
84       { :path => "/user/username/traces/tag/tagname/page/1", :method => :get },
85       { :controller => "trace", :action => "list", :display_name => "username", :tag => "tagname", :page => "1" }
86     )
87
88     assert_routing(
89       { :path => "/traces/mine", :method => :get },
90       { :controller => "trace", :action => "mine" }
91     )
92     assert_routing(
93       { :path => "/traces/mine/page/1", :method => :get },
94       { :controller => "trace", :action => "mine", :page => "1" }
95     )
96     assert_routing(
97       { :path => "/traces/mine/tag/tagname", :method => :get },
98       { :controller => "trace", :action => "mine", :tag => "tagname" }
99     )
100     assert_routing(
101       { :path => "/traces/mine/tag/tagname/page/1", :method => :get },
102       { :controller => "trace", :action => "mine", :tag => "tagname", :page => "1" }
103     )
104
105     assert_routing(
106       { :path => "/traces/rss", :method => :get },
107       { :controller => "trace", :action => "georss", :format => :rss }
108     )
109     assert_routing(
110       { :path => "/traces/tag/tagname/rss", :method => :get },
111       { :controller => "trace", :action => "georss", :tag => "tagname", :format => :rss }
112     )
113     assert_routing(
114       { :path => "/user/username/traces/rss", :method => :get },
115       { :controller => "trace", :action => "georss", :display_name => "username", :format => :rss }
116     )
117     assert_routing(
118       { :path => "/user/username/traces/tag/tagname/rss", :method => :get },
119       { :controller => "trace", :action => "georss", :display_name => "username", :tag => "tagname", :format => :rss }
120     )
121
122     assert_routing(
123       { :path => "/user/username/traces/1", :method => :get },
124       { :controller => "trace", :action => "view", :display_name => "username", :id => "1" }
125     )
126     assert_routing(
127       { :path => "/user/username/traces/1/picture", :method => :get },
128       { :controller => "trace", :action => "picture", :display_name => "username", :id => "1" }
129     )
130     assert_routing(
131       { :path => "/user/username/traces/1/icon", :method => :get },
132       { :controller => "trace", :action => "icon", :display_name => "username", :id => "1" }
133     )
134
135     assert_routing(
136       { :path => "/trace/create", :method => :get },
137       { :controller => "trace", :action => "create" }
138     )
139     assert_routing(
140       { :path => "/trace/create", :method => :post },
141       { :controller => "trace", :action => "create" }
142     )
143     assert_routing(
144       { :path => "/trace/1/data", :method => :get },
145       { :controller => "trace", :action => "data", :id => "1" }
146     )
147     assert_routing(
148       { :path => "/trace/1/data.xml", :method => :get },
149       { :controller => "trace", :action => "data", :id => "1", :format => "xml" }
150     )
151     assert_routing(
152       { :path => "/trace/1/edit", :method => :get },
153       { :controller => "trace", :action => "edit", :id => "1" }
154     )
155     assert_routing(
156       { :path => "/trace/1/edit", :method => :post },
157       { :controller => "trace", :action => "edit", :id => "1" }
158     )
159     assert_routing(
160       { :path => "/trace/1/edit", :method => :patch },
161       { :controller => "trace", :action => "edit", :id => "1" }
162     )
163     assert_routing(
164       { :path => "/trace/1/delete", :method => :post },
165       { :controller => "trace", :action => "delete", :id => "1" }
166     )
167   end
168
169   # Check that the list of changesets is displayed
170   def test_list
171     # First with the public list
172     get :list
173     check_trace_list Trace.visible_to_all
174
175     # Restrict traces to those with a given tag
176     get :list, :tag => "London"
177     check_trace_list Trace.tagged("London").visible_to_all
178
179     # Should see more when we are logged in
180     get :list, {}, { :user => users(:public_user).id }
181     check_trace_list Trace.visible_to(users(:public_user).id)
182
183     # Again, we should see more when we are logged in
184     get :list, { :tag => "London" }, { :user => users(:public_user).id }
185     check_trace_list Trace.tagged("London").visible_to(users(:public_user).id)
186   end
187
188   # Check that I can get mine
189   def test_list_mine
190     # First try to get it when not logged in
191     get :mine
192     assert_redirected_to :controller => "user", :action => "login", :referer => "/traces/mine"
193
194     # Now try when logged in
195     get :mine, {}, { :user => users(:public_user).id }
196     assert_redirected_to :controller => "trace", :action => "list", :display_name => users(:public_user).display_name
197
198     # Fetch the actual list
199     get :list, { :display_name => users(:public_user).display_name }, { :user => users(:public_user).id }
200     check_trace_list users(:public_user).traces
201   end
202
203   # Check the list of changesets for a specific user
204   def test_list_user
205     # Test a user with no traces
206     get :list, :display_name => users(:second_public_user).display_name
207     check_trace_list users(:second_public_user).traces.visible_to_all
208
209     # Test a user with some traces - should see only public ones
210     get :list, :display_name => users(:public_user).display_name
211     check_trace_list users(:public_user).traces.visible_to_all
212
213     # Should still see only public ones when authenticated as another user
214     get :list, { :display_name => users(:public_user).display_name }, { :user => users(:normal_user).id }
215     check_trace_list users(:public_user).traces.visible_to_all
216
217     # Should see all traces when authenticated as the target user
218     get :list, { :display_name => users(:public_user).display_name }, { :user => users(:public_user).id }
219     check_trace_list users(:public_user).traces
220
221     # Should only see traces with the correct tag when a tag is specified
222     get :list, { :display_name => users(:public_user).display_name, :tag => "London" }, { :user => users(:public_user).id }
223     check_trace_list users(:public_user).traces.tagged("London")
224
225     # Should get an error if the user does not exist
226     get :list, :display_name => "UnknownUser"
227     assert_response :not_found
228     assert_template "user/no_such_user"
229   end
230
231   # Check that the rss loads
232   def test_rss
233     # First with the public feed
234     get :georss, :format => :rss
235     check_trace_feed Trace.visible_to_all
236
237     # Restrict traces to those with a given tag
238     get :georss, :tag => "London", :format => :rss
239     check_trace_feed Trace.tagged("London").visible_to_all
240
241     # Restrict traces to those for a given user
242     get :georss, :display_name => users(:public_user).display_name, :format => :rss
243     check_trace_feed users(:public_user).traces.visible_to_all
244
245     # Restrict traces to those for a given user with a tiven tag
246     get :georss, :display_name => users(:public_user).display_name, :tag => "Birmingham", :format => :rss
247     check_trace_feed users(:public_user).traces.tagged("Birmingham").visible_to_all
248   end
249
250   # Test viewing a trace
251   def test_view
252     public_trace_file = create(:trace, :visibility => "public")
253
254     # First with no auth, which should work since the trace is public
255     get :view, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
256     check_trace_view public_trace_file
257
258     # Now with some other user, which should work since the trace is public
259     get :view, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
260     check_trace_view public_trace_file
261
262     # And finally we should be able to do it with the owner of the trace
263     get :view, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
264     check_trace_view public_trace_file
265   end
266
267   # Check an anonymous trace can't be viewed by another user
268   def test_view_anon
269     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
270
271     # First with no auth
272     get :view, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
273     assert_response :redirect
274     assert_redirected_to :action => :list
275
276     # Now with some other user, which should not work since the trace is anon
277     get :view, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:normal_user).id }
278     assert_response :redirect
279     assert_redirected_to :action => :list
280
281     # And finally we should be able to do it with the owner of the trace
282     get :view, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:public_user).id }
283     check_trace_view anon_trace_file
284   end
285
286   # Test viewing a trace that doesn't exist
287   def test_view_not_found
288     # First with no auth
289     get :view, :display_name => users(:public_user).display_name, :id => 0
290     assert_response :redirect
291     assert_redirected_to :action => :list
292
293     # Now with some other user
294     get :view, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
295     assert_response :redirect
296     assert_redirected_to :action => :list
297
298     # And finally we should not be able to view a deleted trace
299     deleted_trace_file = create(:trace, :deleted)
300     get :view, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
301     assert_response :redirect
302     assert_redirected_to :action => :list
303   end
304
305   # Test downloading a trace
306   def test_data
307     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
308     # We need to stub both the trace_name, to control which file from test/traces is used,
309     # and also the Trace.find method so that our stubbed object is used by the controller.
310     public_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
311       Trace.stub :find, public_trace_file do
312         # First with no auth, which should work since the trace is public
313         get :data, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
314         check_trace_data public_trace_file
315
316         # Now with some other user, which should work since the trace is public
317         get :data, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
318         check_trace_data public_trace_file
319
320         # And finally we should be able to do it with the owner of the trace
321         get :data, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
322         check_trace_data public_trace_file
323       end
324     end
325   end
326
327   # Test downloading a compressed trace
328   def test_data_compressed
329     identifiable_trace_file = create(:trace, :visibility => "identifiable")
330     identifiable_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/4.gpx" do
331       Trace.stub :find, identifiable_trace_file do
332         # First get the data as is
333         get :data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id
334         check_trace_data identifiable_trace_file, "application/x-gzip", "gpx.gz"
335
336         # Now ask explicitly for XML format
337         get :data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id, :format => "xml"
338         check_trace_data identifiable_trace_file, "application/xml", "xml"
339
340         # Now ask explicitly for GPX format
341         get :data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id, :format => "gpx"
342         check_trace_data identifiable_trace_file
343       end
344     end
345   end
346
347   # Check an anonymous trace can't be downloaded by another user
348   def test_data_anon
349     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
350     anon_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/2.gpx" do
351       # First with no auth
352       get :data, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
353       assert_response :not_found
354
355       # Now with some other user, which shouldn't work since the trace is anon
356       get :data, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:normal_user).id }
357       assert_response :not_found
358
359       # And finally we should be able to do it with the owner of the trace
360       Trace.stub :find, anon_trace_file do
361         get :data, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:public_user).id }
362         check_trace_data anon_trace_file
363       end
364     end
365   end
366
367   # Test downloading a trace that doesn't exist
368   def test_data_not_found
369     # First with no auth and a trace that has never existed
370     get :data, :display_name => users(:public_user).display_name, :id => 0
371     assert_response :not_found
372
373     # Now with a trace that has never existed
374     get :data, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
375     assert_response :not_found
376
377     # Now with a trace that has been deleted
378     deleted_trace_file = create(:trace, :deleted)
379     get :data, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
380     assert_response :not_found
381   end
382
383   # Test downloading the picture for a trace
384   def test_picture
385     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
386     public_trace_file.stub :large_picture_name, "#{GPX_TRACE_DIR}/1.gif" do
387       Trace.stub :find, public_trace_file do
388         # First with no auth, which should work since the trace is public
389         get :picture, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
390         check_trace_picture public_trace_file
391
392         # Now with some other user, which should work since the trace is public
393         get :picture, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
394         check_trace_picture public_trace_file
395
396         # And finally we should be able to do it with the owner of the trace
397         get :picture, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
398         check_trace_picture public_trace_file
399       end
400     end
401   end
402
403   # Check the picture for an anonymous trace can't be downloaded by another user
404   def test_picture_anon
405     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
406     anon_trace_file.stub :large_picture_name, "#{GPX_TRACE_DIR}/2.gif" do
407       # First with no auth
408       get :picture, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
409       assert_response :forbidden
410
411       # Now with some other user, which shouldn't work since the trace is anon
412       get :picture, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:normal_user).id }
413       assert_response :forbidden
414
415       # And finally we should be able to do it with the owner of the trace
416       Trace.stub :find, anon_trace_file do
417         get :picture, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:public_user).id }
418         check_trace_picture anon_trace_file
419       end
420     end
421   end
422
423   # Test downloading the picture for a trace that doesn't exist
424   def test_picture_not_found
425     # First with no auth, which should work since the trace is public
426     get :picture, :display_name => users(:public_user).display_name, :id => 0
427     assert_response :not_found
428
429     # Now with some other user, which should work since the trace is public
430     get :picture, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
431     assert_response :not_found
432
433     # And finally we should not be able to do it with a deleted trace
434     deleted_trace_file = create(:trace, :deleted)
435     get :picture, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
436     assert_response :not_found
437   end
438
439   # Test downloading the icon for a trace
440   def test_icon
441     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
442     public_trace_file.stub :icon_picture_name, "#{GPX_TRACE_DIR}/1_icon.gif" do
443       Trace.stub :find, public_trace_file do
444         # First with no auth, which should work since the trace is public
445         get :icon, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
446         check_trace_icon public_trace_file
447
448         # Now with some other user, which should work since the trace is public
449         get :icon, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
450         check_trace_icon public_trace_file
451
452         # And finally we should be able to do it with the owner of the trace
453         get :icon, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
454         check_trace_icon public_trace_file
455       end
456     end
457   end
458
459   # Check the icon for an anonymous trace can't be downloaded by another user
460   def test_icon_anon
461     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
462     anon_trace_file.stub :icon_picture_name, "#{GPX_TRACE_DIR}/2_icon.gif" do
463       # First with no auth
464       get :icon, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
465       assert_response :forbidden
466
467       # Now with some other user, which shouldn't work since the trace is anon
468       get :icon, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:normal_user).id }
469       assert_response :forbidden
470
471       # And finally we should be able to do it with the owner of the trace
472       Trace.stub :find, anon_trace_file do
473         get :icon, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:public_user).id }
474         check_trace_icon anon_trace_file
475       end
476     end
477   end
478
479   # Test downloading the icon for a trace that doesn't exist
480   def test_icon_not_found
481     # First with no auth
482     get :icon, :display_name => users(:public_user).display_name, :id => 0
483     assert_response :not_found
484
485     # Now with some other user
486     get :icon, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
487     assert_response :not_found
488
489     # And finally we should not be able to do it with a deleted trace
490     deleted_trace_file = create(:trace, :deleted)
491     get :icon, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
492     assert_response :not_found
493   end
494
495   # Test fetching the create page
496   def test_create_get
497     # First with no auth
498     get :create
499     assert_response :redirect
500     assert_redirected_to :controller => :user, :action => :login, :referer => trace_create_path
501
502     # Now authenticated as a user with gps.trace.visibility set
503     create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
504     get :create, {}, { :user => users(:public_user).id }
505     assert_response :success
506     assert_template :create
507     assert_select "select#trace_visibility option[value=identifiable][selected]", 1
508
509     # Now authenticated as a user with gps.trace.public set
510     create(:user_preference, :user => users(:second_public_user), :k => "gps.trace.public", :v => "default")
511     get :create, {}, { :user => users(:second_public_user).id }
512     assert_response :success
513     assert_template :create
514     assert_select "select#trace_visibility option[value=public][selected]", 1
515
516     # Now authenticated as a user with no preferences
517     get :create, {}, { :user => users(:normal_user).id }
518     assert_response :success
519     assert_template :create
520     assert_select "select#trace_visibility option[value=private][selected]", 1
521   end
522
523   # Test creating a trace
524   def test_create_post
525     public_trace_file = create(:trace, :visibility => "public")
526     public_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
527       # Get file to use
528       file = Rack::Test::UploadedFile.new(public_trace_file.trace_name, "application/gpx+xml")
529
530       # First with no auth
531       post :create, :trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" }
532       assert_response :forbidden
533
534       # Now authenticated
535       create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
536       assert_not_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
537       post :create, { :trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" } }, { :user => users(:public_user).id }
538       assert_response :redirect
539       assert_redirected_to :action => :list, :display_name => users(:public_user).display_name
540       assert_match /file has been uploaded/, flash[:notice]
541       trace = Trace.order(:id => :desc).first
542       assert_equal "1.gpx", trace.name
543       assert_equal "New Trace", trace.description
544       assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
545       assert_equal "trackable", trace.visibility
546       assert_equal false, trace.inserted
547       assert_equal File.new(public_trace_file.trace_name).read, File.new(trace.trace_name).read
548       trace.destroy
549       assert_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
550     end
551   end
552
553   # Test fetching the edit page for a trace
554   def test_edit_get
555     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
556     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
557
558     # First with no auth
559     get :edit, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
560     assert_response :redirect
561     assert_redirected_to :controller => :user, :action => :login, :referer => trace_edit_path(:display_name => users(:normal_user).display_name, :id => public_trace_file.id)
562
563     # Now with some other user, which should fail
564     get :edit, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
565     assert_response :forbidden
566
567     # Now with a trace which doesn't exist
568     get :edit, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
569     assert_response :not_found
570
571     # Now with a trace which has been deleted
572     get :edit, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
573     assert_response :not_found
574
575     # Finally with a trace that we are allowed to edit
576     get :edit, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
577     assert_response :success
578   end
579
580   # Test saving edits to a trace
581   def test_edit_post
582     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
583     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
584     # New details
585     new_details = { :description => "Changed description", :tagstring => "new_tag", :visibility => "private" }
586
587     # First with no auth
588     post :edit, :display_name => users(:normal_user).display_name, :id => public_trace_file.id, :trace => new_details
589     assert_response :forbidden
590
591     # Now with some other user, which should fail
592     post :edit, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id, :trace => new_details }, { :user => users(:public_user).id }
593     assert_response :forbidden
594
595     # Now with a trace which doesn't exist
596     post :edit, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id, :trace => new_details }
597     assert_response :not_found
598
599     # Now with a trace which has been deleted
600     post :edit, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id, :trace => new_details }, { :user => users(:public_user).id }
601     assert_response :not_found
602
603     # Finally with a trace that we are allowed to edit
604     post :edit, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id, :trace => new_details }, { :user => users(:normal_user).id }
605     assert_response :redirect
606     assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
607     trace = Trace.find(public_trace_file.id)
608     assert_equal new_details[:description], trace.description
609     assert_equal new_details[:tagstring], trace.tagstring
610     assert_equal new_details[:visibility], trace.visibility
611   end
612
613   # Test deleting a trace
614   def test_delete
615     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
616     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
617
618     # First with no auth
619     post :delete, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
620     assert_response :forbidden
621
622     # Now with some other user, which should fail
623     post :delete, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
624     assert_response :forbidden
625
626     # Now with a trace which doesn't exist
627     post :delete, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
628     assert_response :not_found
629
630     # Now with a trace has already been deleted
631     post :delete, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
632     assert_response :not_found
633
634     # Finally with a trace that we are allowed to delete
635     post :delete, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
636     assert_response :redirect
637     assert_redirected_to :action => :list, :display_name => users(:normal_user).display_name
638     trace = Trace.find(public_trace_file.id)
639     assert_equal false, trace.visible
640   end
641
642   # Check getting a specific trace through the api
643   def test_api_read
644     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
645
646     # First with no auth
647     get :api_read, :id => public_trace_file.id
648     assert_response :unauthorized
649
650     # Now with some other user, which should work since the trace is public
651     basic_authorization(users(:public_user).display_name, "test")
652     get :api_read, :id => public_trace_file.id
653     assert_response :success
654
655     # And finally we should be able to do it with the owner of the trace
656     basic_authorization(users(:normal_user).display_name, "test")
657     get :api_read, :id => public_trace_file.id
658     assert_response :success
659   end
660
661   # Check an anoymous trace can't be specifically fetched by another user
662   def test_api_read_anon
663     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
664
665     # First with no auth
666     get :api_read, :id => anon_trace_file.id
667     assert_response :unauthorized
668
669     # Now try with another user, which shouldn't work since the trace is anon
670     basic_authorization(users(:normal_user).display_name, "test")
671     get :api_read, :id => anon_trace_file.id
672     assert_response :forbidden
673
674     # And finally we should be able to get the trace details with the trace owner
675     basic_authorization(users(:public_user).display_name, "test")
676     get :api_read, :id => anon_trace_file.id
677     assert_response :success
678   end
679
680   # Check the api details for a trace that doesn't exist
681   def test_api_read_not_found
682     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
683
684     # Try first with no auth, as it should require it
685     get :api_read, :id => 0
686     assert_response :unauthorized
687
688     # Login, and try again
689     basic_authorization(users(:public_user).display_name, "test")
690     get :api_read, :id => 0
691     assert_response :not_found
692
693     # Now try a trace which did exist but has been deleted
694     basic_authorization(users(:public_user).display_name, "test")
695     get :api_read, :id => deleted_trace_file.id
696     assert_response :not_found
697   end
698
699   # Test downloading a trace through the api
700   def test_api_data
701     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
702     public_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
703       visible = MiniTest::Mock.new
704       visible.expect :find, public_trace_file, [String]
705       visible.expect :find, public_trace_file, [String]
706       Trace.stub :visible, visible do
707         # First with no auth
708         get :api_data, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
709         assert_response :unauthorized
710
711         # Now with some other user, which should work since the trace is public
712         basic_authorization(users(:public_user).display_name, "test")
713         get :api_data, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
714         check_trace_data public_trace_file
715
716         # # And finally we should be able to do it with the owner of the trace
717         basic_authorization(users(:normal_user).display_name, "test")
718         get :api_data, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
719         check_trace_data public_trace_file
720       end
721     end
722   end
723
724   # Test downloading a compressed trace through the api
725   def test_api_data_compressed
726     identifiable_trace_file = create(:trace, :visibility => "identifiable", :user => users(:public_user))
727     identifiable_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/4.gpx" do
728       visible = MiniTest::Mock.new
729       visible.expect :find, identifiable_trace_file, [String]
730       visible.expect :find, identifiable_trace_file, [String]
731       visible.expect :find, identifiable_trace_file, [String]
732       Trace.stub :visible, visible do
733         # Authenticate as the owner of the trace we will be using
734         basic_authorization(users(:public_user).display_name, "test")
735
736         # First get the data as is
737         get :api_data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id
738         check_trace_data identifiable_trace_file, "application/x-gzip", "gpx.gz"
739
740         # Now ask explicitly for XML format
741         get :api_data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id, :format => "xml"
742         check_trace_data identifiable_trace_file, "application/xml", "xml"
743
744         # # Now ask explicitly for GPX format
745         get :api_data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id, :format => "gpx"
746         check_trace_data identifiable_trace_file
747       end
748     end
749   end
750
751   # Check an anonymous trace can't be downloaded by another user through the api
752   def test_api_data_anon
753     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
754     anon_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/2.gpx" do
755       visible = MiniTest::Mock.new
756       visible.expect :find, anon_trace_file, [String]
757       visible.expect :find, anon_trace_file, [String]
758       Trace.stub :visible, visible do
759         # First with no auth
760         get :api_data, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
761         assert_response :unauthorized
762
763         # Now with some other user, which shouldn't work since the trace is anon
764         basic_authorization(users(:normal_user).display_name, "test")
765         get :api_data, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
766         assert_response :forbidden
767
768         # And finally we should be able to do it with the owner of the trace
769         basic_authorization(users(:public_user).display_name, "test")
770         get :api_data, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
771         check_trace_data anon_trace_file
772       end
773     end
774   end
775
776   # Test downloading a trace that doesn't exist through the api
777   def test_api_data_not_found
778     # First with no auth
779     get :api_data, :display_name => users(:public_user).display_name, :id => 0
780     assert_response :unauthorized
781
782     # Now with a trace that has never existed
783     basic_authorization(users(:public_user).display_name, "test")
784     get :api_data, :display_name => users(:public_user).display_name, :id => 0
785     assert_response :not_found
786
787     # Now with a trace that has been deleted
788     deleted_trace_file = create(:trace, :deleted)
789     basic_authorization(users(:public_user).display_name, "test")
790     get :api_data, :display_name => users(:public_user).display_name, :id => deleted_trace_file.id
791     assert_response :not_found
792   end
793
794   # Test creating a trace through the api
795   def test_api_create
796     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
797     public_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
798       # Get file to use
799       file = Rack::Test::UploadedFile.new(public_trace_file.trace_name, "application/gpx+xml")
800
801       # First with no auth
802       post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable"
803       assert_response :unauthorized
804
805       # Now authenticated
806       create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
807       assert_not_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
808       basic_authorization(users(:public_user).display_name, "test")
809       post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable"
810       assert_response :success
811       trace = Trace.find(response.body.to_i)
812       assert_equal "1.gpx", trace.name
813       assert_equal "New Trace", trace.description
814       assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
815       assert_equal "trackable", trace.visibility
816       assert_equal false, trace.inserted
817       assert_equal File.new(public_trace_file.trace_name).read, File.new(trace.trace_name).read
818       trace.destroy
819       assert_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
820
821       # Rewind the file
822       file.rewind
823
824       # Now authenticated, with the legacy public flag
825       assert_not_equal "public", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
826       basic_authorization(users(:public_user).display_name, "test")
827       post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :public => 1
828       assert_response :success
829       trace = Trace.find(response.body.to_i)
830       assert_equal "1.gpx", trace.name
831       assert_equal "New Trace", trace.description
832       assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
833       assert_equal "public", trace.visibility
834       assert_equal false, trace.inserted
835       assert_equal File.new(public_trace_file.trace_name).read, File.new(trace.trace_name).read
836       trace.destroy
837       assert_equal "public", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
838
839       # Rewind the file
840       file.rewind
841
842       # Now authenticated, with the legacy private flag
843       assert_nil users(:second_public_user).preferences.where(:k => "gps.trace.visibility").first
844       basic_authorization(users(:second_public_user).display_name, "test")
845       post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :public => 0
846       assert_response :success
847       trace = Trace.find(response.body.to_i)
848       assert_equal "1.gpx", trace.name
849       assert_equal "New Trace", trace.description
850       assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
851       assert_equal "private", trace.visibility
852       assert_equal false, trace.inserted
853       assert_equal File.new(public_trace_file.trace_name).read, File.new(trace.trace_name).read
854       trace.destroy
855       assert_equal "private", users(:second_public_user).preferences.where(:k => "gps.trace.visibility").first.v
856     end
857   end
858
859   # Check updating a trace through the api
860   def test_api_update
861     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
862     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
863     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
864
865     public_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
866       # First with no auth
867       content public_trace_file.to_xml
868       put :api_update, :id => public_trace_file.id
869       assert_response :unauthorized
870
871       # Now with some other user, which should fail
872       basic_authorization(users(:public_user).display_name, "test")
873       content public_trace_file.to_xml
874       put :api_update, :id => public_trace_file.id
875       assert_response :forbidden
876
877       # Now with a trace which doesn't exist
878       basic_authorization(users(:public_user).display_name, "test")
879       content public_trace_file.to_xml
880       put :api_update, :id => 0
881       assert_response :not_found
882
883       # Now with a trace which did exist but has been deleted
884       basic_authorization(users(:public_user).display_name, "test")
885       content deleted_trace_file.to_xml
886       put :api_update, :id => deleted_trace_file.id
887       assert_response :not_found
888
889       # Now try an update with the wrong ID
890       basic_authorization(users(:normal_user).display_name, "test")
891       content anon_trace_file.to_xml
892       put :api_update, :id => public_trace_file.id
893       assert_response :bad_request,
894                       "should not be able to update a trace with a different ID from the XML"
895
896       # And finally try an update that should work
897       basic_authorization(users(:normal_user).display_name, "test")
898       t = public_trace_file
899       t.description = "Changed description"
900       t.visibility = "private"
901       content t.to_xml
902       put :api_update, :id => t.id
903       assert_response :success
904       nt = Trace.find(t.id)
905       assert_equal nt.description, t.description
906       assert_equal nt.visibility, t.visibility
907     end
908   end
909
910   # Check deleting a trace through the api
911   def test_api_delete
912     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
913
914     # First with no auth
915     delete :api_delete, :id => public_trace_file.id
916     assert_response :unauthorized
917
918     # Now with some other user, which should fail
919     basic_authorization(users(:public_user).display_name, "test")
920     delete :api_delete, :id => public_trace_file.id
921     assert_response :forbidden
922
923     # Now with a trace which doesn't exist
924     basic_authorization(users(:public_user).display_name, "test")
925     delete :api_delete, :id => 0
926     assert_response :not_found
927
928     # And finally we should be able to do it with the owner of the trace
929     basic_authorization(users(:normal_user).display_name, "test")
930     delete :api_delete, :id => public_trace_file.id
931     assert_response :success
932
933     # Try it a second time, which should fail
934     basic_authorization(users(:normal_user).display_name, "test")
935     delete :api_delete, :id => public_trace_file.id
936     assert_response :not_found
937   end
938
939   private
940
941   def check_trace_feed(traces)
942     assert_response :success
943     assert_template "georss"
944     assert_equal "application/rss+xml", @response.content_type
945     assert_select "rss", :count => 1 do
946       assert_select "channel", :count => 1 do
947         assert_select "title"
948         assert_select "description"
949         assert_select "link"
950         assert_select "image"
951         assert_select "item", :count => traces.visible.count do |items|
952           traces.visible.order("timestamp DESC").zip(items).each do |trace, item|
953             assert_select item, "title", trace.name
954             assert_select item, "link", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
955             assert_select item, "guid", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
956             assert_select item, "description"
957             # assert_select item, "dc:creator", trace.user.display_name
958             assert_select item, "pubDate", trace.timestamp.rfc822
959           end
960         end
961       end
962     end
963   end
964
965   def check_trace_list(traces)
966     assert_response :success
967     assert_template "list"
968
969     if traces.count > 0
970       assert_select "table#trace_list tbody", :count => 1 do
971         assert_select "tr", :count => traces.visible.count do |rows|
972           traces.visible.order("timestamp DESC").zip(rows).each do |trace, row|
973             assert_select row, "a", Regexp.new(Regexp.escape(trace.name))
974             assert_select row, "span.trace_summary", Regexp.new(Regexp.escape("(#{trace.size} points)")) if trace.inserted?
975             assert_select row, "td", Regexp.new(Regexp.escape(trace.description))
976             assert_select row, "td", Regexp.new(Regexp.escape("by #{trace.user.display_name}"))
977           end
978         end
979       end
980     else
981       assert_select "h4", /Nothing here yet/
982     end
983   end
984
985   def check_trace_view(trace)
986     assert_response :success
987     assert_template "view"
988
989     assert_select "table", :count => 1 do
990       assert_select "td", /^#{Regexp.quote(trace.name)} /
991       assert_select "td", trace.user.display_name
992       assert_select "td", trace.description
993     end
994   end
995
996   def check_trace_data(trace, content_type = "application/gpx+xml", extension = "gpx")
997     assert_response :success
998     assert_equal content_type, response.content_type
999     assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"", @response.header["Content-Disposition"]
1000   end
1001
1002   def check_trace_picture(trace)
1003     assert_response :success
1004     assert_equal "image/gif", response.content_type
1005     assert_equal trace.large_picture, response.body
1006   end
1007
1008   def check_trace_icon(trace)
1009     assert_response :success
1010     assert_equal "image/gif", response.content_type
1011     assert_equal trace.icon_picture, response.body
1012   end
1013 end