3888b1294e2d50da798297b4a1f02c503264c957
[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     Trace.stub_any_instance :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
309       # First with no auth, which should work since the trace is public
310       get :data, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
311       check_trace_data public_trace_file
312
313       # Now with some other user, which should work since the trace is public
314       get :data, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
315       check_trace_data public_trace_file
316
317       # And finally we should be able to do it with the owner of the trace
318       get :data, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
319       check_trace_data public_trace_file
320     end
321   end
322
323   # Test downloading a compressed trace
324   def test_data_compressed
325     identifiable_trace_file = create(:trace, :visibility => "identifiable")
326     Trace.stub_any_instance :trace_name, "#{GPX_TRACE_DIR}/4.gpx" do
327       # First get the data as is
328       get :data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id
329       check_trace_data identifiable_trace_file, "application/x-gzip", "gpx.gz"
330
331       # Now ask explicitly for XML format
332       get :data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id, :format => "xml"
333       check_trace_data identifiable_trace_file, "application/xml", "xml"
334
335       # Now ask explicitly for GPX format
336       get :data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id, :format => "gpx"
337       check_trace_data identifiable_trace_file
338     end
339   end
340
341   # Check an anonymous trace can't be downloaded by another user
342   def test_data_anon
343     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
344     Trace.stub_any_instance :trace_name, "#{GPX_TRACE_DIR}/2.gpx" do
345       # First with no auth
346       get :data, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
347       assert_response :not_found
348
349       # Now with some other user, which shouldn't work since the trace is anon
350       get :data, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:normal_user).id }
351       assert_response :not_found
352
353       # And finally we should be able to do it with the owner of the trace
354       get :data, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:public_user).id }
355       check_trace_data anon_trace_file
356     end
357   end
358
359   # Test downloading a trace that doesn't exist
360   def test_data_not_found
361     # First with no auth and a trace that has never existed
362     get :data, :display_name => users(:public_user).display_name, :id => 0
363     assert_response :not_found
364
365     # Now with a trace that has never existed
366     get :data, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
367     assert_response :not_found
368
369     # Now with a trace that has been deleted
370     deleted_trace_file = create(:trace, :deleted)
371     get :data, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
372     assert_response :not_found
373   end
374
375   # Test downloading the picture for a trace
376   def test_picture
377     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
378     Trace.stub_any_instance :large_picture_name, "#{GPX_TRACE_DIR}/1.gif" do
379       # First with no auth, which should work since the trace is public
380       get :picture, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
381       check_trace_picture public_trace_file
382
383       # Now with some other user, which should work since the trace is public
384       get :picture, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
385       check_trace_picture public_trace_file
386
387       # And finally we should be able to do it with the owner of the trace
388       get :picture, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
389       check_trace_picture public_trace_file
390     end
391   end
392
393   # Check the picture for an anonymous trace can't be downloaded by another user
394   def test_picture_anon
395     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
396     Trace.stub_any_instance :large_picture_name, "#{GPX_TRACE_DIR}/2.gif" do
397       # First with no auth
398       get :picture, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
399       assert_response :forbidden
400
401       # Now with some other user, which shouldn't work since the trace is anon
402       get :picture, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:normal_user).id }
403       assert_response :forbidden
404
405       # And finally we should be able to do it with the owner of the trace
406       get :picture, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:public_user).id }
407       check_trace_picture anon_trace_file
408     end
409   end
410
411   # Test downloading the picture for a trace that doesn't exist
412   def test_picture_not_found
413     # First with no auth, which should work since the trace is public
414     get :picture, :display_name => users(:public_user).display_name, :id => 0
415     assert_response :not_found
416
417     # Now with some other user, which should work since the trace is public
418     get :picture, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
419     assert_response :not_found
420
421     # And finally we should not be able to do it with a deleted trace
422     deleted_trace_file = create(:trace, :deleted)
423     get :picture, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
424     assert_response :not_found
425   end
426
427   # Test downloading the icon for a trace
428   def test_icon
429     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
430     Trace.stub_any_instance :icon_picture_name, "#{GPX_TRACE_DIR}/1_icon.gif" do
431       # First with no auth, which should work since the trace is public
432       get :icon, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
433       check_trace_icon public_trace_file
434
435       # Now with some other user, which should work since the trace is public
436       get :icon, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
437       check_trace_icon public_trace_file
438
439       # And finally we should be able to do it with the owner of the trace
440       get :icon, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
441       check_trace_icon public_trace_file
442     end
443   end
444
445   # Check the icon for an anonymous trace can't be downloaded by another user
446   def test_icon_anon
447     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
448     Trace.stub_any_instance :icon_picture_name, "#{GPX_TRACE_DIR}/2_icon.gif" do
449       # First with no auth
450       get :icon, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
451       assert_response :forbidden
452
453       # Now with some other user, which shouldn't work since the trace is anon
454       get :icon, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:normal_user).id }
455       assert_response :forbidden
456
457       # And finally we should be able to do it with the owner of the trace
458       get :icon, { :display_name => users(:public_user).display_name, :id => anon_trace_file.id }, { :user => users(:public_user).id }
459       check_trace_icon anon_trace_file
460     end
461   end
462
463   # Test downloading the icon for a trace that doesn't exist
464   def test_icon_not_found
465     # First with no auth
466     get :icon, :display_name => users(:public_user).display_name, :id => 0
467     assert_response :not_found
468
469     # Now with some other user
470     get :icon, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
471     assert_response :not_found
472
473     # And finally we should not be able to do it with a deleted trace
474     deleted_trace_file = create(:trace, :deleted)
475     get :icon, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
476     assert_response :not_found
477   end
478
479   # Test fetching the create page
480   def test_create_get
481     # First with no auth
482     get :create
483     assert_response :redirect
484     assert_redirected_to :controller => :user, :action => :login, :referer => trace_create_path
485
486     # Now authenticated as a user with gps.trace.visibility set
487     create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
488     get :create, {}, { :user => users(:public_user).id }
489     assert_response :success
490     assert_template :create
491     assert_select "select#trace_visibility option[value=identifiable][selected]", 1
492
493     # Now authenticated as a user with gps.trace.public set
494     create(:user_preference, :user => users(:second_public_user), :k => "gps.trace.public", :v => "default")
495     get :create, {}, { :user => users(:second_public_user).id }
496     assert_response :success
497     assert_template :create
498     assert_select "select#trace_visibility option[value=public][selected]", 1
499
500     # Now authenticated as a user with no preferences
501     get :create, {}, { :user => users(:normal_user).id }
502     assert_response :success
503     assert_template :create
504     assert_select "select#trace_visibility option[value=private][selected]", 1
505   end
506
507   # Test creating a trace
508   def test_create_post
509     public_trace_file = create(:trace, :visibility => "public")
510     public_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
511       # Get file to use
512       file = Rack::Test::UploadedFile.new(public_trace_file.trace_name, "application/gpx+xml")
513
514       # First with no auth
515       post :create, :trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" }
516       assert_response :forbidden
517
518       # Now authenticated
519       create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
520       assert_not_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
521       post :create, { :trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" } }, { :user => users(:public_user).id }
522       assert_response :redirect
523       assert_redirected_to :action => :list, :display_name => users(:public_user).display_name
524       assert_match /file has been uploaded/, flash[:notice]
525       trace = Trace.order(:id => :desc).first
526       assert_equal "1.gpx", trace.name
527       assert_equal "New Trace", trace.description
528       assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
529       assert_equal "trackable", trace.visibility
530       assert_equal false, trace.inserted
531       assert_equal File.new(public_trace_file.trace_name).read, File.new(trace.trace_name).read
532       trace.destroy
533       assert_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
534     end
535   end
536
537   # Test fetching the edit page for a trace
538   def test_edit_get
539     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
540     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
541
542     # First with no auth
543     get :edit, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
544     assert_response :redirect
545     assert_redirected_to :controller => :user, :action => :login, :referer => trace_edit_path(:display_name => users(:normal_user).display_name, :id => public_trace_file.id)
546
547     # Now with some other user, which should fail
548     get :edit, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
549     assert_response :forbidden
550
551     # Now with a trace which doesn't exist
552     get :edit, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
553     assert_response :not_found
554
555     # Now with a trace which has been deleted
556     get :edit, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
557     assert_response :not_found
558
559     # Finally with a trace that we are allowed to edit
560     get :edit, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
561     assert_response :success
562   end
563
564   # Test saving edits to a trace
565   def test_edit_post
566     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
567     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
568     # New details
569     new_details = { :description => "Changed description", :tagstring => "new_tag", :visibility => "private" }
570
571     # First with no auth
572     post :edit, :display_name => users(:normal_user).display_name, :id => public_trace_file.id, :trace => new_details
573     assert_response :forbidden
574
575     # Now with some other user, which should fail
576     post :edit, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id, :trace => new_details }, { :user => users(:public_user).id }
577     assert_response :forbidden
578
579     # Now with a trace which doesn't exist
580     post :edit, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id, :trace => new_details }
581     assert_response :not_found
582
583     # Now with a trace which has been deleted
584     post :edit, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id, :trace => new_details }, { :user => users(:public_user).id }
585     assert_response :not_found
586
587     # Finally with a trace that we are allowed to edit
588     post :edit, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id, :trace => new_details }, { :user => users(:normal_user).id }
589     assert_response :redirect
590     assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
591     trace = Trace.find(public_trace_file.id)
592     assert_equal new_details[:description], trace.description
593     assert_equal new_details[:tagstring], trace.tagstring
594     assert_equal new_details[:visibility], trace.visibility
595   end
596
597   # Test deleting a trace
598   def test_delete
599     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
600     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
601
602     # First with no auth
603     post :delete, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
604     assert_response :forbidden
605
606     # Now with some other user, which should fail
607     post :delete, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:public_user).id }
608     assert_response :forbidden
609
610     # Now with a trace which doesn't exist
611     post :delete, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
612     assert_response :not_found
613
614     # Now with a trace has already been deleted
615     post :delete, { :display_name => users(:public_user).display_name, :id => deleted_trace_file.id }, { :user => users(:public_user).id }
616     assert_response :not_found
617
618     # Finally with a trace that we are allowed to delete
619     post :delete, { :display_name => users(:normal_user).display_name, :id => public_trace_file.id }, { :user => users(:normal_user).id }
620     assert_response :redirect
621     assert_redirected_to :action => :list, :display_name => users(:normal_user).display_name
622     trace = Trace.find(public_trace_file.id)
623     assert_equal false, trace.visible
624   end
625
626   # Check getting a specific trace through the api
627   def test_api_read
628     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
629
630     # First with no auth
631     get :api_read, :id => public_trace_file.id
632     assert_response :unauthorized
633
634     # Now with some other user, which should work since the trace is public
635     basic_authorization(users(:public_user).display_name, "test")
636     get :api_read, :id => public_trace_file.id
637     assert_response :success
638
639     # And finally we should be able to do it with the owner of the trace
640     basic_authorization(users(:normal_user).display_name, "test")
641     get :api_read, :id => public_trace_file.id
642     assert_response :success
643   end
644
645   # Check an anoymous trace can't be specifically fetched by another user
646   def test_api_read_anon
647     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
648
649     # First with no auth
650     get :api_read, :id => anon_trace_file.id
651     assert_response :unauthorized
652
653     # Now try with another user, which shouldn't work since the trace is anon
654     basic_authorization(users(:normal_user).display_name, "test")
655     get :api_read, :id => anon_trace_file.id
656     assert_response :forbidden
657
658     # And finally we should be able to get the trace details with the trace owner
659     basic_authorization(users(:public_user).display_name, "test")
660     get :api_read, :id => anon_trace_file.id
661     assert_response :success
662   end
663
664   # Check the api details for a trace that doesn't exist
665   def test_api_read_not_found
666     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
667
668     # Try first with no auth, as it should require it
669     get :api_read, :id => 0
670     assert_response :unauthorized
671
672     # Login, and try again
673     basic_authorization(users(:public_user).display_name, "test")
674     get :api_read, :id => 0
675     assert_response :not_found
676
677     # Now try a trace which did exist but has been deleted
678     basic_authorization(users(:public_user).display_name, "test")
679     get :api_read, :id => deleted_trace_file.id
680     assert_response :not_found
681   end
682
683   # Test downloading a trace through the api
684   def test_api_data
685     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
686     Trace.stub_any_instance :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
687       # First with no auth
688       get :api_data, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
689       assert_response :unauthorized
690
691       # Now with some other user, which should work since the trace is public
692       basic_authorization(users(:public_user).display_name, "test")
693       get :api_data, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
694       check_trace_data public_trace_file
695
696       # # And finally we should be able to do it with the owner of the trace
697       basic_authorization(users(:normal_user).display_name, "test")
698       get :api_data, :display_name => users(:normal_user).display_name, :id => public_trace_file.id
699       check_trace_data public_trace_file
700     end
701   end
702
703   # Test downloading a compressed trace through the api
704   def test_api_data_compressed
705     identifiable_trace_file = create(:trace, :visibility => "identifiable", :user => users(:public_user))
706     Trace.stub_any_instance :trace_name, "#{GPX_TRACE_DIR}/4.gpx" do
707       # Authenticate as the owner of the trace we will be using
708       basic_authorization(users(:public_user).display_name, "test")
709
710       # First get the data as is
711       get :api_data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id
712       check_trace_data identifiable_trace_file, "application/x-gzip", "gpx.gz"
713
714       # Now ask explicitly for XML format
715       get :api_data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id, :format => "xml"
716       check_trace_data identifiable_trace_file, "application/xml", "xml"
717
718       # # Now ask explicitly for GPX format
719       get :api_data, :display_name => users(:public_user).display_name, :id => identifiable_trace_file.id, :format => "gpx"
720       check_trace_data identifiable_trace_file
721     end
722   end
723
724   # Check an anonymous trace can't be downloaded by another user through the api
725   def test_api_data_anon
726     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
727     Trace.stub_any_instance :trace_name, "#{GPX_TRACE_DIR}/2.gpx" do
728       # First with no auth
729       get :api_data, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
730       assert_response :unauthorized
731
732       # Now with some other user, which shouldn't work since the trace is anon
733       basic_authorization(users(:normal_user).display_name, "test")
734       get :api_data, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
735       assert_response :forbidden
736
737       # And finally we should be able to do it with the owner of the trace
738       basic_authorization(users(:public_user).display_name, "test")
739       get :api_data, :display_name => users(:public_user).display_name, :id => anon_trace_file.id
740       check_trace_data anon_trace_file
741     end
742   end
743
744   # Test downloading a trace that doesn't exist through the api
745   def test_api_data_not_found
746     # First with no auth
747     get :api_data, :display_name => users(:public_user).display_name, :id => 0
748     assert_response :unauthorized
749
750     # Now with a trace that has never existed
751     basic_authorization(users(:public_user).display_name, "test")
752     get :api_data, :display_name => users(:public_user).display_name, :id => 0
753     assert_response :not_found
754
755     # Now with a trace that has been deleted
756     deleted_trace_file = create(:trace, :deleted)
757     basic_authorization(users(:public_user).display_name, "test")
758     get :api_data, :display_name => users(:public_user).display_name, :id => deleted_trace_file.id
759     assert_response :not_found
760   end
761
762   # Test creating a trace through the api
763   def test_api_create
764     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
765     public_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
766       # Get file to use
767       file = Rack::Test::UploadedFile.new(public_trace_file.trace_name, "application/gpx+xml")
768
769       # First with no auth
770       post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable"
771       assert_response :unauthorized
772
773       # Now authenticated
774       create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
775       assert_not_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
776       basic_authorization(users(:public_user).display_name, "test")
777       post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable"
778       assert_response :success
779       trace = Trace.find(response.body.to_i)
780       assert_equal "1.gpx", trace.name
781       assert_equal "New Trace", trace.description
782       assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
783       assert_equal "trackable", trace.visibility
784       assert_equal false, trace.inserted
785       assert_equal File.new(public_trace_file.trace_name).read, File.new(trace.trace_name).read
786       trace.destroy
787       assert_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
788
789       # Rewind the file
790       file.rewind
791
792       # Now authenticated, with the legacy public flag
793       assert_not_equal "public", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
794       basic_authorization(users(:public_user).display_name, "test")
795       post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :public => 1
796       assert_response :success
797       trace = Trace.find(response.body.to_i)
798       assert_equal "1.gpx", trace.name
799       assert_equal "New Trace", trace.description
800       assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
801       assert_equal "public", trace.visibility
802       assert_equal false, trace.inserted
803       assert_equal File.new(public_trace_file.trace_name).read, File.new(trace.trace_name).read
804       trace.destroy
805       assert_equal "public", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
806
807       # Rewind the file
808       file.rewind
809
810       # Now authenticated, with the legacy private flag
811       assert_nil users(:second_public_user).preferences.where(:k => "gps.trace.visibility").first
812       basic_authorization(users(:second_public_user).display_name, "test")
813       post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :public => 0
814       assert_response :success
815       trace = Trace.find(response.body.to_i)
816       assert_equal "1.gpx", trace.name
817       assert_equal "New Trace", trace.description
818       assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
819       assert_equal "private", trace.visibility
820       assert_equal false, trace.inserted
821       assert_equal File.new(public_trace_file.trace_name).read, File.new(trace.trace_name).read
822       trace.destroy
823       assert_equal "private", users(:second_public_user).preferences.where(:k => "gps.trace.visibility").first.v
824     end
825   end
826
827   # Check updating a trace through the api
828   def test_api_update
829     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
830     deleted_trace_file = create(:trace, :deleted, :user => users(:public_user))
831     anon_trace_file = create(:trace, :visibility => "private", :user => users(:public_user))
832
833     public_trace_file.stub :trace_name, "#{GPX_TRACE_DIR}/1.gpx" do
834       # First with no auth
835       content public_trace_file.to_xml
836       put :api_update, :id => public_trace_file.id
837       assert_response :unauthorized
838
839       # Now with some other user, which should fail
840       basic_authorization(users(:public_user).display_name, "test")
841       content public_trace_file.to_xml
842       put :api_update, :id => public_trace_file.id
843       assert_response :forbidden
844
845       # Now with a trace which doesn't exist
846       basic_authorization(users(:public_user).display_name, "test")
847       content public_trace_file.to_xml
848       put :api_update, :id => 0
849       assert_response :not_found
850
851       # Now with a trace which did exist but has been deleted
852       basic_authorization(users(:public_user).display_name, "test")
853       content deleted_trace_file.to_xml
854       put :api_update, :id => deleted_trace_file.id
855       assert_response :not_found
856
857       # Now try an update with the wrong ID
858       basic_authorization(users(:normal_user).display_name, "test")
859       content anon_trace_file.to_xml
860       put :api_update, :id => public_trace_file.id
861       assert_response :bad_request,
862                       "should not be able to update a trace with a different ID from the XML"
863
864       # And finally try an update that should work
865       basic_authorization(users(:normal_user).display_name, "test")
866       t = public_trace_file
867       t.description = "Changed description"
868       t.visibility = "private"
869       content t.to_xml
870       put :api_update, :id => t.id
871       assert_response :success
872       nt = Trace.find(t.id)
873       assert_equal nt.description, t.description
874       assert_equal nt.visibility, t.visibility
875     end
876   end
877
878   # Check deleting a trace through the api
879   def test_api_delete
880     public_trace_file = create(:trace, :visibility => "public", :user => users(:normal_user))
881
882     # First with no auth
883     delete :api_delete, :id => public_trace_file.id
884     assert_response :unauthorized
885
886     # Now with some other user, which should fail
887     basic_authorization(users(:public_user).display_name, "test")
888     delete :api_delete, :id => public_trace_file.id
889     assert_response :forbidden
890
891     # Now with a trace which doesn't exist
892     basic_authorization(users(:public_user).display_name, "test")
893     delete :api_delete, :id => 0
894     assert_response :not_found
895
896     # And finally we should be able to do it with the owner of the trace
897     basic_authorization(users(:normal_user).display_name, "test")
898     delete :api_delete, :id => public_trace_file.id
899     assert_response :success
900
901     # Try it a second time, which should fail
902     basic_authorization(users(:normal_user).display_name, "test")
903     delete :api_delete, :id => public_trace_file.id
904     assert_response :not_found
905   end
906
907   private
908
909   def check_trace_feed(traces)
910     assert_response :success
911     assert_template "georss"
912     assert_equal "application/rss+xml", @response.content_type
913     assert_select "rss", :count => 1 do
914       assert_select "channel", :count => 1 do
915         assert_select "title"
916         assert_select "description"
917         assert_select "link"
918         assert_select "image"
919         assert_select "item", :count => traces.visible.count do |items|
920           traces.visible.order("timestamp DESC").zip(items).each do |trace, item|
921             assert_select item, "title", trace.name
922             assert_select item, "link", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
923             assert_select item, "guid", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
924             assert_select item, "description"
925             # assert_select item, "dc:creator", trace.user.display_name
926             assert_select item, "pubDate", trace.timestamp.rfc822
927           end
928         end
929       end
930     end
931   end
932
933   def check_trace_list(traces)
934     assert_response :success
935     assert_template "list"
936
937     if traces.count > 0
938       assert_select "table#trace_list tbody", :count => 1 do
939         assert_select "tr", :count => traces.visible.count do |rows|
940           traces.visible.order("timestamp DESC").zip(rows).each do |trace, row|
941             assert_select row, "a", Regexp.new(Regexp.escape(trace.name))
942             assert_select row, "span.trace_summary", Regexp.new(Regexp.escape("(#{trace.size} points)")) if trace.inserted?
943             assert_select row, "td", Regexp.new(Regexp.escape(trace.description))
944             assert_select row, "td", Regexp.new(Regexp.escape("by #{trace.user.display_name}"))
945           end
946         end
947       end
948     else
949       assert_select "h4", /Nothing here yet/
950     end
951   end
952
953   def check_trace_view(trace)
954     assert_response :success
955     assert_template "view"
956
957     assert_select "table", :count => 1 do
958       assert_select "td", /^#{Regexp.quote(trace.name)} /
959       assert_select "td", trace.user.display_name
960       assert_select "td", trace.description
961     end
962   end
963
964   def check_trace_data(trace, content_type = "application/gpx+xml", extension = "gpx")
965     assert_response :success
966     assert_equal content_type, response.content_type
967     assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"", @response.header["Content-Disposition"]
968   end
969
970   def check_trace_picture(trace)
971     assert_response :success
972     assert_equal "image/gif", response.content_type
973     assert_equal trace.large_picture, response.body
974   end
975
976   def check_trace_icon(trace)
977     assert_response :success
978     assert_equal "image/gif", response.content_type
979     assert_equal trace.icon_picture, response.body
980   end
981 end