opal-rspec 0.4.0.beta3 → 0.4.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.gitmodules +15 -0
  4. data/.travis.yml +12 -0
  5. data/.yardopts +5 -0
  6. data/CHANGELOG.md +3 -1
  7. data/Gemfile +6 -7
  8. data/README.md +2 -0
  9. data/Rakefile +12 -50
  10. data/lib/opal/rspec/version.rb +1 -1
  11. data/lib/opal/rspec.rb +14 -0
  12. data/opal/opal/rspec/async.rb +146 -11
  13. data/opal/opal/rspec/fixes.rb +18 -8
  14. data/opal/opal/rspec/requires.rb +45 -0
  15. data/opal/opal/rspec.rb +1 -24
  16. data/opal-rspec.gemspec +1 -1
  17. data/spec/async_spec.rb +4 -5
  18. data/spec/matchers_spec.rb +20 -0
  19. data/spec/named_subject_spec.rb +11 -0
  20. data/spec/should_syntax_spec.rb +17 -0
  21. data/vendor_lib/rspec/autorun.rb +2 -0
  22. data/vendor_lib/rspec/core/backport_random.rb +302 -0
  23. data/vendor_lib/rspec/core/backtrace_formatter.rb +65 -0
  24. data/vendor_lib/rspec/core/command_line.rb +36 -0
  25. data/vendor_lib/rspec/core/configuration.rb +1129 -0
  26. data/vendor_lib/rspec/core/configuration_options.rb +143 -0
  27. data/vendor_lib/rspec/core/drb_command_line.rb +26 -0
  28. data/vendor_lib/rspec/core/drb_options.rb +87 -0
  29. data/vendor_lib/rspec/core/dsl.rb +26 -0
  30. data/vendor_lib/rspec/core/example.rb +312 -0
  31. data/vendor_lib/rspec/core/example_group.rb +540 -0
  32. data/vendor_lib/rspec/core/filter_manager.rb +224 -0
  33. data/vendor_lib/rspec/core/flat_map.rb +17 -0
  34. data/vendor_lib/rspec/core/formatters/base_formatter.rb +291 -0
  35. data/vendor_lib/rspec/core/formatters/base_text_formatter.rb +307 -0
  36. data/vendor_lib/rspec/core/formatters/deprecation_formatter.rb +193 -0
  37. data/vendor_lib/rspec/core/formatters/documentation_formatter.rb +67 -0
  38. data/vendor_lib/rspec/core/formatters/helpers.rb +82 -0
  39. data/vendor_lib/rspec/core/formatters/html_formatter.rb +155 -0
  40. data/vendor_lib/rspec/core/formatters/html_printer.rb +408 -0
  41. data/vendor_lib/rspec/core/formatters/json_formatter.rb +99 -0
  42. data/vendor_lib/rspec/core/formatters/progress_formatter.rb +32 -0
  43. data/vendor_lib/rspec/core/formatters/snippet_extractor.rb +101 -0
  44. data/vendor_lib/rspec/core/formatters.rb +54 -0
  45. data/vendor_lib/rspec/core/hooks.rb +535 -0
  46. data/vendor_lib/rspec/core/memoized_helpers.rb +431 -0
  47. data/vendor_lib/rspec/core/metadata.rb +313 -0
  48. data/vendor_lib/rspec/core/mocking/with_absolutely_nothing.rb +11 -0
  49. data/vendor_lib/rspec/core/mocking/with_flexmock.rb +27 -0
  50. data/vendor_lib/rspec/core/mocking/with_mocha.rb +52 -0
  51. data/vendor_lib/rspec/core/mocking/with_rr.rb +27 -0
  52. data/vendor_lib/rspec/core/mocking/with_rspec.rb +27 -0
  53. data/vendor_lib/rspec/core/option_parser.rb +234 -0
  54. data/vendor_lib/rspec/core/ordering.rb +154 -0
  55. data/vendor_lib/rspec/core/pending.rb +110 -0
  56. data/vendor_lib/rspec/core/project_initializer.rb +88 -0
  57. data/vendor_lib/rspec/core/rake_task.rb +128 -0
  58. data/vendor_lib/rspec/core/reporter.rb +132 -0
  59. data/vendor_lib/rspec/core/ruby_project.rb +44 -0
  60. data/vendor_lib/rspec/core/runner.rb +97 -0
  61. data/vendor_lib/rspec/core/shared_context.rb +53 -0
  62. data/vendor_lib/rspec/core/shared_example_group/collection.rb +27 -0
  63. data/vendor_lib/rspec/core/shared_example_group.rb +146 -0
  64. data/vendor_lib/rspec/core/version.rb +7 -0
  65. data/vendor_lib/rspec/core/warnings.rb +22 -0
  66. data/vendor_lib/rspec/core/world.rb +131 -0
  67. data/vendor_lib/rspec/core.rb +203 -0
  68. data/vendor_lib/rspec/expectations/differ.rb +154 -0
  69. data/vendor_lib/rspec/expectations/errors.rb +9 -0
  70. data/vendor_lib/rspec/expectations/expectation_target.rb +87 -0
  71. data/vendor_lib/rspec/expectations/extensions/object.rb +29 -0
  72. data/vendor_lib/rspec/expectations/extensions.rb +1 -0
  73. data/vendor_lib/rspec/expectations/fail_with.rb +79 -0
  74. data/vendor_lib/rspec/expectations/handler.rb +68 -0
  75. data/vendor_lib/rspec/expectations/syntax.rb +182 -0
  76. data/vendor_lib/rspec/expectations/version.rb +8 -0
  77. data/vendor_lib/rspec/expectations.rb +75 -0
  78. data/vendor_lib/rspec/matchers/built_in/base_matcher.rb +68 -0
  79. data/vendor_lib/rspec/matchers/built_in/be.rb +213 -0
  80. data/vendor_lib/rspec/matchers/built_in/be_instance_of.rb +15 -0
  81. data/vendor_lib/rspec/matchers/built_in/be_kind_of.rb +11 -0
  82. data/vendor_lib/rspec/matchers/built_in/be_within.rb +55 -0
  83. data/vendor_lib/rspec/matchers/built_in/change.rb +141 -0
  84. data/vendor_lib/rspec/matchers/built_in/cover.rb +21 -0
  85. data/vendor_lib/rspec/matchers/built_in/eq.rb +22 -0
  86. data/vendor_lib/rspec/matchers/built_in/eql.rb +23 -0
  87. data/vendor_lib/rspec/matchers/built_in/equal.rb +48 -0
  88. data/vendor_lib/rspec/matchers/built_in/exist.rb +26 -0
  89. data/vendor_lib/rspec/matchers/built_in/has.rb +48 -0
  90. data/vendor_lib/rspec/matchers/built_in/include.rb +61 -0
  91. data/vendor_lib/rspec/matchers/built_in/match.rb +17 -0
  92. data/vendor_lib/rspec/matchers/built_in/match_array.rb +51 -0
  93. data/vendor_lib/rspec/matchers/built_in/raise_error.rb +154 -0
  94. data/vendor_lib/rspec/matchers/built_in/respond_to.rb +74 -0
  95. data/vendor_lib/rspec/matchers/built_in/satisfy.rb +30 -0
  96. data/vendor_lib/rspec/matchers/built_in/start_and_end_with.rb +48 -0
  97. data/vendor_lib/rspec/matchers/built_in/throw_symbol.rb +94 -0
  98. data/vendor_lib/rspec/matchers/built_in/yield.rb +297 -0
  99. data/vendor_lib/rspec/matchers/built_in.rb +39 -0
  100. data/vendor_lib/rspec/matchers/compatibility.rb +14 -0
  101. data/vendor_lib/rspec/matchers/configuration.rb +113 -0
  102. data/vendor_lib/rspec/matchers/dsl.rb +23 -0
  103. data/vendor_lib/rspec/matchers/generated_descriptions.rb +35 -0
  104. data/vendor_lib/rspec/matchers/matcher.rb +301 -0
  105. data/vendor_lib/rspec/matchers/method_missing.rb +12 -0
  106. data/vendor_lib/rspec/matchers/operator_matcher.rb +99 -0
  107. data/vendor_lib/rspec/matchers/pretty.rb +70 -0
  108. data/vendor_lib/rspec/matchers/test_unit_integration.rb +11 -0
  109. data/vendor_lib/rspec/matchers.rb +633 -0
  110. data/vendor_lib/rspec/mocks/any_instance/chain.rb +92 -0
  111. data/vendor_lib/rspec/mocks/any_instance/expectation_chain.rb +47 -0
  112. data/vendor_lib/rspec/mocks/any_instance/message_chains.rb +75 -0
  113. data/vendor_lib/rspec/mocks/any_instance/recorder.rb +200 -0
  114. data/vendor_lib/rspec/mocks/any_instance/stub_chain.rb +45 -0
  115. data/vendor_lib/rspec/mocks/any_instance/stub_chain_chain.rb +23 -0
  116. data/vendor_lib/rspec/mocks/argument_list_matcher.rb +104 -0
  117. data/vendor_lib/rspec/mocks/argument_matchers.rb +264 -0
  118. data/vendor_lib/rspec/mocks/arity_calculator.rb +66 -0
  119. data/vendor_lib/rspec/mocks/configuration.rb +111 -0
  120. data/vendor_lib/rspec/mocks/error_generator.rb +203 -0
  121. data/vendor_lib/rspec/mocks/errors.rb +12 -0
  122. data/vendor_lib/rspec/mocks/example_methods.rb +201 -0
  123. data/vendor_lib/rspec/mocks/extensions/marshal.rb +17 -0
  124. data/vendor_lib/rspec/mocks/framework.rb +36 -0
  125. data/vendor_lib/rspec/mocks/instance_method_stasher.rb +112 -0
  126. data/vendor_lib/rspec/mocks/matchers/have_received.rb +99 -0
  127. data/vendor_lib/rspec/mocks/matchers/receive.rb +112 -0
  128. data/vendor_lib/rspec/mocks/matchers/receive_messages.rb +72 -0
  129. data/vendor_lib/rspec/mocks/message_expectation.rb +643 -0
  130. data/vendor_lib/rspec/mocks/method_double.rb +209 -0
  131. data/vendor_lib/rspec/mocks/method_reference.rb +95 -0
  132. data/vendor_lib/rspec/mocks/mock.rb +7 -0
  133. data/vendor_lib/rspec/mocks/mutate_const.rb +406 -0
  134. data/vendor_lib/rspec/mocks/object_reference.rb +90 -0
  135. data/vendor_lib/rspec/mocks/order_group.rb +82 -0
  136. data/vendor_lib/rspec/mocks/proxy.rb +269 -0
  137. data/vendor_lib/rspec/mocks/proxy_for_nil.rb +37 -0
  138. data/vendor_lib/rspec/mocks/space.rb +95 -0
  139. data/vendor_lib/rspec/mocks/standalone.rb +3 -0
  140. data/vendor_lib/rspec/mocks/stub_chain.rb +51 -0
  141. data/vendor_lib/rspec/mocks/syntax.rb +374 -0
  142. data/vendor_lib/rspec/mocks/targets.rb +90 -0
  143. data/vendor_lib/rspec/mocks/test_double.rb +109 -0
  144. data/vendor_lib/rspec/mocks/verifying_double.rb +77 -0
  145. data/vendor_lib/rspec/mocks/verifying_message_expecation.rb +60 -0
  146. data/vendor_lib/rspec/mocks/verifying_proxy.rb +151 -0
  147. data/vendor_lib/rspec/mocks/version.rb +7 -0
  148. data/vendor_lib/rspec/mocks.rb +100 -0
  149. data/vendor_lib/rspec/support/caller_filter.rb +56 -0
  150. data/vendor_lib/rspec/support/spec/deprecation_helpers.rb +29 -0
  151. data/vendor_lib/rspec/support/spec/in_sub_process.rb +40 -0
  152. data/vendor_lib/rspec/support/spec/stderr_splitter.rb +50 -0
  153. data/vendor_lib/rspec/support/spec.rb +14 -0
  154. data/vendor_lib/rspec/support/version.rb +7 -0
  155. data/vendor_lib/rspec/support/warnings.rb +41 -0
  156. data/vendor_lib/rspec/support.rb +6 -0
  157. data/vendor_lib/rspec/version.rb +5 -0
  158. data/vendor_lib/rspec-expectations.rb +1 -0
  159. data/vendor_lib/rspec.rb +3 -0
  160. metadata +163 -4
  161. data/opal/opal/rspec/rspec.js +0 -20384
