opal-rspec-cj 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
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,224 @@
1
+ module RSpec
2
+ module Core
3
+ # Manages the filtering of examples and groups by matching tags declared on
4
+ # the command line or options files, or filters declared via
5
+ # `RSpec.configure`, with hash key/values submitted within example group
6
+ # and/or example declarations. For example, given this declaration:
7
+ #
8
+ # describe Thing, :awesome => true do
9
+ # it "does something" do
10
+ # # ...
11
+ # end
12
+ # end
13
+ #
14
+ # That group (or any other with `:awesome => true`) would be filtered in
15
+ # with any of the following commands:
16
+ #
17
+ # rspec --tag awesome:true
18
+ # rspec --tag awesome
19
+ # rspec -t awesome:true
20
+ # rspec -t awesome
21
+ #
22
+ # Prefixing the tag names with `~` negates the tags, thus excluding this group with
23
+ # any of:
24
+ #
25
+ # rspec --tag ~awesome:true
26
+ # rspec --tag ~awesome
27
+ # rspec -t ~awesome:true
28
+ # rspec -t ~awesome
29
+ #
30
+ # ## Options files and command line overrides
31
+ #
32
+ # Tag declarations can be stored in `.rspec`, `~/.rspec`, or a custom
33
+ # options file. This is useful for storing defaults. For example, let's
34
+ # say you've got some slow specs that you want to suppress most of the
35
+ # time. You can tag them like this:
36
+ #
37
+ # describe Something, :slow => true do
38
+ #
39
+ # And then store this in `.rspec`:
40
+ #
41
+ # --tag ~slow:true
42
+ #
43
+ # Now when you run `rspec`, that group will be excluded.
44
+ #
45
+ # ## Overriding
46
+ #
47
+ # Of course, you probably want to run them sometimes, so you can override
48
+ # this tag on the command line like this:
49
+ #
50
+ # rspec --tag slow:true
51
+ #
52
+ # ## RSpec.configure
53
+ #
54
+ # You can also store default tags with `RSpec.configure`. We use `tag` on
55
+ # the command line (and in options files like `.rspec`), but for historical
56
+ # reasons we use the term `filter` in `RSpec.configure:
57
+ #
58
+ # RSpec.configure do |c|
59
+ # c.filter_run_including :foo => :bar
60
+ # c.filter_run_excluding :foo => :bar
61
+ # end
62
+ #
63
+ # These declarations can also be overridden from the command line.
64
+ #
65
+ # @see RSpec.configure
66
+ # @see Configuration#filter_run_including
67
+ # @see Configuration#filter_run_excluding
68
+ class FilterManager
69
+ STANDALONE_FILTERS = [:locations, :line_numbers, :full_description]
70
+
71
+ PROC_HEX_NUMBER = /0x[0-9a-f]+@/
72
+ PROJECT_DIR = File.expand_path('.')
73
+
74
+ def self.inspect_filter_hash(hash)
75
+ hash.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','')
76
+ end
77
+
78
+ class InclusionFilterHash < Hash
79
+ def description
80
+ FilterManager.inspect_filter_hash self
81
+ end
82
+ end
83
+
84
+ class ExclusionFilterHash < Hash
85
+ CONDITIONAL_FILTERS = {
86
+ :if => lambda { |value| !value },
87
+ :unless => lambda { |value| value }
88
+ }
89
+
90
+ def initialize(*)
91
+ super
92
+ CONDITIONAL_FILTERS.each {|k,v| store(k, v)}
93
+ end
94
+
95
+ def description
96
+ FilterManager.inspect_filter_hash without_conditional_filters
97
+ end
98
+
99
+ def empty_without_conditional_filters?
100
+ without_conditional_filters.empty?
101
+ end
102
+
103
+ private
104
+
105
+ def without_conditional_filters
106
+ reject {|k,v| CONDITIONAL_FILTERS[k] == v}
107
+ end
108
+ end
109
+
110
+ module BackwardCompatibility
111
+ def merge(orig, opposite, *updates)
112
+ _warn_deprecated_keys(updates.last)
113
+ super
114
+ end
115
+
116
+ def reverse_merge(orig, opposite, *updates)
117
+ _warn_deprecated_keys(updates.last)
118
+ super
119
+ end
120
+
121
+ # Supports a use case that probably doesn't exist: overriding the
122
+ # if/unless procs.
123
+ def _warn_deprecated_keys(updates)
124
+ _warn_deprecated_key(:unless, updates) if updates.has_key?(:unless)
125
+ _warn_deprecated_key(:if, updates) if updates.has_key?(:if)
126
+ end
127
+
128
+ # Emits a deprecation warning for keys that will not be supported in
129
+ # the future.
130
+ def _warn_deprecated_key(key, updates)
131
+ RSpec.deprecate("FilterManager#exclude(#{key.inspect} => #{updates[key].inspect})")
132
+ @exclusions[key] = updates.delete(key)
133
+ end
134
+ end
135
+
136
+ attr_reader :exclusions, :inclusions
137
+
138
+ def initialize
139
+ @exclusions = ExclusionFilterHash.new
140
+ @inclusions = InclusionFilterHash.new
141
+ extend(BackwardCompatibility)
142
+ end
143
+
144
+ def add_location(file_path, line_numbers)
145
+ # locations is a hash of expanded paths to arrays of line
146
+ # numbers to match against. e.g.
147
+ # { "path/to/file.rb" => [37, 42] }
148
+ locations = @inclusions.delete(:locations) || Hash.new {|h,k| h[k] = []}
149
+ locations[File.expand_path(file_path)].push(*line_numbers)
150
+ @inclusions.replace(:locations => locations)
151
+ @exclusions.clear
152
+ end
153
+
154
+ def empty?
155
+ inclusions.empty? && exclusions.empty_without_conditional_filters?
156
+ end
157
+
158
+ def prune(examples)
159
+ examples.select {|e| !exclude?(e) && include?(e)}
160
+ end
161
+
162
+ def exclude(*args)
163
+ merge(@exclusions, @inclusions, *args)
164
+ end
165
+
166
+ def exclude!(*args)
167
+ replace(@exclusions, @inclusions, *args)
168
+ end
169
+
170
+ def exclude_with_low_priority(*args)
171
+ reverse_merge(@exclusions, @inclusions, *args)
172
+ end
173
+
174
+ def exclude?(example)
175
+ @exclusions.empty? ? false : example.any_apply?(@exclusions)
176
+ end
177
+
178
+ def include(*args)
179
+ unless_standalone(*args) { merge(@inclusions, @exclusions, *args) }
180
+ end
181
+
182
+ def include!(*args)
183
+ unless_standalone(*args) { replace(@inclusions, @exclusions, *args) }
184
+ end
185
+
186
+ def include_with_low_priority(*args)
187
+ unless_standalone(*args) { reverse_merge(@inclusions, @exclusions, *args) }
188
+ end
189
+
190
+ def include?(example)
191
+ @inclusions.empty? ? true : example.any_apply?(@inclusions)
192
+ end
193
+
194
+ private
195
+
196
+ def unless_standalone(*args)
197
+ is_standalone_filter?(args.last) ? @inclusions.replace(args.last) : yield unless already_set_standalone_filter?
198
+ end
199
+
200
+ def merge(orig, opposite, *updates)
201
+ orig.merge!(updates.last).each_key {|k| opposite.delete(k)}
202
+ end
203
+
204
+ def replace(orig, opposite, *updates)
205
+ updates.last.each_key {|k| opposite.delete(k)}
206
+ orig.replace(updates.last)
207
+ end
208
+
209
+ def reverse_merge(orig, opposite, *updates)
210
+ updated = updates.last.merge(orig)
211
+ opposite.each_pair {|k,v| updated.delete(k) if updated[k] == v}
212
+ orig.replace(updated)
213
+ end
214
+
215
+ def already_set_standalone_filter?
216
+ is_standalone_filter?(inclusions)
217
+ end
218
+
219
+ def is_standalone_filter?(filter)
220
+ STANDALONE_FILTERS.any? {|key| filter.has_key?(key)}
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,17 @@
1
+ module RSpec
2
+ module Core
3
+ module FlatMap
4
+ if [].respond_to?(:flat_map)
5
+ def flat_map(array)
6
+ array.flat_map { |item| yield item }
7
+ end
8
+ else # for 1.8.7
9
+ def flat_map(array)
10
+ array.map { |item| yield item }.flatten
11
+ end
12
+ end
13
+
14
+ module_function :flat_map
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ # ## Built-in Formatters
2
+ #
3
+ # * progress (default) - prints dots for passing examples, `F` for failures, `*` for pending
4
+ # * documentation - prints the docstrings passed to `describe` and `it` methods (and their aliases)
5
+ # * html
6
+ # * json - useful for archiving data for subsequent analysis
7
+ #
8
+ # The progress formatter is the default, but you can choose any one or more of
9
+ # the other formatters by passing with the `--format` (or `-f` for short)
10
+ # command-line option, e.g.
11
+ #
12
+ # rspec --format documentation
13
+ #
14
+ # You can also send the output of multiple formatters to different streams, e.g.
15
+ #
16
+ # rspec --format documentation --format html --out results.html
17
+ #
18
+ # This example sends the output of the documentation formatter to `$stdout`, and
19
+ # the output of the html formatter to results.html.
20
+ #
21
+ # ## Custom Formatters
22
+ #
23
+ # You can tell RSpec to use a custom formatter by passing its path and name to
24
+ # the `rspec` commmand. For example, if you define MyCustomFormatter in
25
+ # path/to/my_custom_formatter.rb, you would type this command:
26
+ #
27
+ # rspec --require path/to/my_custom_formatter.rb --format MyCustomFormatter
28
+ #
29
+ # The reporter calls every formatter with this protocol:
30
+ #
31
+ # * `start(expected_example_count)`
32
+ # * zero or more of the following
33
+ # * `example_group_started(group)`
34
+ # * `example_started(example)`
35
+ # * `example_passed(example)`
36
+ # * `example_failed(example)`
37
+ # * `example_pending(example)`
38
+ # * `message(string)`
39
+ # * `stop`
40
+ # * `start_dump`
41
+ # * `dump_pending`
42
+ # * `dump_failures`
43
+ # * `dump_summary(duration, example_count, failure_count, pending_count)`
44
+ # * `seed(value)`
45
+ # * `close`
46
+ #
47
+ # You can either implement all of those methods or subclass
48
+ # `RSpec::Core::Formatters::BaseTextFormatter` and override the methods you want
49
+ # to enhance.
50
+ #
51
+ # @see RSpec::Core::Formatters::BaseTextFormatter
52
+ # @see RSpec::Core::Reporter
53
+ module RSpec::Core::Formatters
54
+ end
@@ -0,0 +1,291 @@
1
+ require 'rspec/core/formatters/helpers'
2
+ require 'stringio'
3
+
4
+ module RSpec
5
+ module Core
6
+ module Formatters
7
+ # RSpec's built-in formatters are all subclasses of RSpec::Core::Formatters::BaseTextFormatter,
8
+ # but the BaseTextFormatter documents all of the methods needed to be implemented by a formatter,
9
+ # as they are called from the reporter.
10
+ #
11
+ # @see RSpec::Core::Formatters::BaseTextFormatter
12
+ # @see RSpec::Core::Reporter
13
+ class BaseFormatter
14
+ include Helpers
15
+ attr_accessor :example_group
16
+ attr_reader :duration, :examples, :output
17
+ attr_reader :example_count, :pending_count, :failure_count
18
+ attr_reader :failed_examples, :pending_examples
19
+
20
+ # @api public
21
+ #
22
+ # @param output
23
+ def initialize(output)
24
+ @output = output || StringIO.new
25
+ @example_count = @pending_count = @failure_count = 0
26
+ @examples = []
27
+ @failed_examples = []
28
+ @pending_examples = []
29
+ @example_group = nil
30
+ end
31
+
32
+ # @api public
33
+ #
34
+ # This method is invoked before any examples are run, right after
35
+ # they have all been collected. This can be useful for special
36
+ # formatters that need to provide progress on feedback (graphical ones).
37
+ #
38
+ # This will only be invoked once, and the next one to be invoked
39
+ # is {#example_group_started}.
40
+ #
41
+ # @param example_count
42
+ def start(example_count)
43
+ start_sync_output
44
+ @example_count = example_count
45
+ end
46
+
47
+ # @api public
48
+ #
49
+ # This method is invoked at the beginning of the execution of each example group.
50
+ #
51
+ # @param example_group subclass of `RSpec::Core::ExampleGroup`
52
+ #
53
+ # The next method to be invoked after this is {#example_passed},
54
+ # {#example_pending}, or {#example_group_finished}.
55
+ #
56
+ # @param example_group
57
+ def example_group_started(example_group)
58
+ @example_group = example_group
59
+ end
60
+
61
+ # @api public
62
+ #
63
+ # Invoked at the end of the execution of each example group.
64
+ #
65
+ # @param example_group subclass of `RSpec::Core::ExampleGroup`
66
+ def example_group_finished(example_group)
67
+ end
68
+
69
+ # @api public
70
+ #
71
+ # Invoked at the beginning of the execution of each example.
72
+ #
73
+ # @param example instance of subclass of `RSpec::Core::ExampleGroup`
74
+ # @return [Array]
75
+ def example_started(example)
76
+ examples << example
77
+ end
78
+
79
+ # @api public
80
+ #
81
+ # Invoked when an example passes.
82
+ #
83
+ # @param example instance of subclass of `RSpec::Core::ExampleGroup`
84
+ def example_passed(example)
85
+ end
86
+
87
+ # Invoked when an example is pending.
88
+ #
89
+ # @param example instance of subclass of `RSpec::Core::ExampleGroup`
90
+ # @return [Array]
91
+ def example_pending(example)
92
+ @pending_examples << example
93
+ end
94
+
95
+ # @api public
96
+ #
97
+ # Invoked when an example fails.
98
+ #
99
+ # @param example instance of subclass of `RSpec::Core::ExampleGroup`
100
+ # @return [Array]
101
+ def example_failed(example)
102
+ @failed_examples << example
103
+ end
104
+
105
+ # @api public
106
+ #
107
+ # Used by the reporter to send messages to the output stream.
108
+ #
109
+ # @param [String] message
110
+ def message(message)
111
+ end
112
+
113
+ # @api public
114
+ #
115
+ # Invoked after all examples have executed, before dumping post-run reports.
116
+ #
117
+ # @return [nil]
118
+ def stop
119
+ end
120
+
121
+ # @api public
122
+ #
123
+ # This method is invoked after all of the examples have executed. The next method
124
+ # to be invoked after this one is {#dump_failures}
125
+ # (BaseTextFormatter then calls {#dump_failure} once for each failed example.)
126
+ #
127
+ # @return [nil]
128
+ def start_dump
129
+ end
130
+
131
+ # @api public
132
+ #
133
+ # Dumps detailed information about each example failure.
134
+ #
135
+ # @return [nil]
136
+ def dump_failures
137
+ end
138
+
139
+ # @api public
140
+ #
141
+ # This method is invoked after the dumping of examples and failures. Each parameter
142
+ # is assigned to a corresponding attribute.
143
+ #
144
+ # @param duration
145
+ # @param example_count
146
+ # @param failure_count
147
+ # @param pending_count
148
+ def dump_summary(duration, example_count, failure_count, pending_count)
149
+ @duration = duration
150
+ @example_count = example_count
151
+ @failure_count = failure_count
152
+ @pending_count = pending_count
153
+ end
154
+
155
+ # @api public
156
+ #
157
+ # Outputs a report of pending examples. This gets invoked
158
+ # after the summary if option is set to do so.
159
+ #
160
+ # @return [nil]
161
+ def dump_pending
162
+ end
163
+
164
+ # @api public
165
+ #
166
+ # This methods is invoked form formatters to show slowest examples and example groups
167
+ # when using `--profile COUNT` (default 10).
168
+ #
169
+ # @return [nil]
170
+ def dump_profile
171
+ end
172
+
173
+ # @private not intended for use outside RSpec.
174
+ def seed(number)
175
+ end
176
+
177
+ # @api public
178
+ #
179
+ # Invoked at the very end, `close` allows the formatter to clean
180
+ # up resources, e.g. open streams, etc.
181
+ def close
182
+ restore_sync_output
183
+ end
184
+
185
+ # @api public
186
+ #
187
+ # Formats the given backtrace based on configuration and
188
+ # the metadata of the given example.
189
+ def format_backtrace(backtrace, example)
190
+ configuration.backtrace_formatter.format_backtrace(backtrace, example.metadata)
191
+ end
192
+
193
+ protected
194
+
195
+ def configuration
196
+ RSpec.configuration
197
+ end
198
+
199
+ def read_failed_line(exception, example)
200
+ unless matching_line = find_failed_line(exception.backtrace, example.file_path)
201
+ return "Unable to find matching line from backtrace"
202
+ end
203
+
204
+ file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
205
+
206
+ if File.exist?(file_path)
207
+ File.readlines(file_path)[line_number.to_i - 1] ||
208
+ "Unable to find matching line in #{file_path}"
209
+ else
210
+ "Unable to find #{file_path} to read failed line"
211
+ end
212
+ rescue SecurityError
213
+ "Unable to read failed line"
214
+ end
215
+
216
+ def find_failed_line(backtrace, path)
217
+ path = File.expand_path(path)
218
+ backtrace.detect { |line|
219
+ match = line.match(/(.+?):(\d+)(|:\d+)/)
220
+ match && match[1].downcase == path.downcase
221
+ }
222
+ end
223
+
224
+ def start_sync_output
225
+ @old_sync, output.sync = output.sync, true if output_supports_sync
226
+ end
227
+
228
+ def restore_sync_output
229
+ output.sync = @old_sync if output_supports_sync and !output.closed?
230
+ end
231
+
232
+ def output_supports_sync
233
+ output.respond_to?(:sync=)
234
+ end
235
+
236
+ def profile_examples?
237
+ configuration.profile_examples
238
+ end
239
+
240
+ def fail_fast?
241
+ configuration.fail_fast
242
+ end
243
+
244
+ def color_enabled?
245
+ configuration.color_enabled?(output)
246
+ end
247
+
248
+ def mute_profile_output?(failure_count)
249
+ # Don't print out profiled info if there are failures and `--fail-fast` is used, it just clutters the output
250
+ !profile_examples? || (fail_fast? && failure_count != 0)
251
+ end
252
+
253
+ # @api private
254
+ def slowest_examples
255
+ number_of_examples = RSpec.configuration.profile_examples
256
+ sorted_examples = examples.sort_by {|example|
257
+ example.execution_result[:run_time] }.reverse.first(number_of_examples)
258
+
259
+ total, slows = [examples, sorted_examples].map do |exs|
260
+ exs.inject(0.0) {|i, e| i + e.execution_result[:run_time] }
261
+ end
262
+ {:examples => sorted_examples, :total => total, :slows => slows}
263
+ end
264
+
265
+ # @api private
266
+ def slowest_groups
267
+ number_of_examples = RSpec.configuration.profile_examples
268
+ example_groups = {}
269
+
270
+ examples.each do |example|
271
+ location = example.example_group.parent_groups.last.metadata[:example_group][:location]
272
+
273
+ example_groups[location] ||= Hash.new(0)
274
+ example_groups[location][:total_time] += example.execution_result[:run_time]
275
+ example_groups[location][:count] += 1
276
+ example_groups[location][:description] = example.example_group.top_level_description unless example_groups[location].has_key?(:description)
277
+ end
278
+
279
+ # stop if we've only one example group
280
+ return {} if example_groups.keys.length <= 1
281
+
282
+ example_groups.each_value do |hash|
283
+ hash[:average] = hash[:total_time].to_f / hash[:count]
284
+ end
285
+
286
+ example_groups.sort_by {|_, hash| -hash[:average]}.first(number_of_examples)
287
+ end
288
+ end
289
+ end
290
+ end
291
+ end