rspec 1.1.4 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. data/{CHANGES → History.txt} +116 -64
  2. data/Manifest.txt +403 -0
  3. data/{MIT-LICENSE → README.txt} +43 -0
  4. data/Rakefile +39 -212
  5. data/{TODO → TODO.txt} +0 -0
  6. data/bin/autospec +4 -0
  7. data/bin/spec +1 -1
  8. data/examples/pure/yielding_example.rb +33 -0
  9. data/examples/stories/game-of-life/.loadpath +5 -0
  10. data/examples/stories/game-of-life/behaviour/everything.rb +1 -1
  11. data/examples/stories/game-of-life/behaviour/stories/CellsWithMoreThanThreeNeighboursDie.story +17 -17
  12. data/init.rb +9 -0
  13. data/lib/autotest/discover.rb +1 -1
  14. data/lib/autotest/rspec.rb +3 -29
  15. data/lib/spec.rb +10 -12
  16. data/lib/spec/adapters.rb +1 -0
  17. data/lib/spec/adapters/ruby_engine.rb +26 -0
  18. data/lib/spec/adapters/ruby_engine/mri.rb +8 -0
  19. data/lib/spec/adapters/ruby_engine/rubinius.rb +8 -0
  20. data/lib/spec/example/errors.rb +6 -0
  21. data/lib/spec/example/example_group_methods.rb +17 -14
  22. data/lib/spec/example/example_matcher.rb +2 -0
  23. data/lib/spec/example/example_methods.rb +4 -9
  24. data/lib/spec/example/module_inclusion_warnings.rb +2 -1
  25. data/lib/spec/expectations/extensions/object.rb +2 -2
  26. data/lib/spec/expectations/handler.rb +8 -16
  27. data/lib/spec/extensions/main.rb +2 -17
  28. data/lib/spec/matchers.rb +8 -2
  29. data/lib/spec/matchers/be.rb +0 -3
  30. data/lib/spec/matchers/change.rb +44 -40
  31. data/lib/spec/matchers/has.rb +1 -1
  32. data/lib/spec/matchers/have.rb +17 -12
  33. data/lib/spec/matchers/operator_matcher.rb +10 -4
  34. data/lib/spec/matchers/simple_matcher.rb +113 -10
  35. data/lib/spec/mocks.rb +1 -1
  36. data/lib/spec/mocks/argument_constraints.rb +185 -0
  37. data/lib/spec/mocks/argument_expectation.rb +35 -173
  38. data/lib/spec/mocks/framework.rb +1 -1
  39. data/lib/spec/mocks/message_expectation.rb +30 -5
  40. data/lib/spec/mocks/methods.rb +14 -2
  41. data/lib/spec/mocks/mock.rb +4 -0
  42. data/lib/spec/mocks/proxy.rb +46 -5
  43. data/lib/spec/mocks/spec_methods.rb +9 -1
  44. data/lib/spec/rake/spectask.rb +14 -22
  45. data/lib/spec/rake/verify_rcov.rb +3 -3
  46. data/lib/spec/runner.rb +18 -6
  47. data/lib/spec/runner/backtrace_tweaker.rb +6 -7
  48. data/lib/spec/runner/command_line.rb +6 -17
  49. data/lib/spec/runner/drb_command_line.rb +1 -1
  50. data/lib/spec/runner/formatter/base_formatter.rb +3 -1
  51. data/lib/spec/runner/formatter/base_text_formatter.rb +5 -9
  52. data/lib/spec/runner/formatter/html_formatter.rb +1 -1
  53. data/lib/spec/runner/formatter/nested_text_formatter.rb +1 -1
  54. data/lib/spec/runner/formatter/progress_bar_formatter.rb +2 -2
  55. data/lib/spec/runner/formatter/specdoc_formatter.rb +1 -1
  56. data/lib/spec/runner/formatter/story/html_formatter.rb +62 -16
  57. data/lib/spec/runner/formatter/story/plain_text_formatter.rb +68 -16
  58. data/lib/spec/runner/formatter/story/progress_bar_formatter.rb +42 -0
  59. data/lib/spec/runner/heckle_runner.rb +2 -2
  60. data/lib/spec/runner/option_parser.rb +2 -1
  61. data/lib/spec/runner/options.rb +18 -9
  62. data/lib/spec/runner/reporter.rb +24 -4
  63. data/lib/spec/runner/spec_parser.rb +1 -1
  64. data/lib/spec/story/runner.rb +1 -2
  65. data/lib/spec/story/runner/story_mediator.rb +14 -0
  66. data/lib/spec/story/runner/story_parser.rb +20 -0
  67. data/lib/spec/story/step.rb +40 -28
  68. data/lib/spec/story/step_mother.rb +2 -1
  69. data/lib/spec/story/world.rb +6 -2
  70. data/lib/spec/version.rb +13 -22
  71. data/rake_tasks/failing_examples_with_html.rake +1 -1
  72. data/rake_tasks/verify_rcov.rake +2 -2
  73. data/rspec.gemspec +33 -0
  74. data/spec/autotest/rspec_spec.rb +90 -141
  75. data/spec/spec/adapters/ruby_engine_spec.rb +16 -0
  76. data/spec/spec/example/base_formatter_spec.rb +112 -0
  77. data/spec/spec/example/example_group_factory_spec.rb +2 -2
  78. data/spec/spec/example/example_group_methods_spec.rb +55 -4
  79. data/spec/spec/example/example_group_spec.rb +4 -3
  80. data/spec/spec/example/example_methods_spec.rb +18 -14
  81. data/spec/spec/example/pending_module_spec.rb +38 -0
  82. data/spec/spec/example/shared_example_group_spec.rb +1 -1
  83. data/spec/spec/expectations/extensions/object_spec.rb +0 -12
  84. data/spec/spec/extensions/main_spec.rb +3 -8
  85. data/spec/spec/matchers/change_spec.rb +16 -6
  86. data/spec/spec/matchers/handler_spec.rb +58 -37
  87. data/spec/spec/matchers/has_spec.rb +10 -0
  88. data/spec/spec/matchers/have_spec.rb +105 -2
  89. data/spec/spec/matchers/operator_matcher_spec.rb +35 -2
  90. data/spec/spec/matchers/simple_matcher_spec.rb +64 -2
  91. data/spec/spec/mocks/any_number_of_times_spec.rb +7 -0
  92. data/spec/spec/mocks/bug_report_496.rb +17 -0
  93. data/spec/spec/mocks/failing_mock_argument_constraints_spec.rb +7 -1
  94. data/spec/spec/mocks/hash_including_matcher_spec.rb +45 -24
  95. data/spec/spec/mocks/mock_spec.rb +55 -10
  96. data/spec/spec/mocks/nil_expectation_warning_spec.rb +54 -0
  97. data/spec/spec/mocks/null_object_mock_spec.rb +14 -0
  98. data/spec/spec/mocks/options_hash_spec.rb +18 -28
  99. data/spec/spec/mocks/partial_mock_spec.rb +2 -0
  100. data/spec/spec/mocks/passing_mock_argument_constraints_spec.rb +20 -6
  101. data/spec/spec/mocks/stub_spec.rb +7 -0
  102. data/spec/spec/runner/command_line_spec.rb +5 -12
  103. data/spec/spec/runner/drb_command_line_spec.rb +13 -6
  104. data/spec/spec/runner/formatter/html_formatter_spec.rb +2 -1
  105. data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +3 -3
  106. data/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +20 -2
  107. data/spec/spec/runner/formatter/spec_mate_formatter_spec.rb +2 -1
  108. data/spec/spec/runner/formatter/specdoc_formatter_spec.rb +3 -3
  109. data/spec/spec/runner/formatter/story/html_formatter_spec.rb +76 -2
  110. data/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb +161 -0
  111. data/spec/spec/runner/formatter/story/progress_bar_formatter_spec.rb +82 -0
  112. data/spec/spec/runner/heckle_runner_spec.rb +8 -8
  113. data/spec/spec/runner/option_parser_spec.rb +21 -6
  114. data/spec/spec/runner/output_one_time_fixture_runner.rb +1 -1
  115. data/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +6 -0
  116. data/spec/spec/runner/reporter_spec.rb +51 -5
  117. data/spec/spec/runner/spec_parser_spec.rb +4 -4
  118. data/spec/spec/story/runner/plain_text_story_runner_spec.rb +2 -5
  119. data/spec/spec/story/runner/story_mediator_spec.rb +10 -0
  120. data/spec/spec/story/runner/story_parser_spec.rb +23 -6
  121. data/spec/spec/story/scenario_spec.rb +1 -3
  122. data/spec/spec/story/step_mother_spec.rb +12 -0
  123. data/spec/spec/story/step_spec.rb +57 -4
  124. data/spec/spec/story/story_spec.rb +1 -3
  125. data/spec/spec/story/world_spec.rb +1 -1
  126. data/spec/spec_helper.rb +21 -68
  127. data/stories/all.rb +1 -1
  128. data/stories/configuration/before_blocks.story +21 -0
  129. data/stories/configuration/stories.rb +7 -0
  130. data/stories/example_groups/stories.rb +3 -4
  131. data/stories/resources/spec/before_blocks_example.rb +32 -0
  132. data/stories/stories/multiline_steps.story +23 -0
  133. data/stories/stories/steps/multiline_steps.rb +13 -0
  134. data/stories/stories/stories.rb +6 -0
  135. data/story_server/prototype/javascripts/builder.js +136 -0
  136. data/story_server/prototype/javascripts/controls.js +972 -0
  137. data/story_server/prototype/javascripts/dragdrop.js +976 -0
  138. data/story_server/prototype/javascripts/effects.js +1117 -0
  139. data/story_server/prototype/javascripts/prototype.js +4140 -0
  140. data/story_server/prototype/javascripts/rspec.js +149 -0
  141. data/story_server/prototype/javascripts/scriptaculous.js +58 -0
  142. data/story_server/prototype/javascripts/slider.js +276 -0
  143. data/story_server/prototype/javascripts/sound.js +55 -0
  144. data/story_server/prototype/javascripts/unittest.js +568 -0
  145. data/story_server/prototype/lib/server.rb +24 -0
  146. data/story_server/prototype/stories.html +176 -0
  147. data/story_server/prototype/stylesheets/rspec.css +136 -0
  148. data/story_server/prototype/stylesheets/test.css +90 -0
  149. metadata +166 -166
  150. data/README +0 -36
  151. data/UPGRADE +0 -7
  152. data/bin/spec_translator +0 -8
  153. data/lib/spec/mocks/argument_constraint_matchers.rb +0 -31
  154. data/lib/spec/translator.rb +0 -114
  155. data/spec/spec/example/example_spec.rb +0 -53
  156. data/spec/spec/runner/execution_context_spec.rb +0 -37
  157. data/spec/spec/translator_spec.rb +0 -265
