Merge remote-tracking branch 'openstreetmap/pull/1344'
[rails.git] / test / controllers / trace_controller_test.rb
1 require "test_helper"
2
3 class TraceControllerTest < ActionController::TestCase
4   fixtures :users, :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     create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
459     get :create, {}, { :user => users(:public_user).id }
460     assert_response :success
461     assert_template :create
462     assert_select "select#trace_visibility option[value=identifiable][selected]", 1
463
464     # Now authenticated as a user with gps.trace.public set
465     create(:user_preference, :user => users(:second_public_user), :k => "gps.trace.public", :v => "default")
466     get :create, {}, { :user => users(:second_public_user).id }
467     assert_response :success
468     assert_template :create
469     assert_select "select#trace_visibility option[value=public][selected]", 1
470
471     # Now authenticated as a user with no preferences
472     get :create, {}, { :user => users(:normal_user).id }
473     assert_response :success
474     assert_template :create
475     assert_select "select#trace_visibility option[value=private][selected]", 1
476   end
477
478   # Test creating a trace
479   def test_create_post
480     # Get file to use
481     file = Rack::Test::UploadedFile.new(gpx_files(:public_trace_file).trace_name, "application/gpx+xml")
482
483     # First with no auth
484     post :create, :trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" }
485     assert_response :forbidden
486
487     # Now authenticated
488     create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
489     assert_not_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
490     post :create, { :trace => { :gpx_file => file, :description => "New Trace", :tagstring => "new,trace", :visibility => "trackable" } }, { :user => users(:public_user).id }
491     assert_response :redirect
492     assert_redirected_to :action => :list, :display_name => users(:public_user).display_name
493     assert_match /file has been uploaded/, flash[:notice]
494     trace = Trace.order(:id => :desc).first
495     assert_equal "1.gpx", trace.name
496     assert_equal "New Trace", trace.description
497     assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
498     assert_equal "trackable", trace.visibility
499     assert_equal false, trace.inserted
500     assert_equal File.new(gpx_files(:public_trace_file).trace_name).read, File.new(trace.trace_name).read
501     trace.destroy
502     assert_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
503   end
504
505   # Test fetching the edit page for a trace
506   def test_edit_get
507     # First with no auth
508     get :edit, :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id
509     assert_response :redirect
510     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)
511
512     # Now with some other user, which should fail
513     get :edit, { :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id }, { :user => users(:public_user).id }
514     assert_response :forbidden
515
516     # Now with a trace which doesn't exist
517     get :edit, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
518     assert_response :not_found
519
520     # Now with a trace which has been deleted
521     get :edit, { :display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id }, { :user => users(:public_user).id }
522     assert_response :not_found
523
524     # Finally with a trace that we are allowed to edit
525     get :edit, { :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id }, { :user => users(:normal_user).id }
526     assert_response :success
527   end
528
529   # Test saving edits to a trace
530   def test_edit_post
531     # New details
532     new_details = { :description => "Changed description", :tagstring => "new_tag", :visibility => "private" }
533
534     # First with no auth
535     post :edit, :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details
536     assert_response :forbidden
537
538     # Now with some other user, which should fail
539     post :edit, { :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details }, { :user => users(:public_user).id }
540     assert_response :forbidden
541
542     # Now with a trace which doesn't exist
543     post :edit, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id, :trace => new_details }
544     assert_response :not_found
545
546     # Now with a trace which has been deleted
547     post :edit, { :display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id, :trace => new_details }, { :user => users(:public_user).id }
548     assert_response :not_found
549
550     # Finally with a trace that we are allowed to edit
551     post :edit, { :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id, :trace => new_details }, { :user => users(:normal_user).id }
552     assert_response :redirect
553     assert_redirected_to :action => :view, :display_name => users(:normal_user).display_name
554     trace = Trace.find(gpx_files(:public_trace_file).id)
555     assert_equal new_details[:description], trace.description
556     assert_equal new_details[:tagstring], trace.tagstring
557     assert_equal new_details[:visibility], trace.visibility
558   end
559
560   # Test deleting a trace
561   def test_delete
562     # First with no auth
563     post :delete, :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id
564     assert_response :forbidden
565
566     # Now with some other user, which should fail
567     post :delete, { :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id }, { :user => users(:public_user).id }
568     assert_response :forbidden
569
570     # Now with a trace which doesn't exist
571     post :delete, { :display_name => users(:public_user).display_name, :id => 0 }, { :user => users(:public_user).id }
572     assert_response :not_found
573
574     # Now with a trace has already been deleted
575     post :delete, { :display_name => users(:public_user).display_name, :id => gpx_files(:deleted_trace_file).id }, { :user => users(:public_user).id }
576     assert_response :not_found
577
578     # Finally with a trace that we are allowed to delete
579     post :delete, { :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id }, { :user => users(:normal_user).id }
580     assert_response :redirect
581     assert_redirected_to :action => :list, :display_name => users(:normal_user).display_name
582     trace = Trace.find(gpx_files(:public_trace_file).id)
583     assert_equal false, trace.visible
584   end
585
586   # Check getting a specific trace through the api
587   def test_api_read
588     # First with no auth
589     get :api_read, :id => gpx_files(:public_trace_file).id
590     assert_response :unauthorized
591
592     # Now with some other user, which should work since the trace is public
593     basic_authorization(users(:public_user).display_name, "test")
594     get :api_read, :id => gpx_files(:public_trace_file).id
595     assert_response :success
596
597     # And finally we should be able to do it with the owner of the trace
598     basic_authorization(users(:normal_user).display_name, "test")
599     get :api_read, :id => gpx_files(:public_trace_file).id
600     assert_response :success
601   end
602
603   # Check an anoymous trace can't be specifically fetched by another user
604   def test_api_read_anon
605     # Furst with no auth
606     get :api_read, :id => gpx_files(:anon_trace_file).id
607     assert_response :unauthorized
608
609     # Now try with another user, which shouldn't work since the trace is anon
610     basic_authorization(users(:normal_user).display_name, "test")
611     get :api_read, :id => gpx_files(:anon_trace_file).id
612     assert_response :forbidden
613
614     # And finally we should be able to get the trace details with the trace owner
615     basic_authorization(users(:public_user).display_name, "test")
616     get :api_read, :id => gpx_files(:anon_trace_file).id
617     assert_response :success
618   end
619
620   # Check the api details for a trace that doesn't exist
621   def test_api_read_not_found
622     # Try first with no auth, as it should requure it
623     get :api_read, :id => 0
624     assert_response :unauthorized
625
626     # Login, and try again
627     basic_authorization(users(:public_user).display_name, "test")
628     get :api_read, :id => 0
629     assert_response :not_found
630
631     # Now try a trace which did exist but has been deleted
632     basic_authorization(users(:public_user).display_name, "test")
633     get :api_read, :id => 5
634     assert_response :not_found
635   end
636
637   # Test downloading a trace through the api
638   def test_api_data
639     # First with no auth
640     get :api_data, :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id
641     assert_response :unauthorized
642
643     # Now with some other user, which should work since the trace is public
644     basic_authorization(users(:public_user).display_name, "test")
645     get :api_data, :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id
646     check_trace_data gpx_files(:public_trace_file)
647
648     # And finally we should be able to do it with the owner of the trace
649     basic_authorization(users(:normal_user).display_name, "test")
650     get :api_data, :display_name => users(:normal_user).display_name, :id => gpx_files(:public_trace_file).id
651     check_trace_data gpx_files(:public_trace_file)
652   end
653
654   # Test downloading a compressed trace through the api
655   def test_api_data_compressed
656     # Authenticate as the owner of the trace we will be using
657     basic_authorization(users(:public_user).display_name, "test")
658
659     # First get the data as is
660     get :api_data, :display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id
661     check_trace_data gpx_files(:identifiable_trace_file), "application/x-gzip", "gpx.gz"
662
663     # Now ask explicitly for XML format
664     get :api_data, :display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id, :format => "xml"
665     check_trace_data gpx_files(:identifiable_trace_file), "application/xml", "xml"
666
667     # Now ask explicitly for GPX format
668     get :api_data, :display_name => users(:public_user).display_name, :id => gpx_files(:identifiable_trace_file).id, :format => "gpx"
669     check_trace_data gpx_files(:identifiable_trace_file)
670   end
671
672   # Check an anonymous trace can't be downloaded by another user through the api
673   def test_api_data_anon
674     # First with no auth
675     get :api_data, :display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id
676     assert_response :unauthorized
677
678     # Now with some other user, which shouldn't work since the trace is anon
679     basic_authorization(users(:normal_user).display_name, "test")
680     get :api_data, :display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id
681     assert_response :forbidden
682
683     # And finally we should be able to do it with the owner of the trace
684     basic_authorization(users(:public_user).display_name, "test")
685     get :api_data, :display_name => users(:public_user).display_name, :id => gpx_files(:anon_trace_file).id
686     check_trace_data gpx_files(:anon_trace_file)
687   end
688
689   # Test downloading a trace that doesn't exist through the api
690   def test_api_data_not_found
691     # First with no auth
692     get :api_data, :display_name => users(:public_user).display_name, :id => 0
693     assert_response :unauthorized
694
695     # Now with a trace that has never existed
696     basic_authorization(users(:public_user).display_name, "test")
697     get :api_data, :display_name => users(:public_user).display_name, :id => 0
698     assert_response :not_found
699
700     # Now with a trace that has been deleted
701     basic_authorization(users(:public_user).display_name, "test")
702     get :api_data, :display_name => users(:public_user).display_name, :id => 5
703     assert_response :not_found
704   end
705
706   # Test creating a trace through the api
707   def test_api_create
708     # Get file to use
709     file = Rack::Test::UploadedFile.new(gpx_files(:public_trace_file).trace_name, "application/gpx+xml")
710
711     # First with no auth
712     post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable"
713     assert_response :unauthorized
714
715     # Now authenticated
716     create(:user_preference, :user => users(:public_user), :k => "gps.trace.visibility", :v => "identifiable")
717     assert_not_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
718     basic_authorization(users(:public_user).display_name, "test")
719     post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable"
720     assert_response :success
721     trace = Trace.find(response.body.to_i)
722     assert_equal "1.gpx", trace.name
723     assert_equal "New Trace", trace.description
724     assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
725     assert_equal "trackable", trace.visibility
726     assert_equal false, trace.inserted
727     assert_equal File.new(gpx_files(:public_trace_file).trace_name).read, File.new(trace.trace_name).read
728     trace.destroy
729     assert_equal "trackable", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
730
731     # Rewind the file
732     file.rewind
733
734     # Now authenticated, with the legacy public flag
735     assert_not_equal "public", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
736     basic_authorization(users(:public_user).display_name, "test")
737     post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :public => 1
738     assert_response :success
739     trace = Trace.find(response.body.to_i)
740     assert_equal "1.gpx", trace.name
741     assert_equal "New Trace", trace.description
742     assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
743     assert_equal "public", trace.visibility
744     assert_equal false, trace.inserted
745     assert_equal File.new(gpx_files(:public_trace_file).trace_name).read, File.new(trace.trace_name).read
746     trace.destroy
747     assert_equal "public", users(:public_user).preferences.where(:k => "gps.trace.visibility").first.v
748
749     # Rewind the file
750     file.rewind
751
752     # Now authenticated, with the legacy private flag
753     assert_nil users(:second_public_user).preferences.where(:k => "gps.trace.visibility").first
754     basic_authorization(users(:second_public_user).display_name, "test")
755     post :api_create, :file => file, :description => "New Trace", :tags => "new,trace", :public => 0
756     assert_response :success
757     trace = Trace.find(response.body.to_i)
758     assert_equal "1.gpx", trace.name
759     assert_equal "New Trace", trace.description
760     assert_equal %w(new trace), trace.tags.order(:tag).collect(&:tag)
761     assert_equal "private", trace.visibility
762     assert_equal false, trace.inserted
763     assert_equal File.new(gpx_files(:public_trace_file).trace_name).read, File.new(trace.trace_name).read
764     trace.destroy
765     assert_equal "private", users(:second_public_user).preferences.where(:k => "gps.trace.visibility").first.v
766   end
767
768   # Check updating a trace through the api
769   def test_api_update
770     # First with no auth
771     content gpx_files(:public_trace_file).to_xml
772     put :api_update, :id => gpx_files(:public_trace_file).id
773     assert_response :unauthorized
774
775     # Now with some other user, which should fail
776     basic_authorization(users(:public_user).display_name, "test")
777     content gpx_files(:public_trace_file).to_xml
778     put :api_update, :id => gpx_files(:public_trace_file).id
779     assert_response :forbidden
780
781     # Now with a trace which doesn't exist
782     basic_authorization(users(:public_user).display_name, "test")
783     content gpx_files(:public_trace_file).to_xml
784     put :api_update, :id => 0
785     assert_response :not_found
786
787     # Now with a trace which did exist but has been deleted
788     basic_authorization(users(:public_user).display_name, "test")
789     content gpx_files(:deleted_trace_file).to_xml
790     put :api_update, :id => gpx_files(:deleted_trace_file).id
791     assert_response :not_found
792
793     # Now try an update with the wrong ID
794     basic_authorization(users(:normal_user).display_name, "test")
795     content gpx_files(:anon_trace_file).to_xml
796     put :api_update, :id => gpx_files(:public_trace_file).id
797     assert_response :bad_request,
798                     "should not be able to update a trace with a different ID from the XML"
799
800     # And finally try an update that should work
801     basic_authorization(users(:normal_user).display_name, "test")
802     t = gpx_files(:public_trace_file)
803     t.description = "Changed description"
804     t.visibility = "private"
805     content t.to_xml
806     put :api_update, :id => t.id
807     assert_response :success
808     nt = Trace.find(t.id)
809     assert_equal nt.description, t.description
810     assert_equal nt.visibility, t.visibility
811   end
812
813   # Check deleting a trace through the api
814   def test_api_delete
815     # First with no auth
816     delete :api_delete, :id => gpx_files(:public_trace_file).id
817     assert_response :unauthorized
818
819     # Now with some other user, which should fail
820     basic_authorization(users(:public_user).display_name, "test")
821     delete :api_delete, :id => gpx_files(:public_trace_file).id
822     assert_response :forbidden
823
824     # Now with a trace which doesn't exist
825     basic_authorization(users(:public_user).display_name, "test")
826     delete :api_delete, :id => 0
827     assert_response :not_found
828
829     # And finally we should be able to do it with the owner of the trace
830     basic_authorization(users(:normal_user).display_name, "test")
831     delete :api_delete, :id => gpx_files(:public_trace_file).id
832     assert_response :success
833
834     # Try it a second time, which should fail
835     basic_authorization(users(:normal_user).display_name, "test")
836     delete :api_delete, :id => gpx_files(:public_trace_file).id
837     assert_response :not_found
838   end
839
840   private
841
842   def check_trace_feed(traces)
843     assert_response :success
844     assert_template "georss"
845     assert_equal "application/rss+xml", @response.content_type
846     assert_select "rss", :count => 1 do
847       assert_select "channel", :count => 1 do
848         assert_select "title"
849         assert_select "description"
850         assert_select "link"
851         assert_select "image"
852         assert_select "item", :count => traces.visible.count do |items|
853           traces.visible.order("timestamp DESC").zip(items).each do |trace, item|
854             assert_select item, "title", trace.name
855             assert_select item, "link", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
856             assert_select item, "guid", "http://test.host/user/#{trace.user.display_name}/traces/#{trace.id}"
857             assert_select item, "description"
858             # assert_select item, "dc:creator", trace.user.display_name
859             assert_select item, "pubDate", trace.timestamp.rfc822
860           end
861         end
862       end
863     end
864   end
865
866   def check_trace_list(traces)
867     assert_response :success
868     assert_template "list"
869
870     if traces.count > 0
871       assert_select "table#trace_list tbody", :count => 1 do
872         assert_select "tr", :count => traces.visible.count do |rows|
873           traces.visible.order("timestamp DESC").zip(rows).each do |trace, row|
874             assert_select row, "a", Regexp.new(Regexp.escape(trace.name))
875             assert_select row, "span.trace_summary", Regexp.new(Regexp.escape("(#{trace.size} points)")) if trace.inserted?
876             assert_select row, "td", Regexp.new(Regexp.escape(trace.description))
877             assert_select row, "td", Regexp.new(Regexp.escape("by #{trace.user.display_name}"))
878           end
879         end
880       end
881     else
882       assert_select "h4", /Nothing here yet/
883     end
884   end
885
886   def check_trace_view(trace)
887     assert_response :success
888     assert_template "view"
889
890     assert_select "table", :count => 1 do
891       assert_select "td", /^#{Regexp.quote(trace.name)} /
892       assert_select "td", trace.user.display_name
893       assert_select "td", trace.description
894     end
895   end
896
897   def check_trace_data(trace, content_type = "application/gpx+xml", extension = "gpx")
898     assert_response :success
899     assert_equal content_type, response.content_type
900     assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"", @response.header["Content-Disposition"]
901   end
902
903   def check_trace_picture(trace)
904     assert_response :success
905     assert_equal "image/gif", response.content_type
906     assert_equal trace.large_picture, response.body
907   end
908
909   def check_trace_icon(trace)
910     assert_response :success
911     assert_equal "image/gif", response.content_type
912     assert_equal trace.icon_picture, response.body
913   end
914 end