1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
module RSpec
module Rails
# @api public
# Container class for system tests
module SystemExampleGroup
extend ActiveSupport::Concern
include RSpec::Rails::RailsExampleGroup
include RSpec::Rails::Matchers::RedirectTo
include RSpec::Rails::Matchers::RenderTemplate
include ActionDispatch::Integration::Runner
include ActionDispatch::Assertions
include ActionController::TemplateAssertions
# Special characters to translate into underscores for #method_name
CHARS_TO_TRANSLATE = ['/', '.', ':', ',', "'", '"', " "].freeze
# @private
module BlowAwayTeardownHooks
# @private
def before_teardown
end
# @private
def after_teardown
end
end
# for the SystemTesting Screenshot situation
def passed?
return false if RSpec.current_example.exception
return true unless defined?(::RSpec::Expectations::FailureAggregator)
failure_notifier = ::RSpec::Support.failure_notifier
return true unless failure_notifier.is_a?(::RSpec::Expectations::FailureAggregator)
failure_notifier.failures.empty? && failure_notifier.other_errors.empty?
end
# @private
def method_name
@method_name ||= [
self.class.name.underscore,
RSpec.current_example.description.underscore
].join("_").tr(CHARS_TO_TRANSLATE.join, "_").byteslice(0...200).scrub("") + "_#{rand(1000)}"
end
# @private
# Allows failure screenshot to work whilst not exposing metadata
class SuppressRailsScreenshotMetadata
def initialize
@example_data = {}
end
def [](key)
if @example_data.key?(key)
@example_data[key]
else
raise_wrong_scope_error
end
end
def []=(key, value)
if key == :failure_screenshot_path
@example_data[key] = value
else
raise_wrong_scope_error
end
end
def method_missing(_name, *_args, &_block)
raise_wrong_scope_error
end
private
def raise_wrong_scope_error
raise RSpec::Core::ExampleGroup::WrongScopeError,
"`metadata` is not available from within an example " \
"(e.g. an `it` block) or from constructs that run in the " \
"scope of an example (e.g. `before`, `let`, etc). It is " \
"only available on an example group (e.g. a `describe` or "\
"`context` block)"
end
end
# @private
def metadata
@metadata ||= SuppressRailsScreenshotMetadata.new
end
# Delegates to `Rails.application`.
def app
::Rails.application
end
# Default driver to assign if none specified.
DEFAULT_DRIVER = :selenium_chrome_headless
included do |other|
ActiveSupport.on_load(:action_dispatch_system_test_case) do
ActionDispatch::SystemTesting::Server.silence_puma = true
end
require 'action_dispatch/system_test_case'
begin
require 'capybara'
rescue LoadError => e
abort """
LoadError: #{e.message}
System test integration has a hard
dependency on a webserver and `capybara`, please add capybara to
your Gemfile and configure a webserver (e.g. `Capybara.server =
:puma`) before attempting to use system specs.
""".gsub(/\s+/, ' ').strip
end
original_before_teardown =
::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:before_teardown)
original_after_teardown =
::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:after_teardown)
other.include ::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown
other.include ::ActionDispatch::SystemTesting::TestHelpers::ScreenshotHelper
other.include BlowAwayTeardownHooks
attr_reader :driver
if ActionDispatch::SystemTesting::Server.respond_to?(:silence_puma=)
ActionDispatch::SystemTesting::Server.silence_puma = true
end
def initialize(*args, &blk)
super(*args, &blk)
@driver = nil
self.class.before do
# A user may have already set the driver, so only default if driver
# is not set
driven_by(DEFAULT_DRIVER) unless @driver
end
end
def driven_by(driver, **driver_options, &blk)
@driver = ::ActionDispatch::SystemTestCase.driven_by(driver, **driver_options, &blk).tap(&:use)
end
def served_by(**options)
::ActionDispatch::SystemTestCase.served_by(**options)
end
before do
@routes = ::Rails.application.routes
end
after do
orig_stdout = $stdout
$stdout = StringIO.new
begin
original_before_teardown.bind(self).call
ensure
myio = $stdout
myio.rewind
RSpec.current_example.metadata[:extra_failure_lines] = myio.readlines
$stdout = orig_stdout
end
end
around do |example|
example.run
original_after_teardown.bind(self).call
end
end
end
end
end
|