@@ -9,8 +9,12 @@ module Spec
9
9
  __mock_proxy.add_negative_message_expectation(caller(1)[0], sym.to_sym, &block)
10
10
  end
11
11
 
12
- def stub!(sym, opts={})
13
- __mock_proxy.add_stub(caller(1)[0], sym.to_sym, opts)
12
+ def stub!(sym_or_hash, opts={})
13
+ if Hash === sym_or_hash
14
+ sym_or_hash.each {|method, value| stub!(method).and_return value }
15
+ else
16
+ __mock_proxy.add_stub(caller(1)[0], sym_or_hash.to_sym, opts)
17
+ end
14
18
  end
15
19
 
16
20
  def received_message?(sym, *args, &block) #:nodoc:
@@ -24,6 +28,14 @@ module Spec
24
28
  def rspec_reset #:nodoc:
25
29
  __mock_proxy.reset
26
30
  end
31
+
32
+ def as_null_object
33
+ __mock_proxy.act_as_null_object
34
+ end
35
+
36
+ def null_object?
37
+ __mock_proxy.null_object?
38
+ end
27
39
 
28
40
  private
29
41
 
@@ -36,6 +36,10 @@ module Spec
36
36
  "#<#{self.class}:#{sprintf '0x%x', self.object_id} @name=#{@name.inspect}>"
