You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
9.8 KiB

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