rspec-legacy_formatters 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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