37
37
  end
38
38
 
39
+ def to_s
40
+ inspect.gsub('<','[').gsub('>',']')
41
+ end
42
+
39
43
  private
40
44
 
41
45
  def parse_options(options)
@@ -4,6 +4,16 @@ module Spec
4
4
  DEFAULT_OPTIONS = {
5
5
  :null_object => false,
6
6
  }
7
+
8
+ @@warn_about_expectations_on_nil = true
9
+
10
+ def self.allow_message_expectations_on_nil
11
+ @@warn_about_expectations_on_nil = false
12
+
13
+ # ensure nil.rspec_verify is called even if an expectation is not set in the example
14
+ # otherwise the allowance would effect subsequent examples
15
+ $rspec_mocks.add(nil) unless $rspec_mocks.nil?
16
+ end
7
17
 
8
18
  def initialize(target, name, options={})
9
19
  @target = target
@@ -20,15 +30,27 @@ module Spec
20
30
  def null_object?
21
31
  @options[:null_object]
22
32
  end
33
+
34
+ def act_as_null_object
35
+ @options[:null_object] = true
36
+ @target
37
+ end
23
38
 
24
- def add_message_expectation(expected_from, sym, opts={}, &block)
39
+ def add_message_expectation(expected_from, sym, opts={}, &block)
25
40
  __add sym
