rspec-legacy_formatters 1.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/.yardopts +7 -0
- data/Changelog.md +3 -0
- data/Gemfile +30 -0
- data/License.txt +22 -0
- data/README.md +41 -0
- data/Rakefile +27 -0
- data/cucumber.yml +6 -0
- data/features/custom_formatter.feature +28 -0
- data/features/regression_tests_for_built_in_formatters.feature +86 -0
- data/features/regression_tests_for_custom_formatters.feature +94 -0
- data/features/step_definitions/additional_cli_steps.rb +4 -0
- data/features/support/env.rb +13 -0
- data/lib/rspec/legacy_formatters.rb +59 -0
- data/lib/rspec/legacy_formatters/adaptor.rb +230 -0
- data/lib/rspec/legacy_formatters/base_formatter.rb +248 -0
- data/lib/rspec/legacy_formatters/base_text_formatter.rb +330 -0
- data/lib/rspec/legacy_formatters/documentation_formatter.rb +69 -0
- data/lib/rspec/legacy_formatters/helpers.rb +108 -0
- data/lib/rspec/legacy_formatters/html_formatter.rb +157 -0
- data/lib/rspec/legacy_formatters/html_printer.rb +412 -0
- data/lib/rspec/legacy_formatters/json_formatter.rb +71 -0
- data/lib/rspec/legacy_formatters/progress_formatter.rb +31 -0
- data/lib/rspec/legacy_formatters/snippet_extractor.rb +92 -0
- data/lib/rspec/legacy_formatters/version.rb +9 -0
- data/maintenance-branch +1 -0
- data/rspec-legacy_formatters.gemspec +43 -0
- data/script/functions.sh +144 -0
- data/script/run_build +13 -0
- data/spec/rspec/legacy_formatters_spec.rb +184 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/formatter_support.rb +83 -0
- data/spec/support/legacy_formatter_using_sub_classing_example.rb +87 -0
- data/spec/support/old_style_formatter_example.rb +69 -0
- metadata +243 -0
- metadata.gz.sig +2 -0
@@ -0,0 +1,230 @@
|
|
1
|
+
module RSpec
|
2
|
+
module LegacyFormatters
|
3
|
+
|
4
|
+
# @private
|
5
|
+
# The `LegacyFormatter` is used to wrap older RSpec 2.x style formatters
|
6
|
+
# for the new 3.x implementation. It takes care of registering all the
|
7
|
+
# old notifications and translating them to the older formatter.
|
8
|
+
#
|
9
|
+
# @see RSpec::Core::Formatters::BaseFormatter
|
10
|
+
class Adaptor
|
11
|
+
NOTIFICATIONS = %W[start message example_group_started example_group_finished example_started
|
12
|
+
example_passed example_failed example_pending start_dump dump_pending
|
13
|
+
dump_failures dump_summary seed close stop deprecation deprecation_summary]
|
14
|
+
|
15
|
+
# @private
|
16
|
+
module LegacyColorSupport
|
17
|
+
def red(text)
|
18
|
+
RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#red", :replacement => "#failure_color")
|
19
|
+
color(text, :red)
|
20
|
+
end
|
21
|
+
|
22
|
+
def green(text)
|
23
|
+
RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#green", :replacement => "#success_color")
|
24
|
+
color(text, :green)
|
25
|
+
end
|
26
|
+
|
27
|
+
def yellow(text)
|
28
|
+
RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#yellow", :replacement => "#pending_color")
|
29
|
+
color(text, :yellow)
|
30
|
+
end
|
31
|
+
|
32
|
+
def blue(text)
|
33
|
+
RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#blue", :replacement => "#fixed_color")
|
34
|
+
color(text, :blue)
|
35
|
+
end
|
36
|
+
|
37
|
+
def magenta(text)
|
38
|
+
RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#magenta")
|
39
|
+
color(text, :magenta)
|
40
|
+
end
|
41
|
+
|
42
|
+
def cyan(text)
|
43
|
+
RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#cyan", :replacement => "#detail_color")
|
44
|
+
color(text, :cyan)
|
45
|
+
end
|
46
|
+
|
47
|
+
def white(text)
|
48
|
+
RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#white", :replacement => "#default_color")
|
49
|
+
color(text, :white)
|
50
|
+
end
|
51
|
+
|
52
|
+
# @private
|
53
|
+
module ConstantLookup
|
54
|
+
def const_missing(name)
|
55
|
+
base_name = "RSpec::Core::Formatters::BaseTextFormatter"
|
56
|
+
case name
|
57
|
+
when :VT100_COLORS then
|
58
|
+
RSpec.deprecate("#{base_name}::VT100_COLORS", :replacement => "RSpec::Core::Formatters::ConsoleCodes.code_for(code_or_symbol)")
|
59
|
+
RSpec::Core::Formatters::ConsoleCodes::VT100_CODES
|
60
|
+
when :VT100_COLOR_CODES then
|
61
|
+
RSpec.deprecate("#{base_name}::VT100_COLOR_CODES", :replacement => "RSpec::Core::Formatters::ConsoleCodes.code_for(code_or_symbol)")
|
62
|
+
RSpec::Core::Formatters::ConsoleCodes::VT100_CODE_VALUES
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# These are part of the deprecated interface, so no individual deprecations
|
70
|
+
def color_code_for(code_or_symbol)
|
71
|
+
::RSpec::Core::Formatters::ConsoleCodes.console_code_for(code_or_symbol)
|
72
|
+
end
|
73
|
+
|
74
|
+
def colorize(text, code_or_symbol)
|
75
|
+
::RSpec::Core::Formatters::ConsoleCodes.wrap(text, code_or_symbol)
|
76
|
+
end
|
77
|
+
|
78
|
+
def colorize_summary(summary)
|
79
|
+
if failure_count > 0
|
80
|
+
color(summary, RSpec.configuration.failure_color)
|
81
|
+
elsif pending_count > 0
|
82
|
+
color(summary, RSpec.configuration.pending_color)
|
83
|
+
else
|
84
|
+
color(summary, RSpec.configuration.success_color)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @api private
|
90
|
+
attr_reader :formatter
|
91
|
+
|
92
|
+
# @api private
|
93
|
+
def output
|
94
|
+
formatter.output
|
95
|
+
end
|
96
|
+
|
97
|
+
# @api public
|
98
|
+
#
|
99
|
+
# @param formatter_class [Class] formatter class to build
|
100
|
+
# @param args [Array<IO, Object>] arguments for the formatter, (usually IO but don't have to be)
|
101
|
+
def initialize(formatter_class, *args)
|
102
|
+
@formatter = formatter_class.new(*args)
|
103
|
+
end
|
104
|
+
|
105
|
+
# @api public
|
106
|
+
#
|
107
|
+
# This method is invoked during the setup phase to register
|
108
|
+
# a formatters with the reporter
|
109
|
+
#
|
110
|
+
# @return [Array] notifications the legacy formatter implements
|
111
|
+
def notifications
|
112
|
+
@notifications ||= NOTIFICATIONS.select { |m| @formatter.respond_to? m }
|
113
|
+
end
|
114
|
+
|
115
|
+
# @api public
|
116
|
+
#
|
117
|
+
# @param notification [NullNotification]
|
118
|
+
def start(notification)
|
119
|
+
@formatter.start notification.count
|
120
|
+
end
|
121
|
+
|
122
|
+
# @api public
|
123
|
+
#
|
124
|
+
# @param notification [GroupNotification] containing example_group subclass of `RSpec::Core::ExampleGroup`
|
125
|
+
def example_group_started(notification)
|
126
|
+
@formatter.example_group_started notification.group
|
127
|
+
end
|
128
|
+
|
129
|
+
# @api public
|
130
|
+
#
|
131
|
+
# @param notification [GroupNotification] containing example_group subclass of `RSpec::Core::ExampleGroup`
|
132
|
+
def example_group_finished(notification)
|
133
|
+
@formatter.example_group_finished notification.group
|
134
|
+
end
|
135
|
+
|
136
|
+
# @api public
|
137
|
+
#
|
138
|
+
# @param notification [ExampleNotification] containing example subclass of `RSpec::Core::Example`
|
139
|
+
def example_started(notification)
|
140
|
+
@formatter.example_started notification.example
|
141
|
+
end
|
142
|
+
|
143
|
+
# @api public
|
144
|
+
#
|
145
|
+
# @param notification [ExampleNotification] containing example subclass of `RSpec::Core::Example`
|
146
|
+
def example_passed(notification)
|
147
|
+
@formatter.example_passed notification.example
|
148
|
+
end
|
149
|
+
|
150
|
+
# @api public
|
151
|
+
#
|
152
|
+
# @param notification [ExampleNotification] containing example subclass of `RSpec::Core::Example`
|
153
|
+
def example_pending(notification)
|
154
|
+
@formatter.example_pending notification.example
|
155
|
+
end
|
156
|
+
|
157
|
+
# @api public
|
158
|
+
#
|
159
|
+
# @param notification [ExampleNotification] containing example subclass of `RSpec::Core::Example`
|
160
|
+
def example_failed(notification)
|
161
|
+
@formatter.example_failed notification.example
|
162
|
+
end
|
163
|
+
|
164
|
+
# @api public
|
165
|
+
#
|
166
|
+
# @param notification [MessageNotification] containing message
|
167
|
+
def message(notification)
|
168
|
+
@formatter.message notification.message
|
169
|
+
end
|
170
|
+
|
171
|
+
# @api public
|
172
|
+
#
|
173
|
+
# @param notification [NullNotification]
|
174
|
+
def stop(notification)
|
175
|
+
@formatter.stop
|
176
|
+
end
|
177
|
+
|
178
|
+
# @api public
|
179
|
+
#
|
180
|
+
# @param notification [NullNotification]
|
181
|
+
def start_dump(notification)
|
182
|
+
@formatter.start_dump
|
183
|
+
end
|
184
|
+
|
185
|
+
# @api public
|
186
|
+
#
|
187
|
+
# @param notification [NullNotification]
|
188
|
+
def dump_failures(notification)
|
189
|
+
@formatter.dump_failures
|
190
|
+
end
|
191
|
+
|
192
|
+
# @api public
|
193
|
+
#
|
194
|
+
# @param summary [Core::Notifications::SummaryNotification]
|
195
|
+
def dump_summary(summary)
|
196
|
+
@formatter.load_time = summary.load_time if @formatter.respond_to? :load_time
|
197
|
+
@formatter.dump_summary summary.duration, summary.example_count, summary.failure_count, summary.pending_count
|
198
|
+
end
|
199
|
+
|
200
|
+
# @api public
|
201
|
+
#
|
202
|
+
# @param notification [NullNotification]
|
203
|
+
def dump_pending(notification)
|
204
|
+
@formatter.dump_pending
|
205
|
+
end
|
206
|
+
|
207
|
+
# @api public
|
208
|
+
#
|
209
|
+
# @param notification [NullNotification]
|
210
|
+
def dump_profile(notification)
|
211
|
+
@formatter.dump_profile
|
212
|
+
end
|
213
|
+
|
214
|
+
# @api public
|
215
|
+
#
|
216
|
+
# @param notification [SeedNotification] containing the seed
|
217
|
+
def seed(notification)
|
218
|
+
@formatter.seed notification.seed
|
219
|
+
end
|
220
|
+
|
221
|
+
# @api public
|
222
|
+
#
|
223
|
+
# @param notification [NullNotification]
|
224
|
+
def close(notification)
|
225
|
+
@formatter.close
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require 'rspec/legacy_formatters/helpers'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module RSpec
|
5
|
+
module Core
|
6
|
+
module Formatters
|
7
|
+
remove_const :BaseFormatter
|
8
|
+
|
9
|
+
# RSpec's built-in formatters are all subclasses of RSpec::Core::Formatters::BaseTextFormatter,
|
10
|
+
# but the BaseTextFormatter documents all of the methods needed to be implemented by a formatter,
|
11
|
+
# as they are called from the reporter.
|
12
|
+
#
|
13
|
+
# @see RSpec::Core::Formatters::BaseTextFormatter
|
14
|
+
# @see RSpec::Core::Reporter
|
15
|
+
class BaseFormatter
|
16
|
+
include Helpers
|
17
|
+
attr_accessor :example_group
|
18
|
+
attr_reader :duration, :examples, :output
|
19
|
+
attr_reader :example_count, :pending_count, :failure_count
|
20
|
+
attr_reader :failed_examples, :pending_examples
|
21
|
+
|
22
|
+
# @api public
|
23
|
+
#
|
24
|
+
# @param output
|
25
|
+
def initialize(output)
|
26
|
+
@output = output || StringIO.new
|
27
|
+
@example_count = @pending_count = @failure_count = 0
|
28
|
+
@examples = []
|
29
|
+
@failed_examples = []
|
30
|
+
@pending_examples = []
|
31
|
+
@example_group = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# @api public
|
35
|
+
#
|
36
|
+
# This method is invoked before any examples are run, right after
|
37
|
+
# they have all been collected. This can be useful for special
|
38
|
+
# formatters that need to provide progress on feedback (graphical ones).
|
39
|
+
#
|
40
|
+
# This will only be invoked once, and the next one to be invoked
|
41
|
+
# is {#example_group_started}.
|
42
|
+
#
|
43
|
+
# @param example_count
|
44
|
+
def start(example_count)
|
45
|
+
start_sync_output
|
46
|
+
@example_count = example_count
|
47
|
+
end
|
48
|
+
|
49
|
+
# @api public
|
50
|
+
#
|
51
|
+
# This method is invoked at the beginning of the execution of each example group.
|
52
|
+
#
|
53
|
+
# @param example_group subclass of `RSpec::Core::ExampleGroup`
|
54
|
+
#
|
55
|
+
# The next method to be invoked after this is {#example_passed},
|
56
|
+
# {#example_pending}, or {#example_group_finished}.
|
57
|
+
#
|
58
|
+
# @param example_group
|
59
|
+
def example_group_started(example_group)
|
60
|
+
@example_group = example_group
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api public
|
64
|
+
#
|
65
|
+
# Invoked at the end of the execution of each example group.
|
66
|
+
#
|
67
|
+
# @param example_group subclass of `RSpec::Core::ExampleGroup`
|
68
|
+
def example_group_finished(example_group)
|
69
|
+
end
|
70
|
+
|
71
|
+
# @api public
|
72
|
+
#
|
73
|
+
# Invoked at the beginning of the execution of each example.
|
74
|
+
#
|
75
|
+
# @param example instance of subclass of `RSpec::Core::ExampleGroup`
|
76
|
+
# @return [Array]
|
77
|
+
def example_started(example)
|
78
|
+
examples << example
|
79
|
+
end
|
80
|
+
|
81
|
+
# @api public
|
82
|
+
#
|
83
|
+
# Invoked when an example passes.
|
84
|
+
#
|
85
|
+
# @param example instance of subclass of `RSpec::Core::ExampleGroup`
|
86
|
+
def example_passed(example)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Invoked when an example is pending.
|
90
|
+
#
|
91
|
+
# @param example instance of subclass of `RSpec::Core::ExampleGroup`
|
92
|
+
# @return [Array]
|
93
|
+
def example_pending(example)
|
94
|
+
@pending_examples << example
|
95
|
+
end
|
96
|
+
|
97
|
+
# @api public
|
98
|
+
#
|
99
|
+
# Invoked when an example fails.
|
100
|
+
#
|
101
|
+
# @param example instance of subclass of `RSpec::Core::ExampleGroup`
|
102
|
+
# @return [Array]
|
103
|
+
def example_failed(example)
|
104
|
+
@failed_examples << example
|
105
|
+
end
|
106
|
+
|
107
|
+
# @api public
|
108
|
+
#
|
109
|
+
# Used by the reporter to send messages to the output stream.
|
110
|
+
#
|
111
|
+
# @param [String] message
|
112
|
+
def message(message)
|
113
|
+
end
|
114
|
+
|
115
|
+
# @api public
|
116
|
+
#
|
117
|
+
# Invoked after all examples have executed, before dumping post-run reports.
|
118
|
+
#
|
119
|
+
# @return [nil]
|
120
|
+
def stop
|
121
|
+
end
|
122
|
+
|
123
|
+
# @api public
|
124
|
+
#
|
125
|
+
# This method is invoked after all of the examples have executed. The next method
|
126
|
+
# to be invoked after this one is {#dump_failures}
|
127
|
+
# (BaseTextFormatter then calls {#dump_failure} once for each failed example.)
|
128
|
+
#
|
129
|
+
# @return [nil]
|
130
|
+
def start_dump
|
131
|
+
end
|
132
|
+
|
133
|
+
# @api public
|
134
|
+
#
|
135
|
+
# Dumps detailed information about each example failure.
|
136
|
+
#
|
137
|
+
# @return [nil]
|
138
|
+
def dump_failures
|
139
|
+
end
|
140
|
+
|
141
|
+
# @api public
|
142
|
+
#
|
143
|
+
# This method is invoked after the dumping of examples and failures. Each parameter
|
144
|
+
# is assigned to a corresponding attribute.
|
145
|
+
#
|
146
|
+
# @param duration
|
147
|
+
# @param example_count
|
148
|
+
# @param failure_count
|
149
|
+
# @param pending_count
|
150
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
151
|
+
@duration = duration
|
152
|
+
@example_count = example_count
|
153
|
+
@failure_count = failure_count
|
154
|
+
@pending_count = pending_count
|
155
|
+
end
|
156
|
+
|
157
|
+
# @api public
|
158
|
+
#
|
159
|
+
# Outputs a report of pending examples. This gets invoked
|
160
|
+
# after the summary if option is set to do so.
|
161
|
+
#
|
162
|
+
# @return [nil]
|
163
|
+
def dump_pending
|
164
|
+
end
|
165
|
+
|
166
|
+
# @private not intended for use outside RSpec.
|
167
|
+
def seed(number)
|
168
|
+
end
|
169
|
+
|
170
|
+
# @api public
|
171
|
+
#
|
172
|
+
# Invoked at the very end, `close` allows the formatter to clean
|
173
|
+
# up resources, e.g. open streams, etc.
|
174
|
+
def close
|
175
|
+
restore_sync_output
|
176
|
+
end
|
177
|
+
|
178
|
+
# @api public
|
179
|
+
#
|
180
|
+
# Formats the given backtrace based on configuration and
|
181
|
+
# the metadata of the given example.
|
182
|
+
def format_backtrace(backtrace, example)
|
183
|
+
super(backtrace, example.metadata)
|
184
|
+
end
|
185
|
+
|
186
|
+
protected
|
187
|
+
|
188
|
+
def configuration
|
189
|
+
RSpec.configuration
|
190
|
+
end
|
191
|
+
|
192
|
+
def read_failed_line(exception, example)
|
193
|
+
unless matching_line = find_failed_line(exception.backtrace, example.file_path)
|
194
|
+
return "Unable to find matching line from backtrace"
|
195
|
+
end
|
196
|
+
|
197
|
+
file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
|
198
|
+
|
199
|
+
if File.exist?(file_path)
|
200
|
+
File.readlines(file_path)[line_number.to_i - 1] ||
|
201
|
+
"Unable to find matching line in #{file_path}"
|
202
|
+
else
|
203
|
+
"Unable to find #{file_path} to read failed line"
|
204
|
+
end
|
205
|
+
rescue SecurityError
|
206
|
+
"Unable to read failed line"
|
207
|
+
end
|
208
|
+
|
209
|
+
def find_failed_line(backtrace, path)
|
210
|
+
path = File.expand_path(path)
|
211
|
+
backtrace.detect { |line|
|
212
|
+
match = line.match(/(.+?):(\d+)(|:\d+)/)
|
213
|
+
match && match[1].downcase == path.downcase
|
214
|
+
}
|
215
|
+
end
|
216
|
+
|
217
|
+
def start_sync_output
|
218
|
+
@old_sync, output.sync = output.sync, true if output_supports_sync
|
219
|
+
end
|
220
|
+
|
221
|
+
def restore_sync_output
|
222
|
+
output.sync = @old_sync if output_supports_sync and !output.closed?
|
223
|
+
end
|
224
|
+
|
225
|
+
def output_supports_sync
|
226
|
+
output.respond_to?(:sync=)
|
227
|
+
end
|
228
|
+
|
229
|
+
def profile_examples?
|
230
|
+
configuration.profile_examples
|
231
|
+
end
|
232
|
+
|
233
|
+
def fail_fast?
|
234
|
+
configuration.fail_fast
|
235
|
+
end
|
236
|
+
|
237
|
+
def color_enabled?
|
238
|
+
configuration.color_enabled?(output)
|
239
|
+
end
|
240
|
+
|
241
|
+
def mute_profile_output?(failure_count)
|
242
|
+
# Don't print out profiled info if there are failures and `--fail-fast` is used, it just clutters the output
|
243
|
+
!profile_examples? || (fail_fast? && failure_count != 0)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|