opal-rspec-cj 0.4.4

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 (176) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +15 -0
  4. data/.travis.yml +13 -0
  5. data/.yardopts +5 -0
  6. data/CHANGELOG.md +25 -0
  7. data/Gemfile +8 -0
  8. data/README.md +147 -0
  9. data/Rakefile +26 -0
  10. data/config.ru +10 -0
  11. data/example/Gemfile +4 -0
  12. data/example/README.md +13 -0
  13. data/example/Rakefile +8 -0
  14. data/example/opal/user.rb +11 -0
  15. data/example/spec/user_spec.rb +15 -0
  16. data/lib/opal-rspec.rb +2 -0
  17. data/lib/opal/rspec.rb +20 -0
  18. data/lib/opal/rspec/rake_task.rb +63 -0
  19. data/lib/opal/rspec/version.rb +5 -0
  20. data/opal-rspec.gemspec +21 -0
  21. data/opal/opal-rspec.rb +1 -0
  22. data/opal/opal/rspec.rb +25 -0
  23. data/opal/opal/rspec/async.rb +289 -0
  24. data/opal/opal/rspec/browser_formatter.rb +188 -0
  25. data/opal/opal/rspec/fixes.rb +116 -0
  26. data/opal/opal/rspec/requires.rb +45 -0
  27. data/opal/opal/rspec/runner.rb +69 -0
  28. data/opal/opal/rspec/sprockets_runner.rb.erb +11 -0
  29. data/opal/opal/rspec/text_formatter.rb +74 -0
  30. data/spec/async_spec.rb +38 -0
  31. data/spec/example_spec.rb +163 -0
  32. data/spec/matchers_spec.rb +201 -0
  33. data/spec/mock_spec.rb +63 -0
  34. data/spec/named_subject_spec.rb +11 -0
  35. data/spec/should_syntax_spec.rb +17 -0
  36. data/vendor/spec_runner.js +50 -0
  37. data/vendor_lib/rspec-expectations.rb +1 -0
  38. data/vendor_lib/rspec.rb +3 -0
  39. data/vendor_lib/rspec/autorun.rb +2 -0
  40. data/vendor_lib/rspec/core.rb +203 -0
  41. data/vendor_lib/rspec/core/backport_random.rb +302 -0
  42. data/vendor_lib/rspec/core/backtrace_formatter.rb +65 -0
  43. data/vendor_lib/rspec/core/command_line.rb +36 -0
  44. data/vendor_lib/rspec/core/configuration.rb +1129 -0
  45. data/vendor_lib/rspec/core/configuration_options.rb +143 -0
  46. data/vendor_lib/rspec/core/drb_command_line.rb +26 -0
  47. data/vendor_lib/rspec/core/drb_options.rb +87 -0
  48. data/vendor_lib/rspec/core/dsl.rb +26 -0
  49. data/vendor_lib/rspec/core/example.rb +312 -0
  50. data/vendor_lib/rspec/core/example_group.rb +540 -0
  51. data/vendor_lib/rspec/core/filter_manager.rb +224 -0
  52. data/vendor_lib/rspec/core/flat_map.rb +17 -0
  53. data/vendor_lib/rspec/core/formatters.rb +54 -0
  54. data/vendor_lib/rspec/core/formatters/base_formatter.rb +291 -0
  55. data/vendor_lib/rspec/core/formatters/base_text_formatter.rb +307 -0
  56. data/vendor_lib/rspec/core/formatters/deprecation_formatter.rb +193 -0
  57. data/vendor_lib/rspec/core/formatters/documentation_formatter.rb +67 -0
  58. data/vendor_lib/rspec/core/formatters/helpers.rb +82 -0
  59. data/vendor_lib/rspec/core/formatters/html_formatter.rb +155 -0
  60. data/vendor_lib/rspec/core/formatters/html_printer.rb +408 -0
  61. data/vendor_lib/rspec/core/formatters/json_formatter.rb +99 -0
  62. data/vendor_lib/rspec/core/formatters/progress_formatter.rb +32 -0
  63. data/vendor_lib/rspec/core/formatters/snippet_extractor.rb +101 -0
  64. data/vendor_lib/rspec/core/hooks.rb +535 -0
  65. data/vendor_lib/rspec/core/memoized_helpers.rb +431 -0
  66. data/vendor_lib/rspec/core/metadata.rb +313 -0
  67. data/vendor_lib/rspec/core/mocking/with_absolutely_nothing.rb +11 -0
  68. data/vendor_lib/rspec/core/mocking/with_flexmock.rb +27 -0
  69. data/vendor_lib/rspec/core/mocking/with_mocha.rb +52 -0
  70. data/vendor_lib/rspec/core/mocking/with_rr.rb +27 -0
  71. data/vendor_lib/rspec/core/mocking/with_rspec.rb +27 -0
  72. data/vendor_lib/rspec/core/option_parser.rb +234 -0
  73. data/vendor_lib/rspec/core/ordering.rb +154 -0
  74. data/vendor_lib/rspec/core/pending.rb +110 -0
  75. data/vendor_lib/rspec/core/project_initializer.rb +88 -0
  76. data/vendor_lib/rspec/core/rake_task.rb +128 -0
  77. data/vendor_lib/rspec/core/reporter.rb +132 -0
  78. data/vendor_lib/rspec/core/ruby_project.rb +44 -0
  79. data/vendor_lib/rspec/core/runner.rb +97 -0
  80. data/vendor_lib/rspec/core/shared_context.rb +53 -0
  81. data/vendor_lib/rspec/core/shared_example_group.rb +146 -0
  82. data/vendor_lib/rspec/core/shared_example_group/collection.rb +27 -0
  83. data/vendor_lib/rspec/core/version.rb +7 -0
  84. data/vendor_lib/rspec/core/warnings.rb +22 -0
  85. data/vendor_lib/rspec/core/world.rb +131 -0
  86. data/vendor_lib/rspec/expectations.rb +75 -0
  87. data/vendor_lib/rspec/expectations/differ.rb +154 -0
  88. data/vendor_lib/rspec/expectations/errors.rb +9 -0
  89. data/vendor_lib/rspec/expectations/expectation_target.rb +87 -0
  90. data/vendor_lib/rspec/expectations/extensions.rb +1 -0
  91. data/vendor_lib/rspec/expectations/extensions/object.rb +29 -0
  92. data/vendor_lib/rspec/expectations/fail_with.rb +79 -0
  93. data/vendor_lib/rspec/expectations/handler.rb +68 -0
  94. data/vendor_lib/rspec/expectations/syntax.rb +182 -0
  95. data/vendor_lib/rspec/expectations/version.rb +8 -0
  96. data/vendor_lib/rspec/matchers.rb +633 -0
  97. data/vendor_lib/rspec/matchers/built_in.rb +39 -0
  98. data/vendor_lib/rspec/matchers/built_in/base_matcher.rb +68 -0
  99. data/vendor_lib/rspec/matchers/built_in/be.rb +213 -0
  100. data/vendor_lib/rspec/matchers/built_in/be_instance_of.rb +15 -0
  101. data/vendor_lib/rspec/matchers/built_in/be_kind_of.rb +11 -0
  102. data/vendor_lib/rspec/matchers/built_in/be_within.rb +55 -0
  103. data/vendor_lib/rspec/matchers/built_in/change.rb +141 -0
  104. data/vendor_lib/rspec/matchers/built_in/cover.rb +21 -0
  105. data/vendor_lib/rspec/matchers/built_in/eq.rb +22 -0
  106. data/vendor_lib/rspec/matchers/built_in/eql.rb +23 -0
  107. data/vendor_lib/rspec/matchers/built_in/equal.rb +48 -0
  108. data/vendor_lib/rspec/matchers/built_in/exist.rb +26 -0
  109. data/vendor_lib/rspec/matchers/built_in/has.rb +48 -0
  110. data/vendor_lib/rspec/matchers/built_in/include.rb +61 -0
  111. data/vendor_lib/rspec/matchers/built_in/match.rb +17 -0
  112. data/vendor_lib/rspec/matchers/built_in/match_array.rb +51 -0
  113. data/vendor_lib/rspec/matchers/built_in/raise_error.rb +154 -0
  114. data/vendor_lib/rspec/matchers/built_in/respond_to.rb +74 -0
  115. data/vendor_lib/rspec/matchers/built_in/satisfy.rb +30 -0
  116. data/vendor_lib/rspec/matchers/built_in/start_and_end_with.rb +48 -0
  117. data/vendor_lib/rspec/matchers/built_in/throw_symbol.rb +94 -0
  118. data/vendor_lib/rspec/matchers/built_in/yield.rb +297 -0
  119. data/vendor_lib/rspec/matchers/compatibility.rb +14 -0
  120. data/vendor_lib/rspec/matchers/configuration.rb +113 -0
  121. data/vendor_lib/rspec/matchers/dsl.rb +23 -0
  122. data/vendor_lib/rspec/matchers/generated_descriptions.rb +35 -0
  123. data/vendor_lib/rspec/matchers/matcher.rb +301 -0
  124. data/vendor_lib/rspec/matchers/method_missing.rb +12 -0
  125. data/vendor_lib/rspec/matchers/operator_matcher.rb +99 -0
  126. data/vendor_lib/rspec/matchers/pretty.rb +70 -0
  127. data/vendor_lib/rspec/matchers/test_unit_integration.rb +11 -0
  128. data/vendor_lib/rspec/mocks.rb +100 -0
  129. data/vendor_lib/rspec/mocks/any_instance/chain.rb +92 -0
  130. data/vendor_lib/rspec/mocks/any_instance/expectation_chain.rb +47 -0
  131. data/vendor_lib/rspec/mocks/any_instance/message_chains.rb +75 -0
  132. data/vendor_lib/rspec/mocks/any_instance/recorder.rb +200 -0
  133. data/vendor_lib/rspec/mocks/any_instance/stub_chain.rb +45 -0
  134. data/vendor_lib/rspec/mocks/any_instance/stub_chain_chain.rb +23 -0
  135. data/vendor_lib/rspec/mocks/argument_list_matcher.rb +104 -0
  136. data/vendor_lib/rspec/mocks/argument_matchers.rb +264 -0
  137. data/vendor_lib/rspec/mocks/arity_calculator.rb +66 -0
  138. data/vendor_lib/rspec/mocks/configuration.rb +111 -0
  139. data/vendor_lib/rspec/mocks/error_generator.rb +203 -0
  140. data/vendor_lib/rspec/mocks/errors.rb +12 -0
  141. data/vendor_lib/rspec/mocks/example_methods.rb +201 -0
  142. data/vendor_lib/rspec/mocks/extensions/marshal.rb +17 -0
  143. data/vendor_lib/rspec/mocks/framework.rb +36 -0
  144. data/vendor_lib/rspec/mocks/instance_method_stasher.rb +112 -0
  145. data/vendor_lib/rspec/mocks/matchers/have_received.rb +99 -0
  146. data/vendor_lib/rspec/mocks/matchers/receive.rb +112 -0
  147. data/vendor_lib/rspec/mocks/matchers/receive_messages.rb +72 -0
  148. data/vendor_lib/rspec/mocks/message_expectation.rb +643 -0
  149. data/vendor_lib/rspec/mocks/method_double.rb +209 -0
  150. data/vendor_lib/rspec/mocks/method_reference.rb +95 -0
  151. data/vendor_lib/rspec/mocks/mock.rb +7 -0
  152. data/vendor_lib/rspec/mocks/mutate_const.rb +406 -0
  153. data/vendor_lib/rspec/mocks/object_reference.rb +90 -0
  154. data/vendor_lib/rspec/mocks/order_group.rb +82 -0
  155. data/vendor_lib/rspec/mocks/proxy.rb +269 -0
  156. data/vendor_lib/rspec/mocks/proxy_for_nil.rb +37 -0
  157. data/vendor_lib/rspec/mocks/space.rb +95 -0
  158. data/vendor_lib/rspec/mocks/standalone.rb +3 -0
  159. data/vendor_lib/rspec/mocks/stub_chain.rb +51 -0
  160. data/vendor_lib/rspec/mocks/syntax.rb +374 -0
  161. data/vendor_lib/rspec/mocks/targets.rb +90 -0
  162. data/vendor_lib/rspec/mocks/test_double.rb +109 -0
  163. data/vendor_lib/rspec/mocks/verifying_double.rb +77 -0
  164. data/vendor_lib/rspec/mocks/verifying_message_expecation.rb +60 -0
  165. data/vendor_lib/rspec/mocks/verifying_proxy.rb +151 -0
  166. data/vendor_lib/rspec/mocks/version.rb +7 -0
  167. data/vendor_lib/rspec/support.rb +6 -0
  168. data/vendor_lib/rspec/support/caller_filter.rb +56 -0
  169. data/vendor_lib/rspec/support/spec.rb +14 -0
  170. data/vendor_lib/rspec/support/spec/deprecation_helpers.rb +29 -0
  171. data/vendor_lib/rspec/support/spec/in_sub_process.rb +40 -0
  172. data/vendor_lib/rspec/support/spec/stderr_splitter.rb +50 -0
  173. data/vendor_lib/rspec/support/version.rb +7 -0
  174. data/vendor_lib/rspec/support/warnings.rb +41 -0
  175. data/vendor_lib/rspec/version.rb +5 -0
  176. metadata +268 -0
@@ -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