26
- @expectations << MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts)
41
+ warn_if_nil_class sym
42
+ if existing_stub = @stubs.detect {|s| s.sym == sym }
43
+ expectation = existing_stub.build_child(expected_from, block_given?? block : nil, 1, opts)
44
+ else
45
+ expectation = MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts)
46
+ end
47
+ @expectations << expectation
27
48
  @expectations.last
28
49
  end
29
50
 
30
51
  def add_negative_message_expectation(expected_from, sym, &block)
31
52
  __add sym
53
+ warn_if_nil_class sym
32
54
  @expectations << NegativeMessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil)
33
55
  @expectations.last
34
56
  end
@@ -50,6 +72,7 @@ module Spec
50
72
  clear_stubs
51
73
  reset_proxied_methods
52
74
  clear_proxied_methods
75
+ reset_nil_expectations_warning
53
76
  end
54
77
 
55
78
  def received_message?(sym, *args, &block)
@@ -61,13 +84,17 @@ module Spec
61
84
  end
62
85
 
63
86
  def message_received(sym, *args, &block)
64
- if expectation = find_matching_expectation(sym, *args)
65
- expectation.invoke(args, block)
66
- elsif (stub = find_matching_method_stub(sym, *args))
87
+ expectation = find_matching_expectation(sym, *args)
88
+ stub = find_matching_method_stub(sym, *args)
89
+
90
+ if (stub && expectation && expectation.called_max_times?) ||
91
+ (stub && !expectation)
67
92
  if expectation = find_almost_matching_expectation(sym, *args)
68
93
  expectation.advise(args, block) unless expectation.expected_messages_received?
69
94
  end
70
95
  stub.invoke([], block)
96
+ elsif expectation
97
+ expectation.invoke(args, block)
71
98
  elsif expectation = find_almost_matching_expectation(sym, *args)
72
99
  expectation.advise(args, block) if null_object? unless expectation.expected_messages_received?
73
100
  raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(sym) or null_object?)
@@ -91,6 +118,12 @@ module Spec
91
118
  define_expected_method(sym)
92
119
  end
93
120
 
121
+ def warn_if_nil_class(sym)
122
+ if proxy_for_nil_class? && @@warn_about_expectations_on_nil
123
+ Kernel.warn("An expectation of :#{sym} was set on nil. Called from #{caller[2]}. Use allow_message_expectations_on_nil to disable warnings.")
124
+ end
125
+ end
126
+
94
127
  def define_expected_method(sym)
