]> git.openstreetmap.org Git - rails.git/blob - test/controllers/diary_entries_controller_test.rb
Merge pull request #6394 from openstreetmap/dependabot/github_actions/ruby/setup...
[rails.git] / test / controllers / diary_entries_controller_test.rb
1 # frozen_string_literal: true
2
3 require "test_helper"
4
5 class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
6   include ActionView::Helpers::NumberHelper
7
8   def setup
9     super
10     # Create the default language for diary entries
11     create(:language, :code => "en")
12     # Stub nominatim response for diary entry locations
13     stub_request(:get, %r{^https://nominatim\.openstreetmap\.org/reverse\?})
14       .to_return(:status => 404)
15   end
16
17   ##
18   # test all routes which lead to this controller
19   def test_routes
20     assert_routing(
21       { :path => "/diary", :method => :get },
22       { :controller => "diary_entries", :action => "index" }
23     )
24     assert_routing(
25       { :path => "/diary/language", :method => :get },
26       { :controller => "diary_entries", :action => "index", :language => "language" }
27     )
28     assert_routing(
29       { :path => "/user/username/diary", :method => :get },
30       { :controller => "diary_entries", :action => "index", :display_name => "username" }
31     )
32     assert_routing(
33       { :path => "/diary/friends", :method => :get },
34       { :controller => "diary_entries", :action => "index", :friends => true }
35     )
36     assert_routing(
37       { :path => "/diary/nearby", :method => :get },
38       { :controller => "diary_entries", :action => "index", :nearby => true }
39     )
40
41     assert_routing(
42       { :path => "/diary/rss", :method => :get },
43       { :controller => "diary_entries", :action => "rss", :format => :rss }
44     )
45     assert_routing(
46       { :path => "/diary/language/rss", :method => :get },
47       { :controller => "diary_entries", :action => "rss", :language => "language", :format => :rss }
48     )
49     assert_routing(
50       { :path => "/user/username/diary/rss", :method => :get },
51       { :controller => "diary_entries", :action => "rss", :display_name => "username", :format => :rss }
52     )
53
54     assert_routing(
55       { :path => "/diary/new", :method => :get },
56       { :controller => "diary_entries", :action => "new" }
57     )
58     assert_routing(
59       { :path => "/diary", :method => :post },
60       { :controller => "diary_entries", :action => "create" }
61     )
62     assert_routing(
63       { :path => "/user/username/diary/1", :method => :get },
64       { :controller => "diary_entries", :action => "show", :display_name => "username", :id => "1" }
65     )
66     assert_routing(
67       { :path => "/user/username/diary/1/edit", :method => :get },
68       { :controller => "diary_entries", :action => "edit", :display_name => "username", :id => "1" }
69     )
70     assert_routing(
71       { :path => "/user/username/diary/1", :method => :put },
72       { :controller => "diary_entries", :action => "update", :display_name => "username", :id => "1" }
73     )
74     assert_routing(
75       { :path => "/user/username/diary/1/hide", :method => :post },
76       { :controller => "diary_entries", :action => "hide", :display_name => "username", :id => "1" }
77     )
78     assert_routing(
79       { :path => "/user/username/diary/1/unhide", :method => :post },
80       { :controller => "diary_entries", :action => "unhide", :display_name => "username", :id => "1" }
81     )
82     assert_routing(
83       { :path => "/user/username/diary/1/subscribe", :method => :get },
84       { :controller => "diary_entries", :action => "subscribe", :display_name => "username", :id => "1" }
85     )
86     assert_routing(
87       { :path => "/user/username/diary/1/subscribe", :method => :post },
88       { :controller => "diary_entries", :action => "subscribe", :display_name => "username", :id => "1" }
89     )
90     assert_routing(
91       { :path => "/user/username/diary/1/unsubscribe", :method => :get },
92       { :controller => "diary_entries", :action => "unsubscribe", :display_name => "username", :id => "1" }
93     )
94     assert_routing(
95       { :path => "/user/username/diary/1/unsubscribe", :method => :post },
96       { :controller => "diary_entries", :action => "unsubscribe", :display_name => "username", :id => "1" }
97     )
98   end
99
100   def test_new_no_login
101     # Make sure that you are redirected to the login page when you
102     # are not logged in
103     get new_diary_entry_path
104     assert_redirected_to login_path(:referer => "/diary/new")
105   end
106
107   def test_new_form
108     # Now try again when logged in
109     session_for(create(:user, :languages => ["en"]))
110
111     get new_diary_entry_path
112
113     assert_response :success
114     assert_dom "title", :text => /New Diary Entry/, :count => 1
115     assert_dom "div.content-heading", :count => 1 do
116       assert_dom "h1", :text => /New Diary Entry/, :count => 1
117     end
118     assert_dom "div#content", :count => 1 do
119       assert_dom "form[action='/diary'][method=post]", :count => 1 do
120         assert_dom "input#diary_entry_title[name='diary_entry[title]']", :count => 1
121         assert_dom "textarea#diary_entry_body[name='diary_entry[body]']", :text => "", :count => 1
122         assert_dom "select#diary_entry_language_code", :count => 1 do
123           assert_dom "option[selected]", :count => 1 do
124             assert_dom "> @value", "en"
125           end
126         end
127         assert_dom "input#latitude[name='diary_entry[latitude]']", :count => 1
128         assert_dom "input#longitude[name='diary_entry[longitude]']", :count => 1
129         assert_dom "input[name=commit][type=submit][value=Publish]", :count => 1
130         assert_dom "button[type=button]", :text => "Edit", :count => 1
131         assert_dom "button[type=button]", :text => "Preview", :count => 1
132         assert_dom "input", :count => 4
133       end
134     end
135   end
136
137   def test_new_get_with_params
138     create(:language, :code => "fr")
139     # Now try creating a diary entry using get
140     session_for(create(:user, :languages => ["en"]))
141
142     assert_difference "DiaryEntry.count", 0 do
143       get new_diary_entry_path(:diary_entry => { :title => "New Title", :body => "This is a new body for the diary entry", :latitude => "1.1",
144                                                  :longitude => "2.2", :language_code => "fr" })
145     end
146
147     assert_response :success
148     assert_template :new
149     assert_dom "div#content", :count => 1 do
150       assert_dom "form[action='/diary'][method=post]", :count => 1 do
151         assert_dom "input#diary_entry_title[name='diary_entry[title]']", :count => 1 do
152           assert_dom "> @value", "New Title"
153         end
154         assert_dom "textarea#diary_entry_body[name='diary_entry[body]']", :count => 1, :text => "This is a new body for the diary entry"
155         assert_dom "select#diary_entry_language_code", :count => 1 do
156           assert_dom "option[selected]", :count => 1 do
157             assert_dom "> @value", "fr"
158           end
159         end
160         assert_dom "input#latitude[name='diary_entry[latitude]']", :count => 1 do
161           assert_dom "> @value", "1.1"
162         end
163         assert_dom "input#longitude[name='diary_entry[longitude]']", :count => 1 do
164           assert_dom "> @value", "2.2"
165         end
166       end
167     end
168   end
169
170   def test_create_no_body
171     # Now try creating a invalid diary entry with an empty body
172     user = create(:user)
173     session_for(user)
174     assert_no_difference "DiaryEntry.count" do
175       post diary_entries_path(:diary_entry => { :title => "New Title", :body => "", :latitude => "1.1",
176                                                 :longitude => "2.2", :language_code => "en" })
177     end
178     assert_response :success
179     assert_template :new
180
181     assert_nil UserPreference.find_by(:user => user, :k => "diary.default_language")
182   end
183
184   def test_create
185     # Now try creating a diary entry
186     user = create(:user)
187     session_for(user)
188     assert_difference "DiaryEntry.count", 1 do
189       post diary_entries_path(:diary_entry => { :title => "New Title", :body => "This is a new body for the diary entry", :latitude => "1.1",
190                                                 :longitude => "2.2", :language_code => "en" })
191     end
192     entry = DiaryEntry.last
193     assert_redirected_to diary_entry_path(user, entry)
194     assert_equal user.id, entry.user_id
195     assert_equal "New Title", entry.title
196     assert_equal "This is a new body for the diary entry", entry.body
197     assert_equal "1.1".to_f, entry.latitude
198     assert_equal "2.2".to_f, entry.longitude
199     assert_equal "en", entry.language_code
200
201     # checks if user was subscribed
202     assert_equal 1, entry.subscribers.length
203
204     assert_equal "en", UserPreference.find_by(:user => user, :k => "diary.default_language").v
205   end
206
207   def test_create_german
208     create(:language, :code => "de")
209     user = create(:user)
210     session_for(user)
211
212     # Now try creating a diary entry in a different language
213     assert_difference "DiaryEntry.count", 1 do
214       post diary_entries_path(:diary_entry => { :title => "New Title", :body => "This is a new body for the diary entry", :latitude => "1.1",
215                                                 :longitude => "2.2", :language_code => "de" })
216     end
217     entry = DiaryEntry.last
218     assert_redirected_to diary_entry_path(user, entry)
219     assert_equal user.id, entry.user_id
220     assert_equal "New Title", entry.title
221     assert_equal "This is a new body for the diary entry", entry.body
222     assert_equal "1.1".to_f, entry.latitude
223     assert_equal "2.2".to_f, entry.longitude
224     assert_equal "de", entry.language_code
225
226     # checks if user was subscribed
227     assert_equal 1, entry.subscribers.length
228
229     assert_equal "de", UserPreference.find_by(:user => user, :k => "diary.default_language").v
230   end
231
232   def test_new_spammy
233     user = create(:user)
234     session_for(user)
235
236     # Generate some spammy content
237     spammy_title = "Spam Spam Spam Spam Spam"
238     spammy_body = 1.upto(50).map { |n| "http://example.com/spam#{n}" }.join(" ")
239
240     # Try creating a spammy diary entry
241     assert_difference "DiaryEntry.count", 1 do
242       post diary_entries_path(:diary_entry => { :title => spammy_title, :body => spammy_body, :language_code => "en" })
243     end
244     entry = DiaryEntry.last
245     assert_redirected_to diary_entry_path(user, entry)
246     assert_equal user.id, entry.user_id
247     assert_equal spammy_title, entry.title
248     assert_equal spammy_body, entry.body
249     assert_equal "en", entry.language_code
250     assert_equal "suspended", User.find(user.id).status
251
252     follow_redirect!
253     assert_redirected_to :controller => :users, :action => :suspended
254   end
255
256   def test_edit
257     user = create(:user)
258     other_user = create(:user)
259
260     entry = create(:diary_entry, :user => user)
261
262     # Make sure that you are redirected to the login page when you are
263     # not logged in, without and with the id of the entry you want to edit
264     get edit_diary_entry_path(entry.user, entry)
265     assert_redirected_to login_path(:referer => "/user/#{ERB::Util.u(entry.user.display_name)}/diary/#{entry.id}/edit")
266
267     session_for(other_user)
268
269     # Verify that you get redirected to show if you are not the user
270     # that created the entry
271     get edit_diary_entry_path(entry.user, entry)
272     assert_redirected_to :action => :show, :display_name => entry.user.display_name, :id => entry.id
273
274     session_for(entry.user)
275
276     # Verify that you get a not found error, when you pass a bogus id
277     get edit_diary_entry_path(entry.user, :id => 9999)
278     assert_response :not_found
279     assert_select "div.content-heading", :count => 1 do
280       assert_select "h1", :text => "No entry with the id: 9999", :count => 1
281     end
282
283     # Now pass the id, and check that you can edit it, when using the same
284     # user as the person who created the entry
285     get edit_diary_entry_path(entry.user, entry)
286     assert_response :success
287     assert_select "title", :text => /Edit Diary Entry/, :count => 1
288     assert_select "div.content-heading", :count => 1 do
289       assert_select "h1", :text => /Edit Diary Entry/, :count => 1
290     end
291     assert_select "div#content", :count => 1 do
292       assert_select "form[action='/user/#{ERB::Util.u(entry.user.display_name)}/diary/#{entry.id}'][method=post]", :count => 1 do
293         assert_select "input#diary_entry_title[name='diary_entry[title]'][value='#{entry.title}']", :count => 1
294         assert_select "textarea#diary_entry_body[name='diary_entry[body]']", :text => entry.body, :count => 1
295         assert_select "select#diary_entry_language_code", :count => 1
296         assert_select "input#latitude[name='diary_entry[latitude]']", :count => 1
297         assert_select "input#longitude[name='diary_entry[longitude]']", :count => 1
298         assert_select "input[name=commit][type=submit][value=Update]", :count => 1
299         assert_select "button[type=button]", :text => "Edit", :count => 1
300         assert_select "button[type=button]", :text => "Preview", :count => 1
301         assert_select "input", :count => 5
302       end
303     end
304
305     # Now lets see if you can edit the diary entry
306     new_title = "New Title"
307     new_body = "This is a new body for the diary entry"
308     new_latitude = "1.1"
309     new_longitude = "2.2"
310     new_language_code = "en"
311     put diary_entry_path(entry.user, entry, :diary_entry => { :title => new_title, :body => new_body, :latitude => new_latitude,
312                                                               :longitude => new_longitude, :language_code => new_language_code })
313     assert_redirected_to :action => :show, :display_name => entry.user.display_name, :id => entry.id
314
315     # Now check that the new data is rendered, when logged in
316     get diary_entry_path(entry.user, entry)
317     assert_response :success
318     assert_template "show"
319     assert_select "head title", :text => /Users' Diaries | /, :count => 1
320     assert_select "div.content-heading", :count => 1 do
321       assert_select "h1", :text => /#{entry.user.display_name}'s Diary/, :count => 1
322     end
323     assert_select "div#content", :count => 1 do
324       assert_select "h2", :text => /#{new_title}/, :count => 1
325       # This next line won't work if the text has been run through the htmlize function
326       # due to formatting that could be introduced
327       assert_select "p", :text => /#{new_body}/, :count => 1
328       assert_select "abbr[class='geo'][title='#{number_with_precision(new_latitude, :precision => 4)}; #{number_with_precision(new_longitude, :precision => 4)}']", :count => 1
329       # As we're not logged in, check that you cannot edit
330       assert_select "a[href='/user/#{ERB::Util.u(entry.user.display_name)}/diary/#{entry.id}/edit']", :text => "Edit this entry", :count => 1
331     end
332
333     # and when not logged in as the user who wrote the entry
334     session_for(create(:user))
335     get diary_entry_path(entry.user, entry)
336     assert_response :success
337     assert_template "show"
338     assert_select "head title", :text => /Users' Diaries | /, :count => 1
339     assert_select "div.content-heading", :count => 1 do
340       assert_select "h1", :text => /#{entry.user.display_name}'s Diary/, :count => 1
341     end
342     assert_select "div#content", :count => 1 do
343       assert_select "h2", :text => /#{new_title}/, :count => 1
344       # This next line won't work if the text has been run through the htmlize function
345       # due to formatting that could be introduced
346       assert_select "p", :text => /#{new_body}/, :count => 1
347       assert_select "abbr[class=geo][title='#{number_with_precision(new_latitude, :precision => 4)}; #{number_with_precision(new_longitude, :precision => 4)}']", :count => 1
348       # As we're not logged in, check that you cannot edit
349       assert_select "a[href='/user/#{ERB::Util.u(entry.user.display_name)}/diary/#{entry.id}/edit']", false
350     end
351   end
352
353   def test_edit_i18n
354     user = create(:user)
355     diary_entry = create(:diary_entry, :language_code => "en", :user => user)
356     session_for(user)
357     get edit_diary_entry_path(user, diary_entry)
358     assert_response :success
359     assert_select "span[class=translation_missing]", false, "Missing translation in edit diary entry"
360   end
361
362   def test_update
363     user = create(:user)
364     other_user = create(:user)
365     diary_entry = create(:diary_entry, :language_code => "en", :user => user, :title => "Original Title")
366
367     put diary_entry_path(user, diary_entry, :diary_entry => { :title => "Updated Title" })
368     assert_response :forbidden
369     diary_entry.reload
370     assert_equal "Original Title", diary_entry.title
371
372     session_for(other_user)
373     put diary_entry_path(user, diary_entry, :diary_entry => { :title => "Updated Title" })
374     assert_redirected_to diary_entry_path(user, diary_entry)
375     diary_entry.reload
376     assert_equal "Original Title", diary_entry.title
377
378     session_for(user)
379     put diary_entry_path(user, diary_entry, :diary_entry => { :title => "Updated Title" })
380     assert_redirected_to diary_entry_path(user, diary_entry)
381     diary_entry.reload
382     assert_equal "Updated Title", diary_entry.title
383   end
384
385   def test_index_all
386     diary_entry = create(:diary_entry)
387     geo_entry = create(:diary_entry, :latitude => 51.50763, :longitude => -0.10781)
388     public_entry = create(:diary_entry, :user => create(:user))
389
390     # Try a list of all diary entries
391     get diary_entries_path
392     check_diary_index diary_entry, geo_entry, public_entry
393   end
394
395   def test_index_user
396     user = create(:user)
397     other_user = create(:user)
398
399     diary_entry = create(:diary_entry, :user => user)
400     geo_entry = create(:diary_entry, :user => user, :latitude => 51.50763, :longitude => -0.10781)
401     _other_entry = create(:diary_entry, :user => other_user)
402
403     # Try a list of diary entries for a valid user
404     get diary_entries_path(:display_name => user.display_name)
405     check_diary_index diary_entry, geo_entry
406
407     # Try a list of diary entries for an invalid user
408     get diary_entries_path(:display_name => "No Such User")
409     assert_response :not_found
410     assert_template "users/no_such_user"
411   end
412
413   def test_index_friends
414     user = create(:user)
415     other_user = create(:user)
416     follow = create(:follow, :follower => user)
417     diary_entry = create(:diary_entry, :user => follow.following)
418     _other_entry = create(:diary_entry, :user => other_user)
419
420     # Try a list of diary entries for your friends when not logged in
421     get friends_diary_entries_path
422     assert_redirected_to login_path(:referer => "/diary/friends")
423
424     # Try a list of diary entries for your friends when logged in
425     session_for(user)
426     get friends_diary_entries_path
427     check_diary_index diary_entry
428     session_for(other_user)
429     get friends_diary_entries_path
430     check_diary_index
431   end
432
433   def test_index_nearby
434     user = create(:user, :home_lat => 12, :home_lon => 12)
435     nearby_user = create(:user, :home_lat => 11.9, :home_lon => 12.1)
436
437     diary_entry = create(:diary_entry, :user => user)
438
439     # Try a list of diary entries for nearby users when not logged in
440     get nearby_diary_entries_path
441     assert_redirected_to login_path(:referer => "/diary/nearby")
442
443     # Try a list of diary entries for nearby users when logged in
444     session_for(nearby_user)
445     get nearby_diary_entries_path
446     check_diary_index diary_entry
447     session_for(user)
448     get nearby_diary_entries_path
449     check_diary_index
450   end
451
452   def test_index_language
453     create(:language, :code => "de")
454     create(:language, :code => "sl")
455     diary_entry_en = create(:diary_entry, :language_code => "en")
456     diary_entry_en2 = create(:diary_entry, :language_code => "en")
457     diary_entry_de = create(:diary_entry, :language_code => "de")
458
459     # Try a list of diary entries in english
460     get diary_entries_path(:language => "en")
461     check_diary_index diary_entry_en, diary_entry_en2
462
463     # Try a list of diary entries in german
464     get diary_entries_path(:language => "de")
465     check_diary_index diary_entry_de
466
467     # Try a list of diary entries in slovenian
468     get diary_entries_path(:language => "sl")
469     check_diary_index
470   end
471
472   def test_index_paged
473     create_list(:diary_entry, 50)
474     check_pagination_of_50_entries diary_entries_path
475   end
476
477   def test_index_user_paged
478     user = create(:user)
479     create_list(:diary_entry, 50, :user => user)
480     user.confirm!
481     check_pagination_of_50_entries user_diary_entries_path(user)
482   end
483
484   def test_index_invalid_paged
485     # Try some invalid paged accesses
486     %w[-1 fred].each do |id|
487       get diary_entries_path(:before => id)
488       assert_redirected_to :controller => :errors, :action => :bad_request
489
490       get diary_entries_path(:after => id)
491       assert_redirected_to :controller => :errors, :action => :bad_request
492     end
493   end
494
495   def test_rss
496     create(:language, :code => "de")
497     create(:diary_entry, :language_code => "en")
498     create(:diary_entry, :language_code => "en")
499     create(:diary_entry, :language_code => "de")
500
501     get diary_rss_path
502     assert_response :success, "Should be able to get a diary RSS"
503     assert_select "rss", :count => 1 do
504       assert_select "channel", :count => 1 do
505         assert_select "channel>title", :count => 1
506         assert_select "image", :count => 1
507         assert_select "channel>item", :count => 3
508       end
509     end
510   end
511
512   def test_rss_language
513     create(:language, :code => "de")
514     create(:diary_entry, :language_code => "en")
515     create(:diary_entry, :language_code => "en")
516     create(:diary_entry, :language_code => "de")
517
518     get diary_rss_path(:language => "en")
519     assert_response :success, "Should be able to get a specific language diary RSS"
520     assert_select "rss>channel>item", :count => 2 # , "Diary entries should be filtered by language"
521   end
522
523   #  def test_rss_nonexisting_language
524   #    get :rss, :params => { :language => 'xx', :format => :rss }
525   #    assert_response :not_found, "Should not be able to get a nonexisting language diary RSS"
526   #  end
527
528   def test_rss_language_with_no_entries
529     create(:language, :code => "sl")
530     create(:diary_entry, :language_code => "en")
531
532     get diary_rss_path(:language => "sl")
533     assert_response :success, "Should be able to get a specific language diary RSS"
534     assert_select "rss>channel>item", :count => 0 # , "Diary entries should be filtered by language"
535   end
536
537   def test_rss_user
538     user = create(:user)
539     other_user = create(:user)
540     create(:diary_entry, :user => user)
541     create(:diary_entry, :user => user)
542     create(:diary_entry, :user => other_user)
543
544     get diary_rss_path(:display_name => user.display_name)
545     assert_response :success, "Should be able to get a specific users diary RSS"
546     assert_select "rss>channel>item", :count => 2 # , "Diary entries should be filtered by user"
547   end
548
549   def test_rss_nonexisting_user
550     # Try a user that has never existed
551     get diary_rss_path(:display_name => "fakeUsername76543")
552     assert_response :not_found, "Should not be able to get a nonexisting users diary RSS"
553
554     # Try a suspended user
555     get diary_rss_path(:display_name => create(:user, :suspended).display_name)
556     assert_response :not_found, "Should not be able to get a suspended users diary RSS"
557
558     # Try a deleted user
559     get diary_rss_path(:display_name => create(:user, :deleted).display_name)
560     assert_response :not_found, "Should not be able to get a deleted users diary RSS"
561   end
562
563   def test_rss_character_escaping
564     create(:diary_entry, :title => "<script>")
565     get diary_rss_path
566
567     assert_match "<title>&lt;script&gt;</title>", response.body
568   end
569
570   def test_feed_delay
571     create(:diary_entry, :created_at => 7.hours.ago)
572     create(:diary_entry, :created_at => 5.hours.ago)
573     get diary_rss_path
574     assert_select "rss>channel>item", :count => 2
575
576     with_settings(:diary_feed_delay => 6) do
577       get diary_rss_path
578       assert_select "rss>channel>item", :count => 1
579     end
580   end
581
582   def test_show
583     user = create(:user)
584     suspended_user = create(:user, :suspended)
585     deleted_user = create(:user, :deleted)
586
587     # Try a normal entry that should work
588     diary_entry = create(:diary_entry, :user => user)
589     get diary_entry_path(user, diary_entry)
590     assert_response :success
591     assert_template :show
592
593     # Try a non-integer ID
594     get "/user/#{CGI.escape(user.display_name)}/diary/#{diary_entry.id})"
595     assert_response :not_found
596     assert_template "rescues/routing_error"
597
598     # Try a deleted entry
599     diary_entry_deleted = create(:diary_entry, :user => user, :visible => false)
600     get diary_entry_path(user, diary_entry_deleted)
601     assert_response :not_found
602
603     # Try an entry by a suspended user
604     diary_entry_suspended_user = create(:diary_entry, :user => suspended_user)
605     get diary_entry_path(suspended_user, diary_entry_suspended_user)
606     assert_response :not_found
607
608     # Try an entry by a deleted user
609     diary_entry_deleted_user = create(:diary_entry, :user => deleted_user)
610     get diary_entry_path(deleted_user, diary_entry_deleted_user)
611     assert_response :not_found
612
613     # Now try as a moderator
614     session_for(create(:moderator_user))
615     get diary_entry_path(user, diary_entry_deleted)
616     assert_response :success
617     assert_template :show
618
619     # Finally try as an administrator
620     session_for(create(:administrator_user))
621     get diary_entry_path(user, diary_entry_deleted)
622     assert_response :success
623     assert_template :show
624   end
625
626   def test_show_hidden_comments
627     # Get a diary entry that has hidden comments
628     user = create(:user)
629     diary_entry = create(:diary_entry, :user => user)
630     visible_comment = create(:diary_comment, :diary_entry => diary_entry)
631     suspended_user_comment = create(:diary_comment, :diary_entry => diary_entry, :user => create(:user, :suspended))
632     deleted_user_comment = create(:diary_comment, :diary_entry => diary_entry, :user => create(:user, :deleted))
633     hidden_comment = create(:diary_comment, :diary_entry => diary_entry, :visible => false)
634
635     get diary_entry_path(user, diary_entry)
636     assert_response :success
637     assert_template :show
638     assert_select "div.comments" do
639       assert_select "p#comment#{visible_comment.id}", :count => 1
640       assert_select "p#comment#{suspended_user_comment.id}", :count => 0
641       assert_select "p#comment#{deleted_user_comment.id}", :count => 0
642       assert_select "p#comment#{hidden_comment.id}", :count => 0
643     end
644   end
645
646   def test_show_og_title
647     user = create(:user)
648     diary_entry = create(:diary_entry, :user => user, :title => "The Important Blog Post")
649
650     get diary_entry_path(user, diary_entry)
651     assert_response :success
652     assert_dom "head meta[property='og:title']" do
653       assert_dom "> @content", "The Important Blog Post"
654     end
655   end
656
657   def test_show_og_image_with_no_image
658     user = create(:user)
659     diary_entry = create(:diary_entry, :user => user, :body => "nothing")
660
661     get diary_entry_path(user, diary_entry)
662     assert_response :success
663     assert_dom "head meta[property='og:image']" do
664       assert_dom "> @content", ActionController::Base.helpers.image_url("osm_logo_256.png", :host => root_url)
665     end
666     assert_dom "head meta[property='og:image:alt']" do
667       assert_dom "> @content", "OpenStreetMap logo"
668     end
669   end
670
671   def test_show_og_image
672     user = create(:user)
673     diary_entry = create(:diary_entry, :user => user, :body => "![some picture](https://example.com/picture.jpg)")
674
675     get diary_entry_path(user, diary_entry)
676     assert_response :success
677     assert_dom "head meta[property='og:image']" do
678       assert_dom "> @content", "https://example.com/picture.jpg"
679     end
680     assert_dom "head meta[property='og:image:alt']" do
681       assert_dom "> @content", "some picture"
682     end
683   end
684
685   def test_show_og_image_with_relative_uri
686     user = create(:user)
687     diary_entry = create(:diary_entry, :user => user, :body => "![some local picture](/picture.jpg)")
688
689     get diary_entry_path(user, diary_entry)
690     assert_response :success
691     assert_dom "head meta[property='og:image']" do
692       assert_dom "> @content", "#{root_url}picture.jpg"
693     end
694     assert_dom "head meta[property='og:image:alt']" do
695       assert_dom "> @content", "some local picture"
696     end
697   end
698
699   def test_show_og_image_with_spaces
700     user = create(:user)
701     diary_entry = create(:diary_entry, :user => user, :body => "![some picture](https://example.com/the picture.jpg)")
702
703     get diary_entry_path(user, diary_entry)
704     assert_response :success
705     assert_dom "head meta[property='og:image']" do
706       assert_dom "> @content", "https://example.com/the%20picture.jpg"
707     end
708     assert_dom "head meta[property='og:image:alt']" do
709       assert_dom "> @content", "some picture"
710     end
711   end
712
713   def test_show_og_image_with_relative_uri_and_spaces
714     user = create(:user)
715     diary_entry = create(:diary_entry, :user => user, :body => "![some local picture](/the picture.jpg)")
716
717     get diary_entry_path(user, diary_entry)
718     assert_response :success
719     assert_dom "head meta[property='og:image']" do
720       assert_dom "> @content", "#{root_url}the%20picture.jpg"
721     end
722     assert_dom "head meta[property='og:image:alt']" do
723       assert_dom "> @content", "some local picture"
724     end
725   end
726
727   def test_show_og_image_with_invalid_uri
728     user = create(:user)
729     diary_entry = create(:diary_entry, :user => user, :body => "![](:)")
730
731     get diary_entry_path(user, diary_entry)
732     assert_response :success
733     assert_dom "head meta[property='og:image']" do
734       assert_dom "> @content", ActionController::Base.helpers.image_url("osm_logo_256.png", :host => root_url)
735     end
736     assert_dom "head meta[property='og:image:alt']" do
737       assert_dom "> @content", "OpenStreetMap logo"
738     end
739   end
740
741   def test_show_og_image_without_alt
742     user = create(:user)
743     diary_entry = create(:diary_entry, :user => user, :body => "<img src='https://example.com/no_alt.gif'>")
744
745     get diary_entry_path(user, diary_entry)
746     assert_response :success
747     assert_dom "head meta[property='og:image']" do
748       assert_dom "> @content", "https://example.com/no_alt.gif"
749     end
750     assert_dom "head meta[property='og:image:alt']", :count => 0
751   end
752
753   def test_show_no_og_description
754     user = create(:user)
755     diary_entry = create(:diary_entry, :user => user, :body => "![nope](https://example.com/nope.jpg)")
756
757     get diary_entry_path(user, diary_entry)
758     assert_response :success
759     assert_dom "head meta[property='og:description']" do
760       assert_dom "> @content", I18n.t("layouts.intro_text")
761     end
762   end
763
764   def test_show_og_description
765     user = create(:user)
766     diary_entry = create(:diary_entry, :user => user, :body => "# Hello\n\n![hello](https://example.com/hello.jpg)\n\nFirst paragraph.\n\nSecond paragraph.")
767
768     get diary_entry_path(user, diary_entry)
769     assert_response :success
770     assert_dom "head meta[property='og:description']" do
771       assert_dom "> @content", "First paragraph."
772     end
773   end
774
775   def test_show_article_published_time
776     user = create(:user)
777     diary_entry = create(:diary_entry, :user => user, :created_at => "2020-03-04")
778
779     get diary_entry_path(user, diary_entry)
780     assert_response :success
781     assert_dom "head meta[property='article:published_time']" do
782       assert_dom "> @content", "2020-03-04T00:00:00Z"
783     end
784   end
785
786   def test_hide
787     user = create(:user)
788     diary_entry = create(:diary_entry, :user => user)
789
790     # Try without logging in
791     post hide_diary_entry_path(user, diary_entry)
792     assert_response :forbidden
793     assert DiaryEntry.find(diary_entry.id).visible
794
795     # Now try as a normal user
796     session_for(user)
797     post hide_diary_entry_path(user, diary_entry)
798     assert_redirected_to :controller => :errors, :action => :forbidden
799     assert DiaryEntry.find(diary_entry.id).visible
800
801     # Now try as a moderator
802     session_for(create(:moderator_user))
803     post hide_diary_entry_path(user, diary_entry)
804     assert_redirected_to :action => :index, :display_name => user.display_name
805     assert_not DiaryEntry.find(diary_entry.id).visible
806
807     # Reset
808     diary_entry.reload.update(:visible => true)
809
810     # Finally try as an administrator
811     session_for(create(:administrator_user))
812     post hide_diary_entry_path(user, diary_entry)
813     assert_redirected_to :action => :index, :display_name => user.display_name
814     assert_not DiaryEntry.find(diary_entry.id).visible
815   end
816
817   def test_unhide
818     user = create(:user)
819
820     # Try without logging in
821     diary_entry = create(:diary_entry, :user => user, :visible => false)
822     post unhide_diary_entry_path(user, diary_entry)
823     assert_response :forbidden
824     assert_not DiaryEntry.find(diary_entry.id).visible
825
826     # Now try as a normal user
827     session_for(user)
828     post unhide_diary_entry_path(user, diary_entry)
829     assert_redirected_to :controller => :errors, :action => :forbidden
830     assert_not DiaryEntry.find(diary_entry.id).visible
831
832     # Now try as a moderator
833     session_for(create(:moderator_user))
834     post unhide_diary_entry_path(user, diary_entry)
835     assert_redirected_to :action => :index, :display_name => user.display_name
836     assert DiaryEntry.find(diary_entry.id).visible
837
838     # Reset
839     diary_entry.reload.update(:visible => true)
840
841     # Finally try as an administrator
842     session_for(create(:administrator_user))
843     post unhide_diary_entry_path(user, diary_entry)
844     assert_redirected_to :action => :index, :display_name => user.display_name
845     assert DiaryEntry.find(diary_entry.id).visible
846   end
847
848   def test_subscribe_page
849     user = create(:user)
850     other_user = create(:user)
851     diary_entry = create(:diary_entry, :user => user)
852     path = diary_entry_subscribe_path(user, diary_entry)
853
854     get path
855     assert_redirected_to login_path(:referer => path)
856
857     session_for(other_user)
858     get path
859     assert_response :success
860     assert_dom ".content-body" do
861       assert_dom "a[href='#{diary_entry_path(user, diary_entry)}']", :text => diary_entry.title
862       assert_dom "a[href='#{user_path(user)}']", :text => user.display_name
863     end
864   end
865
866   def test_subscribe_success
867     user = create(:user)
868     other_user = create(:user)
869     diary_entry = create(:diary_entry, :user => user)
870
871     session_for(other_user)
872     assert_difference "diary_entry.subscribers.count", 1 do
873       post diary_entry_subscribe_path(user, diary_entry)
874     end
875     assert_response :redirect
876   end
877
878   def test_subscribe_fail
879     user = create(:user)
880     other_user = create(:user)
881
882     diary_entry = create(:diary_entry, :user => user)
883
884     # not signed in
885     assert_no_difference "diary_entry.subscribers.count" do
886       post diary_entry_subscribe_path(user, diary_entry)
887     end
888     assert_response :forbidden
889
890     session_for(other_user)
891
892     # bad diary id
893     post diary_entry_subscribe_path("username", 999111)
894     assert_response :not_found
895
896     # trying to subscribe when already subscribed
897     post diary_entry_subscribe_path(user, diary_entry)
898     assert_no_difference "diary_entry.subscribers.count" do
899       post diary_entry_subscribe_path(user, diary_entry)
900     end
901   end
902
903   def test_unsubscribe_page
904     user = create(:user)
905     other_user = create(:user)
906     diary_entry = create(:diary_entry, :user => user)
907     path = diary_entry_unsubscribe_path(user, diary_entry)
908
909     get path
910     assert_redirected_to login_path(:referer => path)
911
912     session_for(other_user)
913     get path
914     assert_response :success
915     assert_dom ".content-body" do
916       assert_dom "a[href='#{diary_entry_path(user, diary_entry)}']", :text => diary_entry.title
917       assert_dom "a[href='#{user_path(user)}']", :text => user.display_name
918     end
919   end
920
921   def test_unsubscribe_success
922     user = create(:user)
923     other_user = create(:user)
924
925     diary_entry = create(:diary_entry, :user => user)
926     create(:diary_entry_subscription, :diary_entry => diary_entry, :user => other_user)
927
928     session_for(other_user)
929     assert_difference "diary_entry.subscribers.count", -1 do
930       post diary_entry_unsubscribe_path(user, diary_entry)
931     end
932     assert_response :redirect
933   end
934
935   def test_unsubscribe_fail
936     user = create(:user)
937     other_user = create(:user)
938
939     diary_entry = create(:diary_entry, :user => user)
940
941     # not signed in
942     assert_no_difference "diary_entry.subscribers.count" do
943       post diary_entry_unsubscribe_path(user, diary_entry)
944     end
945     assert_response :forbidden
946
947     session_for(other_user)
948
949     # bad diary id
950     post diary_entry_unsubscribe_path("username", 999111)
951     assert_response :not_found
952
953     # trying to unsubscribe when not subscribed
954     assert_no_difference "diary_entry.subscribers.count" do
955       post diary_entry_unsubscribe_path(user, diary_entry)
956     end
957   end
958
959   private
960
961   def check_diary_index(*entries)
962     assert_response :success
963     assert_template "index"
964     assert_no_missing_translations
965     assert_select "article.diary_post", entries.count
966
967     entries.each do |entry|
968       assert_select "a[href=?]", "/user/#{ERB::Util.u(entry.user.display_name)}/diary/#{entry.id}"
969     end
970   end
971
972   def check_pagination_of_50_entries(path)
973     # Try and get the index
974     get path
975     assert_response :success
976     assert_select "article.diary_post", :count => 20
977     check_no_page_link "Newer Entries"
978     path = check_page_link "Older Entries"
979
980     # Try and get the second page
981     get path
982     assert_response :success
983     assert_select "article.diary_post", :count => 20
984     check_page_link "Newer Entries"
985     path = check_page_link "Older Entries"
986
987     # Try and get the third page
988     get path
989     assert_response :success
990     assert_select "article.diary_post", :count => 10
991     path = check_page_link "Newer Entries"
992     check_no_page_link "Older Entries"
993
994     # Go back to the second page
995     get path
996     assert_response :success
997     assert_select "article.diary_post", :count => 20
998     path = check_page_link "Newer Entries"
999     check_page_link "Older Entries"
1000
1001     # Go back to the first page
1002     get path
1003     assert_response :success
1004     assert_select "article.diary_post", :count => 20
1005     check_no_page_link "Newer Entries"
1006     check_page_link "Older Entries"
1007   end
1008
1009   def check_no_page_link(name)
1010     assert_select "a.page-link", { :text => /#{Regexp.quote(name)}/, :count => 0 }, "unexpected #{name} page link"
1011   end
1012
1013   def check_page_link(name)
1014     assert_select "a.page-link", { :text => /#{Regexp.quote(name)}/ }, "missing #{name} page link" do |buttons|
1015       return buttons.first.attributes["href"].value
1016     end
1017   end
1018 end