/
rspec.rb
117 lines (99 loc) · 5.19 KB
/
rspec.rb
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
require "capybara-screenshot"
require "capybara-screenshot/rspec/text_reporter"
require "capybara-screenshot/rspec/html_link_reporter"
require "capybara-screenshot/rspec/html_embed_reporter"
require "capybara-screenshot/rspec/json_reporter"
require "capybara-screenshot/rspec/textmate_link_reporter"
module Capybara
module Screenshot
module RSpec
# Reporters extend RSpec formatters to display information about screenshots for failed
# examples.
#
# Technically, a reporter is a module that gets injected into a RSpec formatter class.
# It uses method aliasing to extend some (usually just one) of the formatter's methods.
#
# Implementing a custom reporter is as simple as creating a module and setting up the
# appropriate aliases. Use `BaseReporter.enhance_with_screenshot` if you don't want
# to set up the aliases manually:
#
# module MyReporter
# extend Capybara::Screenshot::RSpec::BaseReporter
#
# # Will replace the formatter's original `dump_failure_info` method with
# # `dump_failure_info_with_screenshot` from this module:
# enhance_with_screenshot :dump_failure_info
#
# def dump_failure_info_with_screenshot(example)
# dump_failure_info_without_screenshot(example) # call original implementation
# ... # your additions here
# end
# end
#
# Finally customize `Capybara::Screenshot::RSpec::FORMATTERS` to make sure your reporter
# gets injected into the appropriate formatter.
REPORTERS = {
"RSpec::Core::Formatters::ProgressFormatter" => Capybara::Screenshot::RSpec::TextReporter,
"RSpec::Core::Formatters::DocumentationFormatter" => Capybara::Screenshot::RSpec::TextReporter,
"RSpec::Core::Formatters::HtmlFormatter" => Capybara::Screenshot::RSpec::HtmlLinkReporter,
"RSpec::Core::Formatters::JsonFormatter" => Capybara::Screenshot::RSpec::JsonReporter,
"RSpec::Core::Formatters::TextMateFormatter" => Capybara::Screenshot::RSpec::TextMateLinkReporter, # RSpec 2
"RSpec::Mate::Formatters::TextMateFormatter" => Capybara::Screenshot::RSpec::TextMateLinkReporter, # RSpec 3
"Fuubar" => Capybara::Screenshot::RSpec::TextReporter,
"Spec::Runner::Formatter::TeamcityFormatter" => Capybara::Screenshot::RSpec::TextReporter
}
class << self
attr_accessor :add_link_to_screenshot_for_failed_examples
def after_failed_example(example)
if example.example_group.include?(Capybara::DSL) # Capybara DSL method has been included for a feature we can snapshot
Capybara.using_session(Capybara::Screenshot.final_session_name) do
if Capybara::Screenshot.autosave_on_failure && failed?(example) && Capybara.page.current_url != ''
filename_prefix = Capybara::Screenshot.filename_prefix_for(:rspec, example)
saver = Capybara::Screenshot.new_saver(Capybara, Capybara.page, true, filename_prefix)
saver.save
example.metadata[:screenshot] = {}
example.metadata[:screenshot][:html] = saver.html_path if saver.html_saved?
example.metadata[:screenshot][:image] = saver.screenshot_path if saver.screenshot_saved?
end
end
end
end
private
def failed?(example)
return true if example.exception
return false unless defined?(::RSpec::Expectations::FailureAggregator)
failure_notifier = ::RSpec::Support.failure_notifier
return false unless failure_notifier.is_a?(::RSpec::Expectations::FailureAggregator)
failure_notifier.failures.any? || failure_notifier.other_errors.any?
end
end
self.add_link_to_screenshot_for_failed_examples = true
end
end
end
RSpec.configure do |config|
config.before do
Capybara::Screenshot.final_session_name = nil
end
# TODO: DRY refactor into a method?
# Add support for Rails system specs (previously only worked with feature specs)
config.after(type: :system) do |example_from_block_arg|
# RSpec 3 no longer defines `example`, but passes the example as block argument instead
example = config.respond_to?(:expose_current_running_example_as) ? example_from_block_arg : self.example
Capybara::Screenshot::RSpec.after_failed_example(example)
end
config.after(type: :feature) do |example_from_block_arg|
# RSpec 3 no longer defines `example`, but passes the example as block argument instead
example = config.respond_to?(:expose_current_running_example_as) ? example_from_block_arg : self.example
Capybara::Screenshot::RSpec.after_failed_example(example)
end
config.before(:suite) do
if Capybara::Screenshot::RSpec.add_link_to_screenshot_for_failed_examples
RSpec.configuration.formatters.each do |formatter|
next unless (reporter_module = Capybara::Screenshot::RSpec::REPORTERS[formatter.class.to_s])
next if formatter.singleton_class.included_modules.include?(reporter_module)
formatter.singleton_class.send :include, reporter_module
end
end
end
end