95
128
  visibility_string = "#{visibility(sym)} :#{sym}"
96
129
  if target_responds_to?(sym) && !target_metaclass.method_defined?(munge(sym))
@@ -166,6 +199,14 @@ module Spec
166
199
  end
167
200
  end
168
201
  end
202
+
203
+ def proxy_for_nil_class?
204
+ @name == "NilClass"
205
+ end
206
+
207
+ def reset_nil_expectations_warning
208
+ @@warn_about_expectations_on_nil = true if proxy_for_nil_class?
209
+ end
169
210
 
170
211
  def find_matching_expectation(sym, *args)
171
212
  @expectations.find {|expectation| expectation.matches(sym, args)}
@@ -1,7 +1,7 @@
1
1
  module Spec
2
2
  module Mocks
3
3
  module ExampleMethods
4
- include Spec::Mocks::ArgumentConstraintMatchers
4
+ include Spec::Mocks::ArgumentConstraints
5
5
 
6
6
  # Shortcut for creating an instance of Spec::Mocks::Mock.
7
7
  #
@@ -32,6 +32,14 @@ module Spec
32
32
  def stub_everything(name = 'stub')
33
33
  mock(name, :null_object => true)
34
34
  end
35
+
36
+ # Disables warning messages about expectations being set on nil.
37
+ #
38
+ # By default warning messages are issued when expectations are set on nil. This is to
39
+ # prevent false-positives and to catch potential bugs early on.
40
+ def allow_message_expectations_on_nil
41
+ Proxy.allow_message_expectations_on_nil
42
+ end
35
43
 
36
44
  end
37
45
  end
@@ -155,30 +155,23 @@ module Spec
155
155
  # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts]
156
156
  # or
157
157
  # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts]
158
- cmd = "#{File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])} "
159
-
160
- rb_opts = ruby_opts.clone
161
- rb_opts << "-I\"#{lib_path}\""
162
- rb_opts << "-S rcov" if rcov
163
- rb_opts << "-w" if warning
164
- cmd << rb_opts.join(" ")
165
- cmd << " "
166
- cmd << rcov_option_list
167
- cmd << %[ -o "#{rcov_dir}" ] if rcov
168
- cmd << %Q|"#{spec_script}"|
169
- cmd << " "
170
- cmd << "-- " if rcov
171
- cmd << spec_file_list.collect { |fn| %["#{fn}"] }.join(' ')
172
- cmd << " "
173
- cmd << spec_option_list
158
+ cmd_parts = [RUBY]
159
+ cmd_parts += ruby_opts
160
+ cmd_parts << %[-I"#{lib_path}"]
161
+ cmd_parts << "-S rcov" if rcov
162
+ cmd_parts << "-w" if warning
163
+ cmd_parts << rcov_option_list
164
+ cmd_parts << %[-o "#{rcov_dir}"] if rcov
165
+ cmd_parts << %["#{spec_script}"]
166
+ cmd_parts << "--" if rcov
167
+ cmd_parts += spec_file_list.collect { |fn| %["#{fn}"] }
168
+ cmd_parts << spec_option_list
174
169
  if out
175
- cmd << " "
176
- cmd << %Q| > "#{out}"|
170
+ cmd_parts << %[> "#{out}"]
177
171
  STDERR.puts "The Spec::Rake::SpecTask#out attribute is DEPRECATED and will be removed in a future version. Use --format FORMAT:WHERE instead."
178
172
  end
179
- if verbose
180
- puts cmd
181
- end
173
+ cmd = cmd_parts.join(" ")
174
+ puts cmd if verbose
182
175
  unless system(cmd)
183
176
  STDERR.puts failure_message if failure_message
184
177
  raise("Command #{cmd} failed") if fail_on_error
@@ -232,4 +225,3 @@ module Spec
232
225
  end
233
226
  end
234
227
  end
