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