]> git.openstreetmap.org Git - rails.git/blob - test/controllers/users_controller_test.rb
Merge remote-tracking branch 'upstream/pull/5998'
[rails.git] / test / controllers / users_controller_test.rb
1 require "test_helper"
2
3 class UsersControllerTest < ActionDispatch::IntegrationTest
4   ##
5   # test all routes which lead to this controller
6   def test_routes
7     assert_routing(
8       { :path => "/user/new", :method => :get },
9       { :controller => "users", :action => "new" }
10     )
11
12     assert_routing(
13       { :path => "/user", :method => :post },
14       { :controller => "users", :action => "create" }
15     )
16
17     assert_routing(
18       { :path => "/user/go_public", :method => :post },
19       { :controller => "users", :action => "go_public" }
20     )
21
22     assert_routing(
23       { :path => "/user/suspended", :method => :get },
24       { :controller => "users", :action => "suspended" }
25     )
26
27     assert_routing(
28       { :path => "/user/username", :method => :get },
29       { :controller => "users", :action => "show", :display_name => "username" }
30     )
31   end
32
33   # The user creation page loads
34   def test_new
35     get new_user_path
36     assert_redirected_to new_user_path(:cookie_test => "true")
37
38     get new_user_path, :params => { :cookie_test => "true" }
39     assert_response :success
40
41     assert_no_match(/img-src \* data:;/, @response.headers["Content-Security-Policy-Report-Only"])
42
43     assert_select "html", :count => 1 do
44       assert_select "head", :count => 1 do
45         assert_select "title", :text => /Sign Up/, :count => 1
46       end
47       assert_select "body", :count => 1 do
48         assert_select "div#content", :count => 1 do
49           assert_select "form[action='/user'][method='post']", :count => 1 do
50             assert_select "input[id='user_email']", :count => 1
51             assert_select "input[id='user_display_name']", :count => 1
52             assert_select "input[id='user_pass_crypt'][type='password']", :count => 1
53             assert_select "input[id='user_pass_crypt_confirmation'][type='password']", :count => 1
54             assert_select "input[type='submit'][value='Sign Up']", :count => 1
55           end
56         end
57       end
58     end
59   end
60
61   def test_new_logged_in
62     session_for(create(:user))
63
64     get new_user_path
65     assert_redirected_to root_path
66
67     get new_user_path, :params => { :referer => "/test" }
68     assert_redirected_to "/test"
69   end
70
71   def test_create_success
72     user = build(:user, :pending)
73
74     assert_difference "User.count", 1 do
75       assert_difference "ActionMailer::Base.deliveries.size", 1 do
76         perform_enqueued_jobs do
77           post users_path, :params => { :user => user.attributes }
78         end
79       end
80     end
81
82     # Check the e-mail
83     register_email = ActionMailer::Base.deliveries.first
84
85     assert_equal register_email.to[0], user.email
86     assert_match(/#{@url}/, register_email.body.to_s)
87
88     # Check the page
89     assert_redirected_to :controller => :confirmations, :action => :confirm, :display_name => user.display_name
90   end
91
92   def test_create_duplicate_email
93     user = build(:user, :pending)
94     create(:user, :email => user.email)
95
96     assert_no_difference "User.count" do
97       assert_no_difference "ActionMailer::Base.deliveries.size" do
98         perform_enqueued_jobs do
99           post users_path, :params => { :user => user.attributes }
100         end
101       end
102     end
103
104     assert_response :success
105     assert_template "new"
106     assert_select "form > div > input.is-invalid#user_email"
107   end
108
109   def test_create_duplicate_email_uppercase
110     user = build(:user, :pending)
111     create(:user, :email => user.email.upcase)
112
113     assert_no_difference "User.count" do
114       assert_no_difference "ActionMailer::Base.deliveries.size" do
115         perform_enqueued_jobs do
116           post users_path, :params => { :user => user.attributes }
117         end
118       end
119     end
120
121     assert_response :success
122     assert_template "new"
123     assert_select "form > div > input.is-invalid#user_email"
124   end
125
126   def test_create_duplicate_name
127     user = build(:user, :pending)
128     create(:user, :display_name => user.display_name)
129
130     assert_no_difference "User.count" do
131       assert_no_difference "ActionMailer::Base.deliveries.size" do
132         perform_enqueued_jobs do
133           post users_path, :params => { :user => user.attributes }
134         end
135       end
136     end
137
138     assert_response :success
139     assert_template "new"
140     assert_select "form > div > input.is-invalid#user_display_name"
141   end
142
143   def test_create_duplicate_name_uppercase
144     user = build(:user, :pending)
145     create(:user, :display_name => user.display_name.upcase)
146
147     assert_no_difference "User.count" do
148       assert_no_difference "ActionMailer::Base.deliveries.size" do
149         perform_enqueued_jobs do
150           post users_path, :params => { :user => user.attributes }
151         end
152       end
153     end
154
155     assert_response :success
156     assert_template "new"
157     assert_select "form > div > input.is-invalid#user_display_name"
158   end
159
160   def test_create_blocked_domain
161     user = build(:user, :pending, :email => "user@example.net")
162
163     # Now block that domain
164     create(:acl, :domain => "example.net", :k => "no_account_creation")
165
166     # Check that the second half of registration fails
167     assert_no_difference "User.count" do
168       assert_no_difference "ActionMailer::Base.deliveries.size" do
169         perform_enqueued_jobs do
170           post users_path, :params => { :user => user.attributes }
171         end
172       end
173     end
174
175     assert_response :success
176     assert_template "blocked"
177   end
178
179   def test_create_referer_params
180     user = build(:user, :pending)
181
182     assert_difference "User.count", 1 do
183       assert_difference "ActionMailer::Base.deliveries.size", 1 do
184         post users_path, :params => { :user => user.attributes, :referer => "/edit?editor=id#map=1/2/3" }
185         assert_enqueued_with :job => ActionMailer::MailDeliveryJob,
186                              :args => proc { |args| args[3][:args][2] == welcome_path(:editor => "id", :zoom => 1, :lat => 2, :lon => 3) }
187         perform_enqueued_jobs
188       end
189     end
190   end
191
192   def test_go_public
193     user = create(:user, :data_public => false)
194     session_for(user)
195
196     post user_go_public_path
197
198     assert_redirected_to account_path
199     assert User.find(user.id).data_public
200   end
201
202   # Check that the user account page will display and contains some relevant
203   # information for the user
204   def test_show
205     # Test a non-existent user
206     get user_path("unknown")
207     assert_response :not_found
208
209     # Test a normal user
210     user = create(:user)
211
212     get user_path(user)
213     assert_response :success
214     assert_match(/img-src \* data:;/, @response.headers["Content-Security-Policy-Report-Only"])
215     assert_select "div.content-heading" do
216       assert_select "a[href^='/user/#{ERB::Util.u(user.display_name)}/history']", 1
217       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/traces']", 1
218       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/diary']", 1
219       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/diary_comments']", 1
220       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/account']", 0
221       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/blocks']", 0
222       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/blocks_by']", 0
223       assert_select "a[href='/user_blocks/new/#{ERB::Util.u(user.display_name)}']", 0
224     end
225
226     # Test a user who has been blocked
227     blocked_user = create(:user)
228     create(:user_block, :user => blocked_user)
229     get user_path(blocked_user)
230     assert_response :success
231     assert_select "div.content-heading" do
232       assert_select "a[href^='/user/#{ERB::Util.u(blocked_user.display_name)}/history']", 1
233       assert_select "a[href='/user/#{ERB::Util.u(blocked_user.display_name)}/traces']", 1
234       assert_select "a[href='/user/#{ERB::Util.u(blocked_user.display_name)}/diary']", 1
235       assert_select "a[href='/user/#{ERB::Util.u(blocked_user.display_name)}/diary_comments']", 1
236       assert_select "a[href='/user/#{ERB::Util.u(blocked_user.display_name)}/account']", 0
237       assert_select "a[href='/user/#{ERB::Util.u(blocked_user.display_name)}/blocks']", 1
238       assert_select "a[href='/user/#{ERB::Util.u(blocked_user.display_name)}/blocks_by']", 0
239       assert_select "a[href='/user_blocks/new/#{ERB::Util.u(blocked_user.display_name)}']", 0
240     end
241
242     # Test a moderator who has applied blocks
243     moderator_user = create(:moderator_user)
244     create(:user_block, :creator => moderator_user)
245     get user_path(moderator_user)
246     assert_response :success
247     assert_select "div.content-heading" do
248       assert_select "a[href^='/user/#{ERB::Util.u(moderator_user.display_name)}/history']", 1
249       assert_select "a[href='/user/#{ERB::Util.u(moderator_user.display_name)}/traces']", 1
250       assert_select "a[href='/user/#{ERB::Util.u(moderator_user.display_name)}/diary']", 1
251       assert_select "a[href='/user/#{ERB::Util.u(moderator_user.display_name)}/diary_comments']", 1
252       assert_select "a[href='/account']", 0
253       assert_select "a[href='/user/#{ERB::Util.u(moderator_user.display_name)}/blocks']", 0
254       assert_select "a[href='/user/#{ERB::Util.u(moderator_user.display_name)}/blocks_by']", 1
255       assert_select "a[href='/user_blocks/new/#{ERB::Util.u(moderator_user.display_name)}']", 0
256     end
257
258     # Login as a normal user
259     session_for(user)
260
261     # Test the normal user
262     get user_path(user)
263     assert_response :success
264     assert_select "div.content-heading" do
265       assert_select "a[href^='/user/#{ERB::Util.u(user.display_name)}/history']", 1
266       assert_select "a[href='/traces/mine']", 1
267       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/diary']", 1
268       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/diary_comments']", 1
269       assert_select "a[href='/account']", 1
270       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/blocks']", 0
271       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/blocks_by']", 0
272       assert_select "a[href='/user_blocks/new/#{ERB::Util.u(user.display_name)}']", 0
273       assert_select "a[href='/api/0.6/user/#{ERB::Util.u(user.id)}']", 0
274     end
275
276     # Login as a moderator
277     session_for(create(:moderator_user))
278
279     # Test the normal user
280     get user_path(user)
281     assert_response :success
282     assert_select "div.content-heading" do
283       assert_select "a[href^='/user/#{ERB::Util.u(user.display_name)}/history']", 1
284       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/traces']", 1
285       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/diary']", 1
286       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/diary_comments']", 1
287       assert_select "a[href='/account']", 0
288       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/blocks']", 0
289       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/blocks_by']", 0
290       assert_select "a[href='/user_blocks/new/#{ERB::Util.u(user.display_name)}']", 1
291       assert_select "a[href='/api/0.6/user/#{ERB::Util.u(user.id)}']", 1
292     end
293   end
294
295   # Test whether information about contributor terms is shown for users who haven't agreed
296   def test_terms_not_agreed
297     agreed_user = create(:user, :terms_agreed => 3.days.ago)
298     seen_user = create(:user, :terms_seen => true, :terms_agreed => nil)
299     not_seen_user = create(:user, :terms_seen => false, :terms_agreed => nil)
300
301     get user_path(agreed_user)
302     assert_response :success
303     assert_select "div.content-heading" do
304       assert_select "dt", :count => 0, :text => /Contributor terms/
305     end
306
307     get user_path(seen_user)
308     assert_response :success
309     assert_select "div.content-heading" do
310       assert_select "dt", :count => 1, :text => /Contributor terms/
311       assert_select "dd", /Declined/
312     end
313
314     get user_path(not_seen_user)
315     assert_response :success
316     assert_select "div.content-heading" do
317       assert_select "dt", :count => 1, :text => /Contributor terms/
318       assert_select "dd", /Undecided/
319     end
320   end
321
322   def test_auth_failure_callback
323     get auth_failure_path
324     assert_redirected_to login_path
325
326     get auth_failure_path, :params => { :origin => "/" }
327     assert_redirected_to root_path
328
329     get auth_failure_path, :params => { :origin => "http://www.google.com" }
330     assert_redirected_to login_path
331   end
332
333   def test_show_heatmap_data
334     user = create(:user)
335     # Create two changesets
336     create(:changeset, :user => user, :created_at => 6.months.ago, :num_changes => 10)
337     create(:changeset, :user => user, :created_at => 3.months.ago, :num_changes => 20)
338
339     get user_path(user.display_name)
340     assert_response :success
341     # The data should not be empty
342     heatmap_data = assigns(:heatmap_data)
343     assert_not_nil heatmap_data
344     assert_predicate heatmap_data[:days], :any?
345     # The data should be in the right format
346     assert(heatmap_data[:days].all? { |entry| entry[:date] && entry[:total_changes] }, "Heatmap data should have :date and :total_changes keys")
347     assert_predicate heatmap_data[:months], :any?
348     assert_equal 30, heatmap_data[:total]
349     assert_equal 20, heatmap_data[:max_per_day]
350   end
351
352   def test_show_heatmap_data_caching
353     # Enable caching to be able to test
354     Rails.cache.clear
355     @original_cache_store = Rails.cache
356     Rails.cache = ActiveSupport::Cache::MemoryStore.new
357
358     user = create(:user)
359
360     # Create an initial changeset
361     create(:changeset, :user => user, :created_at => 6.months.ago, :num_changes => 15)
362
363     # First request to populate the cache
364     get user_path(user.display_name)
365     first_response_data = assigns(:heatmap_data)
366     assert_not_nil first_response_data, "Expected heatmap data to be assigned on the first request"
367     assert_equal 1, first_response_data[:days].count { |day| day[:total_changes].positive? }, "Expected one entry in the heatmap data"
368
369     # Inspect cache after the first request
370     cached_data = Rails.cache.read("heatmap_data_of_user_#{user.id}")
371     assert_equal first_response_data, cached_data, "Expected the cache to contain the first response data"
372
373     # Add a new changeset to the database
374     create(:changeset, :user => user, :created_at => 3.months.ago, :num_changes => 20)
375
376     # Second request
377     get user_path(user.display_name)
378     second_response_data = assigns(:heatmap_data)
379
380     # Confirm that the cache is still being used
381     assert_equal first_response_data, second_response_data, "Expected cached data to be returned on the second request"
382
383     # Clear the cache and make a third request to confirm new data is retrieved
384     Rails.cache.clear
385     get user_path(user.display_name)
386     third_response_data = assigns(:heatmap_data)
387
388     # Ensure the new entry is now included
389     assert_equal 2, third_response_data[:days].count { |day| day[:total_changes].positive? }, "Expected two entries in the heatmap data after clearing the cache"
390
391     # Reset caching config to defaults
392     Rails.cache.clear
393     Rails.cache = @original_cache_store
394   end
395
396   def test_show_heatmap_data_no_changesets
397     user = create(:user)
398
399     get user_path(user.display_name)
400     assert_response :success
401     assert_empty(assigns(:heatmap_data)[:days].select { |e| e[:total_changes].positive? })
402     assert_select ".heatmap", :count => 0
403   end
404
405   def test_heatmap_rendering
406     # Test user with no changesets
407     user_without_changesets = create(:user)
408     get user_path(user_without_changesets)
409     assert_response :success
410     assert_select ".heatmap", 0
411
412     # Test user with changesets
413     user_with_changesets = create(:user)
414     changeset39 = create(:changeset, :user => user_with_changesets, :created_at => 4.months.ago.beginning_of_day, :num_changes => 39)
415     _changeset5 = create(:changeset, :user => user_with_changesets, :created_at => 3.months.ago.beginning_of_day, :num_changes => 5)
416     changeset11 = create(:changeset, :user => user_with_changesets, :created_at => 3.months.ago.beginning_of_day, :num_changes => 11)
417     get user_path(user_with_changesets)
418     assert_response :success
419     assert_select ".heatmap a", 2
420
421     history_path = user_history_path(user_with_changesets)
422     assert_select ".heatmap a[data-date='#{4.months.ago.to_date}'][data-count='39'][href='#{history_path}?before=#{changeset39.id + 1}']"
423     assert_select ".heatmap a[data-date='#{3.months.ago.to_date}'][data-count='16'][href='#{history_path}?before=#{changeset11.id + 1}']"
424     assert_select ".heatmap [data-date='#{5.months.ago.to_date}']:not([data-count])"
425   end
426
427   def test_heatmap_headline_changset_zero
428     user = create(:user)
429
430     get user_path(user)
431
432     assert_response :success
433     assert_select "h2.text-body-secondary.fs-5", :count => 0
434   end
435
436   def test_heatmap_headline_changeset_singular
437     user = create(:user)
438     create(:changeset, :user => user, :created_at => 4.months.ago.beginning_of_day, :num_changes => 1)
439
440     get user_path(user)
441
442     assert_response :success
443     assert_select "h2.text-body-secondary.fs-5", :text => "1 contribution in the last year"
444   end
445
446   def test_heatmap_headline_changeset_plural
447     user = create(:user)
448     create(:changeset, :user => user, :created_at => 4.months.ago.beginning_of_day, :num_changes => 12)
449
450     get user_path(user)
451
452     assert_response :success
453     assert_select "h2.text-body-secondary.fs-5", :text => "12 contributions in the last year"
454   end
455 end