235
-
@@ -35,11 +35,11 @@ module RCov
35
35
  def define
36
36
  desc "Verify that rcov coverage is at least #{threshold}%"
37
37
  task @name do
38
- total_coverage = nil
38
+ total_coverage = 0
39
39
 
40
40
  File.open(index_html).each_line do |line|
41
- if line =~ /<tt class='coverage_total'>(\d+\.\d+)%<\/tt>/
42
- total_coverage = eval($1)
41
+ if line =~ /<tt class='coverage_total'>\s*(\d+\.\d+)%\s*<\/tt>/
42
+ total_coverage = $1.to_f
43
43
  break
44
44
  end
45
45
  end
@@ -185,18 +185,30 @@ module Spec
185
185
  end
186
186
 
187
187
  def register_at_exit_hook # :nodoc:
188
- $spec_runner_at_exit_hook_registered ||= nil
189
- unless $spec_runner_at_exit_hook_registered
188
+ @spec_runner_at_exit_hook_registered ||= nil
189
+ unless @spec_runner_at_exit_hook_registered
190
190
  at_exit do
191
- unless $! || Spec.run?; \
192
- success = Spec.run; \
193
- exit success if Spec.exit?; \
191
+ unless $! || Spec.run?
192
+ success = Spec.run
193
+ exit success if Spec.exit?
194
194
  end
195
195
  end
196
- $spec_runner_at_exit_hook_registered = true
196
+ @spec_runner_at_exit_hook_registered = true
197
+ end
198
+ end
199
+
200
+ def options # :nodoc:
201
+ @options ||= begin
202
+ parser = ::Spec::Runner::OptionParser.new(STDERR, STDOUT)
203
+ parser.order!(ARGV)
204
+ parser.options
197
205
  end
198
206
  end
199
207
 
208
+ def use options
209
+ @options = options
210
+ end
211
+
200
212
  end
201
213
  end
202
214
  end
@@ -40,15 +40,14 @@ module Spec
40
40
 
41
41
  def tweak_backtrace(error)
42
42
  return if error.backtrace.nil?
43
- error.backtrace.collect! do |line|
44
- clean_up_double_slashes(line)
45
- IGNORE_PATTERNS.each do |ignore|
46
- if line =~ ignore
47
- line = nil
48
- break
43
+ error.backtrace.collect! do |message|
44
+ clean_up_double_slashes(message)
45
+ kept_lines = message.split("\n").select do |line|
46
+ IGNORE_PATTERNS.each do |ignore|
47
+ break if line =~ ignore
49
48
  end
50
49
  end
51
- line
50
+ kept_lines.empty?? nil : kept_lines.join("\n")
52
51
  end
53
52
  error.backtrace.compact!
54
53
  end
@@ -2,25 +2,14 @@ require 'spec/runner/option_parser'
2
2
 
3
3
  module Spec
4
4
  module Runner
5
- # Facade to run specs without having to fork a new ruby process (using `spec ...`)
6
5
  class CommandLine
7
6
  class << self
8
- # Runs specs. +argv+ is the commandline args as per the spec commandline API, +err+
9
- # and +out+ are the streams output will be written to.
10
- def run(instance_rspec_options)
11
- # NOTE - this call to init_rspec_options is not spec'd, but neither is any of this
12
- # swapping of $rspec_options. That is all here to enable rspec to run against itself
13
- # and maintain coverage in a single process. Therefore, DO NOT mess with this stuff
14
- # unless you know what you are doing!
15
- init_rspec_options(instance_rspec_options)
16
- orig_rspec_options = rspec_options
17
- begin
18
- $rspec_options = instance_rspec_options
19
- return $rspec_options.run_examples
20
- ensure
21
- ::Spec.run = true
22
- $rspec_options = orig_rspec_options
23
- end
7
+ def run(tmp_options=Spec::Runner.options)
8
+ orig_options = Spec::Runner.options
9
+ Spec::Runner.use tmp_options
10
+ tmp_options.run_examples
11
+ ensure
12
+ Spec::Runner.use orig_options
24
13
  end
