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,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