forked from asonix/mastodon
* 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
342 lines
9.2 KiB
Ruby
342 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
|