25
14
  end
26
15
  end
@@ -9,7 +9,7 @@ module Spec
9
9
  def self.run(options)
10
10
  begin
11
11
  DRb.start_service
12
- spec_server = DRbObject.new_with_uri("druby://localhost:8989")
12
+ spec_server = DRbObject.new_with_uri("druby://127.0.0.1:8989")
13
13
  spec_server.run(options.argv, options.error_stream, options.output_stream)
14
14
  rescue DRb::DRbConnError => e
15
15
  options.error_stream.puts "No server is running"
@@ -45,7 +45,9 @@ module Spec
45
45
  # been provided a block), or when an ExamplePendingError is raised.
46
46
  # +message+ is the message from the ExamplePendingError, if it exists, or the
47
47
  # default value of "Not Yet Implemented"
48
- def example_pending(example, message)
48
+ # +pending_caller+ is the file and line number of the spec which
49
+ # has called the pending method
50
+ def example_pending(example, message, pending_caller)
49
51
  end
50
52
 
51
53
  # This method is invoked after all of the examples have executed. The next method
@@ -15,19 +15,14 @@ module Spec
15
15
  super
16
16
  if where.is_a?(String)
17
17
  @output = File.open(where, 'w')
18
- elsif where == STDOUT
19
- @output = Kernel
20
- def @output.flush
21
- STDOUT.flush
22
- end
23
18
  else
24
19
  @output = where
25
20
  end
26
21
  @pending_examples = []
27
22
  end
28
23
 
29
- def example_pending(example, message)
30
- @pending_examples << [example.__full_description, message]
24
+ def example_pending(example, message, pending_caller)
25
+ @pending_examples << [example.__full_description, message, pending_caller]
31
26
  end
32
27
 
33
28
  def dump_failure(counter, failure)
@@ -75,13 +70,14 @@ module Spec
75
70
  @output.puts "Pending:"
76
71
  @pending_examples.each do |pending_example|
77
72
  @output.puts "#{pending_example[0]} (#{pending_example[1]})"
73
+ @output.puts " Called from #{pending_example[2]}"
78
74
  end
79
75
  end
80
76
  @output.flush
81
77
  end
82
78
 
83
79
  def close
84
- if IO === @output
80
+ if IO === @output && @output != STDOUT
85
81
  @output.close
86
82
  end
87
83
  end
@@ -112,7 +108,7 @@ module Spec
112
108
 
113
109
  def output_to_tty?
114
110
  begin
115
- @output == Kernel || @output.tty?
111
+ @output.tty? || ENV.has_key?("AUTOTEST")
116
112
  rescue NoMethodError
117
113
  false
118
114
  end
@@ -85,7 +85,7 @@ module Spec
85
85
  @output.flush
86
86
  end
87
87
 
88
- def example_pending(example, message)
88
+ def example_pending(example, message, pending_caller)
89
89
  @output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>" unless @header_red
90
90
  @output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{example_group_number}');</script>" unless @example_group_red
91
91
  move_progress
@@ -40,7 +40,7 @@ module Spec
40
40
  output.flush
41
41
  end
42
42
 
43
- def example_pending(example, message)
43
+ def example_pending(example, message, pending_caller)
44
44
  super
45
45
  output.puts yellow("#{current_indentation}#{example.description} (PENDING: #{message})")
46
46
  output.flush
@@ -14,9 +14,9 @@ module Spec
14
14
  @output.flush
15
15
  end
16
16
 
17
- def example_pending(example, message)
17
+ def example_pending(example, message, pending_caller)
18
18
  super
19
- @output.print yellow('P')
19
+ @output.print yellow('*')
20
20
  @output.flush
21
21
  end
22
22
 
@@ -28,7 +28,7 @@ module Spec
28
28
  output.flush
29
29
  end
30
30
 
31
- def example_pending(example, message)
31
+ def example_pending(example, message, pending_caller)
32
32
  super
33
33
  output.puts yellow("- #{example.description} (PENDING: #{message})")
34
34
  output.flush
