application_controller_spec.rb 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. describe ApplicationController, type: :controller do
  4. controller do
  5. def success
  6. head 200
  7. end
  8. def routing_error
  9. raise ActionController::RoutingError, ''
  10. end
  11. def record_not_found
  12. raise ActiveRecord::RecordNotFound, ''
  13. end
  14. def invalid_authenticity_token
  15. raise ActionController::InvalidAuthenticityToken, ''
  16. end
  17. end
  18. shared_examples 'respond_with_error' do |code|
  19. it "returns http #{code} for any" do
  20. subject
  21. expect(response).to have_http_status(code)
  22. end
  23. it "returns http #{code} for http" do
  24. subject
  25. expect(response).to have_http_status(code)
  26. end
  27. it "renders template for http" do
  28. is_expected.to render_template("errors/#{code}", layout: 'error')
  29. end
  30. end
  31. context 'forgery' do
  32. subject do
  33. ActionController::Base.allow_forgery_protection = true
  34. routes.draw { post 'success' => 'anonymous#success' }
  35. post 'success'
  36. end
  37. include_examples 'respond_with_error', 422
  38. end
  39. it "does not force ssl if Rails.env.production? is not 'true'" do
  40. routes.draw { get 'success' => 'anonymous#success' }
  41. allow(Rails.env).to receive(:production?).and_return(false)
  42. get 'success'
  43. expect(response).to have_http_status(200)
  44. end
  45. it "forces ssl if Rails.env.production? is 'true'" do
  46. routes.draw { get 'success' => 'anonymous#success' }
  47. allow(Rails.env).to receive(:production?).and_return(true)
  48. get 'success'
  49. expect(response).to redirect_to('https://test.host/success')
  50. end
  51. describe 'helper_method :current_account' do
  52. it 'returns nil if not signed in' do
  53. expect(controller.view_context.current_account).to be_nil
  54. end
  55. it 'returns account if signed in' do
  56. account = Fabricate(:account)
  57. sign_in(Fabricate(:user, account: account))
  58. expect(controller.view_context.current_account).to eq account
  59. end
  60. end
  61. describe 'helper_method :single_user_mode?' do
  62. it 'returns false if it is in single_user_mode but there is no account' do
  63. allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
  64. expect(controller.view_context.single_user_mode?).to eq false
  65. end
  66. it 'returns false if there is an account but it is not in single_user_mode' do
  67. allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false)
  68. Fabricate(:account)
  69. expect(controller.view_context.single_user_mode?).to eq false
  70. end
  71. it 'returns true if it is in single_user_mode and there is an account' do
  72. allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
  73. Fabricate(:account)
  74. expect(controller.view_context.single_user_mode?).to eq true
  75. end
  76. end
  77. describe 'helper_method :current_theme' do
  78. it 'returns "default" when theme wasn\'t changed in admin settings' do
  79. allow(Setting).to receive(:default_settings).and_return({ 'theme' => 'default' })
  80. expect(controller.view_context.current_theme).to eq 'default'
  81. end
  82. it 'returns instances\'s theme when user is not signed in' do
  83. allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
  84. expect(controller.view_context.current_theme).to eq 'contrast'
  85. end
  86. it 'returns instances\'s default theme when user didn\'t set theme' do
  87. current_user = Fabricate(:user)
  88. sign_in current_user
  89. allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
  90. expect(controller.view_context.current_theme).to eq 'contrast'
  91. end
  92. it 'returns user\'s theme when it is set' do
  93. current_user = Fabricate(:user)
  94. current_user.settings['theme'] = 'mastodon-light'
  95. sign_in current_user
  96. allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
  97. expect(controller.view_context.current_theme).to eq 'mastodon-light'
  98. end
  99. end
  100. context 'ActionController::RoutingError' do
  101. subject do
  102. routes.draw { get 'routing_error' => 'anonymous#routing_error' }
  103. get 'routing_error'
  104. end
  105. include_examples 'respond_with_error', 404
  106. end
  107. context 'ActiveRecord::RecordNotFound' do
  108. subject do
  109. routes.draw { get 'record_not_found' => 'anonymous#record_not_found' }
  110. get 'record_not_found'
  111. end
  112. include_examples 'respond_with_error', 404
  113. end
  114. context 'ActionController::InvalidAuthenticityToken' do
  115. subject do
  116. routes.draw { get 'invalid_authenticity_token' => 'anonymous#invalid_authenticity_token' }
  117. get 'invalid_authenticity_token'
  118. end
  119. include_examples 'respond_with_error', 422
  120. end
  121. describe 'before_action :store_current_location' do
  122. it 'stores location for user if it is not devise controller' do
  123. routes.draw { get 'success' => 'anonymous#success' }
  124. get 'success'
  125. expect(controller.stored_location_for(:user)).to eq '/success'
  126. end
  127. context do
  128. controller Devise::SessionsController do
  129. end
  130. it 'does not store location for user if it is devise controller' do
  131. @request.env["devise.mapping"] = Devise.mappings[:user]
  132. get 'create'
  133. expect(controller.stored_location_for(:user)).to be_nil
  134. end
  135. end
  136. end
  137. describe 'before_action :check_suspension' do
  138. before do
  139. routes.draw { get 'success' => 'anonymous#success' }
  140. end
  141. it 'does nothing if not signed in' do
  142. get 'success'
  143. expect(response).to have_http_status(200)
  144. end
  145. it 'does nothing if user who signed in is not suspended' do
  146. sign_in(Fabricate(:user, account: Fabricate(:account, suspended: false)))
  147. get 'success'
  148. expect(response).to have_http_status(200)
  149. end
  150. it 'returns http 403 if user who signed in is suspended' do
  151. sign_in(Fabricate(:user, account: Fabricate(:account, suspended: true)))
  152. get 'success'
  153. expect(response).to have_http_status(403)
  154. end
  155. end
  156. describe 'raise_not_found' do
  157. it 'raises error' do
  158. controller.params[:unmatched_route] = 'unmatched'
  159. expect { controller.raise_not_found }.to raise_error(ActionController::RoutingError, 'No route matches unmatched')
  160. end
  161. end
  162. describe 'require_admin!' do
  163. controller do
  164. before_action :require_admin!
  165. def sucesss
  166. head 200
  167. end
  168. end
  169. before do
  170. routes.draw { get 'sucesss' => 'anonymous#sucesss' }
  171. end
  172. it 'returns a 403 if current user is not admin' do
  173. sign_in(Fabricate(:user, admin: false))
  174. get 'sucesss'
  175. expect(response).to have_http_status(403)
  176. end
  177. it 'returns a 403 if current user is only a moderator' do
  178. sign_in(Fabricate(:user, moderator: true))
  179. get 'sucesss'
  180. expect(response).to have_http_status(403)
  181. end
  182. it 'does nothing if current user is admin' do
  183. sign_in(Fabricate(:user, admin: true))
  184. get 'sucesss'
  185. expect(response).to have_http_status(200)
  186. end
  187. end
  188. describe 'require_staff!' do
  189. controller do
  190. before_action :require_staff!
  191. def sucesss
  192. head 200
  193. end
  194. end
  195. before do
  196. routes.draw { get 'sucesss' => 'anonymous#sucesss' }
  197. end
  198. it 'returns a 403 if current user is not admin or moderator' do
  199. sign_in(Fabricate(:user, admin: false, moderator: false))
  200. get 'sucesss'
  201. expect(response).to have_http_status(403)
  202. end
  203. it 'does nothing if current user is moderator' do
  204. sign_in(Fabricate(:user, moderator: true))
  205. get 'sucesss'
  206. expect(response).to have_http_status(200)
  207. end
  208. it 'does nothing if current user is admin' do
  209. sign_in(Fabricate(:user, admin: true))
  210. get 'sucesss'
  211. expect(response).to have_http_status(200)
  212. end
  213. end
  214. describe 'forbidden' do
  215. controller do
  216. def route_forbidden
  217. forbidden
  218. end
  219. end
  220. subject do
  221. routes.draw { get 'route_forbidden' => 'anonymous#route_forbidden' }
  222. get 'route_forbidden'
  223. end
  224. include_examples 'respond_with_error', 403
  225. end
  226. describe 'not_found' do
  227. controller do
  228. def route_not_found
  229. not_found
  230. end
  231. end
  232. subject do
  233. routes.draw { get 'route_not_found' => 'anonymous#route_not_found' }
  234. get 'route_not_found'
  235. end
  236. include_examples 'respond_with_error', 404
  237. end
  238. describe 'gone' do
  239. controller do
  240. def route_gone
  241. gone
  242. end
  243. end
  244. subject do
  245. routes.draw { get 'route_gone' => 'anonymous#route_gone' }
  246. get 'route_gone'
  247. end
  248. include_examples 'respond_with_error', 410
  249. end
  250. describe 'unprocessable_entity' do
  251. controller do
  252. def route_unprocessable_entity
  253. unprocessable_entity
  254. end
  255. end
  256. subject do
  257. routes.draw { get 'route_unprocessable_entity' => 'anonymous#route_unprocessable_entity' }
  258. get 'route_unprocessable_entity'
  259. end
  260. include_examples 'respond_with_error', 422
  261. end
  262. describe 'cache_collection' do
  263. class C < ApplicationController
  264. public :cache_collection
  265. end
  266. shared_examples 'receives :with_includes' do |fabricator, klass|
  267. it 'uses raw if it is not an ActiveRecord::Relation' do
  268. record = Fabricate(fabricator)
  269. expect(C.new.cache_collection([record], klass)).to eq [record]
  270. end
  271. end
  272. shared_examples 'cacheable' do |fabricator, klass|
  273. include_examples 'receives :with_includes', fabricator, klass
  274. it 'calls cache_ids of raw if it is an ActiveRecord::Relation' do
  275. record = Fabricate(fabricator)
  276. relation = klass.none
  277. allow(relation).to receive(:cache_ids).and_return([record])
  278. expect(C.new.cache_collection(relation, klass)).to eq [record]
  279. end
  280. end
  281. it 'returns raw unless class responds to :with_includes' do
  282. raw = Object.new
  283. expect(C.new.cache_collection(raw, Object)).to eq raw
  284. end
  285. context 'Notification' do
  286. include_examples 'cacheable', :notification, Notification
  287. end
  288. context 'Status' do
  289. include_examples 'cacheable', :status, Status
  290. end
  291. context 'StreamEntry' do
  292. include_examples 'receives :with_includes', :stream_entry, StreamEntry
  293. end
  294. end
  295. end