discourse/spec/rails_helper.rb

351 lines
8.9 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2013-02-05 14:16:51 -05:00
if ENV['COVERAGE']
require 'simplecov'
SimpleCov.start
end
require 'rubygems'
require 'rbtrace'
2017-08-09 17:50:59 -04:00
# Loading more in this block will cause your tests to run faster. However,
# if you change any configuration or code from libraries loaded here, you'll
# need to restart spork for it take effect.
require 'fabrication'
require 'mocha/api'
require 'certified'
require 'webmock/rspec'
class RspecErrorTracker
def self.last_exception=(ex)
@ex = ex
end
def self.last_exception
@ex
end
def initialize(app, config = {})
@app = app
end
def call(env)
begin
@app.call(env)
rescue => e
RspecErrorTracker.last_exception = e
raise e
end
ensure
end
end
2017-08-09 17:50:59 -04:00
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'shoulda-matchers'
2017-08-09 17:50:59 -04:00
require 'sidekiq/testing'
# The shoulda-matchers gem no longer detects the test framework
# you're using or mixes itself into that framework automatically.
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :active_record
with.library :active_model
end
end
2017-08-09 17:50:59 -04:00
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
Dir[Rails.root.join("spec/fabricators/*.rb")].each { |f| require f }
# Require plugin helpers at plugin/[plugin]/spec/plugin_helper.rb (includes symlinked plugins).
if ENV['LOAD_PLUGINS'] == "1"
Dir[Rails.root.join("plugins/*/spec/plugin_helper.rb")].each do |f|
require f
end
2017-08-09 17:50:59 -04:00
end
2017-08-09 17:50:59 -04:00
# let's not run seed_fu every test
SeedFu.quiet = true if SeedFu.respond_to? :quiet
2017-08-09 17:50:59 -04:00
SiteSetting.automatically_download_gravatars = false
2017-08-09 17:50:59 -04:00
SeedFu.seed
2013-02-05 14:16:51 -05:00
2017-08-09 17:50:59 -04:00
RSpec.configure do |config|
config.fail_fast = ENV['RSPEC_FAIL_FAST'] == "1"
config.include Helpers
config.include MessageBus
config.include RSpecHtmlMatchers
config.include IntegrationHelpers, type: :request
config.include SiteSettingsHelpers
2017-08-09 17:50:59 -04:00
config.mock_framework = :mocha
config.order = 'random'
config.infer_spec_type_from_file_location!
2013-02-05 14:16:51 -05:00
2017-08-09 17:50:59 -04:00
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
2013-02-05 14:16:51 -05:00
2017-08-09 17:50:59 -04:00
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = true
2013-02-05 14:16:51 -05:00
2017-08-09 17:50:59 -04:00
config.before(:suite) do
Sidekiq.error_handlers.clear
2017-08-09 17:50:59 -04:00
# Ugly, but needed until we have a user creator
User.skip_callback(:create, :after, :ensure_in_trust_level_group)
2017-08-09 17:50:59 -04:00
DiscoursePluginRegistry.clear if ENV['LOAD_PLUGINS'] != "1"
Discourse.current_user_provider = TestCurrentUserProvider
2017-08-09 17:50:59 -04:00
SiteSetting.refresh!
2017-08-09 17:50:59 -04:00
# Rebase defaults
#
# We nuke the DB storage provider from site settings, so need to yank out the existing settings
# and pretend they are default.
# There are a bunch of settings that are seeded, they must be loaded as defaults
SiteSetting.current.each do |k, v|
# skip setting defaults for settings that are in unloaded plugins
SiteSetting.defaults.set_regardless_of_locale(k, v) if SiteSetting.respond_to? k
end
2017-08-09 17:50:59 -04:00
require_dependency 'site_settings/local_process_provider'
SiteSetting.provider = SiteSettings::LocalProcessProvider.new
2017-08-09 17:50:59 -04:00
WebMock.disable_net_connect!
end
2017-08-09 17:50:59 -04:00
class DiscourseMockRedis < MockRedis
def without_namespace
self
end
2017-08-09 17:50:59 -04:00
def delete_prefixed(prefix)
keys("#{prefix}*").each { |k| del(k) }
end
2017-08-09 17:50:59 -04:00
end
config.after :each do |x|
if x.exception && ex = RspecErrorTracker.last_exception
# magic in a cause if we have none
unless x.exception.cause
class << x.exception
attr_accessor :cause
end
x.exception.cause = ex
end
end
unfreeze_time
ActionMailer::Base.deliveries.clear
2019-01-08 21:53:38 -05:00
if ActiveRecord::Base.connection_pool.stat[:busy] > 1
raise ActiveRecord::Base.connection_pool.stat.inspect
end
end
2017-08-09 17:50:59 -04:00
config.before :each do |x|
# TODO not sure about this, we could use a mock redis implementation here:
# this gives us really clean "flush" semantics, howere the side-effect is that
# we are no longer using a clean redis implementation, a preferable solution may
# be simply flushing before tests, trouble is that redis may be reused with dev
# so that would mean the dev would act weird
#
# perf benefit seems low (shaves 20 secs off a 4 minute test suite)
#
# $redis = DiscourseMockRedis.new
RateLimiter.disable
2017-08-09 17:50:59 -04:00
PostActionNotifier.disable
SearchIndexer.disable
UserActionManager.disable
2017-08-09 17:50:59 -04:00
NotificationEmailer.disable
FEATURE: Automatically generate optimized site metadata icons (#7372) This change automatically resizes icons for various purposes. Admins can now upload `logo` and `logo_small`, and everything else will be auto-generated. Specific icons can still be uploaded separately if required. ## Core - Adds an SiteIconManager module which manages automatic resizing and fallback - Icons are looked up in the OptimizedImage table at runtime, and then cached in Redis. If the resized version is missing for some reason, then most icons will fall back to the original files. Some icons (e.g. PWA Manifest) will return `nil` (because an incorrectly sized icon is worse than a missing icon). - `SiteSetting.site_large_icon_url` will return the optimized version, including any fallback. `SiteSetting.large_icon` continues to return the upload object. This means that (almost) no changes are required in core/plugins to support this new system. - Icons are resized whenever a relevant site setting is changed, and during post-deploy migrations ## Wizard - Allows `requiresRefresh` wizard steps to reload data via AJAX instead of a full page reload - Add placeholders to the **icons** step of the wizard, which automatically update from the "Square Logo" - Various copy updates to support the changes - Remove the "upload-time" resizing for `large_icon`. This is no longer required. ## Site Settings UX - Move logo/icon settings under a new "Branding" tab - Various copy changes to support the changes - Adds placeholder support to the `image-uploader` component - Automatically reloads site settings after saving. This allows setting placeholders to change based on changes to other settings - Upload site settings will be assigned a placeholder if SiteIconManager `responds_to?` an icon of the same name ## Dashboard Warnings - Remove PWA icon and PWA title warnings. Both are now handled automatically. ## Bonus - Updated the sketch logos to use @awesomerobot's new high-res designs
2019-05-01 09:44:45 -04:00
SiteIconManager.disable
2017-08-09 17:50:59 -04:00
SiteSetting.provider.all.each do |setting|
SiteSetting.remove_override!(setting.name)
end
2017-08-09 17:50:59 -04:00
# very expensive IO operations
SiteSetting.automatically_download_gravatars = false
2017-08-09 17:50:59 -04:00
Discourse.clear_readonly!
Sidekiq::Worker.clear_all
2017-08-09 17:50:59 -04:00
I18n.locale = :en
RspecErrorTracker.last_exception = nil
if $test_cleanup_callbacks
$test_cleanup_callbacks.reverse_each(&:call)
$test_cleanup_callbacks = nil
end
# Running jobs are expensive and most of our tests are not concern with
# code that runs inside jobs. run_later! means they are put on the redis
# queue and never processed.
Jobs.run_later!
2013-02-05 14:16:51 -05:00
end
config.before(:each, type: :multisite) do
Rails.configuration.multisite = true
RailsMultisite::ConnectionManagement.config_filename =
"spec/fixtures/multisite/two_dbs.yml"
end
config.after(:each, type: :multisite) do
ActiveRecord::Base.clear_all_connections!
Rails.configuration.multisite = false
RailsMultisite::ConnectionManagement.clear_settings!
ActiveRecord::Base.establish_connection
end
2017-08-09 17:50:59 -04:00
class TestCurrentUserProvider < Auth::DefaultCurrentUserProvider
def log_on_user(user, session, cookies, opts = {})
2017-08-09 17:50:59 -04:00
session[:current_user_id] = user.id
super
end
2017-08-09 17:50:59 -04:00
def log_off_user(session, cookies)
session[:current_user_id] = nil
super
end
2017-08-09 17:50:59 -04:00
end
# Normally we `use_transactional_fixtures` to clear out a database after a test
# runs. However, this does not apply to tests done for multisite. The second time
# a test runs you can end up with stale data that breaks things. This method will
# force a rollback after using a multisite connection.
def test_multisite_connection(name)
RailsMultisite::ConnectionManagement.with_connection(name) do
spec_exception = nil
ActiveRecord::Base.transaction do
begin
yield
rescue Exception => spec_exception
ensure
raise ActiveRecord::Rollback
end
end
raise spec_exception if spec_exception
end
end
2017-08-09 17:50:59 -04:00
end
class TrackTimeStub
def self.stubbed
false
end
2017-08-09 17:50:59 -04:00
end
def before_next_spec(&callback)
($test_cleanup_callbacks ||= []) << callback
end
def global_setting(name, value)
GlobalSetting.reset_s3_cache!
GlobalSetting.stubs(name).returns(value)
before_next_spec do
GlobalSetting.reset_s3_cache!
end
end
def set_env(var, value)
old = ENV.fetch var, :missing
ENV[var] = value
before_next_spec do
if old == :missing
ENV.delete var
else
ENV[var] = old
end
end
end
def set_cdn_url(cdn_url)
global_setting :cdn_url, cdn_url
Rails.configuration.action_controller.asset_host = cdn_url
ActionController::Base.asset_host = cdn_url
before_next_spec do
Rails.configuration.action_controller.asset_host = nil
ActionController::Base.asset_host = nil
end
end
2017-08-09 17:50:59 -04:00
def freeze_time(now = Time.now)
time = now
datetime = now
if Time === now
datetime = now.to_datetime
elsif DateTime === now
time = now.to_time
else
datetime = DateTime.parse(now.to_s)
time = Time.parse(now.to_s)
end
2017-08-09 17:50:59 -04:00
if block_given?
raise "nested freeze time not supported" if TrackTimeStub.stubbed
2013-02-05 14:16:51 -05:00
end
2017-08-09 17:50:59 -04:00
DateTime.stubs(:now).returns(datetime)
Time.stubs(:now).returns(time)
Date.stubs(:today).returns(datetime.to_date)
TrackTimeStub.stubs(:stubbed).returns(true)
if block_given?
begin
yield
ensure
unfreeze_time
end
end
2013-02-05 14:16:51 -05:00
end
2017-08-09 17:50:59 -04:00
def unfreeze_time
DateTime.unstub(:now)
Time.unstub(:now)
Date.unstub(:today)
TrackTimeStub.unstub(:stubbed)
end
2017-08-09 17:50:59 -04:00
def file_from_fixtures(filename, directory = "images")
FileUtils.mkdir_p("#{Rails.root}/tmp/spec") unless Dir.exists?("#{Rails.root}/tmp/spec")
FileUtils.cp("#{Rails.root}/spec/fixtures/#{directory}/#{filename}", "#{Rails.root}/tmp/spec/#{filename}")
File.new("#{Rails.root}/tmp/spec/#{filename}")
end
def has_trigger?(trigger_name)
DB.exec(<<~SQL) != 0
SELECT 1
FROM INFORMATION_SCHEMA.TRIGGERS
WHERE trigger_name = '#{trigger_name}'
SQL
end
def silence_stdout
STDOUT.stubs(:write)
yield
ensure
STDOUT.unstub(:write)
end