mastodon/spec/controllers/application_controller_spec.rb
Claire cbd0ee1d07
Update Mastodon to Rails 6.1 (#15910)
* Update devise-two-factor to unreleased fork for Rails 6 support

Update tests to match new `rotp` version.

* Update nsa gem to unreleased fork for Rails 6 support

* Update rails to 6.1.3 and rails-i18n to 6.0

* Update to unreleased fork of pluck_each for Ruby 6 support

* Run "rails app:update"

* Add missing ActiveStorage config file

* Use config.ssl_options instead of removed ApplicationController#force_ssl

Disabled force_ssl-related tests as they do not seem to be easily testable
anymore.

* Fix nonce directives by removing Rails 5 specific monkey-patching

* Fix fixture_file_upload deprecation warning

* Fix yield-based test failing with Rails 6

* Use Rails 6's index_with when possible

* Use ActiveRecord::Cache::Store#delete_multi from Rails 6

This will yield better performances when deleting an account

* Disable Rails 6.1's automatic preload link headers

Since Rails 6.1, ActionView adds preload links for javascript files
in the Links header per default.

In our case, that will bloat headers too much and potentially cause
issues with reverse proxies. Furhermore, we don't need those links,
as we already output them as HTML link tags.

* Switch to Rails 6.0 default config

* Switch to Rails 6.1 default config

* Do not include autoload paths in the load path
2021-03-24 10:44:31 +01:00

343 lines
9.2 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
describe ApplicationController, type: :controller do
controller do
def success
head 200
end
def routing_error
raise ActionController::RoutingError, ''
end
def record_not_found
raise ActiveRecord::RecordNotFound, ''
end
def invalid_authenticity_token
raise ActionController::InvalidAuthenticityToken, ''
end
end
shared_examples 'respond_with_error' do |code|
it "returns http #{code} for http" do
subject
expect(response).to have_http_status(code)
end
it "renders template for http" do
is_expected.to render_template("errors/#{code}", layout: 'error')
end
end
context 'forgery' do
subject do
ActionController::Base.allow_forgery_protection = true
routes.draw { post 'success' => 'anonymous#success' }
post 'success'
end
include_examples 'respond_with_error', 422
end
describe 'helper_method :current_account' do
it 'returns nil if not signed in' do
expect(controller.view_context.current_account).to be_nil
end
it 'returns account if signed in' do
account = Fabricate(:account)
sign_in(Fabricate(:user, account: account))
expect(controller.view_context.current_account).to eq account
end
end
describe 'helper_method :single_user_mode?' do
it 'returns false if it is in single_user_mode but there is no account' do
allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
expect(controller.view_context.single_user_mode?).to eq false
end
it 'returns false if there is an account but it is not in single_user_mode' do
allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false)
Fabricate(:account)
expect(controller.view_context.single_user_mode?).to eq false
end
it 'returns true if it is in single_user_mode and there is an account' do
allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
Fabricate(:account)
expect(controller.view_context.single_user_mode?).to eq true
end
end
describe 'helper_method :current_theme' do
it 'returns "default" when theme wasn\'t changed in admin settings' do
allow(Setting).to receive(:default_settings).and_return({ 'theme' => 'default' })
expect(controller.view_context.current_theme).to eq 'default'
end
it 'returns instances\'s theme when user is not signed in' do
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
expect(controller.view_context.current_theme).to eq 'contrast'
end
it 'returns instances\'s default theme when user didn\'t set theme' do
current_user = Fabricate(:user)
sign_in current_user
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
allow(Setting).to receive(:[]).with('noindex').and_return false
expect(controller.view_context.current_theme).to eq 'contrast'
end
it 'returns user\'s theme when it is set' do
current_user = Fabricate(:user)
current_user.settings['theme'] = 'mastodon-light'
sign_in current_user
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
expect(controller.view_context.current_theme).to eq 'mastodon-light'
end
end
context 'ActionController::RoutingError' do
subject do
routes.draw { get 'routing_error' => 'anonymous#routing_error' }
get 'routing_error'
end
include_examples 'respond_with_error', 404
end
context 'ActiveRecord::RecordNotFound' do
subject do
routes.draw { get 'record_not_found' => 'anonymous#record_not_found' }
get 'record_not_found'
end
include_examples 'respond_with_error', 404
end
context 'ActionController::InvalidAuthenticityToken' do
subject do
routes.draw { get 'invalid_authenticity_token' => 'anonymous#invalid_authenticity_token' }
get 'invalid_authenticity_token'
end
include_examples 'respond_with_error', 422
end
describe 'before_action :store_current_location' do
it 'stores location for user if it is not devise controller' do
routes.draw { get 'success' => 'anonymous#success' }
get 'success'
expect(controller.stored_location_for(:user)).to eq '/success'
end
context do
controller Devise::SessionsController do
end
it 'does not store location for user if it is devise controller' do
@request.env["devise.mapping"] = Devise.mappings[:user]
get 'create'
expect(controller.stored_location_for(:user)).to be_nil
end
end
end
describe 'before_action :check_suspension' do
before do
routes.draw { get 'success' => 'anonymous#success' }
end
it 'does nothing if not signed in' do
get 'success'
expect(response).to have_http_status(200)
end
it 'does nothing if user who signed in is not suspended' do
sign_in(Fabricate(:user, account: Fabricate(:account, suspended: false)))
get 'success'
expect(response).to have_http_status(200)
end
it 'redirects to account status page' do
sign_in(Fabricate(:user, account: Fabricate(:account, suspended: true)))
get 'success'
expect(response).to redirect_to(edit_user_registration_path)
end
end
describe 'raise_not_found' do
it 'raises error' do
controller.params[:unmatched_route] = 'unmatched'
expect { controller.raise_not_found }.to raise_error(ActionController::RoutingError, 'No route matches unmatched')
end
end
describe 'require_admin!' do
controller do
before_action :require_admin!
def sucesss
head 200
end
end
before do
routes.draw { get 'sucesss' => 'anonymous#sucesss' }
end
it 'returns a 403 if current user is not admin' do
sign_in(Fabricate(:user, admin: false))
get 'sucesss'
expect(response).to have_http_status(403)
end
it 'returns a 403 if current user is only a moderator' do
sign_in(Fabricate(:user, moderator: true))
get 'sucesss'
expect(response).to have_http_status(403)
end
it 'does nothing if current user is admin' do
sign_in(Fabricate(:user, admin: true))
get 'sucesss'
expect(response).to have_http_status(200)
end
end
describe 'require_staff!' do
controller do
before_action :require_staff!
def sucesss
head 200
end
end
before do
routes.draw { get 'sucesss' => 'anonymous#sucesss' }
end
it 'returns a 403 if current user is not admin or moderator' do
sign_in(Fabricate(:user, admin: false, moderator: false))
get 'sucesss'
expect(response).to have_http_status(403)
end
it 'does nothing if current user is moderator' do
sign_in(Fabricate(:user, moderator: true))
get 'sucesss'
expect(response).to have_http_status(200)
end
it 'does nothing if current user is admin' do
sign_in(Fabricate(:user, admin: true))
get 'sucesss'
expect(response).to have_http_status(200)
end
end
describe 'forbidden' do
controller do
def route_forbidden
forbidden
end
end
subject do
routes.draw { get 'route_forbidden' => 'anonymous#route_forbidden' }
get 'route_forbidden'
end
include_examples 'respond_with_error', 403
end
describe 'not_found' do
controller do
def route_not_found
not_found
end
end
subject do
routes.draw { get 'route_not_found' => 'anonymous#route_not_found' }
get 'route_not_found'
end
include_examples 'respond_with_error', 404
end
describe 'gone' do
controller do
def route_gone
gone
end
end
subject do
routes.draw { get 'route_gone' => 'anonymous#route_gone' }
get 'route_gone'
end
include_examples 'respond_with_error', 410
end
describe 'unprocessable_entity' do
controller do
def route_unprocessable_entity
unprocessable_entity
end
end
subject do
routes.draw { get 'route_unprocessable_entity' => 'anonymous#route_unprocessable_entity' }
get 'route_unprocessable_entity'
end
include_examples 'respond_with_error', 422
end
describe 'cache_collection' do
class C < ApplicationController
public :cache_collection
end
shared_examples 'receives :with_includes' do |fabricator, klass|
it 'uses raw if it is not an ActiveRecord::Relation' do
record = Fabricate(fabricator)
expect(C.new.cache_collection([record], klass)).to eq [record]
end
end
shared_examples 'cacheable' do |fabricator, klass|
include_examples 'receives :with_includes', fabricator, klass
it 'calls cache_ids of raw if it is an ActiveRecord::Relation' do
record = Fabricate(fabricator)
relation = klass.none
allow(relation).to receive(:cache_ids).and_return([record])
expect(C.new.cache_collection(relation, klass)).to eq [record]
end
end
it 'returns raw unless class responds to :with_includes' do
raw = Object.new
expect(C.new.cache_collection(raw, Object)).to eq raw
end
context 'Status' do
include_examples 'cacheable', :status, Status
end
end
end