@@ -0,0 +1,307 @@
1
+ require 'rspec/core/formatters/base_formatter'
2
+ require 'set'
3
+
4
+ module RSpec
5
+ module Core
6
+ module Formatters
7
+
8
+ # Base for all of RSpec's built-in formatters. See RSpec::Core::Formatters::BaseFormatter
9
+ # to learn more about all of the methods called by the reporter.
10
+ #
11
+ # @see RSpec::Core::Formatters::BaseFormatter
12
+ # @see RSpec::Core::Reporter
13
+ class BaseTextFormatter < BaseFormatter
14
+ def message(message)
15
+ output.puts message
16
+ end
17
+
18
+ def dump_failures
19
+ return if failed_examples.empty?
20
+ output.puts
21
+ output.puts "Failures:"
22
+ failed_examples.each_with_index do |example, index|
23
+ output.puts
24
+ pending_fixed?(example) ? dump_pending_fixed(example, index) : dump_failure(example, index)
25
+ dump_backtrace(example)
26
+ end
27
+ end
28
+
29
+ # @api public
30
+ #
31
+ # Colorizes the output red for failure, yellow for
32
+ # pending, and green otherwise.
33
+ #
34
+ # @param [String] string
35
+ def colorise_summary(summary)
36
+ if failure_count > 0
37
+ color(summary, RSpec.configuration.failure_color)
38
+ elsif pending_count > 0
39
+ color(summary, RSpec.configuration.pending_color)
40
+ else
41
+ color(summary, RSpec.configuration.success_color)
42
+ end
43
+ end
44
+
45
+ def dump_summary(duration, example_count, failure_count, pending_count)
46
+ super(duration, example_count, failure_count, pending_count)
47
+ dump_profile unless mute_profile_output?(failure_count)
48
+ output.puts "\nFinished in #{format_duration(duration)}\n"
49
+ output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
50
+ dump_commands_to_rerun_failed_examples
51
+ end
52
+
53
+ # @api public
54
+ #
55
+ # Outputs commands which can be used to re-run failed examples.
56
+ #
57
+ def dump_commands_to_rerun_failed_examples
58
+ return if failed_examples.empty?
59
+ output.puts
60
+ output.puts("Failed examples:")
61
+ output.puts
62
+
63
+ failed_examples.each do |example|
64
+ output.puts(failure_color("rspec #{RSpec::Core::Metadata::relative_path(example.location)}") + " " + detail_color("# #{example.full_description}"))
65
+ end
66
+ end
67
+
68
+ # @api public
69
+ #
70
+ # Outputs the slowest examples and example groups in a report when using `--profile COUNT` (default 10).
71
+ #
72
+ def dump_profile
73
+ dump_profile_slowest_examples
74
+ dump_profile_slowest_example_groups
75
+ end
76
+
77
+ def dump_profile_slowest_examples
78
+ sorted_examples = slowest_examples
79
+
80
+ time_taken = sorted_examples[:slows] / sorted_examples[:total]
81
+ percentage = '%.1f' % ((time_taken.nan? ? 0.0 : time_taken) * 100)
82
+
83
+ output.puts "\nTop #{sorted_examples[:examples].size} slowest examples (#{format_seconds(sorted_examples[:slows])} seconds, #{percentage}% of total time):\n"
84
+
85
+ sorted_examples[:examples].each do |example|
86
+ output.puts " #{example.full_description}"
87
+ output.puts " #{bold(format_seconds(example.execution_result[:run_time]))} #{bold("seconds")} #{format_caller(example.location)}"
88
+ end
89
+ end
90
+
91
+ def dump_profile_slowest_example_groups
92
+
93
+ sorted_groups = slowest_groups
94
+ return if sorted_groups.empty?
95
+
96
+ output.puts "\nTop #{sorted_groups.size} slowest example groups:"
97
+ slowest_groups.each do |loc, hash|
98
+ average = "#{bold(format_seconds(hash[:average]))} #{bold("seconds")} average"
99
+ total = "#{format_seconds(hash[:total_time])} seconds"
100
+ count = pluralize(hash[:count], "example")
101
+ output.puts " #{hash[:description]}"
102
+ output.puts " #{average} (#{total} / #{count}) #{loc}"
103
+ end
104
+ end
105
+
106
+ # @api public
107
+ #
108
+ # Outputs summary with number of examples, failures and pending.
109
+ #
110
+ def summary_line(example_count, failure_count, pending_count)
111
+ summary = pluralize(example_count, "example")
112
+ summary << ", " << pluralize(failure_count, "failure")
113
+ summary << ", #{pending_count} pending" if pending_count > 0
114
+ summary
115
+ end
116
+
117
+ def dump_pending
118
+ unless pending_examples.empty?
119
+ output.puts
120
+ output.puts "Pending:"
121
+ pending_examples.each do |pending_example|
122
+ output.puts pending_color(" #{pending_example.full_description}")
123
+ output.puts detail_color(" # #{pending_example.execution_result[:pending_message]}")
124
+ output.puts detail_color(" # #{format_caller(pending_example.location)}")
125
+ if pending_example.execution_result[:exception] \
126
+ && RSpec.configuration.show_failures_in_pending_blocks?
127
+ dump_failure_info(pending_example)
128
+ dump_backtrace(pending_example)
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ def seed(number)
135
+ output.puts
136
+ output.puts "Randomized with seed #{number}"
137
+ output.puts
138
+ end
139
+
140
+ def close
141
+ output.close if IO === output && output != $stdout
142
+ end
143
+
144
+ VT100_COLORS = {
145
+ :black => 30,
146
+ :red => 31,
147
+ :green => 32,
148
+ :yellow => 33,
149
+ :blue => 34,
150
+ :magenta => 35,
151
+ :cyan => 36,
152
+ :white => 37
153
+ }
154
+
155
+ VT100_COLOR_CODES = VT100_COLORS.values.to_set
156
+
157
+ def color_code_for(code_or_symbol)
158
+ if VT100_COLOR_CODES.include?(code_or_symbol)
159
+ code_or_symbol
160
+ else
161
+ VT100_COLORS.fetch(code_or_symbol) do
162
+ color_code_for(:white)
163
+ end
164
+ end
165
+ end
166
+
167
+ def colorize(text, code_or_symbol)
168
+ "\e[#{color_code_for(code_or_symbol)}m#{text}\e[0m"
169
+ end
170
+
171
+ protected
172
+
173
+ def bold(text)
174
+ color_enabled? ? "\e[1m#{text}\e[0m" : text
175
+ end
176
+
177
+ def color(text, color_code)
178
+ color_enabled? ? colorize(text, color_code) : text
179
+ end
180
+
181
+ def failure_color(text)
182
+ color(text, RSpec.configuration.failure_color)
183
+ end
184
+
185
+ def success_color(text)
186
+ color(text, RSpec.configuration.success_color)
187
+ end
188
+
189
+ def pending_color(text)
190
+ color(text, RSpec.configuration.pending_color)
191
+ end
192
+
193
+ def fixed_color(text)
194
+ color(text, RSpec.configuration.fixed_color)
195
+ end
196
+
197
+ def detail_color(text)
198
+ color(text, RSpec.configuration.detail_color)
199
+ end
200
+
201
+ def default_color(text)
202
+ color(text, RSpec.configuration.default_color)
203
+ end
204
+
205
+ def red(text)
206
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#red", :replacement => "#failure_color")
207
+ color(text, :red)
208
+ end
209
+
210
+ def green(text)
211
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#green", :replacement => "#success_color")
212
+ color(text, :green)
213
+ end
214
+
215
+ def yellow(text)
216
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#yellow", :replacement => "#pending_color")
217
+ color(text, :yellow)
218
+ end
219
+
220
+ def blue(text)
221
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#blue", :replacement => "#fixed_color")
222
+ color(text, :blue)
223
+ end
224
+
225
+ def magenta(text)
226
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#magenta")
227
+ color(text, :magenta)
228
+ end
229
+
230
+ def cyan(text)
231
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#cyan", :replacement => "#detail_color")
232
+ color(text, :cyan)
233
+ end
234
+
235
+ def white(text)
236
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#white", :replacement => "#default_color")
237
+ color(text, :white)
238
+ end
239
+
240
+ def short_padding
241
+ ' '
242
+ end
243
+
244
+ def long_padding
245
+ ' '
246
+ end
247
+
248
+ private
249
+
250
+ def format_caller(caller_info)
251
+ configuration.backtrace_formatter.backtrace_line(caller_info.to_s.split(':in `block').first)
252
+ end
253
+
254
+ def dump_backtrace(example)
255
+ format_backtrace(example.execution_result[:exception].backtrace, example).each do |backtrace_info|
256
+ output.puts detail_color("#{long_padding}# #{backtrace_info}")
257
+ end
258
+ end
259
+
260
+ def dump_pending_fixed(example, index)
261
+ output.puts "#{short_padding}#{index.next}) #{example.full_description} FIXED"
262
+ output.puts fixed_color("#{long_padding}Expected pending '#{example.metadata[:execution_result][:pending_message]}' to fail. No Error was raised.")
263
+ end
264
+
265
+ def pending_fixed?(example)
266
+ example.execution_result[:pending_fixed]
267
+ end
268
+
269
+ def dump_failure(example, index)
270
+ output.puts "#{short_padding}#{index.next}) #{example.full_description}"
271
+ dump_failure_info(example)
272
+ end
273
+
274
+ def dump_failure_info(example)
275
+ exception = example.execution_result[:exception]
276
+ exception_class_name = exception_class_name_for(exception)
277
+ output.puts "#{long_padding}#{failure_color("Failure/Error:")} #{failure_color(read_failed_line(exception, example).strip)}"
278
+ output.puts "#{long_padding}#{failure_color(exception_class_name)}:" unless exception_class_name =~ /RSpec/
279
+ exception.message.to_s.split("\n").each { |line| output.puts "#{long_padding} #{failure_color(line)}" } if exception.message
280
+
281
+ if shared_group = find_shared_group(example)
282
+ dump_shared_failure_info(shared_group)
283
+ end
284
+ end
285
+
286
+ def exception_class_name_for(exception)
287
+ name = exception.class.name.to_s
288
+ name ="(anonymous error class)" if name == ''
289
+ name
290
+ end
291
+
292
+ def dump_shared_failure_info(group)
293
+ output.puts "#{long_padding}Shared Example Group: \"#{group.metadata[:shared_group_name]}\" called from " +
294
+ "#{configuration.backtrace_formatter.backtrace_line(group.metadata[:example_group][:location])}"
295
+ end
296
+
297
+ def find_shared_group(example)
298
+ group_and_parent_groups(example).find {|group| group.metadata[:shared_group_name]}
299
+ end
300
+
301
+ def group_and_parent_groups(example)
302
+ example.example_group.parent_groups + [example.example_group]
303
+ end
304
+ end
305
+ end
306
+ end
307
+ end
@@ -0,0 +1,193 @@
1
+ require 'rspec/core/formatters/helpers'
2
+ require 'set'
3
+
4
+ module RSpec
5
+ module Core
6
+ module Formatters
7
+ class DeprecationFormatter
8
+ attr_reader :count, :deprecation_stream, :summary_stream
9
+
10
+ def initialize(deprecation_stream, summary_stream)
11
+ @deprecation_stream = deprecation_stream
12
+ @summary_stream = summary_stream
13
+ @seen_deprecations = Set.new
14
+ @count = 0
15
+ end
16
+
17
+ def printer
18
+ @printer ||= case deprecation_stream
19
+ when File, RaiseErrorStream
20
+ ImmediatePrinter.new(deprecation_stream, summary_stream, self)
21
+ else
22
+ DelayedPrinter.new(deprecation_stream, summary_stream, self)
23
+ end
24
+ end
25
+
26
+ def deprecation(data)
27
+ return if @seen_deprecations.include?(data)
28
+
29
+ @count += 1
30
+ printer.print_deprecation_message data
31
+ @seen_deprecations << data
32
+ end
33
+
34
+ def deprecation_summary
35
+ printer.deprecation_summary
36
+ end
37
+
38
+ def deprecation_message_for(data)
39
+ if data[:message]
40
+ SpecifiedDeprecationMessage.new(data)
41
+ else
42
+ GeneratedDeprecationMessage.new(data)
43
+ end
44
+ end
45
+
46
+ RAISE_ERROR_CONFIG_NOTICE = <<-EOS.gsub(/^\s+\|/, '')
47
+ |
48
+ |If you need more of the backtrace for any of these deprecations to
49
+ |identify where to make the necessary changes, you can configure
50
+ |`config.raise_errors_for_deprecations!`, and it will turn the
51
+ |deprecation warnings into errors, giving you the full backtrace.
52
+ EOS
53
+
54
+ SpecifiedDeprecationMessage = Struct.new(:type) do
55
+ def initialize(data)
56
+ @message = data[:message]
57
+ super deprecation_type_for(data)
58
+ end
59
+
60
+ def to_s
61
+ @message
62
+ end
63
+
64
+ def too_many_warnings_message
65
+ msg = "Too many similar deprecation messages reported, disregarding further reports."
66
+ msg << " Set config.deprecation_stream to a File for full output."
67
+ msg
68
+ end
69
+
70
+ private
71
+
72
+ def deprecation_type_for(data)
73
+ data[:message].gsub(/(\w+\/)+\w+\.rb:\d+/, '')
74
+ end
75
+ end
76
+
77
+ GeneratedDeprecationMessage = Struct.new(:type) do
78
+ def initialize(data)
79
+ @data = data
80
+ super data[:deprecated]
81
+ end
82
+
83
+ def to_s
84
+ msg = "#{@data[:deprecated]} is deprecated."
85
+ msg << " Use #{@data[:replacement]} instead." if @data[:replacement]
86
+ msg << " Called from #{@data[:call_site]}." if @data[:call_site]
87
+ msg
88
+ end
89
+
90
+ def too_many_warnings_message
91
+ msg = "Too many uses of deprecated '#{type}'."
92
+ msg << " Set config.deprecation_stream to a File for full output."
93
+ msg
94
+ end
95
+ end
96
+
97
+ class ImmediatePrinter
98
+ include ::RSpec::Core::Formatters::Helpers
99
+
100
+ attr_reader :deprecation_stream, :summary_stream, :deprecation_formatter
101
+
102
+ def initialize(deprecation_stream, summary_stream, deprecation_formatter)
103
+ @deprecation_stream = deprecation_stream
104
+
105
+ # In one of my test suites, I got lots of duplicate output in the
106
+ # deprecation file (e.g. 200 of the same deprecation, even though
107
+ # the `puts` below was only called 6 times). Setting `sync = true`
108
+ # fixes this (but we really have no idea why!).
109
+ @deprecation_stream.sync = true
110
+
111
+ @summary_stream = summary_stream
112
+ @deprecation_formatter = deprecation_formatter
113
+ end
114
+
115
+ def print_deprecation_message(data)
116
+ deprecation_message = deprecation_formatter.deprecation_message_for(data)
117
+ deprecation_stream.puts deprecation_message.to_s
118
+ end
119
+
120
+ def deprecation_summary
121
+ if deprecation_formatter.count > 0
122
+ summary_stream.puts "\n#{pluralize(deprecation_formatter.count, 'deprecation')} logged to #{deprecation_stream.path}"
123
+ deprecation_stream.puts RAISE_ERROR_CONFIG_NOTICE
124
+ end
125
+ end
126
+ end
127
+
128
+ class DelayedPrinter
129
+ TOO_MANY_USES_LIMIT = 4
130
+
131
+ include ::RSpec::Core::Formatters::Helpers
132
+
133
+ attr_reader :deprecation_stream, :summary_stream, :deprecation_formatter
134
+
135
+ def initialize(deprecation_stream, summary_stream, deprecation_formatter)
136
+ @deprecation_stream = deprecation_stream
137
+ @summary_stream = summary_stream
138
+ @deprecation_formatter = deprecation_formatter
139
+ @seen_deprecations = Hash.new { 0 }
140
+ @deprecation_messages = Hash.new { |h, k| h[k] = [] }
141
+ end
142
+
143
+ def print_deprecation_message(data)
144
+ deprecation_message = deprecation_formatter.deprecation_message_for(data)
145
+ @seen_deprecations[deprecation_message] += 1
146
+
147
+ stash_deprecation_message(deprecation_message)
148
+ end
149
+
150
+ def stash_deprecation_message(deprecation_message)
151
+ if @seen_deprecations[deprecation_message] < TOO_MANY_USES_LIMIT
152
+ @deprecation_messages[deprecation_message] << deprecation_message.to_s
153
+ elsif @seen_deprecations[deprecation_message] == TOO_MANY_USES_LIMIT
154
+ @deprecation_messages[deprecation_message] << deprecation_message.too_many_warnings_message
155
+ end
156
+ end
157
+
158
+ def deprecation_summary
159
+ return unless @deprecation_messages.any?
160
+
161
+ print_deferred_deprecation_warnings
162
+ deprecation_stream.puts RAISE_ERROR_CONFIG_NOTICE
163
+
164
+ summary_stream.puts "\n#{pluralize(deprecation_formatter.count, 'deprecation warning')} total"
165
+ end
166
+
167
+ def print_deferred_deprecation_warnings
168
+ deprecation_stream.puts "\nDeprecation Warnings:\n\n"
169
+ @deprecation_messages.keys.sort_by(&:type).each do |deprecation|
170
+ messages = @deprecation_messages[deprecation]
171
+ messages.each { |msg| deprecation_stream.puts msg }
172
+ deprecation_stream.puts
173
+ end
174
+ end
175
+ end
176
+
177
+ # Not really a stream, but is usable in place of one.
178
+ class RaiseErrorStream
179
+ def puts(message)
180
+ raise DeprecationError, message
181
+ end
182
+
183
+ def sync=(value)
184
+ # no-op
185
+ end
186
+ end
187
+
188
+ end
189
+ end
190
+
191
+ DeprecationError = Class.new(StandardError)
192
+ end
193
+ end
@@ -0,0 +1,67 @@
1
+ require 'rspec/core/formatters/base_text_formatter'
2
+
3
+ module RSpec
4
+ module Core
5
+ module Formatters
6
+ class DocumentationFormatter < BaseTextFormatter
7
+ def initialize(output)
8
+ super(output)
9
+ @group_level = 0
10
+ end
11
+
12
+ def example_group_started(example_group)
13
+ super(example_group)
14
+
15
+ output.puts if @group_level == 0
16
+ output.puts "#{current_indentation}#{example_group.description.strip}"
17
+
18
+ @group_level += 1
19
+ end
20
+
21
+ def example_group_finished(example_group)
22
+ @group_level -= 1
23
+ end
24
+
25
+ def example_passed(example)
26
+ super(example)
27
+ output.puts passed_output(example)
28
+ end
29
+
30
+ def example_pending(example)
31
+ super(example)
32
+ output.puts pending_output(example, example.execution_result[:pending_message])
33
+ end
34
+
35
+ def example_failed(example)
36
+ super(example)
37
+ output.puts failure_output(example, example.execution_result[:exception])
38
+ end
39
+
40
+ def failure_output(example, exception)
41
+ failure_color("#{current_indentation}#{example.description.strip} (FAILED - #{next_failure_index})")
42
+ end
43
+
44
+ def next_failure_index
45
+ @next_failure_index ||= 0
46
+ @next_failure_index += 1
47
+ end
48
+
49
+ def passed_output(example)
50
+ success_color("#{current_indentation}#{example.description.strip}")
51
+ end
52
+
53
+ def pending_output(example, message)
54
+ pending_color("#{current_indentation}#{example.description.strip} (PENDING: #{message})")
55
+ end
56
+
57
+ def current_indentation
58
+ ' ' * @group_level
59
+ end
60
+
61
+ def example_group_chain
62
+ example_group.parent_groups.reverse
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,82 @@
1
+ module RSpec
2
+ module Core
3
+ module Formatters
4
+ module Helpers
5
+ SUB_SECOND_PRECISION = 5
6
+ DEFAULT_PRECISION = 2
7
+
8
+ # @api private
9
+ #
10
+ # Formats seconds into a human-readable string.
11
+ #
12
+ # @param [Float, Fixnum] duration in seconds
13
+ # @return [String] human-readable time
14
+ #
15
+ # @example
16
+ # format_duration(1) #=> "1 minute 1 second"
17
+ # format_duration(135.14) #=> "2 minutes 15.14 seconds"
18
+ def format_duration(duration)
19
+ precision = case
20
+ when duration < 1; SUB_SECOND_PRECISION
21
+ when duration < 120; DEFAULT_PRECISION
22
+ when duration < 300; 1
23
+ else 0
24
+ end
25
+
26
+ if duration > 60
27
+ minutes = (duration.to_i / 60).to_i
28
+ seconds = duration - minutes * 60
29
+
30
+ "#{pluralize(minutes, 'minute')} #{pluralize(format_seconds(seconds, precision), 'second')}"
31
+ else
32
+ pluralize(format_seconds(duration, precision), 'second')
33
+ end
34
+ end
35
+
36
+ # @api private
37
+ #
38
+ # Formats seconds to have 5 digits of precision with trailing zeros removed if the number
39
+ # is less than 1 or with 2 digits of precision if the number is greater than zero.
40
+ #
41
+ # @param [Float] float
42
+ # @return [String] formatted float
43
+ #
44
+ # @example
45
+ # format_seconds(0.000006) #=> "0.00001"
46
+ # format_seconds(0.020000) #=> "0.02"
47
+ # format_seconds(1.00000000001) #=> "1"
48
+ #
49
+ # The precision used is set in {Helpers::SUB_SECOND_PRECISION} and {Helpers::DEFAULT_PRECISION}.
50
+ #
51
+ # @see #strip_trailing_zeroes
52
+ def format_seconds(float, precision = nil)
53
+ precision ||= (float < 1) ? SUB_SECOND_PRECISION : DEFAULT_PRECISION
54
+ formatted = sprintf("%.#{precision}f", float)
55
+ strip_trailing_zeroes(formatted)
56
+ end
57
+
58
+ # @api private
59
+ #
60
+ # Remove trailing zeros from a string.
61
+ #
62
+ # @param [String] string string with trailing zeros
63
+ # @return [String] string with trailing zeros removed
64
+ def strip_trailing_zeroes(string)
65
+ stripped = string.sub(/[^1-9]+$/, '')
66
+ stripped.empty? ? "0" : stripped
67
+ end
68
+
69
+ # @api private
70
+ #
71
+ # Pluralize a word based on a count.
72
+ #
73
+ # @param [Fixnum] count number of objects
74
+ # @param [String] string word to be pluralized
75
+ # @return [String] pluralized word
76
+ def pluralize(count, string)
77
+ "#{count} #{string}#{'s' unless count.to_f == 1}"
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end