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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -0
  4. data/.gitignore +11 -0
  5. data/.rspec +2 -0
  6. data/.travis.yml +16 -0
  7. data/.yardopts +7 -0
  8. data/Changelog.md +3 -0
  9. data/Gemfile +30 -0
  10. data/License.txt +22 -0
  11. data/README.md +41 -0
  12. data/Rakefile +27 -0
  13. data/cucumber.yml +6 -0
  14. data/features/custom_formatter.feature +28 -0
  15. data/features/regression_tests_for_built_in_formatters.feature +86 -0
  16. data/features/regression_tests_for_custom_formatters.feature +94 -0
  17. data/features/step_definitions/additional_cli_steps.rb +4 -0
  18. data/features/support/env.rb +13 -0
  19. data/lib/rspec/legacy_formatters.rb +59 -0
  20. data/lib/rspec/legacy_formatters/adaptor.rb +230 -0
  21. data/lib/rspec/legacy_formatters/base_formatter.rb +248 -0
  22. data/lib/rspec/legacy_formatters/base_text_formatter.rb +330 -0
  23. data/lib/rspec/legacy_formatters/documentation_formatter.rb +69 -0
  24. data/lib/rspec/legacy_formatters/helpers.rb +108 -0
  25. data/lib/rspec/legacy_formatters/html_formatter.rb +157 -0
  26. data/lib/rspec/legacy_formatters/html_printer.rb +412 -0
  27. data/lib/rspec/legacy_formatters/json_formatter.rb +71 -0
  28. data/lib/rspec/legacy_formatters/progress_formatter.rb +31 -0
  29. data/lib/rspec/legacy_formatters/snippet_extractor.rb +92 -0
  30. data/lib/rspec/legacy_formatters/version.rb +9 -0
  31. data/maintenance-branch +1 -0
  32. data/rspec-legacy_formatters.gemspec +43 -0
  33. data/script/functions.sh +144 -0
  34. data/script/run_build +13 -0
  35. data/spec/rspec/legacy_formatters_spec.rb +184 -0
  36. data/spec/spec_helper.rb +7 -0
  37. data/spec/support/formatter_support.rb +83 -0
  38. data/spec/support/legacy_formatter_using_sub_classing_example.rb +87 -0
  39. data/spec/support/old_style_formatter_example.rb +69 -0
  40. metadata +243 -0
  41. 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