@@ -8,6 +8,15 @@ module Spec
8
8
  class HtmlFormatter < BaseTextFormatter
9
9
  include ERB::Util
10
10
 
11
+ def initialize(options, where)
12
+ super
13
+ @previous_type = nil
14
+ @scenario_text = ""
15
+ @story_text = ""
16
+ @scenario_failed = false
17
+ @story_failed = false
18
+ end
19
+
11
20
  def run_started(count)
12
21
  @output.puts <<-EOF
13
22
  <?xml version="1.0" encoding="UTF-8"?>
@@ -49,8 +58,8 @@ EOF
49
58
  end
50
59
 
51
60
  def story_started(title, narrative)
52
- @output.puts <<-EOF
53
- <dl class="story passed">
61
+ @story_failed = false
62
+ @story_text = <<-EOF
54
63
  <dt>Story: #{h title}</dt>
55
64
  <dd>
56
65
  <p>
@@ -59,27 +68,49 @@ EOF
59
68
  EOF
60
69
  end
61
70
 
62
- def story_ended(title, narrative)
63
- @output.puts <<-EOF
71
+ def story_ended(title, narrative)
72
+ if @story_failed
73
+ @output.puts <<-EOF
74
+ <dl class="story failed">
75
+ EOF
76
+ else
77
+ @output.puts <<-EOF
78
+ <dl class="story passed">
79
+ EOF
80
+ end
81
+ @output.puts <<-EOF
82
+ #{@story_text}
64
83
  </dd>
65
84
  </dl>
66
85
  EOF
67
86
  end
68
-
87
+
69
88
  def scenario_started(story_title, scenario_name)
70
- @output.puts <<-EOF
71
- <dl class="passed">
72
- <dt>Scenario: #{h scenario_name}</dt>
73
- <dd>
74
- <ul class="steps">
89
+ @previous_type = nil
90
+ @scenario_failed = false
91
+ @scenario_text = <<-EOF
92
+ <dt>Scenario: #{h scenario_name}</dt>
93
+ <dd>
94
+ <ul class="steps">
75
95
  EOF
76
96
  end
77
97
 
78
98
  def scenario_ended
79
- @output.puts <<-EOF
80
- </ul>
81
- </dd>
82
- </dl>
99
+ if @scenario_failed
100
+ @story_text += <<-EOF
101
+ <dl class="failed">
102
+ EOF
103
+ else
104
+ @story_text += <<-EOF
105
+ <dl class="passed">
106
+ EOF
107
+ end
108
+
109
+ @story_text += <<-EOF
110
+ #{@scenario_text}
111
+ </ul>
112
+ </dd>
113
+ </dl>
83
114
  EOF
84
115
  end
85
116
 
@@ -95,6 +126,8 @@ EOF
95
126
  end
96
127
 
97
128
  def scenario_failed(story_title, scenario_name, err)
129
+ @scenario_failed = true
130
+ @story_failed = true
98
131
  scenario_ended
99
132
  end
100
133
 
@@ -117,9 +150,22 @@ EOF
117
150
  spans = args.map { |arg| "<span class=\"param\">#{arg}</span>" }
118
151
  desc_string = description.step_name
119
152
  arg_regexp = description.arg_regexp
153
+ inner = if(type == @previous_type)
154
+ "And "
155
+ else
156
+ "#{type.to_s.capitalize} "
157
+ end
120
158
  i = -1
121
- inner = type.to_s.capitalize + ' ' + desc_string.gsub(arg_regexp) { |param| spans[i+=1] }
122
- @output.puts " <li class=\"#{klass}\">#{inner}</li>"
159
+ inner += desc_string.gsub(arg_regexp) { |param| spans[i+=1] }
160
+
161
+ @scenario_text += " <li class=\"#{klass}\">#{inner}</li>\n"
162
+
163
+ if type == :'given scenario'
164
+ @previous_type = :given
165
+ else
166
+ @previous_type = type
167
+ end
168
+
123
169
  end
124
170
  end
125
171
  end